From bfc2f6ebbfd610c17ba62fcfb16a8bd61c444811 Mon Sep 17 00:00:00 2001 From: bibymaths Date: Wed, 10 Jun 2026 13:07:23 +0200 Subject: [PATCH 01/42] add: frontend plan --- docs/Audit_and_build_plan.md | 371 +++++++++++++++++++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 docs/Audit_and_build_plan.md diff --git a/docs/Audit_and_build_plan.md b/docs/Audit_and_build_plan.md new file mode 100644 index 0000000..1562326 --- /dev/null +++ b/docs/Audit_and_build_plan.md @@ -0,0 +1,371 @@ +# PhosKinTime No‑Code Frontend Audit and Build Plan + +This document summarizes the current state of the **PhosKinTime** repository and proposes a structured approach for building a unified no‑code dashboard. It is intended as a planning aid; **no frontend implementation is included**. The audit draws from the repository contents and documentation available as of 9 June 2026. + +## 1. Repository Audit Summary + +### 1.1 Overview of the repository + +PhosKinTime is organised as a Python package with several subpackages, configuration files, documentation, Streamlit applications and post‑processing scripts. The top‑level directories and their functions are summarised below: + +- `kinopt` – optimisation of kinase‑phosphorylation interactions. Contains two flavours (`local` and `evol`), a `fitanalysis` module for analysing optimisation performance and an `optimality` subpackage. The `local` flavour has a `__main__.py` that implements a CLI using `argparse`; it parses bounds and loss settings and orchestrates data loading, multistart optimisation and result export[\[1\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). +- `tfopt` – optimisation of transcription factor–mRNA relations. Similar structure to `kinopt` with `local` and `evol` flavours and a `fitanalysis` submodule. The CLI for the `local` flavour reads bounds and loss type from `config.toml` and runs a multistart optimiser before exporting results. +- `protwise` – contains mechanistic ODE models and estimation routines for protein dynamics. It includes modules for parameter estimation (`paramest`), plotting, steady state calculations and a `runner` submodule that exposes an entry point (`protwise.runner.main`) used by the config CLI and pixi tasks. +- `networkmodel` – the integrated global model built on JAX. It includes routines for building matrices, running optimisation (`runner.py`), Bayesian inference, sensitivity analysis and exporting results. The module also provides a Streamlit dashboard (`dashboard_app.py`) and a bundle utility (`dashboard_bundle.py`) for serialising optimisation results. The CLI in `runner.py` accepts numerous arguments (paths to network files, data files, regularisation parameters, solver choice, number of generations, etc.) and writes output to an `--output-dir` with subfolders for optimisation, profiles, posterior samples, plots and a pickled dashboard bundle[\[2\]](file:///home/oai/share/phoskintime/phoskintime-global/config/cli.py)[\[3\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/dashboard.md). +- `common` – shared utilities, Frechét distance computation and helpers used across modules. +- `processing` – preprocessing routines (currently a `cleanup` module) invoked by the `config/cli.py` `prep` command. +- `config` – default configuration and command‑line shortcuts. The file `config/cli.py` defines a Typer app with commands `prep`, `tfopt`, `kinopt`, `model`, `networkmodel`, `clean` and `all`. Each command delegates to the appropriate module via Python `-m` and passes `--conf` options if provided[\[1\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). The `config_loader.py` reads TOML/YAML configuration files. +- `app` – Streamlit dashboards for interactive exploration of TF and kinase optimisation results. `app/tfopt.py` provides an upload‑based dashboard for TF optimisation and network visualisation; it recomputes model‑consistent signal flow, generates numerous plots (latent activity, dominance, knockout effects, scatter and bar charts) and renders networks via **gravis**. `app/kinopt.py` offers similar functionality for kinase optimisation[\[1\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). These apps are independent of the package CLI and expect Excel files with specific sheet names. +- `scripts` – stand‑alone analysis and visualisation scripts intended to be run after the main pipeline. The documentation lists their purposes and default arguments[\[4\]](chrome://newtab/)[\[5\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). Scripts include `analyze_tf_kin_counts.py`, `compare_mechanisms.py` (Streamlit app), `curve_similarity.py`, `export_subnetworks.py`, `find_protein_accumulators.py`, `mechanistic_insights.py`, `temporal_sensitivity.py`, and others. +- `docs` – MkDocs documentation under `docs/Documentation`. Key pages include a script reference[\[4\]](chrome://newtab/)[\[5\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md) and dashboard usage guide[\[2\]](file:///home/oai/share/phoskintime/phoskintime-global/config/cli.py)[\[3\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/dashboard.md). +- `tests` – pytest suite covering configuration loading, notebook execution, inference routines and dashboard behaviour. The tests assert that optimisation routines save expected CSVs, NPZ files and plots in specific subdirectories (`optimization/`, `profiles/`, `posterior/`, `plots/`) and that the dashboard can load inference outputs. + +### 1.2 Major functional areas + +| Area | Description | +|---------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Scientific model modules** | `kinopt`, `tfopt`, `protwise`, `networkmodel`, plus utilities in `common` and `processing`. These contain the core optimisation, simulation, parameter estimation and ODE models. | +| **CLI entry points** | `config/cli.py` provides Typer‑based commands; `kinopt.local/__main__.py`, `tfopt.local/__main__.py`, `networkmodel/runner.py` implement `argparse` CLIs; `protwise/runner/main.py` is called via pixi task. | +| **Pixi tasks** | `pixi.toml` defines tasks for running tests, building docs, executing optimisations (`kinopt-local`, `kinopt-evol`, `tfopt-local`, `tfopt-evol`), preprocessing, running the global model (`networkmodel`), and launching the Streamlit dashboard (`network-dashboard`). | +| **Scripts** | Post‑processing utilities in `scripts/` used after optimisation. They analyse beta counts, compute Fréchet distances, export subnetworks, identify accumulator proteins, summarise mechanistic insights and perform temporal sensitivity analysis[\[5\]\[6\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | +| **Dashboards / Streamlit apps** | Streamlit apps in `app/` for TF and kinase optimisation readouts; `networkmodel/dashboard_app.py` for the global model; `run_dashboard.py` for launching the global dashboard; `scripts/compare_mechanisms.py` for mechanistic comparison. | +| **Result viewers** | `networkmodel/dashboard_app.py` loads a pickled bundle and various CSVs/plots to display scalar objective values, convergence history, predicted vs. observed timeseries and residuals[\[2\]](file:///home/oai/share/phoskintime/phoskintime-global/config/cli.py). The TF/kinase dashboards compute and display analyses directly from uploaded Excel files. | +| **Tests** | The pytest suite checks CLI correctness, output file saving, parameter projection, inference routines and that the dashboard handles missing files gracefully. Tests also ensure that old dependencies (e.g., `scipy.integrate.solve_ivp`) are not used. | +| **Documentation** | Extensive documentation covers installation, pipeline overview, dashboards, script usage and developer guidelines. It includes a script reference table and dashboard instructions[\[4\]](chrome://newtab/)[\[2\]](file:///home/oai/share/phoskintime/phoskintime-global/config/cli.py). | +| **Generated outputs / ignored files** | Optimisation routines produce results directories (e.g., `results/kinopt_local_*`, `results/tfopt_local_*`, `results_model_global_*`) containing CSVs, NPZ files, Excel files, plots, reports and pickled bundles. Git ignores notebooks outputs, compiled artefacts and result folders via `.gitignore`. | + +## 2. Existing CLI and Pixi Entry Points + +The table below summarises each CLI or Pixi task, its source, purpose, inputs and suitability for a unified frontend. Columns labelled “Inputs” list required inputs first and optional inputs afterwards. “Changes needed” notes refactors necessary before frontend integration. + +| Command / Pixi task | Source module | Purpose | Required inputs | Optional inputs | Output behaviour | Suitable for frontend? | Changes needed | +|---------------------------------------|------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------| +| `kinopt-local` | `kinopt/local/__main__.py` | Runs gradient‑based kinase optimisation with multistart. Parses lower/upper bounds, loss type, scaling, segmentation and optimisation method[\[1\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | Data files: `input1.csv` (protein), `input2.csv` (kinase network) via `config.toml`; segmentation points. | Bounds, loss type, missing‑kinase estimation flag, scaling method, segmentation points, optimiser (slsqp/trust‑constr). | Writes Excel `kinopt_results.xlsx`, CSVs and NPZ to `results` directory and copies results to `data/ode` folder. Creates plots and HTML report via `latexit` and organises outputs. | Yes | Expose explicit `--outdir`; include metadata and command provenance; unify logging; remove hard‑coded copying; improve error handling. | +| `kinopt-evol` | `kinopt/evol/__main__.py` | Evolutionary optimiser for kinase optimisation. Inputs similar to local flavour. | Same as above | Evolutionary parameters (population size, generations etc.). | Writes results into `results` directory; may differ in folder naming. | Yes | Ensure consistent output structure and metadata; expose `--outdir`; unify CLI argument names. | +| `kinopt-fitanalysis` | `kinopt/fitanalysis/__main__.py` | Post‑hoc analysis of optimisation performance; reads results and generates plots/summary tables. | Results Excel/NPZ files produced by `kinopt` runs. | None. | Produces plots, CSV summaries. | Yes, but better integrated as part of result viewer rather than separate execution. | Standardise output folder; treat as optional analysis step. | +| `tfopt-local` | `tfopt/local/__main__.py` | Gradient‑based transcription‑factor optimisation. Parses bounds and loss type, loads expression data and PSite information, runs multistart optimiser and exports results. | Data files: `input1.csv` (protein/phospho), `input3.csv` (RNA), `input4.csv` (TF network). | Bounds, loss type. | Writes `tfopt_results.xlsx`, `multistart_summary.csv`, NPZ files, plots and a report in `results` directory. | Yes | Expose `--outdir`; unify metadata and logging; ensure time grid metadata saved. | +| `tfopt-evol` | `tfopt/evol/__main__.py` | Evolutionary optimiser for TF optimisation. | Same as above. | Evolutionary parameters. | Writes results into `results` directory. | Yes | Same changes as for `kinopt-evol`. | +| `prep` | `processing/cleanup.py` via `config/cli.py` | Preprocesses raw data into standardised inputs for optimisation. | Raw CSV files (e.g., `input*.csv` in `data/`). | Path to configuration file via `--conf`. | Writes cleaned CSVs into `data/` and logs to `results/logs`. | Yes | Provide explicit output directory; record provenance; validate inputs with user feedback. | +| `model` | `protwise/runner/main.py` via pixi or Typer | Runs parameter estimation and ODE simulation for protein time‑series given optimised alpha/beta values. | Configuration file via `--conf`; uses defaults from `config.toml`. | None. | Saves predictions, plots, sensitivity indices and reports under `results`. | Yes | Standardise output structure; ensure JSON/CSV results for frontend consumption. | +| `networkmodel` | `networkmodel/runner.py` | Runs the global optimisation pipeline combining kinases, TFs and ODE simulation. Accepts numerous CLI arguments for network files, data files, regularisation parameters, solver choice and number of generations[\[3\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/dashboard.md). | Input networks: `kinase-net`, `tf-net`; data files: `ms`, `rna`, `phospho`; optional prior results from `kinopt` and `tfopt`. | Output directory (`--output-dir`), solver (`--solver`), number of generations, λ regularisation values, flags for hyperparameter scan (`--scan`), sensitivity analysis, profile likelihood and posterior sampling. | Creates `dashboard_bundle.pkl`, `scalar_objective.csv`/`pareto_F.csv`, `convergence_history.csv`, prediction CSVs, optimisation results (`optimization/*`), profiles, posterior samples and numerous plots[\[2\]](file:///home/oai/share/phoskintime/phoskintime-global/config/cli.py)[\[3\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/dashboard.md). | Yes, but heavy | Require consistent `--outdir`; guarantee writing of metadata and command provenance; decouple long‑running optimisation from UI; improve error messages. | +| `phoskintime` **/** `phoskintime-all` | `config/cli.py` Typer commands | Wrapper that calls `processing.cleanup`, `tfopt`, `kinopt` and `protwise` sequentially; the `all` command runs preprocessing → `tfopt` → `kinopt` → `model`. | None by default (uses defaults from `config.toml`). | `--conf` for each stage. | Writes results for each submodule into their respective `results` directories. | Yes | Clarify configuration passing; unify output directories; return status information. | +| `network-dashboard` | `run_dashboard.py` → `networkmodel/dashboard_app.py` | Launches the global Streamlit dashboard to view completed optimisation results[\[2\]](file:///home/oai/share/phoskintime/phoskintime-global/config/cli.py). | `--output-dir` pointing to a completed `networkmodel` run. | Streamlit server options (port). | Interactive viewer only; no new outputs. | Not a backend command but a UI component; embed in unified dashboard. | Already a UI component; to be embedded as a panel. | +| `compare_mechanisms.py` | `scripts/compare_mechanisms.py` | Streamlit app to compare different network mechanisms and global knockout effects[\[5\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | None; uses `config.toml` defaults and result files. | None. | Interactive viewer; heavy simulation. | Could be integrated as an advanced analysis tab. | Parameterise inputs; separate heavy computation; modularise. | +| **Other scripts** | Various files under `scripts/` | Compute PSite statistics, Fréchet distance, export subnetworks, find accumulator proteins, summarise mechanistic insights and perform temporal sensitivity analysis[\[6\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | See script reference; some accept CLI flags for input/output directories[\[6\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | Additional parameters such as sample size (`--samples`), hop distance (`--hops`), etc. | Write CSVs/plots into specified output directories; some scripts simply print results. | Many can be exposed as on‑demand analyses in the frontend. | Refactor to accept explicit input/output paths; return data structures; include metadata. | + +## 3. Existing Dashboard and Streamlit App Audit + +The repository already contains several Streamlit applications. Their status and integration recommendations are summarised below. + +| App file | Purpose & inputs | Outputs/visualisation | Reusability | Integration recommendation | +|---------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `networkmodel/dashboard_app.py` | Global model viewer launched via `run_dashboard.py`. Requires `--output-dir` pointing to a completed `networkmodel` run. Uses `dashboard_bundle.pkl` and CSVs such as `scalar_objective.csv`, `convergence_history.csv`, `pred_prot_picked.csv`, `pred_rna_picked.csv` and `pred_phospho_picked.csv`[\[2\]](file:///home/oai/share/phoskintime/phoskintime-global/config/cli.py)[\[3\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/dashboard.md). | Displays scalar objective scatter, convergence history plot, predicted vs. observed timeseries, image/video galleries and PDF report viewer. When inference outputs exist (`optimization/`, `profiles/`, `posterior/`), additional tables are shown. | Self‑contained and modular; uses helper functions for loading outputs. | **Keep and import** into the unified dashboard. Expose as a component taking a result directory and rendering the appropriate tabs. | +| `app/tfopt.py` | Dashboard for TF optimisation. Users upload a `tfopt_results.xlsx` file. The app recomputes model‑consistent signal flow and displays analysis tables (latent activity, target dominance, knockout effects) and numerous plots; it also renders networks via gravis and supports knockout previews. | Visualises bar charts, scatter plots, time‑series fits, network graphs and knockout effects. Provides CSV download buttons. | High reusability; computations are performed on the fly from uploaded Excel; caching is used. | **Import as a workflow panel**. Refactor into functions that separate data processing from UI; reuse plotting and table components; integrate network rendering within unified dashboard. | +| `app/kinopt.py` | Dashboard for kinase optimisation results. Inputs are `kinopt_results.xlsx` with sheets “Observed”, “Estimated”, “Alpha Values” and “Beta Values”. Computes latent kinase activity, control load, breadth vs. load scatter, bound pressure vs. load, dominance distribution and knockout effects; renders network graphs via gravis; provides CSV downloads. | Similar to TF dashboard: multiple interactive plots and tables. | Reusable with minor refactoring. | **Import as a workflow panel**. Separate computation into helper functions; expose parameter widgets; integrate network rendering into unified dashboard. | +| `scripts/compare_mechanisms.py` | Streamlit app comparing network mechanisms across different model topologies and showing global knockout effects[\[5\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). Uses `networkmodel.config` defaults to locate networks and data; loads optimisation results. | Renders protein/TF networks, computes proxy mapping for orphan transcription factors, filters phospho data mechanistically, simulates until steady state and plots results; depends on heavy libraries (`gravis`, `networkx`, `imageio`). | Reusable but computationally heavy; currently uses default paths. | **Refactor into a reusable component**. Parameterise file paths; separate simulation functions; integrate as optional advanced analysis panel. | +| `run_dashboard.py` | Thin launcher script that sets up `sys.path` and calls `networkmodel.dashboard_app.main()`. | None (it only prints “Dashboard launched successfully”). | Not needed in the unified dashboard. | **Deprecate** after integration; retain for backward compatibility. | + +## 4. `scripts/` Audit + +Every script under `scripts/` was reviewed. The following table summarises their purpose, CLI usage, inputs, outputs and integration recommendation. Scripts without command‑line flags rely on hard‑coded defaults; those should be refactored to accept explicit arguments so the frontend can supply user‑selected files. + +| Script | Purpose | CLI usage / parameters | Inputs | Outputs | Duplicates package functionality? | Frontend action | Recommendation | +|----------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|-------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------| +| `analyze_tf_kin_counts.py` | Compute PSite statistics for TFs and kinases; counts how many unique PSites each entity has and how many regulators target each gene[\[4\]](chrome://newtab/). | No CLI flags; call `python scripts/analyze_tf_kin_counts.py` or import `main()` with custom paths[\[4\]](chrome://newtab/). | Reads `data/tfopt_results.xlsx` and `data/kinopt_results.xlsx` by default; expects sheets named “Alpha Values” and “Beta Values”. | CSVs (`tf_beta_psite_counts.csv`, `kin_beta_psite_counts.csv`, `per_gene_num_tfs_num_kinases.csv`) in `results_scripts/` and console summary. | Partially duplicated by the TF/Kinopt dashboards (PSite counts and per‑gene statistics). | Yes – could be triggered as a downloadable summary. | Parameterise inputs/outputs; move computation into backend; call from frontend when needed. | +| `compare_mechanisms.py` | Streamlit app comparing network mechanisms (see Section 3). | Run via `streamlit run scripts/compare_mechanisms.py`[\[5\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | Uses `config.toml` defaults to locate networks and data; reads optimisation results. | Interactive viewer only; no file outputs. | Overlaps with the networkmodel dashboard; adds mechanism comparison and network simulation. | Yes – as an optional advanced panel. | Refactor for parameterised inputs; separate heavy simulation; integrate into advanced analysis tab. | +| `curve_similarity.py` | Compute discrete Fréchet distance between observed and estimated curves per row. Useful for ranking fits[\[5\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | CLI flags `--tfopt-xlsx`, `--kinopt-xlsx`, `--out-dir`[\[5\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | Excel files with “Observed” and “Estimated” sheets; optionally both TF and kinase results. | CSV with Fréchet scores per row. | Unique functionality not available elsewhere. | Yes – implement as on‑demand analysis. | Keep; move computation into backend module; provide asynchronous execution. | +| `export_subnetworks.py` | Export k‑hop subnetworks around shared nodes from kinase and TF networks[\[6\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | CLI flags `--input2`, `--input4`, `--outdir`, `--hops`[\[6\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | Input network CSVs (`input2.csv`, `input4.csv`). | Per‑node subnetworks saved as CSV in `//` and a summary index; optional ZIP. | Stand‑alone utility. | Maybe – for network exploration outside optimisation. | Offer as download tool; integrate into advanced network analysis panel. | +| `find_protein_accumulators.py` | Identify proteins whose predicted fold‑change greatly exceeds RNA fold‑change (ratio \> 100)[\[6\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | CLI flags `--prot`, `--rna`[\[6\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | CSVs `pred_prot_picked.csv` and `pred_rna_picked.csv` from `networkmodel` outputs. | CSV listing accumulator proteins. | Unique analysis; not present in existing dashboards. | Yes – useful in result browser. | Refactor into backend function; call after predictions are available; display table. | +| `kinopt_network_readout.py` / `tfopt_network_readout.py` | Older scripts (now replaced by the Streamlit dashboards) to recompute signal flow and generate analysis tables. | CLI requiring `--kinopt-xlsx` / `--tfopt-xlsx`. | Excel results; optional input2/input4 network files. | CSV tables summarising activity, dominance, load and knockout effects. | Duplicated by `app/kinopt.py` and `app/tfopt.py`. | Possibly, but redundant. | Mark as deprecated; rely on dashboard components. | +| `kinopt_network_viz.py` / `tfopt_network_viz.py` | Old matplotlib‑based visualisation scripts for kinase/TF optimisation results. | CLI requiring Excel results; outputs numerous PNG figures. | Excel results. | Plots saved in output directory. | Duplicated by Streamlit dashboards. | No. | Deprecate; keep only for reproducibility. | +| `make_kinopt_diagram.py` | Generates a flowchart of the Kinopt algorithm for the manuscript. | No CLI; run manually. | None. | Saves PNG diagram. | Not relevant for frontend. | No. | Exclude from frontend. | +| `mechanistic_insights.py` | Extract biological insights (refractory period, kinetic lag, transcriptional saturation, feedback gain) using optimised parameters[\[7\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | CLI flags for network/data files, kinopt/tfopt parameter JSONs and `--output-dir`[\[7\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | Kinase and TF networks (`input2.csv`, `input4.csv`), protein and RNA data (`input1.csv`, `input3.csv`), phospho data (`input1.csv`), JSON parameter files. | CSVs and plots in the specified output directory. | Unique analysis. | Yes – advanced analysis panel. | Refactor to accept parameter dictionaries rather than JSON files; allow users to select metrics; integrate into backend. | +| `temporal_sensitivity.py` | Perform global sensitivity analysis using SALib and Sobol' indices[\[7\]\[8\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | CLI flags `--results-dir`, `--samples` (must be a power of two)[\[8\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | A completed `networkmodel` result directory; JSON parameter files inside. | CSV of Sobol' first‑order and total‑order indices; Plotly HTML plots of parameter rankings over time[\[8\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md). | Complementary to built‑in networkmodel sensitivity analysis. | Yes – optional analysis after model run. | Offload heavy sampling to worker processes; provide progress feedback; integrate into advanced panel. | + +## 5. Result Directory and Output Format Audit + +### 5.1 Current conventions + +Different modules produce outputs in various layouts, leading to inconsistent parsing. The tests for the global model enforce that optimisation outputs reside in subdirectories named `optimization`, `profiles`, `posterior` and `plots` inside the user‑specified output directory, with CSVs such as `multistart_summary.csv`, `best_fit.csv`, `profile_likelihood_summary.csv` and `posterior_summary.csv`[\[3\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/dashboard.md). Predicted timeseries (`pred_prot_picked.csv`, `pred_rna_picked.csv`, `pred_phospho_picked.csv`) live at the top level of the output directory alongside `scalar_objective.csv` (or its alias `pareto_F.csv`). A pickled bundle (`dashboard_bundle.pkl`) stores scalar objectives and metadata[\[2\]](file:///home/oai/share/phoskintime/phoskintime-global/config/cli.py). + +`kinopt.local` and `tfopt.local` write their Excel results (`*_results.xlsx`), multistart summaries and parameter arrays into a `results` directory defined in `config.toml`. They also copy the final Excel file to `data/ode/` (hard‑coded) and generate plots and an HTML report via `latexit`. The directory structure is flat and does not clearly separate raw tables, plots, logs or metadata. + +`protwise/runner` and the network readout scripts produce additional outputs like heatmaps, PCA plots and LaTeX reports. These are saved directly in the `OUT_DIR` without subfolder structure. + +### 5.2 Problems + +1. **Inconsistent directory layouts** – different optimisers write files into different folder names (`results`, `optimization`, `profiles`, `posterior`, `plots`), making it hard to build a general result browser. +2. **Missing metadata** – most modules do not write a `metadata.json` capturing the command run, version of the software, time stamps and resolved configuration. Provenance tracking is essential for reproducibility. +3. **Implicit copying** – `kinopt.local` copies the final Excel results to `data/ode/`, which mixes inputs and outputs. +4. **Lack of standardised logs** – logs are emitted to the console or separate log directories but are not always saved alongside the results with consistent file names. +5. **Varied naming conventions** – some outputs use long sheet names (“Alpha Values”), while others use snake_case CSVs; this complicates programmatic discovery. + +### 5.3 Proposed result directory contract + +To support a robust frontend, a unified result directory structure is proposed: + + results// + ├── metadata.json # date/time, command, git commit, resolved config, module version + ├── command.txt # exact CLI command executed + ├── console.log # captured stdout/stderr + ├── config_resolved.yaml # full configuration used for the run + ├── tables/ # CSV/TSV/XLSX result tables (e.g., multistart summaries, parameter matrices) + ├── plots/ # static image files (PNG/SVG) and interactive HTML/JSON for Plotly + ├── logs/ # per‑run log files if separate from console.log + ├── reports/ # HTML or PDF reports generated by latextit/markdown + └── artifacts/ # pickled bundles, NPZ arrays, NPZ parameter samples, etc. + +Each module should accept an explicit `--outdir` parameter, create the directory if it does not exist and write all outputs relative to that folder. Hard‑coded copies to `data/ode/` should be removed. The `metadata.json` should include at least: date/time, package version, commit hash, command arguments, data file hashes and time grid used. This contract mirrors the information needed by the Streamlit dashboards and ensures that the frontend can parse results consistently. + +### 5.4 Comparison with existing outputs + +| Module / script | Meets proposed contract? | Required changes | +|--------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `networkmodel/runner.py` | **Partial.** Writes a pickled bundle, `scalar_objective.csv`, convergence history and prediction CSVs, and organises optimisation, profiles and posterior outputs into subfolders. Lacks `metadata.json` and `command.txt`, and logs are not always captured. | Add metadata and provenance files; save resolved configuration; unify names (e.g., always write `scalar_objective.csv` rather than `pareto_F.csv`); create `tables/` and `plots/` subfolders instead of mixing files in top‑level output. | +| `kinopt.local` / `tfopt.local` | **No.** Flat output in `results`; no metadata; copying to `data/ode`; no standardised logs. | Accept `--outdir`; create subfolders; write metadata; record CLI command; avoid copying results to data directory; separate tables from plots. | +| `protwise/runner` | **Partial.** Writes predictions and reports but without metadata. | Same as above: unify output structure; include metadata and provenance files. | +| Post‑processing scripts | **Varies.** Most scripts accept an `--out-dir` and write CSVs/plots inside, but they do not write metadata or logs. | Standardise by writing into `tables/` and `plots/` subfolders and including a brief metadata file (script name, parameters). | + +## 6. Module‑Level Frontend Readiness + +### 6.1 Kinopt + +- **CLI availability:** Two flavours (`local` and `evol`) with `argparse` CLIs. Typer wrapper in `config/cli.py` simplifies invocation. +- **Input validation:** Arguments are parsed but input files are implicitly read from paths defined in `config.toml`. Missing file errors propagate as Python exceptions. No interactive validation. +- **Output consistency:** Outputs are placed in a flat `results` directory; Excel file names are fixed; some results copied to `data/ode/`. +- **Plotting/export behaviour:** A large number of static plots are generated using matplotlib and saved into the same directory. A LaTeX report is produced via `latexit`. +- **Missing‑data handling:** Options such as `--estimate_missing_kinases` allow imputation, but the CLI does not check whether required columns are present in input CSVs. +- **Error reporting:** Errors propagate through Python traces; no structured error messages for user consumption. +- **Frontend integration risks:** Long‑running multistart optimisation may block the UI; the code writes to disk and expects certain directory names; logs and progress are not streamed. +- **Required refactors:** Factor out core optimisation into a function that accepts inputs and returns results; add progress callbacks; standardise output directory; ensure the function raises informative exceptions; return results as data structures for immediate plotting. + +### 6.2 TFopt + +- **CLI availability:** Similar to Kinopt; separate `local` and `evol` modules; Typer wrapper. +- **Input validation:** Data loading functions assume particular sheet names and column order; poor handling of missing or malformed input. +- **Output consistency:** Same issues as Kinopt: flat directory; Excel results; plots without metadata. +- **Plotting/export behaviour:** Many static plots; report via `latexit`. +- **Integration risks:** Large matrices and multistart optimisation may take time; network visualisation (gravis) requires Graphviz; potential memory use. +- **Required refactors:** Provide function‐level API; standardise outputs; allow asynchronous execution; better input validation and user feedback; ensure dependencies (gravis, pygraphviz) are optional. + +### 6.3 Protwise + +- **CLI availability:** `protwise.runner.main` is invoked via pixi task or Typer wrapper; accepts configuration file to run protein dynamics simulations. +- **Input validation:** Expects configuration with parameter bounds and initial conditions; may fail with cryptic error if not provided. +- **Output consistency:** Writes predictions and plots in its output directory but lacks metadata and standard subfolder structure. +- **Integration risks:** JAX/NumPy heavy ODE solver; may require GPU or CPU thread control; long runtime; numerous plots and sensitivity analyses. +- **Required refactors:** Unify with global result contract; export predictions as CSV; provide progress updates; catch exceptions. + +### 6.4 Networkmodel + +- **CLI availability:** `networkmodel/runner.py` uses `argparse` and accepts many parameters (paths, regularisation values, solver choice, iteration counts)[\[3\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/dashboard.md). +- **Input validation:** Some checks for file existence and consistent shapes; still heavy reliance on defaults from `config.toml` and implicit assumptions (e.g., presence of kinopt/tfopt results for parameter initialisation). +- **Output consistency:** Better than other modules; results placed into subfolders (`optimization`, `profiles`, `posterior`, `plots`) and pickled bundle saved[\[2\]](file:///home/oai/share/phoskintime/phoskintime-global/config/cli.py); however metadata and command provenance are missing. +- **Integration risks:** Long runtimes (hyperparameter scanning, sensitivity analysis, posterior sampling); heavy memory usage; JAX/NumPy error messages; concurrency issues if run inside Streamlit process. +- **Required refactors:** Provide API to run the model asynchronously (e.g., via multiprocessing); unify result directory; capture metadata; export predictions and objective values in separate tables; decouple dashboard bundling from run to allow user‑selected result directories; ensure logs and errors are captured for UI. + +## 7. Proposed Unified Frontend Architecture + +The unified no‑code frontend should wrap existing scientific modules without re‑implementing their logic. It should consist of three conceptual layers: + + Frontend (Streamlit UI) + ├─ Wrapper (command builder + launcher) + ├─ Result viewer (table/plot/log/metadata browser) + └─ Workflow panels (for kinopt, tfopt, protwise, networkmodel) + + CLI modules (source of truth) ↔ Scientific modules (model logic) + +### 7.1 Core components + +1. **Upload panel** – allows users to upload raw data (CSV or Excel) or preprocessed results. Performs basic validation and previews files. Supports selecting sample configuration files. + +2. **Workflow selector** – lists available workflows (`prep`, `tfopt`, `kinopt`, `model`, `networkmodel`) and shows a description and estimated runtime. + +3. **Configuration panel** – exposes CLI arguments for the selected workflow. For example, for `kinopt` and `tfopt`, the user can choose bounds, loss type, scaling method, segmentation points and number of multistart runs. For `networkmodel`, users can set regularisation λ values, solver choice, generation count and toggle sensitivity or hyperparameter scanning. Each option should display the default value and help text. + +4. **Command preview** – shows the exact command that will be executed (e.g., `python -m kinopt.local --lower_bound -4 --upper_bound 4 --loss_type weighted ...`). This transparency builds trust and allows advanced users to copy the command for manual runs. The preview updates when the user modifies options. + +5. **Pixi environment selector** – allows selecting a Pixi environment (`default`, `dev`, `viz`, `full`) before launching the command. It may call `pixi run` under the hood. + +6. **Execution console** – a console panel streams stdout/stderr and displays progress. Long‑running jobs should run in separate worker processes to keep the UI responsive. Provide cancellation and show runtime and status at completion. Save the command and console output to `command.txt` and `console.log` in the result directory. + +7. **Result browser** – after a run, detect the `results/` directory and display a tree of available outputs. Users can navigate into tables, plots, logs, reports and artifacts. Provide viewers for DataFrames (sorting/filtering), images (with download), interactive Plotly charts, log files, HTML/PDF reports and metadata. Offer a ZIP download of the entire run. + +8. **Workflow‑specific panels** – for each major module: + +9. **Kinopt panel** – embed computations and visualisations from `app/kinopt.py`; allow uploading results or linking from a recent run; provide options to recompute knockout effects and network filters. + +10. **TFopt panel** – embed `app/tfopt.py` similarly. + +11. **Protwise panel** – design a new panel summarising ODE predictions, parameter profiles, PCA/t‑SNE results, residual plots and sensitivity indices. + +12. **Networkmodel panel** – reuse `networkmodel/dashboard_app.py` to view global optimisation results; add additional tabs for inference outputs and advanced analyses. + +13. **Advanced analysis panel** – integrate functions for Fréchet distance, accumulator detection, mechanistic insights and temporal sensitivity. Provide parameter sliders and run analyses asynchronously. + +### 7.2 Interaction flow + +1. **Load data** – user uploads or selects raw files; `prep` can be run if necessary. +2. **Optimise TF or kinase modules** – user configures parameters and launches `tfopt` or `kinopt`. On completion, immediate analysis is available via their respective panels. +3. **Run Protwise model** – using optimised alpha/beta values, the user runs the ODE model and explores results in the Protwise panel. +4. **Run global model** – user configures and launches `networkmodel` optimisation; results are explored via the Networkmodel panel and advanced analyses. +5. **Analyse results** – through the result browser and analysis panels, the user inspects outputs, compares fits, performs sensitivity analyses and exports findings. + +### 7.3 Separation of concerns + +To maintain maintainability and reproducibility, the frontend must **not** implement or duplicate scientific computations. All optimisation and modelling should be executed via existing CLI modules. The frontend acts as an orchestrator, passing validated arguments, launching subprocesses and visualising outputs. When new features are needed, the scientific code should be extended (e.g., adding an API function) rather than being re‑written in the UI layer. + +## 8. Integration Plan for Existing Apps + +Integration should proceed module by module: + +1. **Networkmodel dashboard** – wrap `networkmodel/dashboard_app.py` as a component that accepts a result directory and renders the existing tabs. Adjust to read the unified result contract and display metadata. +2. **Kinopt and TFopt dashboards** – refactor `app/kinopt.py` and `app/tfopt.py` into modules exposing functions that accept dataframes and parameters and return Streamlit layouts. The unified dashboard can call these functions after a run or when a user uploads results. Remove duplicated logic for reading from Excel; rely on result tables. +3. **Compare mechanisms** – break `scripts/compare_mechanisms.py` into backend functions for loading data, running steady‑state simulations and producing graphs. Provide a thin UI wrapper for integration into the advanced analysis panel. Offer asynchronous execution and caching. +4. **Legacy visualisation scripts** – mark `kinopt_network_viz.py`, `tfopt_network_viz.py` and network readout scripts as deprecated. Their functionality is replaced by interactive dashboards. Keep them only for batch use or reproducibility. +5. **Post‑processing utilities** – incorporate computations from scripts (Fréchet distance, accumulator detection, mechanistic insights, temporal sensitivity) into backend functions with clean APIs. Provide UI triggers for these analyses with progress feedback. Offer results in the result browser and advanced panel. + +## 9. Frontend Build Phases + +### Phase 0 — Audit and stabilisation + +- Complete this repository audit and agree on the standard result directory contract and metadata schema. +- Refactor modules to accept explicit `--outdir`, write metadata and provenance files, and avoid copying outputs into input folders. +- Remove hard‑coded default paths in scripts; parameterise inputs and outputs. + +### Phase 1 — Result browser integration + +- Implement a base Streamlit app with a sidebar for selecting a results directory. +- Build functions to parse the new result directory structure: list tables, plots, logs, reports and artifacts; read metadata; and return DataFrames or binary content. +- Add viewers for tables (using pandas and Streamlit), images, interactive Plotly charts and logs. Provide download buttons. +- Support zipped download of an entire result run. + +### Phase 2 — CLI launcher + +- Implement a command builder UI that lists available workflows (`prep`, `tfopt`, `kinopt`, `model`, `networkmodel`) and exposes their arguments. Use CLI descriptions for help texts. +- Show a command preview that updates with user selections. Provide a “Run” button that launches the command in a separate process or Pixi environment. Stream stdout/stderr to the UI and save them. +- Provide cancellation and error handling. On completion, detect the new results directory and open it in the result browser. + +### Phase 3 — Upload and configuration UI + +- Implement file upload for raw datasets and existing results. Validate file formats and show previews. +- Add configuration panels for each workflow with defaults from `config.toml`. Allow saving/loading presets. +- Allow selection of Pixi environment and detect missing optional dependencies. + +### Phase 4 — Workflow‑specific panels + +- **Kinopt panel:** integrate computation and visualisation from `app/kinopt.py`; allow uploading results or linking from a previous run; provide options to recompute knockout effects and network filters. +- **TFopt panel:** integrate `app/tfopt.py` similarly. +- **Protwise panel:** design a new panel summarising ODE predictions, parameter profiles, PCA/t‑SNE results, residual plots and sensitivity indices. +- **Networkmodel panel:** reuse `networkmodel/dashboard_app.py`; add additional tabs for inference outputs and advanced analyses. +- **Advanced analysis panel:** integrate functions for Fréchet distance, accumulator detection, mechanistic insights and temporal sensitivity. Provide parameter sliders and run analyses asynchronously. + +### Phase 5 — Testing and documentation + +- Write unit tests for the command builder, result parser and workflow registry. Mock CLI commands to ensure commands are constructed correctly. +- Add tests for file discovery and parsing across various result directory layouts. +- Write integration tests for script functions that compute Fréchet distance, accumulators and sensitivity indices. +- Document usage of the dashboard, including how to upload data, configure workflows, run optimisations and browse results. Update MkDocs accordingly. + +## 10. Required Code Changes Before Frontend Implementation + +1. **Consistent** `--outdir` **support** – all CLI modules must accept an explicit `--outdir` parameter and write all outputs relative to it. Default values can come from `config.toml`, but overrides must be honoured. +2. **Metadata and provenance** – every run should generate `metadata.json`, `command.txt` and `console.log` capturing the command, parameters, software version, commit and timestamps. +3. **Predictable subfolders** – adopt the proposed `tables/`, `plots/`, `logs/`, `reports/` and `artifacts/` layout. Group plots by category. +4. **Consistent naming** – unify file names (use snake_case; avoid spaces); always write `scalar_objective.csv` rather than alias `pareto_F.csv`. +5. **Centralised logging** – log to both console and a file in the run directory; support verbosity flags. +6. **Error handling** – catch common errors (missing files, malformed data) and emit user‑friendly messages; return non‑zero exit codes. +7. **API functions** – expose core functionality as importable functions so the frontend can call them directly; CLI wrappers should delegate to these functions. +8. **Remove implicit copies** – avoid copying results into `data/ode/` or other input directories; keep outputs within the result directory. +9. **No absolute paths** – ensure file paths in results and metadata are relative; sanitise paths in logs. +10. **Refactor scripts** – modify scripts to accept explicit input/output parameters, write metadata, and return data structures; provide a module interface (e.g., `def run_curve_similarity(...)`). + +## 11. Proposed File Structure + +To organise the unified frontend and keep it separate from the core package, add a `dashboard/` directory at the repository root. The following file structure is proposed (names may be adjusted): + + dashboard/ + ├── app.py # Streamlit entry point; sets up pages and routing + ├── command_builder.py # Builds CLI commands from user selections + ├── runner.py # Launches subprocesses or calls backend API asynchronously + ├── result_parser.py # Discovers result directories and parses tables/plots/logs/metadata + ├── file_utils.py # Helper functions for file upload, validation and zip download + ├── registry.py # Registers available workflows, their arguments and execution functions + ├── components/ + │ ├── upload_panel.py # Handles file uploads and previews + │ ├── workflow_selector.py + │ ├── command_preview.py + │ ├── console_panel.py + │ ├── result_browser.py + │ ├── table_viewer.py + │ ├── plot_viewer.py + │ ├── log_viewer.py + │ └── download_panel.py + └── workflow_panels/ + ├── kinopt.py # Wraps the Kinopt dashboard logic + ├── tfopt.py # Wraps the TFopt dashboard logic + ├── protwise.py # Summarises Protwise outputs + ├── networkmodel.py # Embeds the global dashboard + └── analysis.py # Advanced analysis panels (Fréchet, accumulators, sensitivity) + + tests/dashboard/ + ├── test_command_builder.py + ├── test_result_parser.py + ├── test_registry.py + └── test_file_utils.py + +This structure isolates UI components, workflow definitions and utility functions. Each `workflow_panels/*.py` file should import the corresponding backend module, call its API functions and use Streamlit to present outputs. The tests ensure that commands are built correctly, results are parsed and that the registry contains all expected workflows. + +## 12. Pixi and Dependency Plan + +The current `pixi.toml` lists numerous dependencies, some of which are heavy or optional. For the frontend, only a subset is required. Recommended dependencies: + +| Package | Purpose | Optional? | +|---------------------------------------|---------------------------------------------------------------------------------------|--------------------------------------------------------------| +| **streamlit** | Web UI framework; core requirement | No | +| **pandas** | DataFrame operations and CSV/XLSX parsing | No | +| **openpyxl** | Read Excel files in upload panels and TF/Kinopt dashboards | Yes (only if Excel preview needed) | +| **plotly** | Interactive plots in dashboards | Yes (can fallback to matplotlib) | +| **pyarrow** | For Parquet support in large tables | Yes | +| **gravis**, **networkx**, **imageio** | Required for network visualisation in TF/Kinopt dashboards and compare_mechanisms app | Optional; should be loaded only when network panels are used | + +Pixi tasks should be added for the dashboard. In `pixi.toml`, under `[tasks]`, add: + + dashboard = "streamlit run dashboard/app.py" + dashboard-dev = "streamlit run dashboard/app.py --server.runOnSave true" + +Users can then run `pixi run dashboard` or `dashboard-dev`. The frontend should detect missing optional dependencies and disable features accordingly. + +## 13. Risks and Mitigations + +| Risk | Description | Mitigation | +|---------------------------------------------------------|-------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Duplicate dashboards** | Existing Streamlit apps may diverge from the unified frontend. | Keep original apps for backward compatibility, but route users to the unified dashboard. Import existing dashboard functions instead of re‑implementing logic. | +| **Inconsistent output folders** | Modules currently write results into varying layouts. | Refactor modules to adopt the proposed result contract. Implement the result browser to handle legacy layouts gracefully (e.g., recognise `optimization`, `profiles`, `plots` subfolders). | +| **Scripts bypass package logic** | Scripts reimplement analysis instead of importing functions. | Refactor scripts into backend modules; use them in both CLI and UI; deprecate direct script usage. | +| **Frontend becomes a second scientific implementation** | Risk of duplicating computations in the UI. | Keep scientific code exclusively in backend modules; the UI calls them via API functions or CLI wrappers. | +| **Broken CLI commands** | Parameter changes or refactors may break existing pipelines. | Write regression tests for each CLI entry point; maintain backward compatibility through Typer wrappers; document deprecated flags. | +| **Large result folders** | Output directories may contain hundreds of MB of plots, NPZ files and videos. | Implement lazy loading of plots; compress images for web; allow users to choose which subfolders to load; offer zipped downloads. | +| **Long‑running jobs blocking Streamlit** | Optimisation and inference can take minutes or hours. | Run jobs in separate processes or using asynchronous workers; show progress bars and allow cancellation; persist results to disk for later review. | +| **Missing provenance** | Without metadata, users cannot reproduce runs. | Enforce writing of `metadata.json`, `command.txt` and `console.log` on every run; display metadata in the result browser. | +| **Hidden local paths** | Absolute paths in outputs may expose local directory structure. | Use relative paths in outputs; sanitise paths in metadata and logs. | + +## 14. Final Recommendation + +The PhosKinTime repository contains a rich suite of optimisation algorithms, ODE models, analysis scripts and interactive dashboards. Before building a no‑code frontend, stabilise the backend by refactoring modules to accept explicit output directories, write metadata and adopt a unified result layout. De‑duplicate analysis logic by moving computations into importable functions and reusing them in both CLI scripts and Streamlit dashboards. Once the backend is standardised, proceed with the phased implementation of the unified dashboard: start with a result browser, then add a command builder and upload/configuration panels, followed by workflow‑specific panels that embed existing dashboards. Finally, implement advanced analysis panels and comprehensive tests. By following this plan, the no‑code frontend will provide a seamless experience for researchers while preserving the integrity and reproducibility of the underlying scientific computations. + +[\[1\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md) [\[5\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md) [\[6\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md) [\[7\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md) [\[8\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/scripts.md) \[title unknown\] + + + +[\[2\]](file:///home/oai/share/phoskintime/phoskintime-global/config/cli.py) \[title unknown\] + + + +[\[3\]](file:///home/oai/share/phoskintime/phoskintime-global/docs/Documentation/dashboard.md) \[title unknown\] + + + +[\[4\]](chrome://newtab/) \[title unknown\] + + From 4c042d87e8546b6fd59205030c8a1a9d3f637174 Mon Sep 17 00:00:00 2001 From: bibymaths Date: Wed, 10 Jun 2026 13:08:28 +0200 Subject: [PATCH 02/42] add: frontend plan renamed --- docs/{Audit_and_build_plan.md => dashboard_build_plan.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/{Audit_and_build_plan.md => dashboard_build_plan.md} (100%) diff --git a/docs/Audit_and_build_plan.md b/docs/dashboard_build_plan.md similarity index 100% rename from docs/Audit_and_build_plan.md rename to docs/dashboard_build_plan.md From b01db87452acb231c77daaca8a24be0f6cc94063 Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Wed, 10 Jun 2026 17:56:19 +0530 Subject: [PATCH 03/42] Standardize dashboard-ready output contract --- common/__init__.py | 8 +- common/results.py | 229 ++++++++++++++++++++++++++++ config/cli.py | 23 ++- config/config.py | 4 + docs/Documentation/scripts.md | 4 + docs/dashboard_build_plan.md | 4 + kinopt/local/__main__.py | 63 +++++--- kinopt/local/config/constants.py | 9 ++ kinopt/local/exporter/plotout.py | 20 +-- kinopt/local/exporter/sheetutils.py | 16 +- networkmodel/runner.py | 20 ++- protwise/runner/main.py | 19 +++ tests/test_result_contract.py | 77 ++++++++++ tfopt/local/__main__.py | 50 +++--- tfopt/local/config/constants.py | 10 +- 15 files changed, 490 insertions(+), 66 deletions(-) create mode 100644 common/results.py create mode 100644 tests/test_result_contract.py diff --git a/common/__init__.py b/common/__init__.py index c1495b5..99f847d 100644 --- a/common/__init__.py +++ b/common/__init__.py @@ -1 +1,7 @@ -from common.utils.display import format_duration \ No newline at end of file +def format_duration(seconds): + """Format a duration in seconds into a human-readable string.""" + if seconds < 60: + return f"{seconds:.2f} sec" + if seconds < 3600: + return f"{seconds / 60:.2f} min" + return f"{seconds / 3600:.2f} hr" diff --git a/common/results.py b/common/results.py new file mode 100644 index 0000000..a46e3c7 --- /dev/null +++ b/common/results.py @@ -0,0 +1,229 @@ +from __future__ import annotations + +import hashlib +import json +import os +import platform +import shutil +import subprocess +import sys +from contextlib import contextmanager +from datetime import datetime, timezone +from pathlib import Path +from typing import Any, Iterable + +STANDARD_SUBDIRS = ("tables", "plots", "logs", "reports", "artifacts") + + +def ensure_result_dir(outdir: str | Path) -> dict[str, Path]: + root = Path(outdir).expanduser().resolve() + root.mkdir(parents=True, exist_ok=True) + paths = {"root": root} + for name in STANDARD_SUBDIRS: + p = root / name + p.mkdir(parents=True, exist_ok=True) + paths[name] = p + return paths + + +def file_sha256(path: str | Path, chunk_size: int = 1024 * 1024) -> str | None: + p = Path(path) + if not p.is_file(): + return None + h = hashlib.sha256() + with p.open("rb") as fh: + for chunk in iter(lambda: fh.read(chunk_size), b""): + h.update(chunk) + return h.hexdigest() + + +def describe_inputs(paths: Iterable[str | Path | None]) -> list[dict[str, Any]]: + out = [] + for raw in paths: + if raw is None: + continue + p = Path(raw).expanduser() + item: dict[str, Any] = {"path": str(p)} + if p.exists(): + try: + item["resolved_path"] = str(p.resolve()) + except OSError: + pass + if p.is_file(): + item["sha256"] = file_sha256(p) + item["size_bytes"] = p.stat().st_size + else: + item["missing"] = True + out.append(item) + return out + + +def package_version() -> str | None: + try: + import importlib.metadata as metadata + return metadata.version("phoskintime") + except Exception: + pass + try: + import tomllib + with Path("pixi.toml").open("rb") as fh: + return tomllib.load(fh).get("workspace", {}).get("version") + except Exception: + return None + + +def git_commit() -> str | None: + try: + return subprocess.check_output( + ["git", "rev-parse", "HEAD"], stderr=subprocess.DEVNULL, text=True + ).strip() + except Exception: + return None + + +def pixi_environment() -> str | None: + return os.environ.get("PIXI_ENVIRONMENT_NAME") or os.environ.get("PIXI_ENVIRONMENT") + + +def command_text(argv: Iterable[str] | None = None) -> str: + args = list(sys.argv if argv is None else argv) + return " ".join(shlex_quote(a) for a in args) + + +def shlex_quote(value: str) -> str: + import shlex + return shlex.quote(str(value)) + + +def _jsonable(value: Any) -> Any: + if isinstance(value, Path): + return str(value) + if isinstance(value, dict): + return {str(k): _jsonable(v) for k, v in value.items()} + if isinstance(value, (list, tuple, set)): + return [_jsonable(v) for v in value] + if hasattr(value, "__dict__"): + return _jsonable(vars(value)) + try: + json.dumps(value) + return value + except TypeError: + return str(value) + + +def write_command(outdir: str | Path, argv: Iterable[str] | None = None) -> Path: + root = ensure_result_dir(outdir)["root"] + path = root / "command.txt" + path.write_text(command_text(argv) + "\n", encoding="utf-8") + return path + + +def write_metadata( + outdir: str | Path, + workflow: str, + args: Any | None = None, + inputs: Iterable[str | Path | None] = (), + extra: dict[str, Any] | None = None, +) -> Path: + root = ensure_result_dir(outdir)["root"] + metadata = { + "workflow": workflow, + "timestamp": datetime.now(timezone.utc).isoformat(), + "command_arguments": _jsonable(args) if args is not None else sys.argv[1:], + "output_directory": str(root), + "package_version": package_version(), + "git_commit": git_commit(), + "python_version": platform.python_version(), + "python_executable": sys.executable, + "pixi_environment": pixi_environment(), + "inputs": describe_inputs(inputs), + } + if extra: + metadata.update(_jsonable(extra)) + path = root / "metadata.json" + path.write_text(json.dumps(metadata, indent=2, sort_keys=True) + "\n", encoding="utf-8") + return path + + +def write_resolved_config(outdir: str | Path, config: Any | None) -> Path | None: + if config is None: + return None + root = ensure_result_dir(outdir)["root"] + path = root / "config_resolved.yaml" + try: + import yaml # type: ignore + text = yaml.safe_dump(_jsonable(config), sort_keys=True) + except Exception: + text = json.dumps(_jsonable(config), indent=2, sort_keys=True) + path.write_text(text, encoding="utf-8") + return path + + +@contextmanager +def tee_console_log(outdir: str | Path): + root = ensure_result_dir(outdir)["root"] + log_path = root / "console.log" + class Tee: + def __init__(self, stream, fh): + self.stream = stream + self.fh = fh + def write(self, data): + self.stream.write(data) + self.fh.write(data) + def flush(self): + self.stream.flush(); self.fh.flush() + with log_path.open("a", encoding="utf-8") as fh: + old_out, old_err = sys.stdout, sys.stderr + sys.stdout, sys.stderr = Tee(old_out, fh), Tee(old_err, fh) + try: + yield log_path + finally: + sys.stdout, sys.stderr = old_out, old_err + + +def attach_file_console_logger(logger, outdir: str | Path, filename: str = "console.log"): + import logging + root = ensure_result_dir(outdir)["root"] + log_path = root / filename + abs_path = str(log_path.resolve()) + for handler in logger.handlers: + if getattr(handler, "baseFilename", None) == abs_path: + return log_path + handler = logging.FileHandler(log_path, mode="a", encoding="utf-8") + handler.setLevel(logging.DEBUG) + handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")) + logger.addHandler(handler) + return log_path + + +def populate_standard_subdirs(outdir: str | Path, *, copy: bool = True) -> None: + paths = ensure_result_dir(outdir) + root = paths["root"] + skip_names = set(STANDARD_SUBDIRS) | {"metadata.json", "command.txt", "console.log", "config_resolved.yaml"} + table_ext = {".csv", ".tsv", ".xlsx", ".xls", ".parquet", ".json", ".npy", ".npz"} + plot_ext = {".png", ".jpg", ".jpeg", ".svg", ".pdf", ".html"} + report_names = {"report.html"} + artifact_ext = {".pkl", ".pickle", ".joblib"} + for p in list(root.iterdir()): + if p.name in skip_names or p.is_dir(): + continue + ext = p.suffix.lower() + if p.name in report_names: + dest_dir = paths["reports"] + elif ext in table_ext: + dest_dir = paths["tables"] + elif ext in plot_ext: + dest_dir = paths["plots"] + elif ext in artifact_ext: + dest_dir = paths["artifacts"] + elif ext == ".log": + dest_dir = paths["logs"] + else: + dest_dir = paths["artifacts"] + dest = dest_dir / p.name + if dest.exists(): + continue + if copy: + shutil.copy2(p, dest) + else: + shutil.move(str(p), str(dest)) diff --git a/config/cli.py b/config/cli.py index b35687f..fcd2f46 100644 --- a/config/cli.py +++ b/config/cli.py @@ -54,7 +54,7 @@ def _run(cmd: list[str]) -> None: sp.check_call([PY, "-m", *cmd], cwd=ROOT) -def _python_module(module: str, cfg: Path | None) -> list[str]: +def _python_module(module: str, cfg: Path | None, outdir: Path | None = None) -> list[str]: """ Return `python module [--conf path]`. @@ -67,6 +67,8 @@ def _python_module(module: str, cfg: Path | None) -> list[str]: cmd = [module] if cfg is not None: cmd += ["--conf", str(cfg)] + if outdir is not None: + cmd += ["--outdir", str(outdir)] return cmd @@ -84,6 +86,7 @@ def prep(): @app.command() def tfopt( mode: str = typer.Option("local", help="local | evol"), + outdir: Path | None = typer.Option(None, "--outdir", "--output-dir", file_okay=False, dir_okay=True, help="Directory for workflow outputs."), conf: Path | None = typer.Option( None, "--conf", file_okay=True, dir_okay=False, writable=False, help="Path to TOML/YAML config. Uses defaults if omitted." @@ -99,12 +102,13 @@ def tfopt( None """ module = f"tfopt.{mode}" - _run(_python_module(module, conf)) + _run(_python_module(module, conf, outdir if mode == "local" else None)) @app.command() def kinopt( mode: str = typer.Option("local", help="local | evol"), + outdir: Path | None = typer.Option(None, "--outdir", "--output-dir", file_okay=False, dir_okay=True, help="Directory for workflow outputs."), conf: Path | None = typer.Option( None, "--conf", file_okay=True, dir_okay=False, writable=False, help="Path to TOML/YAML config. Uses defaults if omitted." @@ -120,11 +124,12 @@ def kinopt( None """ module = f"kinopt.{mode}" - _run(_python_module(module, conf)) + _run(_python_module(module, conf, outdir if mode == "local" else None)) @app.command() def model( + outdir: Path | None = typer.Option(None, "--outdir", "--output-dir", file_okay=False, dir_okay=True, help="Directory for workflow outputs."), conf: Path | None = typer.Option( None, "--conf", file_okay=True, dir_okay=False, writable=False, help="Path to model config file. Uses defaults if omitted." @@ -138,11 +143,12 @@ def model( Returns: None """ - _run(_python_module("protwise.runner.main", conf)) + _run(_python_module("protwise.runner.main", conf, outdir)) @app.command() def networkmodel( + outdir: Path | None = typer.Option(None, "--outdir", "--output-dir", file_okay=False, dir_okay=True, help="Directory for workflow outputs."), conf: Path | None = typer.Option( "config.toml", "--conf", file_okay=True, dir_okay=False, writable=False, help="Path to global model config file. Uses config.toml by default." @@ -155,7 +161,7 @@ def networkmodel( section of your configuration. """ # Assuming the package is named 'networkmodel' and has a 'runner.py' - _run(_python_module("networkmodel.runner", conf)) + _run(_python_module("networkmodel.runner", conf, outdir)) @app.command() @@ -201,6 +207,7 @@ def all( tf_conf: Path | None = typer.Option(None, help="tfopt config file"), kin_conf: Path | None = typer.Option(None, help="kinopt config file"), model_conf: Path | None = typer.Option(None, help="model config file"), + outdir: Path | None = typer.Option(None, "--outdir", "--output-dir", file_okay=False, dir_okay=True, help="Base directory for workflow outputs."), ): """ Run every stage in sequence. @@ -220,9 +227,9 @@ def all( None """ prep() - tfopt.callback(mode=tf_mode, conf=tf_conf) - kinopt.callback(mode=kin_mode, conf=kin_conf) - model.callback(conf=model_conf) + tfopt.callback(mode=tf_mode, conf=tf_conf, outdir=(outdir / "tfopt" if outdir else None)) + kinopt.callback(mode=kin_mode, conf=kin_conf, outdir=(outdir / "kinopt" if outdir else None)) + model.callback(conf=model_conf, outdir=(outdir / "protwise" if outdir else None)) if __name__ == "__main__": diff --git a/config/config.py b/config/config.py index 4434f3f..75b76c7 100644 --- a/config/config.py +++ b/config/config.py @@ -102,6 +102,7 @@ def parse_args(): parser = argparse.ArgumentParser( description="PhosKinTime - ODE Parameter Estimation of Cell Signalling Events in Temporal Space" ) + parser.add_argument("--conf", default=None, help="Compatibility option; configuration is loaded before argument parsing.") parser.add_argument("--A-bound", type=parse_bound_pair, default=f"0, {UB_mRNA_prod}") parser.add_argument("--B-bound", type=parse_bound_pair, default=f"0, {UB_mRNA_deg}") parser.add_argument("--C-bound", type=parse_bound_pair, default=f"0, {UB_Protein_prod}") @@ -118,6 +119,8 @@ def parse_args(): parser.add_argument("--input-excel-rna", type=str, default=INPUT_EXCEL_RNA, help="Path to the estimated optimized mRNA-TF file") + parser.add_argument("--outdir", "--output-dir", dest="outdir", type=str, default=None, + help="Directory where all run outputs and provenance files are written.") return parser.parse_args() @@ -170,6 +173,7 @@ def extract_config(args): 'input_excel_psite': args.input_excel_psite, 'input_excel_rna': args.input_excel_rna, 'max_workers': 1 if DEV_TEST else os.cpu_count(), + 'outdir': args.outdir, } return config diff --git a/docs/Documentation/scripts.md b/docs/Documentation/scripts.md index b26d263..59f2f8f 100644 --- a/docs/Documentation/scripts.md +++ b/docs/Documentation/scripts.md @@ -220,3 +220,7 @@ High sample counts significantly increase computation time. `networkmodel/config.py`. - The `compare_mechanisms.py` script requires additional dependencies (`gravis`, `networkx`, `imageio`) not included in the base `requirements.txt`. + +## Dashboard-ready output directories + +Major backend workflows accept an explicit `--outdir`/`--output-dir` option so automated tools and the planned no-code dashboard can discover outputs consistently. A run directory contains `metadata.json`, `command.txt`, `console.log`, `config_resolved.yaml` when applicable, and the standard `tables/`, `plots/`, `logs/`, `reports/`, and `artifacts/` subdirectories. Legacy filenames are retained at the run-directory root where existing scripts or documentation rely on them, with dashboard-facing copies mirrored into the standard subfolders. diff --git a/docs/dashboard_build_plan.md b/docs/dashboard_build_plan.md index 1562326..55d2641 100644 --- a/docs/dashboard_build_plan.md +++ b/docs/dashboard_build_plan.md @@ -369,3 +369,7 @@ The PhosKinTime repository contains a rich suite of optimisation algorithms, ODE [\[4\]](chrome://newtab/) \[title unknown\] + +### Phase 0 implementation note (June 2026) + +The backend output contract is implemented with shared result utilities in `common/results.py`. The local kinase, local TF, ProtWise runner, network model runner, and Typer workflow wrappers now accept `--outdir`/`--output-dir` and initialize the standard run subdirectories (`tables/`, `plots/`, `logs/`, `reports/`, `artifacts/`) plus provenance files (`metadata.json`, `command.txt`, `console.log`, and `config_resolved.yaml` when a resolved configuration is available). Legacy top-level output filenames are retained for compatibility, and dashboard-facing copies are mirrored into the standard subfolders. diff --git a/kinopt/local/__main__.py b/kinopt/local/__main__.py index fa09afb..2bf60f2 100644 --- a/kinopt/local/__main__.py +++ b/kinopt/local/__main__.py @@ -1,7 +1,6 @@ -import shutil from functools import partial -from kinopt.local.config.constants import parse_args, OUT_DIR, OUT_FILE, ODE_DATA_DIR +from kinopt.local.config.constants import parse_args, OUT_FILE, INPUT1, INPUT2, _CFG from kinopt.local.config.helpers import location from kinopt.local.exporter.plotout import export_outcomes_to_csv, plot_multistart_summary_runtime_overlay from kinopt.local.exporter.sheetutils import output_results, export_params_npz @@ -16,6 +15,10 @@ from kinopt.optimality.KKT import post_optimization_results from kinopt.fitanalysis import optimization_performance from common.utils import latexit +from common.results import ( + attach_file_console_logger, ensure_result_dir, populate_standard_subdirs, + write_command, write_metadata, write_resolved_config, +) logger = setup_logger() @@ -33,7 +36,23 @@ def main(): check_kinases() # Parse arguments. - lb, ub, loss_type, estimate_missing, scaling_method, split_point, seg_points, opt_method = parse_args() + lb, ub, loss_type, estimate_missing, scaling_method, split_point, seg_points, opt_method, out_dir = parse_args() + result_dirs = ensure_result_dir(out_dir) + out_dir = result_dirs["root"] + out_file = out_dir / OUT_FILE.name + attach_file_console_logger(logger, out_dir) + write_command(out_dir) + write_resolved_config(out_dir, _CFG) + write_metadata( + out_dir, + workflow="kinopt.local", + args={ + "lower_bound": lb, "upper_bound": ub, "loss_type": loss_type, + "estimate_missing_kinases": estimate_missing, "scaling_method": scaling_method, + "split_point": split_point, "segment_points": seg_points, "method": opt_method, + }, + inputs=[INPUT1, INPUT2], + ) # Load and scale data. full_df, interact_df, _ = load_and_scale_data(estimate_missing, scaling_method, split_point, seg_points) @@ -107,16 +126,16 @@ def main(): # Save outcomes export_outcomes_to_csv( outcomes, - OUT_DIR / "multistart_summary.csv" + out_dir / "multistart_summary.csv" ) # Save optimized parameters for each start - export_params_npz(outcomes, OUT_DIR / "multistart_params.npz") + export_params_npz(outcomes, out_dir / "multistart_params.npz") # Save runtime vs objective function value plot plot_multistart_summary_runtime_overlay( - OUT_DIR / "multistart_summary.csv", - out_path=OUT_DIR / "multistart_fun_vs_rank_runtime.png", + out_dir / "multistart_summary.csv", + out_path=out_dir / "multistart_fun_vs_rank_runtime.png", figsize=(8, 8), ) @@ -133,28 +152,36 @@ def main(): # Output results. output_results(P_initial, P_init_dense, P_estimated, residuals, alpha_values, beta_values, - result, mse, rmse, mae, mape, r_squared) - - # Copy output file to ODE data directory. - shutil.copy(OUT_FILE, ODE_DATA_DIR / OUT_FILE.name) - - # Analyze optimization performance. + result, mse, rmse, mae, mape, r_squared, filename=out_file, out_dir=out_dir) + + + # Analyze optimization performance using the selected result directory. + import kinopt.optimality.KKT as kkt_module + import kinopt.fitanalysis.__main__ as fitanalysis_module + import kinopt.fitanalysis.helpers.postfit as postfit_module + kkt_module.OUT_FILE = out_file + kkt_module.OUT_DIR = out_dir + fitanalysis_module.OUT_FILE = out_file + fitanalysis_module.OUT_DIR = out_dir + postfit_module.OUT_DIR = out_dir post_optimization_results() optimization_performance() # LateX the results. - latexit.main(OUT_DIR) + latexit.main(out_dir) # Organize output files and create a report. - organize_output_files(OUT_DIR) - create_report(OUT_DIR) + organize_output_files(out_dir) + create_report(out_dir) - logger.info(f'Report & Results {location(str(OUT_DIR))}') + logger.info(f'Report & Results {location(str(out_dir))}') # Click to open the report in a web browser. - for fpath in [OUT_DIR / 'report.html']: + for fpath in [out_dir / 'report.html']: logger.info(f"{fpath.as_uri()}") + populate_standard_subdirs(out_dir) + if __name__ == "__main__": main() diff --git a/kinopt/local/config/constants.py b/kinopt/local/config/constants.py index c2dcbb6..32dc1cf 100644 --- a/kinopt/local/config/constants.py +++ b/kinopt/local/config/constants.py @@ -45,6 +45,7 @@ def parse_args(): description="PhosKinTime - SLSQP/TRUST-CONSTR Kinase Phosphorylation Optimization Problem prior to ODE Modelling." ) + parser.add_argument("--conf", default=None, help="Compatibility option; configuration is loaded before argument parsing.") parser.add_argument("--lower_bound", type=float, default=float(_CFG.get("lower_bound", -4.0))) parser.add_argument("--upper_bound", type=float, default=float(_CFG.get("upper_bound", 4.0))) @@ -92,6 +93,13 @@ def parse_args(): default=str(_CFG.get("method", "slsqp")), help="Optimization method.", ) + parser.add_argument( + "--outdir", "--output-dir", + dest="outdir", + type=Path, + default=OUT_DIR, + help="Directory where all run outputs and provenance files are written.", + ) args = parser.parse_args() @@ -107,4 +115,5 @@ def parse_args(): args.split_point, seg_points, args.method, + args.outdir, ) diff --git a/kinopt/local/exporter/plotout.py b/kinopt/local/exporter/plotout.py index 1ab5a72..92bfd75 100644 --- a/kinopt/local/exporter/plotout.py +++ b/kinopt/local/exporter/plotout.py @@ -36,7 +36,7 @@ def format_timepoints(tp, tol=1e-9): labels.append(f"{x:.1f}") return labels -def plot_fits_for_gene(gene, gene_data, real_timepoints): +def plot_fits_for_gene(gene, gene_data, real_timepoints, out_dir=OUT_DIR): """ Function to plot the observed and estimated phosphorylation levels for each psite of a gene. @@ -86,7 +86,7 @@ def plot_fits_for_gene(gene, gene_data, real_timepoints): axs[1].set_xticklabels(format_timepoints(xt)) plt.tight_layout() - filename = f"{OUT_DIR}/{gene}_fit_.png" + filename = Path(out_dir) / f"{gene}_fit_.png" plt.savefig(filename, dpi=300, bbox_inches='tight') plt.close() @@ -120,7 +120,7 @@ def export_outcomes_to_csv(outcomes, csv_path): writer.writeheader() writer.writerows(rows) -def plot_cumulative_residuals(gene, gene_data, real_timepoints): +def plot_cumulative_residuals(gene, gene_data, real_timepoints, out_dir=OUT_DIR): """ Function to plot the cumulative residuals for each psite of a gene. @@ -142,12 +142,12 @@ def plot_cumulative_residuals(gene, gene_data, real_timepoints): plt.grid(True, alpha=0.2) plt.legend(title="Residue_Position") plt.tight_layout() - filename = f"{OUT_DIR}/{gene}_cumulative_residuals_.png" + filename = Path(out_dir) / f"{gene}_cumulative_residuals_.png" plt.savefig(filename, format='png', dpi=300) plt.close() -def plot_autocorrelation_residuals(gene, gene_data, real_timepoints): +def plot_autocorrelation_residuals(gene, gene_data, real_timepoints, out_dir=OUT_DIR): """ Function to plot the autocorrelation of residuals for each psite of a gene. @@ -164,12 +164,12 @@ def plot_autocorrelation_residuals(gene, gene_data, real_timepoints): plt.xlabel("Lags") plt.ylabel("Autocorrelation") plt.tight_layout() - filename = f"{OUT_DIR}/{gene}_autocorrelation_residuals_.png" + filename = Path(out_dir) / f"{gene}_autocorrelation_residuals_.png" plt.savefig(filename, format='png', dpi=300) plt.close() -def plot_histogram_residuals(gene, gene_data, real_timepoints): +def plot_histogram_residuals(gene, gene_data, real_timepoints, out_dir=OUT_DIR): """ Function to plot histograms of residuals for each psite of a gene. @@ -190,12 +190,12 @@ def plot_histogram_residuals(gene, gene_data, real_timepoints): plt.grid(True, alpha=0.2) plt.legend(title="Residue_Position") plt.tight_layout() - filename = f"{OUT_DIR}/{gene}_histogram_residuals_.png" + filename = Path(out_dir) / f"{gene}_histogram_residuals_.png" plt.savefig(filename, format='png', dpi=300) plt.close() -def plot_qqplot_residuals(gene, gene_data, real_timepoints): +def plot_qqplot_residuals(gene, gene_data, real_timepoints, out_dir=OUT_DIR): """ Function to plot QQ plots of residuals for each psite of a gene. @@ -209,7 +209,7 @@ def plot_qqplot_residuals(gene, gene_data, real_timepoints): qqplot(gene_data["residuals"][i], line='s', ax=plt.gca()) plt.title(f"{gene}") plt.tight_layout() - filename = f"{OUT_DIR}/{gene}_qqplot_residuals_.png" + filename = Path(out_dir) / f"{gene}_qqplot_residuals_.png" plt.savefig(filename, format='png', dpi=300) plt.close('all') diff --git a/kinopt/local/exporter/sheetutils.py b/kinopt/local/exporter/sheetutils.py index a6dd5a9..39f17b2 100644 --- a/kinopt/local/exporter/sheetutils.py +++ b/kinopt/local/exporter/sheetutils.py @@ -1,5 +1,5 @@ import pandas as pd -from kinopt.local.config.constants import TIME_POINTS, OUT_FILE +from kinopt.local.config.constants import TIME_POINTS, OUT_FILE, OUT_DIR from kinopt.local.exporter.helpers import build_genes_data from kinopt.local.exporter.plotout import * from kinopt.local.config.logconf import setup_logger @@ -8,7 +8,7 @@ def output_results(P_initial, P_init_dense, P_estimated, residuals, alpha_values, beta_values, - result, mse, rmse, mae, mape, r_squared): + result, mse, rmse, mae, mape, r_squared, filename=OUT_FILE, out_dir=OUT_DIR): """ Function to output the results of the optimization process. @@ -53,14 +53,14 @@ def output_results(P_initial, P_init_dense, P_estimated, residuals, alpha_values # For each gene, call the plotting functions. for gene, data in genes_data.items(): - plot_fits_for_gene(gene, data, TIME_POINTS) - plot_cumulative_residuals(gene, data, TIME_POINTS) - plot_autocorrelation_residuals(gene, data, TIME_POINTS) - plot_histogram_residuals(gene, data, TIME_POINTS) - plot_qqplot_residuals(gene, data, TIME_POINTS) + plot_fits_for_gene(gene, data, TIME_POINTS, out_dir=out_dir) + plot_cumulative_residuals(gene, data, TIME_POINTS, out_dir=out_dir) + plot_autocorrelation_residuals(gene, data, TIME_POINTS, out_dir=out_dir) + plot_histogram_residuals(gene, data, TIME_POINTS, out_dir=out_dir) + plot_qqplot_residuals(gene, data, TIME_POINTS, out_dir=out_dir) # Write results to Excel. - output_file = OUT_FILE + output_file = filename with pd.ExcelWriter(output_file, engine='openpyxl') as writer: alpha_list = [] for (gene, psite), kinases in alpha_values.items(): diff --git a/networkmodel/runner.py b/networkmodel/runner.py index 07d3077..40ac6e2 100644 --- a/networkmodel/runner.py +++ b/networkmodel/runner.py @@ -26,6 +26,7 @@ import json import logging import pickle +import sys import multiprocessing as mp import numpy as np @@ -69,6 +70,10 @@ from networkmodel.PosteriorObjective import write_posterior_payload from networkmodel.mode_outputs import write_scalar_result_tables from common.frechet import frechet_distance +from common.results import ( + attach_file_console_logger, ensure_result_dir, populate_standard_subdirs, + write_command, write_metadata, write_resolved_config, +) from config_loader import load_config_toml from config.config import setup_logger @@ -98,6 +103,7 @@ def main(): ValueError: When inputs are inconsistent or unsupported. """ parser = argparse.ArgumentParser() + parser.add_argument("--conf", default=None, help="Compatibility option; networkmodel settings are loaded before argument parsing.") parser.add_argument("--kinase-net", default=KINASE_NET_FILE) parser.add_argument("--tf-net", default=TF_NET_FILE) parser.add_argument("--ms", default=MS_DATA_FILE) @@ -108,7 +114,7 @@ def main(): parser.add_argument("--kinopt", default=KINOPT_RESULTS_FILE) parser.add_argument("--tfopt", default=TFOPT_RESULTS_FILE) - parser.add_argument("--output-dir", default=RESULTS_DIR) + parser.add_argument("--output-dir", "--outdir", dest="output_dir", default=RESULTS_DIR) parser.add_argument("--cores", type=int, default=CORES) # JAXopt @@ -135,7 +141,16 @@ def main(): help="Choice of optimization solver. Legacy pymoo/optuna values map to jaxopt.") args = parser.parse_args() - os.makedirs(args.output_dir, exist_ok=True) + args.output_dir = str(ensure_result_dir(args.output_dir)["root"]) + attach_file_console_logger(logger, args.output_dir) + write_command(args.output_dir) + write_resolved_config(args.output_dir, vars(args)) + write_metadata( + args.output_dir, + workflow="networkmodel.runner", + args=args, + inputs=[args.kinase_net, args.tf_net, args.ms, args.rna, args.phospho, args.kinopt, args.tfopt], + ) # logger.info Arguments logger.info("============================================================") @@ -1120,6 +1135,7 @@ def _proxy_score(orphan: str, candidate: str) -> float: logger.info(f"[Dashboard] Saved dashboard bundle: {bundle_path}") # Finalize logging + populate_standard_subdirs(args.output_dir) logger.info(f"[Complete] All results saved to: {args.output_dir}") diff --git a/protwise/runner/main.py b/protwise/runner/main.py index cc94c0b..aefdde5 100644 --- a/protwise/runner/main.py +++ b/protwise/runner/main.py @@ -18,6 +18,10 @@ from protwise.paramest.core import process_gene_wrapper from protwise.plotting import Plotter from common.utils import latexit +from common.results import ( + attach_file_console_logger, ensure_result_dir, populate_standard_subdirs, + write_command, write_metadata, write_resolved_config, +) from common.utils.display import ensure_output_directory, save_result, organize_output_files, create_report, merge_obs_est logger = setup_logger() @@ -36,6 +40,10 @@ exit(1) config = extract_config(args) +if getattr(args, "outdir", None): + OUT_DIR = ensure_result_dir(args.outdir)["root"] + OUT_RESULTS_DIR = OUT_DIR / OUT_RESULTS_DIR.name + # Check if the configuration is valid if not config: logger.error("Invalid configuration. Exiting.") @@ -62,6 +70,17 @@ def main(): Returns: None """ + ensure_result_dir(OUT_DIR) + attach_file_console_logger(logger, OUT_DIR) + write_command(OUT_DIR) + write_resolved_config(OUT_DIR, config) + write_metadata( + OUT_DIR, + workflow="protwise.runner", + args=args, + inputs=[config.get("input_excel_protein"), config.get("input_excel_psite"), config.get("input_excel_rna")], + ) + # Set up the logger logger.info(" --------------------------------") logger.info(f"{model_type} Phosphorylation Modelling Configuration") diff --git a/tests/test_result_contract.py b/tests/test_result_contract.py new file mode 100644 index 0000000..711edad --- /dev/null +++ b/tests/test_result_contract.py @@ -0,0 +1,77 @@ +from __future__ import annotations + +import json +from pathlib import Path + +from common.results import ( + STANDARD_SUBDIRS, + ensure_result_dir, + populate_standard_subdirs, + write_command, + write_metadata, + write_resolved_config, +) + + +def test_result_contract_helpers_write_provenance(tmp_path): + input_file = tmp_path / "input.csv" + input_file.write_text("a,b\n1,2\n", encoding="utf-8") + outdir = tmp_path / "run" + + paths = ensure_result_dir(outdir) + write_command(outdir, ["python", "-m", "kinopt.local", "--outdir", str(outdir)]) + write_resolved_config(outdir, {"alpha": 1, "nested": {"beta": True}}) + write_metadata(outdir, "unit.workflow", args={"outdir": outdir}, inputs=[input_file]) + + for name in STANDARD_SUBDIRS: + assert paths[name].is_dir() + assert (outdir / "command.txt").read_text(encoding="utf-8").startswith("python -m kinopt.local") + assert (outdir / "config_resolved.yaml").is_file() + + metadata = json.loads((outdir / "metadata.json").read_text(encoding="utf-8")) + assert metadata["workflow"] == "unit.workflow" + assert metadata["output_directory"] == str(outdir.resolve()) + assert metadata["python_version"] + assert metadata["inputs"][0]["sha256"] + + +def test_populate_standard_subdirs_copies_legacy_outputs(tmp_path): + outdir = tmp_path / "run" + ensure_result_dir(outdir) + (outdir / "summary.csv").write_text("x\n1\n", encoding="utf-8") + (outdir / "plot.png").write_bytes(b"png") + (outdir / "report.html").write_text("", encoding="utf-8") + (outdir / "state.pkl").write_bytes(b"pickle") + + populate_standard_subdirs(outdir) + + assert (outdir / "tables" / "summary.csv").is_file() + assert (outdir / "plots" / "plot.png").is_file() + assert (outdir / "reports" / "report.html").is_file() + assert (outdir / "artifacts" / "state.pkl").is_file() + # Backward-compatible top-level names are retained. + assert (outdir / "summary.csv").is_file() + + +def test_local_workflows_do_not_copy_outputs_to_data_ode(): + kinopt_main = Path("kinopt/local/__main__.py").read_text(encoding="utf-8") + tfopt_main = Path("tfopt/local/__main__.py").read_text(encoding="utf-8") + + assert "ODE_DATA_DIR" not in kinopt_main + assert "ODE_DATA_DIR" not in tfopt_main + assert "shutil.copy" not in kinopt_main + assert "shutil.copy" not in tfopt_main + + +def test_major_cli_parsers_expose_outdir_flags(): + parser_files = [ + Path("kinopt/local/config/constants.py"), + Path("tfopt/local/config/constants.py"), + Path("config/config.py"), + Path("networkmodel/runner.py"), + Path("config/cli.py"), + ] + for path in parser_files: + text = path.read_text(encoding="utf-8") + assert "--outdir" in text, path + assert "--output-dir" in text, path diff --git a/tfopt/local/__main__.py b/tfopt/local/__main__.py index 68c2cfd..bda7236 100644 --- a/tfopt/local/__main__.py +++ b/tfopt/local/__main__.py @@ -1,7 +1,5 @@ -import shutil - from config.helpers import location -from tfopt.local.config.constants import parse_args, OUT_DIR, OUT_FILE, ODE_DATA_DIR +from tfopt.local.config.constants import parse_args, OUT_FILE, INPUT1, INPUT3, INPUT4, _CFG from tfopt.local.config.logconf import setup_logger from tfopt.local.utils.iodata import organize_output_files, create_report from tfopt.local.exporter.plotout import plot_estimated_vs_observed, plot_multistart_summary_runtime_overlay @@ -13,6 +11,10 @@ from tfopt.local.utils.params import get_optimization_parameters, postprocess_results from tfopt.fitanalysis.helper import Plotter from common.utils import latexit +from common.results import ( + attach_file_console_logger, ensure_result_dir, populate_standard_subdirs, + write_command, write_metadata, write_resolved_config, +) logger = setup_logger() @@ -24,7 +26,19 @@ def main(): logger.info("[Local Optimization] mRNA-TF Optimization Problem Started") # STEP 0: Parse command line arguments. - lb, ub, loss_type = parse_args() + lb, ub, loss_type, out_dir = parse_args() + result_dirs = ensure_result_dir(out_dir) + out_dir = result_dirs["root"] + out_file = out_dir / OUT_FILE.name + attach_file_console_logger(logger, out_dir) + write_command(out_dir) + write_resolved_config(out_dir, _CFG) + write_metadata( + out_dir, + workflow="tfopt.local", + args={"lower_bound": lb, "upper_bound": ub, "loss_type": loss_type}, + inputs=[INPUT1, INPUT3, INPUT4], + ) # STEP 1: Load and filter the data. gene_ids, expr_matrix, expr_time_cols, tf_ids, tf_protein, tf_psite_data, tf_psite_labels, tf_time_cols, reg_map = \ @@ -78,18 +92,18 @@ def main(): f"cv={_get_constraint_violation(result)} start_id={getattr(result, 'start_id', None)}") # Save multistart results to CSV. - export_multistart_results(all_results).to_csv(OUT_DIR / "multistart_summary.csv", index=False) + export_multistart_results(all_results).to_csv(out_dir / "multistart_summary.csv", index=False) # Save multistart solutions to NPZ. save_multistart_solutions_npz( all_results, - OUT_DIR / "multistart_params.npz", + out_dir / "multistart_params.npz", ) # Save waterfall plot. plot_multistart_summary_runtime_overlay( - OUT_DIR / "multistart_summary.csv", - out_path=OUT_DIR / "multistart_fun_vs_rank_runtime.png", + out_dir / "multistart_summary.csv", + out_path=out_dir / "multistart_fun_vs_rank_runtime.png", figsize=(8, 8), ) @@ -104,14 +118,14 @@ def main(): predictions = compute_predictions(final_x, regulators, tf_protein_matrix, psite_tensor, n_reg, T_use, n_genes, beta_start_indices, num_psites) plot_estimated_vs_observed(predictions, expression_matrix, gene_ids, expr_time_cols, regulators, - tf_protein_matrix, tf_ids, num_targets=n_genes) + tf_protein_matrix, tf_ids, num_targets=n_genes, save_path=out_dir) # Save results to Excel. save_results_to_excel(gene_ids, tf_ids, final_alpha, final_beta, psite_labels_arr, expression_matrix, - predictions, result.fun, reg_map) + predictions, result.fun, reg_map, filename=out_file) # Generate plots. - plotter = Plotter(OUT_FILE, OUT_DIR) + plotter = Plotter(out_file, out_dir) plotter.plot_alpha_distribution() plotter.plot_beta_barplots() plotter.plot_heatmap_abs_residuals() @@ -124,22 +138,22 @@ def main(): plotter.plot_cdf_beta() plotter.plot_time_wise_residuals() - # Copy output file to the ODE_DATA_DIR. - shutil.copy(OUT_FILE, ODE_DATA_DIR / OUT_FILE.name) # LateX the results - latexit.main(OUT_DIR) + latexit.main(out_dir) # Organize output files and create a report. - organize_output_files(OUT_DIR) - create_report(OUT_DIR) + organize_output_files(out_dir) + create_report(out_dir) - logger.info(f'[Local] Report & Results {location(str(OUT_DIR))}') + logger.info(f'[Local] Report & Results {location(str(out_dir))}') # Click to open the report in a web browser. - for fpath in [OUT_DIR / 'report.html']: + for fpath in [out_dir / 'report.html']: logger.info(f"{fpath.as_uri()}") + populate_standard_subdirs(out_dir) + if __name__ == "__main__": main() diff --git a/tfopt/local/config/constants.py b/tfopt/local/config/constants.py index 930da68..31de08a 100644 --- a/tfopt/local/config/constants.py +++ b/tfopt/local/config/constants.py @@ -46,6 +46,7 @@ def parse_args(): parser = argparse.ArgumentParser( description="PhosKinTime - SLSQP mRNA-TF Optimization Problem." ) + parser.add_argument("--conf", default=None, help="Compatibility option; configuration is loaded before argument parsing.") parser.add_argument("--lower_bound", type=float, default=float(_CFG.get("lower_bound", -4.0))) parser.add_argument("--upper_bound", type=float, default=float(_CFG.get("upper_bound", 4.0))) parser.add_argument( @@ -55,6 +56,13 @@ def parse_args(): default=int(_CFG.get("loss_type", 5)), help="0:MSE 1:MAE 2:softl1 3:cauchy 4:arctan 5:elastic-net 6:tikhonov", ) + parser.add_argument( + "--outdir", "--output-dir", + dest="outdir", + type=Path, + default=OUT_DIR, + help="Directory where all run outputs and provenance files are written.", + ) args = parser.parse_args() - return args.lower_bound, args.upper_bound, args.loss_type + return args.lower_bound, args.upper_bound, args.loss_type, args.outdir From e08ad03c84a760caf9993c2af183a7bacdd5ca61 Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Wed, 10 Jun 2026 18:11:06 +0530 Subject: [PATCH 04/42] Add dashboard result browser --- common/__init__.py | 13 +-- dashboard/__init__.py | 1 + dashboard/app.py | 47 +++++++++ dashboard/components/__init__.py | 1 + dashboard/components/download_panel.py | 19 ++++ dashboard/components/log_viewer.py | 30 ++++++ dashboard/components/metadata_viewer.py | 24 +++++ dashboard/components/plot_viewer.py | 23 +++++ dashboard/components/report_viewer.py | 37 ++++++++ dashboard/components/result_browser.py | 70 ++++++++++++++ dashboard/components/table_viewer.py | 38 ++++++++ dashboard/file_utils.py | 109 +++++++++++++++++++++ dashboard/registry.py | 48 ++++++++++ dashboard/result_parser.py | 121 ++++++++++++++++++++++++ docs/dashboard_build_plan.md | 4 + pixi.toml | 2 + tests/dashboard/test_file_utils.py | 49 ++++++++++ tests/dashboard/test_registry.py | 33 +++++++ tests/dashboard/test_result_parser.py | 75 +++++++++++++++ 19 files changed, 738 insertions(+), 6 deletions(-) create mode 100644 dashboard/__init__.py create mode 100644 dashboard/app.py create mode 100644 dashboard/components/__init__.py create mode 100644 dashboard/components/download_panel.py create mode 100644 dashboard/components/log_viewer.py create mode 100644 dashboard/components/metadata_viewer.py create mode 100644 dashboard/components/plot_viewer.py create mode 100644 dashboard/components/report_viewer.py create mode 100644 dashboard/components/result_browser.py create mode 100644 dashboard/components/table_viewer.py create mode 100644 dashboard/file_utils.py create mode 100644 dashboard/registry.py create mode 100644 dashboard/result_parser.py create mode 100644 tests/dashboard/test_file_utils.py create mode 100644 tests/dashboard/test_registry.py create mode 100644 tests/dashboard/test_result_parser.py diff --git a/common/__init__.py b/common/__init__.py index 99f847d..33a10dc 100644 --- a/common/__init__.py +++ b/common/__init__.py @@ -1,7 +1,8 @@ +"""Shared PhosKinTime utilities.""" + + def format_duration(seconds): - """Format a duration in seconds into a human-readable string.""" - if seconds < 60: - return f"{seconds:.2f} sec" - if seconds < 3600: - return f"{seconds / 60:.2f} min" - return f"{seconds / 3600:.2f} hr" + """Format a duration in seconds without importing heavy common utilities at package import time.""" + from common.utils.display import format_duration as _format_duration + + return _format_duration(seconds) diff --git a/dashboard/__init__.py b/dashboard/__init__.py new file mode 100644 index 0000000..d8ce9db --- /dev/null +++ b/dashboard/__init__.py @@ -0,0 +1 @@ +"""Dashboard result-browser package for PhosKinTime.""" diff --git a/dashboard/app.py b/dashboard/app.py new file mode 100644 index 0000000..aeb6b72 --- /dev/null +++ b/dashboard/app.py @@ -0,0 +1,47 @@ +from __future__ import annotations + +from pathlib import Path + +import streamlit as st + +from dashboard.components.result_browser import render_result_browser +from dashboard.result_parser import discover_result_directory + + +def _candidate_result_dirs(base: Path) -> list[Path]: + if not base.is_dir(): + return [] + candidates = [base] + candidates.extend(path for path in sorted(base.iterdir()) if path.is_dir()) + return candidates + + +def main() -> None: + st.set_page_config(page_title="PhosKinTime Result Browser", layout="wide") + st.title("PhosKinTime Result Browser") + st.write("Browse existing PhosKinTime result directories without launching workflows or uploading files.") + + with st.sidebar: + st.header("Result directory") + base = Path(st.text_input("Base results folder", value="results")).expanduser() + candidates = _candidate_result_dirs(base) + if candidates: + choice = st.selectbox("Select folder", candidates, format_func=lambda path: str(path)) + directory_text = st.text_input("Selected result directory", value=str(choice)) + else: + st.info("No selectable folders found under the base path. Enter a result directory manually.") + directory_text = st.text_input("Selected result directory", value=str(base)) + + try: + inventory = discover_result_directory(directory_text) + except (FileNotFoundError, NotADirectoryError) as exc: + st.error(str(exc)) + return + + if not inventory.has_content: + st.warning("This directory exists, but no standard PhosKinTime result files were discovered.") + render_result_browser(inventory) + + +if __name__ == "__main__": + main() diff --git a/dashboard/components/__init__.py b/dashboard/components/__init__.py new file mode 100644 index 0000000..a23e77a --- /dev/null +++ b/dashboard/components/__init__.py @@ -0,0 +1 @@ +"""Streamlit components for the PhosKinTime result browser.""" diff --git a/dashboard/components/download_panel.py b/dashboard/components/download_panel.py new file mode 100644 index 0000000..916fff1 --- /dev/null +++ b/dashboard/components/download_panel.py @@ -0,0 +1,19 @@ +from __future__ import annotations + +import streamlit as st + +from dashboard.file_utils import create_result_zip +from dashboard.result_parser import ResultInventory + + +def render_download_panel(inventory: ResultInventory) -> None: + st.subheader("Download") + st.caption("Create a ZIP archive of the selected result directory. The archive is generated in memory and not written to disk.") + if st.button("Prepare ZIP archive"): + zip_bytes = create_result_zip(inventory.root) + st.download_button( + "Download result ZIP", + data=zip_bytes, + file_name=f"{inventory.root.name or 'phoskintime_results'}.zip", + mime="application/zip", + ) diff --git a/dashboard/components/log_viewer.py b/dashboard/components/log_viewer.py new file mode 100644 index 0000000..dc6f78b --- /dev/null +++ b/dashboard/components/log_viewer.py @@ -0,0 +1,30 @@ +from __future__ import annotations + +from pathlib import Path + +import streamlit as st + +from dashboard.file_utils import DisplayFile, read_text_preview + + +def render_text_file(label: str, path: Path | None, language: str | None = None) -> None: + st.subheader(label) + if path is None: + st.info(f"No {label} file was found in this result directory.") + return + text, truncated = read_text_preview(path) + st.code(text, language=language) + if truncated: + st.caption("Preview truncated for display; download the file to inspect all content.") + + +def render_logs(logs: list[DisplayFile]) -> None: + st.subheader("Logs") + if not logs: + st.info("No log files were found under logs/ or console.log.") + return + selected = st.selectbox("Log file", logs, format_func=lambda item: item.relative_path) + text, truncated = read_text_preview(selected.path) + st.text_area(selected.relative_path, text, height=420) + if truncated: + st.caption("Preview truncated for display; download the file to inspect all content.") diff --git a/dashboard/components/metadata_viewer.py b/dashboard/components/metadata_viewer.py new file mode 100644 index 0000000..c211860 --- /dev/null +++ b/dashboard/components/metadata_viewer.py @@ -0,0 +1,24 @@ +from __future__ import annotations + +import json +from pathlib import Path + +import streamlit as st + +from dashboard.file_utils import read_text_preview + + +def render_metadata(path: Path | None) -> None: + """Render metadata.json with a clear missing-state message.""" + st.subheader("Metadata") + if path is None: + st.info("No metadata.json file was found in this result directory.") + return + try: + st.json(json.loads(path.read_text(encoding="utf-8"))) + except json.JSONDecodeError: + text, truncated = read_text_preview(path) + st.warning("metadata.json is not valid JSON; showing raw content instead.") + st.code(text, language="json") + if truncated: + st.caption("Preview truncated for display.") diff --git a/dashboard/components/plot_viewer.py b/dashboard/components/plot_viewer.py new file mode 100644 index 0000000..8139e76 --- /dev/null +++ b/dashboard/components/plot_viewer.py @@ -0,0 +1,23 @@ +from __future__ import annotations + +import streamlit as st +import streamlit.components.v1 as components + +from dashboard.file_utils import DisplayFile, human_size, read_text_preview + + +def render_plots(plots: list[DisplayFile]) -> None: + st.subheader("Plots") + if not plots: + st.info("No PNG, JPG, JPEG, SVG, or HTML plots were found in plots/ or recognised legacy plot folders.") + return + selected = st.selectbox("Plot", plots, format_func=lambda item: f"{item.relative_path} ({human_size(item.size_bytes)})") + if selected.suffix in {".png", ".jpg", ".jpeg", ".svg"}: + st.image(str(selected.path), caption=selected.relative_path, use_container_width=True) + elif selected.suffix in {".html", ".htm"}: + html, truncated = read_text_preview(selected.path, max_bytes=2_000_000) + components.html(html, height=700, scrolling=True) + if truncated: + st.warning("HTML preview was truncated because the file is large. Download the file for the full plot.") + else: + st.info("This plot type can be downloaded but is not previewed inline.") diff --git a/dashboard/components/report_viewer.py b/dashboard/components/report_viewer.py new file mode 100644 index 0000000..995fc36 --- /dev/null +++ b/dashboard/components/report_viewer.py @@ -0,0 +1,37 @@ +from __future__ import annotations + +import base64 + +import streamlit as st +import streamlit.components.v1 as components + +from dashboard.file_utils import DisplayFile, human_size, read_text_preview + + +def render_reports(reports: list[DisplayFile]) -> None: + """Render report files where Streamlit can preview them.""" + st.subheader("Reports") + if not reports: + st.info("No HTML, Markdown, or PDF reports were found in reports/.") + return + selected = st.selectbox("Report", reports, format_func=lambda item: f"{item.relative_path} ({human_size(item.size_bytes)})") + if selected.suffix in {".html", ".htm"}: + html, truncated = read_text_preview(selected.path, max_bytes=2_000_000) + components.html(html, height=700, scrolling=True) + if truncated: + st.warning("HTML report preview was truncated because the file is large. Download the file for the full report.") + elif selected.suffix == ".md": + markdown, truncated = read_text_preview(selected.path, max_bytes=1_000_000) + st.markdown(markdown) + if truncated: + st.warning("Markdown report preview was truncated because the file is large. Download the file for the full report.") + elif selected.suffix == ".pdf": + pdf_bytes = selected.path.read_bytes() + encoded = base64.b64encode(pdf_bytes).decode("ascii") + components.html( + f'', + height=720, + scrolling=True, + ) + with selected.path.open("rb") as handle: + st.download_button("Download report", data=handle.read(), file_name=selected.name) diff --git a/dashboard/components/result_browser.py b/dashboard/components/result_browser.py new file mode 100644 index 0000000..dd2ef78 --- /dev/null +++ b/dashboard/components/result_browser.py @@ -0,0 +1,70 @@ +from __future__ import annotations + +import streamlit as st + +from dashboard.components.download_panel import render_download_panel +from dashboard.components.log_viewer import render_logs, render_text_file +from dashboard.components.metadata_viewer import render_metadata +from dashboard.components.plot_viewer import render_plots +from dashboard.components.report_viewer import render_reports +from dashboard.components.table_viewer import render_tables +from dashboard.registry import infer_workflow +from dashboard.result_parser import ResultInventory + + +def _summary_metric(label: str, value: int) -> None: + st.metric(label, value) + + +def render_result_browser(inventory: ResultInventory) -> None: + """Render all discovered result-directory content.""" + workflow = infer_workflow(inventory) + st.header("Result browser") + st.caption(f"Directory: `{inventory.root}`") + st.info(f"Detected workflow: **{workflow.label}** — {workflow.description}") + + columns = st.columns(5) + with columns[0]: + _summary_metric("Tables", len(inventory.tables)) + with columns[1]: + _summary_metric("Plots", len(inventory.plots)) + with columns[2]: + _summary_metric("Logs", len(inventory.logs)) + with columns[3]: + _summary_metric("Reports", len(inventory.reports)) + with columns[4]: + _summary_metric("Artifacts", len(inventory.artifacts)) + + if inventory.missing_expected: + with st.expander("Missing standard contract files/folders", expanded=False): + st.write("The browser can still show recognised legacy outputs, but these standard items were not found:") + st.code("\n".join(inventory.missing_expected)) + + tabs = st.tabs(["Metadata", "Tables", "Plots", "Logs", "Reports", "Artifacts", "Download"]) + with tabs[0]: + render_metadata(inventory.metadata) + render_text_file("Command", inventory.command, language="bash") + render_text_file("Resolved config", inventory.config, language="yaml") + with tabs[1]: + render_tables(inventory.tables) + with tabs[2]: + render_plots(inventory.plots) + with tabs[3]: + render_logs(inventory.logs) + with tabs[4]: + render_reports(inventory.reports) + with tabs[5]: + _render_downloadable_list("Artifacts", inventory.artifacts) + with tabs[6]: + render_download_panel(inventory) + + +def _render_downloadable_list(label: str, files) -> None: + st.subheader(label) + if not files: + st.info(f"No {label.lower()} were found in the selected result directory.") + return + selected = st.selectbox(label, files, format_func=lambda item: item.relative_path) + st.write(f"Selected: `{selected.relative_path}`") + with selected.path.open("rb") as handle: + st.download_button("Download", data=handle.read(), file_name=selected.name, key=f"download-{label}-{selected.relative_path}") diff --git a/dashboard/components/table_viewer.py b/dashboard/components/table_viewer.py new file mode 100644 index 0000000..68cd2f8 --- /dev/null +++ b/dashboard/components/table_viewer.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +import pandas as pd +import streamlit as st + +from dashboard.file_utils import DisplayFile, human_size + + +@st.cache_data(show_spinner=False) +def _read_table(path: str, suffix: str, sheet_name: str | None = None) -> pd.DataFrame: + if suffix == ".csv": + return pd.read_csv(path) + if suffix == ".tsv": + return pd.read_csv(path, sep="\t") + if suffix in {".xlsx", ".xls"}: + return pd.read_excel(path, sheet_name=sheet_name or 0) + raise ValueError(f"Unsupported table suffix: {suffix}") + + +@st.cache_data(show_spinner=False) +def _excel_sheets(path: str) -> list[str]: + return pd.ExcelFile(path).sheet_names + + +def render_tables(tables: list[DisplayFile]) -> None: + st.subheader("Tables") + if not tables: + st.info("No CSV, TSV, or Excel tables were found in tables/ or recognised legacy locations.") + return + selected = st.selectbox("Table", tables, format_func=lambda item: f"{item.relative_path} ({human_size(item.size_bytes)})") + sheet_name = None + if selected.suffix in {".xlsx", ".xls"}: + sheets = _excel_sheets(str(selected.path)) + sheet_name = st.selectbox("Sheet", sheets) + try: + st.dataframe(_read_table(str(selected.path), selected.suffix, sheet_name), use_container_width=True) + except Exception as exc: + st.error(f"Could not load table {selected.relative_path}: {exc}") diff --git a/dashboard/file_utils.py b/dashboard/file_utils.py new file mode 100644 index 0000000..3ed3759 --- /dev/null +++ b/dashboard/file_utils.py @@ -0,0 +1,109 @@ +from __future__ import annotations + +from dataclasses import dataclass +from io import BytesIO +from pathlib import Path +from typing import Iterable +from zipfile import ZIP_DEFLATED, ZipFile + +TABLE_EXTENSIONS = {".csv", ".tsv", ".xlsx", ".xls"} +IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".svg"} +HTML_EXTENSIONS = {".html", ".htm"} +PLOT_EXTENSIONS = IMAGE_EXTENSIONS | HTML_EXTENSIONS +REPORT_EXTENSIONS = HTML_EXTENSIONS | {".md", ".pdf"} +TEXT_EXTENSIONS = {".txt", ".log", ".yaml", ".yml", ".json", ".md", ".csv", ".tsv"} + +EXCLUDED_ZIP_PARTS = {"__pycache__", ".pytest_cache", ".mypy_cache", ".ruff_cache", ".git"} + + +@dataclass(frozen=True) +class DisplayFile: + """A discovered result file with paths suitable for UI labels and reading.""" + + path: Path + root: Path + category: str + + @property + def name(self) -> str: + return self.path.name + + @property + def relative_path(self) -> str: + try: + return self.path.relative_to(self.root).as_posix() + except ValueError: + return self.path.as_posix() + + @property + def suffix(self) -> str: + return self.path.suffix.lower() + + @property + def size_bytes(self) -> int: + try: + return self.path.stat().st_size + except OSError: + return 0 + + +def resolve_directory(path: str | Path) -> Path: + """Resolve an existing result directory path.""" + directory = Path(path).expanduser().resolve() + if not directory.exists(): + raise FileNotFoundError(f"Result directory does not exist: {directory}") + if not directory.is_dir(): + raise NotADirectoryError(f"Result path is not a directory: {directory}") + return directory + + +def iter_files(directory: Path, patterns: Iterable[str] = ("*",), recursive: bool = False) -> list[Path]: + """Return sorted files matching one or more glob patterns without reading file contents.""" + if not directory.is_dir(): + return [] + matches: set[Path] = set() + for pattern in patterns: + iterator = directory.rglob(pattern) if recursive else directory.glob(pattern) + matches.update(path for path in iterator if path.is_file()) + return sorted(matches, key=lambda path: path.as_posix().lower()) + + +def filter_by_suffix(paths: Iterable[Path], suffixes: set[str]) -> list[Path]: + """Filter paths by lower-case suffix and sort deterministically.""" + return sorted((p for p in paths if p.suffix.lower() in suffixes), key=lambda path: path.as_posix().lower()) + + +def read_text_preview(path: Path, max_bytes: int = 512_000) -> tuple[str, bool]: + """Read a bounded text preview and return whether truncation occurred.""" + size = path.stat().st_size + with path.open("rb") as handle: + raw = handle.read(max_bytes + 1) + truncated = len(raw) > max_bytes or size > max_bytes + if truncated: + raw = raw[:max_bytes] + return raw.decode("utf-8", errors="replace"), truncated + + +def create_result_zip(root: str | Path) -> bytes: + """Create an in-memory ZIP archive for a result directory.""" + directory = resolve_directory(root) + buffer = BytesIO() + with ZipFile(buffer, mode="w", compression=ZIP_DEFLATED) as archive: + for path in sorted(directory.rglob("*"), key=lambda p: p.as_posix().lower()): + if not path.is_file(): + continue + rel = path.relative_to(directory) + if any(part in EXCLUDED_ZIP_PARTS for part in rel.parts): + continue + archive.write(path, rel.as_posix()) + return buffer.getvalue() + + +def human_size(num_bytes: int) -> str: + """Format a byte count for display.""" + value = float(num_bytes) + for unit in ("B", "KB", "MB", "GB"): + if value < 1024 or unit == "GB": + return f"{value:.1f} {unit}" if unit != "B" else f"{int(value)} B" + value /= 1024 + return f"{num_bytes} B" diff --git a/dashboard/registry.py b/dashboard/registry.py new file mode 100644 index 0000000..40f469b --- /dev/null +++ b/dashboard/registry.py @@ -0,0 +1,48 @@ +from __future__ import annotations + +import json +from dataclasses import dataclass + +from dashboard.result_parser import ResultInventory + + +@dataclass(frozen=True) +class WorkflowDescriptor: + key: str + label: str + description: str + + +WORKFLOWS: dict[str, WorkflowDescriptor] = { + "kinopt.local": WorkflowDescriptor("kinopt.local", "KinOpt local", "Local kinase-phosphorylation optimisation results."), + "tfopt.local": WorkflowDescriptor("tfopt.local", "TFOpt local", "Local transcription-factor optimisation results."), + "protwise.runner": WorkflowDescriptor("protwise.runner", "ProtWise", "ProtWise ODE modelling results."), + "networkmodel.runner": WorkflowDescriptor("networkmodel.runner", "Network model", "Integrated global network model results."), + "unknown": WorkflowDescriptor("unknown", "Unknown workflow", "Result directory without recognised workflow metadata."), +} + + +def infer_workflow(inventory: ResultInventory) -> WorkflowDescriptor: + """Infer workflow identity from metadata first, then legacy filenames.""" + if inventory.metadata is not None: + try: + metadata = json.loads(inventory.metadata.read_text(encoding="utf-8")) + workflow = str(metadata.get("workflow", "")).strip() + if workflow in WORKFLOWS: + return WORKFLOWS[workflow] + except (OSError, json.JSONDecodeError): + pass + + names = {item.name for item in inventory.tables} + if "kinopt_results.xlsx" in names: + return WORKFLOWS["kinopt.local"] + if "tfopt_results.xlsx" in names: + return WORKFLOWS["tfopt.local"] + if {"scalar_objective.csv", "pred_prot_picked.csv", "pred_rna_picked.csv", "pred_phospho_picked.csv"} & names: + return WORKFLOWS["networkmodel.runner"] + return WORKFLOWS["unknown"] + + +def registered_workflows() -> list[WorkflowDescriptor]: + """Return known workflow descriptors for display or tests.""" + return [WORKFLOWS[key] for key in sorted(WORKFLOWS)] diff --git a/dashboard/result_parser.py b/dashboard/result_parser.py new file mode 100644 index 0000000..f91525f --- /dev/null +++ b/dashboard/result_parser.py @@ -0,0 +1,121 @@ +from __future__ import annotations + +from dataclasses import dataclass, field +from pathlib import Path + +from dashboard.file_utils import ( + DisplayFile, + PLOT_EXTENSIONS, + REPORT_EXTENSIONS, + TABLE_EXTENSIONS, + filter_by_suffix, + iter_files, + resolve_directory, +) + +LEGACY_TABLE_NAMES = { + "scalar_objective.csv", + "convergence_history.csv", + "pred_prot_picked.csv", + "pred_rna_picked.csv", + "pred_phospho_picked.csv", + "kinopt_results.xlsx", + "tfopt_results.xlsx", +} +LEGACY_ANALYSIS_DIRS = ("optimization", "profiles", "posterior", "plots") +PROVENANCE_FILES = ("metadata.json", "command.txt", "console.log", "config_resolved.yaml") + + +@dataclass(frozen=True) +class ResultInventory: + """Lazy inventory of files in a PhosKinTime result directory.""" + + root: Path + metadata: Path | None = None + command: Path | None = None + console_log: Path | None = None + config: Path | None = None + tables: list[DisplayFile] = field(default_factory=list) + plots: list[DisplayFile] = field(default_factory=list) + logs: list[DisplayFile] = field(default_factory=list) + reports: list[DisplayFile] = field(default_factory=list) + artifacts: list[DisplayFile] = field(default_factory=list) + missing_expected: list[str] = field(default_factory=list) + + @property + def has_content(self) -> bool: + return any((self.metadata, self.command, self.console_log, self.config, self.tables, self.plots, self.logs, self.reports, self.artifacts)) + + +def _display_files(root: Path, paths: list[Path], category: str) -> list[DisplayFile]: + seen: set[Path] = set() + files: list[DisplayFile] = [] + for path in paths: + resolved = path.resolve() + if resolved in seen: + continue + seen.add(resolved) + files.append(DisplayFile(path=path, root=root, category=category)) + return files + + +def _top_level_legacy_tables(root: Path) -> list[Path]: + return sorted((root / name for name in LEGACY_TABLE_NAMES if (root / name).is_file()), key=lambda p: p.name.lower()) + + +def _legacy_dir_files(root: Path, suffixes: set[str]) -> list[Path]: + files: list[Path] = [] + for dirname in LEGACY_ANALYSIS_DIRS: + files.extend(filter_by_suffix(iter_files(root / dirname, recursive=True), suffixes)) + return files + + +def discover_result_directory(path: str | Path) -> ResultInventory: + """Discover dashboard-readable files in a result directory without loading file contents.""" + root = resolve_directory(path) + + metadata = root / "metadata.json" if (root / "metadata.json").is_file() else None + command = root / "command.txt" if (root / "command.txt").is_file() else None + console_log = root / "console.log" if (root / "console.log").is_file() else None + config = root / "config_resolved.yaml" if (root / "config_resolved.yaml").is_file() else None + + table_paths = filter_by_suffix(iter_files(root / "tables"), TABLE_EXTENSIONS) + table_paths.extend(_top_level_legacy_tables(root)) + table_paths.extend(_legacy_dir_files(root, TABLE_EXTENSIONS)) + + plot_paths = filter_by_suffix(iter_files(root / "plots"), PLOT_EXTENSIONS) + plot_paths.extend(_legacy_dir_files(root, PLOT_EXTENSIONS)) + plot_paths.extend(filter_by_suffix([p for p in root.iterdir() if p.is_file()], PLOT_EXTENSIONS)) + + log_paths = iter_files(root / "logs") + if console_log is not None: + log_paths.insert(0, console_log) + + report_paths = filter_by_suffix(iter_files(root / "reports"), REPORT_EXTENSIONS) + report_paths.extend( + filter_by_suffix( + [p for p in root.iterdir() if p.is_file() and p.stem.lower() == "report"], + REPORT_EXTENSIONS, + ) + ) + + artifact_paths = iter_files(root / "artifacts") + + missing = [name for name in PROVENANCE_FILES if not (root / name).is_file()] + for dirname in ("tables", "plots", "logs", "reports", "artifacts"): + if not (root / dirname).is_dir(): + missing.append(f"{dirname}/") + + return ResultInventory( + root=root, + metadata=metadata, + command=command, + console_log=console_log, + config=config, + tables=_display_files(root, table_paths, "table"), + plots=_display_files(root, plot_paths, "plot"), + logs=_display_files(root, log_paths, "log"), + reports=_display_files(root, report_paths, "report"), + artifacts=_display_files(root, artifact_paths, "artifact"), + missing_expected=missing, + ) diff --git a/docs/dashboard_build_plan.md b/docs/dashboard_build_plan.md index 55d2641..c98d0d9 100644 --- a/docs/dashboard_build_plan.md +++ b/docs/dashboard_build_plan.md @@ -373,3 +373,7 @@ The PhosKinTime repository contains a rich suite of optimisation algorithms, ODE ### Phase 0 implementation note (June 2026) The backend output contract is implemented with shared result utilities in `common/results.py`. The local kinase, local TF, ProtWise runner, network model runner, and Typer workflow wrappers now accept `--outdir`/`--output-dir` and initialize the standard run subdirectories (`tables/`, `plots/`, `logs/`, `reports/`, `artifacts/`) plus provenance files (`metadata.json`, `command.txt`, `console.log`, and `config_resolved.yaml` when a resolved configuration is available). Legacy top-level output filenames are retained for compatibility, and dashboard-facing copies are mirrored into the standard subfolders. + +### Phase 1 implementation note (June 2026) + +The initial dashboard component lives under `dashboard/` and focuses only on browsing existing result directories. It discovers the Phase 0 output contract and selected legacy outputs, lazily loads tables/plots/logs/reports only after a user selects them, and provides an in-memory ZIP archive for downloading a result directory. Workflow launching and file uploads remain outside this phase. diff --git a/pixi.toml b/pixi.toml index d64811a..c9ff1e8 100644 --- a/pixi.toml +++ b/pixi.toml @@ -50,6 +50,7 @@ mygene = "*" tqdm = "*" python-dotenv = "*" typer = "*" +streamlit = "*" jinja2 = "*" tomli = "*" git-cliff = ">=2.13.1,<3" @@ -128,6 +129,7 @@ phoskintime = "PYTHONPATH=.:.. python -m phoskintime.config.cli" phoskintime-all = "PYTHONPATH=.:.. python -m phoskintime.config.cli all" network-dashboard = "PYTHONPATH=. python run_dashboard.py" +dashboard = "PYTHONPATH=. streamlit run dashboard/app.py" docs-serve = "zensical serve" docs-build = "zensical build" diff --git a/tests/dashboard/test_file_utils.py b/tests/dashboard/test_file_utils.py new file mode 100644 index 0000000..64d26f6 --- /dev/null +++ b/tests/dashboard/test_file_utils.py @@ -0,0 +1,49 @@ +from __future__ import annotations + +from zipfile import ZipFile +from io import BytesIO + +import pytest + +from dashboard.file_utils import create_result_zip, filter_by_suffix, human_size, read_text_preview, resolve_directory + + +def test_create_result_zip_archives_files_without_writing_zip(tmp_path): + root = tmp_path / "run" + (root / "tables").mkdir(parents=True) + (root / "tables" / "a.csv").write_text("x\n1\n", encoding="utf-8") + (root / "plots").mkdir() + (root / "plots" / "fit.png").write_bytes(b"png") + (root / "__pycache__").mkdir() + (root / "__pycache__" / "ignored.pyc").write_bytes(b"cache") + + archive_bytes = create_result_zip(root) + + with ZipFile(BytesIO(archive_bytes)) as archive: + assert sorted(archive.namelist()) == ["plots/fit.png", "tables/a.csv"] + assert not list(root.glob("*.zip")) + + +def test_read_text_preview_truncates(tmp_path): + path = tmp_path / "console.log" + path.write_text("abcdef", encoding="utf-8") + + text, truncated = read_text_preview(path, max_bytes=3) + + assert text == "abc" + assert truncated is True + + +def test_filter_by_suffix_and_human_size(tmp_path): + csv = tmp_path / "a.csv" + png = tmp_path / "b.png" + csv.write_text("x", encoding="utf-8") + png.write_bytes(b"p") + + assert filter_by_suffix([png, csv], {".csv"}) == [csv] + assert human_size(1024) == "1.0 KB" + + +def test_resolve_directory_rejects_missing_path(tmp_path): + with pytest.raises(FileNotFoundError): + resolve_directory(tmp_path / "missing") diff --git a/tests/dashboard/test_registry.py b/tests/dashboard/test_registry.py new file mode 100644 index 0000000..025ed18 --- /dev/null +++ b/tests/dashboard/test_registry.py @@ -0,0 +1,33 @@ +from __future__ import annotations + +import json + +from dashboard.registry import infer_workflow, registered_workflows +from dashboard.result_parser import discover_result_directory + + +def test_infer_workflow_from_metadata(tmp_path): + root = tmp_path / "run" + root.mkdir() + (root / "metadata.json").write_text(json.dumps({"workflow": "tfopt.local"}), encoding="utf-8") + + descriptor = infer_workflow(discover_result_directory(root)) + + assert descriptor.key == "tfopt.local" + assert descriptor.label == "TFOpt local" + + +def test_infer_workflow_from_legacy_networkmodel_tables(tmp_path): + root = tmp_path / "legacy" + root.mkdir() + (root / "scalar_objective.csv").write_text("x\n", encoding="utf-8") + + descriptor = infer_workflow(discover_result_directory(root)) + + assert descriptor.key == "networkmodel.runner" + + +def test_registered_workflows_contains_unknown_fallback(): + keys = {descriptor.key for descriptor in registered_workflows()} + + assert {"kinopt.local", "tfopt.local", "protwise.runner", "networkmodel.runner", "unknown"} <= keys diff --git a/tests/dashboard/test_result_parser.py b/tests/dashboard/test_result_parser.py new file mode 100644 index 0000000..7821eca --- /dev/null +++ b/tests/dashboard/test_result_parser.py @@ -0,0 +1,75 @@ +from __future__ import annotations + +import json + +from dashboard.result_parser import discover_result_directory + + +def test_discovers_standard_result_contract(tmp_path): + root = tmp_path / "run1" + for dirname in ("tables", "plots", "logs", "reports", "artifacts"): + (root / dirname).mkdir(parents=True, exist_ok=True) + (root / "metadata.json").write_text(json.dumps({"workflow": "networkmodel.runner"}), encoding="utf-8") + (root / "command.txt").write_text("python -m networkmodel.runner", encoding="utf-8") + (root / "console.log").write_text("done", encoding="utf-8") + (root / "config_resolved.yaml").write_text("x: 1\n", encoding="utf-8") + (root / "tables" / "summary.csv").write_text("a\n1\n", encoding="utf-8") + (root / "tables" / "summary.tsv").write_text("a\t b\n", encoding="utf-8") + (root / "tables" / "workbook.xlsx").write_bytes(b"placeholder") + (root / "plots" / "fit.png").write_bytes(b"png") + (root / "plots" / "interactive.html").write_text("", encoding="utf-8") + (root / "logs" / "worker.log").write_text("worker", encoding="utf-8") + (root / "reports" / "report.md").write_text("# Report", encoding="utf-8") + (root / "reports" / "report.pdf").write_bytes(b"pdf") + (root / "artifacts" / "state.pkl").write_bytes(b"pickle") + + inventory = discover_result_directory(root) + + assert inventory.metadata == root.resolve() / "metadata.json" + assert inventory.command == root.resolve() / "command.txt" + assert inventory.console_log == root.resolve() / "console.log" + assert inventory.config == root.resolve() / "config_resolved.yaml" + assert {item.relative_path for item in inventory.tables} == {"tables/summary.csv", "tables/summary.tsv", "tables/workbook.xlsx"} + assert {item.relative_path for item in inventory.plots} == {"plots/fit.png", "plots/interactive.html"} + assert {item.relative_path for item in inventory.logs} == {"console.log", "logs/worker.log"} + assert {item.relative_path for item in inventory.reports} == {"reports/report.md", "reports/report.pdf"} + assert {item.relative_path for item in inventory.artifacts} == {"artifacts/state.pkl"} + assert inventory.missing_expected == [] + + +def test_discovers_legacy_networkmodel_outputs(tmp_path): + root = tmp_path / "legacy" + root.mkdir() + for name in ("scalar_objective.csv", "convergence_history.csv", "pred_prot_picked.csv", "pred_rna_picked.csv", "pred_phospho_picked.csv"): + (root / name).write_text("value\n1\n", encoding="utf-8") + (root / "optimization").mkdir() + (root / "optimization" / "multistart_summary.csv").write_text("x\n", encoding="utf-8") + (root / "profiles").mkdir() + (root / "profiles" / "profile_likelihood_summary.csv").write_text("x\n", encoding="utf-8") + (root / "posterior").mkdir() + (root / "posterior" / "posterior_summary.csv").write_text("x\n", encoding="utf-8") + (root / "plots").mkdir() + (root / "plots" / "ranked_objective.png").write_bytes(b"png") + + inventory = discover_result_directory(root) + + table_names = {item.name for item in inventory.tables} + assert "scalar_objective.csv" in table_names + assert "convergence_history.csv" in table_names + assert "pred_prot_picked.csv" in table_names + assert "multistart_summary.csv" in table_names + assert "profile_likelihood_summary.csv" in table_names + assert "posterior_summary.csv" in table_names + assert {item.relative_path for item in inventory.plots} == {"plots/ranked_objective.png"} + assert "metadata.json" in inventory.missing_expected + + +def test_discovers_legacy_local_excel_outputs(tmp_path): + root = tmp_path / "legacy-local" + root.mkdir() + (root / "kinopt_results.xlsx").write_bytes(b"xlsx") + (root / "tfopt_results.xlsx").write_bytes(b"xlsx") + + inventory = discover_result_directory(root) + + assert {item.name for item in inventory.tables} == {"kinopt_results.xlsx", "tfopt_results.xlsx"} From 5af71a281832fd913c86d758831f16359f14c0a7 Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Wed, 10 Jun 2026 18:19:30 +0530 Subject: [PATCH 05/42] Add dashboard CLI launcher --- dashboard/app.py | 99 ++++++++++- dashboard/command_builder.py | 97 +++++++++++ dashboard/components/command_preview.py | 14 ++ dashboard/components/console_panel.py | 18 ++ dashboard/components/run_status.py | 17 ++ dashboard/components/workflow_selector.py | 35 ++++ dashboard/registry.py | 200 +++++++++++++++++++++- dashboard/runner.py | 126 ++++++++++++++ docs/dashboard_build_plan.md | 4 + tests/dashboard/test_command_builder.py | 61 +++++++ tests/dashboard/test_registry.py | 18 +- tests/dashboard/test_runner.py | 88 ++++++++++ 12 files changed, 756 insertions(+), 21 deletions(-) create mode 100644 dashboard/command_builder.py create mode 100644 dashboard/components/command_preview.py create mode 100644 dashboard/components/console_panel.py create mode 100644 dashboard/components/run_status.py create mode 100644 dashboard/components/workflow_selector.py create mode 100644 dashboard/runner.py create mode 100644 tests/dashboard/test_command_builder.py create mode 100644 tests/dashboard/test_runner.py diff --git a/dashboard/app.py b/dashboard/app.py index aeb6b72..ceb3375 100644 --- a/dashboard/app.py +++ b/dashboard/app.py @@ -4,8 +4,16 @@ import streamlit as st +from dashboard.command_builder import build_workflow_command +from dashboard.components.command_preview import render_command_preview +from dashboard.components.console_panel import render_cancellation_note, render_console from dashboard.components.result_browser import render_result_browser +from dashboard.components.run_status import render_run_status +from dashboard.components.workflow_selector import render_workflow_selector from dashboard.result_parser import discover_result_directory +from dashboard.runner import log_tail, run_built_command + +REPO_ROOT = Path(__file__).resolve().parents[1] def _candidate_result_dirs(base: Path) -> list[Path]: @@ -16,21 +24,21 @@ def _candidate_result_dirs(base: Path) -> list[Path]: return candidates -def main() -> None: - st.set_page_config(page_title="PhosKinTime Result Browser", layout="wide") - st.title("PhosKinTime Result Browser") - st.write("Browse existing PhosKinTime result directories without launching workflows or uploading files.") - +def _render_browser_panel(default_directory: Path | None = None) -> None: with st.sidebar: st.header("Result directory") - base = Path(st.text_input("Base results folder", value="results")).expanduser() + default_base = default_directory.parent if default_directory else Path("results") + base = Path(st.text_input("Base results folder", value=str(default_base), key="browser-base")).expanduser() candidates = _candidate_result_dirs(base) + if default_directory and default_directory.is_dir() and default_directory not in candidates: + candidates.insert(0, default_directory) if candidates: - choice = st.selectbox("Select folder", candidates, format_func=lambda path: str(path)) - directory_text = st.text_input("Selected result directory", value=str(choice)) + index = candidates.index(default_directory) if default_directory in candidates else 0 + choice = st.selectbox("Select folder", candidates, index=index, format_func=lambda path: str(path), key="browser-choice") + directory_text = st.text_input("Selected result directory", value=str(choice), key="browser-directory") else: st.info("No selectable folders found under the base path. Enter a result directory manually.") - directory_text = st.text_input("Selected result directory", value=str(base)) + directory_text = st.text_input("Selected result directory", value=str(base), key="browser-directory-manual") try: inventory = discover_result_directory(directory_text) @@ -43,5 +51,78 @@ def main() -> None: render_result_browser(inventory) +def _render_launcher_panel() -> None: + st.header("Workflow launcher") + st.write("Construct, preview, and run registered PhosKinTime workflows using existing CLI modules.") + render_cancellation_note() + + workflow, env, run_name, argument_values = render_workflow_selector(REPO_ROOT) + try: + built = build_workflow_command( + workflow.key, + repo_root=REPO_ROOT, + pixi_environment=env, + run_name=run_name, + argument_values=argument_values, + ) + except (KeyError, ValueError) as exc: + st.error(str(exc)) + return + + render_command_preview(built) + render_run_status(st.session_state.get("launcher_status"), st.session_state.get("launcher_returncode")) + + if st.button("Run workflow", type="primary"): + console_lines: list[str] = [] + console_placeholder = st.empty() + status_placeholder = st.empty() + st.session_state["launcher_status"] = "running" + st.session_state["launcher_returncode"] = None + with status_placeholder.container(): + render_run_status("running") + final_event = None + try: + for event in run_built_command(built, repo_root=REPO_ROOT): + final_event = event + if event.line: + console_lines.append(event.line) + with console_placeholder.container(): + render_console(console_lines) + except FileNotFoundError as exc: + st.session_state["launcher_status"] = "failure" + st.session_state["launcher_returncode"] = 127 + st.error(f"Could not start workflow command: {exc}") + return + + if final_event is not None: + st.session_state["launcher_status"] = final_event.status + st.session_state["launcher_returncode"] = final_event.returncode + st.session_state["last_run_dir"] = str(built.outdir) + with status_placeholder.container(): + render_run_status(final_event.status, final_event.returncode) + if final_event.status == "failure": + st.subheader("Log tail") + st.code(log_tail(built.outdir), language="text") + elif final_event.status == "success": + st.success("Run completed. The result directory is shown below.") + try: + render_result_browser(discover_result_directory(built.outdir)) + except (FileNotFoundError, NotADirectoryError) as exc: + st.warning(f"Run finished, but the result directory could not be opened: {exc}") + + +def main() -> None: + st.set_page_config(page_title="PhosKinTime Dashboard", layout="wide") + st.title("PhosKinTime Dashboard") + st.write("Browse existing result directories or launch registered CLI workflows without reimplementing scientific logic.") + + launcher_tab, browser_tab = st.tabs(["Run workflow", "Browse results"]) + with launcher_tab: + _render_launcher_panel() + with browser_tab: + last_run_dir = st.session_state.get("last_run_dir") + _render_browser_panel(Path(last_run_dir) if last_run_dir else None) + + if __name__ == "__main__": main() diff --git a/dashboard/command_builder.py b/dashboard/command_builder.py new file mode 100644 index 0000000..edc9288 --- /dev/null +++ b/dashboard/command_builder.py @@ -0,0 +1,97 @@ +from __future__ import annotations + +import re +import shlex +from dataclasses import dataclass +from pathlib import Path +from typing import Any + +from dashboard.registry import ArgumentSpec, WorkflowDescriptor, get_workflow + +_SAFE_RUN_CHARS = re.compile(r"[^A-Za-z0-9._-]+") + + +@dataclass(frozen=True) +class BuiltCommand: + """A safely constructed workflow command.""" + + workflow: WorkflowDescriptor + command: list[str] + outdir: Path + pixi_environment: str + + @property + def preview(self) -> str: + return " ".join(shlex.quote(str(part)) for part in self.command) + + +def sanitize_run_name(name: str) -> str: + """Return a filesystem-safe run name from dashboard input.""" + cleaned = _SAFE_RUN_CHARS.sub("-", name.strip()).strip(".-_") + return cleaned or "run" + + +def build_output_dir(repo_root: str | Path, workflow_key: str, run_name: str, output_base: str | Path = "results") -> Path: + """Build a project-local output directory for a workflow run.""" + root = Path(repo_root).resolve() + base = Path(output_base).expanduser() + if not base.is_absolute(): + base = root / base + safe_name = sanitize_run_name(run_name) + return (base / workflow_key / safe_name).resolve() + + +def _coerce_argument(spec: ArgumentSpec, value: Any) -> list[str]: + if value is None or value == "": + if spec.required: + raise ValueError(f"Missing required argument: {spec.name}") + return [] + if spec.kind == "bool": + return [spec.flag] if bool(value) else [] + if spec.kind == "int": + return [spec.flag, str(int(value))] + if spec.kind == "float": + return [spec.flag, str(float(value))] + return [spec.flag, str(value)] + + +def workflow_arguments(workflow: WorkflowDescriptor, values: dict[str, Any] | None = None) -> list[str]: + """Convert structured argument values into a safe argv fragment.""" + values = values or {} + accepted = {spec.name: spec for spec in workflow.accepted_arguments} + unknown = sorted(set(values) - set(accepted)) + if unknown: + raise ValueError(f"Unsupported arguments for {workflow.key}: {', '.join(unknown)}") + + args: list[str] = [] + for spec in workflow.accepted_arguments: + value = values.get(spec.name, spec.default) + args.extend(_coerce_argument(spec, value)) + return args + + +def build_workflow_command( + workflow_key: str, + *, + repo_root: str | Path = ".", + pixi_environment: str = "default", + run_name: str = "run", + output_base: str | Path = "results", + argument_values: dict[str, Any] | None = None, + use_pixi: bool = True, +) -> BuiltCommand: + """Build a workflow command as argv list without shell interpolation.""" + workflow = get_workflow(workflow_key) + if not workflow.python_module: + raise ValueError(f"Workflow {workflow_key!r} does not define a Python module command.") + + outdir = build_output_dir(repo_root, workflow.key, run_name, output_base) + command: list[str] = [] + if use_pixi: + command.extend(["pixi", "run", "-e", pixi_environment]) + command.extend(["python", "-m", workflow.python_module]) + command.extend(workflow.module_args) + command.extend(workflow_arguments(workflow, argument_values)) + if workflow.output_dir_arg: + command.extend([workflow.output_dir_arg, str(outdir)]) + return BuiltCommand(workflow=workflow, command=command, outdir=outdir, pixi_environment=pixi_environment) diff --git a/dashboard/components/command_preview.py b/dashboard/components/command_preview.py new file mode 100644 index 0000000..2f8eee2 --- /dev/null +++ b/dashboard/components/command_preview.py @@ -0,0 +1,14 @@ +from __future__ import annotations + +import streamlit as st + +from dashboard.command_builder import BuiltCommand + + +def render_command_preview(built: BuiltCommand) -> None: + """Show an exact command preview before execution.""" + st.subheader("Command preview") + st.code(built.preview, language="bash") + with st.expander("Argument list", expanded=False): + st.json(built.command) + st.caption(f"Output directory: `{built.outdir}`") diff --git a/dashboard/components/console_panel.py b/dashboard/components/console_panel.py new file mode 100644 index 0000000..4925e09 --- /dev/null +++ b/dashboard/components/console_panel.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +import streamlit as st + + +def render_console(lines: list[str], height: int = 360) -> None: + """Render streamed console output.""" + text = "".join(lines) + st.text_area("Console", text, height=height) + + +def render_cancellation_note() -> None: + """Explain the current cancellation boundary without exposing unsafe controls.""" + st.caption( + "Cancellation is not exposed in this dashboard phase: Streamlit reruns make reliable foreground " + "process termination fragile without a background job supervisor. The runner supports a cancellation " + "callback for future supervised execution." + ) diff --git a/dashboard/components/run_status.py b/dashboard/components/run_status.py new file mode 100644 index 0000000..ef93fdc --- /dev/null +++ b/dashboard/components/run_status.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +import streamlit as st + + +def render_run_status(status: str | None, returncode: int | None = None) -> None: + """Render workflow completion status.""" + if status is None: + st.info("No workflow has been run in this session.") + elif status == "running": + st.warning("Workflow is running…") + elif status == "success": + st.success("Workflow completed successfully.") + elif status == "cancelled": + st.warning(f"Workflow was cancelled. Return code: {returncode}") + else: + st.error(f"Workflow failed. Return code: {returncode}") diff --git a/dashboard/components/workflow_selector.py b/dashboard/components/workflow_selector.py new file mode 100644 index 0000000..6b337bb --- /dev/null +++ b/dashboard/components/workflow_selector.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +from pathlib import Path +from typing import Any + +import streamlit as st + +from dashboard.registry import WorkflowDescriptor, launchable_workflows, pixi_environments + + +def render_workflow_selector(repo_root: Path) -> tuple[WorkflowDescriptor, str, str, dict[str, Any]]: + """Render structured workflow/env/argument controls for safe command building.""" + workflows = launchable_workflows() + workflow = st.selectbox("Workflow", workflows, format_func=lambda item: f"{item.label} ({item.key})") + st.caption(workflow.description) + if workflow.required_inputs: + st.write("Known inputs:", ", ".join(workflow.required_inputs)) + + envs = pixi_environments(repo_root / "pixi.toml") + env = st.selectbox("Pixi environment", envs, index=0) + run_name = st.text_input("Run name", value=f"{workflow.key}-run") + + values: dict[str, Any] = {} + if workflow.accepted_arguments: + with st.expander("Structured CLI arguments", expanded=False): + for spec in workflow.accepted_arguments: + current = spec.default + help_text = spec.description or None + if spec.kind == "bool": + values[spec.name] = st.checkbox(spec.flag, value=bool(current), help=help_text) + elif spec.kind in {"int", "float"}: + values[spec.name] = st.text_input(spec.flag, value="" if current is None else str(current), help=help_text) + else: + values[spec.name] = st.text_input(spec.flag, value="" if current is None else str(current), help=help_text) + return workflow, env, run_name, values diff --git a/dashboard/registry.py b/dashboard/registry.py index 40f469b..8a50a8c 100644 --- a/dashboard/registry.py +++ b/dashboard/registry.py @@ -1,35 +1,198 @@ from __future__ import annotations import json -from dataclasses import dataclass +from dataclasses import dataclass, field +from pathlib import Path +from typing import Literal from dashboard.result_parser import ResultInventory +ArgKind = Literal["str", "int", "float", "bool", "path"] + + +@dataclass(frozen=True) +class ArgumentSpec: + """Structured argument accepted by a registered workflow launcher.""" + + name: str + flag: str + kind: ArgKind = "str" + description: str = "" + default: str | int | float | bool | None = None + required: bool = False + @dataclass(frozen=True) class WorkflowDescriptor: key: str label: str description: str + pixi_task: str | None = None + python_module: str | None = None + module_args: tuple[str, ...] = () + accepted_arguments: tuple[ArgumentSpec, ...] = () + required_inputs: tuple[str, ...] = () + output_dir_arg: str | None = "--outdir" + expected_output_folder: str | None = None + result_workflow_keys: tuple[str, ...] = field(default_factory=tuple) + safe_for_dashboard: bool = True WORKFLOWS: dict[str, WorkflowDescriptor] = { - "kinopt.local": WorkflowDescriptor("kinopt.local", "KinOpt local", "Local kinase-phosphorylation optimisation results."), - "tfopt.local": WorkflowDescriptor("tfopt.local", "TFOpt local", "Local transcription-factor optimisation results."), - "protwise.runner": WorkflowDescriptor("protwise.runner", "ProtWise", "ProtWise ODE modelling results."), - "networkmodel.runner": WorkflowDescriptor("networkmodel.runner", "Network model", "Integrated global network model results."), - "unknown": WorkflowDescriptor("unknown", "Unknown workflow", "Result directory without recognised workflow metadata."), + # Result-browser descriptors retained for backwards-compatible metadata inference. + "kinopt.local": WorkflowDescriptor( + "kinopt.local", "KinOpt local", "Local kinase-phosphorylation optimisation results.", + result_workflow_keys=("kinopt.local",), expected_output_folder="results", + ), + "tfopt.local": WorkflowDescriptor( + "tfopt.local", "TFOpt local", "Local transcription-factor optimisation results.", + result_workflow_keys=("tfopt.local",), expected_output_folder="results", + ), + "protwise.runner": WorkflowDescriptor( + "protwise.runner", "ProtWise", "ProtWise ODE modelling results.", + result_workflow_keys=("protwise.runner",), expected_output_folder="results", + ), + "networkmodel.runner": WorkflowDescriptor( + "networkmodel.runner", "Network model", "Integrated global network model results.", + result_workflow_keys=("networkmodel.runner",), expected_output_folder="results", + ), + "unknown": WorkflowDescriptor( + "unknown", "Unknown workflow", "Result directory without recognised workflow metadata.", + output_dir_arg=None, safe_for_dashboard=False, + ), + # Launchable workflows for Phase 2. + "prep": WorkflowDescriptor( + key="prep", + label="Preprocessing", + description="Run preprocessing cleanup using the existing processing.cleanup module.", + pixi_task="prep", + python_module="processing.cleanup", + output_dir_arg=None, + expected_output_folder="results/prep", + result_workflow_keys=("prep",), + ), + "kinopt-local": WorkflowDescriptor( + key="kinopt-local", + label="KinOpt local", + description="Run local kinase-phosphorylation optimisation via kinopt.local.", + pixi_task="kinopt-local", + python_module="kinopt.local", + accepted_arguments=( + ArgumentSpec("conf", "--conf", "path", "Optional TOML/YAML configuration file."), + ArgumentSpec("lower_bound", "--lower_bound", "float", "Lower optimisation bound."), + ArgumentSpec("upper_bound", "--upper_bound", "float", "Upper optimisation bound."), + ArgumentSpec("loss_type", "--loss_type", "str", "Loss function name."), + ArgumentSpec("method", "--method", "str", "Optimisation method."), + ), + required_inputs=("input1.csv", "input2.csv"), + output_dir_arg="--outdir", + expected_output_folder="results/kinopt-local", + result_workflow_keys=("kinopt.local",), + ), + "tfopt-local": WorkflowDescriptor( + key="tfopt-local", + label="TFOpt local", + description="Run local transcription-factor optimisation via tfopt.local.", + pixi_task="tfopt-local", + python_module="tfopt.local", + accepted_arguments=( + ArgumentSpec("conf", "--conf", "path", "Optional TOML/YAML configuration file."), + ArgumentSpec("lower_bound", "--lower_bound", "float", "Lower optimisation bound."), + ArgumentSpec("upper_bound", "--upper_bound", "float", "Upper optimisation bound."), + ArgumentSpec("loss_type", "--loss_type", "int", "Loss function identifier."), + ), + required_inputs=("input1.csv", "input3.csv", "input4.csv"), + output_dir_arg="--outdir", + expected_output_folder="results/tfopt-local", + result_workflow_keys=("tfopt.local",), + ), + "protwise-model": WorkflowDescriptor( + key="protwise-model", + label="ProtWise model", + description="Run the ProtWise ODE model via protwise.runner.main.", + pixi_task="model", + python_module="protwise.runner.main", + accepted_arguments=( + ArgumentSpec("conf", "--conf", "path", "Optional model configuration file."), + ArgumentSpec("bootstraps", "--bootstraps", "int", "Bootstrap iterations."), + ArgumentSpec("input_excel_protein", "--input-excel-protein", "path", "Protein input Excel file."), + ArgumentSpec("input_excel_psite", "--input-excel-psite", "path", "Phosphosite input Excel file."), + ArgumentSpec("input_excel_rna", "--input-excel-rna", "path", "RNA input Excel file."), + ), + required_inputs=("protein Excel", "phosphosite Excel", "RNA Excel"), + output_dir_arg="--outdir", + expected_output_folder="results/protwise-model", + result_workflow_keys=("protwise.runner",), + ), + "networkmodel": WorkflowDescriptor( + key="networkmodel", + label="Network model", + description="Run the integrated global model via networkmodel.runner.", + pixi_task="networkmodel", + python_module="networkmodel.runner", + accepted_arguments=( + ArgumentSpec("conf", "--conf", "path", "Optional global model config file."), + ArgumentSpec("kinase_net", "--kinase-net", "path", "Kinase network CSV."), + ArgumentSpec("tf_net", "--tf-net", "path", "TF network CSV."), + ArgumentSpec("ms", "--ms", "path", "Protein/MS data file."), + ArgumentSpec("rna", "--rna", "path", "RNA data file."), + ArgumentSpec("phospho", "--phospho", "path", "Phosphoproteomics data file."), + ArgumentSpec("cores", "--cores", "int", "Worker/core count."), + ArgumentSpec("n_gen", "--n-gen", "int", "Maximum optimiser iterations."), + ArgumentSpec("seed", "--seed", "int", "Random seed."), + ArgumentSpec("scan", "--scan", "bool", "Run hyperparameter scan."), + ArgumentSpec("sensitivity", "--sensitivity", "bool", "Run sensitivity analysis."), + ), + required_inputs=("kinase network", "TF network", "MS/protein data", "RNA data", "phospho data"), + output_dir_arg="--output-dir", + expected_output_folder="results/networkmodel", + result_workflow_keys=("networkmodel.runner",), + ), + "phoskintime-all": WorkflowDescriptor( + key="phoskintime-all", + label="PhosKinTime all", + description="Run the existing config.cli all wrapper for preprocessing, local TF/KinOpt, and ProtWise model.", + pixi_task="phoskintime-all", + python_module="config.cli", + module_args=("all",), + accepted_arguments=( + ArgumentSpec("tf_mode", "--tf-mode", "str", "TFOpt mode.", default="local"), + ArgumentSpec("kin_mode", "--kin-mode", "str", "KinOpt mode.", default="local"), + ArgumentSpec("tf_conf", "--tf-conf", "path", "TFOpt config file."), + ArgumentSpec("kin_conf", "--kin-conf", "path", "KinOpt config file."), + ArgumentSpec("model_conf", "--model-conf", "path", "ProtWise config file."), + ), + output_dir_arg="--outdir", + expected_output_folder="results/phoskintime-all", + result_workflow_keys=("phoskintime.all",), + safe_for_dashboard=True, + ), } +def get_workflow(key: str) -> WorkflowDescriptor: + """Return a registered workflow or raise a KeyError with a helpful message.""" + try: + return WORKFLOWS[key] + except KeyError as exc: + known = ", ".join(sorted(WORKFLOWS)) + raise KeyError(f"Unknown workflow {key!r}. Known workflows: {known}") from exc + + +def launchable_workflows() -> list[WorkflowDescriptor]: + """Return dashboard-safe workflows that have an executable Python module.""" + return [wf for wf in sorted(WORKFLOWS.values(), key=lambda item: item.key) if wf.safe_for_dashboard and wf.python_module] + + def infer_workflow(inventory: ResultInventory) -> WorkflowDescriptor: """Infer workflow identity from metadata first, then legacy filenames.""" if inventory.metadata is not None: try: metadata = json.loads(inventory.metadata.read_text(encoding="utf-8")) workflow = str(metadata.get("workflow", "")).strip() - if workflow in WORKFLOWS: - return WORKFLOWS[workflow] + for descriptor in WORKFLOWS.values(): + if workflow == descriptor.key or workflow in descriptor.result_workflow_keys: + return descriptor except (OSError, json.JSONDecodeError): pass @@ -44,5 +207,24 @@ def infer_workflow(inventory: ResultInventory) -> WorkflowDescriptor: def registered_workflows() -> list[WorkflowDescriptor]: - """Return known workflow descriptors for display or tests.""" + """Return all known workflow descriptors for display or tests.""" return [WORKFLOWS[key] for key in sorted(WORKFLOWS)] + + +def pixi_environments(pixi_toml: str | Path = "pixi.toml") -> list[str]: + """Return Pixi environments defined by pixi.toml, always including default first.""" + path = Path(pixi_toml) + envs = ["default"] + if not path.is_file(): + return envs + try: + import tomllib + with path.open("rb") as handle: + data = tomllib.load(handle) + configured = data.get("environments", {}) or {} + for name in configured: + if name not in envs: + envs.append(str(name)) + except Exception: + return envs + return envs diff --git a/dashboard/runner.py b/dashboard/runner.py new file mode 100644 index 0000000..9eb4c9e --- /dev/null +++ b/dashboard/runner.py @@ -0,0 +1,126 @@ +from __future__ import annotations + +import json +import subprocess +from collections.abc import Callable, Iterator +from dataclasses import dataclass +from datetime import datetime, timezone +from pathlib import Path +from typing import Literal + +from common.results import ensure_result_dir, write_command, write_metadata +from dashboard.command_builder import BuiltCommand + +RunStatus = Literal["running", "success", "failure", "cancelled"] + + +@dataclass(frozen=True) +class RunEvent: + """A single launcher event for the dashboard console/status panels.""" + + status: RunStatus + line: str = "" + returncode: int | None = None + outdir: Path | None = None + + +def _merge_metadata(outdir: Path, updates: dict) -> None: + path = outdir / "metadata.json" + try: + existing = json.loads(path.read_text(encoding="utf-8")) if path.is_file() else {} + except json.JSONDecodeError: + existing = {} + existing.update(updates) + path.write_text(json.dumps(existing, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def prepare_run_provenance(built: BuiltCommand, extra: dict | None = None) -> Path: + """Create result folders and initial launcher provenance before subprocess execution.""" + outdir = ensure_result_dir(built.outdir)["root"] + write_command(outdir, built.command) + write_metadata( + outdir, + workflow=built.workflow.result_workflow_keys[0] if built.workflow.result_workflow_keys else built.workflow.key, + args={ + "launcher_workflow": built.workflow.key, + "pixi_environment": built.pixi_environment, + "command": built.command, + }, + extra={"launcher": "dashboard", "launcher_status": "running", **(extra or {})}, + ) + return outdir + + +def stream_command( + command: list[str], + *, + cwd: str | Path, + outdir: str | Path, + env: dict[str, str] | None = None, + cancel_check: Callable[[], bool] | None = None, +) -> Iterator[RunEvent]: + """Run a command with shell=False, streaming merged stdout/stderr and writing console.log.""" + root = ensure_result_dir(outdir)["root"] + console_path = root / "console.log" + with console_path.open("a", encoding="utf-8") as console: + console.write(f"\n[dashboard] start {datetime.now(timezone.utc).isoformat()}\n") + console.write("[dashboard] command " + " ".join(command) + "\n") + process = subprocess.Popen( + command, + cwd=Path(cwd), + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + bufsize=1, + shell=False, + env=env, + ) + cancelled = False + assert process.stdout is not None + for line in process.stdout: + console.write(line) + console.flush() + yield RunEvent(status="running", line=line, outdir=root) + if cancel_check is not None and cancel_check(): + cancelled = True + process.terminate() + break + returncode = process.wait() + if cancelled: + status: RunStatus = "cancelled" + else: + status = "success" if returncode == 0 else "failure" + console.write(f"[dashboard] {status} returncode={returncode}\n") + console.flush() + yield RunEvent(status=status, returncode=returncode, outdir=root) + + +def run_built_command( + built: BuiltCommand, + *, + repo_root: str | Path, + cancel_check: Callable[[], bool] | None = None, +) -> Iterator[RunEvent]: + """Prepare provenance, execute a built workflow command, and update run metadata.""" + outdir = prepare_run_provenance(built) + final_event: RunEvent | None = None + for event in stream_command(built.command, cwd=repo_root, outdir=outdir, cancel_check=cancel_check): + final_event = event + yield event + if final_event is not None and final_event.status in {"success", "failure", "cancelled"}: + _merge_metadata( + outdir, + { + "launcher_status": final_event.status, + "launcher_returncode": final_event.returncode, + "launcher_completed_at": datetime.now(timezone.utc).isoformat(), + }, + ) + + +def log_tail(outdir: str | Path, lines: int = 40) -> str: + """Return a bounded console.log tail for failure display.""" + path = Path(outdir) / "console.log" + if not path.is_file(): + return "" + return "".join(path.read_text(encoding="utf-8", errors="replace").splitlines(keepends=True)[-lines:]) diff --git a/docs/dashboard_build_plan.md b/docs/dashboard_build_plan.md index c98d0d9..cf987b5 100644 --- a/docs/dashboard_build_plan.md +++ b/docs/dashboard_build_plan.md @@ -377,3 +377,7 @@ The backend output contract is implemented with shared result utilities in `comm ### Phase 1 implementation note (June 2026) The initial dashboard component lives under `dashboard/` and focuses only on browsing existing result directories. It discovers the Phase 0 output contract and selected legacy outputs, lazily loads tables/plots/logs/reports only after a user selects them, and provides an in-memory ZIP archive for downloading a result directory. Workflow launching and file uploads remain outside this phase. + +### Phase 2 implementation note (June 2026) + +The dashboard now includes a registered workflow launcher that builds argv-list commands for existing Pixi/Python entry points, previews commands before execution, runs subprocesses from the repository root with `shell=False`, streams merged stdout/stderr into the UI and `console.log`, records launcher provenance, and opens successful run directories in the result browser. Upload/config editing remains out of scope. Interactive cancellation is not exposed yet because reliable Streamlit cancellation needs a persistent background job supervisor; the runner has a cancellation callback boundary for a future supervised implementation. diff --git a/tests/dashboard/test_command_builder.py b/tests/dashboard/test_command_builder.py new file mode 100644 index 0000000..d2608b3 --- /dev/null +++ b/tests/dashboard/test_command_builder.py @@ -0,0 +1,61 @@ +from __future__ import annotations + +from pathlib import Path + +import pytest + +from dashboard.command_builder import build_output_dir, build_workflow_command, sanitize_run_name, workflow_arguments +from dashboard.registry import get_workflow, launchable_workflows, pixi_environments + + +def test_command_construction_for_each_launchable_workflow(tmp_path): + keys = {workflow.key for workflow in launchable_workflows()} + assert {"prep", "kinopt-local", "tfopt-local", "protwise-model", "networkmodel", "phoskintime-all"} <= keys + + for key in keys: + built = build_workflow_command(key, repo_root=tmp_path, pixi_environment="dev", run_name="my run", use_pixi=True) + assert built.command[:4] == ["pixi", "run", "-e", "dev"] + assert built.command[4:7] == ["python", "-m", built.workflow.python_module] + if built.workflow.output_dir_arg: + assert built.workflow.output_dir_arg in built.command + assert str(built.outdir) in built.command + assert built.outdir == tmp_path / "results" / built.workflow.key / "my-run" + + +def test_builds_direct_python_command_without_pixi(tmp_path): + built = build_workflow_command("networkmodel", repo_root=tmp_path, run_name="n", use_pixi=False, argument_values={"cores": 2, "scan": True}) + + assert built.command[:3] == ["python", "-m", "networkmodel.runner"] + assert "pixi" not in built.command + assert ["--cores", "2"] == built.command[built.command.index("--cores"):built.command.index("--cores") + 2] + assert "--scan" in built.command + assert "--output-dir" in built.command + + +def test_phoskintime_all_places_subcommand_before_options(tmp_path): + built = build_workflow_command("phoskintime-all", repo_root=tmp_path, run_name="all", use_pixi=False) + + assert built.command[:4] == ["python", "-m", "config.cli", "all"] + assert "--outdir" in built.command + + +def test_structured_arguments_reject_unknown_values(): + workflow = get_workflow("tfopt-local") + + with pytest.raises(ValueError, match="Unsupported arguments"): + workflow_arguments(workflow, {"raw_shell": "rm -rf ."}) + + +def test_run_name_is_sanitized_and_output_dir_stays_under_base(tmp_path): + assert sanitize_run_name("../../bad run!!") == "bad-run" + + outdir = build_output_dir(tmp_path, "kinopt-local", "../../bad run!!") + + assert outdir == tmp_path / "results" / "kinopt-local" / "bad-run" + + +def test_pixi_environment_selection_reads_defined_environments(tmp_path): + pixi = tmp_path / "pixi.toml" + pixi.write_text('[environments]\ndefault = {}\ndev = {}\nviz = {}\n', encoding="utf-8") + + assert pixi_environments(pixi) == ["default", "dev", "viz"] diff --git a/tests/dashboard/test_registry.py b/tests/dashboard/test_registry.py index 025ed18..7e11ad3 100644 --- a/tests/dashboard/test_registry.py +++ b/tests/dashboard/test_registry.py @@ -2,7 +2,7 @@ import json -from dashboard.registry import infer_workflow, registered_workflows +from dashboard.registry import get_workflow, infer_workflow, launchable_workflows, registered_workflows from dashboard.result_parser import discover_result_directory @@ -13,7 +13,7 @@ def test_infer_workflow_from_metadata(tmp_path): descriptor = infer_workflow(discover_result_directory(root)) - assert descriptor.key == "tfopt.local" + assert descriptor.key in {"tfopt.local", "tfopt-local"} assert descriptor.label == "TFOpt local" @@ -27,7 +27,19 @@ def test_infer_workflow_from_legacy_networkmodel_tables(tmp_path): assert descriptor.key == "networkmodel.runner" -def test_registered_workflows_contains_unknown_fallback(): +def test_registered_workflows_contains_result_and_launcher_entries(): keys = {descriptor.key for descriptor in registered_workflows()} assert {"kinopt.local", "tfopt.local", "protwise.runner", "networkmodel.runner", "unknown"} <= keys + assert {"prep", "kinopt-local", "tfopt-local", "protwise-model", "networkmodel", "phoskintime-all"} <= keys + + +def test_launchable_registry_entries_include_command_metadata(): + workflows = {workflow.key: workflow for workflow in launchable_workflows()} + + kinopt = workflows["kinopt-local"] + assert kinopt.pixi_task == "kinopt-local" + assert kinopt.python_module == "kinopt.local" + assert kinopt.output_dir_arg == "--outdir" + assert kinopt.accepted_arguments + assert get_workflow("networkmodel").output_dir_arg == "--output-dir" diff --git a/tests/dashboard/test_runner.py b/tests/dashboard/test_runner.py new file mode 100644 index 0000000..35c92d2 --- /dev/null +++ b/tests/dashboard/test_runner.py @@ -0,0 +1,88 @@ +from __future__ import annotations + +import json +import sys + +from dashboard.command_builder import build_workflow_command +from dashboard.runner import RunEvent, log_tail, run_built_command, stream_command + + +def test_stream_command_uses_shell_false(monkeypatch, tmp_path): + calls = {} + + class FakeProcess: + stdout = iter(["hello\n"]) + + def wait(self): + return 0 + + def terminate(self): + calls["terminated"] = True + + def fake_popen(command, **kwargs): + calls["command"] = command + calls["shell"] = kwargs.get("shell") + return FakeProcess() + + monkeypatch.setattr("dashboard.runner.subprocess.Popen", fake_popen) + + events = list(stream_command(["python", "-c", "print('hello')"], cwd=tmp_path, outdir=tmp_path / "run")) + + assert calls["shell"] is False + assert events[-1] == RunEvent(status="success", returncode=0, outdir=(tmp_path / "run").resolve()) + assert "hello" in (tmp_path / "run" / "console.log").read_text(encoding="utf-8") + + +def test_run_built_command_executes_tiny_python_and_writes_provenance(tmp_path): + built = build_workflow_command("prep", repo_root=tmp_path, run_name="tiny", use_pixi=False) + command = [sys.executable, "-c", "print('tiny ok')"] + built = type(built)(workflow=built.workflow, command=command, outdir=built.outdir, pixi_environment="default") + + events = list(run_built_command(built, repo_root=tmp_path)) + + assert events[-1].status == "success" + assert events[-1].returncode == 0 + assert "tiny ok" in (built.outdir / "console.log").read_text(encoding="utf-8") + command_text = (built.outdir / "command.txt").read_text(encoding="utf-8").strip() + assert str(command[0]) in command_text + assert "print" in command_text + metadata = json.loads((built.outdir / "metadata.json").read_text(encoding="utf-8")) + assert metadata["launcher"] == "dashboard" + assert metadata["launcher_status"] == "success" + assert metadata["launcher_returncode"] == 0 + + +def test_run_built_command_reports_failure_and_log_tail(tmp_path): + built = build_workflow_command("prep", repo_root=tmp_path, run_name="fail", use_pixi=False) + command = [sys.executable, "-c", "import sys; print('bad'); sys.exit(3)"] + built = type(built)(workflow=built.workflow, command=command, outdir=built.outdir, pixi_environment="default") + + events = list(run_built_command(built, repo_root=tmp_path)) + + assert events[-1].status == "failure" + assert events[-1].returncode == 3 + assert "bad" in log_tail(built.outdir) + + +def test_stream_command_can_report_cancelled(monkeypatch, tmp_path): + calls = {"checks": 0} + + class FakeProcess: + stdout = iter(["line\n"]) + + def wait(self): + return -15 + + def terminate(self): + calls["terminated"] = True + + monkeypatch.setattr("dashboard.runner.subprocess.Popen", lambda *args, **kwargs: FakeProcess()) + + def cancel_after_first_line(): + calls["checks"] += 1 + return True + + events = list(stream_command(["python"], cwd=tmp_path, outdir=tmp_path / "run", cancel_check=cancel_after_first_line)) + + assert calls["terminated"] is True + assert events[-1].status == "cancelled" From 9c0d76bf866cbb545b5d0d0fade10681067be132 Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Wed, 10 Jun 2026 18:40:08 +0530 Subject: [PATCH 06/42] Add dashboard upload and configuration UI --- .gitignore | 4 + dashboard/app.py | 34 ++++- dashboard/command_builder.py | 40 +++++- dashboard/components/config_panel.py | 53 ++++++++ dashboard/components/input_preview.py | 30 +++++ dashboard/components/preset_panel.py | 27 ++++ dashboard/components/upload_panel.py | 47 +++++++ dashboard/components/validation_panel.py | 31 +++++ dashboard/components/workflow_selector.py | 20 +-- dashboard/config_utils.py | 149 ++++++++++++++++++++++ dashboard/file_utils.py | 98 ++++++++++++++ dashboard/registry.py | 41 ++++++ docs/dashboard_build_plan.md | 4 + tests/dashboard/test_command_builder.py | 24 ++++ tests/dashboard/test_config_utils.py | 35 +++++ tests/dashboard/test_file_utils.py | 66 ++++++++++ tests/dashboard/test_upload_validation.py | 36 ++++++ 17 files changed, 716 insertions(+), 23 deletions(-) create mode 100644 dashboard/components/config_panel.py create mode 100644 dashboard/components/input_preview.py create mode 100644 dashboard/components/preset_panel.py create mode 100644 dashboard/components/upload_panel.py create mode 100644 dashboard/components/validation_panel.py create mode 100644 dashboard/config_utils.py create mode 100644 tests/dashboard/test_config_utils.py create mode 100644 tests/dashboard/test_upload_validation.py diff --git a/.gitignore b/.gitignore index 2d16db1..43848bd 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,7 @@ site/ !/notebooks/outputs/ !/notebooks/outputs/*/ !/notebooks/outputs/*/.gitkeep + +# Dashboard uploads and local archives +/dashboard_uploads/ +*.zip diff --git a/dashboard/app.py b/dashboard/app.py index ceb3375..9e35a4e 100644 --- a/dashboard/app.py +++ b/dashboard/app.py @@ -4,12 +4,18 @@ import streamlit as st -from dashboard.command_builder import build_workflow_command +from dashboard.command_builder import build_workflow_command, sanitize_run_name from dashboard.components.command_preview import render_command_preview +from dashboard.components.config_panel import render_config_panel from dashboard.components.console_panel import render_cancellation_note, render_console +from dashboard.components.input_preview import render_input_preview +from dashboard.components.preset_panel import render_preset_panel from dashboard.components.result_browser import render_result_browser from dashboard.components.run_status import render_run_status +from dashboard.components.upload_panel import render_upload_panel +from dashboard.components.validation_panel import render_validation_panel, validate_dashboard_setup from dashboard.components.workflow_selector import render_workflow_selector +from dashboard.config_utils import DashboardSelection from dashboard.result_parser import discover_result_directory from dashboard.runner import log_tail, run_built_command @@ -56,23 +62,43 @@ def _render_launcher_panel() -> None: st.write("Construct, preview, and run registered PhosKinTime workflows using existing CLI modules.") render_cancellation_note() - workflow, env, run_name, argument_values = render_workflow_selector(REPO_ROOT) + workflow, env, run_name = render_workflow_selector(REPO_ROOT) + safe_run_name = sanitize_run_name(run_name) + uploaded_paths = render_upload_panel(REPO_ROOT, safe_run_name) + retained_paths = [Path(path) for path in st.session_state.get("uploaded_paths", []) if Path(path).exists()] + combined_paths = sorted({*retained_paths, *uploaded_paths}, key=lambda path: path.name.lower()) + if uploaded_paths: + st.session_state["uploaded_paths"] = [str(path) for path in combined_paths] + render_input_preview(combined_paths) + argument_values, input_assignments = render_config_panel(workflow, combined_paths) + validation_problems = validate_dashboard_setup(workflow, combined_paths, input_assignments) + can_run = render_validation_panel(validation_problems) + try: built = build_workflow_command( workflow.key, repo_root=REPO_ROOT, pixi_environment=env, - run_name=run_name, + run_name=safe_run_name, argument_values=argument_values, + input_assignments=input_assignments, ) except (KeyError, ValueError) as exc: st.error(str(exc)) return render_command_preview(built) + selection = DashboardSelection( + workflow_key=workflow.key, + run_name=safe_run_name, + pixi_environment=env, + arguments=argument_values, + input_assignments=input_assignments, + ) + render_preset_panel(selection, REPO_ROOT) render_run_status(st.session_state.get("launcher_status"), st.session_state.get("launcher_returncode")) - if st.button("Run workflow", type="primary"): + if st.button("Run workflow", type="primary", disabled=not can_run): console_lines: list[str] = [] console_placeholder = st.empty() status_placeholder = st.empty() diff --git a/dashboard/command_builder.py b/dashboard/command_builder.py index edc9288..9368bb5 100644 --- a/dashboard/command_builder.py +++ b/dashboard/command_builder.py @@ -47,7 +47,10 @@ def _coerce_argument(spec: ArgumentSpec, value: Any) -> list[str]: raise ValueError(f"Missing required argument: {spec.name}") return [] if spec.kind == "bool": - return [spec.flag] if bool(value) else [] + enabled = value + if isinstance(value, str): + enabled = value.strip().lower() in {"1", "true", "yes", "y", "on"} + return [spec.flag] if bool(enabled) else [] if spec.kind == "int": return [spec.flag, str(int(value))] if spec.kind == "float": @@ -70,6 +73,37 @@ def workflow_arguments(workflow: WorkflowDescriptor, values: dict[str, Any] | No return args + +def arguments_from_input_assignments(workflow: WorkflowDescriptor, input_assignments: dict[str, str | Path] | None = None) -> dict[str, str]: + """Map workflow input roles to supported CLI argument names.""" + input_assignments = input_assignments or {} + specs = {spec.role: spec for spec in workflow.input_assignments} + unknown = sorted(set(input_assignments) - set(specs)) + if unknown: + raise ValueError(f"Unsupported input roles for {workflow.key}: {', '.join(unknown)}") + + mapped: dict[str, str] = {} + for role, path in input_assignments.items(): + if path is None or str(path) == "": + continue + spec = specs[role] + if spec.argument_name is None: + continue + mapped[spec.argument_name] = str(path) + return mapped + + +def merge_argument_sources( + workflow: WorkflowDescriptor, + argument_values: dict[str, Any] | None = None, + input_assignments: dict[str, str | Path] | None = None, +) -> dict[str, Any]: + """Merge structured parameters with input assignments without inventing CLI options.""" + merged = dict(argument_values or {}) + for name, value in arguments_from_input_assignments(workflow, input_assignments).items(): + merged[name] = value + return merged + def build_workflow_command( workflow_key: str, *, @@ -78,6 +112,7 @@ def build_workflow_command( run_name: str = "run", output_base: str | Path = "results", argument_values: dict[str, Any] | None = None, + input_assignments: dict[str, str | Path] | None = None, use_pixi: bool = True, ) -> BuiltCommand: """Build a workflow command as argv list without shell interpolation.""" @@ -91,7 +126,8 @@ def build_workflow_command( command.extend(["pixi", "run", "-e", pixi_environment]) command.extend(["python", "-m", workflow.python_module]) command.extend(workflow.module_args) - command.extend(workflow_arguments(workflow, argument_values)) + merged_arguments = merge_argument_sources(workflow, argument_values, input_assignments) + command.extend(workflow_arguments(workflow, merged_arguments)) if workflow.output_dir_arg: command.extend([workflow.output_dir_arg, str(outdir)]) return BuiltCommand(workflow=workflow, command=command, outdir=outdir, pixi_environment=pixi_environment) diff --git a/dashboard/components/config_panel.py b/dashboard/components/config_panel.py new file mode 100644 index 0000000..ad62e3f --- /dev/null +++ b/dashboard/components/config_panel.py @@ -0,0 +1,53 @@ +from __future__ import annotations + +from pathlib import Path +from typing import Any + +import streamlit as st + +from dashboard.config_utils import parse_config_file +from dashboard.registry import WorkflowDescriptor + + +def render_config_panel(workflow: WorkflowDescriptor, available_files: list[Path]) -> tuple[dict[str, Any], dict[str, str]]: + """Render structured parameter and workflow-specific input assignment controls.""" + st.subheader("Configure workflow") + arguments: dict[str, Any] = {} + assignments: dict[str, str] = {} + + if workflow.accepted_arguments: + with st.expander("Parameters", expanded=True): + for spec in workflow.accepted_arguments: + if any(input_spec.argument_name == spec.name for input_spec in workflow.input_assignments): + continue + help_text = spec.description or None + default = "" if spec.default is None else str(spec.default) + if spec.kind == "bool": + arguments[spec.name] = st.checkbox(spec.flag, value=bool(spec.default), help=help_text) + else: + arguments[spec.name] = st.text_input(spec.flag, value=default, help=help_text, key=f"arg-{workflow.key}-{spec.name}") + + if workflow.input_assignments: + with st.expander("Input assignments", expanded=True): + labels = ["Do not pass"] + [str(path) for path in available_files] + for spec in workflow.input_assignments: + selected = st.selectbox(spec.label, labels, help=spec.description or None, key=f"input-{workflow.key}-{spec.role}") + custom = st.text_input(f"Existing path for {spec.label}", value="", key=f"input-path-{workflow.key}-{spec.role}") + if custom.strip(): + assignments[spec.role] = custom.strip() + elif selected != "Do not pass": + assignments[spec.role] = selected + + config_paths = [Path(path) for path in assignments.values() if Path(path).suffix.lower() in {".json", ".yaml", ".yml", ".toml", ".txt"}] + if config_paths: + with st.expander("Config preview", expanded=False): + selected_config = st.selectbox("Config file", config_paths, format_func=lambda path: path.name) + try: + parsed = parse_config_file(selected_config) + if isinstance(parsed, (dict, list)): + st.json(parsed) + else: + st.code(str(parsed)) + except Exception as exc: + st.error(f"Could not parse config: {exc}") + return arguments, assignments diff --git a/dashboard/components/input_preview.py b/dashboard/components/input_preview.py new file mode 100644 index 0000000..699efd2 --- /dev/null +++ b/dashboard/components/input_preview.py @@ -0,0 +1,30 @@ +from __future__ import annotations + +from pathlib import Path + +import streamlit as st + +from dashboard.file_utils import preview_table, read_text_preview, validate_existing_file + + +def render_input_preview(paths: list[Path]) -> None: + """Preview uploaded/selected files without modifying them.""" + st.subheader("Input preview") + if not paths: + st.info("Upload or select files to preview them here.") + return + selected = st.selectbox("Preview file", paths, format_func=lambda path: path.name) + problems = validate_existing_file(selected) + if problems: + st.error("; ".join(problems)) + return + if selected.suffix.lower() in {".csv", ".tsv", ".xlsx"}: + try: + st.dataframe(preview_table(selected), use_container_width=True) + except Exception as exc: + st.error(f"Could not preview table: {exc}") + else: + text, truncated = read_text_preview(selected) + st.code(text) + if truncated: + st.caption("Preview truncated for display.") diff --git a/dashboard/components/preset_panel.py b/dashboard/components/preset_panel.py new file mode 100644 index 0000000..5d06765 --- /dev/null +++ b/dashboard/components/preset_panel.py @@ -0,0 +1,27 @@ +from __future__ import annotations + +from pathlib import Path + +import streamlit as st + +from dashboard.config_utils import DashboardSelection, save_preset + + +def render_preset_panel(selection: DashboardSelection, repo_root: Path) -> None: + """Allow saving the resolved dashboard selections as a preset file.""" + st.subheader("Preset") + preset_name = st.text_input("Preset filename", value=f"{selection.run_name}.json") + if st.button("Save preset"): + target = repo_root / "dashboard_uploads" / selection.run_name / preset_name + try: + path = save_preset(selection, target) + except ValueError as exc: + st.error(str(exc)) + return + st.success(f"Saved preset to {path}") + st.download_button( + "Download preset JSON", + data=__import__("json").dumps(selection.to_dict(), indent=2, sort_keys=True), + file_name=f"{selection.run_name}.json", + mime="application/json", + ) diff --git a/dashboard/components/upload_panel.py b/dashboard/components/upload_panel.py new file mode 100644 index 0000000..9992259 --- /dev/null +++ b/dashboard/components/upload_panel.py @@ -0,0 +1,47 @@ +from __future__ import annotations + +from pathlib import Path + +import streamlit as st + +from dashboard.file_utils import ( + UPLOAD_EXTENSIONS, + create_upload_dir, + detect_duplicate_filenames, + save_uploaded_file, + validate_upload_filename, +) + + +def render_upload_panel(repo_root: Path, run_name: str) -> list[Path]: + """Render upload controls and save files under dashboard_uploads// on demand.""" + st.subheader("Upload inputs") + uploaded = st.file_uploader( + "Upload input/config files", + type=sorted(ext.lstrip(".") for ext in UPLOAD_EXTENSIONS), + accept_multiple_files=True, + ) + saved: list[Path] = [] + if not uploaded: + return saved + + duplicates = detect_duplicate_filenames(file.name for file in uploaded) + if duplicates: + st.error("Duplicate filenames after sanitization: " + ", ".join(duplicates)) + return saved + + upload_dir = create_upload_dir(repo_root, run_name) + for file in uploaded: + problems = validate_upload_filename(file.name) + if problems: + st.error("; ".join(problems)) + continue + try: + path = save_uploaded_file(file, upload_dir) + except ValueError as exc: + st.error(str(exc)) + continue + saved.append(path) + if saved: + st.success(f"Saved {len(saved)} file(s) to {upload_dir}") + return saved diff --git a/dashboard/components/validation_panel.py b/dashboard/components/validation_panel.py new file mode 100644 index 0000000..3a7d5d0 --- /dev/null +++ b/dashboard/components/validation_panel.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +from dashboard.config_utils import validate_input_assignments +from dashboard.file_utils import detect_duplicate_filenames, validate_existing_file +from dashboard.registry import WorkflowDescriptor + + +def validate_dashboard_setup(workflow: WorkflowDescriptor, available_paths, assignments: dict[str, str]) -> list[str]: + """Validate uploaded/selected files and workflow input assignments.""" + problems: list[str] = [] + duplicates = detect_duplicate_filenames(path.name for path in available_paths) + if duplicates: + problems.append("Duplicate filenames: " + ", ".join(duplicates)) + for path in available_paths: + problems.extend(f"{path.name}: {problem}" for problem in validate_existing_file(path)) + problems.extend(validate_input_assignments(workflow, assignments)) + return problems + + +def render_validation_panel(problems: list[str]) -> bool: + """Render validation status and return whether running should be enabled.""" + import streamlit as st + + st.subheader("Validation") + if problems: + st.error("Resolve validation issues before running.") + for problem in problems: + st.write(f"- {problem}") + return False + st.success("No validation issues detected for the current dashboard selections.") + return True diff --git a/dashboard/components/workflow_selector.py b/dashboard/components/workflow_selector.py index 6b337bb..fe703eb 100644 --- a/dashboard/components/workflow_selector.py +++ b/dashboard/components/workflow_selector.py @@ -1,15 +1,14 @@ from __future__ import annotations from pathlib import Path -from typing import Any import streamlit as st from dashboard.registry import WorkflowDescriptor, launchable_workflows, pixi_environments -def render_workflow_selector(repo_root: Path) -> tuple[WorkflowDescriptor, str, str, dict[str, Any]]: - """Render structured workflow/env/argument controls for safe command building.""" +def render_workflow_selector(repo_root: Path) -> tuple[WorkflowDescriptor, str, str]: + """Render workflow, Pixi environment, and run-name controls.""" workflows = launchable_workflows() workflow = st.selectbox("Workflow", workflows, format_func=lambda item: f"{item.label} ({item.key})") st.caption(workflow.description) @@ -19,17 +18,4 @@ def render_workflow_selector(repo_root: Path) -> tuple[WorkflowDescriptor, str, envs = pixi_environments(repo_root / "pixi.toml") env = st.selectbox("Pixi environment", envs, index=0) run_name = st.text_input("Run name", value=f"{workflow.key}-run") - - values: dict[str, Any] = {} - if workflow.accepted_arguments: - with st.expander("Structured CLI arguments", expanded=False): - for spec in workflow.accepted_arguments: - current = spec.default - help_text = spec.description or None - if spec.kind == "bool": - values[spec.name] = st.checkbox(spec.flag, value=bool(current), help=help_text) - elif spec.kind in {"int", "float"}: - values[spec.name] = st.text_input(spec.flag, value="" if current is None else str(current), help=help_text) - else: - values[spec.name] = st.text_input(spec.flag, value="" if current is None else str(current), help=help_text) - return workflow, env, run_name, values + return workflow, env, run_name diff --git a/dashboard/config_utils.py b/dashboard/config_utils.py new file mode 100644 index 0000000..f2bd2f3 --- /dev/null +++ b/dashboard/config_utils.py @@ -0,0 +1,149 @@ +from __future__ import annotations + +import json +from dataclasses import dataclass, field +from pathlib import Path +from typing import Any + + +@dataclass(frozen=True) +class DashboardSelection: + """Serializable dashboard workflow setup selections.""" + + workflow_key: str + run_name: str + pixi_environment: str = "default" + arguments: dict[str, Any] = field(default_factory=dict) + input_assignments: dict[str, str] = field(default_factory=dict) + + def to_dict(self) -> dict[str, Any]: + return { + "workflow_key": self.workflow_key, + "run_name": self.run_name, + "pixi_environment": self.pixi_environment, + "arguments": self.arguments, + "input_assignments": self.input_assignments, + } + + +def _parse_simple_yaml(text: str) -> dict[str, Any]: + """Parse a conservative flat YAML subset when PyYAML is unavailable.""" + data: dict[str, Any] = {} + for raw_line in text.splitlines(): + line = raw_line.strip() + if not line or line.startswith("#"): + continue + if ":" not in line: + raise ValueError("Only simple key: value YAML is supported without PyYAML") + key, value = line.split(":", 1) + value = value.strip() + if value.lower() in {"true", "false"}: + parsed: Any = value.lower() == "true" + elif value == "": + parsed = None + else: + try: + parsed = int(value) + except ValueError: + try: + parsed = float(value) + except ValueError: + parsed = value.strip('"\'') + data[key.strip()] = parsed + return data + + +def parse_config_file(path: str | Path) -> Any: + """Parse supported dashboard config/preset files for preview.""" + file_path = Path(path) + suffix = file_path.suffix.lower() + text = file_path.read_text(encoding="utf-8") + if suffix == ".json": + return json.loads(text) + if suffix in {".yaml", ".yml"}: + try: + import yaml # type: ignore + return yaml.safe_load(text) + except ImportError: + return _parse_simple_yaml(text) + if suffix == ".toml": + import tomllib + with file_path.open("rb") as handle: + return tomllib.load(handle) + if suffix == ".txt": + return text + raise ValueError(f"Unsupported config extension: {suffix or ''}") + + +def selection_to_preset(selection: DashboardSelection) -> dict[str, Any]: + """Convert dashboard selections to a preset dictionary.""" + return selection.to_dict() + + +def save_preset(selection: DashboardSelection, path: str | Path) -> Path: + """Save dashboard selections as JSON or simple YAML based on extension.""" + target = Path(path) + target.parent.mkdir(parents=True, exist_ok=True) + data = selection_to_preset(selection) + suffix = target.suffix.lower() + if suffix == ".json": + target.write_text(json.dumps(data, indent=2, sort_keys=True) + "\n", encoding="utf-8") + elif suffix in {".yaml", ".yml"}: + try: + import yaml # type: ignore + text = yaml.safe_dump(data, sort_keys=True) + except ImportError: + lines = [f"{key}: {json.dumps(value)}" for key, value in data.items()] + text = "\n".join(lines) + "\n" + target.write_text(text, encoding="utf-8") + else: + raise ValueError("Presets must be saved as .json, .yaml, or .yml") + return target + + +def load_preset(path: str | Path) -> DashboardSelection: + """Load a saved dashboard selection preset.""" + parsed = parse_config_file(path) + if not isinstance(parsed, dict): + raise ValueError("Preset must contain a mapping/object") + return DashboardSelection( + workflow_key=str(parsed.get("workflow_key", "")), + run_name=str(parsed.get("run_name", "run")), + pixi_environment=str(parsed.get("pixi_environment", "default")), + arguments=dict(parsed.get("arguments", {}) or {}), + input_assignments=dict(parsed.get("input_assignments", {}) or {}), + ) + + +def validate_input_assignments(workflow, assignments: dict[str, str]) -> list[str]: + """Validate assigned input roles against workflow specs and basic file rules.""" + problems: list[str] = [] + specs = {spec.role: spec for spec in workflow.input_assignments} + for role in sorted(set(assignments) - set(specs)): + problems.append(f"Unsupported input role for {workflow.key}: {role}") + for spec in workflow.input_assignments: + raw_path = assignments.get(spec.role, "") + if spec.required and not raw_path: + problems.append(f"Missing required input: {spec.label}") + continue + if not raw_path: + continue + path = Path(raw_path) + if spec.argument_name is None: + if not path.exists(): + problems.append(f"{spec.label} does not exist: {path}") + continue + if not path.exists(): + problems.append(f"{spec.label} does not exist: {path}") + continue + if not path.is_file(): + problems.append(f"{spec.label} is not a file: {path}") + continue + if spec.extensions and path.suffix.lower() not in spec.extensions: + problems.append(f"{spec.label} must use one of {', '.join(spec.extensions)}") + try: + if path.stat().st_size == 0: + problems.append(f"{spec.label}: File is empty") + except OSError as exc: + problems.append(f"{spec.label}: Unreadable file: {exc}") + return problems diff --git a/dashboard/file_utils.py b/dashboard/file_utils.py index 3ed3759..c8ac755 100644 --- a/dashboard/file_utils.py +++ b/dashboard/file_utils.py @@ -15,6 +15,9 @@ EXCLUDED_ZIP_PARTS = {"__pycache__", ".pytest_cache", ".mypy_cache", ".ruff_cache", ".git"} +UPLOAD_EXTENSIONS = {".csv", ".tsv", ".xlsx", ".yaml", ".yml", ".json", ".txt"} +_FILENAME_SAFE_CHARS = set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._-") + @dataclass(frozen=True) class DisplayFile: @@ -107,3 +110,98 @@ def human_size(num_bytes: int) -> str: return f"{value:.1f} {unit}" if unit != "B" else f"{int(value)} B" value /= 1024 return f"{num_bytes} B" + + +def sanitize_filename(filename: str) -> str: + """Return a safe filename while preserving a supported extension when present.""" + raw = Path(filename).name.strip().replace(" ", "-") + cleaned = "".join(ch if ch in _FILENAME_SAFE_CHARS else "-" for ch in raw).strip(".-_") + return cleaned or "uploaded-file" + + +def create_upload_dir(repo_root: str | Path, run_id: str, base_dir: str | Path = "dashboard_uploads") -> Path: + """Create a per-run dashboard upload directory under the repository by default.""" + from dashboard.command_builder import sanitize_run_name + + root = Path(repo_root).resolve() + base = Path(base_dir).expanduser() + if not base.is_absolute(): + base = root / base + directory = (base / sanitize_run_name(run_id)).resolve() + directory.mkdir(parents=True, exist_ok=True) + return directory + + +def detect_duplicate_filenames(filenames: Iterable[str]) -> list[str]: + """Return sanitized duplicate upload filenames.""" + seen: set[str] = set() + duplicates: set[str] = set() + for name in filenames: + safe = sanitize_filename(name) + if safe in seen: + duplicates.add(safe) + seen.add(safe) + return sorted(duplicates) + + +def validate_upload_filename(filename: str) -> list[str]: + """Validate a dashboard upload filename without reading content.""" + safe = sanitize_filename(filename) + suffix = Path(safe).suffix.lower() + if suffix not in UPLOAD_EXTENSIONS: + return [f"Unsupported extension for {filename!r}: {suffix or ''}"] + return [] + + +def save_uploaded_file(uploaded_file, upload_dir: str | Path) -> Path: + """Save a Streamlit-style uploaded file into the run upload directory.""" + directory = Path(upload_dir) + directory.mkdir(parents=True, exist_ok=True) + name = sanitize_filename(getattr(uploaded_file, "name", "uploaded-file")) + problems = validate_upload_filename(name) + if problems: + raise ValueError("; ".join(problems)) + target = directory / name + if hasattr(uploaded_file, "getbuffer"): + data = bytes(uploaded_file.getbuffer()) + elif hasattr(uploaded_file, "read"): + data = uploaded_file.read() + else: + data = bytes(uploaded_file) + if not data: + raise ValueError(f"Uploaded file is empty: {name}") + target.write_bytes(data) + return target + + +def validate_existing_file(path: str | Path) -> list[str]: + """Detect basic file problems for saved uploads or selected paths.""" + file_path = Path(path) + problems: list[str] = [] + if not file_path.exists(): + return [f"File does not exist: {file_path}"] + if not file_path.is_file(): + return [f"Path is not a file: {file_path}"] + if file_path.suffix.lower() not in UPLOAD_EXTENSIONS: + problems.append(f"Unsupported extension: {file_path.suffix.lower() or ''}") + try: + if file_path.stat().st_size == 0: + problems.append("File is empty") + except OSError as exc: + problems.append(f"Unreadable file: {exc}") + return problems + + +def preview_table(path: str | Path, max_rows: int = 50, sheet_name: str | int | None = 0): + """Read a bounded preview of CSV/TSV/XLSX files using pandas.""" + import pandas as pd + + file_path = Path(path) + suffix = file_path.suffix.lower() + if suffix == ".csv": + return pd.read_csv(file_path, nrows=max_rows) + if suffix == ".tsv": + return pd.read_csv(file_path, sep="\t", nrows=max_rows) + if suffix == ".xlsx": + return pd.read_excel(file_path, sheet_name=0 if sheet_name is None else sheet_name, nrows=max_rows) + raise ValueError(f"Preview is not supported for {suffix or ''} files") diff --git a/dashboard/registry.py b/dashboard/registry.py index 8a50a8c..fa2097b 100644 --- a/dashboard/registry.py +++ b/dashboard/registry.py @@ -22,6 +22,18 @@ class ArgumentSpec: required: bool = False +@dataclass(frozen=True) +class InputSpec: + """Workflow input role that can be assigned from uploads or selected files.""" + + role: str + label: str + argument_name: str | None = None + description: str = "" + required: bool = False + extensions: tuple[str, ...] = () + + @dataclass(frozen=True) class WorkflowDescriptor: key: str @@ -32,6 +44,7 @@ class WorkflowDescriptor: module_args: tuple[str, ...] = () accepted_arguments: tuple[ArgumentSpec, ...] = () required_inputs: tuple[str, ...] = () + input_assignments: tuple[InputSpec, ...] = () output_dir_arg: str | None = "--outdir" expected_output_folder: str | None = None result_workflow_keys: tuple[str, ...] = field(default_factory=tuple) @@ -85,6 +98,9 @@ class WorkflowDescriptor: ArgumentSpec("method", "--method", "str", "Optimisation method."), ), required_inputs=("input1.csv", "input2.csv"), + input_assignments=( + InputSpec("config", "Config file", "conf", "Optional kinopt config file.", extensions=(".toml", ".yaml", ".yml", ".json")), + ), output_dir_arg="--outdir", expected_output_folder="results/kinopt-local", result_workflow_keys=("kinopt.local",), @@ -102,6 +118,9 @@ class WorkflowDescriptor: ArgumentSpec("loss_type", "--loss_type", "int", "Loss function identifier."), ), required_inputs=("input1.csv", "input3.csv", "input4.csv"), + input_assignments=( + InputSpec("config", "Config file", "conf", "Optional tfopt config file.", extensions=(".toml", ".yaml", ".yml", ".json")), + ), output_dir_arg="--outdir", expected_output_folder="results/tfopt-local", result_workflow_keys=("tfopt.local",), @@ -120,6 +139,12 @@ class WorkflowDescriptor: ArgumentSpec("input_excel_rna", "--input-excel-rna", "path", "RNA input Excel file."), ), required_inputs=("protein Excel", "phosphosite Excel", "RNA Excel"), + input_assignments=( + InputSpec("config", "Config file", "conf", "Optional ProtWise config file.", extensions=(".toml", ".yaml", ".yml", ".json")), + InputSpec("protein_file", "Protein file", "input_excel_protein", "Protein input Excel file.", extensions=(".xlsx",)), + InputSpec("phosphosite_file", "Phosphosite file", "input_excel_psite", "Phosphosite input Excel file.", extensions=(".xlsx",)), + InputSpec("rna_file", "RNA/mRNA file", "input_excel_rna", "RNA input Excel file.", extensions=(".xlsx",)), + ), output_dir_arg="--outdir", expected_output_folder="results/protwise-model", result_workflow_keys=("protwise.runner",), @@ -144,6 +169,17 @@ class WorkflowDescriptor: ArgumentSpec("sensitivity", "--sensitivity", "bool", "Run sensitivity analysis."), ), required_inputs=("kinase network", "TF network", "MS/protein data", "RNA data", "phospho data"), + input_assignments=( + InputSpec("config", "Config file", "conf", "Optional networkmodel config file.", extensions=(".toml", ".yaml", ".yml", ".json")), + InputSpec("kinase_network", "Kinase network file", "kinase_net", "Kinase network CSV/TSV file.", extensions=(".csv", ".tsv")), + InputSpec("tf_network", "TF network file", "tf_net", "TF network CSV/TSV file.", extensions=(".csv", ".tsv")), + InputSpec("protein_file", "Protein/MS file", "ms", "Protein/MS data file.", extensions=(".csv", ".tsv", ".xlsx")), + InputSpec("rna_file", "RNA/mRNA file", "rna", "RNA data file.", extensions=(".csv", ".tsv", ".xlsx")), + InputSpec("phosphosite_file", "Phosphosite file", "phospho", "Phosphoproteomics data file.", extensions=(".csv", ".tsv", ".xlsx")), + InputSpec("previous_kinopt", "Previous KinOpt result", "kinopt", "Previous kinopt Excel result.", extensions=(".xlsx",)), + InputSpec("previous_tfopt", "Previous TFOpt result", "tfopt", "Previous tfopt Excel result.", extensions=(".xlsx",)), + InputSpec("networkmodel_result_dir", "Networkmodel result directory", None, "Reference result directory for browsing; not passed to CLI."), + ), output_dir_arg="--output-dir", expected_output_folder="results/networkmodel", result_workflow_keys=("networkmodel.runner",), @@ -162,6 +198,11 @@ class WorkflowDescriptor: ArgumentSpec("kin_conf", "--kin-conf", "path", "KinOpt config file."), ArgumentSpec("model_conf", "--model-conf", "path", "ProtWise config file."), ), + input_assignments=( + InputSpec("tf_config", "TFOpt config file", "tf_conf", "Config for TFOpt stage.", extensions=(".toml", ".yaml", ".yml", ".json")), + InputSpec("kin_config", "KinOpt config file", "kin_conf", "Config for KinOpt stage.", extensions=(".toml", ".yaml", ".yml", ".json")), + InputSpec("model_config", "ProtWise config file", "model_conf", "Config for ProtWise stage.", extensions=(".toml", ".yaml", ".yml", ".json")), + ), output_dir_arg="--outdir", expected_output_folder="results/phoskintime-all", result_workflow_keys=("phoskintime.all",), diff --git a/docs/dashboard_build_plan.md b/docs/dashboard_build_plan.md index cf987b5..433e7f5 100644 --- a/docs/dashboard_build_plan.md +++ b/docs/dashboard_build_plan.md @@ -381,3 +381,7 @@ The initial dashboard component lives under `dashboard/` and focuses only on bro ### Phase 2 implementation note (June 2026) The dashboard now includes a registered workflow launcher that builds argv-list commands for existing Pixi/Python entry points, previews commands before execution, runs subprocesses from the repository root with `shell=False`, streams merged stdout/stderr into the UI and `console.log`, records launcher provenance, and opens successful run directories in the result browser. Upload/config editing remains out of scope. Interactive cancellation is not exposed yet because reliable Streamlit cancellation needs a persistent background job supervisor; the runner has a cancellation callback boundary for a future supervised implementation. + +### Phase 3 implementation note (June 2026) + +The dashboard now supports no-code setup before launching registered workflows: users can upload supported input/config files into `dashboard_uploads//`, preview CSV/TSV/XLSX data, assign files to workflow-specific input roles, edit structured parameters based on the actual CLI flags, validate basic file problems, and save or download JSON/YAML presets. These selections are converted into the existing argv-list command builder so execution still goes through the original CLI modules rather than dashboard-side scientific logic. diff --git a/tests/dashboard/test_command_builder.py b/tests/dashboard/test_command_builder.py index d2608b3..5289b04 100644 --- a/tests/dashboard/test_command_builder.py +++ b/tests/dashboard/test_command_builder.py @@ -59,3 +59,27 @@ def test_pixi_environment_selection_reads_defined_environments(tmp_path): pixi.write_text('[environments]\ndefault = {}\ndev = {}\nviz = {}\n', encoding="utf-8") assert pixi_environments(pixi) == ["default", "dev", "viz"] + + +def test_command_generation_from_assigned_inputs(tmp_path): + kinase = tmp_path / "kinase.csv" + config = tmp_path / "config.toml" + kinase.write_text("a\n", encoding="utf-8") + config.write_text("[x]\n", encoding="utf-8") + + built = build_workflow_command( + "networkmodel", + repo_root=tmp_path, + run_name="assigned", + use_pixi=False, + input_assignments={"kinase_network": kinase, "config": config, "networkmodel_result_dir": tmp_path}, + ) + + assert ["--kinase-net", str(kinase)] == built.command[built.command.index("--kinase-net"):built.command.index("--kinase-net") + 2] + assert ["--conf", str(config)] == built.command[built.command.index("--conf"):built.command.index("--conf") + 2] + assert "networkmodel_result_dir" not in built.command + + +def test_unsupported_input_roles_are_not_generated(tmp_path): + with pytest.raises(ValueError, match="Unsupported input roles"): + build_workflow_command("networkmodel", repo_root=tmp_path, input_assignments={"shell": "bad"}) diff --git a/tests/dashboard/test_config_utils.py b/tests/dashboard/test_config_utils.py new file mode 100644 index 0000000..fc0e30e --- /dev/null +++ b/tests/dashboard/test_config_utils.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +import json + +from dashboard.config_utils import DashboardSelection, load_preset, parse_config_file, save_preset + + +def test_parse_json_yaml_and_text_configs(tmp_path): + json_path = tmp_path / "config.json" + yaml_path = tmp_path / "config.yaml" + text_path = tmp_path / "notes.txt" + json_path.write_text('{"alpha": 1}', encoding="utf-8") + yaml_path.write_text("alpha: 2\nflag: true\n", encoding="utf-8") + text_path.write_text("hello", encoding="utf-8") + + assert parse_config_file(json_path) == {"alpha": 1} + assert parse_config_file(yaml_path)["alpha"] == 2 + assert parse_config_file(text_path) == "hello" + + +def test_save_and_load_json_preset(tmp_path): + selection = DashboardSelection( + workflow_key="networkmodel", + run_name="run1", + pixi_environment="dev", + arguments={"cores": "2"}, + input_assignments={"kinase_network": "kin.csv"}, + ) + path = save_preset(selection, tmp_path / "preset.json") + + loaded = load_preset(path) + + assert json.loads(path.read_text(encoding="utf-8"))["workflow_key"] == "networkmodel" + assert loaded.workflow_key == selection.workflow_key + assert loaded.arguments == {"cores": "2"} diff --git a/tests/dashboard/test_file_utils.py b/tests/dashboard/test_file_utils.py index 64d26f6..1d1d95b 100644 --- a/tests/dashboard/test_file_utils.py +++ b/tests/dashboard/test_file_utils.py @@ -47,3 +47,69 @@ def test_filter_by_suffix_and_human_size(tmp_path): def test_resolve_directory_rejects_missing_path(tmp_path): with pytest.raises(FileNotFoundError): resolve_directory(tmp_path / "missing") + +from io import BytesIO + + +from dashboard.file_utils import ( + create_upload_dir, + detect_duplicate_filenames, + preview_table, + sanitize_filename, + save_uploaded_file, + validate_existing_file, + validate_upload_filename, +) + + +class DummyUpload: + def __init__(self, name: str, data: bytes): + self.name = name + self._data = data + + def getbuffer(self): + return memoryview(self._data) + + +def test_upload_path_creation_and_filename_sanitization(tmp_path): + upload_dir = create_upload_dir(tmp_path, "../Bad Run!!") + + assert upload_dir == tmp_path / "dashboard_uploads" / "Bad-Run" + assert upload_dir.is_dir() + assert sanitize_filename("../bad file.csv") == "bad-file.csv" + + +def test_save_uploaded_file_rejects_empty_and_unsupported(tmp_path): + upload_dir = create_upload_dir(tmp_path, "run") + + with pytest.raises(ValueError, match="empty"): + save_uploaded_file(DummyUpload("empty.csv", b""), upload_dir) + assert validate_upload_filename("bad.exe") + + +def test_duplicate_filename_detection_uses_sanitized_names(): + assert detect_duplicate_filenames(["a file.csv", "a-file.csv"]) == ["a-file.csv"] + + +def test_preview_csv_tsv_xlsx_helpers(tmp_path): + pd = pytest.importorskip("pandas") + csv = tmp_path / "a.csv" + tsv = tmp_path / "a.tsv" + xlsx = tmp_path / "a.xlsx" + csv.write_text("a,b\n1,2\n", encoding="utf-8") + tsv.write_text("a\tb\n3\t4\n", encoding="utf-8") + pd.DataFrame({"a": [5], "b": [6]}).to_excel(xlsx, index=False) + + assert preview_table(csv).iloc[0].to_dict() == {"a": 1, "b": 2} + assert preview_table(tsv).iloc[0].to_dict() == {"a": 3, "b": 4} + assert preview_table(xlsx).iloc[0].to_dict() == {"a": 5, "b": 6} + + +def test_invalid_existing_file_handling(tmp_path): + empty = tmp_path / "empty.csv" + empty.write_text("", encoding="utf-8") + unsupported = tmp_path / "x.exe" + unsupported.write_bytes(b"x") + + assert "File is empty" in validate_existing_file(empty) + assert any("Unsupported extension" in problem for problem in validate_existing_file(unsupported)) diff --git a/tests/dashboard/test_upload_validation.py b/tests/dashboard/test_upload_validation.py new file mode 100644 index 0000000..09a5894 --- /dev/null +++ b/tests/dashboard/test_upload_validation.py @@ -0,0 +1,36 @@ +from __future__ import annotations + +from dashboard.components.validation_panel import validate_dashboard_setup +from dashboard.config_utils import validate_input_assignments +from dashboard.registry import get_workflow + + +def test_validate_input_assignments_allows_supported_config_toml(tmp_path): + config = tmp_path / "config.toml" + config.write_text("[x]\ny = 1\n", encoding="utf-8") + workflow = get_workflow("networkmodel") + + assert validate_input_assignments(workflow, {"config": str(config)}) == [] + + +def test_validate_input_assignments_reports_bad_extension(tmp_path): + bad = tmp_path / "kinase.xlsx" + bad.write_bytes(b"x") + workflow = get_workflow("networkmodel") + + problems = validate_input_assignments(workflow, {"kinase_network": str(bad)}) + + assert any("must use one of" in problem for problem in problems) + + +def test_validation_panel_helper_reports_duplicate_and_unknown_role(tmp_path): + one = tmp_path / "a file.csv" + two = tmp_path / "a-file.csv" + one.write_text("a\n1\n", encoding="utf-8") + two.write_text("a\n2\n", encoding="utf-8") + workflow = get_workflow("tfopt-local") + + problems = validate_dashboard_setup(workflow, [one, two], {"unknown": str(one)}) + + assert any("Duplicate filenames" in problem for problem in problems) + assert any("Unsupported input role" in problem for problem in problems) From 992d58dc1a2a2294e504208252e0dc856b4ceeef Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Wed, 10 Jun 2026 18:48:23 +0530 Subject: [PATCH 07/42] Integrate workflow-specific dashboard panels --- dashboard/app.py | 6 +- dashboard/components/analysis_panel.py | 15 +++ dashboard/components/workflow_tabs.py | 23 ++++ dashboard/workflow_panels/__init__.py | 1 + dashboard/workflow_panels/analysis.py | 125 ++++++++++++++++++++++ dashboard/workflow_panels/common.py | 33 ++++++ dashboard/workflow_panels/kinopt.py | 54 ++++++++++ dashboard/workflow_panels/networkmodel.py | 65 +++++++++++ dashboard/workflow_panels/protwise.py | 45 ++++++++ dashboard/workflow_panels/tfopt.py | 44 ++++++++ docs/Documentation/scripts.md | 4 + docs/dashboard_build_plan.md | 4 + tests/dashboard/test_workflow_panels.py | 89 +++++++++++++++ 13 files changed, 507 insertions(+), 1 deletion(-) create mode 100644 dashboard/components/analysis_panel.py create mode 100644 dashboard/components/workflow_tabs.py create mode 100644 dashboard/workflow_panels/__init__.py create mode 100644 dashboard/workflow_panels/analysis.py create mode 100644 dashboard/workflow_panels/common.py create mode 100644 dashboard/workflow_panels/kinopt.py create mode 100644 dashboard/workflow_panels/networkmodel.py create mode 100644 dashboard/workflow_panels/protwise.py create mode 100644 dashboard/workflow_panels/tfopt.py create mode 100644 tests/dashboard/test_workflow_panels.py diff --git a/dashboard/app.py b/dashboard/app.py index 9e35a4e..c235267 100644 --- a/dashboard/app.py +++ b/dashboard/app.py @@ -15,6 +15,7 @@ from dashboard.components.upload_panel import render_upload_panel from dashboard.components.validation_panel import render_validation_panel, validate_dashboard_setup from dashboard.components.workflow_selector import render_workflow_selector +from dashboard.components.workflow_tabs import render_workflow_tabs from dashboard.config_utils import DashboardSelection from dashboard.result_parser import discover_result_directory from dashboard.runner import log_tail, run_built_command @@ -55,6 +56,7 @@ def _render_browser_panel(default_directory: Path | None = None) -> None: if not inventory.has_content: st.warning("This directory exists, but no standard PhosKinTime result files were discovered.") render_result_browser(inventory) + render_workflow_tabs(inventory.root) def _render_launcher_panel() -> None: @@ -132,7 +134,9 @@ def _render_launcher_panel() -> None: elif final_event.status == "success": st.success("Run completed. The result directory is shown below.") try: - render_result_browser(discover_result_directory(built.outdir)) + inventory = discover_result_directory(built.outdir) + render_result_browser(inventory) + render_workflow_tabs(inventory.root) except (FileNotFoundError, NotADirectoryError) as exc: st.warning(f"Run finished, but the result directory could not be opened: {exc}") diff --git a/dashboard/components/analysis_panel.py b/dashboard/components/analysis_panel.py new file mode 100644 index 0000000..fb04fc0 --- /dev/null +++ b/dashboard/components/analysis_panel.py @@ -0,0 +1,15 @@ +from __future__ import annotations + +from pathlib import Path + +from dashboard.workflow_panels.analysis import ANALYSIS_TASKS, build_analysis_command, discover_analysis_outputs + + +def render_analysis_panel(result_dir: str | Path) -> None: + """Compatibility wrapper for rendering advanced analysis controls.""" + from dashboard.workflow_panels.analysis import render + + render(result_dir) + + +__all__ = ["ANALYSIS_TASKS", "build_analysis_command", "discover_analysis_outputs", "render_analysis_panel"] diff --git a/dashboard/components/workflow_tabs.py b/dashboard/components/workflow_tabs.py new file mode 100644 index 0000000..0e43324 --- /dev/null +++ b/dashboard/components/workflow_tabs.py @@ -0,0 +1,23 @@ +from __future__ import annotations + +from pathlib import Path + + +def render_workflow_tabs(result_dir: str | Path) -> None: + """Render workflow-specific tabs for a selected result directory.""" + import streamlit as st + + from dashboard.workflow_panels import analysis, kinopt, networkmodel, protwise, tfopt + + root = Path(result_dir) + tabs = st.tabs(["KinOpt", "TFOpt", "ProtWise", "Networkmodel", "Advanced analysis"]) + with tabs[0]: + kinopt.render(root) + with tabs[1]: + tfopt.render(root) + with tabs[2]: + protwise.render(root) + with tabs[3]: + networkmodel.render(root) + with tabs[4]: + analysis.render(root) diff --git a/dashboard/workflow_panels/__init__.py b/dashboard/workflow_panels/__init__.py new file mode 100644 index 0000000..2968679 --- /dev/null +++ b/dashboard/workflow_panels/__init__.py @@ -0,0 +1 @@ +"""Workflow-specific dashboard panels.""" diff --git a/dashboard/workflow_panels/analysis.py b/dashboard/workflow_panels/analysis.py new file mode 100644 index 0000000..14396d4 --- /dev/null +++ b/dashboard/workflow_panels/analysis.py @@ -0,0 +1,125 @@ +from __future__ import annotations + +from dataclasses import dataclass, field +from pathlib import Path +from typing import Any + +from common.results import ensure_result_dir + + +@dataclass(frozen=True) +class AnalysisTask: + key: str + label: str + description: str + script: str + arguments: dict[str, str] = field(default_factory=dict) + + +ANALYSIS_TASKS: dict[str, AnalysisTask] = { + "tf-kin-counts": AnalysisTask( + "tf-kin-counts", + "TF/Kin counts", + "Summarise TF and kinase psite/target counts from TFOpt and KinOpt workbooks.", + "scripts/analyze_tf_kin_counts.py", + {"tfopt_xlsx": "--tfopt-xlsx", "kinopt_xlsx": "--kinopt-xlsx", "out_dir": "--out-dir"}, + ), + "curve-similarity": AnalysisTask( + "curve-similarity", + "Curve similarity / Fréchet distance", + "Run the existing curve similarity backend for TFOpt and KinOpt workbooks.", + "scripts/curve_similarity.py", + {"tfopt_xlsx": "--tfopt-xlsx", "kinopt_xlsx": "--kinopt-xlsx", "out_dir": "--out-dir"}, + ), + "export-subnetworks": AnalysisTask( + "export-subnetworks", + "Export subnetworks", + "Run the existing subnetworks export script on kinase and TF network input files.", + "scripts/export_subnetworks.py", + {"input2": "--input2", "input4": "--input4", "out_dir": "--outdir", "hops": "--hops"}, + ), + "protein-accumulators": AnalysisTask( + "protein-accumulators", + "Protein accumulators", + "Detect protein-vs-RNA accumulator patterns from networkmodel prediction CSVs.", + "scripts/find_protein_accumulators.py", + {"prot": "--prot", "rna": "--rna", "threshold": "--threshold"}, + ), + "mechanistic-insights": AnalysisTask( + "mechanistic-insights", + "Mechanistic insights", + "Run the existing mechanistic insights script; inputs are passed through its CLI.", + "scripts/mechanistic_insights.py", + {"results_dir": "--results-dir", "out_dir": "--out-dir"}, + ), + "temporal-sensitivity": AnalysisTask( + "temporal-sensitivity", + "Temporal sensitivity", + "Run global temporal sensitivity analysis for an existing networkmodel results directory.", + "scripts/temporal_sensitivity.py", + {"results_dir": "--results-dir", "samples": "--samples"}, + ), +} + + +def analysis_output_dir(result_dir: str | Path, task_key: str) -> Path: + """Create a dashboard-standard artifacts/reports area for analysis outputs.""" + paths = ensure_result_dir(result_dir) + out_dir = paths["artifacts"] / "analysis" / task_key + out_dir.mkdir(parents=True, exist_ok=True) + return out_dir + + +def build_analysis_command(task_key: str, values: dict[str, Any], result_dir: str | Path) -> list[str]: + """Build a safe argv-list command for an existing analysis script.""" + if task_key not in ANALYSIS_TASKS: + raise KeyError(f"Unknown analysis task: {task_key}") + task = ANALYSIS_TASKS[task_key] + command = ["python", task.script] + merged = dict(values) + if "out_dir" in task.arguments and not merged.get("out_dir"): + merged["out_dir"] = analysis_output_dir(result_dir, task_key) + elif task_key in {"protein-accumulators", "temporal-sensitivity"}: + analysis_output_dir(result_dir, task_key) + for name, flag in task.arguments.items(): + value = merged.get(name) + if value is None or value == "": + continue + command.extend([flag, str(value)]) + return command + + +def discover_analysis_outputs(result_dir: str | Path) -> dict[str, list[Path]]: + """Discover outputs previously written by dashboard-triggered analyses.""" + root = Path(result_dir) + base = root / "artifacts" / "analysis" + if not base.is_dir(): + return {} + return { + task_dir.name: sorted(path for path in task_dir.rglob("*") if path.is_file()) + for task_dir in sorted(base.iterdir()) + if task_dir.is_dir() + } + + +def render(root: str | Path) -> None: + import streamlit as st + + st.subheader("Advanced analyses") + st.caption("Analyses are not run automatically. Build a command, review it, and run via the launcher or terminal when appropriate.") + task = st.selectbox("Analysis", list(ANALYSIS_TASKS.values()), format_func=lambda item: item.label) + st.write(task.description) + values: dict[str, Any] = {} + for name in task.arguments: + if name == "out_dir": + continue + values[name] = st.text_input(name.replace("_", " "), value="") + try: + command = build_analysis_command(task.key, values, root) + st.code(" ".join(command), language="bash") + except Exception as exc: + st.error(str(exc)) + outputs = discover_analysis_outputs(root) + if outputs: + st.write("Existing analysis outputs") + st.json({key: [str(path) for path in paths] for key, paths in outputs.items()}) diff --git a/dashboard/workflow_panels/common.py b/dashboard/workflow_panels/common.py new file mode 100644 index 0000000..95249be --- /dev/null +++ b/dashboard/workflow_panels/common.py @@ -0,0 +1,33 @@ +from __future__ import annotations + +from dataclasses import dataclass, field +from pathlib import Path + +from dashboard.file_utils import DisplayFile +from dashboard.result_parser import discover_result_directory + + +@dataclass(frozen=True) +class WorkflowPanelData: + root: Path + primary_result: Path | None = None + tables: dict[str, Path] = field(default_factory=dict) + plots: list[DisplayFile] = field(default_factory=list) + reports: list[DisplayFile] = field(default_factory=list) + artifacts: list[DisplayFile] = field(default_factory=list) + messages: list[str] = field(default_factory=list) + + @property + def has_content(self) -> bool: + return bool(self.primary_result or self.tables or self.plots or self.reports or self.artifacts) + + +def _first_existing(root: Path, names: tuple[str, ...]) -> Path | None: + candidates = [] + for name in names: + candidates.extend([root / name, root / "tables" / name, root / "artifacts" / name]) + return next((path for path in candidates if path.is_file()), None) + + +def _inventory(root: str | Path): + return discover_result_directory(root) diff --git a/dashboard/workflow_panels/kinopt.py b/dashboard/workflow_panels/kinopt.py new file mode 100644 index 0000000..fb130c5 --- /dev/null +++ b/dashboard/workflow_panels/kinopt.py @@ -0,0 +1,54 @@ +from __future__ import annotations + +from pathlib import Path + +from dashboard.workflow_panels.common import WorkflowPanelData, _first_existing, _inventory + +KINOPT_SHEETS = ("Alpha Values", "Beta Values", "Observed", "Estimated", "Residuals", "Summary") + + +def discover_kinopt_panel(root: str | Path) -> WorkflowPanelData: + """Discover KinOpt result files and generated displays.""" + root = Path(root).resolve() + inventory = _inventory(root) + result = _first_existing(root, ("kinopt_results.xlsx",)) + tables = {"kinopt_results": result} if result else {} + messages = [] if result else ["No kinopt_results.xlsx file found in the result directory or tables/."] + return WorkflowPanelData(root=root, primary_result=result, tables=tables, plots=inventory.plots, reports=inventory.reports, artifacts=inventory.artifacts, messages=messages) + + +def render(root: str | Path) -> None: + """Render KinOpt-specific outputs without recomputing analyses.""" + import pandas as pd + import streamlit as st + + data = discover_kinopt_panel(root) + st.subheader("KinOpt panel") + for message in data.messages: + st.info(message) + if data.primary_result: + st.caption(f"Workbook: `{data.primary_result}`") + for sheet in KINOPT_SHEETS: + try: + df = pd.read_excel(data.primary_result, sheet_name=sheet) + except Exception: + continue + with st.expander(sheet, expanded=sheet in {"Alpha Values", "Beta Values"}): + st.dataframe(df, use_container_width=True) + _render_existing_media(data) + + +def _render_existing_media(data: WorkflowPanelData) -> None: + import streamlit as st + + if data.plots: + st.write("Existing plots") + for item in data.plots[:12]: + if item.suffix in {".png", ".jpg", ".jpeg", ".svg"}: + st.image(str(item.path), caption=item.relative_path, use_container_width=True) + else: + st.write(item.relative_path) + if data.reports: + st.write("Reports") + for item in data.reports: + st.write(item.relative_path) diff --git a/dashboard/workflow_panels/networkmodel.py b/dashboard/workflow_panels/networkmodel.py new file mode 100644 index 0000000..89dfffb --- /dev/null +++ b/dashboard/workflow_panels/networkmodel.py @@ -0,0 +1,65 @@ +from __future__ import annotations + +from pathlib import Path + +from dashboard.workflow_panels.common import WorkflowPanelData, _first_existing, _inventory + +NETWORK_TABLES = ( + "scalar_objective.csv", + "convergence_history.csv", + "pred_prot_picked.csv", + "pred_rna_picked.csv", + "pred_phospho_picked.csv", + "picked_objectives.json", +) + + +def discover_networkmodel_panel(root: str | Path) -> WorkflowPanelData: + """Discover networkmodel bundle, scalar objective, predictions, and inference outputs.""" + root = Path(root).resolve() + inventory = _inventory(root) + bundle = _first_existing(root, ("dashboard_bundle.pkl", "networkmodel_dashboard_bundle.pkl")) + tables = {} + for name in NETWORK_TABLES: + found = _first_existing(root, (name,)) + if found: + tables[name] = found + for item in inventory.tables: + if item.relative_path.startswith(("optimization/", "profiles/", "posterior/")): + tables[item.relative_path] = item.path + messages = [] if (bundle or tables or inventory.plots) else ["No networkmodel bundle, scalar objective, predictions, or inference outputs were found."] + return WorkflowPanelData(root=root, primary_result=bundle, tables=tables, plots=inventory.plots, reports=inventory.reports, artifacts=inventory.artifacts, messages=messages) + + +def render(root: str | Path) -> None: + import pandas as pd + import streamlit as st + + data = discover_networkmodel_panel(root) + st.subheader("Networkmodel panel") + for message in data.messages: + st.info(message) + if data.primary_result: + st.success(f"Dashboard bundle found: {data.primary_result}") + try: + from networkmodel.dashboard_bundle import load_dashboard_bundle + bundle = load_dashboard_bundle(data.root) + st.json({"bundle_keys": sorted(bundle.keys())}) + except Exception as exc: + st.warning(f"Bundle exists but could not be loaded here: {exc}") + for label, path in data.tables.items(): + with st.expander(label, expanded=label == "scalar_objective.csv"): + try: + if path.suffix == ".csv": + st.dataframe(pd.read_csv(path), use_container_width=True) + elif path.suffix == ".json": + st.json(__import__("json").loads(path.read_text(encoding="utf-8"))) + except Exception as exc: + st.warning(f"Could not read {label}: {exc}") + if data.plots: + st.write("Networkmodel plots") + for item in data.plots[:12]: + if item.suffix in {".png", ".jpg", ".jpeg", ".svg"}: + st.image(str(item.path), caption=item.relative_path, use_container_width=True) + else: + st.write(item.relative_path) diff --git a/dashboard/workflow_panels/protwise.py b/dashboard/workflow_panels/protwise.py new file mode 100644 index 0000000..05aa56f --- /dev/null +++ b/dashboard/workflow_panels/protwise.py @@ -0,0 +1,45 @@ +from __future__ import annotations + +from pathlib import Path + +from dashboard.workflow_panels.common import WorkflowPanelData, _inventory + +PROTWISE_KEYWORDS = ("fit", "residual", "sensitivity", "prediction", "model_error", "regularization") + + +def discover_protwise_panel(root: str | Path) -> WorkflowPanelData: + """Discover ProtWise tables, plots, sensitivity outputs, and reports.""" + root = Path(root).resolve() + inventory = _inventory(root) + tables = { + item.relative_path: item.path + for item in inventory.tables + if any(key in item.name.lower() for key in PROTWISE_KEYWORDS) or item.suffix in {".xlsx", ".csv"} + } + plots = [item for item in inventory.plots if any(key in item.name.lower() for key in PROTWISE_KEYWORDS)] or inventory.plots + messages = [] if (tables or plots or inventory.reports) else ["No ProtWise-specific outputs were discovered; run the model first or select another result directory."] + return WorkflowPanelData(root=root, tables=tables, plots=plots, reports=inventory.reports, artifacts=inventory.artifacts, messages=messages) + + +def render(root: str | Path) -> None: + import pandas as pd + import streamlit as st + + data = discover_protwise_panel(root) + st.subheader("ProtWise panel") + for message in data.messages: + st.info(message) + for label, path in data.tables.items(): + with st.expander(label): + try: + if path.suffix == ".csv": + st.dataframe(pd.read_csv(path), use_container_width=True) + elif path.suffix in {".xlsx", ".xls"}: + st.dataframe(pd.read_excel(path), use_container_width=True) + except Exception as exc: + st.warning(f"Could not read {label}: {exc}") + for item in data.plots[:12]: + if item.suffix in {".png", ".jpg", ".jpeg", ".svg"}: + st.image(str(item.path), caption=item.relative_path, use_container_width=True) + else: + st.write(item.relative_path) diff --git a/dashboard/workflow_panels/tfopt.py b/dashboard/workflow_panels/tfopt.py new file mode 100644 index 0000000..4e588a2 --- /dev/null +++ b/dashboard/workflow_panels/tfopt.py @@ -0,0 +1,44 @@ +from __future__ import annotations + +from pathlib import Path + +from dashboard.workflow_panels.common import WorkflowPanelData, _first_existing, _inventory + +TFOPT_SHEETS = ("Alpha Values", "Beta Values", "Observed", "Estimated", "Residuals", "Optimization Results") + + +def discover_tfopt_panel(root: str | Path) -> WorkflowPanelData: + """Discover TFOpt result files and generated displays.""" + root = Path(root).resolve() + inventory = _inventory(root) + result = _first_existing(root, ("tfopt_results.xlsx",)) + tables = {"tfopt_results": result} if result else {} + messages = [] if result else ["No tfopt_results.xlsx file found in the result directory or tables/."] + return WorkflowPanelData(root=root, primary_result=result, tables=tables, plots=inventory.plots, reports=inventory.reports, artifacts=inventory.artifacts, messages=messages) + + +def render(root: str | Path) -> None: + """Render TFOpt-specific outputs without recomputing analyses.""" + import pandas as pd + import streamlit as st + + data = discover_tfopt_panel(root) + st.subheader("TFOpt panel") + for message in data.messages: + st.info(message) + if data.primary_result: + st.caption(f"Workbook: `{data.primary_result}`") + for sheet in TFOPT_SHEETS: + try: + df = pd.read_excel(data.primary_result, sheet_name=sheet) + except Exception: + continue + with st.expander(sheet, expanded=sheet in {"Alpha Values", "Beta Values"}): + st.dataframe(df, use_container_width=True) + if data.plots: + st.write("Existing plots and latent/dominance/knockout exports") + for item in data.plots[:12]: + if item.suffix in {".png", ".jpg", ".jpeg", ".svg"}: + st.image(str(item.path), caption=item.relative_path, use_container_width=True) + else: + st.write(item.relative_path) diff --git a/docs/Documentation/scripts.md b/docs/Documentation/scripts.md index 59f2f8f..1d0c974 100644 --- a/docs/Documentation/scripts.md +++ b/docs/Documentation/scripts.md @@ -224,3 +224,7 @@ High sample counts significantly increase computation time. ## Dashboard-ready output directories Major backend workflows accept an explicit `--outdir`/`--output-dir` option so automated tools and the planned no-code dashboard can discover outputs consistently. A run directory contains `metadata.json`, `command.txt`, `console.log`, `config_resolved.yaml` when applicable, and the standard `tables/`, `plots/`, `logs/`, `reports/`, and `artifacts/` subdirectories. Legacy filenames are retained at the run-directory root where existing scripts or documentation rely on them, with dashboard-facing copies mirrored into the standard subfolders. + +## Unified dashboard integration and legacy script status + +The unified dashboard now provides workflow-specific result panels for KinOpt, TFOpt, ProtWise, Networkmodel, and advanced analyses. Legacy visualization/readout scripts such as `kinopt_network_viz.py`, `tfopt_network_viz.py`, `kinopt_network_readout.py`, and `tfopt_network_readout.py` are retained for batch reproducibility, but interactive exploration should prefer the unified dashboard panels and the existing `app/kinopt.py` / `app/tfopt.py` logic where available. Analysis scripts remain callable backends; the dashboard builds parameterized commands and writes outputs under the selected run directory instead of duplicating scientific computations in Streamlit. diff --git a/docs/dashboard_build_plan.md b/docs/dashboard_build_plan.md index 433e7f5..8d0e1d5 100644 --- a/docs/dashboard_build_plan.md +++ b/docs/dashboard_build_plan.md @@ -385,3 +385,7 @@ The dashboard now includes a registered workflow launcher that builds argv-list ### Phase 3 implementation note (June 2026) The dashboard now supports no-code setup before launching registered workflows: users can upload supported input/config files into `dashboard_uploads//`, preview CSV/TSV/XLSX data, assign files to workflow-specific input roles, edit structured parameters based on the actual CLI flags, validate basic file problems, and save or download JSON/YAML presets. These selections are converted into the existing argv-list command builder so execution still goes through the original CLI modules rather than dashboard-side scientific logic. + +### Phase 4 implementation note (June 2026) + +Workflow-specific dashboard panels now live under `dashboard/workflow_panels/` for KinOpt, TFOpt, ProtWise, Networkmodel, and advanced analyses. The panels discover and display existing workbooks, CSVs, plots, reports, bundles, and inference outputs from the selected result directory while leaving model fitting, ODE solving, optimization, and expensive analyses in the existing backend scripts/CLI modules. Advanced analyses are exposed as parameterized command builders and are not executed automatically on page load. diff --git a/tests/dashboard/test_workflow_panels.py b/tests/dashboard/test_workflow_panels.py new file mode 100644 index 0000000..1f05009 --- /dev/null +++ b/tests/dashboard/test_workflow_panels.py @@ -0,0 +1,89 @@ +from __future__ import annotations + +from dashboard.workflow_panels.analysis import build_analysis_command, discover_analysis_outputs +from dashboard.workflow_panels.kinopt import discover_kinopt_panel +from dashboard.workflow_panels.networkmodel import discover_networkmodel_panel +from dashboard.workflow_panels.protwise import discover_protwise_panel +from dashboard.workflow_panels.tfopt import discover_tfopt_panel + + +def _standard_dirs(root): + for name in ("tables", "plots", "logs", "reports", "artifacts"): + (root / name).mkdir(parents=True, exist_ok=True) + + +def test_kinopt_and_tfopt_panel_discovery(tmp_path): + kin = tmp_path / "kin" + tf = tmp_path / "tf" + _standard_dirs(kin) + _standard_dirs(tf) + (kin / "tables" / "kinopt_results.xlsx").write_bytes(b"xlsx") + (kin / "plots" / "fit.png").write_bytes(b"png") + (tf / "tfopt_results.xlsx").write_bytes(b"xlsx") + + kin_data = discover_kinopt_panel(kin) + tf_data = discover_tfopt_panel(tf) + + assert kin_data.primary_result == kin.resolve() / "tables" / "kinopt_results.xlsx" + assert len(kin_data.plots) == 1 + assert tf_data.primary_result == tf.resolve() / "tfopt_results.xlsx" + assert not tf_data.messages + + +def test_missing_files_do_not_crash_panel_discovery(tmp_path): + root = tmp_path / "empty" + _standard_dirs(root) + + kin_data = discover_kinopt_panel(root) + tf_data = discover_tfopt_panel(root) + prot_data = discover_protwise_panel(root) + net_data = discover_networkmodel_panel(root) + + assert kin_data.messages + assert tf_data.messages + assert prot_data.messages + assert net_data.messages + + +def test_protwise_and_networkmodel_discovery(tmp_path): + prot = tmp_path / "protwise" + net = tmp_path / "network" + _standard_dirs(prot) + _standard_dirs(net) + (prot / "tables" / "fit_residuals.csv").write_text("a\n1\n", encoding="utf-8") + (prot / "plots" / "sensitivity.png").write_bytes(b"png") + (net / "scalar_objective.csv").write_text("scalar_objective\n1\n", encoding="utf-8") + (net / "pred_prot_picked.csv").write_text("protein,pred_fc\nA,1\n", encoding="utf-8") + (net / "artifacts" / "dashboard_bundle.pkl").write_bytes(b"bundle") + (net / "optimization").mkdir() + (net / "optimization" / "best_fit.csv").write_text("x\n1\n", encoding="utf-8") + + prot_data = discover_protwise_panel(prot) + net_data = discover_networkmodel_panel(net) + + assert "tables/fit_residuals.csv" in prot_data.tables + assert len(prot_data.plots) == 1 + assert net_data.primary_result == net.resolve() / "artifacts" / "dashboard_bundle.pkl" + assert "scalar_objective.csv" in net_data.tables + assert "optimization/best_fit.csv" in net_data.tables + + +def test_analysis_command_wrapper_and_output_discovery(tmp_path): + root = tmp_path / "run" + _standard_dirs(root) + command = build_analysis_command( + "export-subnetworks", + {"input2": "input2.csv", "input4": "input4.csv", "hops": "auto"}, + root, + ) + + assert command[:2] == ["python", "scripts/export_subnetworks.py"] + assert "--input2" in command + assert "--outdir" in command + outdir = root / "artifacts" / "analysis" / "export-subnetworks" + assert str(outdir) in command + (outdir / "index.csv").write_text("x\n", encoding="utf-8") + + outputs = discover_analysis_outputs(root) + + assert outputs["export-subnetworks"] == [outdir / "index.csv"] From fa8ba1b37c66fdc75f7217fb256d48c37adfd4be Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Wed, 10 Jun 2026 22:16:54 +0530 Subject: [PATCH 08/42] Add dashboard tests and documentation --- .gitignore | 2 + dashboard/app.py | 7 +- dashboard/components/command_preview.py | 4 +- dashboard/components/config_panel.py | 3 +- dashboard/components/console_panel.py | 8 +- dashboard/components/download_panel.py | 12 +- dashboard/components/input_preview.py | 12 +- dashboard/components/log_viewer.py | 6 +- dashboard/components/metadata_viewer.py | 6 +- dashboard/components/plot_viewer.py | 6 +- dashboard/components/preset_panel.py | 9 +- dashboard/components/report_viewer.py | 6 +- dashboard/components/result_browser.py | 8 +- dashboard/components/run_status.py | 6 +- dashboard/components/table_viewer.py | 21 ++- dashboard/components/upload_panel.py | 5 +- dashboard/components/workflow_selector.py | 8 +- docs/Documentation/dashboard.md | 6 + docs/Documentation/no_code_dashboard.md | 160 ++++++++++++++++++++++ docs/dashboard_build_plan.md | 5 + docs/index.md | 5 + pixi.toml | 1 + tests/dashboard/test_file_utils.py | 9 ++ tests/dashboard/test_git_hygiene.py | 24 ++++ tests/dashboard/test_importability.py | 20 +++ 25 files changed, 311 insertions(+), 48 deletions(-) create mode 100644 docs/Documentation/no_code_dashboard.md create mode 100644 tests/dashboard/test_git_hygiene.py create mode 100644 tests/dashboard/test_importability.py diff --git a/.gitignore b/.gitignore index 43848bd..d989501 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,5 @@ site/ # Dashboard uploads and local archives /dashboard_uploads/ *.zip +/results/ +/.streamlit/ diff --git a/dashboard/app.py b/dashboard/app.py index c235267..9591079 100644 --- a/dashboard/app.py +++ b/dashboard/app.py @@ -2,7 +2,6 @@ from pathlib import Path -import streamlit as st from dashboard.command_builder import build_workflow_command, sanitize_run_name from dashboard.components.command_preview import render_command_preview @@ -32,6 +31,8 @@ def _candidate_result_dirs(base: Path) -> list[Path]: def _render_browser_panel(default_directory: Path | None = None) -> None: + import streamlit as st + with st.sidebar: st.header("Result directory") default_base = default_directory.parent if default_directory else Path("results") @@ -60,6 +61,8 @@ def _render_browser_panel(default_directory: Path | None = None) -> None: def _render_launcher_panel() -> None: + import streamlit as st + st.header("Workflow launcher") st.write("Construct, preview, and run registered PhosKinTime workflows using existing CLI modules.") render_cancellation_note() @@ -142,6 +145,8 @@ def _render_launcher_panel() -> None: def main() -> None: + import streamlit as st + st.set_page_config(page_title="PhosKinTime Dashboard", layout="wide") st.title("PhosKinTime Dashboard") st.write("Browse existing result directories or launch registered CLI workflows without reimplementing scientific logic.") diff --git a/dashboard/components/command_preview.py b/dashboard/components/command_preview.py index 2f8eee2..aff903b 100644 --- a/dashboard/components/command_preview.py +++ b/dashboard/components/command_preview.py @@ -1,12 +1,12 @@ from __future__ import annotations -import streamlit as st - from dashboard.command_builder import BuiltCommand def render_command_preview(built: BuiltCommand) -> None: """Show an exact command preview before execution.""" + import streamlit as st + st.subheader("Command preview") st.code(built.preview, language="bash") with st.expander("Argument list", expanded=False): diff --git a/dashboard/components/config_panel.py b/dashboard/components/config_panel.py index ad62e3f..a27d3e6 100644 --- a/dashboard/components/config_panel.py +++ b/dashboard/components/config_panel.py @@ -3,13 +3,14 @@ from pathlib import Path from typing import Any -import streamlit as st from dashboard.config_utils import parse_config_file from dashboard.registry import WorkflowDescriptor def render_config_panel(workflow: WorkflowDescriptor, available_files: list[Path]) -> tuple[dict[str, Any], dict[str, str]]: + import streamlit as st + """Render structured parameter and workflow-specific input assignment controls.""" st.subheader("Configure workflow") arguments: dict[str, Any] = {} diff --git a/dashboard/components/console_panel.py b/dashboard/components/console_panel.py index 4925e09..7a5122e 100644 --- a/dashboard/components/console_panel.py +++ b/dashboard/components/console_panel.py @@ -1,16 +1,18 @@ from __future__ import annotations -import streamlit as st - def render_console(lines: list[str], height: int = 360) -> None: """Render streamed console output.""" + import streamlit as st + text = "".join(lines) - st.text_area("Console", text, height=height) + st.text_area("Console output", text, height=height, help="Live stdout/stderr from the workflow process.") def render_cancellation_note() -> None: """Explain the current cancellation boundary without exposing unsafe controls.""" + import streamlit as st + st.caption( "Cancellation is not exposed in this dashboard phase: Streamlit reruns make reliable foreground " "process termination fragile without a background job supervisor. The runner supports a cancellation " diff --git a/dashboard/components/download_panel.py b/dashboard/components/download_panel.py index 916fff1..b69e477 100644 --- a/dashboard/components/download_panel.py +++ b/dashboard/components/download_panel.py @@ -1,16 +1,20 @@ from __future__ import annotations -import streamlit as st - from dashboard.file_utils import create_result_zip from dashboard.result_parser import ResultInventory def render_download_panel(inventory: ResultInventory) -> None: + import streamlit as st + st.subheader("Download") st.caption("Create a ZIP archive of the selected result directory. The archive is generated in memory and not written to disk.") - if st.button("Prepare ZIP archive"): - zip_bytes = create_result_zip(inventory.root) + if st.button("Prepare ZIP archive", help="Package all files in this result directory for download."): + try: + zip_bytes = create_result_zip(inventory.root) + except (FileNotFoundError, NotADirectoryError, ValueError) as exc: + st.error(f"Could not create result ZIP: {exc}") + return st.download_button( "Download result ZIP", data=zip_bytes, diff --git a/dashboard/components/input_preview.py b/dashboard/components/input_preview.py index 699efd2..6bd3714 100644 --- a/dashboard/components/input_preview.py +++ b/dashboard/components/input_preview.py @@ -2,13 +2,13 @@ from pathlib import Path -import streamlit as st - from dashboard.file_utils import preview_table, read_text_preview, validate_existing_file def render_input_preview(paths: list[Path]) -> None: """Preview uploaded/selected files without modifying them.""" + import streamlit as st + st.subheader("Input preview") if not paths: st.info("Upload or select files to preview them here.") @@ -22,9 +22,13 @@ def render_input_preview(paths: list[Path]) -> None: try: st.dataframe(preview_table(selected), use_container_width=True) except Exception as exc: - st.error(f"Could not preview table: {exc}") + st.error(f"Could not preview table. Check that the file is a readable CSV, TSV, or Excel workbook: {exc}") else: - text, truncated = read_text_preview(selected) + try: + text, truncated = read_text_preview(selected) + except UnicodeDecodeError as exc: + st.error(f"Could not preview text file: {exc}") + return st.code(text) if truncated: st.caption("Preview truncated for display.") diff --git a/dashboard/components/log_viewer.py b/dashboard/components/log_viewer.py index dc6f78b..0566bee 100644 --- a/dashboard/components/log_viewer.py +++ b/dashboard/components/log_viewer.py @@ -2,12 +2,12 @@ from pathlib import Path -import streamlit as st - from dashboard.file_utils import DisplayFile, read_text_preview def render_text_file(label: str, path: Path | None, language: str | None = None) -> None: + import streamlit as st + st.subheader(label) if path is None: st.info(f"No {label} file was found in this result directory.") @@ -19,6 +19,8 @@ def render_text_file(label: str, path: Path | None, language: str | None = None) def render_logs(logs: list[DisplayFile]) -> None: + import streamlit as st + st.subheader("Logs") if not logs: st.info("No log files were found under logs/ or console.log.") diff --git a/dashboard/components/metadata_viewer.py b/dashboard/components/metadata_viewer.py index c211860..d020f66 100644 --- a/dashboard/components/metadata_viewer.py +++ b/dashboard/components/metadata_viewer.py @@ -3,16 +3,16 @@ import json from pathlib import Path -import streamlit as st - from dashboard.file_utils import read_text_preview def render_metadata(path: Path | None) -> None: """Render metadata.json with a clear missing-state message.""" + import streamlit as st + st.subheader("Metadata") if path is None: - st.info("No metadata.json file was found in this result directory.") + st.info("No metadata.json file was found. The run can still be browsed, but provenance details are unavailable.") return try: st.json(json.loads(path.read_text(encoding="utf-8"))) diff --git a/dashboard/components/plot_viewer.py b/dashboard/components/plot_viewer.py index 8139e76..5c911c8 100644 --- a/dashboard/components/plot_viewer.py +++ b/dashboard/components/plot_viewer.py @@ -1,12 +1,12 @@ from __future__ import annotations -import streamlit as st -import streamlit.components.v1 as components - from dashboard.file_utils import DisplayFile, human_size, read_text_preview def render_plots(plots: list[DisplayFile]) -> None: + import streamlit as st + import streamlit.components.v1 as components + st.subheader("Plots") if not plots: st.info("No PNG, JPG, JPEG, SVG, or HTML plots were found in plots/ or recognised legacy plot folders.") diff --git a/dashboard/components/preset_panel.py b/dashboard/components/preset_panel.py index 5d06765..3d50b8a 100644 --- a/dashboard/components/preset_panel.py +++ b/dashboard/components/preset_panel.py @@ -1,16 +1,17 @@ from __future__ import annotations +import json from pathlib import Path -import streamlit as st - from dashboard.config_utils import DashboardSelection, save_preset def render_preset_panel(selection: DashboardSelection, repo_root: Path) -> None: """Allow saving the resolved dashboard selections as a preset file.""" + import streamlit as st + st.subheader("Preset") - preset_name = st.text_input("Preset filename", value=f"{selection.run_name}.json") + preset_name = st.text_input("Preset filename", value=f"{selection.run_name}.json", help="Save the current dashboard selections for reproducibility.") if st.button("Save preset"): target = repo_root / "dashboard_uploads" / selection.run_name / preset_name try: @@ -21,7 +22,7 @@ def render_preset_panel(selection: DashboardSelection, repo_root: Path) -> None: st.success(f"Saved preset to {path}") st.download_button( "Download preset JSON", - data=__import__("json").dumps(selection.to_dict(), indent=2, sort_keys=True), + data=json.dumps(selection.to_dict(), indent=2, sort_keys=True), file_name=f"{selection.run_name}.json", mime="application/json", ) diff --git a/dashboard/components/report_viewer.py b/dashboard/components/report_viewer.py index 995fc36..1577251 100644 --- a/dashboard/components/report_viewer.py +++ b/dashboard/components/report_viewer.py @@ -2,14 +2,14 @@ import base64 -import streamlit as st -import streamlit.components.v1 as components - from dashboard.file_utils import DisplayFile, human_size, read_text_preview def render_reports(reports: list[DisplayFile]) -> None: """Render report files where Streamlit can preview them.""" + import streamlit as st + import streamlit.components.v1 as components + st.subheader("Reports") if not reports: st.info("No HTML, Markdown, or PDF reports were found in reports/.") diff --git a/dashboard/components/result_browser.py b/dashboard/components/result_browser.py index dd2ef78..700dfc8 100644 --- a/dashboard/components/result_browser.py +++ b/dashboard/components/result_browser.py @@ -1,7 +1,5 @@ from __future__ import annotations -import streamlit as st - from dashboard.components.download_panel import render_download_panel from dashboard.components.log_viewer import render_logs, render_text_file from dashboard.components.metadata_viewer import render_metadata @@ -13,11 +11,15 @@ def _summary_metric(label: str, value: int) -> None: + import streamlit as st + st.metric(label, value) def render_result_browser(inventory: ResultInventory) -> None: """Render all discovered result-directory content.""" + import streamlit as st + workflow = infer_workflow(inventory) st.header("Result browser") st.caption(f"Directory: `{inventory.root}`") @@ -60,6 +62,8 @@ def render_result_browser(inventory: ResultInventory) -> None: def _render_downloadable_list(label: str, files) -> None: + import streamlit as st + st.subheader(label) if not files: st.info(f"No {label.lower()} were found in the selected result directory.") diff --git a/dashboard/components/run_status.py b/dashboard/components/run_status.py index ef93fdc..6176138 100644 --- a/dashboard/components/run_status.py +++ b/dashboard/components/run_status.py @@ -1,10 +1,10 @@ from __future__ import annotations -import streamlit as st - def render_run_status(status: str | None, returncode: int | None = None) -> None: """Render workflow completion status.""" + import streamlit as st + if status is None: st.info("No workflow has been run in this session.") elif status == "running": @@ -14,4 +14,4 @@ def render_run_status(status: str | None, returncode: int | None = None) -> None elif status == "cancelled": st.warning(f"Workflow was cancelled. Return code: {returncode}") else: - st.error(f"Workflow failed. Return code: {returncode}") + st.error(f"Workflow failed. Return code: {returncode}. Review the console log tail for details.") diff --git a/dashboard/components/table_viewer.py b/dashboard/components/table_viewer.py index 68cd2f8..f6ecebb 100644 --- a/dashboard/components/table_viewer.py +++ b/dashboard/components/table_viewer.py @@ -1,13 +1,13 @@ from __future__ import annotations -import pandas as pd -import streamlit as st +from typing import Any from dashboard.file_utils import DisplayFile, human_size -@st.cache_data(show_spinner=False) -def _read_table(path: str, suffix: str, sheet_name: str | None = None) -> pd.DataFrame: +def _read_table(path: str, suffix: str, sheet_name: str | None = None) -> Any: + import pandas as pd + if suffix == ".csv": return pd.read_csv(path) if suffix == ".tsv": @@ -17,12 +17,15 @@ def _read_table(path: str, suffix: str, sheet_name: str | None = None) -> pd.Dat raise ValueError(f"Unsupported table suffix: {suffix}") -@st.cache_data(show_spinner=False) def _excel_sheets(path: str) -> list[str]: + import pandas as pd + return pd.ExcelFile(path).sheet_names def render_tables(tables: list[DisplayFile]) -> None: + import streamlit as st + st.subheader("Tables") if not tables: st.info("No CSV, TSV, or Excel tables were found in tables/ or recognised legacy locations.") @@ -30,9 +33,13 @@ def render_tables(tables: list[DisplayFile]) -> None: selected = st.selectbox("Table", tables, format_func=lambda item: f"{item.relative_path} ({human_size(item.size_bytes)})") sheet_name = None if selected.suffix in {".xlsx", ".xls"}: - sheets = _excel_sheets(str(selected.path)) + try: + sheets = _excel_sheets(str(selected.path)) + except Exception as exc: + st.error(f"Could not inspect Excel workbook {selected.relative_path}: {exc}") + return sheet_name = st.selectbox("Sheet", sheets) try: st.dataframe(_read_table(str(selected.path), selected.suffix, sheet_name), use_container_width=True) except Exception as exc: - st.error(f"Could not load table {selected.relative_path}: {exc}") + st.error(f"Could not load table {selected.relative_path}. Check that it is a readable CSV, TSV, or Excel file: {exc}") diff --git a/dashboard/components/upload_panel.py b/dashboard/components/upload_panel.py index 9992259..da59f93 100644 --- a/dashboard/components/upload_panel.py +++ b/dashboard/components/upload_panel.py @@ -2,8 +2,6 @@ from pathlib import Path -import streamlit as st - from dashboard.file_utils import ( UPLOAD_EXTENSIONS, create_upload_dir, @@ -15,11 +13,14 @@ def render_upload_panel(repo_root: Path, run_name: str) -> list[Path]: """Render upload controls and save files under dashboard_uploads// on demand.""" + import streamlit as st + st.subheader("Upload inputs") uploaded = st.file_uploader( "Upload input/config files", type=sorted(ext.lstrip(".") for ext in UPLOAD_EXTENSIONS), accept_multiple_files=True, + help="Files are copied to dashboard_uploads// and are not written into data/ automatically.", ) saved: list[Path] = [] if not uploaded: diff --git a/dashboard/components/workflow_selector.py b/dashboard/components/workflow_selector.py index fe703eb..c89900d 100644 --- a/dashboard/components/workflow_selector.py +++ b/dashboard/components/workflow_selector.py @@ -2,13 +2,13 @@ from pathlib import Path -import streamlit as st - from dashboard.registry import WorkflowDescriptor, launchable_workflows, pixi_environments def render_workflow_selector(repo_root: Path) -> tuple[WorkflowDescriptor, str, str]: """Render workflow, Pixi environment, and run-name controls.""" + import streamlit as st + workflows = launchable_workflows() workflow = st.selectbox("Workflow", workflows, format_func=lambda item: f"{item.label} ({item.key})") st.caption(workflow.description) @@ -16,6 +16,6 @@ def render_workflow_selector(repo_root: Path) -> tuple[WorkflowDescriptor, str, st.write("Known inputs:", ", ".join(workflow.required_inputs)) envs = pixi_environments(repo_root / "pixi.toml") - env = st.selectbox("Pixi environment", envs, index=0) - run_name = st.text_input("Run name", value=f"{workflow.key}-run") + env = st.selectbox("Pixi environment", envs, index=0, help="Choose a Pixi environment defined in pixi.toml.") + run_name = st.text_input("Run name", value=f"{workflow.key}-run", help="Used to name the result and upload folders; unsafe characters are sanitized.") return workflow, env, run_name diff --git a/docs/Documentation/dashboard.md b/docs/Documentation/dashboard.md index 3defd4c..81c23dd 100644 --- a/docs/Documentation/dashboard.md +++ b/docs/Documentation/dashboard.md @@ -161,3 +161,9 @@ The dashboard includes an **Inference** tab when optional inference files are pr - plots from `plots/multistart/`, `plots/profile_likelihood/`, and `plots/posterior/` These are diagnostic scalar-objective summaries, not true multi-objective optimizer fronts. + +--- + +## Unified no-code dashboard + +The newer unified dashboard lives in `dashboard/app.py` and can browse existing result directories, launch registered CLI/Pixi workflows, preview uploads, and show workflow-specific panels. See [No-code PhosKinTime dashboard](no_code_dashboard.md) for launch commands, supported workflows, result-directory contract details, upload behavior, examples, and troubleshooting. diff --git a/docs/Documentation/no_code_dashboard.md b/docs/Documentation/no_code_dashboard.md new file mode 100644 index 0000000..81f1149 --- /dev/null +++ b/docs/Documentation/no_code_dashboard.md @@ -0,0 +1,160 @@ +# No-code PhosKinTime dashboard + +The unified dashboard is a Streamlit application for browsing completed PhosKinTime runs and for launching existing CLI/Pixi workflows without editing Python code. It is intentionally a thin user interface: scientific fitting, ODE solving, optimization, and analysis remain in the existing backend modules and scripts. + +## Launching the dashboard + +From the repository root, start the dashboard with Pixi: + +```bash +pixi run dashboard +``` + +For development with Streamlit reload-on-save enabled: + +```bash +pixi run dashboard-dev +``` + +The tasks are defined in `pixi.toml` and run `streamlit run dashboard/app.py` with `PYTHONPATH=.` so the in-repository packages are importable. + +## Supported workflows + +The launcher registry exposes only structured, known commands. It builds argument lists, not shell strings, and runs subprocesses from the repository root. + +| Workflow | What it launches | Typical inputs | +| --- | --- | --- | +| `prep` | preprocessing cleanup task | files referenced by the current project config | +| `kinopt-local` | `python -m kinopt.local` | phosphosite/protein tables, kinase network data, optional config | +| `tfopt-local` | `python -m tfopt.local` | RNA/mRNA tables, TF network data, optional config | +| `protwise-model` | `python -m protwise.runner.main` | protein/phosphosite data and optional config | +| `networkmodel` | `python -m networkmodel.runner` | kinase network, TF network, omics tables, optional config | +| `phoskintime-all` | `python -m config.cli all` | project-level configuration and data files | + +The dashboard does not invent new CLI flags. If an option is not listed in the workflow registry, it is not generated. + +## Result directory contract + +Each dashboard-launched run uses a predictable result directory under `results///` unless a workflow-specific backend chooses a compatible location. The browser expects this contract: + +```text +results// +├── metadata.json +├── command.txt +├── console.log +├── config_resolved.yaml +├── tables/ +├── plots/ +├── logs/ +├── reports/ +└── artifacts/ +``` + +The result browser also recognizes practical legacy layouts, including Networkmodel top-level CSVs such as `scalar_objective.csv`, `convergence_history.csv`, prediction CSVs, `optimization/`, `profiles/`, `posterior/`, and legacy `kinopt_results.xlsx` or `tfopt_results.xlsx` files. + +## Upload behavior + +The upload panel accepts `.csv`, `.tsv`, `.xlsx`, `.yaml`, `.yml`, `.json`, and `.txt` files. Uploaded files are copied to a per-run folder: + +```text +dashboard_uploads// +``` + +Uploads are not written into `data/` and are not modified silently. The dashboard checks for empty files, unsupported extensions, unreadable files, and duplicate filenames after sanitization. CSV, TSV, and Excel inputs can be previewed with pandas before they are assigned to a workflow. + +## Command preview and execution + +Before a run starts, the dashboard shows the exact command preview and the underlying argument list. This keeps runs reproducible and helps users copy the command into a terminal if preferred. + +During execution, stdout and stderr are streamed into the page and written to `console.log` in the run directory. The runner records `command.txt` and launcher metadata in `metadata.json`. Failures are displayed with the return code and a log tail rather than crashing the Streamlit session. + +## Result browser usage + +Use the **Browse results** tab to select an existing result directory. The browser displays: + +- `metadata.json` with `st.json` when valid; +- `command.txt`, `console.log`, and other logs as text/code; +- CSV, TSV, and Excel tables with `st.dataframe`; +- PNG, JPG, JPEG, SVG, and HTML plots; +- Markdown, HTML, and PDF reports where Streamlit can render them; +- artifacts as downloadable files; +- a ZIP download button for the selected result directory. + +If standard contract files are missing, the browser reports them clearly and still attempts to show recognized legacy outputs. + +## Workflow-specific panels + +The result browser includes workflow tabs for KinOpt, TFOpt, ProtWise, Networkmodel, and advanced analyses. + +- **KinOpt** displays discovered KinOpt result workbooks, alpha/beta-related tables where available, observed-vs-estimated output files, and existing plots. +- **TFOpt** displays TFOpt result workbooks, TF alpha/beta or equivalent tables, latent activity/dominance/knockout outputs when present, and existing plots. +- **ProtWise** displays ODE prediction tables, residual/fits files, sensitivity outputs, and generated plots or reports. +- **Networkmodel** supports both the standardized result layout and legacy Networkmodel outputs such as `dashboard_bundle.pkl`, scalar objective CSVs, convergence history, predictions, optimization summaries, profiles, and posterior outputs. +- **Advanced analysis** exposes parameterized command wrappers for existing scripts such as curve similarity, protein accumulator detection, subnetwork export, mechanistic insights, temporal sensitivity, and mechanism comparison. These analyses are not run automatically on page load. + +Optional visualization packages are imported only when the affected panel is used. If a dependency is unavailable, the dashboard should show a clear message instead of failing during import. + +## Examples + +### Browse an existing result directory + +1. Run `pixi run dashboard`. +2. Open **Browse results**. +3. Enter the base results folder, for example `results`. +4. Select a run folder. +5. Review metadata, tables, plots, logs, reports, artifacts, and workflow-specific tabs. + +### Run KinOpt + +1. Open **Run workflow**. +2. Select `KinOpt local (kinopt-local)`. +3. Upload or select phosphosite/protein and kinase-network inputs as required by the current CLI/config. +4. Preview uploaded tables. +5. Confirm validation passes. +6. Review the command preview. +7. Click **Run workflow**. +8. When the process completes, the result browser opens the run directory. + +### Run TFOpt + +1. Select `TFOpt local (tfopt-local)`. +2. Upload or select RNA/mRNA and TF-network inputs. +3. Pass a config file through the existing config argument when needed. +4. Review and run the generated command. +5. Inspect TFOpt tables, plots, logs, and workflow tabs after completion. + +### Run ProtWise/model + +1. Select `ProtWise model (protwise-model)`. +2. Assign the required protein/phosphosite inputs and optional config file. +3. Preview the command and run it. +4. Use the ProtWise panel to inspect predictions, residuals, fits, sensitivity files, plots, and reports. + +### Run Networkmodel + +1. Select `Networkmodel (networkmodel)`. +2. Assign kinase-network, TF-network, omics, and config inputs supported by the CLI. +3. Review the structured command preview. +4. Run the workflow. +5. Inspect scalar objective, convergence, predictions, optimization/profile/posterior outputs, plots, and the dashboard bundle when available. + +### Download a result ZIP + +1. Open a result directory in **Browse results**. +2. Open the **Download** tab. +3. Click **Prepare ZIP archive**. +4. Click **Download result ZIP**. + +The ZIP is generated in memory and is not committed to the repository. + +## Troubleshooting + +| Symptom | Suggested action | +| --- | --- | +| Dashboard command is unavailable | Confirm Pixi is installed and run commands from the repository root. | +| Result directory is missing | Check the selected folder path and whether the workflow wrote to the expected `results///` directory. | +| `metadata.json` is missing or malformed | The browser can still show files, but provenance is incomplete. Re-run through an updated CLI wrapper when reproducibility is required. | +| CSV/TSV/XLSX preview fails | Verify the file is not empty, is readable, and matches its extension. | +| Workflow fails | Review the return code and `console.log` tail shown by the launcher. Copy the command preview into a terminal for deeper debugging if needed. | +| Optional visualization is unavailable | Install the optional Pixi environment or dependency for that visualization; core browsing remains available. | +| Large HTML/report previews are truncated | Download the original file from the browser or result ZIP. | diff --git a/docs/dashboard_build_plan.md b/docs/dashboard_build_plan.md index 8d0e1d5..91c6522 100644 --- a/docs/dashboard_build_plan.md +++ b/docs/dashboard_build_plan.md @@ -389,3 +389,8 @@ The dashboard now supports no-code setup before launching registered workflows: ### Phase 4 implementation note (June 2026) Workflow-specific dashboard panels now live under `dashboard/workflow_panels/` for KinOpt, TFOpt, ProtWise, Networkmodel, and advanced analyses. The panels discover and display existing workbooks, CSVs, plots, reports, bundles, and inference outputs from the selected result directory while leaving model fitting, ODE solving, optimization, and expensive analyses in the existing backend scripts/CLI modules. Advanced analyses are exposed as parameterized command builders and are not executed automatically on page load. + + +## 15. Implementation Status + +The no-code dashboard phases are implemented in the unified `dashboard/` package. The current implementation provides the standard result contract and provenance helpers, a lazy result browser, a structured command launcher, upload/configuration panels, workflow-specific result panels, advanced-analysis command wrappers, dashboard-focused tests, Pixi dashboard tasks, git-ignore coverage for generated artifacts, and user documentation. Streamlit UI imports are kept inside render functions so importing dashboard modules does not start a Streamlit server or require optional UI dependencies until those render paths are used. diff --git a/docs/index.md b/docs/index.md index 45e5572..9a8da8e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -75,6 +75,11 @@ Executable educational notebooks are available under `notebooks/` and cover end- Run them interactively with `jupyter lab notebooks/` or as executable tests with `pytest --nbmake notebooks/*.ipynb`. + +## No-code dashboard + +Use the unified Streamlit dashboard to browse existing result directories, preview uploaded inputs, launch registered CLI/Pixi workflows, and download result archives. See [No-code dashboard documentation](Documentation/no_code_dashboard.md). + ## Modeling backends (local vs global) PhosKinTime provides two complementary modeling stacks: diff --git a/pixi.toml b/pixi.toml index c9ff1e8..cdd2ab7 100644 --- a/pixi.toml +++ b/pixi.toml @@ -130,6 +130,7 @@ phoskintime-all = "PYTHONPATH=.:.. python -m phoskintime.config.cli all" network-dashboard = "PYTHONPATH=. python run_dashboard.py" dashboard = "PYTHONPATH=. streamlit run dashboard/app.py" +dashboard-dev = "PYTHONPATH=. streamlit run dashboard/app.py --server.runOnSave=true" docs-serve = "zensical serve" docs-build = "zensical build" diff --git a/tests/dashboard/test_file_utils.py b/tests/dashboard/test_file_utils.py index 1d1d95b..ec924e0 100644 --- a/tests/dashboard/test_file_utils.py +++ b/tests/dashboard/test_file_utils.py @@ -113,3 +113,12 @@ def test_invalid_existing_file_handling(tmp_path): assert "File is empty" in validate_existing_file(empty) assert any("Unsupported extension" in problem for problem in validate_existing_file(unsupported)) + + +def test_preview_rejects_malformed_excel_with_user_actionable_error(tmp_path): + pytest.importorskip("pandas") + workbook = tmp_path / "broken.xlsx" + workbook.write_bytes(b"not an excel workbook") + + with pytest.raises(Exception): + preview_table(workbook) diff --git a/tests/dashboard/test_git_hygiene.py b/tests/dashboard/test_git_hygiene.py new file mode 100644 index 0000000..dd38ac3 --- /dev/null +++ b/tests/dashboard/test_git_hygiene.py @@ -0,0 +1,24 @@ +from __future__ import annotations + +import subprocess +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] + + +def test_generated_dashboard_artifacts_are_ignored(): + gitignore = (REPO_ROOT / ".gitignore").read_text(encoding="utf-8") + + assert "/dashboard_uploads/" in gitignore + assert "/results/" in gitignore or "/*results" in gitignore + assert "logs/" in gitignore + assert "*.zip" in gitignore + assert "/.streamlit/" in gitignore or ".streamlit/" in gitignore + + +def test_no_generated_dashboard_folders_are_tracked(): + tracked = subprocess.check_output(["git", "ls-files"], cwd=REPO_ROOT, text=True).splitlines() + + forbidden_prefixes = ("dashboard_uploads/", "results/", "logs/", ".streamlit/") + assert not [path for path in tracked if path.startswith(forbidden_prefixes)] diff --git a/tests/dashboard/test_importability.py b/tests/dashboard/test_importability.py new file mode 100644 index 0000000..2890993 --- /dev/null +++ b/tests/dashboard/test_importability.py @@ -0,0 +1,20 @@ +from __future__ import annotations + +import importlib +import pkgutil +import sys + +import dashboard + + +def test_dashboard_modules_import_without_starting_streamlit(monkeypatch): + """Import dashboard modules without requiring a Streamlit server or optional UI package at import time.""" + sys.modules.pop("streamlit", None) + imported = [] + for module_info in pkgutil.walk_packages(dashboard.__path__, prefix="dashboard."): + module = importlib.import_module(module_info.name) + imported.append(module.__name__) + + assert "dashboard.app" in imported + assert "dashboard.components.table_viewer" in imported + assert "streamlit" not in sys.modules From b3234ecca6d4f800bd8c4c4ccb59ecaed0bd1a23 Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Wed, 10 Jun 2026 22:35:09 +0530 Subject: [PATCH 09/42] Fix networkmodel custom config handling --- networkmodel/config.py | 13 +- networkmodel/runner.py | 458 ++++++++++++++++------- tests/test_networkmodel_runner_config.py | 150 ++++++++ 3 files changed, 483 insertions(+), 138 deletions(-) create mode 100644 tests/test_networkmodel_runner_config.py diff --git a/networkmodel/config.py b/networkmodel/config.py index c8808e3..c6ec4e5 100644 --- a/networkmodel/config.py +++ b/networkmodel/config.py @@ -2,11 +2,16 @@ import os from config_loader import load_config_toml -# cfg: PhosKinConfig loaded from ./config.toml; no default because import requires the file. -if os.path.exists("config.toml"): - cfg = load_config_toml("config.toml") +CONFIG_ENV_VAR = "PHOSKINTIME_NETWORKMODEL_CONFIG" +CONFIG_PATH = os.environ.get(CONFIG_ENV_VAR, "config.toml") + +# cfg: PhosKinConfig loaded from the selected TOML. networkmodel.runner sets +# PHOSKINTIME_NETWORKMODEL_CONFIG after parsing --conf and before importing +# modules that rely on this compatibility constants surface. +if os.path.exists(CONFIG_PATH): + cfg = load_config_toml(CONFIG_PATH) else: - raise FileNotFoundError("config.toml not found in current directory.") + raise FileNotFoundError(f"networkmodel config not found: {CONFIG_PATH}") def _as_bool(x): diff --git a/networkmodel/runner.py b/networkmodel/runner.py index 40ac6e2..d88a219 100644 --- a/networkmodel/runner.py +++ b/networkmodel/runner.py @@ -23,61 +23,20 @@ import argparse import atexit +import importlib import json import logging import pickle import sys import multiprocessing as mp +from dataclasses import asdict, is_dataclass +from pathlib import Path +from typing import Any -import numpy as np -import pandas as pd - -from networkmodel.dashboard_bundle import save_dashboard_bundle -from networkmodel.scan import run_hyperparameter_scan -from networkmodel.sensitivity import run_sensitivity_analysis -from networkmodel.InitialConditions import _dump_y0 -from networkmodel.BuildMatrix import build_W_parallel, build_tf_matrix -from networkmodel.cache import prepare_fast_loss_data -from networkmodel.config import TIME_POINTS_PROTEIN, TIME_POINTS_RNA, RESULTS_DIR, MAX_ITERATIONS, \ - SEED, REGULARIZATION_LAMBDA, REGULARIZATION_RNA, REGULARIZATION_PHOSPHO, TIME_POINTS_PHOSPHO, \ - REGULARIZATION_PROTEIN, NORMALIZE_FC_STEADY, USE_INITIAL_CONDITION_FROM_DATA, KINASE_NET_FILE, TF_NET_FILE, \ - MS_DATA_FILE, RNA_DATA_FILE, PHOSPHO_DATA_FILE, KINOPT_RESULTS_FILE, TFOPT_RESULTS_FILE, \ - WEIGHTING_METHOD_PROTEIN, WEIGHTING_METHOD_RNA, APP_NAME, VERSION, PARENT_PACKAGE, CITATION, DOI, GITHUB_URL, \ - DOCS_URL, SENSITIVITY_METRIC, SENSITIVITY_ANALYSIS, AVAILABLE_MODELS, HYPERPARAM_SCAN, MODEL, CORES, \ - N_STARTS, PROFILE_LIKELIHOOD, PROFILE_INDICES, PROFILE_GRID_SIZE, POSTERIOR_SAMPLING, \ - POSTERIOR_NUM_WARMUP, POSTERIOR_NUM_SAMPLES -from networkmodel.io import load_data -from networkmodel.network import Index, KinaseInput, System -from networkmodel.OptimizationProblem import GlobalODEScalarObjective, build_weight_functions -from networkmodel.params import init_raw_params, unpack_params -from networkmodel.simulate import simulate_and_measure -from networkmodel.utils import normalize_fc_to_t0, _base_idx, calculate_bio_bounds, \ - get_optimized_sets -from networkmodel.export import export_pareto_front_to_excel, plot_goodness_of_fit, \ - export_results, save_gene_timeseries_plots, \ - export_S_rates, plot_s_rates_report, export_kinase_activities, \ - export_param_correlations, export_residuals, export_parameter_distributions -from networkmodel.SteadyStateAnalysis import simulate_until_steady, plot_steady_state_all -from networkmodel.backend import warn_deprecated_backend_options, detect_data_mode, JaxoptResult -from networkmodel.BayesianInference import ( - InferenceContext, - run_multistart, - run_profile_likelihood_standalone_processes, - run_numpyro_posterior_standalone_processes, - configure_jax_parallelism, -) - -from networkmodel.PosteriorObjective import write_posterior_payload -from networkmodel.mode_outputs import write_scalar_result_tables -from common.frechet import frechet_distance -from common.results import ( - attach_file_console_logger, ensure_result_dir, populate_standard_subdirs, - write_command, write_metadata, write_resolved_config, -) -from config_loader import load_config_toml -from config.config import setup_logger +DEFAULT_CONFIG_PATH = Path(__file__).resolve().parents[1] / "config.toml" +NETWORKMODEL_CONFIG_ENV = "PHOSKINTIME_NETWORKMODEL_CONFIG" -logger = setup_logger(log_dir=RESULTS_DIR) +logger = logging.getLogger(__name__) global problem @@ -93,92 +52,323 @@ def _close_log_handlers(): pass -def main(): - """Run the networkmodel entry point - - Returns: - Computed result from this routine. - - Raises: - ValueError: When inputs are inconsistent or unsupported. - """ + +def _jsonable_runtime(value: Any) -> Any: + """Convert runtime configuration values to JSON/YAML-safe primitives.""" + if isinstance(value, Path): + return str(value) + if is_dataclass(value): + return _jsonable_runtime(asdict(value)) + if isinstance(value, dict): + return {str(k): _jsonable_runtime(v) for k, v in value.items()} + if isinstance(value, (list, tuple, set)): + return [_jsonable_runtime(v) for v in value] + if hasattr(value, "tolist"): + return value.tolist() + try: + json.dumps(value) + return value + except TypeError: + return str(value) + + +def _as_bool(value: Any) -> bool: + if isinstance(value, bool): + return value + if isinstance(value, str): + return value.strip().lower() in {"1", "true", "yes", "y", "on"} + return bool(value) + + +def _default_config_path() -> Path: + return DEFAULT_CONFIG_PATH + + +def parse_config_path(argv: list[str] | None = None) -> Path | None: + """Parse only --conf so selected config is known before defaults are resolved.""" + pre_parser = argparse.ArgumentParser(add_help=False) + pre_parser.add_argument("--conf", default=None) + known, _ = pre_parser.parse_known_args(argv) + return Path(known.conf).expanduser() if known.conf else None + + +def _resolve_config_path(conf_path: Path | None) -> Path: + return (conf_path or _default_config_path()).expanduser().resolve() + + +def load_networkmodel_config(conf_path: Path | None): + """Load selected networkmodel config and expose it to networkmodel.config importers.""" + resolved = _resolve_config_path(conf_path) + os.environ[NETWORKMODEL_CONFIG_ENV] = str(resolved) + if "networkmodel.config" in sys.modules: + importlib.reload(sys.modules["networkmodel.config"]) + from config_loader import load_config_toml + + return load_config_toml(resolved) + + +def _model_code(model: Any) -> int: + if isinstance(model, int): + return model + name = str(model).strip().lower() + mapping = {"distributive": 0, "sequential": 1, "successive": 1, "combinatorial": 2, "saturating": 4, "saturation": 4} + return mapping.get(name, 4) + + +def _config_defaults(config: Any, resolved_config_path: Path, supplied_conf_path: Path | None) -> dict[str, Any]: + default_path = _default_config_path().resolve() + return { + "conf": str(supplied_conf_path) if supplied_conf_path is not None else None, + "resolved_config_path": str(resolved_config_path), + "config_source": "custom" if supplied_conf_path is not None and resolved_config_path != default_path else "default", + "kinase_net": config.kinase_net, + "tf_net": config.tf_net, + "ms": config.ms_data, + "rna": config.rna_data, + "phospho": config.phospho_data, + "kinopt": config.kinopt_results, + "tfopt": config.tfopt_results, + "output_dir": config.results_dir, + "cores": config.cores, + "n_gen": config.maximum_iterations, + "seed": config.seed, + "lambda_prior": config.regularization_lambda, + "lambda_protein": config.regularization_protein, + "lambda_rna": config.regularization_rna, + "lambda_phospho": config.regularization_phospho, + "normalize_fc_steady": _as_bool(config.normalize_fc_steady), + "use_initial_condition_from_data": _as_bool(config.use_initial_condition_from_data), + "scan": _as_bool(config.hyperparam_scan), + "sensitivity": _as_bool(config.sensitivity_analysis), + "solver": "jaxopt", + "app_name": getattr(config, "app_name", "Phoskintime-Global"), + "version": getattr(config, "version", "0.1.0"), + "parent_package": getattr(config, "parent_package", "phoskintime"), + "citation": getattr(config, "citation", ""), + "doi": getattr(config, "doi", ""), + "github_url": getattr(config, "github_url", ""), + "docs_url": getattr(config, "docs_url", ""), + "available_models": tuple(getattr(config, "available_models", ()) or ()), + "model": getattr(config, "model", "combinatorial"), + "model_code": _model_code(getattr(config, "model", "combinatorial")), + "time_points_protein": config.time_points_prot, + "time_points_rna": config.time_points_rna, + "time_points_phospho": config.time_points_phospho, + "weighting_method_protein": getattr(config, "weighting_method_protein", "uniform"), + "weighting_method_rna": getattr(config, "weighting_method_rna", "uniform"), + "sensitivity_metric": getattr(config, "sensitivity_metric", "total_signal"), + "n_starts": int(getattr(config, "n_starts", 1)), + "profile_likelihood": _as_bool(getattr(config, "profile_likelihood", False)), + "profile_indices": str(getattr(config, "profile_indices", "")), + "profile_grid_size": int(getattr(config, "profile_grid_size", 10)), + "posterior_sampling": _as_bool(getattr(config, "posterior_sampling", False)), + "posterior_num_warmup": int(getattr(config, "posterior_num_warmup", 20)), + "posterior_num_samples": int(getattr(config, "posterior_num_samples", 30)), + "raw_config": config, + } + + +def build_parser(config_defaults: dict[str, Any]) -> argparse.ArgumentParser: + """Build the full parser after config-backed defaults are known.""" parser = argparse.ArgumentParser() - parser.add_argument("--conf", default=None, help="Compatibility option; networkmodel settings are loaded before argument parsing.") - parser.add_argument("--kinase-net", default=KINASE_NET_FILE) - parser.add_argument("--tf-net", default=TF_NET_FILE) - parser.add_argument("--ms", default=MS_DATA_FILE) - parser.add_argument("--rna", default=RNA_DATA_FILE) - parser.add_argument("--phospho", default=PHOSPHO_DATA_FILE) - - # kinopt and tfopt results - parser.add_argument("--kinopt", default=KINOPT_RESULTS_FILE) - parser.add_argument("--tfopt", default=TFOPT_RESULTS_FILE) - - parser.add_argument("--output-dir", "--outdir", dest="output_dir", default=RESULTS_DIR) - parser.add_argument("--cores", type=int, default=CORES) - - # JAXopt - parser.add_argument("--n-gen", type=int, default=MAX_ITERATIONS) - parser.add_argument("--seed", type=int, default=SEED) - - # Loss weights - parser.add_argument("--lambda-prior", type=float, default=REGULARIZATION_LAMBDA) - parser.add_argument("--lambda-protein", type=float, default=REGULARIZATION_PROTEIN) - parser.add_argument("--lambda-rna", type=float, default=REGULARIZATION_RNA) - parser.add_argument("--lambda-phospho", type=float, default=REGULARIZATION_PHOSPHO) - - # Data inference - parser.add_argument("--normalize-fc-steady", action="store_true", default=NORMALIZE_FC_STEADY) - parser.add_argument("--use-initial-condition-from-data", action="store_true", - default=USE_INITIAL_CONDITION_FROM_DATA) - parser.add_argument("--scan", action="store_true", - help="Run a hyperparameter scan using Optuna to find the best regularization parameters.", - default=HYPERPARAM_SCAN) - parser.add_argument("--sensitivity", action="store_true", - help="Run a sensitivity analysis after optimization.", - default=SENSITIVITY_ANALYSIS) - parser.add_argument("--solver", type=str, choices=["jaxopt", "pymoo", "optuna"], default="jaxopt", - help="Choice of optimization solver. Legacy pymoo/optuna values map to jaxopt.") - - args = parser.parse_args() + parser.add_argument("--conf", default=config_defaults["conf"], help="Path to TOML config used for networkmodel defaults.") + parser.add_argument("--kinase-net", default=config_defaults["kinase_net"]) + parser.add_argument("--tf-net", default=config_defaults["tf_net"]) + parser.add_argument("--ms", default=config_defaults["ms"]) + parser.add_argument("--rna", default=config_defaults["rna"]) + parser.add_argument("--phospho", default=config_defaults["phospho"]) + parser.add_argument("--kinopt", default=config_defaults["kinopt"]) + parser.add_argument("--tfopt", default=config_defaults["tfopt"]) + parser.add_argument("--output-dir", "--outdir", dest="output_dir", default=config_defaults["output_dir"]) + parser.add_argument("--cores", type=int, default=config_defaults["cores"]) + parser.add_argument("--n-gen", type=int, default=config_defaults["n_gen"]) + parser.add_argument("--seed", type=int, default=config_defaults["seed"]) + parser.add_argument("--lambda-prior", type=float, default=config_defaults["lambda_prior"]) + parser.add_argument("--lambda-protein", type=float, default=config_defaults["lambda_protein"]) + parser.add_argument("--lambda-rna", type=float, default=config_defaults["lambda_rna"]) + parser.add_argument("--lambda-phospho", type=float, default=config_defaults["lambda_phospho"]) + parser.add_argument("--normalize-fc-steady", action="store_true", default=config_defaults["normalize_fc_steady"]) + parser.add_argument("--use-initial-condition-from-data", action="store_true", default=config_defaults["use_initial_condition_from_data"]) + parser.add_argument("--scan", action="store_true", help="Run a hyperparameter scan using Optuna to find the best regularization parameters.", default=config_defaults["scan"]) + parser.add_argument("--sensitivity", action="store_true", help="Run a sensitivity analysis after optimization.", default=config_defaults["sensitivity"]) + parser.add_argument("--solver", type=str, choices=["jaxopt", "pymoo", "optuna"], default=config_defaults["solver"], help="Choice of optimization solver. Legacy pymoo/optuna values map to jaxopt.") + return parser + + +def resolve_runtime_config(args: argparse.Namespace, config_defaults: dict[str, Any]) -> argparse.Namespace: + """Attach selected-config metadata and config-only defaults to parsed args.""" + for key, value in config_defaults.items(): + if key not in vars(args): + setattr(args, key, value) + return args + + +def parse_runtime_args(argv: list[str] | None = None) -> tuple[argparse.Namespace, dict[str, Any]]: + """Parse --conf first, load that config, then parse all args with selected defaults.""" + supplied_conf_path = parse_config_path(argv) + resolved_config_path = _resolve_config_path(supplied_conf_path) + config = load_networkmodel_config(supplied_conf_path) + defaults = _config_defaults(config, resolved_config_path, supplied_conf_path) + parser = build_parser(defaults) + args = parser.parse_args(argv) + return resolve_runtime_config(args, defaults), defaults + + +def _runtime_metadata_extra(args: argparse.Namespace) -> dict[str, Any]: + return { + "supplied_config_path": args.conf, + "resolved_config_path": args.resolved_config_path, + "config_source": args.config_source, + "effective_inputs": { + "kinase_net": args.kinase_net, + "tf_net": args.tf_net, + "ms": args.ms, + "rna": args.rna, + "phospho": args.phospho, + "kinopt": args.kinopt, + "tfopt": args.tfopt, + }, + "effective_settings": { + "output_dir": args.output_dir, + "cores": args.cores, + "n_gen": args.n_gen, + "seed": args.seed, + "solver": args.solver, + "lambda_prior": args.lambda_prior, + "lambda_protein": args.lambda_protein, + "lambda_rna": args.lambda_rna, + "lambda_phospho": args.lambda_phospho, + "normalize_fc_steady": args.normalize_fc_steady, + "use_initial_condition_from_data": args.use_initial_condition_from_data, + "scan": args.scan, + "sensitivity": args.sensitivity, + "model": args.model, + "model_code": args.model_code, + "time_points_protein": args.time_points_protein, + "time_points_rna": args.time_points_rna, + "time_points_phospho": args.time_points_phospho, + "n_starts": args.n_starts, + "profile_likelihood": args.profile_likelihood, + "posterior_sampling": args.posterior_sampling, + }, + } + + +def initialize_run_contract(args: argparse.Namespace) -> argparse.Namespace: + """Create output/provenance files after config and CLI precedence are resolved.""" + from common.results import attach_file_console_logger, ensure_result_dir, write_command, write_metadata, write_resolved_config + from config.config import setup_logger + + global logger args.output_dir = str(ensure_result_dir(args.output_dir)["root"]) + logger = setup_logger(log_dir=args.output_dir) attach_file_console_logger(logger, args.output_dir) write_command(args.output_dir) - write_resolved_config(args.output_dir, vars(args)) + write_resolved_config(args.output_dir, _jsonable_runtime(vars(args))) write_metadata( args.output_dir, workflow="networkmodel.runner", args=args, inputs=[args.kinase_net, args.tf_net, args.ms, args.rna, args.phospho, args.kinopt, args.tfopt], + extra=_runtime_metadata_extra(args), + ) + return args + + +def _import_runtime_dependencies() -> None: + """Import networkmodel runtime modules only after --conf selected the config file.""" + global np, pd, save_dashboard_bundle, run_hyperparameter_scan, run_sensitivity_analysis + global _dump_y0, build_W_parallel, build_tf_matrix, prepare_fast_loss_data, load_data + global Index, KinaseInput, System, GlobalODEScalarObjective, build_weight_functions + global init_raw_params, unpack_params, simulate_and_measure, normalize_fc_to_t0, _base_idx + global calculate_bio_bounds, get_optimized_sets, export_pareto_front_to_excel, plot_goodness_of_fit + global export_results, save_gene_timeseries_plots, export_S_rates, plot_s_rates_report + global export_kinase_activities, export_param_correlations, export_residuals, export_parameter_distributions + global simulate_until_steady, plot_steady_state_all, warn_deprecated_backend_options, detect_data_mode + global JaxoptResult, InferenceContext, run_multistart, run_profile_likelihood_standalone_processes + global run_numpyro_posterior_standalone_processes, configure_jax_parallelism, write_posterior_payload + global write_scalar_result_tables, frechet_distance, populate_standard_subdirs + + import numpy as np + import pandas as pd + from common.frechet import frechet_distance + from common.results import populate_standard_subdirs + from networkmodel.BayesianInference import ( + InferenceContext, + configure_jax_parallelism, + run_multistart, + run_numpyro_posterior_standalone_processes, + run_profile_likelihood_standalone_processes, ) + from networkmodel.BuildMatrix import build_W_parallel, build_tf_matrix + from networkmodel.InitialConditions import _dump_y0 + from networkmodel.OptimizationProblem import GlobalODEScalarObjective, build_weight_functions + from networkmodel.PosteriorObjective import write_posterior_payload + from networkmodel.SteadyStateAnalysis import simulate_until_steady, plot_steady_state_all + from networkmodel.backend import JaxoptResult, detect_data_mode, warn_deprecated_backend_options + from networkmodel.cache import prepare_fast_loss_data + from networkmodel.dashboard_bundle import save_dashboard_bundle + from networkmodel.export import ( + export_S_rates, + export_kinase_activities, + export_param_correlations, + export_pareto_front_to_excel, + export_parameter_distributions, + export_residuals, + export_results, + plot_goodness_of_fit, + plot_s_rates_report, + save_gene_timeseries_plots, + ) + from networkmodel.io import load_data + from networkmodel.mode_outputs import write_scalar_result_tables + from networkmodel.network import Index, KinaseInput, System + from networkmodel.params import init_raw_params, unpack_params + from networkmodel.scan import run_hyperparameter_scan + from networkmodel.sensitivity import run_sensitivity_analysis + from networkmodel.simulate import simulate_and_measure + from networkmodel.utils import _base_idx, calculate_bio_bounds, get_optimized_sets, normalize_fc_to_t0 + +def main(): + """Run the networkmodel entry point + + Returns: + Computed result from this routine. + + Raises: + ValueError: When inputs are inconsistent or unsupported. + """ + args, config_defaults = parse_runtime_args() + args = initialize_run_contract(args) + _import_runtime_dependencies() # logger.info Arguments logger.info("============================================================") logger.info("PhosKinTime Global Model") logger.info("------------------------------------------------------------") - logger.info(f"Application : {APP_NAME}") - logger.info(f"Version : {VERSION}") - logger.info(f"Available Models : {AVAILABLE_MODELS}") + logger.info(f"Application : {args.app_name}") + logger.info(f"Version : {args.version}") + logger.info(f"Available Models : {args.available_models}") logger.info("------------------------------------------------------------") - logger.info(f"Parent Package : {PARENT_PACKAGE}") - logger.info(f"Citation : {CITATION}") - logger.info(f"DOI : {DOI}") - logger.info(f"Source Code : {GITHUB_URL}") - logger.info(f"Documentation : {DOCS_URL}") + logger.info(f"Parent Package : {args.parent_package}") + logger.info(f"Citation : {args.citation}") + logger.info(f"DOI : {args.doi}") + logger.info(f"Source Code : {args.github_url}") + logger.info(f"Documentation : {args.docs_url}") logger.info("============================================================") logger.info("[Solver] Using Diffrax Kvaerno Solver") - if MODEL == 0: + if args.model_code == 0: logger.info("[Model] Using Distributive Model") - elif MODEL == 1: + elif args.model_code == 1: logger.info("[Model] Using Sequential Model") - elif MODEL == 2: + elif args.model_code == 2: logger.info("[Model] Using Combinatorial Model") - elif MODEL == 4: + elif args.model_code == 4: logger.info("[Model] Using Saturating Model") else: - raise ValueError(f"Unknown MODEL value in config file: {MODEL}") + raise ValueError(f"Unknown MODEL value in config file: {args.model_code}") logger.info(f"[Args] Output directory: {args.output_dir}") logger.info(f"[Args] Number of cores: {args.cores}") @@ -380,7 +570,7 @@ def _proxy_score(orphan: str, candidate: str) -> float: ) # ----------------------------------------------------------------------------- - # FULL-UNIVERSE MODE (LEGACY / “MODEL EVERYTHING” BEHAVIOR) + # FULL-UNIVERSE MODE (LEGACY / “args.model_code EVERYTHING” BEHAVIOR) # ----------------------------------------------------------------------------- # Rationale # --------- @@ -442,9 +632,9 @@ def _proxy_score(orphan: str, candidate: str) -> float: # New: keep the config for logging, but don't treat it as a callable weight_cfg = build_weight_functions( - method_protein=WEIGHTING_METHOD_PROTEIN, - method_rna=WEIGHTING_METHOD_RNA, - time_grid=TIME_POINTS_PROTEIN, + method_protein=args.weighting_method_protein, + method_rna=args.weighting_method_rna, + time_grid=args.time_points_protein, ) logger.info("[Weights] Protein weighting scheme: %s", weight_cfg["protein"]) @@ -454,11 +644,11 @@ def _proxy_score(orphan: str, candidate: str) -> float: df_prot["w"] = 1.0 df_rna["w"] = 1.0 - # 3) Build W + TF + # 3) Build W + TF # ------------------------------------------------------------------------- # Network Matrix Construction # ------------------------------------------------------------------------- - # Build the kinase-substrate interaction matrix (W_global) and the + # Build the kinase-substrate interaction matrix (W_global) and the # transcription factor regulatory matrix (tf_mat) in parallel for efficiency. # # W_global: Sparse matrix (sites × kinases) encoding kinase-substrate relationships @@ -554,7 +744,7 @@ def _proxy_score(orphan: str, candidate: str) -> float: logger.info("[Model] Initial conditions set from data.") # 5) Precompute loss data on solver time grid - solver_times = np.unique(np.concatenate([TIME_POINTS_PROTEIN, TIME_POINTS_RNA, TIME_POINTS_PHOSPHO])) + solver_times = np.unique(np.concatenate([args.time_points_protein, args.time_points_rna, args.time_points_phospho])) loss_data = prepare_fast_loss_data(idx, df_prot, df_rna, df_pho, solver_times) loss_data["prot_base_idx"] = _base_idx(solver_times, 0.0) @@ -690,9 +880,9 @@ def _proxy_score(orphan: str, candidate: str) -> float: maxiter=args.n_gen, tol=1e-6, ) - if N_STARTS > 1: + if args.n_starts > 1: try: - ms = run_multistart(ctx, n_starts=N_STARTS, seed=args.seed, max_workers=args.cores) + ms = run_multistart(ctx, n_starts=args.n_starts, seed=args.seed, max_workers=args.cores) best_row = ms["best"].drop( columns=["start_id", "seed", "success", "selected_best"], errors="ignore", @@ -736,11 +926,11 @@ def _proxy_score(orphan: str, candidate: str) -> float: tol=1e-6, ) - if PROFILE_LIKELIHOOD and PROFILE_INDICES.strip(): + if args.profile_likelihood and args.profile_indices.strip(): try: - logger.info("[Profile] Profile likelihood requested for indices: %s", PROFILE_INDICES) + logger.info("[Profile] Profile likelihood requested for indices: %s", args.profile_indices) - profile_indices = [int(x) for x in PROFILE_INDICES.split(",") if x.strip()] + profile_indices = [int(x) for x in args.profile_indices.split(",") if x.strip()] profile_run_config_path = write_posterior_payload( ctx=ctx, @@ -753,7 +943,7 @@ def _proxy_score(orphan: str, candidate: str) -> float: run_config_path=profile_run_config_path, output_dir=args.output_dir, parameter_indices=profile_indices, - grid_size=PROFILE_GRID_SIZE, + grid_size=args.profile_grid_size, max_workers=1, ) @@ -766,13 +956,13 @@ def _proxy_score(orphan: str, candidate: str) -> float: except Exception: logger.exception("[Profile] Profile likelihood failed.") - if POSTERIOR_SAMPLING: + if args.posterior_sampling: try: logger.info( "[Posterior] Requested standalone posterior sampling " "with warmup=%s, samples=%s.", - POSTERIOR_NUM_WARMUP, - POSTERIOR_NUM_SAMPLES, + args.posterior_num_warmup, + args.posterior_num_samples, ) run_config_path = write_posterior_payload( @@ -785,8 +975,8 @@ def _proxy_score(orphan: str, candidate: str) -> float: posterior_result = run_numpyro_posterior_standalone_processes( run_config_path=run_config_path, output_dir=args.output_dir, - num_warmup=POSTERIOR_NUM_WARMUP, - num_samples=POSTERIOR_NUM_SAMPLES, + num_warmup=args.posterior_num_warmup, + num_samples=args.posterior_num_samples, seed=args.seed, num_processes=4, ) @@ -847,7 +1037,7 @@ def _proxy_score(orphan: str, candidate: str) -> float: # Simulate with current parameters dfp_temp, dfr_temp, dfph_temp = simulate_and_measure( - sys, idx, TIME_POINTS_PROTEIN, TIME_POINTS_RNA, TIME_POINTS_PHOSPHO + sys, idx, args.time_points_protein, args.time_points_rna, args.time_points_phospho ) detailed_scores = {"prot": {}, "rna": {}, "phospho": {}} @@ -931,7 +1121,7 @@ def _proxy_score(orphan: str, candidate: str) -> float: idx=idx, fitted_params=params, output_dir=args.output_dir, - metric=SENSITIVITY_METRIC + metric=args.sensitivity_metric ) # 1. Export Dynamic Kinase Activities (Mechanism check) @@ -972,7 +1162,7 @@ def _proxy_score(orphan: str, candidate: str) -> float: f"[Output] Saved phosphorylation rates report for picked solution {args.output_dir}/S_rates_report.pdf.") # 12) Export picked solution - dfp, dfr, dfph = simulate_and_measure(sys, idx, TIME_POINTS_PROTEIN, TIME_POINTS_RNA, TIME_POINTS_PHOSPHO) + dfp, dfr, dfph = simulate_and_measure(sys, idx, args.time_points_protein, args.time_points_rna, args.time_points_phospho) # Save raw preds if dfp is not None: dfp.to_csv(os.path.join(args.output_dir, "pred_prot_picked.csv"), index=False) @@ -1007,8 +1197,8 @@ def _proxy_score(orphan: str, candidate: str) -> float: df_phos_obs=df_pho, df_phos_pred=dfph, output_dir=ts_dir, - prot_times=TIME_POINTS_PROTEIN, - rna_times=TIME_POINTS_RNA, + prot_times=args.time_points_protein, + rna_times=args.time_points_rna, filename_prefix="fit" ) @@ -1053,8 +1243,8 @@ def _proxy_score(orphan: str, candidate: str) -> float: logger.info("[Done] Exported results saved.") - # Display all parameters from the configuration class - global_config = load_config_toml("config.toml") + # Display all parameters from the selected configuration class + global_config = args.raw_config logger.info("=" * 80) logger.info("GLOBAL MODEL CONFIGURATION") logger.info("=" * 80) diff --git a/tests/test_networkmodel_runner_config.py b/tests/test_networkmodel_runner_config.py new file mode 100644 index 0000000..07c6478 --- /dev/null +++ b/tests/test_networkmodel_runner_config.py @@ -0,0 +1,150 @@ +from __future__ import annotations + +import json +import sys +from pathlib import Path + +import pytest + + +def _write_network_config(path: Path, outdir: Path) -> None: + path.write_text( + f''' +[networkmodel] +kinase_net = "custom/kinase_network.csv" +tf_net = "custom/tf_network.csv" +ms = "custom/protein.csv" +rna = "custom/rna.csv" +phospho = "custom/phospho.csv" +kinopt = "custom/kinopt.xlsx" +tfopt = "custom/tfopt.xlsx" +output_dir = "{outdir.as_posix()}" +cores = 7 +seed = 123 +n_gen = 44 +lambda_prior = 0.31 +lambda_protein = 0.41 +lambda_rna = 0.51 +lambda_phospho = 0.61 +normalize_fc_steady = true +use_initial_condition_from_data = false +model = "sequential" +n_starts = 3 +profile_likelihood = true +profile_indices = "1,2" +profile_grid_size = 5 +posterior_sampling = true +posterior_num_warmup = 6 +posterior_num_samples = 7 +weighting_method_protein = "variance" +weighting_method_rna = "uniform" +sensitivity_metric = "total_signal" + +[networkmodel.timepoints] +protein = [0, 10, 20] +rna = [4, 14, 24] +phospho_protein = [0, 5, 15] + +[networkmodel.solver] +absolute_tolerance = 1e-6 +relative_tolerance = 1e-5 +max_timesteps = 12345 +''', + encoding="utf-8", + ) + + +def test_importing_runner_does_not_import_networkmodel_config_eagerly(): + sys.modules.pop("networkmodel.config", None) + + import networkmodel.runner as runner + + assert runner.parse_config_path(["--conf", "custom.toml"]) == Path("custom.toml") + assert "networkmodel.config" not in sys.modules + + +def test_custom_conf_is_used_for_networkmodel_defaults(tmp_path, monkeypatch): + pytest.importorskip("numpy") + from networkmodel import runner + + conf = tmp_path / "custom_config.toml" + outdir = tmp_path / "configured-output" + _write_network_config(conf, outdir) + + args, _ = runner.parse_runtime_args(["--conf", str(conf)]) + + assert args.config_source == "custom" + assert Path(args.resolved_config_path) == conf.resolve() + assert args.kinase_net == "custom/kinase_network.csv" + assert args.tf_net == "custom/tf_network.csv" + assert args.output_dir == outdir.as_posix() + assert args.cores == 7 + assert args.n_gen == 44 + assert args.lambda_prior == pytest.approx(0.31) + assert args.lambda_protein == pytest.approx(0.41) + assert args.lambda_rna == pytest.approx(0.51) + assert args.lambda_phospho == pytest.approx(0.61) + assert args.model_code == 1 + assert args.time_points_protein.tolist() == [0.0, 10.0, 20.0] + assert args.time_points_rna.tolist() == [4.0, 14.0, 24.0] + assert args.time_points_phospho.tolist() == [0.0, 5.0, 15.0] + assert args.raw_config.ode_abs_tol == pytest.approx(1e-6) + assert args.raw_config.ode_rel_tol == pytest.approx(1e-5) + assert args.raw_config.ode_max_steps == 12345 + + +def test_cli_flags_override_custom_conf(tmp_path): + pytest.importorskip("numpy") + from networkmodel import runner + + conf = tmp_path / "custom_config.toml" + configured_outdir = tmp_path / "configured-output" + cli_outdir = tmp_path / "cli-output" + _write_network_config(conf, configured_outdir) + + args, _ = runner.parse_runtime_args([ + "--conf", str(conf), + "--solver", "optuna", + "--output-dir", str(cli_outdir), + "--lambda-rna", "9.5", + "--cores", "2", + ]) + + assert args.output_dir == str(cli_outdir) + assert args.solver == "optuna" + assert args.lambda_rna == pytest.approx(9.5) + assert args.cores == 2 + assert args.kinase_net == "custom/kinase_network.csv" + + +def test_default_config_is_used_when_conf_is_omitted(): + pytest.importorskip("numpy") + from networkmodel import runner + + args, _ = runner.parse_runtime_args([]) + + assert args.config_source == "default" + assert Path(args.resolved_config_path) == runner.DEFAULT_CONFIG_PATH.resolve() + assert args.conf is None + + +def test_networkmodel_initialization_writes_resolved_config_and_metadata(tmp_path): + pytest.importorskip("numpy") + pytest.importorskip("numba") + from networkmodel import runner + + conf = tmp_path / "custom_config.toml" + outdir = tmp_path / "configured-output" + _write_network_config(conf, outdir) + + args, _ = runner.parse_runtime_args(["--conf", str(conf)]) + runner.initialize_run_contract(args) + + metadata = json.loads((outdir / "metadata.json").read_text(encoding="utf-8")) + assert (outdir / "config_resolved.yaml").is_file() + assert metadata["supplied_config_path"] == str(conf) + assert metadata["resolved_config_path"] == str(conf.resolve()) + assert metadata["config_source"] == "custom" + assert metadata["effective_inputs"]["kinase_net"] == "custom/kinase_network.csv" + assert metadata["effective_settings"]["lambda_rna"] == pytest.approx(0.51) + assert metadata["effective_settings"]["time_points_protein"] == [0.0, 10.0, 20.0] From 9565a25d15f1a22723dd100926b49c720b741e01 Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Wed, 10 Jun 2026 22:48:05 +0530 Subject: [PATCH 10/42] Fix dashboard input extension validation --- dashboard/registry.py | 16 +++--- docs/Documentation/no_code_dashboard.md | 2 + tests/dashboard/test_command_builder.py | 30 ++++++++++ tests/dashboard/test_registry.py | 22 ++++++++ tests/dashboard/test_upload_validation.py | 67 +++++++++++++++++++++++ 5 files changed, 129 insertions(+), 8 deletions(-) diff --git a/dashboard/registry.py b/dashboard/registry.py index fa2097b..37e55de 100644 --- a/dashboard/registry.py +++ b/dashboard/registry.py @@ -134,14 +134,14 @@ class WorkflowDescriptor: accepted_arguments=( ArgumentSpec("conf", "--conf", "path", "Optional model configuration file."), ArgumentSpec("bootstraps", "--bootstraps", "int", "Bootstrap iterations."), - ArgumentSpec("input_excel_protein", "--input-excel-protein", "path", "Protein input Excel file."), + ArgumentSpec("input_excel_protein", "--input-excel-protein", "path", "Protein input CSV file."), ArgumentSpec("input_excel_psite", "--input-excel-psite", "path", "Phosphosite input Excel file."), ArgumentSpec("input_excel_rna", "--input-excel-rna", "path", "RNA input Excel file."), ), - required_inputs=("protein Excel", "phosphosite Excel", "RNA Excel"), + required_inputs=("protein CSV", "phosphosite Excel", "RNA Excel"), input_assignments=( InputSpec("config", "Config file", "conf", "Optional ProtWise config file.", extensions=(".toml", ".yaml", ".yml", ".json")), - InputSpec("protein_file", "Protein file", "input_excel_protein", "Protein input Excel file.", extensions=(".xlsx",)), + InputSpec("protein_file", "Protein CSV file", "input_excel_protein", "Protein input CSV file read by ProtWise.", extensions=(".csv",)), InputSpec("phosphosite_file", "Phosphosite file", "input_excel_psite", "Phosphosite input Excel file.", extensions=(".xlsx",)), InputSpec("rna_file", "RNA/mRNA file", "input_excel_rna", "RNA input Excel file.", extensions=(".xlsx",)), ), @@ -171,11 +171,11 @@ class WorkflowDescriptor: required_inputs=("kinase network", "TF network", "MS/protein data", "RNA data", "phospho data"), input_assignments=( InputSpec("config", "Config file", "conf", "Optional networkmodel config file.", extensions=(".toml", ".yaml", ".yml", ".json")), - InputSpec("kinase_network", "Kinase network file", "kinase_net", "Kinase network CSV/TSV file.", extensions=(".csv", ".tsv")), - InputSpec("tf_network", "TF network file", "tf_net", "TF network CSV/TSV file.", extensions=(".csv", ".tsv")), - InputSpec("protein_file", "Protein/MS file", "ms", "Protein/MS data file.", extensions=(".csv", ".tsv", ".xlsx")), - InputSpec("rna_file", "RNA/mRNA file", "rna", "RNA data file.", extensions=(".csv", ".tsv", ".xlsx")), - InputSpec("phosphosite_file", "Phosphosite file", "phospho", "Phosphoproteomics data file.", extensions=(".csv", ".tsv", ".xlsx")), + InputSpec("kinase_network", "Kinase network CSV file", "kinase_net", "Kinase network CSV file read by networkmodel.", extensions=(".csv",)), + InputSpec("tf_network", "TF network CSV file", "tf_net", "TF network CSV file read by networkmodel.", extensions=(".csv",)), + InputSpec("protein_file", "Protein/MS CSV file", "ms", "Protein/MS CSV data file read by networkmodel.", extensions=(".csv",)), + InputSpec("rna_file", "RNA/mRNA CSV file", "rna", "RNA CSV data file read by networkmodel.", extensions=(".csv",)), + InputSpec("phosphosite_file", "Phosphoproteomics CSV file", "phospho", "Phosphoproteomics CSV data file read by networkmodel.", extensions=(".csv",)), InputSpec("previous_kinopt", "Previous KinOpt result", "kinopt", "Previous kinopt Excel result.", extensions=(".xlsx",)), InputSpec("previous_tfopt", "Previous TFOpt result", "tfopt", "Previous tfopt Excel result.", extensions=(".xlsx",)), InputSpec("networkmodel_result_dir", "Networkmodel result directory", None, "Reference result directory for browsing; not passed to CLI."), diff --git a/docs/Documentation/no_code_dashboard.md b/docs/Documentation/no_code_dashboard.md index 81f1149..750a038 100644 --- a/docs/Documentation/no_code_dashboard.md +++ b/docs/Documentation/no_code_dashboard.md @@ -62,6 +62,8 @@ dashboard_uploads// Uploads are not written into `data/` and are not modified silently. The dashboard checks for empty files, unsupported extensions, unreadable files, and duplicate filenames after sanitization. CSV, TSV, and Excel inputs can be previewed with pandas before they are assigned to a workflow. +Workflow-specific validation follows the backend readers. ProtWise protein input and Networkmodel kinase network, TF network, MS/protein, RNA, and phosphoproteomics inputs must be CSV files because those runners read them with `pandas.read_csv`. Excel remains valid only for workflow inputs that are actually read as Excel, such as ProtWise phosphosite/RNA files or previous KinOpt/TFOpt result workbooks. + ## Command preview and execution Before a run starts, the dashboard shows the exact command preview and the underlying argument list. This keeps runs reproducible and helps users copy the command into a terminal if preferred. diff --git a/tests/dashboard/test_command_builder.py b/tests/dashboard/test_command_builder.py index 5289b04..51602e4 100644 --- a/tests/dashboard/test_command_builder.py +++ b/tests/dashboard/test_command_builder.py @@ -83,3 +83,33 @@ def test_command_generation_from_assigned_inputs(tmp_path): def test_unsupported_input_roles_are_not_generated(tmp_path): with pytest.raises(ValueError, match="Unsupported input roles"): build_workflow_command("networkmodel", repo_root=tmp_path, input_assignments={"shell": "bad"}) + + +def test_networkmodel_command_with_csv_assignments_is_unchanged(tmp_path): + kinase = tmp_path / "kinase.csv" + tf = tmp_path / "tf.csv" + protein = tmp_path / "protein.csv" + rna = tmp_path / "rna.csv" + phospho = tmp_path / "phospho.csv" + for path in (kinase, tf, protein, rna, phospho): + path.write_text("col\nvalue\n", encoding="utf-8") + + built = build_workflow_command( + "networkmodel", + repo_root=tmp_path, + run_name="csv-inputs", + use_pixi=False, + input_assignments={ + "kinase_network": kinase, + "tf_network": tf, + "protein_file": protein, + "rna_file": rna, + "phosphosite_file": phospho, + }, + ) + + assert ["--kinase-net", str(kinase)] == built.command[built.command.index("--kinase-net"):built.command.index("--kinase-net") + 2] + assert ["--tf-net", str(tf)] == built.command[built.command.index("--tf-net"):built.command.index("--tf-net") + 2] + assert ["--ms", str(protein)] == built.command[built.command.index("--ms"):built.command.index("--ms") + 2] + assert ["--rna", str(rna)] == built.command[built.command.index("--rna"):built.command.index("--rna") + 2] + assert ["--phospho", str(phospho)] == built.command[built.command.index("--phospho"):built.command.index("--phospho") + 2] diff --git a/tests/dashboard/test_registry.py b/tests/dashboard/test_registry.py index 7e11ad3..3bd2bf4 100644 --- a/tests/dashboard/test_registry.py +++ b/tests/dashboard/test_registry.py @@ -43,3 +43,25 @@ def test_launchable_registry_entries_include_command_metadata(): assert kinopt.output_dir_arg == "--outdir" assert kinopt.accepted_arguments assert get_workflow("networkmodel").output_dir_arg == "--output-dir" + + +def _spec(workflow_key: str, role: str): + workflow = get_workflow(workflow_key) + return next(spec for spec in workflow.input_assignments if spec.role == role) + + +def test_protwise_protein_input_matches_csv_backend_reader(): + spec = _spec("protwise-model", "protein_file") + + assert spec.extensions == (".csv",) + assert "CSV" in spec.label + assert "Excel" not in spec.description + + +def test_networkmodel_input_specs_match_csv_backend_readers(): + roles = ("kinase_network", "tf_network", "protein_file", "rna_file", "phosphosite_file") + + for role in roles: + spec = _spec("networkmodel", role) + assert spec.extensions == (".csv",) + assert "CSV" in spec.label diff --git a/tests/dashboard/test_upload_validation.py b/tests/dashboard/test_upload_validation.py index 09a5894..930c22e 100644 --- a/tests/dashboard/test_upload_validation.py +++ b/tests/dashboard/test_upload_validation.py @@ -34,3 +34,70 @@ def test_validation_panel_helper_reports_duplicate_and_unknown_role(tmp_path): assert any("Duplicate filenames" in problem for problem in problems) assert any("Unsupported input role" in problem for problem in problems) + + +def _write_file(path): + path.write_text("col\nvalue\n", encoding="utf-8") + return path + + +def _validation_problems(workflow_key: str, role: str, path): + return validate_input_assignments(get_workflow(workflow_key), {role: str(path)}) + + +def test_protwise_protein_input_accepts_csv_and_rejects_xlsx(tmp_path): + csv = _write_file(tmp_path / "protein.csv") + xlsx = _write_file(tmp_path / "protein.xlsx") + + assert _validation_problems("protwise-model", "protein_file", csv) == [] + assert any(".csv" in problem for problem in _validation_problems("protwise-model", "protein_file", xlsx)) + + +def test_networkmodel_kinase_network_accepts_only_csv(tmp_path): + csv = _write_file(tmp_path / "kinase.csv") + tsv = _write_file(tmp_path / "kinase.tsv") + xlsx = _write_file(tmp_path / "kinase.xlsx") + + assert _validation_problems("networkmodel", "kinase_network", csv) == [] + assert any(".csv" in problem for problem in _validation_problems("networkmodel", "kinase_network", tsv)) + assert any(".csv" in problem for problem in _validation_problems("networkmodel", "kinase_network", xlsx)) + + +def test_networkmodel_tf_network_accepts_only_csv(tmp_path): + csv = _write_file(tmp_path / "tf.csv") + tsv = _write_file(tmp_path / "tf.tsv") + xlsx = _write_file(tmp_path / "tf.xlsx") + + assert _validation_problems("networkmodel", "tf_network", csv) == [] + assert any(".csv" in problem for problem in _validation_problems("networkmodel", "tf_network", tsv)) + assert any(".csv" in problem for problem in _validation_problems("networkmodel", "tf_network", xlsx)) + + +def test_networkmodel_ms_protein_data_accepts_only_csv(tmp_path): + csv = _write_file(tmp_path / "protein.csv") + tsv = _write_file(tmp_path / "protein.tsv") + xlsx = _write_file(tmp_path / "protein.xlsx") + + assert _validation_problems("networkmodel", "protein_file", csv) == [] + assert any(".csv" in problem for problem in _validation_problems("networkmodel", "protein_file", tsv)) + assert any(".csv" in problem for problem in _validation_problems("networkmodel", "protein_file", xlsx)) + + +def test_networkmodel_rna_data_accepts_only_csv(tmp_path): + csv = _write_file(tmp_path / "rna.csv") + tsv = _write_file(tmp_path / "rna.tsv") + xlsx = _write_file(tmp_path / "rna.xlsx") + + assert _validation_problems("networkmodel", "rna_file", csv) == [] + assert any(".csv" in problem for problem in _validation_problems("networkmodel", "rna_file", tsv)) + assert any(".csv" in problem for problem in _validation_problems("networkmodel", "rna_file", xlsx)) + + +def test_networkmodel_phospho_data_accepts_only_csv(tmp_path): + csv = _write_file(tmp_path / "phospho.csv") + tsv = _write_file(tmp_path / "phospho.tsv") + xlsx = _write_file(tmp_path / "phospho.xlsx") + + assert _validation_problems("networkmodel", "phosphosite_file", csv) == [] + assert any(".csv" in problem for problem in _validation_problems("networkmodel", "phosphosite_file", tsv)) + assert any(".csv" in problem for problem in _validation_problems("networkmodel", "phosphosite_file", xlsx)) From 5604439fb5c3428a51b0ea5dab6e4a77e163bb70 Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Wed, 10 Jun 2026 23:07:04 +0530 Subject: [PATCH 11/42] Fix ProtWise custom config handling --- config/config.py | 233 +++++++++++++++----- config/constants.py | 27 ++- protwise/runner/main.py | 289 +++++++++++++------------ tests/test_protwise_config_handling.py | 177 +++++++++++++++ 4 files changed, 532 insertions(+), 194 deletions(-) create mode 100644 tests/test_protwise_config_handling.py diff --git a/config/config.py b/config/config.py index 75b76c7..587e40f 100644 --- a/config/config.py +++ b/config/config.py @@ -2,7 +2,12 @@ import argparse import numpy as np from pathlib import Path -from typing import Optional +from typing import Optional, Any + +try: + import tomllib +except ModuleNotFoundError: # pragma: no cover + import tomli as tomllib from numba import njit from config.constants import ( @@ -82,47 +87,156 @@ def ensure_output_directory(directory): os.makedirs(directory, exist_ok=True) -def parse_args(): - """ - Parse command-line arguments for the PhosKinTime script. - This function uses argparse to define and handle the command-line options. - It includes options for setting bounds, fixed parameters, bootstrapping, - profile estimation, and input file paths. - The function returns the parsed arguments as a Namespace object. - The arguments include: - --A-bound, --B-bound, --C-bound, --D-bound, - --Ssite-bound, --Dsite-bound, --bootstraps, - --input-excel-protein, --input-excel-psite, --input-excel-rna. - Args: - None - Returns: - argparse.Namespace: The parsed command-line arguments. - """ +def _deep_merge(base: dict[str, Any], override: dict[str, Any]) -> dict[str, Any]: + out = dict(base) + for key, value in (override or {}).items(): + if isinstance(value, dict) and isinstance(out.get(key), dict): + out[key] = _deep_merge(out[key], value) + else: + out[key] = value + return out + + +def default_config_path() -> Path: + return PROJECT_ROOT / "config.toml" + + +def parse_config_path(argv: list[str] | None = None) -> Path | None: + pre_parser = argparse.ArgumentParser(add_help=False) + pre_parser.add_argument("--conf", default=None) + known, _ = pre_parser.parse_known_args(argv) + return Path(known.conf).expanduser() if known.conf else None + + +def _model_type(model: str) -> str: + return { + "protwise": "Protein-wise", + "distmod": "Distributive", + "succmod": "Successive", + "randmod": "Random", + }.get(str(model), "Unknown") + + +def load_selected_config(conf_path: str | Path | None = None) -> dict[str, Any]: + selected = Path(conf_path).expanduser().resolve() if conf_path else default_config_path().resolve() + with selected.open("rb") as handle: + raw = tomllib.load(handle) + ode = raw.get("ode", {}) or {} + modes = ode.get("modes", {}) or {} + merged = _deep_merge(ode, modes.get("local", {}) or {}) + merged["_paths"] = raw.get("paths", {}) or {} + merged["_root"] = str(PROJECT_ROOT) + merged["_config_path"] = str(selected) + merged["_config_source"] = "custom" if conf_path else "default" + return merged + + +def _path_from_config(root: Path, value: str | Path) -> Path: + path = Path(value).expanduser() + return path if path.is_absolute() else root / path + + +def _defaults_from_loaded_config(loaded_config: dict[str, Any]) -> dict[str, Any]: + root = Path(loaded_config.get("_root", PROJECT_ROOT)) + paths = loaded_config.get("_paths", {}) or {} + bounds = loaded_config.get("bounds", {}) or {} + bootstrap = loaded_config.get("bootstrap", {}) or {} + time = loaded_config.get("time", {}) or {} + inputs = loaded_config.get("inputs", {}) or {} + output = loaded_config.get("output", {}) or {} + fit = loaded_config.get("fit", {}) or {} + weights = fit.get("composite_weights", {}) or {} + sensitivity = loaded_config.get("sensitivity", {}) or {} + morris = sensitivity.get("morris", {}) or {} + + model = str(loaded_config.get("model", "randmod")) + model_type = _model_type(model) + results_dir = _path_from_config(root, paths.get("results_dir", "results")) + out_dir_name = str(output.get("out_dir_name") or "").strip() + out_xlsx_name = str(output.get("out_xlsx_name") or "").strip() + out_dir = results_dir / (out_dir_name or f"{model_type}_results") + + return { + "conf": None if loaded_config.get("_config_source") == "default" else loaded_config.get("_config_path"), + "resolved_config_path": loaded_config.get("_config_path"), + "config_source": loaded_config.get("_config_source", "default"), + "A_bound": (0.0, float(bounds.get("mRNA_prod", 20))), + "B_bound": (0.0, float(bounds.get("mRNA_deg", 20))), + "C_bound": (0.0, float(bounds.get("protein_prod", 20))), + "D_bound": (0.0, float(bounds.get("protein_deg", 20))), + "Ssite_bound": (0.0, float(bounds.get("phospho_prod", 20))), + "Dsite_bound": (0.0, float(bounds.get("phospho_deg", bounds.get("protein_deg", 20)))), + "bootstraps": int(bootstrap.get("n", 0)), + "input_excel_protein": _path_from_config(root, inputs.get("protein_excel", "data/input1.csv")), + "input_excel_psite": _path_from_config(root, inputs.get("psite_excel", "data/kinopt_results.xlsx")), + "input_excel_rna": _path_from_config(root, inputs.get("rna_excel", "data/tfopt_results.xlsx")), + "outdir": out_dir, + "out_results_dir": out_dir / (out_xlsx_name or f"{model_type}_results.xlsx"), + "time_points": np.asarray(time.get("protein", [0.0, 0.5, 0.75, 1.0, 2.0, 4.0, 8.0, 16.0, 30.0, 60.0, 120.0, 240.0, 480.0, 960.0]), dtype=float), + "time_points_rna": np.asarray(time.get("rna", [4.0, 8.0, 15.0, 30.0, 60.0, 120.0, 240.0, 480.0, 960.0]), dtype=float), + "model": model, + "model_type": model_type, + "dev_test": bool(loaded_config.get("dev_test", False)), + "use_regularization": bool(fit.get("use_regularization", True)), + "alpha_ci": float(loaded_config.get("alpha_ci", 0.95)), + "weights": { + "alpha": float(weights.get("rmse", 1.0)), + "beta": float(weights.get("mae", 1.0)), + "gamma": float(weights.get("var", 1.0)), + "delta": float(weights.get("mse", 1.0)), + "mu": float(weights.get("l2", 1.0)), + }, + "sensitivity": { + "enabled": bool(sensitivity.get("enabled", True)), + "metric": str(loaded_config.get("y_metric", "total_signal")), + "num_trajectories": int(morris.get("num_trajectories", 1000)), + "num_levels": int(morris.get("num_levels", 400)), + "perturbation": float(sensitivity.get("perturbation", 0.5)), + }, + } + + +def build_parser(defaults: dict[str, Any]) -> argparse.ArgumentParser: parser = argparse.ArgumentParser( description="PhosKinTime - ODE Parameter Estimation of Cell Signalling Events in Temporal Space" ) - parser.add_argument("--conf", default=None, help="Compatibility option; configuration is loaded before argument parsing.") - parser.add_argument("--A-bound", type=parse_bound_pair, default=f"0, {UB_mRNA_prod}") - parser.add_argument("--B-bound", type=parse_bound_pair, default=f"0, {UB_mRNA_deg}") - parser.add_argument("--C-bound", type=parse_bound_pair, default=f"0, {UB_Protein_prod}") - parser.add_argument("--D-bound", type=parse_bound_pair, default=f"0, {UB_Protein_deg}") - parser.add_argument("--Ssite-bound", type=parse_bound_pair, default=f"0, {UB_Phospho_prod}") - parser.add_argument("--Dsite-bound", type=parse_bound_pair, default=f"0, {UB_Protein_deg}") - parser.add_argument("--bootstraps", type=int, default=BOOTSTRAPS) - parser.add_argument("--input-excel-protein", type=str, - default=INPUT_EXCEL_PROTEIN, - help="Path to the original protein data file") - parser.add_argument("--input-excel-psite", type=str, - default=INPUT_EXCEL_PSITE, - help="Path to the estimated optimized phosphorylation-residue file") - parser.add_argument("--input-excel-rna", type=str, - default=INPUT_EXCEL_RNA, - help="Path to the estimated optimized mRNA-TF file") - parser.add_argument("--outdir", "--output-dir", dest="outdir", type=str, default=None, - help="Directory where all run outputs and provenance files are written.") - return parser.parse_args() - + parser.add_argument("--conf", default=defaults["conf"], help="Path to ProtWise/ODE TOML config file.") + parser.add_argument("--A-bound", type=parse_bound_pair, default=defaults["A_bound"]) + parser.add_argument("--B-bound", type=parse_bound_pair, default=defaults["B_bound"]) + parser.add_argument("--C-bound", type=parse_bound_pair, default=defaults["C_bound"]) + parser.add_argument("--D-bound", type=parse_bound_pair, default=defaults["D_bound"]) + parser.add_argument("--Ssite-bound", type=parse_bound_pair, default=defaults["Ssite_bound"]) + parser.add_argument("--Dsite-bound", type=parse_bound_pair, default=defaults["Dsite_bound"]) + parser.add_argument("--bootstraps", type=int, default=defaults["bootstraps"]) + parser.add_argument("--input-excel-protein", type=str, default=str(defaults["input_excel_protein"]), help="Path to the original protein data file") + parser.add_argument("--input-excel-psite", type=str, default=str(defaults["input_excel_psite"]), help="Path to the estimated optimized phosphorylation-residue file") + parser.add_argument("--input-excel-rna", type=str, default=str(defaults["input_excel_rna"]), help="Path to the estimated optimized mRNA-TF file") + parser.add_argument("--outdir", "--output-dir", dest="outdir", type=str, default=str(defaults["outdir"]), help="Directory where all run outputs and provenance files are written.") + return parser + + +def parse_args(argv: list[str] | None = None): + selected_config = parse_config_path(argv) + if selected_config is not None: + os.environ["PHOSKINTIME_ODE_CONFIG"] = str(selected_config.expanduser().resolve()) + loaded_config = load_selected_config(selected_config) + defaults = _defaults_from_loaded_config(loaded_config) + parser = build_parser(defaults) + args = parser.parse_args(argv) + args.resolved_config_path = str(Path(defaults["resolved_config_path"]).resolve()) + args.config_source = defaults["config_source"] + args.time_points = defaults["time_points"] + args.time_points_rna = defaults["time_points_rna"] + args.out_results_dir = str(Path(args.outdir) / Path(defaults["out_results_dir"]).name) + args.model = defaults["model"] + args.model_type = defaults["model_type"] + args.dev_test = defaults["dev_test"] + args.use_regularization = defaults["use_regularization"] + args.alpha_ci = defaults["alpha_ci"] + args.weights = defaults["weights"] + args.sensitivity = defaults["sensitivity"] + return args def log_config(logger, bounds, args): """ @@ -146,17 +260,11 @@ def log_config(logger, bounds, args): np.set_printoptions(suppress=True) -def extract_config(args): - """ - Extract configuration settings from command-line arguments. - This function creates a dictionary containing the parameter bounds, bootstrapping iterations. - The function returns the configuration dictionary. - - Args: - args (argparse.Namespace): The command-line arguments. - Returns: - dict: The configuration settings. +def extract_config(args, loaded_config: dict[str, Any] | None = None): + """ + Extract effective ProtWise runtime settings after config and CLI precedence + have been resolved. CLI values override values loaded from --conf/default config. """ bounds = { "A": args.A_bound, @@ -164,16 +272,29 @@ def extract_config(args): "C": args.C_bound, "D": args.D_bound, "S(i)": args.Ssite_bound, - "D(i)": args.Dsite_bound + "D(i)": args.Dsite_bound, } config = { - 'bounds': bounds, - 'bootstraps': args.bootstraps, - 'input_excel_protein': args.input_excel_protein, - 'input_excel_psite': args.input_excel_psite, - 'input_excel_rna': args.input_excel_rna, - 'max_workers': 1 if DEV_TEST else os.cpu_count(), - 'outdir': args.outdir, + "bounds": bounds, + "bootstraps": args.bootstraps, + "input_excel_protein": args.input_excel_protein, + "input_excel_psite": args.input_excel_psite, + "input_excel_rna": args.input_excel_rna, + "max_workers": 1 if getattr(args, "dev_test", DEV_TEST) else os.cpu_count(), + "outdir": args.outdir, + "out_results_dir": args.out_results_dir, + "time_points": args.time_points, + "time_points_rna": args.time_points_rna, + "supplied_config_path": args.conf, + "resolved_config_path": args.resolved_config_path, + "config_source": args.config_source, + "model": args.model, + "model_type": args.model_type, + "dev_test": args.dev_test, + "use_regularization": args.use_regularization, + "alpha_ci": args.alpha_ci, + "weights": args.weights, + "sensitivity": args.sensitivity, } return config diff --git a/config/constants.py b/config/constants.py index ba130c1..08cc8af 100644 --- a/config/constants.py +++ b/config/constants.py @@ -1,3 +1,4 @@ +import os import numpy as np import matplotlib.pyplot as plt import matplotlib.colors as mcolors @@ -7,12 +8,32 @@ from config.helpers import * from config_loader import load +try: + import tomllib +except ModuleNotFoundError: # pragma: no cover + import tomli as tomllib + # ------------------------------------------------------------------------------------------------- -# Load configuration (ODE section) from config.toml +# Load configuration (ODE section) from config.toml or the runner-selected custom file. # This module must not import tfopt/kinopt constants to avoid hard coupling / circular dependencies. # ------------------------------------------------------------------------------------------------- -_CFG = load("local", "ode") # mode is optional for ODE, but keeps a consistent API -_ROOT = Path(_CFG["_root"]) +CONFIG_ENV_VAR = "PHOSKINTIME_ODE_CONFIG" +_CONFIG_PATH = Path(os.environ[CONFIG_ENV_VAR]).expanduser().resolve() if os.environ.get(CONFIG_ENV_VAR) else None + +if _CONFIG_PATH is None: + _CFG = load("local", "ode") # mode is optional for ODE, but keeps a consistent API + _ROOT = Path(_CFG["_root"]) +else: + with _CONFIG_PATH.open("rb") as _fh: + _RAW_CFG = tomllib.load(_fh) + _ODE_BASE = (_RAW_CFG.get("ode", {}) or {}) + _ODE_MODES = (_ODE_BASE.get("modes", {}) or {}) + _CFG = {**_ODE_BASE, **(_ODE_MODES.get("local", {}) or {})} + _PATHS = _RAW_CFG.get("paths", {}) or {} + _ROOT = Path(__file__).resolve().parents[1] + _CFG["_paths"] = _PATHS + _CFG["_root"] = str(_ROOT) + _PATHS = _CFG.get("_paths", {}) or {} # Flag to indicate if the code is in development mode. diff --git a/protwise/runner/main.py b/protwise/runner/main.py index aefdde5..a606bb6 100644 --- a/protwise/runner/main.py +++ b/protwise/runner/main.py @@ -5,49 +5,34 @@ os.environ.setdefault("VECLIB_MAXIMUM_THREADS", "1") os.environ.setdefault("NUMEXPR_NUM_THREADS", "1") +import argparse import atexit import logging -import pandas as pd -from config.helpers import location -from config.config import parse_args, extract_config, log_config -from config.constants import (model_type, OUT_DIR, TIME_POINTS, OUT_RESULTS_DIR, DEV_TEST, - NUM_TRAJECTORIES, PARAMETER_SPACE, PERTURBATIONS_VALUE, ALPHA_CI, - SENSITIVITY_ANALYSIS, USE_REGULARIZATION, Y_METRIC, Y_METRIC_DESCRIPTIONS, - DELTA_WEIGHT, ALPHA_WEIGHT, BETA_WEIGHT, GAMMA_WEIGHT, MU_WEIGHT) -from config.logconf import setup_logger -from protwise.paramest.core import process_gene_wrapper -from protwise.plotting import Plotter -from common.utils import latexit -from common.results import ( - attach_file_console_logger, ensure_result_dir, populate_standard_subdirs, - write_command, write_metadata, write_resolved_config, -) -from common.utils.display import ensure_output_directory, save_result, organize_output_files, create_report, merge_obs_est - -logger = setup_logger() - -# Check if OUT_DIR, TIME_POINTS, OUT_RESULTS_DIR, ESTIMATION_MODE are defined -if OUT_DIR is None or TIME_POINTS is None or OUT_RESULTS_DIR is None: - logger.error("Output directory, time points, not defined. Exiting.") - exit(1) - -# Parse command line arguments and extract configuration -args = parse_args() - -# Check if the arguments are valid -if not args: - logger.error("Invalid arguments. Exiting.") - exit(1) -config = extract_config(args) - -if getattr(args, "outdir", None): - OUT_DIR = ensure_result_dir(args.outdir)["root"] - OUT_RESULTS_DIR = OUT_DIR / OUT_RESULTS_DIR.name - -# Check if the configuration is valid -if not config: - logger.error("Invalid configuration. Exiting.") - exit(1) +import sys +from pathlib import Path + +ODE_CONFIG_ENV = "PHOSKINTIME_ODE_CONFIG" + + +def _parse_config_path(argv: list[str] | None = None) -> Path | None: + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("--conf", default=None) + known, _ = parser.parse_known_args(argv) + return Path(known.conf).expanduser().resolve() if known.conf else None + + +def _select_config_for_runtime(argv: list[str] | None = None) -> None: + conf_path = _parse_config_path(argv) + if conf_path is not None: + os.environ[ODE_CONFIG_ENV] = str(conf_path) + for module_name in list(sys.modules): + if module_name in {"config.constants", "config.config"} or module_name.startswith(( + "protwise.paramest", + "protwise.plotting", + "protwise.models", + )): + sys.modules.pop(module_name, None) + @atexit.register def _close_log_handlers(): @@ -59,36 +44,92 @@ def _close_log_handlers(): except Exception: pass -def main(): - """ - Main function to run the phosphorylation modelling process. - It reads the configuration, loads the data, and processes each gene in parallel. - It also handles logging and output organization. - Args: - None - Returns: - None - """ - ensure_result_dir(OUT_DIR) - attach_file_console_logger(logger, OUT_DIR) - write_command(OUT_DIR) - write_resolved_config(OUT_DIR, config) +def _metadata_extra(config: dict) -> dict: + return { + "supplied_config_path": config.get("supplied_config_path"), + "resolved_config_path": config.get("resolved_config_path"), + "config_source": config.get("config_source"), + "effective_inputs": { + "protein": config.get("input_excel_protein"), + "phosphosite": config.get("input_excel_psite"), + "rna": config.get("input_excel_rna"), + }, + "effective_bounds": config.get("bounds"), + "effective_bootstraps": config.get("bootstraps"), + "effective_time_grid": config.get("time_points"), + "output_directory": config.get("outdir"), + } + + + +def initialize_run_contract(config: dict, args, logger): + from common.results import ( + attach_file_console_logger, + ensure_result_dir, + write_command, + write_metadata, + write_resolved_config, + ) + + out_dir = ensure_result_dir(config["outdir"])["root"] + out_results_dir = out_dir / Path(config["out_results_dir"]).name + config["outdir"] = str(out_dir) + config["out_results_dir"] = str(out_results_dir) + attach_file_console_logger(logger, out_dir) + write_command(out_dir) + write_resolved_config(out_dir, config) write_metadata( - OUT_DIR, + out_dir, workflow="protwise.runner", args=args, inputs=[config.get("input_excel_protein"), config.get("input_excel_psite"), config.get("input_excel_rna")], + extra=_metadata_extra(config), + ) + return out_dir, out_results_dir + +def main(argv: list[str] | None = None): + """ + Main function to run the phosphorylation modelling process. + It reads the selected configuration, loads the data, and processes each gene. + """ + _select_config_for_runtime(argv) + + import pandas as pd + from config.helpers import location + from config.config import parse_args, extract_config, log_config + from config.constants import ( + NUM_TRAJECTORIES, + PARAMETER_SPACE, + PERTURBATIONS_VALUE, + Y_METRIC_DESCRIPTIONS, ) + from config.logconf import setup_logger + from protwise.paramest.core import process_gene_wrapper + from protwise.plotting import Plotter + from common.utils import latexit + from common.results import populate_standard_subdirs + from common.utils.display import ensure_output_directory, save_result, organize_output_files, create_report, merge_obs_est + + logger = setup_logger() + args = parse_args(argv) + config = extract_config(args) + if not config: + logger.error("Invalid configuration. Exiting.") + return + + out_dir, out_results_dir = initialize_run_contract(config, args, logger) # Set up the logger + weights = config.get("weights", {}) + sensitivity = config.get("sensitivity", {}) logger.info(" --------------------------------") - logger.info(f"{model_type} Phosphorylation Modelling Configuration") + logger.info(f"{config['model_type']} Phosphorylation Modelling Configuration") logger.info(" --------------------------------") - log_config(logger, config['bounds'], args) - logger.info(f" i = Number of phosphorylation sites (Residue_Position) in the model") - logger.info(f" L2 Regularization: {USE_REGULARIZATION}") - logger.info(f" Confidence Interval: {ALPHA_CI*100}") + log_config(logger, config["bounds"], args) + logger.info(" i = Number of phosphorylation sites (Residue_Position) in the model") + logger.info(f" L2 Regularization: {config['use_regularization']}") + logger.info(f" Confidence Interval: {config['alpha_ci'] * 100}") logger.info(" --------------------------------") logger.info(" Composite Scoring Function:") logger.info(" score = α * RMSE + β * MAE + γ * Var(residuals) + δ * MSE + μ * L2 norm") @@ -101,57 +142,49 @@ def main(): logger.info(" - L2 norm: L2 norm of parameter estimates") logger.info(" --------------------------------") logger.info(" Weights:") - logger.info(f" - α (RMSE): {ALPHA_WEIGHT}") - logger.info(f" - β (MAE): {BETA_WEIGHT}") - logger.info(f" - γ (Var): {GAMMA_WEIGHT}") - logger.info(f" - δ (MSE): {DELTA_WEIGHT}") - logger.info(f" - μ (L2 norm): {MU_WEIGHT}") + logger.info(f" - α (RMSE): {weights.get('alpha')}") + logger.info(f" - β (MAE): {weights.get('beta')}") + logger.info(f" - γ (Var): {weights.get('gamma')}") + logger.info(f" - δ (MSE): {weights.get('delta')}") + logger.info(f" - μ (L2 norm): {weights.get('mu')}") logger.info(" --------------------------------") logger.info(" Lower score indicates a better fit.") logger.info(" --------------------------------") - logger.info(f" Sensitivity Analysis: {SENSITIVITY_ANALYSIS}") - if SENSITIVITY_ANALYSIS: - logger.info(f" - Metric: {' '.join(part.upper() for part in Y_METRIC.split('_'))}") - logger.info(f" - {Y_METRIC_DESCRIPTIONS.get(Y_METRIC, 'No description available.')}") - logger.info(f" - Number of Trajectories: {NUM_TRAJECTORIES}") - logger.info(f" - Parameter Space: {PARAMETER_SPACE}") - logger.info(f" - Perturbations: {PERTURBATIONS_VALUE}") + logger.info(f" Sensitivity Analysis: {sensitivity.get('enabled')}") + if sensitivity.get("enabled"): + metric = str(sensitivity.get("metric", "total_signal")) + logger.info(f" - Metric: {' '.join(part.upper() for part in metric.split('_'))}") + logger.info(f" - {Y_METRIC_DESCRIPTIONS.get(metric, 'No description available.')}") + logger.info(f" - Number of Trajectories: {sensitivity.get('num_trajectories', NUM_TRAJECTORIES)}") + logger.info(f" - Parameter Space: {sensitivity.get('num_levels', PARAMETER_SPACE)}") + logger.info(f" - Perturbations: {sensitivity.get('perturbation', PERTURBATIONS_VALUE)}") logger.info(" --------------------------------") - # Make output directory - ensure_output_directory(OUT_DIR) - # Load the data - protein_data = pd.read_csv(config['input_excel_protein']) - kinase_data = pd.read_excel(config['input_excel_psite'], sheet_name='Estimated') - mrna_data = pd.read_excel(config['input_excel_rna'], sheet_name='Estimated') + ensure_output_directory(out_dir) + + protein_data = pd.read_csv(config["input_excel_protein"]) + kinase_data = pd.read_excel(config["input_excel_psite"], sheet_name="Estimated") + mrna_data = pd.read_excel(config["input_excel_rna"], sheet_name="Estimated") - # Check if the data is empty if mrna_data.empty and kinase_data.empty and protein_data.empty: - logger.error("No data found in the input Excel files.") + logger.error("No data found in the input files.") return - # Check if the required columns are present: Gene, Psite, x1 - x14 - required_columns = ['Gene', 'Psite'] + [f'x{i}' for i in range(1, 15)] + required_columns = ["Gene", "Psite"] + [f"x{i}" for i in range(1, 15)] missing_columns = [col for col in required_columns if col not in kinase_data.columns and col not in protein_data.columns] if missing_columns: logger.error(f"Missing columns in the phosphorylation data: {', '.join(missing_columns)}") return - # Check if the required columns are present in mRNA data: mRNA, x1 - x9 - required_mrna_columns = ['mRNA'] + [f'x{i}' for i in range(1, 10)] + required_mrna_columns = ["mRNA"] + [f"x{i}" for i in range(1, 10)] missing_mrna_columns = [col for col in required_mrna_columns if col not in mrna_data.columns] if missing_mrna_columns: logger.error(f"Missing columns in the mRNA data: {', '.join(missing_mrna_columns)}") return - # Extract unique values from both datasets - proteins = set(kinase_data['Gene'].dropna().unique()) - mrnas = set(mrna_data['mRNA'].dropna().unique()) - - # Get sorted common proteins + proteins = set(kinase_data["Gene"].dropna().unique()) + mrnas = set(mrna_data["mRNA"].dropna().unique()) common_proteins = sorted(proteins.intersection(mrnas)) - - # Get sorted non-common proteins non_common = sorted(proteins.symmetric_difference(mrnas)) if not common_proteins: @@ -167,18 +200,15 @@ def main(): logger.info(" " + " ".join(f"[{gene}]" for gene in non_common)) logger.info(" --------------------------------") - if DEV_TEST: - # Load only gene 'X' - _test = "ABL2" - if _test in kinase_data["Gene"].values: - genes = kinase_data[kinase_data["Gene"] == _test]["Gene"].unique().tolist() + if config.get("dev_test"): + test_gene = "ABL2" + if test_gene in kinase_data["Gene"].values: + genes = kinase_data[kinase_data["Gene"] == test_gene]["Gene"].unique().tolist() else: - raise ValueError(f"{_test} not found in the input data.") + raise ValueError(f"{test_gene} not found in the input data.") else: - # Load all protein groups genes = common_proteins - # Check if the genes are empty if not genes: logger.error("No genes found in the input data.") return @@ -187,56 +217,45 @@ def main(): for gene in genes: logger.info(f"[{gene}] Processing...") result = process_gene_wrapper( - gene, protein_data, kinase_data, mrna_data, TIME_POINTS, - config['bounds'], config['bootstraps'] + gene, + protein_data, + kinase_data, + mrna_data, + config["time_points"], + config["bounds"], + config["bootstraps"], + out_dir=out_dir, ) results.append(result) - # Check if the results are empty if not results: logger.error("No results found after processing.") return - # Save the results - save_result(results, excel_filename=OUT_RESULTS_DIR) - - # Merge the observed data and model fits for each gene - merged_df = merge_obs_est(OUT_RESULTS_DIR) - - # Plot goodness of fit. - Plotter("", OUT_DIR).plot_gof(merged_df) - - # Plot Kullback-Leibler divergence. - Plotter("", OUT_DIR).plot_kld(merged_df) - - # Plot parameter relationships - profiles - Plotter("", OUT_DIR).plot_top_param_pairs(OUT_RESULTS_DIR) - - # Plot regularization term values. - Plotter("", OUT_DIR).plot_regularization(OUT_RESULTS_DIR) - - # Plot model protein wise errors. - Plotter("", OUT_DIR).plot_model_error(OUT_RESULTS_DIR) + save_result(results, excel_filename=out_results_dir) + merged_df = merge_obs_est(out_results_dir) + Plotter("", out_dir).plot_gof(merged_df) + Plotter("", out_dir).plot_kld(merged_df) + Plotter("", out_dir).plot_top_param_pairs(out_results_dir) + Plotter("", out_dir).plot_regularization(out_results_dir) + Plotter("", out_dir).plot_model_error(out_results_dir) logger.info("Plotting completed.") - # LateX the results - latexit.main(OUT_DIR) - - logger.info(f"LateX generated.") + latexit.main(out_dir) + logger.info("LateX generated.") - # Organize output files and create a report - organize_output_files([OUT_DIR]) - create_report(OUT_DIR) + organize_output_files([out_dir]) + create_report(out_dir) logger.info(" --------------------------------") - logger.info(f" Report & Results {location(str(OUT_DIR))}") - - # Click to open the report in a web browser. - for fpath in [OUT_DIR / 'report.html']: + logger.info(f" Report & Results {location(str(out_dir))}") + for fpath in [out_dir / "report.html"]: logger.info(f" {fpath.as_uri()}") - logger.info(" --------------------------------") + populate_standard_subdirs(out_dir) + + if __name__ == "__main__": main() diff --git a/tests/test_protwise_config_handling.py b/tests/test_protwise_config_handling.py new file mode 100644 index 0000000..5f4b600 --- /dev/null +++ b/tests/test_protwise_config_handling.py @@ -0,0 +1,177 @@ +from __future__ import annotations + +import json +import logging +from pathlib import Path + +import pytest + + +def _write_protwise_config(path: Path, outdir: Path) -> None: + path.write_text( + f''' +[paths] +data_dir = "data" +results_dir = "{outdir.parent.as_posix()}" +logs_dir = "{(outdir.parent / 'logs').as_posix()}" +ode_data_dir = "data" + +[ode] +model = "succmod" +dev_test = true +y_metric = "variance" +alpha_ci = 0.9 + +[ode.bounds] +mRNA_prod = 11 +mRNA_deg = 12 +protein_prod = 13 +protein_deg = 14 +phospho_prod = 15 +phospho_deg = 16 + +[ode.bootstrap] +n = 17 + +[ode.time] +protein = [0, 2, 4, 8] +rna = [4, 8, 16] + +[ode.fit] +use_regularization = false + +[ode.fit.composite_weights] +rmse = 1.1 +mae = 1.2 +var = 1.3 +mse = 1.4 +l2 = 1.5 + +[ode.sensitivity] +enabled = false +perturbation = 0.25 + +[ode.sensitivity.morris] +num_trajectories = 12 +num_levels = 6 + +[ode.inputs] +protein_excel = "custom/protein.csv" +psite_excel = "custom/psite.xlsx" +rna_excel = "custom/rna.xlsx" + +[ode.output] +out_dir_name = "{outdir.name}" +out_xlsx_name = "custom_results.xlsx" +''', + encoding="utf-8", + ) + + +def test_custom_protwise_conf_is_honored(tmp_path): + pytest.importorskip("numpy") + from config.config import parse_args, extract_config + + conf = tmp_path / "protwise.toml" + outdir = tmp_path / "configured-out" + _write_protwise_config(conf, outdir) + + args = parse_args(["--conf", str(conf)]) + config = extract_config(args) + + assert config["config_source"] == "custom" + assert Path(config["resolved_config_path"]) == conf.resolve() + assert config["input_excel_protein"].endswith("custom/protein.csv") + assert config["input_excel_psite"].endswith("custom/psite.xlsx") + assert config["input_excel_rna"].endswith("custom/rna.xlsx") + assert config["bounds"]["A"] == (0.0, 11.0) + assert config["bounds"]["B"] == (0.0, 12.0) + assert config["bounds"]["C"] == (0.0, 13.0) + assert config["bounds"]["D"] == (0.0, 14.0) + assert config["bounds"]["S(i)"] == (0.0, 15.0) + assert config["bounds"]["D(i)"] == (0.0, 16.0) + assert config["bootstraps"] == 17 + assert config["time_points"].tolist() == [0.0, 2.0, 4.0, 8.0] + assert Path(config["outdir"]) == outdir + + +def test_cli_flags_override_custom_protwise_conf(tmp_path): + pytest.importorskip("numpy") + from config.config import parse_args, extract_config + + conf = tmp_path / "protwise.toml" + configured_out = tmp_path / "configured-out" + cli_out = tmp_path / "cli-out" + _write_protwise_config(conf, configured_out) + + args = parse_args([ + "--conf", str(conf), + "--A-bound", "0,99", + "--bootstraps", "3", + "--outdir", str(cli_out), + ]) + config = extract_config(args) + + assert config["bounds"]["A"] == (0.0, 99.0) + assert config["bootstraps"] == 3 + assert Path(config["outdir"]) == cli_out + assert config["input_excel_protein"].endswith("custom/protein.csv") + + +def test_default_protwise_config_is_used_without_conf(): + pytest.importorskip("numpy") + from config.config import parse_args, extract_config, default_config_path + + args = parse_args([]) + config = extract_config(args) + + assert config["config_source"] == "default" + assert Path(config["resolved_config_path"]) == default_config_path().resolve() + assert config["supplied_config_path"] is None + + +def test_config_cli_model_forwards_custom_conf(monkeypatch, tmp_path): + pytest.importorskip("typer") + from config import cli + + calls = [] + monkeypatch.setattr(cli, "_run", lambda cmd: calls.append(cmd)) + conf = tmp_path / "protwise.toml" + conf.write_text("[ode]\n", encoding="utf-8") + + cli.model(conf=conf, outdir=tmp_path / "out") + + assert calls == [["protwise.runner.main", "--conf", str(conf), "--outdir", str(tmp_path / "out")]] + + +def test_importing_protwise_runner_does_not_parse_defaults(monkeypatch): + import importlib + + runner = importlib.import_module("protwise.runner.main") + + assert runner._parse_config_path(["--conf", "custom.toml"]) == Path("custom.toml").resolve() + + +def test_protwise_run_contract_records_custom_config(tmp_path): + pytest.importorskip("numpy") + pytest.importorskip("numba") + from config.config import parse_args, extract_config + from protwise.runner.main import initialize_run_contract + + conf = tmp_path / "protwise.toml" + outdir = tmp_path / "configured-out" + _write_protwise_config(conf, outdir) + args = parse_args(["--conf", str(conf)]) + config = extract_config(args) + + initialize_run_contract(config, args, logging.getLogger("protwise-test")) + + metadata = json.loads((outdir / "metadata.json").read_text(encoding="utf-8")) + assert (outdir / "config_resolved.yaml").is_file() + assert metadata["supplied_config_path"] == str(conf) + assert metadata["resolved_config_path"] == str(conf.resolve()) + assert metadata["config_source"] == "custom" + assert metadata["effective_inputs"]["protein"].endswith("custom/protein.csv") + assert metadata["effective_bounds"]["A"] == [0.0, 11.0] + assert metadata["effective_bootstraps"] == 17 + assert metadata["effective_time_grid"] == [0.0, 2.0, 4.0, 8.0] From 63fb6bb7debbacd7779a8ff934c58494e76a10db Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Thu, 11 Jun 2026 12:23:55 +0530 Subject: [PATCH 12/42] Add dashboard user, developer, and troubleshooting guides --- docs/dashboard_developer_guide.md | 182 +++++++++++++++++++ docs/dashboard_quickstart.md | 111 +++++++++++ docs/dashboard_troubleshooting.md | 215 ++++++++++++++++++++++ docs/dashboard_user_guide.md | 176 ++++++++++++++++++ docs/result_directory_contract.md | 147 +++++++++++++++ docs/workflow_cli_reference.md | 293 ++++++++++++++++++++++++++++++ mkdocs.yml | 6 + 7 files changed, 1130 insertions(+) create mode 100644 docs/dashboard_developer_guide.md create mode 100644 docs/dashboard_quickstart.md create mode 100644 docs/dashboard_troubleshooting.md create mode 100644 docs/dashboard_user_guide.md create mode 100644 docs/result_directory_contract.md create mode 100644 docs/workflow_cli_reference.md diff --git a/docs/dashboard_developer_guide.md b/docs/dashboard_developer_guide.md new file mode 100644 index 0000000..a1d594e --- /dev/null +++ b/docs/dashboard_developer_guide.md @@ -0,0 +1,182 @@ +# Dashboard developer guide + +## Architecture + +The dashboard package is organized as a thin UI and orchestration layer around existing backend CLIs. + +```text +dashboard/ +├── app.py +├── command_builder.py +├── runner.py +├── result_parser.py +├── file_utils.py +├── registry.py +├── components/ +└── workflow_panels/ +``` + +Key responsibilities: + +- `app.py` wires the Streamlit tabs together. +- `registry.py` describes workflows, CLI flags, input assignment roles, and file-extension rules. +- `command_builder.py` converts structured selections into argv lists. +- `runner.py` executes subprocesses from the repository root and streams logs. +- `result_parser.py` lazily inventories standard and legacy result layouts. +- `file_utils.py` handles safe path, upload, preview, and ZIP helpers. +- `components/` contains reusable Streamlit render functions. +- `workflow_panels/` contains workflow-specific result viewers and analysis command wrappers. + +## Design principles + +- Do not put scientific computation in Streamlit UI files. +- Do not execute user-generated shell strings. +- Never use `shell=True` for dashboard-built workflow commands. +- Build commands as `list[str]` argv values. +- Backend CLI remains the source of truth. +- Result parsing must support both the standard result directory contract and practical legacy layouts. +- Optional dependencies must fail gracefully and only be imported on the render path that needs them. +- Importing dashboard modules should not start Streamlit. +- File validation must match backend readers. + +## Workflow registry + +`dashboard/registry.py` defines `WorkflowDescriptor`, `ArgumentSpec`, and `InputSpec` records. + +Registry rules: + +- Accepted file extensions must match backend readers. +- Required inputs must match CLI behavior. +- Labels/help text must not overpromise support. +- `--conf` must be forwarded and honored by the backend runner. +- Explicit CLI flags override config values. +- `output_dir_arg` must match the workflow CLI (`--outdir` or `--output-dir`). +- `safe_for_dashboard` should be `False` for result-only descriptors or unsafe workflows. + +Important file-format examples: + +- ProtWise protein input is CSV because the runner reads it with `pd.read_csv`. +- Networkmodel network/data inputs are CSV because `networkmodel.io.load_data` uses default `pd.read_csv`. +- Previous KinOpt/TFOpt prior result inputs are Excel workbooks where the backend uses Excel readers. + +## Command builder + +`dashboard/command_builder.py` resolves a workflow key, structured arguments, input assignments, Pixi environment, and run name into a `BuiltCommand`. + +Precedence for configuration and arguments should remain: + +```text +explicit dashboard/CLI selection +> uploaded/selected config +> repository default config +> hard-coded fallback only where unavoidable +``` + +Guidelines: + +- Reject unknown argument names. +- Reject unknown input roles. +- Sanitize run names before constructing output paths. +- Keep output directories under the project `results/` area unless the user explicitly selects another path. +- Keep the command preview reproducible. + +## Runner + +`dashboard/runner.py` runs command lists with `subprocess.Popen(..., shell=False)` from the repository root. It merges stdout/stderr, streams output to the dashboard, and writes `console.log` in the run directory. + +Return status conventions: + +- `success` when return code is `0`. +- `failure` when return code is non-zero. +- `cancelled` when cancellation is requested and the process is terminated. + +Interactive cancellation is intentionally limited until a robust background job supervisor is introduced. The runner exposes a cancellation callback boundary for supervised execution. + +## Result parser + +`dashboard/result_parser.py` inventories files without eagerly loading large content. The parser recognizes: + +- standard files: `metadata.json`, `command.txt`, `console.log`, `config_resolved.yaml`; +- standard folders: `tables/`, `plots/`, `logs/`, `reports/`, `artifacts/`; +- legacy Networkmodel outputs such as `scalar_objective.csv`, prediction CSVs, `optimization/`, `profiles/`, `posterior/`, and `plots/`; +- legacy local result workbooks such as `kinopt_results.xlsx` and `tfopt_results.xlsx`. + +Load file contents only inside viewer components after the user selects a file. + +## Workflow panels + +Workflow panels should present existing outputs and call reusable backend functions where needed. Do not copy scientific logic into Streamlit callbacks. + +Existing apps and scripts to consider when adding or improving panels: + +- `app/kinopt.py` +- `app/tfopt.py` +- `networkmodel/dashboard_app.py` +- `scripts/compare_mechanisms.py` + +Refactor shared logic into reusable backend functions rather than copying code into dashboard files. + +## Adding a new workflow + +```text +1. Add or verify backend CLI +2. Ensure --outdir support +3. Ensure metadata/command/log output +4. Add registry entry +5. Add input specs +6. Add command builder tests +7. Add result parser tests +8. Add docs +``` + +Additional checklist: + +- Verify `--conf` precedence if the workflow supports config files. +- Add result-panel discovery helpers for workflow-specific outputs. +- Add missing-file tests. +- Add file-format validation tests matching backend readers. +- Ensure generated outputs are ignored by Git. + +## Testing + +Run the full configured dev test task: + +```bash +pixi run -e dev test +``` + +Useful focused tests: + +```text +tests/dashboard/test_command_builder.py +tests/dashboard/test_result_parser.py +tests/dashboard/test_registry.py +tests/dashboard/test_file_utils.py +tests/dashboard/test_runner.py +tests/dashboard/test_upload_validation.py +tests/dashboard/test_workflow_panels.py +tests/test_result_contract.py +tests/test_networkmodel_runner_config.py +tests/test_protwise_config_handling.py +``` + +Docs build: + +```bash +pixi run -e docs docs-build +``` + +## Git hygiene + +Generated/local folders should remain ignored and uncommitted: + +```text +dashboard_uploads/ +results/ +logs/ +*.zip +.streamlit/ +__pycache__/ +``` + +Do not commit result folders, uploaded files, logs, ZIP archives, local Streamlit state, or cache directories. diff --git a/docs/dashboard_quickstart.md b/docs/dashboard_quickstart.md new file mode 100644 index 0000000..5e66b6f --- /dev/null +++ b/docs/dashboard_quickstart.md @@ -0,0 +1,111 @@ +# Dashboard quickstart + +The PhosKinTime no-code dashboard is a Streamlit interface for users who want to run existing PhosKinTime workflows and inspect completed result folders without writing Python code. + +## What the dashboard does + +- Browses existing PhosKinTime result directories. +- Shows metadata, commands, logs, tables, plots, reports, artifacts, and ZIP downloads. +- Lets users upload/select input files into a dashboard-managed upload folder. +- Builds and previews safe CLI/Pixi commands for registered workflows. +- Runs registered workflows as subprocesses and streams console output. + +## What the dashboard does not do + +- It does not replace the CLI or Python API. +- It does not implement new scientific models. +- It does not silently convert file formats. +- It does not copy uploaded files into `data/` unless a user or backend command explicitly does so. +- It does not make long-running optimization jobs instant. + +## Install dependencies + +From the repository root: + +```bash +pixi install +``` + +For development and test dependencies: + +```bash +pixi run -e dev test +``` + +## Launch the dashboard + +```bash +pixi run dashboard +``` + +Development mode with Streamlit reload-on-save: + +```bash +pixi run dashboard-dev +``` + +After Streamlit starts, the terminal prints a local URL, usually `http://localhost:8501`. Open that URL in a browser. If Streamlit can open a browser automatically on your machine, it may do so. + +## Browse existing results + +1. Open the **Browse results** tab. +2. Select a base folder, commonly `results`. +3. Pick a result directory. +4. Inspect metadata, command, logs, tables, plots, reports, artifacts, and workflow-specific panels. +5. Use the **Download** tab to create a ZIP archive in memory. + +## Run a workflow from the dashboard + +1. Open the **Run workflow** tab. +2. Select a workflow. +3. Upload or select files. +4. Assign files to workflow input roles. +5. Review validation messages. +6. Preview the generated command. +7. Click **Run workflow**. +8. Watch console output and open the completed result directory. + +## Upload input files + +Uploaded files are saved under: + +```text +dashboard_uploads// +``` + +Supported upload extensions are `.csv`, `.tsv`, `.xlsx`, `.yaml`, `.yml`, `.json`, and `.txt`. Workflow execution validation may be stricter than upload validation. For example, Networkmodel execution inputs and the ProtWise protein input currently use CSV readers in the backend, so those assigned inputs must be `.csv`. + +## Download results + +The result browser can package the selected result directory into a ZIP file. The ZIP is generated in memory for browser download and should not be committed to Git. + +## Minimal command examples + +```bash +pixi install +pixi run dashboard +pixi run dashboard-dev +pixi run -e dev test +``` + +Workflow examples: + +```bash +pixi run kinopt-local --outdir results/example_kinopt +pixi run tfopt-local --outdir results/example_tfopt +pixi run model --conf config.toml --outdir results/example_protwise +pixi run networkmodel --conf config.toml --output-dir results/example_networkmodel +``` + +## Checklist + +```text +1. Start dashboard +2. Select or upload files +3. Select workflow +4. Preview command +5. Run +6. Inspect console +7. Browse results +8. Download ZIP +``` diff --git a/docs/dashboard_troubleshooting.md b/docs/dashboard_troubleshooting.md new file mode 100644 index 0000000..2f75800 --- /dev/null +++ b/docs/dashboard_troubleshooting.md @@ -0,0 +1,215 @@ +# Dashboard troubleshooting + +## Quick diagnostic table + +| Symptom | Likely cause | Fix | Diagnostic command | +| --- | --- | --- | --- | +| Dashboard does not start | Dependencies missing or Pixi environment incomplete | Reinstall and run dashboard from repo root | `pixi install && pixi run dashboard` | +| Streamlit import fails | Streamlit missing from active env | Use Pixi environment, not system Python | `pixi run python -c "import streamlit; print(streamlit.__version__)"` | +| Pixi command fails | Pixi not installed or environment broken | Reinstall Pixi/env | `pixi run python --version` | +| Uploaded file rejected | Registry extension validation failed | Use the backend-supported extension | Check dashboard validation panel | +| Custom `--conf` appears ignored | Runner imported config constants too early or CLI field overrides config | Inspect provenance | `cat results//metadata.json` | +| Result folder is empty | Workflow failed, wrong `--outdir`, permissions, or wrong selected folder | Inspect logs and command | `cat results//console.log` | +| Tables/plots are missing | Legacy output layout or workflow wrote elsewhere | Check metadata/command output path | `cat results//command.txt` | +| UI freezes during long run | Heavy workflow running in Streamlit callback/process | Use subprocess workflow launcher; wait for logs | Inspect `console.log` | +| Optional visualization missing | Optional package not installed | Add dependency with Pixi | `pixi add plotly` | +| Tests fail after dashboard edits | Registry/command/result contract changed | Run focused tests | `pixi run -e dev pytest tests/dashboard -v` | + +## Dashboard does not start + +Install or refresh dependencies: + +```bash +pixi install +pixi run dashboard +``` + +Check Streamlit: + +```bash +pixi run python -c "import streamlit; print(streamlit.__version__)" +``` + +Run from the repository root. Streamlit should print a local URL such as `http://localhost:8501`. + +## Pixi environment is broken + +Basic checks: + +```bash +pixi install +pixi run python --version +pixi run -e dev test +``` + +If the environment is corrupt, remove and recreate it: + +```bash +rm -rf .pixi/envs/default +pixi install +``` + +## PyCharm notebook/kernel issues + +PyCharm may use the wrong interpreter or Jupyter kernel. Check available kernels and the executable: + +```bash +pixi run jupyter kernelspec list +pixi run python -c "import sys; print(sys.executable)" +``` + +The expected interpreter is inside the Pixi environment: + +```text +.pixi/envs/default/bin/python +``` + +Register a kernel for notebooks: + +```bash +pixi run python -m ipykernel install --user --name phoskintime --display-name "Python (phoskintime)" +``` + +Select `Python (phoskintime)` in PyCharm/Jupyter. + +## `pip._internal.operations.build` error + +This usually means the Pixi environment's `pip` is corrupted, or PyCharm is trying to install packages through its own helper instead of using Pixi. + +Fix: + +```bash +rm -rf .pixi/envs/default +pixi install +pixi add pip ipykernel +``` + +Do not rely on the PyCharm package installer for Pixi-managed dependencies. Add dependencies through `pixi.toml`/`pixi add` so the environment remains reproducible. + +## Uploaded file rejected + +The upload panel accepts a broad set of extensions, but workflow assignment validation follows backend readers. + +- ProtWise protein input currently expects CSV when the backend uses `pd.read_csv`. +- Networkmodel kinase network, TF network, MS/protein, RNA, and phosphoproteomics inputs currently expect CSV with the default `pd.read_csv` reader. +- ProtWise phosphosite/RNA and previous KinOpt/TFOpt result inputs are Excel where the backend uses Excel readers. + +Use the extension shown in the validation message. + +## TSV/XLSX accepted but workflow fails + +This should not happen after registry validation fixes. If it happens, the dashboard registry and backend reader are inconsistent. + +Developer fix: + +1. Check the backend reader (`pd.read_csv`, `pd.read_excel`, custom separator, etc.). +2. Update `dashboard/registry.py` `InputSpec.extensions` to match the reader. +3. Add a validation test in `tests/dashboard/test_upload_validation.py`. +4. Update user docs. + +## Custom `--conf` appears ignored + +Expected priority: + +```text +explicit CLI/dashboard field +> custom --conf +> default config.toml +``` + +Diagnostics: + +```bash +cat results//metadata.json +cat results//config_resolved.yaml +cat results//command.txt +``` + +Check these fields: + +- supplied config path; +- resolved config path; +- config source/custom flag; +- effective inputs; +- effective bounds/lambdas/time grids; +- output directory. + +If a workflow imports config constants at module load time, it may ignore custom `--conf`. This is a bug and should be fixed in the runner by parsing `--conf` before importing config-dependent modules. + +## Result folder is empty + +Likely causes: + +- workflow failed before writing outputs; +- wrong `--outdir`/`--output-dir`; +- permission issue; +- dashboard pointed at the wrong result directory. + +Diagnostics: + +```bash +cat results//console.log +cat results//command.txt +``` + +If `console.log` is missing, the runner may have failed before result contract initialization. + +## Dashboard cannot find tables/plots + +Likely causes: + +- legacy output layout; +- workflow did not follow result directory contract; +- output was written elsewhere; +- selected directory is a parent folder rather than the run folder. + +Fix: + +1. Open `metadata.json` and `command.txt`. +2. Confirm the command used the expected output directory. +3. Search the selected run folder for generated files. +4. If needed, update `dashboard/result_parser.py` to recognize a documented legacy layout. + +## Long-running workflow freezes UI + +Heavy workflows should run as subprocesses or external workers, not as scientific computation inside Streamlit callbacks. The dashboard launcher uses subprocess execution for registered workflows. If a new panel triggers expensive analysis directly, refactor it into a backend CLI/function and call it through the runner or a supervised job mechanism. + +## Missing optional dependency + +Examples: + +- `gravis` +- `networkx` +- `imageio` +- `openpyxl` +- `plotly` + +Install through Pixi only: + +```bash +pixi add openpyxl +pixi add plotly +``` + +For visualization extras already modeled as a Pixi feature, prefer the appropriate Pixi environment if documented. + +## Tests fail after dashboard changes + +Run the configured test task: + +```bash +pixi run -e dev test +``` + +Isolate dashboard tests: + +```bash +pixi run -e dev pytest tests/dashboard -v +``` + +Common causes: + +- registry `InputSpec` does not match backend reader; +- command builder accepts unsupported arguments; +- result parser no longer recognizes a legacy layout; +- a dashboard module imports Streamlit or optional heavy dependencies at module import time. diff --git a/docs/dashboard_user_guide.md b/docs/dashboard_user_guide.md new file mode 100644 index 0000000..9e8b1d3 --- /dev/null +++ b/docs/dashboard_user_guide.md @@ -0,0 +1,176 @@ +# Dashboard user guide + +## Overview + +The PhosKinTime dashboard is a no-code wrapper around existing PhosKinTime command-line workflows. It helps users choose files, preview commands, launch supported workflows, monitor logs, and browse output folders. + +```text +Dashboard = wrapper + launcher + result viewer +CLI = source of truth +Scientific modules = model logic +``` + +The dashboard should be used for convenience and reproducibility. The CLI and backend modules remain authoritative for scientific behavior. + +## Supported workflows + +| Workflow | Purpose | Expected inputs | Accepted execution formats | Output location | Runtime class | Dashboard execution | Result-only viewing | +| --- | --- | --- | --- | --- | --- | --- | --- | +| `prep` | Run preprocessing cleanup via `processing.cleanup`. | Files referenced by repository configuration and preprocessing conventions. | Config/data dependent. | Existing preprocessing outputs; no dedicated dashboard output flag. | Short | Yes | Limited | +| `kinopt-local` / `kinopt` | Local kinase-to-phosphosite optimization. | Protein/kinase abundance CSV, phosphosite CSV/network data, optional config. | Registered config files: `.toml`, `.yaml`, `.yml`, `.json`; workflow data follows backend config. | `results/kinopt-local//` when launched by dashboard; CLI `--outdir` supported. | Medium | Yes | Yes | +| `kinopt-evol` | Evolutionary KinOpt mode exposed as a Pixi task. | Same family of KinOpt inputs, governed by backend config. | Backend dependent. | Backend-defined outputs. | Medium/long | Not directly registered in dashboard launcher | Result folders can be browsed if contract/legacy layout is present | +| `tfopt-local` / `tfopt` | Local TF-to-mRNA optimization. | mRNA/RNA CSV, TF network CSV, optional config. | Registered config files: `.toml`, `.yaml`, `.yml`, `.json`; workflow data follows backend config. | `results/tfopt-local//` when launched by dashboard; CLI `--outdir` supported. | Medium | Yes | Yes | +| `tfopt-evol` | Evolutionary TFOpt mode exposed as a Pixi task. | Same family of TFOpt inputs, governed by backend config. | Backend dependent. | Backend-defined outputs. | Medium/long | Not directly registered in dashboard launcher | Result folders can be browsed if contract/legacy layout is present | +| `protwise-model` / `model` | Protein-wise ODE fitting downstream of KinOpt/TFOpt. | Protein CSV, phosphosite Excel workbook, RNA/TFOpt Excel workbook, optional TOML config. | Protein input: `.csv`; phosphosite and RNA result inputs: `.xlsx`; config: `.toml`, `.yaml`, `.yml`, `.json` in dashboard assignment. | `results/protwise-model//` when launched by dashboard; CLI `--outdir` supported. | Medium/long | Yes | Yes | +| `networkmodel` | Coupled kinase-signaling and TF/RNA global network model. | Kinase network CSV, TF network CSV, MS/protein CSV, RNA CSV, optional phosphoproteomics CSV, optional KinOpt/TFOpt Excel priors, TOML config. | Network/data inputs read by backend with `pandas.read_csv`: `.csv` only; prior result workbooks: `.xlsx`. | `results/networkmodel//` when launched by dashboard; CLI `--output-dir`/`--outdir` supported. | Long | Yes | Yes | +| `phoskintime-all` | Typer wrapper for preprocessing, local TFOpt, local KinOpt, and ProtWise. | Stage-specific configs for TFOpt/KinOpt/ProtWise. | Config assignment: `.toml`, `.yaml`, `.yml`, `.json`. | `results/phoskintime-all//` when launched by dashboard. | Long | Yes | Stage result folders can be browsed | +| Advanced analysis scripts | Existing analysis utilities such as curve similarity, protein accumulator detection, subnetwork export, mechanistic insights, temporal sensitivity, and mechanism comparison. | Existing result folders/tables, depending on script. | Script-specific; do not assume upload conversion. | Selected run directory under `tables/`, `plots/`, `reports/`, or `artifacts/` when integrated. | Medium/long | Exposed as parameterized wrappers where available; not run automatically | Yes | + +## Launching the dashboard + +Install dependencies first: + +```bash +pixi install +``` + +Start the user dashboard: + +```bash +pixi run dashboard +``` + +Start development mode with reload-on-save: + +```bash +pixi run dashboard-dev +``` + +Streamlit prints a local browser URL such as `http://localhost:8501`. + +## Browsing existing results + +Use **Browse results** to select a result directory. The dashboard discovers standard contract files and known legacy outputs. + +The browser can show: + +- `metadata.json` provenance. +- `command.txt` command provenance. +- `console.log` and `logs/*`. +- Tables from `tables/*.csv`, `tables/*.tsv`, and `tables/*.xlsx`. +- Plots from `plots/*.png`, `plots/*.jpg`, `plots/*.jpeg`, `plots/*.svg`, and `plots/*.html`. +- Reports from `reports/*.html`, `reports/*.md`, and PDFs where possible. +- Artifacts from `artifacts/*`. +- A downloadable ZIP archive of the selected result directory. + +If standard files are missing, the dashboard still attempts to show recognized legacy outputs and reports what is missing. + +## Uploading files + +Uploaded files are stored in: + +```text +dashboard_uploads// +``` + +Uploaded files are not silently copied into `data/`. The command preview points to the uploaded/selected path used by the backend. + +General upload extensions accepted by the UI are: + +```text +.csv, .tsv, .xlsx, .yaml, .yml, .json, .txt +``` + +Workflow execution validation is stricter and follows backend readers: + +- ProtWise protein input currently expects CSV because the backend reads it with `pd.read_csv`. +- ProtWise phosphosite and RNA result inputs currently expect Excel workbooks. +- Networkmodel kinase network, TF network, MS/protein data, RNA data, and phosphoproteomics inputs currently expect CSV because the backend reads them with default `pd.read_csv`. +- Networkmodel previous KinOpt/TFOpt result priors remain Excel workbooks. + +## Running workflows + +The dashboard-generated command is shown before execution. These are representative commands using actual Pixi task names from `pixi.toml`: + +```bash +pixi run kinopt-local --outdir results/example_kinopt +``` + +```bash +pixi run tfopt-local --outdir results/example_tfopt +``` + +```bash +pixi run model --conf config.toml --outdir results/example_protwise +``` + +```bash +pixi run networkmodel --conf config.toml --output-dir results/example_networkmodel +``` + +Additional actual tasks include: + +```bash +pixi run prep +pixi run kinopt-evol +pixi run tfopt-evol +pixi run phoskintime-all +``` + +Use long-running workflows with care. Networkmodel and full integrated runs can take substantially longer than local parsing or result browsing. + +## Command preview + +The dashboard shows the exact command and argument list before running because: + +- users can copy/paste it into a terminal; +- the command can be recorded in `command.txt`; +- it makes file paths and config choices visible; +- it prevents hidden free-text shell execution. + +Commands are built as argument lists, not shell strings. + +## Result interpretation + +Common output groups: + +| Folder | Meaning | +| --- | --- | +| `tables/` | CSV, TSV, Excel, JSON, NumPy, or other table-like outputs. | +| `plots/` | Static and interactive plots. | +| `logs/` | Auxiliary logs beyond the root `console.log`. | +| `reports/` | HTML, Markdown, or PDF reports. | +| `artifacts/` | Pickles, serialized bundles, intermediate arrays, and files that are useful for reloading or debugging. | + +Workflow-specific tabs add convenience views for KinOpt, TFOpt, ProtWise, Networkmodel, and advanced analyses when recognized files are present. + +## Downloading results + +Open the **Download** tab in a selected result directory and click **Prepare ZIP archive**. The ZIP is generated in memory and served to the browser. It is not written into the repository by default. + +## Reproducibility + +A dashboard-ready run should contain: + +- `metadata.json` — workflow identity, timestamps, environment details, config provenance, input hashes where practical, and selected parameters. +- `command.txt` — exact or reconstructed command invocation. +- `console.log` — stdout/stderr or logger output. +- `config_resolved.yaml` or `config_resolved.toml` — effective resolved configuration after defaults and CLI overrides. + +Config precedence is: + +```text +explicit CLI/dashboard field +> custom --conf +> repository config.toml +> hard-coded fallback only where unavoidable +``` + +## Known limitations + +- Long-running jobs can take minutes or hours. +- Large result folders may load slowly, especially large HTML reports or many images. +- Optional visualization dependencies may be missing in minimal environments. +- The dashboard does not replace CLI/API workflows. +- The dashboard does not change scientific model assumptions. +- Workflow validation should match backend readers; if a backend cannot read TSV/XLSX, the dashboard should not permit those formats for execution. diff --git a/docs/result_directory_contract.md b/docs/result_directory_contract.md new file mode 100644 index 0000000..b593e97 --- /dev/null +++ b/docs/result_directory_contract.md @@ -0,0 +1,147 @@ +# Result directory contract + +PhosKinTime workflows should write outputs into a predictable result directory so the dashboard, tests, and downstream tools can parse runs without workflow-specific guesses. + +## Standard layout + +```text +results// +├── metadata.json +├── command.txt +├── console.log +├── config_resolved.yaml +├── tables/ +├── plots/ +├── logs/ +├── reports/ +└── artifacts/ +``` + +`config_resolved.toml` is also acceptable when a workflow naturally writes TOML. Current shared helpers write `config_resolved.yaml`. + +## Files and folders + +| Path | Required? | Purpose | Expected formats | Produced by | Dashboard use | +| --- | --- | --- | --- | --- | --- | +| `metadata.json` | Required for new runs | Machine-readable provenance: workflow, environment, config, inputs, status, settings. | JSON | CLI wrappers, dashboard runner, backend runners | Rendered in Metadata tab; used to infer workflow. | +| `command.txt` | Required for new runs | Exact or reconstructed invocation. | Plain text | CLI wrappers and dashboard runner | Rendered as command provenance. | +| `console.log` | Required when run through CLI/dashboard logging | Combined stdout/stderr or logger output. | Text/log | CLI wrappers and dashboard runner | Rendered in Logs tab and failure tail. | +| `config_resolved.yaml` / `config_resolved.toml` | Required when config/defaults are used | Effective config after default resolution and CLI overrides. | YAML/TOML/JSON-compatible YAML | Config-aware workflows | Rendered in Metadata tab for reproducibility. | +| `tables/` | Required folder, contents optional | Tabular outputs and mirrored legacy tables. | `.csv`, `.tsv`, `.xlsx`, `.xls`, `.json`, `.npy`, `.npz`, `.parquet` | All workflows as applicable | Listed lazily; shown with `st.dataframe` where supported. | +| `plots/` | Required folder, contents optional | Static and interactive figures. | `.png`, `.jpg`, `.jpeg`, `.svg`, `.html`, sometimes `.pdf` | Optimization, fitting, analysis workflows | Displayed with image/HTML viewers. | +| `logs/` | Required folder, contents optional | Auxiliary logs beyond root `console.log`. | Text/log files | Workflows and analysis scripts | Listed in Logs tab. | +| `reports/` | Required folder, contents optional | Human-readable reports. | `.html`, `.md`, `.pdf` | ProtWise, Networkmodel, analysis scripts | Rendered when possible; downloadable. | +| `artifacts/` | Required folder, contents optional | Serialized states and non-table artifacts. | `.pkl`, `.pickle`, `.joblib`, arbitrary files | Networkmodel, analyses, dashboard bundles | Downloadable; some workflow panels may parse known artifacts. | + +## Metadata schema + +New producers should include at least the following conceptual fields. Names may differ slightly for legacy runs, but dashboard-facing writers should prefer these stable keys when possible. + +```json +{ + "workflow": "networkmodel", + "run_id": "example", + "timestamp_start": "...", + "timestamp_end": "...", + "status": "success", + "return_code": 0, + "command": ["pixi", "run", "..."], + "config_path": "config.toml", + "custom_config_used": false, + "output_dir": "results/example", + "python_version": "...", + "package_version": "...", + "git_commit": "...", + "inputs": {}, + "parameters": {} +} +``` + +Current shared metadata helpers also record fields such as `command_arguments`, `output_directory`, `python_executable`, `pixi_environment`, input hashes, and workflow-specific effective settings. + +Recommended metadata details: + +- Use paths relative to the repository root where possible. +- Include resolved absolute paths only when useful for debugging local runs. +- Include file hashes for user inputs where practical. +- Record config priority outcomes: supplied `--conf`, resolved config path, default/custom config source, and effective settings. +- Record status and return code for dashboard-launched subprocesses. + +## Config precedence + +Workflow runners should resolve settings in this order: + +```text +explicit CLI/dashboard field +> custom --conf +> repository config.toml +> hard-coded fallback only where unavoidable +``` + +`config_resolved.*` should represent the effective configuration after this precedence is applied. + +## Legacy layout support + +The dashboard result parser recognizes selected legacy outputs so older runs can still be browsed. Known examples include: + +- Networkmodel top-level `scalar_objective.csv`, `convergence_history.csv`, `pred_prot_picked.csv`, `pred_rna_picked.csv`, `pred_phospho_picked.csv`. +- Networkmodel `optimization/`, `profiles/`, `posterior/`, and `plots/` folders. +- Legacy `kinopt_results.xlsx` and `tfopt_results.xlsx` workbooks. +- Top-level `report.html` where present. + +Legacy support is compatibility behavior. New workflow code should still write the standard folders and provenance files. + +## Workflow-specific expected outputs + +### KinOpt + +Expected outputs include: + +- `kinopt_results.xlsx` or a mirrored copy under `tables/`; +- alpha/beta or equivalent parameter tables; +- observed-vs-estimated sheets/tables when available; +- fit and diagnostic plots under `plots/`; +- logs and provenance files. + +### TFOpt + +Expected outputs include: + +- `tfopt_results.xlsx` or a mirrored copy under `tables/`; +- TF alpha/beta or equivalent tables; +- latent activity, dominance, knockout, or fit outputs when generated; +- plots and reports under standard folders; +- logs and provenance files. + +### ProtWise + +Expected outputs include: + +- protein-wise ODE fit workbook/tables; +- residuals, fitted predictions, sensitivity outputs when generated; +- goodness-of-fit and diagnostic plots; +- `report.html` under `reports/` or mirrored from top level; +- provenance and resolved config. + +### Networkmodel + +Expected outputs include: + +- scalar objective/convergence CSVs; +- picked protein/RNA/phospho prediction CSVs; +- `dashboard_bundle.pkl` and optimization artifacts; +- optimization/profile/posterior subfolders; +- fit plots and steady-state/network plots; +- provenance and resolved config. + +### Scripts and advanced analyses + +Advanced analysis scripts should write into the selected run directory: + +- tables to `tables/`; +- figures to `plots/`; +- narrative outputs to `reports/`; +- serialized or miscellaneous outputs to `artifacts/`; +- logs to `logs/` or root `console.log` when run through the dashboard runner. + +Scripts should not write into input data folders unless an explicit, documented export action requests it. diff --git a/docs/workflow_cli_reference.md b/docs/workflow_cli_reference.md new file mode 100644 index 0000000..0cd7c25 --- /dev/null +++ b/docs/workflow_cli_reference.md @@ -0,0 +1,293 @@ +# Workflow CLI reference + +This reference lists actual Pixi tasks and Typer wrapper commands present in the repository. The CLI remains the source of truth for workflow execution; the dashboard builds and previews these commands. + +## Config precedence + +For workflows that support `--conf`: + +```text +Explicit CLI flags override values from --conf. +Values from --conf override repository defaults. +If --conf is not supplied, repository config.toml is used. +``` + +Do not assume a custom config was used unless `metadata.json` and `config_resolved.*` confirm it. + +## Pixi tasks + +| Task | Purpose | Backend command/module | Example | +| --- | --- | --- | --- | +| `prep` | Preprocessing cleanup. | `python -m processing.cleanup` | `pixi run prep` | +| `kinopt-local` | Local KinOpt. | `python -m kinopt.local` | `pixi run kinopt-local --outdir results/example_kinopt` | +| `kinopt-evol` | Evolutionary KinOpt. | `python -m kinopt.evol` | `pixi run kinopt-evol` | +| `kinopt-fitanalysis` | KinOpt fit analysis. | `python -m kinopt.fitanalysis` | `pixi run kinopt-fitanalysis` | +| `tfopt-local` | Local TFOpt. | `python -m tfopt.local` | `pixi run tfopt-local --outdir results/example_tfopt` | +| `tfopt-evol` | Evolutionary TFOpt. | `python -m tfopt.evol` | `pixi run tfopt-evol` | +| `model` | ProtWise model runner. | `python -m protwise.runner.main` | `pixi run model --conf config.toml --outdir results/example_protwise` | +| `networkmodel` | Global network model runner. | `python -m networkmodel.runner` | `pixi run networkmodel --conf config.toml --output-dir results/example_networkmodel` | +| `phoskintime` | Typer workflow wrapper. | `python -m phoskintime.config.cli` | `pixi run phoskintime --help` | +| `phoskintime-all` | Typer wrapper `all` command. | `python -m phoskintime.config.cli all` | `pixi run phoskintime-all` | +| `network-dashboard` | Legacy Networkmodel dashboard launcher. | `python run_dashboard.py` | `pixi run network-dashboard` | +| `dashboard` | Unified no-code dashboard. | `streamlit run dashboard/app.py` | `pixi run dashboard` | +| `dashboard-dev` | Unified dashboard with reload-on-save. | `streamlit run dashboard/app.py --server.runOnSave=true` | `pixi run dashboard-dev` | +| `test` | Run pytest with project path. | `PYTHONPATH=.:.. pytest` | `pixi run -e dev test` | +| `test-notebooks` | Execute notebooks as tests. | `pytest --nbmake notebooks/*.ipynb` | `pixi run -e dev test-notebooks` | +| `test-cov` | Coverage test run. | `pytest --cov=...` | `pixi run -e dev test-cov` | +| `check-import` | Import smoke check. | Python one-liner | `pixi run check-import` | +| `docs-serve` | Serve documentation. | `zensical serve` | `pixi run -e docs docs-serve` | +| `docs-build` | Build documentation. | `zensical build` | `pixi run -e docs docs-build` | + +## Typer wrapper commands (`config/cli.py`) + +These commands are available through the package CLI wrapper when invoked as the configured module. + +### `prep` + +- Purpose: run preprocessing cleanup. +- Backend module: `processing.cleanup`. +- Required inputs: project preprocessing inputs. +- Config support: no explicit `--conf` on wrapper command. +- Output directory flag: none. +- Example: + +```bash +pixi run phoskintime prep +``` + +Dashboard integration: registered as `prep`. + +### `kinopt` + +- Purpose: run KinOpt local or evolutionary mode. +- Backend module: `kinopt.`. +- Required inputs: KinOpt inputs configured in `config.toml`/backend constants. +- Config support: `--conf`. +- Output directory flag: `--outdir` / `--output-dir` for local mode. +- Optional arguments: `--mode local|evol`. +- Example: + +```bash +pixi run phoskintime kinopt --mode local --conf config.toml --outdir results/example_kinopt +``` + +Dashboard integration: local mode registered as `kinopt-local`. + +### `tfopt` + +- Purpose: run TFOpt local or evolutionary mode. +- Backend module: `tfopt.`. +- Required inputs: TFOpt inputs configured in `config.toml`/backend constants. +- Config support: `--conf`. +- Output directory flag: `--outdir` / `--output-dir` for local mode. +- Optional arguments: `--mode local|evol`. +- Example: + +```bash +pixi run phoskintime tfopt --mode local --conf config.toml --outdir results/example_tfopt +``` + +Dashboard integration: local mode registered as `tfopt-local`. + +### `model` + +- Purpose: run ProtWise protein-wise ODE fitting. +- Backend module: `protwise.runner.main`. +- Required inputs: protein CSV, phosphosite Excel workbook, RNA/TFOpt Excel workbook. +- Config support: `--conf`; custom config values are used unless overridden by explicit CLI fields. +- Output directory flag: `--outdir` / `--output-dir`. +- Example: + +```bash +pixi run phoskintime model --conf config.toml --outdir results/example_protwise +``` + +Dashboard integration: registered as `protwise-model` / Pixi task `model`. + +### `networkmodel` + +- Purpose: run the integrated global network model. +- Backend module: `networkmodel.runner`. +- Required inputs: kinase network CSV, TF network CSV, MS/protein CSV, RNA CSV, optional phosphoproteomics CSV, optional KinOpt/TFOpt Excel priors. +- Config support: `--conf`; custom config values are used unless overridden by explicit CLI fields. +- Output directory flag: `--outdir` / `--output-dir`; dashboard uses `--output-dir`. +- Example: + +```bash +pixi run phoskintime networkmodel --conf config.toml --outdir results/example_networkmodel +``` + +Dashboard integration: registered as `networkmodel`. + +### `all` + +- Purpose: run preprocessing, TFOpt, KinOpt, and ProtWise model stages in sequence. +- Backend modules: `processing.cleanup`, `tfopt.`, `kinopt.`, `protwise.runner.main`. +- Config support: `--tf-conf`, `--kin-conf`, `--model-conf`. +- Output directory flag: `--outdir` / `--output-dir` as a base directory for stage outputs. +- Example: + +```bash +pixi run phoskintime-all --outdir results/example_all +``` + +Dashboard integration: registered as `phoskintime-all`. + +### `clean` + +- Purpose: remove bytecode, cache, and build artifacts. +- Backend: filesystem cleanup in `config/cli.py`. +- Config support: none. +- Output directory flag: none. +- Example: + +```bash +pixi run phoskintime clean +``` + +Dashboard integration: not a dashboard workflow. + +## Workflow details + +### Preprocessing / `prep` + +- Command name: `prep`. +- Purpose: cleanup/preprocessing. +- Backend module: `processing.cleanup`. +- Required inputs: repository raw/processing inputs. +- Optional arguments: none in the Pixi task. +- Config file support: not exposed by task. +- Output directory flag: none. +- Expected outputs: preprocessing outputs defined by `processing.cleanup`. +- Dashboard status: executable from dashboard registry; result browsing is limited unless outputs follow the result contract. + +### KinOpt local + +- Command name: `kinopt-local`. +- Purpose: local kinase/phosphosite optimization. +- Backend module: `kinopt.local`. +- Required inputs: configured KinOpt input files, commonly CSV files under `data/`. +- Optional arguments include `--conf`, `--lower_bound`, `--upper_bound`, `--loss_type`, and `--method` where supported. +- Output directory flag: `--outdir` / `--output-dir`. +- Expected outputs: `kinopt_results.xlsx`, tables, plots, reports, logs, provenance. +- Dashboard status: executable and result-browsable. + +### KinOpt evol + +- Command name: `kinopt-evol`. +- Purpose: evolutionary KinOpt optimization. +- Backend module: `kinopt.evol`. +- Inputs/config: backend-defined. +- Output directory flag: not dashboard-standardized in the Pixi task. +- Dashboard status: not directly registered for dashboard execution; produced folders can be browsed if layout is recognized. + +### TFOpt local + +- Command name: `tfopt-local`. +- Purpose: local TF/mRNA optimization. +- Backend module: `tfopt.local`. +- Required inputs: configured TFOpt files, commonly CSV files under `data/`. +- Optional arguments include `--conf`, `--lower_bound`, `--upper_bound`, and `--loss_type` where supported. +- Output directory flag: `--outdir` / `--output-dir`. +- Expected outputs: `tfopt_results.xlsx`, tables, plots, reports, logs, provenance. +- Dashboard status: executable and result-browsable. + +### TFOpt evol + +- Command name: `tfopt-evol`. +- Purpose: evolutionary TFOpt optimization. +- Backend module: `tfopt.evol`. +- Inputs/config: backend-defined. +- Output directory flag: not dashboard-standardized in the Pixi task. +- Dashboard status: not directly registered for dashboard execution; produced folders can be browsed if layout is recognized. + +### ProtWise / model + +- Command name: `model`. +- Purpose: protein-wise ODE fitting. +- Backend module: `protwise.runner.main`. +- Required inputs: protein CSV, phosphosite Excel workbook, RNA/TFOpt Excel workbook. +- Config support: `--conf`. +- Output directory flag: `--outdir` / `--output-dir`. +- Example: + +```bash +pixi run model --conf config.toml --outdir results/example_protwise +``` + +- Expected outputs: result workbook, plots, report, logs, provenance, standard folders. +- Dashboard status: executable and result-browsable. + +### Networkmodel + +- Command name: `networkmodel`. +- Purpose: global coupled signaling/GRN model. +- Backend module: `networkmodel.runner`. +- Required inputs: kinase network CSV, TF network CSV, MS/protein CSV, RNA CSV, optional phosphoproteomics CSV; optional prior workbooks from KinOpt/TFOpt. +- Config support: `--conf`. +- Output directory flag: `--output-dir` / `--outdir`. +- Example: + +```bash +pixi run networkmodel --conf config.toml --output-dir results/example_networkmodel +``` + +- Expected outputs: scalar objective/convergence CSVs, predictions, `dashboard_bundle.pkl`, plots, optimization/profile/posterior outputs, logs, provenance. +- Dashboard status: executable and result-browsable. + +### Dashboard + +- Commands: `dashboard`, `dashboard-dev`, `network-dashboard`. +- Purpose: `dashboard` and `dashboard-dev` run the unified dashboard; `network-dashboard` runs the legacy Networkmodel dashboard. +- Backend modules: `dashboard/app.py` or `run_dashboard.py`. +- Example: + +```bash +pixi run dashboard +pixi run dashboard-dev +``` + +### Tests and docs + +- Test command: + +```bash +pixi run -e dev test +``` + +- Focused dashboard tests: + +```bash +pixi run -e dev pytest tests/dashboard -v +``` + +- Docs build: + +```bash +pixi run -e docs docs-build +``` + +## Standalone analysis scripts + +The `scripts/` directory contains standalone utilities, including: + +- `analyze_tf_kin_counts.py` +- `compare_mechanisms.py` +- `curve_similarity.py` +- `export_subnetworks.py` +- `find_protein_accumulators.py` +- `kinopt_network_readout.py` +- `kinopt_network_viz.py` +- `make_kinopt_diagram.py` +- `mechanistic_insights.py` +- `temporal_sensitivity.py` +- `tfopt_network_readout.py` +- `tfopt_network_viz.py` + +These are not all Pixi tasks. Run them directly only after reading each script's arguments and expected inputs. When integrating a script into the dashboard, parameterize input/output paths and write outputs into the selected run directory under `tables/`, `plots/`, `reports/`, or `artifacts/`. + +## File-format constraints + +- Do not document TSV/XLSX execution support for Networkmodel network/data inputs unless the backend reader is extended beyond default `pandas.read_csv`. +- Do not document Excel support for ProtWise protein input unless the backend reader changes from `pd.read_csv`. +- Dashboard upload preview can read more formats than a specific workflow can execute. diff --git a/mkdocs.yml b/mkdocs.yml index 57adbc4..58fd93a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -54,6 +54,12 @@ nav: - Plotting: Documentation/plotting/README.md - Utils: Documentation/utils/README.md - Dashboard: Documentation/dashboard.md + - Dashboard Quickstart: dashboard_quickstart.md + - Dashboard User Guide: dashboard_user_guide.md + - Dashboard Developer Guide: dashboard_developer_guide.md + - Dashboard Troubleshooting: dashboard_troubleshooting.md + - Result Directory Contract: result_directory_contract.md + - Workflow CLI Reference: workflow_cli_reference.md - Scripts: Documentation/scripts.md - Docker: Documentation/docker.md - Testing: Documentation/testing.md From 9aafe615f4c1ffb357c24cc9f2edd1bd6390e543 Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Thu, 11 Jun 2026 12:46:02 +0530 Subject: [PATCH 13/42] Fix dashboard result discovery for reports and child runs --- dashboard/components/result_browser.py | 37 +++++++++++- dashboard/result_parser.py | 78 ++++++++++++++++++++++---- docs/result_directory_contract.md | 2 + tests/dashboard/test_result_parser.py | 40 +++++++++++++ 4 files changed, 144 insertions(+), 13 deletions(-) diff --git a/dashboard/components/result_browser.py b/dashboard/components/result_browser.py index 700dfc8..9bc8c7c 100644 --- a/dashboard/components/result_browser.py +++ b/dashboard/components/result_browser.py @@ -7,7 +7,7 @@ from dashboard.components.report_viewer import render_reports from dashboard.components.table_viewer import render_tables from dashboard.registry import infer_workflow -from dashboard.result_parser import ResultInventory +from dashboard.result_parser import ResultInventory, discover_result_directory def _summary_metric(label: str, value: int) -> None: @@ -25,7 +25,7 @@ def render_result_browser(inventory: ResultInventory) -> None: st.caption(f"Directory: `{inventory.root}`") st.info(f"Detected workflow: **{workflow.label}** — {workflow.description}") - columns = st.columns(5) + columns = st.columns(6) with columns[0]: _summary_metric("Tables", len(inventory.tables)) with columns[1]: @@ -36,13 +36,15 @@ def render_result_browser(inventory: ResultInventory) -> None: _summary_metric("Reports", len(inventory.reports)) with columns[4]: _summary_metric("Artifacts", len(inventory.artifacts)) + with columns[5]: + _summary_metric("Child runs", len(inventory.child_runs)) if inventory.missing_expected: with st.expander("Missing standard contract files/folders", expanded=False): st.write("The browser can still show recognised legacy outputs, but these standard items were not found:") st.code("\n".join(inventory.missing_expected)) - tabs = st.tabs(["Metadata", "Tables", "Plots", "Logs", "Reports", "Artifacts", "Download"]) + tabs = st.tabs(["Metadata", "Tables", "Plots", "Logs", "Reports", "Artifacts", "Child runs", "Download"]) with tabs[0]: render_metadata(inventory.metadata) render_text_file("Command", inventory.command, language="bash") @@ -58,6 +60,8 @@ def render_result_browser(inventory: ResultInventory) -> None: with tabs[5]: _render_downloadable_list("Artifacts", inventory.artifacts) with tabs[6]: + _render_child_runs(inventory) + with tabs[7]: render_download_panel(inventory) @@ -72,3 +76,30 @@ def _render_downloadable_list(label: str, files) -> None: st.write(f"Selected: `{selected.relative_path}`") with selected.path.open("rb") as handle: st.download_button("Download", data=handle.read(), file_name=selected.name, key=f"download-{label}-{selected.relative_path}") + + +def _render_child_runs(inventory: ResultInventory) -> None: + import streamlit as st + + st.subheader("Child workflow result folders") + if not inventory.child_runs: + st.info("No nested workflow result folders were found in the selected directory.") + return + + selected = st.selectbox( + "Select child workflow result", + inventory.child_runs, + format_func=lambda path: ( + path.relative_to(inventory.root).as_posix() + if path.is_relative_to(inventory.root) + else str(path) + ), + key=f"child-run-{inventory.root}", + ) + st.caption(f"Opening `{selected}`") + try: + child_inventory = discover_result_directory(selected) + except (FileNotFoundError, NotADirectoryError) as exc: + st.warning(f"Child result directory could not be opened: {exc}") + return + render_result_browser(child_inventory) diff --git a/dashboard/result_parser.py b/dashboard/result_parser.py index f91525f..29f7826 100644 --- a/dashboard/result_parser.py +++ b/dashboard/result_parser.py @@ -24,6 +24,8 @@ } LEGACY_ANALYSIS_DIRS = ("optimization", "profiles", "posterior", "plots") PROVENANCE_FILES = ("metadata.json", "command.txt", "console.log", "config_resolved.yaml") +STANDARD_SUBDIRS = {"tables", "plots", "logs", "reports", "artifacts"} +CHILD_WORKFLOW_DIRS = {"tfopt", "kinopt", "protwise", "networkmodel"} @dataclass(frozen=True) @@ -40,11 +42,25 @@ class ResultInventory: logs: list[DisplayFile] = field(default_factory=list) reports: list[DisplayFile] = field(default_factory=list) artifacts: list[DisplayFile] = field(default_factory=list) + child_runs: list[Path] = field(default_factory=list) missing_expected: list[str] = field(default_factory=list) @property def has_content(self) -> bool: - return any((self.metadata, self.command, self.console_log, self.config, self.tables, self.plots, self.logs, self.reports, self.artifacts)) + return any( + ( + self.metadata, + self.command, + self.console_log, + self.config, + self.tables, + self.plots, + self.logs, + self.reports, + self.artifacts, + self.child_runs, + ) + ) def _display_files(root: Path, paths: list[Path], category: str) -> list[DisplayFile]: @@ -59,6 +75,37 @@ def _display_files(root: Path, paths: list[Path], category: str) -> list[Display return files +def _is_report_like_html(path: Path) -> bool: + """Return whether an HTML file should be treated as a report rather than a plot.""" + return path.suffix.lower() in {".html", ".htm"} and "report" in path.stem.lower() + + +def _is_child_result_dir(path: Path) -> bool: + """Detect immediate nested workflow outputs such as phoskintime-all stage folders.""" + if not path.is_dir() or path.name in STANDARD_SUBDIRS: + return False + if path.name in CHILD_WORKFLOW_DIRS: + return True + if any((path / name).is_file() for name in PROVENANCE_FILES): + return True + if any((path / dirname).is_dir() for dirname in STANDARD_SUBDIRS): + return True + if any((path / name).is_file() for name in LEGACY_TABLE_NAMES): + return True + if any((path / dirname).is_dir() for dirname in LEGACY_ANALYSIS_DIRS): + return True + return False + + +def discover_child_result_directories(path: str | Path) -> list[Path]: + """Return immediate nested result directories without recursively parsing contents.""" + root = resolve_directory(path) + return sorted( + (child.resolve() for child in root.iterdir() if _is_child_result_dir(child)), + key=lambda p: p.name.lower(), + ) + + def _top_level_legacy_tables(root: Path) -> list[Path]: return sorted((root / name for name in LEGACY_TABLE_NAMES if (root / name).is_file()), key=lambda p: p.name.lower()) @@ -83,23 +130,33 @@ def discover_result_directory(path: str | Path) -> ResultInventory: table_paths.extend(_top_level_legacy_tables(root)) table_paths.extend(_legacy_dir_files(root, TABLE_EXTENSIONS)) - plot_paths = filter_by_suffix(iter_files(root / "plots"), PLOT_EXTENSIONS) - plot_paths.extend(_legacy_dir_files(root, PLOT_EXTENSIONS)) - plot_paths.extend(filter_by_suffix([p for p in root.iterdir() if p.is_file()], PLOT_EXTENSIONS)) + top_level_files = [p for p in root.iterdir() if p.is_file()] + plot_dir_paths = filter_by_suffix(iter_files(root / "plots"), PLOT_EXTENSIONS) + legacy_plot_paths = _legacy_dir_files(root, PLOT_EXTENSIONS) + report_like_html = [ + p + for p in [*top_level_files, *plot_dir_paths, *legacy_plot_paths] + if _is_report_like_html(p) + ] + + plot_paths = [p for p in plot_dir_paths if not _is_report_like_html(p)] + plot_paths.extend(p for p in legacy_plot_paths if not _is_report_like_html(p)) + plot_paths.extend( + filter_by_suffix( + (p for p in top_level_files if not _is_report_like_html(p)), + PLOT_EXTENSIONS, + ) + ) log_paths = iter_files(root / "logs") if console_log is not None: log_paths.insert(0, console_log) report_paths = filter_by_suffix(iter_files(root / "reports"), REPORT_EXTENSIONS) - report_paths.extend( - filter_by_suffix( - [p for p in root.iterdir() if p.is_file() and p.stem.lower() == "report"], - REPORT_EXTENSIONS, - ) - ) + report_paths.extend(filter_by_suffix(report_like_html, REPORT_EXTENSIONS)) artifact_paths = iter_files(root / "artifacts") + child_runs = discover_child_result_directories(root) missing = [name for name in PROVENANCE_FILES if not (root / name).is_file()] for dirname in ("tables", "plots", "logs", "reports", "artifacts"): @@ -117,5 +174,6 @@ def discover_result_directory(path: str | Path) -> ResultInventory: logs=_display_files(root, log_paths, "log"), reports=_display_files(root, report_paths, "report"), artifacts=_display_files(root, artifact_paths, "artifact"), + child_runs=child_runs, missing_expected=missing, ) diff --git a/docs/result_directory_contract.md b/docs/result_directory_contract.md index b593e97..2651926 100644 --- a/docs/result_directory_contract.md +++ b/docs/result_directory_contract.md @@ -91,6 +91,8 @@ The dashboard result parser recognizes selected legacy outputs so older runs can Legacy support is compatibility behavior. New workflow code should still write the standard folders and provenance files. +Integrated `phoskintime-all` runs may contain child workflow result folders such as `tfopt/`, `kinopt/`, and `protwise/` beneath the parent run directory. The parent directory records launcher-level provenance, while each child directory remains independently browseable with its own tables, plots, reports, logs, artifacts, and provenance where produced. + ## Workflow-specific expected outputs ### KinOpt diff --git a/tests/dashboard/test_result_parser.py b/tests/dashboard/test_result_parser.py index 7821eca..9830ee4 100644 --- a/tests/dashboard/test_result_parser.py +++ b/tests/dashboard/test_result_parser.py @@ -73,3 +73,43 @@ def test_discovers_legacy_local_excel_outputs(tmp_path): inventory = discover_result_directory(root) assert {item.name for item in inventory.tables} == {"kinopt_results.xlsx", "tfopt_results.xlsx"} + + +def test_protwise_report_like_html_is_report_not_plot(tmp_path): + root = tmp_path / "protwise" + root.mkdir() + (root / "Protein-wise_report.html").write_text("report", encoding="utf-8") + (root / "fit.html").write_text("plot", encoding="utf-8") + + inventory = discover_result_directory(root) + + assert {item.relative_path for item in inventory.reports} == {"Protein-wise_report.html"} + assert {item.relative_path for item in inventory.plots} == {"fit.html"} + + +def test_all_workflow_parent_discovers_child_result_directories(tmp_path): + root = tmp_path / "all-run" + root.mkdir() + for dirname in ("tables", "plots", "logs", "reports", "artifacts"): + (root / dirname).mkdir() + (root / "metadata.json").write_text(json.dumps({"workflow": "phoskintime-all"}), encoding="utf-8") + (root / "command.txt").write_text("pixi run phoskintime-all", encoding="utf-8") + (root / "console.log").write_text("done", encoding="utf-8") + (root / "config_resolved.yaml").write_text("workflow: all\n", encoding="utf-8") + + for child in ("tfopt", "kinopt", "protwise"): + child_root = root / child + (child_root / "tables").mkdir(parents=True) + (child_root / "plots").mkdir() + (child_root / "logs").mkdir() + (child_root / "reports").mkdir() + (child_root / "artifacts").mkdir() + (child_root / "metadata.json").write_text(json.dumps({"workflow": child}), encoding="utf-8") + (child_root / "tables" / f"{child}_summary.csv").write_text("x\n1\n", encoding="utf-8") + + inventory = discover_result_directory(root) + + assert [path.name for path in inventory.child_runs] == ["kinopt", "protwise", "tfopt"] + assert inventory.has_content + child_inventory = discover_result_directory(root / "protwise") + assert {item.relative_path for item in child_inventory.tables} == {"tables/protwise_summary.csv"} From 95f1b82818a4562d5ab623c46640d342cdea742a Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Thu, 11 Jun 2026 13:03:44 +0530 Subject: [PATCH 14/42] Restrict dashboard config inputs to TOML --- dashboard/registry.py | 18 +++++++++--------- docs/Documentation/no_code_dashboard.md | 2 +- docs/dashboard_developer_guide.md | 1 + docs/dashboard_quickstart.md | 2 +- docs/dashboard_troubleshooting.md | 1 + docs/dashboard_user_guide.md | 11 ++++++----- docs/workflow_cli_reference.md | 3 ++- tests/dashboard/test_registry.py | 14 ++++++++++++++ tests/dashboard/test_upload_validation.py | 21 +++++++++++++++++++++ 9 files changed, 56 insertions(+), 17 deletions(-) diff --git a/dashboard/registry.py b/dashboard/registry.py index 37e55de..1628914 100644 --- a/dashboard/registry.py +++ b/dashboard/registry.py @@ -91,7 +91,7 @@ class WorkflowDescriptor: pixi_task="kinopt-local", python_module="kinopt.local", accepted_arguments=( - ArgumentSpec("conf", "--conf", "path", "Optional TOML/YAML configuration file."), + ArgumentSpec("conf", "--conf", "path", "Optional TOML configuration file."), ArgumentSpec("lower_bound", "--lower_bound", "float", "Lower optimisation bound."), ArgumentSpec("upper_bound", "--upper_bound", "float", "Upper optimisation bound."), ArgumentSpec("loss_type", "--loss_type", "str", "Loss function name."), @@ -99,7 +99,7 @@ class WorkflowDescriptor: ), required_inputs=("input1.csv", "input2.csv"), input_assignments=( - InputSpec("config", "Config file", "conf", "Optional kinopt config file.", extensions=(".toml", ".yaml", ".yml", ".json")), + InputSpec("config", "TOML config file", "conf", "Optional kinopt TOML config file.", extensions=(".toml",)), ), output_dir_arg="--outdir", expected_output_folder="results/kinopt-local", @@ -112,14 +112,14 @@ class WorkflowDescriptor: pixi_task="tfopt-local", python_module="tfopt.local", accepted_arguments=( - ArgumentSpec("conf", "--conf", "path", "Optional TOML/YAML configuration file."), + ArgumentSpec("conf", "--conf", "path", "Optional TOML configuration file."), ArgumentSpec("lower_bound", "--lower_bound", "float", "Lower optimisation bound."), ArgumentSpec("upper_bound", "--upper_bound", "float", "Upper optimisation bound."), ArgumentSpec("loss_type", "--loss_type", "int", "Loss function identifier."), ), required_inputs=("input1.csv", "input3.csv", "input4.csv"), input_assignments=( - InputSpec("config", "Config file", "conf", "Optional tfopt config file.", extensions=(".toml", ".yaml", ".yml", ".json")), + InputSpec("config", "TOML config file", "conf", "Optional tfopt TOML config file.", extensions=(".toml",)), ), output_dir_arg="--outdir", expected_output_folder="results/tfopt-local", @@ -140,7 +140,7 @@ class WorkflowDescriptor: ), required_inputs=("protein CSV", "phosphosite Excel", "RNA Excel"), input_assignments=( - InputSpec("config", "Config file", "conf", "Optional ProtWise config file.", extensions=(".toml", ".yaml", ".yml", ".json")), + InputSpec("config", "TOML config file", "conf", "Optional ProtWise TOML config file.", extensions=(".toml",)), InputSpec("protein_file", "Protein CSV file", "input_excel_protein", "Protein input CSV file read by ProtWise.", extensions=(".csv",)), InputSpec("phosphosite_file", "Phosphosite file", "input_excel_psite", "Phosphosite input Excel file.", extensions=(".xlsx",)), InputSpec("rna_file", "RNA/mRNA file", "input_excel_rna", "RNA input Excel file.", extensions=(".xlsx",)), @@ -170,7 +170,7 @@ class WorkflowDescriptor: ), required_inputs=("kinase network", "TF network", "MS/protein data", "RNA data", "phospho data"), input_assignments=( - InputSpec("config", "Config file", "conf", "Optional networkmodel config file.", extensions=(".toml", ".yaml", ".yml", ".json")), + InputSpec("config", "TOML config file", "conf", "Optional networkmodel TOML config file.", extensions=(".toml",)), InputSpec("kinase_network", "Kinase network CSV file", "kinase_net", "Kinase network CSV file read by networkmodel.", extensions=(".csv",)), InputSpec("tf_network", "TF network CSV file", "tf_net", "TF network CSV file read by networkmodel.", extensions=(".csv",)), InputSpec("protein_file", "Protein/MS CSV file", "ms", "Protein/MS CSV data file read by networkmodel.", extensions=(".csv",)), @@ -199,9 +199,9 @@ class WorkflowDescriptor: ArgumentSpec("model_conf", "--model-conf", "path", "ProtWise config file."), ), input_assignments=( - InputSpec("tf_config", "TFOpt config file", "tf_conf", "Config for TFOpt stage.", extensions=(".toml", ".yaml", ".yml", ".json")), - InputSpec("kin_config", "KinOpt config file", "kin_conf", "Config for KinOpt stage.", extensions=(".toml", ".yaml", ".yml", ".json")), - InputSpec("model_config", "ProtWise config file", "model_conf", "Config for ProtWise stage.", extensions=(".toml", ".yaml", ".yml", ".json")), + InputSpec("tf_config", "TFOpt TOML config file", "tf_conf", "TOML config for TFOpt stage.", extensions=(".toml",)), + InputSpec("kin_config", "KinOpt TOML config file", "kin_conf", "TOML config for KinOpt stage.", extensions=(".toml",)), + InputSpec("model_config", "ProtWise TOML config file", "model_conf", "TOML config for ProtWise stage.", extensions=(".toml",)), ), output_dir_arg="--outdir", expected_output_folder="results/phoskintime-all", diff --git a/docs/Documentation/no_code_dashboard.md b/docs/Documentation/no_code_dashboard.md index 750a038..99a2272 100644 --- a/docs/Documentation/no_code_dashboard.md +++ b/docs/Documentation/no_code_dashboard.md @@ -54,7 +54,7 @@ The result browser also recognizes practical legacy layouts, including Networkmo ## Upload behavior -The upload panel accepts `.csv`, `.tsv`, `.xlsx`, `.yaml`, `.yml`, `.json`, and `.txt` files. Uploaded files are copied to a per-run folder: +The upload panel accepts `.csv`, `.tsv`, `.xlsx`, `.yaml`, `.yml`, `.json`, and `.txt` files for upload/preview or preset workflows. Files assigned to workflow `--conf` fields currently must be `.toml` because the target runners parse TOML. Uploaded files are copied to a per-run folder: ```text dashboard_uploads// diff --git a/docs/dashboard_developer_guide.md b/docs/dashboard_developer_guide.md index a1d594e..b005f12 100644 --- a/docs/dashboard_developer_guide.md +++ b/docs/dashboard_developer_guide.md @@ -48,6 +48,7 @@ Registry rules: - Accepted file extensions must match backend readers. - Required inputs must match CLI behavior. - Labels/help text must not overpromise support. +- Config `InputSpec` extensions passed as `--conf` must remain `.toml` unless the target runner implements YAML/JSON parsing with tests. - `--conf` must be forwarded and honored by the backend runner. - Explicit CLI flags override config values. - `output_dir_arg` must match the workflow CLI (`--outdir` or `--output-dir`). diff --git a/docs/dashboard_quickstart.md b/docs/dashboard_quickstart.md index 5e66b6f..84c603d 100644 --- a/docs/dashboard_quickstart.md +++ b/docs/dashboard_quickstart.md @@ -73,7 +73,7 @@ Uploaded files are saved under: dashboard_uploads// ``` -Supported upload extensions are `.csv`, `.tsv`, `.xlsx`, `.yaml`, `.yml`, `.json`, and `.txt`. Workflow execution validation may be stricter than upload validation. For example, Networkmodel execution inputs and the ProtWise protein input currently use CSV readers in the backend, so those assigned inputs must be `.csv`. +Supported upload extensions are `.csv`, `.tsv`, `.xlsx`, `.yaml`, `.yml`, `.json`, and `.txt`. Workflow execution validation may be stricter than upload validation. Config files passed as `--conf` currently must be `.toml`, and Networkmodel execution inputs plus the ProtWise protein input currently use CSV readers in the backend, so those assigned data inputs must be `.csv`. ## Download results diff --git a/docs/dashboard_troubleshooting.md b/docs/dashboard_troubleshooting.md index 2f75800..538e63d 100644 --- a/docs/dashboard_troubleshooting.md +++ b/docs/dashboard_troubleshooting.md @@ -90,6 +90,7 @@ Do not rely on the PyCharm package installer for Pixi-managed dependencies. Add The upload panel accepts a broad set of extensions, but workflow assignment validation follows backend readers. +- Config files assigned to workflow `--conf` fields currently must be TOML; YAML/JSON uploads are for preview/preset contexts unless a runner explicitly supports them. - ProtWise protein input currently expects CSV when the backend uses `pd.read_csv`. - Networkmodel kinase network, TF network, MS/protein, RNA, and phosphoproteomics inputs currently expect CSV with the default `pd.read_csv` reader. - ProtWise phosphosite/RNA and previous KinOpt/TFOpt result inputs are Excel where the backend uses Excel readers. diff --git a/docs/dashboard_user_guide.md b/docs/dashboard_user_guide.md index 9e8b1d3..cd9dda3 100644 --- a/docs/dashboard_user_guide.md +++ b/docs/dashboard_user_guide.md @@ -17,13 +17,13 @@ The dashboard should be used for convenience and reproducibility. The CLI and ba | Workflow | Purpose | Expected inputs | Accepted execution formats | Output location | Runtime class | Dashboard execution | Result-only viewing | | --- | --- | --- | --- | --- | --- | --- | --- | | `prep` | Run preprocessing cleanup via `processing.cleanup`. | Files referenced by repository configuration and preprocessing conventions. | Config/data dependent. | Existing preprocessing outputs; no dedicated dashboard output flag. | Short | Yes | Limited | -| `kinopt-local` / `kinopt` | Local kinase-to-phosphosite optimization. | Protein/kinase abundance CSV, phosphosite CSV/network data, optional config. | Registered config files: `.toml`, `.yaml`, `.yml`, `.json`; workflow data follows backend config. | `results/kinopt-local//` when launched by dashboard; CLI `--outdir` supported. | Medium | Yes | Yes | +| `kinopt-local` / `kinopt` | Local kinase-to-phosphosite optimization. | Protein/kinase abundance CSV, phosphosite CSV/network data, optional config. | Registered config files passed as `--conf`: `.toml`; workflow data follows backend config. | `results/kinopt-local//` when launched by dashboard; CLI `--outdir` supported. | Medium | Yes | Yes | | `kinopt-evol` | Evolutionary KinOpt mode exposed as a Pixi task. | Same family of KinOpt inputs, governed by backend config. | Backend dependent. | Backend-defined outputs. | Medium/long | Not directly registered in dashboard launcher | Result folders can be browsed if contract/legacy layout is present | -| `tfopt-local` / `tfopt` | Local TF-to-mRNA optimization. | mRNA/RNA CSV, TF network CSV, optional config. | Registered config files: `.toml`, `.yaml`, `.yml`, `.json`; workflow data follows backend config. | `results/tfopt-local//` when launched by dashboard; CLI `--outdir` supported. | Medium | Yes | Yes | +| `tfopt-local` / `tfopt` | Local TF-to-mRNA optimization. | mRNA/RNA CSV, TF network CSV, optional config. | Registered config files passed as `--conf`: `.toml`; workflow data follows backend config. | `results/tfopt-local//` when launched by dashboard; CLI `--outdir` supported. | Medium | Yes | Yes | | `tfopt-evol` | Evolutionary TFOpt mode exposed as a Pixi task. | Same family of TFOpt inputs, governed by backend config. | Backend dependent. | Backend-defined outputs. | Medium/long | Not directly registered in dashboard launcher | Result folders can be browsed if contract/legacy layout is present | -| `protwise-model` / `model` | Protein-wise ODE fitting downstream of KinOpt/TFOpt. | Protein CSV, phosphosite Excel workbook, RNA/TFOpt Excel workbook, optional TOML config. | Protein input: `.csv`; phosphosite and RNA result inputs: `.xlsx`; config: `.toml`, `.yaml`, `.yml`, `.json` in dashboard assignment. | `results/protwise-model//` when launched by dashboard; CLI `--outdir` supported. | Medium/long | Yes | Yes | +| `protwise-model` / `model` | Protein-wise ODE fitting downstream of KinOpt/TFOpt. | Protein CSV, phosphosite Excel workbook, RNA/TFOpt Excel workbook, optional TOML config. | Protein input: `.csv`; phosphosite and RNA result inputs: `.xlsx`; config passed as `--conf`: `.toml`. | `results/protwise-model//` when launched by dashboard; CLI `--outdir` supported. | Medium/long | Yes | Yes | | `networkmodel` | Coupled kinase-signaling and TF/RNA global network model. | Kinase network CSV, TF network CSV, MS/protein CSV, RNA CSV, optional phosphoproteomics CSV, optional KinOpt/TFOpt Excel priors, TOML config. | Network/data inputs read by backend with `pandas.read_csv`: `.csv` only; prior result workbooks: `.xlsx`. | `results/networkmodel//` when launched by dashboard; CLI `--output-dir`/`--outdir` supported. | Long | Yes | Yes | -| `phoskintime-all` | Typer wrapper for preprocessing, local TFOpt, local KinOpt, and ProtWise. | Stage-specific configs for TFOpt/KinOpt/ProtWise. | Config assignment: `.toml`, `.yaml`, `.yml`, `.json`. | `results/phoskintime-all//` when launched by dashboard. | Long | Yes | Stage result folders can be browsed | +| `phoskintime-all` | Typer wrapper for preprocessing, local TFOpt, local KinOpt, and ProtWise. | Stage-specific configs for TFOpt/KinOpt/ProtWise. | Config assignment for CLI execution: `.toml`. | `results/phoskintime-all//` when launched by dashboard. | Long | Yes | Stage result folders can be browsed | | Advanced analysis scripts | Existing analysis utilities such as curve similarity, protein accumulator detection, subnetwork export, mechanistic insights, temporal sensitivity, and mechanism comparison. | Existing result folders/tables, depending on script. | Script-specific; do not assume upload conversion. | Selected run directory under `tables/`, `plots/`, `reports/`, or `artifacts/` when integrated. | Medium/long | Exposed as parameterized wrappers where available; not run automatically | Yes | ## Launching the dashboard @@ -75,7 +75,7 @@ dashboard_uploads// Uploaded files are not silently copied into `data/`. The command preview points to the uploaded/selected path used by the backend. -General upload extensions accepted by the UI are: +General upload extensions accepted by the UI for preview or preset storage are: ```text .csv, .tsv, .xlsx, .yaml, .yml, .json, .txt @@ -83,6 +83,7 @@ General upload extensions accepted by the UI are: Workflow execution validation is stricter and follows backend readers: +- Config files assigned to workflow `--conf` fields currently must be TOML because the target runners parse TOML. - ProtWise protein input currently expects CSV because the backend reads it with `pd.read_csv`. - ProtWise phosphosite and RNA result inputs currently expect Excel workbooks. - Networkmodel kinase network, TF network, MS/protein data, RNA data, and phosphoproteomics inputs currently expect CSV because the backend reads them with default `pd.read_csv`. diff --git a/docs/workflow_cli_reference.md b/docs/workflow_cli_reference.md index 0cd7c25..d676c70 100644 --- a/docs/workflow_cli_reference.md +++ b/docs/workflow_cli_reference.md @@ -4,7 +4,7 @@ This reference lists actual Pixi tasks and Typer wrapper commands present in the ## Config precedence -For workflows that support `--conf`: +For workflows that support `--conf`, the dashboard currently validates assigned config files as TOML because the target runners parse TOML: ```text Explicit CLI flags override values from --conf. @@ -288,6 +288,7 @@ These are not all Pixi tasks. Run them directly only after reading each script's ## File-format constraints +- Do not document YAML/JSON execution config support unless the target runner implements YAML/JSON loading; dashboard `--conf` assignments are restricted to `.toml`. - Do not document TSV/XLSX execution support for Networkmodel network/data inputs unless the backend reader is extended beyond default `pandas.read_csv`. - Do not document Excel support for ProtWise protein input unless the backend reader changes from `pd.read_csv`. - Dashboard upload preview can read more formats than a specific workflow can execute. diff --git a/tests/dashboard/test_registry.py b/tests/dashboard/test_registry.py index 3bd2bf4..c4cb592 100644 --- a/tests/dashboard/test_registry.py +++ b/tests/dashboard/test_registry.py @@ -65,3 +65,17 @@ def test_networkmodel_input_specs_match_csv_backend_readers(): spec = _spec("networkmodel", role) assert spec.extensions == (".csv",) assert "CSV" in spec.label + + +def test_config_input_specs_match_toml_only_runners(): + for workflow_key, roles in { + "kinopt-local": ("config",), + "tfopt-local": ("config",), + "protwise-model": ("config",), + "networkmodel": ("config",), + "phoskintime-all": ("tf_config", "kin_config", "model_config"), + }.items(): + for role in roles: + spec = _spec(workflow_key, role) + assert spec.extensions == (".toml",) + assert "TOML" in spec.label diff --git a/tests/dashboard/test_upload_validation.py b/tests/dashboard/test_upload_validation.py index 930c22e..19a710f 100644 --- a/tests/dashboard/test_upload_validation.py +++ b/tests/dashboard/test_upload_validation.py @@ -101,3 +101,24 @@ def test_networkmodel_phospho_data_accepts_only_csv(tmp_path): assert _validation_problems("networkmodel", "phosphosite_file", csv) == [] assert any(".csv" in problem for problem in _validation_problems("networkmodel", "phosphosite_file", tsv)) assert any(".csv" in problem for problem in _validation_problems("networkmodel", "phosphosite_file", xlsx)) + + +def test_workflow_config_inputs_accept_only_toml(tmp_path): + toml = _write_file(tmp_path / "config.toml") + yaml = _write_file(tmp_path / "config.yaml") + yml = _write_file(tmp_path / "config.yml") + json_config = _write_file(tmp_path / "config.json") + + for workflow_key, role in ( + ("kinopt-local", "config"), + ("tfopt-local", "config"), + ("protwise-model", "config"), + ("networkmodel", "config"), + ("phoskintime-all", "tf_config"), + ("phoskintime-all", "kin_config"), + ("phoskintime-all", "model_config"), + ): + assert _validation_problems(workflow_key, role, toml) == [] + for invalid in (yaml, yml, json_config): + problems = _validation_problems(workflow_key, role, invalid) + assert any(".toml" in problem for problem in problems) From b30ecc0409fbdcf2362a0b2be4d0dce819b3a09a Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Thu, 11 Jun 2026 13:21:12 +0530 Subject: [PATCH 15/42] Serialize run metadata with JSON-safe arrays --- common/results.py | 20 ++++++++++++++++---- tests/test_result_contract.py | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/common/results.py b/common/results.py index a46e3c7..24dd799 100644 --- a/common/results.py +++ b/common/results.py @@ -95,15 +95,23 @@ def shlex_quote(value: str) -> str: return shlex.quote(str(value)) -def _jsonable(value: Any) -> Any: +def to_json_safe(value: Any) -> Any: + """Convert values such as NumPy arrays/scalars and Paths to JSON-safe objects.""" if isinstance(value, Path): return str(value) if isinstance(value, dict): - return {str(k): _jsonable(v) for k, v in value.items()} + return {str(k): to_json_safe(v) for k, v in value.items()} if isinstance(value, (list, tuple, set)): - return [_jsonable(v) for v in value] + return [to_json_safe(v) for v in value] + if hasattr(value, "tolist") and callable(value.tolist): + return to_json_safe(value.tolist()) + if hasattr(value, "item") and callable(value.item): + try: + return to_json_safe(value.item()) + except (TypeError, ValueError): + pass if hasattr(value, "__dict__"): - return _jsonable(vars(value)) + return to_json_safe(vars(value)) try: json.dumps(value) return value @@ -111,6 +119,10 @@ def _jsonable(value: Any) -> Any: return str(value) +def _jsonable(value: Any) -> Any: + return to_json_safe(value) + + def write_command(outdir: str | Path, argv: Iterable[str] | None = None) -> Path: root = ensure_result_dir(outdir)["root"] path = root / "command.txt" diff --git a/tests/test_result_contract.py b/tests/test_result_contract.py index 711edad..e7277f2 100644 --- a/tests/test_result_contract.py +++ b/tests/test_result_contract.py @@ -3,6 +3,8 @@ import json from pathlib import Path +import pytest + from common.results import ( STANDARD_SUBDIRS, ensure_result_dir, @@ -35,6 +37,23 @@ def test_result_contract_helpers_write_provenance(tmp_path): assert metadata["inputs"][0]["sha256"] +def test_metadata_and_resolved_config_preserve_numpy_arrays_as_lists(tmp_path): + np = pytest.importorskip("numpy") + outdir = tmp_path / "run" + time_grid = np.asarray([0.0, 2.0, 4.0, 8.0], dtype=float) + + write_resolved_config(outdir, {"time_grid": time_grid, "scalar": np.float64(1.5)}) + write_metadata(outdir, "unit.workflow", extra={"effective_time_grid": time_grid}) + + metadata = json.loads((outdir / "metadata.json").read_text(encoding="utf-8")) + assert metadata["effective_time_grid"] == [0.0, 2.0, 4.0, 8.0] + + resolved = (outdir / "config_resolved.yaml").read_text(encoding="utf-8") + assert "[ 0." not in resolved + assert "0.0" in resolved + assert "8.0" in resolved + + def test_populate_standard_subdirs_copies_legacy_outputs(tmp_path): outdir = tmp_path / "run" ensure_result_dir(outdir) From b1e65cbef26c38d8c10e25080996a682aaaea006 Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Thu, 11 Jun 2026 13:47:55 +0530 Subject: [PATCH 16/42] Fix advanced analysis dashboard commands --- dashboard/workflow_panels/analysis.py | 14 ++- scripts/analyze_tf_kin_counts.py | 18 +++- scripts/curve_similarity.py | 18 +++- tests/dashboard/test_workflow_panels.py | 135 ++++++++++++++++++++++++ 4 files changed, 182 insertions(+), 3 deletions(-) diff --git a/dashboard/workflow_panels/analysis.py b/dashboard/workflow_panels/analysis.py index 14396d4..1b3b6d6 100644 --- a/dashboard/workflow_panels/analysis.py +++ b/dashboard/workflow_panels/analysis.py @@ -50,7 +50,17 @@ class AnalysisTask: "Mechanistic insights", "Run the existing mechanistic insights script; inputs are passed through its CLI.", "scripts/mechanistic_insights.py", - {"results_dir": "--results-dir", "out_dir": "--out-dir"}, + { + "kinase_net": "--kinase-net", + "tf_net": "--tf-net", + "ms": "--ms", + "rna": "--rna", + "phospho": "--phospho", + "kinopt": "--kinopt", + "tfopt": "--tfopt", + "output_dir": "--output-dir", + "cores": "--cores", + }, ), "temporal-sensitivity": AnalysisTask( "temporal-sensitivity", @@ -79,6 +89,8 @@ def build_analysis_command(task_key: str, values: dict[str, Any], result_dir: st merged = dict(values) if "out_dir" in task.arguments and not merged.get("out_dir"): merged["out_dir"] = analysis_output_dir(result_dir, task_key) + elif task_key == "mechanistic-insights" and not merged.get("output_dir"): + merged["output_dir"] = result_dir elif task_key in {"protein-accumulators", "temporal-sensitivity"}: analysis_output_dir(result_dir, task_key) for name, flag in task.arguments.items(): diff --git a/scripts/analyze_tf_kin_counts.py b/scripts/analyze_tf_kin_counts.py index df676dd..d57208c 100644 --- a/scripts/analyze_tf_kin_counts.py +++ b/scripts/analyze_tf_kin_counts.py @@ -11,6 +11,7 @@ Author: Abhinav Mishra """ +import argparse from pathlib import Path import pandas as pd @@ -148,5 +149,20 @@ def main( print(per_gene.head(10).to_string(index=False)) +def parse_args(argv: list[str] | None = None) -> argparse.Namespace: + """Parse command-line arguments for dashboard and terminal execution.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--tfopt-xlsx", default="data/tfopt_results.xlsx", help="Path to TFOpt result workbook.") + parser.add_argument("--kinopt-xlsx", default="data/kinopt_results.xlsx", help="Path to KinOpt result workbook.") + parser.add_argument("--out-dir", default="results_scripts", help="Directory where analysis outputs are written.") + return parser.parse_args(argv) + + +def cli(argv: list[str] | None = None) -> None: + """CLI entry point that forwards parsed arguments to the analysis function.""" + args = parse_args(argv) + main(tfopt_xlsx=args.tfopt_xlsx, kinopt_xlsx=args.kinopt_xlsx, out_dir=args.out_dir) + + if __name__ == "__main__": - main() + cli() diff --git a/scripts/curve_similarity.py b/scripts/curve_similarity.py index 31fc476..ed32bea 100644 --- a/scripts/curve_similarity.py +++ b/scripts/curve_similarity.py @@ -41,6 +41,7 @@ from __future__ import annotations +import argparse from pathlib import Path import numpy as np import pandas as pd @@ -313,5 +314,20 @@ def summarize(name: str, df: pd.DataFrame): print(" -", out_dir / "frechet_kinopt.csv") +def parse_args(argv: list[str] | None = None) -> argparse.Namespace: + """Parse command-line arguments for dashboard and terminal execution.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--tfopt-xlsx", default="data/tfopt_results.xlsx", help="Path to TFOpt result workbook.") + parser.add_argument("--kinopt-xlsx", default="data/kinopt_results.xlsx", help="Path to KinOpt result workbook.") + parser.add_argument("--out-dir", default="results_scripts", help="Directory where analysis outputs are written.") + return parser.parse_args(argv) + + +def cli(argv: list[str] | None = None) -> None: + """CLI entry point that forwards parsed arguments to the analysis function.""" + args = parse_args(argv) + main(tfopt_xlsx=args.tfopt_xlsx, kinopt_xlsx=args.kinopt_xlsx, out_dir=args.out_dir) + + if __name__ == "__main__": - main() + cli() diff --git a/tests/dashboard/test_workflow_panels.py b/tests/dashboard/test_workflow_panels.py index 1f05009..f6bb73a 100644 --- a/tests/dashboard/test_workflow_panels.py +++ b/tests/dashboard/test_workflow_panels.py @@ -1,5 +1,9 @@ from __future__ import annotations +import ast +from pathlib import Path + +import pytest from dashboard.workflow_panels.analysis import build_analysis_command, discover_analysis_outputs from dashboard.workflow_panels.kinopt import discover_kinopt_panel from dashboard.workflow_panels.networkmodel import discover_networkmodel_panel @@ -87,3 +91,134 @@ def test_analysis_command_wrapper_and_output_discovery(tmp_path): outputs = discover_analysis_outputs(root) assert outputs["export-subnetworks"] == [outdir / "index.csv"] + + +def _command_options(command): + return {part for part in command[2:] if part.startswith("--")} + + +def test_advanced_analysis_commands_match_supported_cli_flags(tmp_path): + root = tmp_path / "run" + _standard_dirs(root) + + tf_counts = build_analysis_command( + "tf-kin-counts", + {"tfopt_xlsx": "tf.xlsx", "kinopt_xlsx": "kin.xlsx"}, + root, + ) + assert _command_options(tf_counts) == {"--tfopt-xlsx", "--kinopt-xlsx", "--out-dir"} + + curve = build_analysis_command( + "curve-similarity", + {"tfopt_xlsx": "tf.xlsx", "kinopt_xlsx": "kin.xlsx"}, + root, + ) + assert _command_options(curve) == {"--tfopt-xlsx", "--kinopt-xlsx", "--out-dir"} + + mechanistic = build_analysis_command( + "mechanistic-insights", + { + "kinase_net": "kinase.csv", + "tf_net": "tf.csv", + "ms": "protein.csv", + "rna": "rna.csv", + "phospho": "phospho.csv", + "kinopt": "kinopt.json", + "tfopt": "tfopt.json", + "cores": 2, + }, + root, + ) + assert "--output-dir" in mechanistic + assert "--results-dir" not in mechanistic + assert "--out-dir" not in mechanistic + assert str(root) in mechanistic + + + + +def _script_argparse_flags(script: str) -> set[str]: + tree = ast.parse(Path(script).read_text(encoding="utf-8")) + flags: set[str] = set() + for node in ast.walk(tree): + if not isinstance(node, ast.Call): + continue + func = node.func + if not isinstance(func, ast.Attribute) or func.attr != "add_argument": + continue + for arg in node.args: + if isinstance(arg, ast.Constant) and isinstance(arg.value, str) and arg.value.startswith("--"): + flags.add(arg.value) + return flags + + +def test_generated_analysis_commands_use_target_script_argparse_flags(tmp_path): + root = tmp_path / "run" + _standard_dirs(root) + command_values = { + "tf-kin-counts": {"tfopt_xlsx": "tf.xlsx", "kinopt_xlsx": "kin.xlsx"}, + "curve-similarity": {"tfopt_xlsx": "tf.xlsx", "kinopt_xlsx": "kin.xlsx"}, + "export-subnetworks": {"input2": "input2.csv", "input4": "input4.csv", "hops": "auto"}, + "protein-accumulators": {"prot": "prot.csv", "rna": "rna.csv", "threshold": 2.0}, + "mechanistic-insights": { + "kinase_net": "kinase.csv", + "tf_net": "tf.csv", + "ms": "protein.csv", + "rna": "rna.csv", + "phospho": "phospho.csv", + "kinopt": "kinopt.json", + "tfopt": "tfopt.json", + "cores": 2, + }, + "temporal-sensitivity": {"results_dir": str(root), "samples": 8}, + } + + for task_key, values in command_values.items(): + command = build_analysis_command(task_key, values, root) + accepted = _script_argparse_flags(command[1]) + assert _command_options(command) <= accepted, task_key + + +def test_analyze_tf_kin_counts_cli_uses_selected_paths(monkeypatch, tmp_path): + pytest.importorskip("pandas") + import importlib + + module = importlib.import_module("scripts.analyze_tf_kin_counts") + calls = {} + + def fake_main(*, tfopt_xlsx, kinopt_xlsx, out_dir): + calls["tfopt_xlsx"] = tfopt_xlsx + calls["kinopt_xlsx"] = kinopt_xlsx + calls["out_dir"] = out_dir + + monkeypatch.setattr(module, "main", fake_main) + tf = tmp_path / "tf.xlsx" + kin = tmp_path / "kin.xlsx" + out = tmp_path / "out" + + module.cli(["--tfopt-xlsx", str(tf), "--kinopt-xlsx", str(kin), "--out-dir", str(out)]) + + assert calls == {"tfopt_xlsx": str(tf), "kinopt_xlsx": str(kin), "out_dir": str(out)} + + +def test_curve_similarity_cli_uses_selected_paths(monkeypatch, tmp_path): + pytest.importorskip("pandas") + pytest.importorskip("numpy") + import importlib + + module = importlib.import_module("scripts.curve_similarity") + calls = {} + + def fake_main(*, tfopt_xlsx, kinopt_xlsx, out_dir): + calls["tfopt_xlsx"] = tfopt_xlsx + calls["kinopt_xlsx"] = kinopt_xlsx + calls["out_dir"] = out_dir + + monkeypatch.setattr(module, "main", fake_main) + tf = tmp_path / "tf.xlsx" + kin = tmp_path / "kin.xlsx" + out = tmp_path / "out" + + module.cli(["--tfopt-xlsx", str(tf), "--kinopt-xlsx", str(kin), "--out-dir", str(out)]) + + assert calls == {"tfopt_xlsx": str(tf), "kinopt_xlsx": str(kin), "out_dir": str(out)} From 3898b16f593bb46a60260edb0711238045f01a32 Mon Sep 17 00:00:00 2001 From: bibymaths Date: Thu, 11 Jun 2026 15:17:35 +0200 Subject: [PATCH 17/42] fixed: console display, posterior log, workflow testing for frontend --- dashboard/components/console_panel.py | 32 +- dashboard/file_utils.py | 4 +- dashboard/registry.py | 8 + networkmodel/PosteriorObjective.py | 2 +- pixi.lock | 3826 +++++++++++++++++++++++-- pixi.toml | 1 + 6 files changed, 3637 insertions(+), 236 deletions(-) diff --git a/dashboard/components/console_panel.py b/dashboard/components/console_panel.py index 7a5122e..92b71c3 100644 --- a/dashboard/components/console_panel.py +++ b/dashboard/components/console_panel.py @@ -1,13 +1,37 @@ from __future__ import annotations - def render_console(lines: list[str], height: int = 360) -> None: - """Render streamed console output.""" + """Render streamed ANSI-colored console output in Streamlit.""" import streamlit as st + from ansi2html import Ansi2HTMLConverter + + raw_text = "".join(lines) - text = "".join(lines) - st.text_area("Console output", text, height=height, help="Live stdout/stderr from the workflow process.") + converter = Ansi2HTMLConverter( + inline=True, + escaped=True, + scheme="ansi2html", + ) + html = converter.convert(raw_text, full=False) + st.markdown( + f""" +
{html}
+ """, + unsafe_allow_html=True, + ) def render_cancellation_note() -> None: """Explain the current cancellation boundary without exposing unsafe controls.""" diff --git a/dashboard/file_utils.py b/dashboard/file_utils.py index c8ac755..2803af7 100644 --- a/dashboard/file_utils.py +++ b/dashboard/file_utils.py @@ -11,11 +11,11 @@ HTML_EXTENSIONS = {".html", ".htm"} PLOT_EXTENSIONS = IMAGE_EXTENSIONS | HTML_EXTENSIONS REPORT_EXTENSIONS = HTML_EXTENSIONS | {".md", ".pdf"} -TEXT_EXTENSIONS = {".txt", ".log", ".yaml", ".yml", ".json", ".md", ".csv", ".tsv"} +TEXT_EXTENSIONS = {".txt", ".log", ".yaml", ".yml", ".toml", ".json", ".md", ".csv", ".tsv"} EXCLUDED_ZIP_PARTS = {"__pycache__", ".pytest_cache", ".mypy_cache", ".ruff_cache", ".git"} -UPLOAD_EXTENSIONS = {".csv", ".tsv", ".xlsx", ".yaml", ".yml", ".json", ".txt"} +UPLOAD_EXTENSIONS = {".csv", ".tsv", ".xlsx", ".yaml", ".yml", ".toml", ".json", ".txt"} _FILENAME_SAFE_CHARS = set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._-") diff --git a/dashboard/registry.py b/dashboard/registry.py index 1628914..9c73741 100644 --- a/dashboard/registry.py +++ b/dashboard/registry.py @@ -167,6 +167,14 @@ class WorkflowDescriptor: ArgumentSpec("seed", "--seed", "int", "Random seed."), ArgumentSpec("scan", "--scan", "bool", "Run hyperparameter scan."), ArgumentSpec("sensitivity", "--sensitivity", "bool", "Run sensitivity analysis."), + ArgumentSpec( + name="kinopt", + flag="--kinopt", + ), + ArgumentSpec( + name="tfopt", + flag="--tfopt", + ), ), required_inputs=("kinase network", "TF network", "MS/protein data", "RNA data", "phospho data"), input_assignments=( diff --git a/networkmodel/PosteriorObjective.py b/networkmodel/PosteriorObjective.py index de561ac..f7f0c2d 100644 --- a/networkmodel/PosteriorObjective.py +++ b/networkmodel/PosteriorObjective.py @@ -11,7 +11,7 @@ from pathlib import Path from types import SimpleNamespace -from config.constants import RESULTS_DIR +from networkmodel.config import RESULTS_DIR os.environ.setdefault("OMP_NUM_THREADS", "1") os.environ.setdefault("OPENBLAS_NUM_THREADS", "1") diff --git a/pixi.lock b/pixi.lock index eccd9a2..151f8b5 100644 --- a/pixi.lock +++ b/pixi.lock @@ -19,15 +19,37 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-atk-2.38.0-h0630a04_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-core-2.40.3-h0630a04_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/atk-1.0-2.38.0-h04ea711_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.10.3-hea842a7_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.9.14-h78948cc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.14.0-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-compression-0.3.2-haa0cbde_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.7.1-h9cf6be0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-http-0.11.0-h6488f85_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.26.3-h5b668fc_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-mqtt-0.15.2-h0d2f46f_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-s3-0.12.5-hb916526_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-sdkutils-0.2.4-haa0cbde_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.2.10-haa0cbde_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.40.0-h41299d8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.747-h6154047_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-core-cpp-1.16.2-h206d751_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-identity-cpp-1.13.3-hed0cdb0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-blobs-cpp-12.17.0-hf824e48_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-common-cpp-12.13.0-ha7a2c86_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-files-datalake-cpp-12.15.0-h1e5b466_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.5.0-py312h90b7ffd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda @@ -72,8 +94,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.16-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.6-h2b0a6b4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-h5888daf_1005.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/git-cliff-2.13.1-h66dc0b5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.88.1-hee1de02_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.1-hbabe93e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphviz-14.1.2-h8b86629_0.conda @@ -86,6 +112,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/hicolor-icon-theme-0.17-ha770c72_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/httptools-0.8.0-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda @@ -94,6 +121,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/jaxlib-0.9.2-cpu_py312hc81e8bd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -101,6 +129,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.9.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda @@ -110,18 +140,27 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-24.0.0-h8ff9baf_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-acero-24.0.0-h635bf11_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-compute-24.0.0-h53684a4_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-dataset-24.0.0-h635bf11_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-substrait-24.0.0-hb4dd7c2_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.5-default_h746c552_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.20.0-hcf29cc6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.127-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.0-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda @@ -139,16 +178,22 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-devel-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-3.5.0-h8d2ee43_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-3.5.0-hdbdcf42_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.78.1-h1d1128b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h47877c9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.5-hf7376ad_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libntlm-1.8-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopentelemetry-cpp-1.27.0-h9692893_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopentelemetry-cpp-headers-1.27.0-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libparquet-24.0.0-h7376487_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.19-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.4-hd5a49e9_0.conda @@ -160,7 +205,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.22.0-h7d032f7_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.11.3-hfe17d71_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libvulkan-loader-1.4.341.0-h5279c79_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda @@ -174,6 +221,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/lineax-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/llvmlite-0.47.0-py312h7424e68_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lxml-6.1.0-py312h63ddcf0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda @@ -190,6 +238,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numba-0.65.1-py312hd1dde6f_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.5-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/numpyro-0.21.0-pyhd8ed1ab_0.conda @@ -202,6 +251,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/opt_einsum-3.4.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-2.3.0-h21090e2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pandas-3.0.3-py312h8ecdadd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pango-1.56.4-hda50119_1.conda @@ -217,11 +267,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/prometheus-cpp-1.3.0-ha5d0236_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/protobuf-6.33.5-py312ha7b3241_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-24.0.0-py312h7900ff3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-core-24.0.0-py312h2054cf2_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyld-3.0.0-pyhcf101f3_0.conda @@ -234,6 +289,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_3.conda @@ -241,8 +297,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/qt6-main-6.11.1-pl5321h16c4a6b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2025.11.05-h5301d42_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-2026.5.1-py312h192e038_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.7.3-hc5a330e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/salib-1.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scikit-learn-1.8.0-np2py312h3226591_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.17.1-py312h54fa4ab_0.conda @@ -251,12 +310,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sqlalchemy-2.0.49-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/statsmodels-0.14.6-py312h4f23490_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -267,10 +332,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.1-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/watchdog-6.0.0-py312h20c3967_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.25.0-hd6090a7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/websockets-16.0-py312h5253ce2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-2.1.2-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-0.4.1-h4f16b4b_2.conda @@ -301,6 +369,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h09e67af_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - pypi: https://files.pythonhosted.org/packages/7d/da/dd2867c25adbb41563720f14b5fc895c98bf88be682a3faff4f7b3118d2a/igraph-1.0.0-cp39-abi3-manylinux_2_28_x86_64.whl @@ -317,14 +386,36 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/atk-1.0-2.38.0-h4bec284_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.10.3-h2dfa1e0_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.9.14-hcb77be1_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.14.0-ha1e9b39_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.3.2-ha04291d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.7.1-hf02f33c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.11.0-he315c99_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.26.3-hd35ae92_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.15.2-h60a7cf6_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.12.5-h8cc6e82_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.2.4-ha04291d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.2.10-ha04291d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.40.0-h29c3229_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.747-h6b5c32a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-core-cpp-1.16.2-h87f1c7e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-identity-cpp-1.13.3-h1135191_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-blobs-cpp-12.17.0-hefc3566_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-common-cpp-12.13.0-h74781cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-files-datalake-cpp-12.15.0-haae7687_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/backports.zstd-1.5.0-py312h5f4ecc6_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-1.2.0-hf139dec_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-bin-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.2.0-py312h4b46afd_1.conda @@ -366,8 +457,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/fribidi-1.0.16-h8616949_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/frozendict-2.4.7-py312h80b0991_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gdk-pixbuf-2.44.6-hae309b2_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hac325c4_1005.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/git-cliff-2.13.1-h6d18f09_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glib-tools-2.88.1-h6437393_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.1-h2790a97_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphite2-1.3.14-h21dd04a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphviz-14.1.2-h44fc223_0.conda @@ -380,6 +475,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/hicolor-icon-theme-0.17-h694c41f_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/httptools-0.8.0-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda @@ -388,6 +484,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/jaxlib-0.9.0-cpu_py312hf3c3857_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -395,6 +492,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.9.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/kiwisolver-1.5.0-py312hb1dc2e7_0.conda @@ -402,14 +501,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/lcms2-2.19.1-h5ea7634_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lerc-4.1.0-h35c7297_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20260107.1-cxx17_h7ed6875_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-24.0.0-h9e06b3e_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-24.0.0-h91633f5_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-compute-24.0.0-hb38465b_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-24.0.0-h91633f5_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-24.0.0-h613493e_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-7_he492b99_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-7_h9b27e0a_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.20.0-h8f0b9e4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.5-h19cb2f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libdeflate-1.25-h517ebb2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.0-hcc62823_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libfreetype-2.14.3-h694c41f_0.conda @@ -420,13 +528,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_19.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libgit2-1.9.3-h415d65b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libglib-2.88.1-hf28f236_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-3.5.0-h8b848e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-3.5.0-hea209c6_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libgrpc-1.78.1-h147dede_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libintl-0.25.1-h3184127_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libjpeg-turbo-3.1.4.1-ha1e9b39_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.11.0-7_h859234e_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h70048d4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.33-openmp_h9e49c7b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopentelemetry-cpp-1.27.0-h7a0a166_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopentelemetry-cpp-headers-1.27.0-h694c41f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libparquet-24.0.0-h0f82bca_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libpng-1.6.58-he930e7c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-6.33.5-hff14b61_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libre2-11-2025.11.05-h6e8c311_1.conda @@ -434,7 +548,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libsodium-1.0.22-ha3d0635_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.1-h8f8c405_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libthrift-0.22.0-hebea4ca_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libtiff-4.7.1-ha0a348c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libutf8proc-2.11.3-hc282952_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libwebp-base-1.6.0-hb807250_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libxcb-1.17.0-hf1f96e2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.3-h7a90416_0.conda @@ -445,6 +561,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.5-h0d3cbff_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/llvmlite-0.47.0-py312ha5a82fe_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lxml-6.1.0-py312h211e60a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-3.0.3-py312heb39f77_1.conda @@ -461,6 +578,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/nlohmann_json-3.12.0-h06076ce_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numba-0.65.1-py312h704f9c4_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-2.4.5-py312h746d82c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/numpyro-0.21.0-pyhd8ed1ab_0.conda @@ -471,6 +589,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/opt_einsum-3.4.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-2.3.0-hb9b210e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pandas-3.0.3-py312h8e27051_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pango-1.56.4-hf280016_1.conda @@ -486,11 +605,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/prometheus-cpp-1.3.0-h7802330_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/protobuf-6.33.5-py312hf5f8d9f_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-7.2.2-py312hf7082af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pthread-stubs-0.4-h00291cd_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-24.0.0-py312hb401068_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-core-24.0.0-py312h3987635_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyld-3.0.0-pyhcf101f3_0.conda @@ -502,14 +626,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.3-py312h51361c1_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pyzmq-27.1.0-py312h2ac7433_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/qhull-2020.2-h3c5361c_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2025.11.05-h77e0585_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rpds-py-2026.5.1-py312hb77ea7e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/salib-1.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/scikit-learn-1.8.0-np2py312h47bbdc5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.17.1-py312h6309490_0.conda @@ -518,12 +645,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.2.2-h01f5ddf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sqlalchemy-2.0.49-py312hba6025d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/statsmodels-0.14.6-py312h391ab28_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tornado-6.5.5-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -534,9 +667,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/unicodedata2-17.0.1-py312h1a1c95f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/watchdog-6.0.0-py312hba6025d_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/websockets-16.0-py312hf7082af_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/wrapt-2.1.2-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/xlsxwriter-3.2.9-pyhd8ed1ab_0.conda @@ -545,6 +681,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zeromq-4.3.5-h84953be_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.2-hbb4bfdb_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-ng-2.3.3-h8bce59a_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - pypi: https://files.pythonhosted.org/packages/a5/03/3278ad0ceb3ea0e84d8ae3a85bdded4d0e57853aeb802a200feb43847b93/igraph-1.0.0-cp39-abi3-macosx_10_15_x86_64.whl @@ -561,14 +698,36 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/atk-1.0-2.38.0-hd03087b_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.10.3-hceed5df_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.9.14-h81c6212_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.14.0-h84a0fba_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-0.3.2-h61d3404_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-event-stream-0.7.1-h7e6a3cf_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-0.11.0-h0a63974_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-0.26.3-h58c0f83_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-mqtt-0.15.2-ha70999f_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-0.12.5-h43def2a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-0.2.4-h61d3404_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.2.10-h61d3404_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.40.0-hd6eb0f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.747-h55dad5a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-core-cpp-1.16.2-he5ae378_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-identity-cpp-1.13.3-h810541e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-blobs-cpp-12.17.0-h5446563_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-common-cpp-12.13.0-he467506_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-files-datalake-cpp-12.15.0-hfea7fb9_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.5.0-py312h87c4bb7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.2.0-h7d5ae5b_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py312h0dfefe5_1.conda @@ -610,8 +769,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fribidi-1.0.16-hc919400_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozendict-2.4.7-py312h4409184_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gdk-pixbuf-2.44.6-h4e57454_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hf9b8971_1005.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/git-cliff-2.13.1-h5a0b6fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-tools-2.88.1-h37541a8_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.1-heb240a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.14-hec049ff_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphviz-14.1.2-hec8c438_0.conda @@ -624,6 +787,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/hicolor-icon-theme-0.17-hce30654_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/httptools-0.8.0-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda @@ -632,6 +796,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/jaxlib-0.9.2-cpu_py312h8d61f43_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -639,6 +804,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.9.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/kiwisolver-1.5.0-py312h3093aea_0.conda @@ -646,14 +813,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lcms2-2.19.1-hdfa7624_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lerc-4.1.0-h1eee2c3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260107.1-cxx17_h2062a1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-24.0.0-h91214ac_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-acero-24.0.0-ha4f4840_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-compute-24.0.0-h8d10c55_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-dataset-24.0.0-ha4f4840_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-substrait-24.0.0-h05be00f_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-7_h51639a9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-7_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.20.0-hd5a2499_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.0-hf6b4638_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.3-hce30654_0.conda @@ -664,13 +840,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgit2-1.9.3-h9a1894c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libglib-2.88.1-ha08bb59_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-3.5.0-h688a705_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-storage-3.5.0-ha114238_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgrpc-1.78.1-h3e3f78d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.25.1-h493aca8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-3.1.4.1-h84a0fba_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-7_hd9741b5_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.33-openmp_he657e61_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopentelemetry-cpp-1.27.0-h08d5cc3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopentelemetry-cpp-headers-1.27.0-hce30654_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libparquet-24.0.0-h840b369_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.58-h132b30e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-6.33.5-h2d4b707_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libre2-11-2025.11.05-h4c27e2a_1.conda @@ -678,7 +860,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.22-h1a92334_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libthrift-0.22.0-h1fb9c8a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libutf8proc-2.11.3-h2431656_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.3-h5ef1a60_0.conda @@ -689,6 +873,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvmlite-0.47.0-py312h7ca588d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lxml-6.1.0-py312h2f8615f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py312h04c11ed_1.conda @@ -705,6 +890,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numba-0.65.1-py312h2d3d6e9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.4.5-py312ha003a3f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/numpyro-0.21.0-pyhd8ed1ab_0.conda @@ -714,6 +900,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/opt_einsum-3.4.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-2.3.0-hd11884d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pandas-3.0.3-py312h6510ced_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pango-1.56.4-hf80efc4_1.conda @@ -729,11 +916,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prometheus-cpp-1.3.0-h0967b3e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/protobuf-6.33.5-py312h857ab9a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py312hb3ab3e3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-24.0.0-py312h1f38498_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-core-24.0.0-py312h21b41d0_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyld-3.0.0-pyhcf101f3_0.conda @@ -745,14 +937,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py312h04c11ed_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/qhull-2020.2-h420ef59_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2025.11.05-ha480c28_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-2026.5.1-py312h8b1d842_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/salib-1.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py312he5ca3e3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.17.1-py312h0f234b1_0.conda @@ -761,12 +956,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sqlalchemy-2.0.49-py312hb3ab3e3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/statsmodels-0.14.6-py312ha11c99a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -777,9 +978,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/unicodedata2-17.0.1-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/watchdog-6.0.0-py312hb3ab3e3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/websockets-16.0-py312hb3ab3e3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/wrapt-2.1.2-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/xlsxwriter-3.2.9-pyhd8ed1ab_0.conda @@ -788,6 +992,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h10816f8_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - pypi: https://files.pythonhosted.org/packages/0d/bc/6281ec7f9baaf71ee57c3b1748da2d3148d15d253e1a03006f204aa68ca5/igraph-1.0.0-cp39-abi3-macosx_11_0_arm64.whl @@ -814,7 +1019,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py312h4c3975b_2.conda @@ -826,12 +1033,31 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/atk-1.0-2.38.0-h04ea711_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.10.3-hea842a7_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.9.14-h78948cc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.14.0-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-compression-0.3.2-haa0cbde_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.7.1-h9cf6be0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-http-0.11.0-h6488f85_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.26.3-h5b668fc_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-mqtt-0.15.2-h0d2f46f_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-s3-0.12.5-hb916526_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-sdkutils-0.2.4-haa0cbde_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.2.10-haa0cbde_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.40.0-h41299d8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.747-h6154047_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-core-cpp-1.16.2-h206d751_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-identity-cpp-1.13.3-hed0cdb0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-blobs-cpp-12.17.0-hf824e48_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-common-cpp-12.13.0-ha7a2c86_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-files-datalake-cpp-12.15.0-h1e5b466_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.5.0-py312h90b7ffd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.15.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.4.0-hac0b51c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda @@ -883,8 +1109,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.16-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.6-h2b0a6b4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-h5888daf_1005.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/git-cliff-2.13.1-h66dc0b5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.88.1-hee1de02_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.1-hbabe93e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphviz-14.1.2-h8b86629_0.conda @@ -897,6 +1127,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/hicolor-icon-theme-0.17-ha770c72_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/httptools-0.8.0-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda @@ -906,9 +1137,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_genutils-0.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-8.1.8-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-7.8.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/jaxlib-0.9.2-cpu_py312hc81e8bd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -932,7 +1165,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.8-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-3.0.16-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-1.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.5.0-py312h0a2e395_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda @@ -941,18 +1174,27 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-24.0.0-h8ff9baf_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-acero-24.0.0-h635bf11_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-compute-24.0.0-h53684a4_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-dataset-24.0.0-h635bf11_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-substrait-24.0.0-hb4dd7c2_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.5-default_h746c552_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.20.0-hcf29cc6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.127-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.0-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda @@ -970,16 +1212,22 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-devel-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-3.5.0-h8d2ee43_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-3.5.0-hdbdcf42_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.78.1-h1d1128b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h47877c9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.5-hf7376ad_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libntlm-1.8-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopentelemetry-cpp-1.27.0-h9692893_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopentelemetry-cpp-headers-1.27.0-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libparquet-24.0.0-h7376487_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.19-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.4-hd5a49e9_0.conda @@ -991,7 +1239,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.22.0-h7d032f7_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.11.3-hfe17d71_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libvulkan-loader-1.4.341.0-h5279c79_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda @@ -1005,6 +1255,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/lineax-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/llvmlite-0.47.0-py312h7424e68_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lxml-6.1.0-py312h63ddcf0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda @@ -1026,6 +1277,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-7.5.7-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numba-0.65.1-py312hd1dde6f_1.conda @@ -1040,6 +1292,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/opt_einsum-3.4.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-2.3.0-h21090e2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pandas-3.0.3-py312h8ecdadd_0.conda @@ -1058,14 +1311,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/prometheus-cpp-1.3.0-ha5d0236_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.52-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/protobuf-6.33.5-py312ha7b3241_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-24.0.0-py312h7900ff3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-core-24.0.0-py312h2054cf2_0_cpu.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyld-3.0.0-pyhcf101f3_0.conda @@ -1082,6 +1340,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda @@ -1097,6 +1356,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-2026.5.1-py312h192e038_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.7.3-hc5a330e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/salib-1.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scikit-learn-1.8.0-np2py312h3226591_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.17.1-py312h54fa4ab_0.conda @@ -1106,15 +1366,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sqlalchemy-2.0.49-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/statsmodels-0.14.6-py312h4f23490_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -1127,15 +1393,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.1-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/watchdog-6.0.0-py312h20c3967_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.25.0-hd6090a7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/websockets-16.0-py312h5253ce2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-4.0.15-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-3.6.10-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-2.1.2-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-0.4.1-h4f16b4b_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-cursor-0.1.6-hb03c661_0.conda @@ -1165,6 +1434,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h09e67af_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - pypi: https://files.pythonhosted.org/packages/90/3d/5642a1a06191b2e1e0f87a2e824e6d3eb7c32c589a68ed4d1dcbd3324d63/coverage_badge-1.1.2-py2.py3-none-any.whl @@ -1182,7 +1452,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda @@ -1193,12 +1465,31 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/atk-1.0-2.38.0-h4bec284_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.10.3-h2dfa1e0_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.9.14-hcb77be1_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.14.0-ha1e9b39_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.3.2-ha04291d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.7.1-hf02f33c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.11.0-he315c99_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.26.3-hd35ae92_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.15.2-h60a7cf6_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.12.5-h8cc6e82_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.2.4-ha04291d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.2.10-ha04291d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.40.0-h29c3229_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.747-h6b5c32a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-core-cpp-1.16.2-h87f1c7e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-identity-cpp-1.13.3-h1135191_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-blobs-cpp-12.17.0-hefc3566_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-common-cpp-12.13.0-h74781cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-files-datalake-cpp-12.15.0-haae7687_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/backports.zstd-1.5.0-py312h5f4ecc6_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.15.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.4.0-hac0b51c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-1.2.0-hf139dec_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-bin-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.2.0-py312h4b46afd_1.conda @@ -1247,8 +1538,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/fribidi-1.0.16-h8616949_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/frozendict-2.4.7-py312h80b0991_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gdk-pixbuf-2.44.6-hae309b2_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hac325c4_1005.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/git-cliff-2.13.1-h6d18f09_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glib-tools-2.88.1-h6437393_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.1-h2790a97_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphite2-1.3.14-h21dd04a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphviz-14.1.2-h44fc223_0.conda @@ -1261,6 +1556,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/hicolor-icon-theme-0.17-h694c41f_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/httptools-0.8.0-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda @@ -1270,9 +1566,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_genutils-0.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-8.1.8-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-7.8.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/jaxlib-0.9.0-cpu_py312hf3c3857_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -1296,21 +1594,30 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.8-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-3.0.16-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-1.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/kiwisolver-1.5.0-py312hb1dc2e7_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.22.2-h207b36a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lcms2-2.19.1-h5ea7634_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lerc-4.1.0-h35c7297_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20260107.1-cxx17_h7ed6875_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-24.0.0-h9e06b3e_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-24.0.0-h91633f5_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-compute-24.0.0-hb38465b_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-24.0.0-h91633f5_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-24.0.0-h613493e_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-7_he492b99_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-7_h9b27e0a_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.20.0-h8f0b9e4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.5-h19cb2f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libdeflate-1.25-h517ebb2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.0-hcc62823_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libfreetype-2.14.3-h694c41f_0.conda @@ -1321,13 +1628,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_19.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libgit2-1.9.3-h415d65b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libglib-2.88.1-hf28f236_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-3.5.0-h8b848e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-3.5.0-hea209c6_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libgrpc-1.78.1-h147dede_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libintl-0.25.1-h3184127_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libjpeg-turbo-3.1.4.1-ha1e9b39_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.11.0-7_h859234e_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h70048d4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.33-openmp_h9e49c7b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopentelemetry-cpp-1.27.0-h7a0a166_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopentelemetry-cpp-headers-1.27.0-h694c41f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libparquet-24.0.0-h0f82bca_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libpng-1.6.58-he930e7c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-6.33.5-hff14b61_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libre2-11-2025.11.05-h6e8c311_1.conda @@ -1335,7 +1648,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libsodium-1.0.22-ha3d0635_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.1-h8f8c405_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libthrift-0.22.0-hebea4ca_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libtiff-4.7.1-ha0a348c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libutf8proc-2.11.3-hc282952_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libwebp-base-1.6.0-hb807250_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libxcb-1.17.0-hf1f96e2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.3-h7a90416_0.conda @@ -1346,6 +1661,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.5-h0d3cbff_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/llvmlite-0.47.0-py312ha5a82fe_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lxml-6.1.0-py312h211e60a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-3.0.3-py312heb39f77_1.conda @@ -1367,6 +1683,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/nlohmann_json-3.12.0-h06076ce_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-7.5.7-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numba-0.65.1-py312h704f9c4_1.conda @@ -1379,6 +1696,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/opt_einsum-3.4.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-2.3.0-hb9b210e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pandas-3.0.3-py312h8e27051_0.conda @@ -1397,14 +1715,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/prometheus-cpp-1.3.0-h7802330_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.52-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/protobuf-6.33.5-py312hf5f8d9f_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-7.2.2-py312hf7082af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pthread-stubs-0.4-h00291cd_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-24.0.0-py312hb401068_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-core-24.0.0-py312h3987635_0_cpu.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyld-3.0.0-pyhcf101f3_0.conda @@ -1422,6 +1745,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.3-py312h51361c1_1.conda @@ -1445,15 +1769,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.2.2-h01f5ddf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sqlalchemy-2.0.49-py312hba6025d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/statsmodels-0.14.6-py312h391ab28_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tornado-6.5.5-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -1466,14 +1796,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/unicodedata2-17.0.1-py312h1a1c95f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/watchdog-6.0.0-py312hba6025d_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/websockets-16.0-py312hf7082af_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-4.0.15-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-3.6.10-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/wrapt-2.1.2-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/xlsxwriter-3.2.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/xorg-libxau-1.0.12-h8616949_1.conda @@ -1481,6 +1814,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zeromq-4.3.5-h84953be_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.2-hbb4bfdb_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-ng-2.3.3-h8bce59a_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - pypi: https://files.pythonhosted.org/packages/90/3d/5642a1a06191b2e1e0f87a2e824e6d3eb7c32c589a68ed4d1dcbd3324d63/coverage_badge-1.1.2-py2.py3-none-any.whl @@ -1498,7 +1832,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda @@ -1509,12 +1845,31 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/atk-1.0-2.38.0-hd03087b_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.10.3-hceed5df_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.9.14-h81c6212_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.14.0-h84a0fba_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-0.3.2-h61d3404_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-event-stream-0.7.1-h7e6a3cf_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-0.11.0-h0a63974_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-0.26.3-h58c0f83_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-mqtt-0.15.2-ha70999f_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-0.12.5-h43def2a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-0.2.4-h61d3404_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.2.10-h61d3404_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.40.0-hd6eb0f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.747-h55dad5a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-core-cpp-1.16.2-he5ae378_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-identity-cpp-1.13.3-h810541e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-blobs-cpp-12.17.0-h5446563_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-common-cpp-12.13.0-he467506_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-files-datalake-cpp-12.15.0-hfea7fb9_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.5.0-py312h87c4bb7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.15.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.4.0-hac0b51c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.2.0-h7d5ae5b_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py312h0dfefe5_1.conda @@ -1563,8 +1918,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fribidi-1.0.16-hc919400_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozendict-2.4.7-py312h4409184_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gdk-pixbuf-2.44.6-h4e57454_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hf9b8971_1005.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/git-cliff-2.13.1-h5a0b6fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-tools-2.88.1-h37541a8_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.1-heb240a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.14-hec049ff_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphviz-14.1.2-hec8c438_0.conda @@ -1577,6 +1936,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/hicolor-icon-theme-0.17-hce30654_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/httptools-0.8.0-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda @@ -1586,9 +1946,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_genutils-0.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-8.1.8-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-7.8.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/jaxlib-0.9.2-cpu_py312h8d61f43_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -1612,21 +1974,30 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.8-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-3.0.16-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-1.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/kiwisolver-1.5.0-py312h3093aea_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lcms2-2.19.1-hdfa7624_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lerc-4.1.0-h1eee2c3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260107.1-cxx17_h2062a1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-24.0.0-h91214ac_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-acero-24.0.0-ha4f4840_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-compute-24.0.0-h8d10c55_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-dataset-24.0.0-ha4f4840_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-substrait-24.0.0-h05be00f_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-7_h51639a9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-7_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.20.0-hd5a2499_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.0-hf6b4638_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.3-hce30654_0.conda @@ -1637,13 +2008,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgit2-1.9.3-h9a1894c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libglib-2.88.1-ha08bb59_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-3.5.0-h688a705_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-storage-3.5.0-ha114238_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgrpc-1.78.1-h3e3f78d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.25.1-h493aca8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-3.1.4.1-h84a0fba_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-7_hd9741b5_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.33-openmp_he657e61_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopentelemetry-cpp-1.27.0-h08d5cc3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopentelemetry-cpp-headers-1.27.0-hce30654_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libparquet-24.0.0-h840b369_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.58-h132b30e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-6.33.5-h2d4b707_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libre2-11-2025.11.05-h4c27e2a_1.conda @@ -1651,7 +2028,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.22-h1a92334_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libthrift-0.22.0-h1fb9c8a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libutf8proc-2.11.3-h2431656_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.3-h5ef1a60_0.conda @@ -1662,6 +2041,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvmlite-0.47.0-py312h7ca588d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lxml-6.1.0-py312h2f8615f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py312h04c11ed_1.conda @@ -1683,6 +2063,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-7.5.7-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numba-0.65.1-py312h2d3d6e9_1.conda @@ -1694,6 +2075,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/opt_einsum-3.4.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-2.3.0-hd11884d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pandas-3.0.3-py312h6510ced_0.conda @@ -1712,14 +2094,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prometheus-cpp-1.3.0-h0967b3e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.52-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/protobuf-6.33.5-py312h857ab9a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py312hb3ab3e3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-24.0.0-py312h1f38498_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-core-24.0.0-py312h21b41d0_0_cpu.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyld-3.0.0-pyhcf101f3_0.conda @@ -1737,6 +2124,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py312h04c11ed_1.conda @@ -1760,15 +2148,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sqlalchemy-2.0.49-py312hb3ab3e3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/statsmodels-0.14.6-py312ha11c99a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -1781,14 +2175,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/unicodedata2-17.0.1-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/watchdog-6.0.0-py312hb3ab3e3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/websockets-16.0-py312hb3ab3e3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-4.0.15-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-3.6.10-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/wrapt-2.1.2-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/xlsxwriter-3.2.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xorg-libxau-1.0.12-hc919400_1.conda @@ -1796,6 +2193,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h10816f8_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - pypi: https://files.pythonhosted.org/packages/90/3d/5642a1a06191b2e1e0f87a2e824e6d3eb7c32c589a68ed4d1dcbd3324d63/coverage_badge-1.1.2-py2.py3-none-any.whl @@ -1823,15 +2221,37 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-atk-2.38.0-h0630a04_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-core-2.40.3-h0630a04_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/atk-1.0-2.38.0-h04ea711_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.10.3-hea842a7_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.9.14-h78948cc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.14.0-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-compression-0.3.2-haa0cbde_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.7.1-h9cf6be0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-http-0.11.0-h6488f85_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.26.3-h5b668fc_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-mqtt-0.15.2-h0d2f46f_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-s3-0.12.5-hb916526_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-sdkutils-0.2.4-haa0cbde_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.2.10-haa0cbde_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.40.0-h41299d8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.747-h6154047_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-core-cpp-1.16.2-h206d751_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-identity-cpp-1.13.3-hed0cdb0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-blobs-cpp-12.17.0-hf824e48_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-common-cpp-12.13.0-ha7a2c86_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-files-datalake-cpp-12.15.0-h1e5b466_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.5.0-py312h90b7ffd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda @@ -1877,9 +2297,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.16-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.6-h2b0a6b4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-h5888daf_1005.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/git-cliff-2.13.1-h66dc0b5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.88.1-hee1de02_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.1-hbabe93e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphviz-14.1.2-h8b86629_0.conda @@ -1895,6 +2319,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/hicolor-icon-theme-0.17-ha770c72_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/httptools-0.8.0-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda @@ -1903,6 +2328,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/jaxlib-0.9.2-cpu_py312hc81e8bd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -1910,6 +2336,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.9.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda @@ -1919,18 +2347,27 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-24.0.0-h8ff9baf_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-acero-24.0.0-h635bf11_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-compute-24.0.0-h53684a4_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-dataset-24.0.0-h635bf11_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-substrait-24.0.0-hb4dd7c2_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.5-default_h746c552_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.20.0-hcf29cc6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.127-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.0-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda @@ -1948,16 +2385,22 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-devel-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-3.5.0-h8d2ee43_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-3.5.0-hdbdcf42_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.78.1-h1d1128b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h47877c9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.5-hf7376ad_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libntlm-1.8-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopentelemetry-cpp-1.27.0-h9692893_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopentelemetry-cpp-headers-1.27.0-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libparquet-24.0.0-h7376487_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.19-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.4-hd5a49e9_0.conda @@ -1969,7 +2412,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.22.0-h7d032f7_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.11.3-hfe17d71_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libvulkan-loader-1.4.341.0-h5279c79_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda @@ -1983,6 +2428,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/lineax-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/llvmlite-0.47.0-py312h7424e68_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lxml-6.1.0-py312h63ddcf0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda @@ -2006,6 +2452,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numba-0.65.1-py312hd1dde6f_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.5-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/numpyro-0.21.0-pyhd8ed1ab_0.conda @@ -2018,6 +2465,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/opt_einsum-3.4.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-2.3.0-h21090e2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pandas-3.0.3-py312h8ecdadd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pango-1.56.4-hda50119_1.conda @@ -2034,11 +2482,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/prometheus-cpp-1.3.0-ha5d0236_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/protobuf-6.33.5-py312ha7b3241_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-24.0.0-py312h7900ff3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-core-24.0.0-py312h2054cf2_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyld-3.0.0-pyhcf101f3_0.conda @@ -2052,6 +2505,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyyaml-env-tag-1.1-pyhd8ed1ab_0.conda @@ -2060,8 +2514,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/qt6-main-6.11.1-pl5321h16c4a6b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2025.11.05-h5301d42_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-2026.5.1-py312h192e038_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.7.3-hc5a330e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/salib-1.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scikit-learn-1.8.0-np2py312h3226591_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.17.1-py312h54fa4ab_0.conda @@ -2070,12 +2527,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sqlalchemy-2.0.49-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/statsmodels-0.14.6-py312h4f23490_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -2086,11 +2549,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.1-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/watchdog-6.0.0-py312h20c3967_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.25.0-hd6090a7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/websockets-16.0-py312h5253ce2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-2.1.2-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-0.4.1-h4f16b4b_2.conda @@ -2121,6 +2586,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h09e67af_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - pypi: https://files.pythonhosted.org/packages/2d/82/e5d2c1c67d19841e9edc74954c827444ae826978499bde3dfc1d007c8c11/deepmerge-2.0-py3-none-any.whl @@ -2139,14 +2605,36 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/atk-1.0-2.38.0-h4bec284_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.10.3-h2dfa1e0_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.9.14-hcb77be1_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.14.0-ha1e9b39_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.3.2-ha04291d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.7.1-hf02f33c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.11.0-he315c99_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.26.3-hd35ae92_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.15.2-h60a7cf6_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.12.5-h8cc6e82_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.2.4-ha04291d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.2.10-ha04291d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.40.0-h29c3229_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.747-h6b5c32a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-core-cpp-1.16.2-h87f1c7e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-identity-cpp-1.13.3-h1135191_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-blobs-cpp-12.17.0-hefc3566_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-common-cpp-12.13.0-h74781cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-files-datalake-cpp-12.15.0-haae7687_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/backports.zstd-1.5.0-py312h5f4ecc6_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-1.2.0-hf139dec_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-bin-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.2.0-py312h4b46afd_1.conda @@ -2189,9 +2677,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/fribidi-1.0.16-h8616949_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/frozendict-2.4.7-py312h80b0991_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gdk-pixbuf-2.44.6-hae309b2_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hac325c4_1005.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/git-cliff-2.13.1-h6d18f09_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glib-tools-2.88.1-h6437393_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.1-h2790a97_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphite2-1.3.14-h21dd04a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphviz-14.1.2-h44fc223_0.conda @@ -2207,6 +2699,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/hicolor-icon-theme-0.17-h694c41f_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/httptools-0.8.0-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda @@ -2215,6 +2708,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/jaxlib-0.9.0-cpu_py312hf3c3857_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -2222,6 +2716,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.9.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/kiwisolver-1.5.0-py312hb1dc2e7_0.conda @@ -2229,14 +2725,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/lcms2-2.19.1-h5ea7634_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lerc-4.1.0-h35c7297_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20260107.1-cxx17_h7ed6875_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-24.0.0-h9e06b3e_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-24.0.0-h91633f5_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-compute-24.0.0-hb38465b_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-24.0.0-h91633f5_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-24.0.0-h613493e_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-7_he492b99_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-7_h9b27e0a_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.20.0-h8f0b9e4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.5-h19cb2f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libdeflate-1.25-h517ebb2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.0-hcc62823_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libfreetype-2.14.3-h694c41f_0.conda @@ -2247,13 +2752,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_19.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libgit2-1.9.3-h415d65b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libglib-2.88.1-hf28f236_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-3.5.0-h8b848e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-3.5.0-hea209c6_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libgrpc-1.78.1-h147dede_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libintl-0.25.1-h3184127_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libjpeg-turbo-3.1.4.1-ha1e9b39_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.11.0-7_h859234e_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h70048d4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.33-openmp_h9e49c7b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopentelemetry-cpp-1.27.0-h7a0a166_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopentelemetry-cpp-headers-1.27.0-h694c41f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libparquet-24.0.0-h0f82bca_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libpng-1.6.58-he930e7c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-6.33.5-hff14b61_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libre2-11-2025.11.05-h6e8c311_1.conda @@ -2261,7 +2772,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libsodium-1.0.22-ha3d0635_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.1-h8f8c405_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libthrift-0.22.0-hebea4ca_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libtiff-4.7.1-ha0a348c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libutf8proc-2.11.3-hc282952_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libwebp-base-1.6.0-hb807250_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libxcb-1.17.0-hf1f96e2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.3-h7a90416_0.conda @@ -2272,6 +2785,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.5-h0d3cbff_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/llvmlite-0.47.0-py312ha5a82fe_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lxml-6.1.0-py312h211e60a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda @@ -2295,6 +2809,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/nlohmann_json-3.12.0-h06076ce_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numba-0.65.1-py312h704f9c4_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-2.4.5-py312h746d82c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/numpyro-0.21.0-pyhd8ed1ab_0.conda @@ -2305,6 +2820,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/opt_einsum-3.4.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-2.3.0-hb9b210e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pandas-3.0.3-py312h8e27051_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pango-1.56.4-hf280016_1.conda @@ -2321,11 +2837,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/prometheus-cpp-1.3.0-h7802330_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/protobuf-6.33.5-py312hf5f8d9f_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-7.2.2-py312hf7082af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pthread-stubs-0.4-h00291cd_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-24.0.0-py312hb401068_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-core-24.0.0-py312h3987635_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyld-3.0.0-pyhcf101f3_0.conda @@ -2338,6 +2859,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.3-py312h51361c1_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyyaml-env-tag-1.1-pyhd8ed1ab_0.conda @@ -2345,8 +2867,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/qhull-2020.2-h3c5361c_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2025.11.05-h77e0585_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rpds-py-2026.5.1-py312hb77ea7e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/salib-1.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/scikit-learn-1.8.0-np2py312h47bbdc5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.17.1-py312h6309490_0.conda @@ -2355,12 +2879,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.2.2-h01f5ddf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sqlalchemy-2.0.49-py312hba6025d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/statsmodels-0.14.6-py312h391ab28_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tornado-6.5.5-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -2371,10 +2901,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/unicodedata2-17.0.1-py312h1a1c95f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/watchdog-6.0.0-py312hba6025d_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/websockets-16.0-py312hf7082af_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/wrapt-2.1.2-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/xlsxwriter-3.2.9-pyhd8ed1ab_0.conda @@ -2383,6 +2915,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zeromq-4.3.5-h84953be_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.2-hbb4bfdb_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-ng-2.3.3-h8bce59a_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - pypi: https://files.pythonhosted.org/packages/2d/82/e5d2c1c67d19841e9edc74954c827444ae826978499bde3dfc1d007c8c11/deepmerge-2.0-py3-none-any.whl @@ -2401,14 +2934,36 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/atk-1.0-2.38.0-hd03087b_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.10.3-hceed5df_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.9.14-h81c6212_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.14.0-h84a0fba_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-0.3.2-h61d3404_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-event-stream-0.7.1-h7e6a3cf_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-0.11.0-h0a63974_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-0.26.3-h58c0f83_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-mqtt-0.15.2-ha70999f_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-0.12.5-h43def2a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-0.2.4-h61d3404_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.2.10-h61d3404_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.40.0-hd6eb0f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.747-h55dad5a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-core-cpp-1.16.2-he5ae378_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-identity-cpp-1.13.3-h810541e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-blobs-cpp-12.17.0-h5446563_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-common-cpp-12.13.0-he467506_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-files-datalake-cpp-12.15.0-hfea7fb9_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.5.0-py312h87c4bb7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.2.0-h7d5ae5b_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py312h0dfefe5_1.conda @@ -2451,9 +3006,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fribidi-1.0.16-hc919400_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozendict-2.4.7-py312h4409184_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gdk-pixbuf-2.44.6-h4e57454_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hf9b8971_1005.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/git-cliff-2.13.1-h5a0b6fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-tools-2.88.1-h37541a8_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.1-heb240a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.14-hec049ff_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphviz-14.1.2-hec8c438_0.conda @@ -2469,6 +3028,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/hicolor-icon-theme-0.17-hce30654_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/httptools-0.8.0-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda @@ -2477,6 +3037,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/jaxlib-0.9.2-cpu_py312h8d61f43_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -2484,6 +3045,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.9.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/kiwisolver-1.5.0-py312h3093aea_0.conda @@ -2491,14 +3054,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lcms2-2.19.1-hdfa7624_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lerc-4.1.0-h1eee2c3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260107.1-cxx17_h2062a1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-24.0.0-h91214ac_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-acero-24.0.0-ha4f4840_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-compute-24.0.0-h8d10c55_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-dataset-24.0.0-ha4f4840_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-substrait-24.0.0-h05be00f_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-7_h51639a9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-7_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.20.0-hd5a2499_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.0-hf6b4638_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.3-hce30654_0.conda @@ -2509,13 +3081,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgit2-1.9.3-h9a1894c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libglib-2.88.1-ha08bb59_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-3.5.0-h688a705_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-storage-3.5.0-ha114238_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgrpc-1.78.1-h3e3f78d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.25.1-h493aca8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-3.1.4.1-h84a0fba_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-7_hd9741b5_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.33-openmp_he657e61_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopentelemetry-cpp-1.27.0-h08d5cc3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopentelemetry-cpp-headers-1.27.0-hce30654_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libparquet-24.0.0-h840b369_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.58-h132b30e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-6.33.5-h2d4b707_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libre2-11-2025.11.05-h4c27e2a_1.conda @@ -2523,7 +3101,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.22-h1a92334_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libthrift-0.22.0-h1fb9c8a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libutf8proc-2.11.3-h2431656_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.3-h5ef1a60_0.conda @@ -2534,6 +3114,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvmlite-0.47.0-py312h7ca588d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lxml-6.1.0-py312h2f8615f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda @@ -2557,6 +3138,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numba-0.65.1-py312h2d3d6e9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.4.5-py312ha003a3f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/numpyro-0.21.0-pyhd8ed1ab_0.conda @@ -2566,6 +3148,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/opt_einsum-3.4.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-2.3.0-hd11884d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pandas-3.0.3-py312h6510ced_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pango-1.56.4-hf80efc4_1.conda @@ -2582,11 +3165,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prometheus-cpp-1.3.0-h0967b3e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/protobuf-6.33.5-py312h857ab9a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py312hb3ab3e3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-24.0.0-py312h1f38498_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-core-24.0.0-py312h21b41d0_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyld-3.0.0-pyhcf101f3_0.conda @@ -2599,6 +3187,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py312h04c11ed_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyyaml-env-tag-1.1-pyhd8ed1ab_0.conda @@ -2606,8 +3195,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/qhull-2020.2-h420ef59_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2025.11.05-ha480c28_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-2026.5.1-py312h8b1d842_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/salib-1.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py312he5ca3e3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.17.1-py312h0f234b1_0.conda @@ -2616,12 +3207,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sqlalchemy-2.0.49-py312hb3ab3e3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/statsmodels-0.14.6-py312ha11c99a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -2632,10 +3229,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/unicodedata2-17.0.1-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/watchdog-6.0.0-py312hb3ab3e3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/websockets-16.0-py312hb3ab3e3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/wrapt-2.1.2-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/xlsxwriter-3.2.9-pyhd8ed1ab_0.conda @@ -2644,6 +3243,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h10816f8_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - pypi: https://files.pythonhosted.org/packages/2d/82/e5d2c1c67d19841e9edc74954c827444ae826978499bde3dfc1d007c8c11/deepmerge-2.0-py3-none-any.whl @@ -2672,7 +3272,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py312h4c3975b_2.conda @@ -2684,12 +3286,31 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/atk-1.0-2.38.0-h04ea711_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.10.3-hea842a7_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.9.14-h78948cc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.14.0-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-compression-0.3.2-haa0cbde_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.7.1-h9cf6be0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-http-0.11.0-h6488f85_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.26.3-h5b668fc_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-mqtt-0.15.2-h0d2f46f_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-s3-0.12.5-hb916526_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-sdkutils-0.2.4-haa0cbde_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.2.10-haa0cbde_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.40.0-h41299d8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.747-h6154047_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-core-cpp-1.16.2-h206d751_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-identity-cpp-1.13.3-hed0cdb0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-blobs-cpp-12.17.0-hf824e48_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-common-cpp-12.13.0-ha7a2c86_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-files-datalake-cpp-12.15.0-h1e5b466_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.5.0-py312h90b7ffd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.15.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.4.0-hac0b51c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bottle-0.13.4-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda @@ -2742,9 +3363,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.16-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.6-h2b0a6b4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-h5888daf_1005.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/git-cliff-2.13.1-h66dc0b5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.88.1-hee1de02_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.1-hbabe93e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphviz-14.1.2-h8b86629_0.conda @@ -2761,6 +3386,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/hicolor-icon-theme-0.17-ha770c72_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/httptools-0.8.0-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda @@ -2770,9 +3396,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_genutils-0.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-8.1.8-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-7.8.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/jaxlib-0.9.2-cpu_py312hc81e8bd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -2796,7 +3424,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.8-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-3.0.16-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-1.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.5.0-py312h0a2e395_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda @@ -2805,18 +3433,27 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-24.0.0-h8ff9baf_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-acero-24.0.0-h635bf11_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-compute-24.0.0-h53684a4_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-dataset-24.0.0-h635bf11_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-substrait-24.0.0-hb4dd7c2_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.5-default_h746c552_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.20.0-hcf29cc6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.127-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.0-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda @@ -2834,16 +3471,22 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-devel-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-3.5.0-h8d2ee43_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-3.5.0-hdbdcf42_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.78.1-h1d1128b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h47877c9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.5-hf7376ad_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libntlm-1.8-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopentelemetry-cpp-1.27.0-h9692893_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopentelemetry-cpp-headers-1.27.0-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libparquet-24.0.0-h7376487_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.19-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.4-hd5a49e9_0.conda @@ -2855,7 +3498,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.22.0-h7d032f7_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.11.3-hfe17d71_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libvulkan-loader-1.4.341.0-h5279c79_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda @@ -2869,6 +3514,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/lineax-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/llvmlite-0.47.0-py312h7424e68_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lxml-6.1.0-py312h63ddcf0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda @@ -2897,6 +3543,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-7.5.7-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numba-0.65.1-py312hd1dde6f_1.conda @@ -2912,6 +3559,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-dashboard-0.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-2.3.0-h21090e2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pandas-3.0.3-py312h8ecdadd_0.conda @@ -2931,14 +3579,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/prometheus-cpp-1.3.0-ha5d0236_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.52-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/protobuf-6.33.5-py312ha7b3241_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-24.0.0-py312h7900ff3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-core-24.0.0-py312h2054cf2_0_cpu.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pygraphviz-1.14-py312hcdbcef4_3.conda @@ -2957,6 +3610,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda @@ -2973,6 +3627,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-2026.5.1-py312h192e038_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.7.3-hc5a330e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/salib-1.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scikit-learn-1.8.0-np2py312h3226591_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.17.1-py312h54fa4ab_0.conda @@ -2982,15 +3637,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sqlalchemy-2.0.49-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/statsmodels-0.14.6-py312h4f23490_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -3003,6 +3664,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.1-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/watchdog-6.0.0-py312h20c3967_3.conda @@ -3011,8 +3673,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/websockets-16.0-py312h5253ce2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-4.0.15-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-3.6.10-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-2.1.2-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-0.4.1-h4f16b4b_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-cursor-0.1.6-hb03c661_0.conda @@ -3042,6 +3705,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h09e67af_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - pypi: https://files.pythonhosted.org/packages/90/3d/5642a1a06191b2e1e0f87a2e824e6d3eb7c32c589a68ed4d1dcbd3324d63/coverage_badge-1.1.2-py2.py3-none-any.whl @@ -3061,7 +3725,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda @@ -3072,12 +3738,31 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/atk-1.0-2.38.0-h4bec284_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.10.3-h2dfa1e0_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.9.14-hcb77be1_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.14.0-ha1e9b39_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.3.2-ha04291d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.7.1-hf02f33c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.11.0-he315c99_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.26.3-hd35ae92_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.15.2-h60a7cf6_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.12.5-h8cc6e82_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.2.4-ha04291d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.2.10-ha04291d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.40.0-h29c3229_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.747-h6b5c32a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-core-cpp-1.16.2-h87f1c7e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-identity-cpp-1.13.3-h1135191_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-blobs-cpp-12.17.0-hefc3566_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-common-cpp-12.13.0-h74781cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-files-datalake-cpp-12.15.0-haae7687_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/backports.zstd-1.5.0-py312h5f4ecc6_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.15.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.4.0-hac0b51c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bottle-0.13.4-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-1.2.0-hf139dec_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-bin-1.2.0-h8616949_1.conda @@ -3127,9 +3812,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/fribidi-1.0.16-h8616949_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/frozendict-2.4.7-py312h80b0991_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gdk-pixbuf-2.44.6-hae309b2_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hac325c4_1005.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/git-cliff-2.13.1-h6d18f09_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glib-tools-2.88.1-h6437393_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.1-h2790a97_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphite2-1.3.14-h21dd04a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphviz-14.1.2-h44fc223_0.conda @@ -3146,6 +3835,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/hicolor-icon-theme-0.17-h694c41f_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/httptools-0.8.0-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda @@ -3155,9 +3845,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_genutils-0.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-8.1.8-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-7.8.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/jaxlib-0.9.0-cpu_py312hf3c3857_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -3181,21 +3873,30 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.8-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-3.0.16-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-1.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/kiwisolver-1.5.0-py312hb1dc2e7_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.22.2-h207b36a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lcms2-2.19.1-h5ea7634_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lerc-4.1.0-h35c7297_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20260107.1-cxx17_h7ed6875_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-24.0.0-h9e06b3e_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-24.0.0-h91633f5_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-compute-24.0.0-hb38465b_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-24.0.0-h91633f5_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-24.0.0-h613493e_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-7_he492b99_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-7_h9b27e0a_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.20.0-h8f0b9e4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.5-h19cb2f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libdeflate-1.25-h517ebb2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.0-hcc62823_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libfreetype-2.14.3-h694c41f_0.conda @@ -3206,13 +3907,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_19.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libgit2-1.9.3-h415d65b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libglib-2.88.1-hf28f236_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-3.5.0-h8b848e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-3.5.0-hea209c6_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libgrpc-1.78.1-h147dede_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libintl-0.25.1-h3184127_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libjpeg-turbo-3.1.4.1-ha1e9b39_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.11.0-7_h859234e_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h70048d4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.33-openmp_h9e49c7b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopentelemetry-cpp-1.27.0-h7a0a166_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopentelemetry-cpp-headers-1.27.0-h694c41f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libparquet-24.0.0-h0f82bca_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libpng-1.6.58-he930e7c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-6.33.5-hff14b61_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libre2-11-2025.11.05-h6e8c311_1.conda @@ -3220,7 +3927,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libsodium-1.0.22-ha3d0635_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.1-h8f8c405_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libthrift-0.22.0-hebea4ca_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libtiff-4.7.1-ha0a348c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libutf8proc-2.11.3-hc282952_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libwebp-base-1.6.0-hb807250_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libxcb-1.17.0-hf1f96e2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.3-h7a90416_0.conda @@ -3231,6 +3940,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.5-h0d3cbff_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/llvmlite-0.47.0-py312ha5a82fe_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lxml-6.1.0-py312h211e60a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda @@ -3259,6 +3969,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/nlohmann_json-3.12.0-h06076ce_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-7.5.7-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numba-0.65.1-py312h704f9c4_1.conda @@ -3272,6 +3983,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-dashboard-0.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-2.3.0-hb9b210e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pandas-3.0.3-py312h8e27051_0.conda @@ -3291,14 +4003,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/prometheus-cpp-1.3.0-h7802330_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.52-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/protobuf-6.33.5-py312hf5f8d9f_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-7.2.2-py312hf7082af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pthread-stubs-0.4-h00291cd_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-24.0.0-py312hb401068_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-core-24.0.0-py312h3987635_0_cpu.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pygraphviz-1.14-py312h9f547f1_3.conda @@ -3318,6 +4035,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.3-py312h51361c1_1.conda @@ -3342,15 +4060,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.2.2-h01f5ddf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sqlalchemy-2.0.49-py312hba6025d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/statsmodels-0.14.6-py312h391ab28_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tornado-6.5.5-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -3363,6 +4087,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/unicodedata2-17.0.1-py312h1a1c95f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/watchdog-6.0.0-py312hba6025d_3.conda @@ -3370,8 +4095,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/websockets-16.0-py312hf7082af_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-4.0.15-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-3.6.10-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/wrapt-2.1.2-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/xlsxwriter-3.2.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/xorg-libxau-1.0.12-h8616949_1.conda @@ -3379,6 +4105,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zeromq-4.3.5-h84953be_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.2-hbb4bfdb_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-ng-2.3.3-h8bce59a_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - pypi: https://files.pythonhosted.org/packages/90/3d/5642a1a06191b2e1e0f87a2e824e6d3eb7c32c589a68ed4d1dcbd3324d63/coverage_badge-1.1.2-py2.py3-none-any.whl @@ -3398,7 +4125,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda @@ -3409,12 +4138,31 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/atk-1.0-2.38.0-hd03087b_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.10.3-hceed5df_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.9.14-h81c6212_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.14.0-h84a0fba_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-0.3.2-h61d3404_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-event-stream-0.7.1-h7e6a3cf_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-0.11.0-h0a63974_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-0.26.3-h58c0f83_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-mqtt-0.15.2-ha70999f_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-0.12.5-h43def2a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-0.2.4-h61d3404_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.2.10-h61d3404_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.40.0-hd6eb0f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.747-h55dad5a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-core-cpp-1.16.2-he5ae378_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-identity-cpp-1.13.3-h810541e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-blobs-cpp-12.17.0-h5446563_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-common-cpp-12.13.0-he467506_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-files-datalake-cpp-12.15.0-hfea7fb9_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.5.0-py312h87c4bb7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.15.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.4.0-hac0b51c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bottle-0.13.4-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.2.0-h7d5ae5b_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.2.0-hc919400_1.conda @@ -3464,9 +4212,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fribidi-1.0.16-hc919400_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozendict-2.4.7-py312h4409184_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gdk-pixbuf-2.44.6-h4e57454_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hf9b8971_1005.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/git-cliff-2.13.1-h5a0b6fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-tools-2.88.1-h37541a8_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.1-heb240a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.14-hec049ff_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphviz-14.1.2-hec8c438_0.conda @@ -3483,6 +4235,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/hicolor-icon-theme-0.17-hce30654_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/httptools-0.8.0-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda @@ -3492,9 +4245,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_genutils-0.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-8.1.8-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-7.8.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/jaxlib-0.9.2-cpu_py312h8d61f43_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -3518,21 +4273,30 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.8-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-3.0.16-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-1.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/kiwisolver-1.5.0-py312h3093aea_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lcms2-2.19.1-hdfa7624_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lerc-4.1.0-h1eee2c3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260107.1-cxx17_h2062a1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-24.0.0-h91214ac_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-acero-24.0.0-ha4f4840_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-compute-24.0.0-h8d10c55_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-dataset-24.0.0-ha4f4840_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-substrait-24.0.0-h05be00f_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-7_h51639a9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-7_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.20.0-hd5a2499_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.0-hf6b4638_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.3-hce30654_0.conda @@ -3543,13 +4307,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgit2-1.9.3-h9a1894c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libglib-2.88.1-ha08bb59_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-3.5.0-h688a705_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-storage-3.5.0-ha114238_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgrpc-1.78.1-h3e3f78d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.25.1-h493aca8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-3.1.4.1-h84a0fba_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-7_hd9741b5_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.33-openmp_he657e61_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopentelemetry-cpp-1.27.0-h08d5cc3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopentelemetry-cpp-headers-1.27.0-hce30654_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libparquet-24.0.0-h840b369_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.58-h132b30e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-6.33.5-h2d4b707_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libre2-11-2025.11.05-h4c27e2a_1.conda @@ -3557,7 +4327,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.22-h1a92334_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libthrift-0.22.0-h1fb9c8a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libutf8proc-2.11.3-h2431656_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.3-h5ef1a60_0.conda @@ -3568,6 +4340,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvmlite-0.47.0-py312h7ca588d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lxml-6.1.0-py312h2f8615f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda @@ -3596,6 +4369,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-7.5.7-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numba-0.65.1-py312h2d3d6e9_1.conda @@ -3608,6 +4382,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-dashboard-0.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-2.3.0-hd11884d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pandas-3.0.3-py312h6510ced_0.conda @@ -3627,14 +4402,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prometheus-cpp-1.3.0-h0967b3e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.52-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/protobuf-6.33.5-py312h857ab9a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py312hb3ab3e3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-24.0.0-py312h1f38498_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-core-24.0.0-py312h21b41d0_0_cpu.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pygraphviz-1.14-py312h0c23599_3.conda @@ -3654,6 +4434,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py312h04c11ed_1.conda @@ -3678,15 +4459,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sqlalchemy-2.0.49-py312hb3ab3e3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/statsmodels-0.14.6-py312ha11c99a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -3699,6 +4486,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/unicodedata2-17.0.1-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/watchdog-6.0.0-py312hb3ab3e3_3.conda @@ -3706,8 +4494,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/websockets-16.0-py312hb3ab3e3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-4.0.15-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-3.6.10-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/wrapt-2.1.2-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/xlsxwriter-3.2.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xorg-libxau-1.0.12-hc919400_1.conda @@ -3715,6 +4504,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h10816f8_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - pypi: https://files.pythonhosted.org/packages/90/3d/5642a1a06191b2e1e0f87a2e824e6d3eb7c32c589a68ed4d1dcbd3324d63/coverage_badge-1.1.2-py2.py3-none-any.whl @@ -3744,15 +4534,37 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-atk-2.38.0-h0630a04_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-core-2.40.3-h0630a04_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/atk-1.0-2.38.0-h04ea711_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.10.3-hea842a7_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.9.14-h78948cc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.14.0-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-compression-0.3.2-haa0cbde_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.7.1-h9cf6be0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-http-0.11.0-h6488f85_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.26.3-h5b668fc_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-mqtt-0.15.2-h0d2f46f_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-s3-0.12.5-hb916526_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-sdkutils-0.2.4-haa0cbde_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.2.10-haa0cbde_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.40.0-h41299d8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.747-h6154047_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-core-cpp-1.16.2-h206d751_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-identity-cpp-1.13.3-hed0cdb0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-blobs-cpp-12.17.0-hf824e48_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-common-cpp-12.13.0-ha7a2c86_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-files-datalake-cpp-12.15.0-h1e5b466_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.5.0-py312h90b7ffd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bottle-0.13.4-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda @@ -3798,8 +4610,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.16-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.6-h2b0a6b4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-h5888daf_1005.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/git-cliff-2.13.1-h66dc0b5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.88.1-hee1de02_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.1-hbabe93e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphviz-14.1.2-h8b86629_0.conda @@ -3813,6 +4629,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/hicolor-icon-theme-0.17-ha770c72_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/httptools-0.8.0-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda @@ -3821,6 +4638,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/jaxlib-0.9.2-cpu_py312hc81e8bd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -3828,6 +4646,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.9.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda @@ -3837,18 +4657,27 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-24.0.0-h8ff9baf_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-acero-24.0.0-h635bf11_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-compute-24.0.0-h53684a4_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-dataset-24.0.0-h635bf11_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-substrait-24.0.0-hb4dd7c2_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.5-default_h746c552_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.20.0-hcf29cc6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.127-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.0-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda @@ -3866,16 +4695,22 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-devel-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-3.5.0-h8d2ee43_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-3.5.0-hdbdcf42_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.78.1-h1d1128b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h47877c9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.5-hf7376ad_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libntlm-1.8-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopentelemetry-cpp-1.27.0-h9692893_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopentelemetry-cpp-headers-1.27.0-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libparquet-24.0.0-h7376487_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.19-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.4-hd5a49e9_0.conda @@ -3887,7 +4722,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.22.0-h7d032f7_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.11.3-hfe17d71_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libvulkan-loader-1.4.341.0-h5279c79_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda @@ -3901,6 +4738,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/lineax-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/llvmlite-0.47.0-py312h7424e68_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lxml-6.1.0-py312h63ddcf0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda @@ -3917,6 +4755,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numba-0.65.1-py312hd1dde6f_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.5-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/numpyro-0.21.0-pyhd8ed1ab_0.conda @@ -3930,6 +4769,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-dashboard-0.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-2.3.0-h21090e2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pandas-3.0.3-py312h8ecdadd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pango-1.56.4-hda50119_1.conda @@ -3945,11 +4785,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/prometheus-cpp-1.3.0-ha5d0236_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/protobuf-6.33.5-py312ha7b3241_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-24.0.0-py312h7900ff3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-core-24.0.0-py312h2054cf2_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pygraphviz-1.14-py312hcdbcef4_3.conda @@ -3963,6 +4808,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_3.conda @@ -3970,8 +4816,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/qt6-main-6.11.1-pl5321h16c4a6b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2025.11.05-h5301d42_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-2026.5.1-py312h192e038_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.7.3-hc5a330e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/salib-1.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scikit-learn-1.8.0-np2py312h3226591_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.17.1-py312h54fa4ab_0.conda @@ -3980,12 +4829,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sqlalchemy-2.0.49-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/statsmodels-0.14.6-py312h4f23490_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -3996,10 +4851,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.1-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/watchdog-6.0.0-py312h20c3967_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.25.0-hd6090a7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/websockets-16.0-py312h5253ce2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-2.1.2-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-0.4.1-h4f16b4b_2.conda @@ -4030,6 +4888,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h09e67af_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - pypi: https://files.pythonhosted.org/packages/7d/da/dd2867c25adbb41563720f14b5fc895c98bf88be682a3faff4f7b3118d2a/igraph-1.0.0-cp39-abi3-manylinux_2_28_x86_64.whl @@ -4046,14 +4905,36 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/atk-1.0-2.38.0-h4bec284_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.10.3-h2dfa1e0_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.9.14-hcb77be1_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.14.0-ha1e9b39_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.3.2-ha04291d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.7.1-hf02f33c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.11.0-he315c99_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.26.3-hd35ae92_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.15.2-h60a7cf6_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.12.5-h8cc6e82_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.2.4-ha04291d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.2.10-ha04291d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.40.0-h29c3229_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.747-h6b5c32a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-core-cpp-1.16.2-h87f1c7e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-identity-cpp-1.13.3-h1135191_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-blobs-cpp-12.17.0-hefc3566_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-common-cpp-12.13.0-h74781cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-files-datalake-cpp-12.15.0-haae7687_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/backports.zstd-1.5.0-py312h5f4ecc6_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bottle-0.13.4-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-1.2.0-hf139dec_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-bin-1.2.0-h8616949_1.conda @@ -4096,8 +4977,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/fribidi-1.0.16-h8616949_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/frozendict-2.4.7-py312h80b0991_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gdk-pixbuf-2.44.6-hae309b2_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hac325c4_1005.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/git-cliff-2.13.1-h6d18f09_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glib-tools-2.88.1-h6437393_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.1-h2790a97_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphite2-1.3.14-h21dd04a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphviz-14.1.2-h44fc223_0.conda @@ -4111,6 +4996,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/hicolor-icon-theme-0.17-h694c41f_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/httptools-0.8.0-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda @@ -4119,6 +5005,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/jaxlib-0.9.0-cpu_py312hf3c3857_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -4126,6 +5013,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.9.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/kiwisolver-1.5.0-py312hb1dc2e7_0.conda @@ -4133,14 +5022,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/lcms2-2.19.1-h5ea7634_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lerc-4.1.0-h35c7297_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20260107.1-cxx17_h7ed6875_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-24.0.0-h9e06b3e_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-24.0.0-h91633f5_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-compute-24.0.0-hb38465b_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-24.0.0-h91633f5_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-24.0.0-h613493e_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-7_he492b99_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.2.0-h8616949_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-7_h9b27e0a_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.20.0-h8f0b9e4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.5-h19cb2f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libdeflate-1.25-h517ebb2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.0-hcc62823_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libfreetype-2.14.3-h694c41f_0.conda @@ -4151,13 +5049,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_19.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libgit2-1.9.3-h415d65b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libglib-2.88.1-hf28f236_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-3.5.0-h8b848e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-3.5.0-hea209c6_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libgrpc-1.78.1-h147dede_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libintl-0.25.1-h3184127_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libjpeg-turbo-3.1.4.1-ha1e9b39_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.11.0-7_h859234e_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h70048d4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.33-openmp_h9e49c7b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopentelemetry-cpp-1.27.0-h7a0a166_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopentelemetry-cpp-headers-1.27.0-h694c41f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libparquet-24.0.0-h0f82bca_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libpng-1.6.58-he930e7c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-6.33.5-hff14b61_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libre2-11-2025.11.05-h6e8c311_1.conda @@ -4165,7 +5069,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libsodium-1.0.22-ha3d0635_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.1-h8f8c405_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libthrift-0.22.0-hebea4ca_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libtiff-4.7.1-ha0a348c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libutf8proc-2.11.3-hc282952_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libwebp-base-1.6.0-hb807250_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libxcb-1.17.0-hf1f96e2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.3-h7a90416_0.conda @@ -4176,6 +5082,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.5-h0d3cbff_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/llvmlite-0.47.0-py312ha5a82fe_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lxml-6.1.0-py312h211e60a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-3.0.3-py312heb39f77_1.conda @@ -4192,6 +5099,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/nlohmann_json-3.12.0-h06076ce_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numba-0.65.1-py312h704f9c4_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-2.4.5-py312h746d82c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/numpyro-0.21.0-pyhd8ed1ab_0.conda @@ -4203,6 +5111,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-dashboard-0.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-2.3.0-hb9b210e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pandas-3.0.3-py312h8e27051_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pango-1.56.4-hf280016_1.conda @@ -4218,11 +5127,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/prometheus-cpp-1.3.0-h7802330_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/protobuf-6.33.5-py312hf5f8d9f_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-7.2.2-py312hf7082af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pthread-stubs-0.4-h00291cd_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-24.0.0-py312hb401068_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-core-24.0.0-py312h3987635_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pygraphviz-1.14-py312h9f547f1_3.conda @@ -4235,14 +5149,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.3-py312h51361c1_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pyzmq-27.1.0-py312h2ac7433_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/qhull-2020.2-h3c5361c_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2025.11.05-h77e0585_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rpds-py-2026.5.1-py312hb77ea7e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/salib-1.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/scikit-learn-1.8.0-np2py312h47bbdc5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.17.1-py312h6309490_0.conda @@ -4251,12 +5168,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.2.2-h01f5ddf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sqlalchemy-2.0.49-py312hba6025d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/statsmodels-0.14.6-py312h391ab28_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tornado-6.5.5-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -4267,9 +5190,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/unicodedata2-17.0.1-py312h1a1c95f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/watchdog-6.0.0-py312hba6025d_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/websockets-16.0-py312hf7082af_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/wrapt-2.1.2-py312h933eb07_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/xlsxwriter-3.2.9-pyhd8ed1ab_0.conda @@ -4278,6 +5204,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zeromq-4.3.5-h84953be_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.2-hbb4bfdb_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-ng-2.3.3-h8bce59a_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - pypi: https://files.pythonhosted.org/packages/a5/03/3278ad0ceb3ea0e84d8ae3a85bdded4d0e57853aeb802a200feb43847b93/igraph-1.0.0-cp39-abi3-macosx_10_15_x86_64.whl @@ -4294,14 +5221,36 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.18.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alive-progress-3.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/atk-1.0-2.38.0-hd03087b_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/autograd-1.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.10.3-hceed5df_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.9.14-h81c6212_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.14.0-h84a0fba_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-0.3.2-h61d3404_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-event-stream-0.7.1-h7e6a3cf_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-0.11.0-h0a63974_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-0.26.3-h58c0f83_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-mqtt-0.15.2-ha70999f_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-0.12.5-h43def2a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-0.2.4-h61d3404_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.2.10-h61d3404_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.40.0-hd6eb0f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.747-h55dad5a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-core-cpp-1.16.2-he5ae378_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-identity-cpp-1.13.3-h810541e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-blobs-cpp-12.17.0-h5446563_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-common-cpp-12.13.0-he467506_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-files-datalake-cpp-12.15.0-hfea7fb9_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.5.0-py312h87c4bb7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bottle-0.13.4-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.2.0-h7d5ae5b_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.2.0-hc919400_1.conda @@ -4344,8 +5293,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fribidi-1.0.16-hc919400_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozendict-2.4.7-py312h4409184_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gdk-pixbuf-2.44.6-h4e57454_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hf9b8971_1005.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/git-cliff-2.13.1-h5a0b6fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-tools-2.88.1-h37541a8_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.1-heb240a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.14-hec049ff_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphviz-14.1.2-hec8c438_0.conda @@ -4359,6 +5312,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/hicolor-icon-theme-0.17-hce30654_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/httptools-0.8.0-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda @@ -4367,6 +5321,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/jaxlib-0.9.2-cpu_py312h8d61f43_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaxopt-0.8.4-pyhd8ed1ab_0.conda @@ -4374,6 +5329,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.9.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/kiwisolver-1.5.0-py312h3093aea_0.conda @@ -4381,14 +5338,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lcms2-2.19.1-hdfa7624_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lerc-4.1.0-h1eee2c3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260107.1-cxx17_h2062a1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-24.0.0-h91214ac_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-acero-24.0.0-ha4f4840_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-compute-24.0.0-h8d10c55_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-dataset-24.0.0-ha4f4840_5_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-substrait-24.0.0-h05be00f_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-7_h51639a9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-7_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.20.0-hd5a2499_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.0-hf6b4638_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.3-hce30654_0.conda @@ -4399,13 +5365,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgit2-1.9.3-h9a1894c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libglib-2.88.1-ha08bb59_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-3.5.0-h688a705_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-storage-3.5.0-ha114238_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgrpc-1.78.1-h3e3f78d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.25.1-h493aca8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-3.1.4.1-h84a0fba_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-7_hd9741b5_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.33-openmp_he657e61_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopentelemetry-cpp-1.27.0-h08d5cc3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopentelemetry-cpp-headers-1.27.0-hce30654_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libparquet-24.0.0-h840b369_5_cpu.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.58-h132b30e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-6.33.5-h2d4b707_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libre2-11-2025.11.05-h4c27e2a_1.conda @@ -4413,7 +5385,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.22-h1a92334_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libthrift-0.22.0-h1fb9c8a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libutf8proc-2.11.3-h2431656_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.3-h5ef1a60_0.conda @@ -4424,6 +5398,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvmlite-0.47.0-py312h7ca588d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lxml-6.1.0-py312h2f8615f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py312h04c11ed_1.conda @@ -4440,6 +5415,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numba-0.65.1-py312h2d3d6e9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.4.5-py312ha003a3f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/numpyro-0.21.0-pyhd8ed1ab_0.conda @@ -4450,6 +5426,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/optimistix-0.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.8.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-dashboard-0.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-2.3.0-hd11884d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pandas-3.0.3-py312h6510ced_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pango-1.56.4-hf80efc4_1.conda @@ -4465,11 +5442,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pox-0.3.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ppft-1.7.8-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prometheus-cpp-1.3.0-h0967b3e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/protobuf-6.33.5-py312h857ab9a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py312hb3ab3e3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-24.0.0-py312h1f38498_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-core-24.0.0-py312h21b41d0_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pygraphviz-1.14-py312h0c23599_3.conda @@ -4482,14 +5464,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-graphviz-0.21-pyhbacfb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py312h04c11ed_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/qhull-2020.2-h420ef59_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2025.11.05-ha480c28_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-2026.5.1-py312h8b1d842_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/salib-1.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py312he5ca3e3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.17.1-py312h0f234b1_0.conda @@ -4498,12 +5483,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-81.0.0-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sqlalchemy-2.0.49-py312hb3ab3e3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/statsmodels-0.14.6-py312ha11c99a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda @@ -4514,9 +5505,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/unicodedata2-17.0.1-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/watchdog-6.0.0-py312hb3ab3e3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/websockets-16.0-py312hb3ab3e3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/wrapt-2.1.2-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/xlsxwriter-3.2.9-pyhd8ed1ab_0.conda @@ -4525,6 +5519,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h10816f8_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - pypi: https://files.pythonhosted.org/packages/0d/bc/6281ec7f9baaf71ee57c3b1748da2d3148d15d253e1a03006f204aa68ca5/igraph-1.0.0-cp39-abi3-macosx_11_0_arm64.whl @@ -4668,6 +5663,23 @@ packages: purls: [] size: 584660 timestamp: 1768327524772 +- conda: https://conda.anaconda.org/conda-forge/noarch/altair-6.2.1-pyhd8ed1ab_0.conda + sha256: a420cfb87d5688a00fd859c30115ff85528a0cc0b899b419537b259bb62a26d5 + md5: ba28d9dfeb5bfc14d26f2730ed8f13d8 + depends: + - importlib-metadata + - jinja2 + - jsonschema >=3.0 + - narwhals >=2.4.0 + - packaging + - python >=3.10 + - typing-extensions >=4.12.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/altair?source=compressed-mapping + size: 570625 + timestamp: 1780924043343 - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-doc-0.0.4-pyhcf101f3_0.conda sha256: cc9fbc50d4ee7ee04e49ee119243e6f1765750f0fd0b4d270d5ef35461b643b1 md5: 52be5139047efadaeeb19c6a5103f92a @@ -4680,6 +5692,18 @@ packages: - pkg:pypi/annotated-doc?source=hash-mapping size: 14222 timestamp: 1762868213144 +- conda: https://conda.anaconda.org/conda-forge/noarch/ansi2html-1.9.2-pyhcf101f3_3.conda + sha256: aa38131a1a861fa24b9ef61fb4a2412b81039e47bc714c030ee9d524fc0b7da4 + md5: d8573ef104c250314148c020f4c552e4 + depends: + - python >=3.10 + - python + license: LGPL-3.0-or-later + license_family: LGPL + purls: + - pkg:pypi/ansi2html?source=hash-mapping + size: 35961 + timestamp: 1757744058909 - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda sha256: f09aed24661cd45ba54a43772504f05c0698248734f9ae8cd289d314ac89707e md5: af2df4b9108808da3dc76710fe50eae2 @@ -4907,198 +5931,956 @@ packages: - pkg:pypi/autograd?source=hash-mapping size: 47679 timestamp: 1746451563674 -- conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - sha256: a14a9ad02101aab25570543a59c5193043b73dc311a25650134ed9e6cb691770 - md5: f1976ce927373500cc19d3c0b2c85177 - depends: - - python >=3.10 - - python - constrains: - - pytz >=2015.7 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/babel?source=hash-mapping - size: 7684321 - timestamp: 1772555330347 -- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.5.0-py312h90b7ffd_0.conda - sha256: a2b08a4e5e549b5f67c38edffd175437e2208547a7e67b5fa5373b67ef419e50 - md5: b31dba71fe091e7201826e57e0f7b261 +- conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.10.3-hea842a7_2.conda + sha256: 5b9c20a38fe084b4ffd1f2c64b3797ec6ef9a99e83cc0c1f84e016c9801e3a5c + md5: c463d2dbfb12a208c943165d2a568db4 depends: - - python - - libgcc >=14 - __glibc >=2.17,<3.0.a0 - - zstd >=1.5.7,<1.6.0a0 - - python_abi 3.12.* *_cp312 - license: BSD-3-Clause AND MIT AND EPL-2.0 - purls: - - pkg:pypi/backports-zstd?source=hash-mapping - size: 239928 - timestamp: 1778594049826 -- conda: https://conda.anaconda.org/conda-forge/osx-64/backports.zstd-1.5.0-py312h5f4ecc6_0.conda - sha256: f6166347ee8dd7e5c71029c27e89cc5d4a84ccb3f374761363d5bce08ce92227 - md5: c987aba92ae6e528ed495f1ea71d4834 + - libgcc >=14 + - aws-c-io >=0.26.3,<0.26.4.0a0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.11.0,<0.11.1.0a0 + - aws-c-sdkutils >=0.2.4,<0.2.5.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 134385 + timestamp: 1780598328124 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.10.3-h2dfa1e0_2.conda + sha256: 25f88f6ab63db63ef3011084cee06c62bfadde169a630a16588b21d6969320a2 + md5: 512f46909e6c405c20728918f60851b8 depends: - - python - __osx >=11.0 - - python_abi 3.12.* *_cp312 - - zstd >=1.5.7,<1.6.0a0 - license: BSD-3-Clause AND MIT AND EPL-2.0 - purls: - - pkg:pypi/backports-zstd?source=hash-mapping - size: 240621 - timestamp: 1778594129022 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.5.0-py312h87c4bb7_0.conda - sha256: a492dcf07b1c58797b3192f11aef7e3beb18ec91646d6a5acfe5c6e61e66118d - md5: 6ec306e02579965dc9c01092a5f4ce4c + - aws-c-sdkutils >=0.2.4,<0.2.5.0a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + - aws-c-http >=0.11.0,<0.11.1.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 120720 + timestamp: 1780598468278 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.10.3-hceed5df_2.conda + sha256: b4689664156e8067ba1aa97125f2a309a96b2bc0d1c608f4a88f30ea1f4c9aba + md5: e7501df14d3145fc86943ebfeb76a402 depends: - - python - __osx >=11.0 - - zstd >=1.5.7,<1.6.0a0 - - python_abi 3.12.* *_cp312 - license: BSD-3-Clause AND MIT AND EPL-2.0 - purls: - - pkg:pypi/backports-zstd?source=compressed-mapping - size: 240840 - timestamp: 1778594074672 -- conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.15.0-pyha770c72_0.conda - sha256: aed4b9dcf68ec2a75e5645fed14d77fd884d38d2e52bfa6ef4b278d90cd88781 - md5: 3b261da3fe9b4168738712832410b022 - depends: - - python >=3.10 - - soupsieve >=1.2 - - typing-extensions - license: MIT - license_family: MIT - purls: - - pkg:pypi/beautifulsoup4?source=hash-mapping - size: 92704 - timestamp: 1780853175566 -- conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda - sha256: 93b3f5782a46773e6e16d96c3fcd37f52a4ec0f8c4c28ec2427596b1dc7a2a7c - md5: e6a300dfd0e778f3f7c8a25b8894c56f - depends: - - python >=3.10 - - httpx >=0.22.0 - - pandas >=1.1.5 - - pyld >=0.7.2 - - python - license: BSD-2-Clause - license_family: BSD - purls: - - pkg:pypi/biothings-client?source=hash-mapping - size: 38022 - timestamp: 1775024557715 -- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.4.0-pyhcf101f3_0.conda - sha256: 0c786f3e571bd58ac73d730d06314716663884d848ae320de0b438fae5e0bea9 - md5: 93009c29cdd6f2500468f2502fff9209 - depends: - - python >=3.10 - - webencodings - - python - constrains: - - tinycss2 >=1.1.0,<1.5 - license: Apache-2.0 AND MIT - purls: - - pkg:pypi/bleach?source=compressed-mapping - size: 142246 - timestamp: 1780675823953 -- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.4.0-hac0b51c_0.conda - sha256: ede77e412304cd080e23967352a7904932207d0167ecdccd6a9e210530942be6 - md5: 5f710eab1f3c4e773c75686f5e8e6481 - depends: - - bleach ==6.4.0 pyhcf101f3_0 - - tinycss2 - license: Apache-2.0 AND MIT + - aws-c-sdkutils >=0.2.4,<0.2.5.0a0 + - aws-c-http >=0.11.0,<0.11.1.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: APACHE purls: [] - size: 4406 - timestamp: 1780675823953 -- conda: https://conda.anaconda.org/conda-forge/noarch/bottle-0.13.4-pyhe01879c_0.conda - sha256: 2a7c5d93059cc656de4af20d533f91fcf3aa063596f95aa93245553249b69030 - md5: ddb34ae9ba36f9479bf605302adf54e2 - depends: - - python >=3.9 - - python - license: MIT - license_family: MIT - purls: - - pkg:pypi/bottle?source=hash-mapping - size: 58208 - timestamp: 1754876199648 -- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda - sha256: e511644d691f05eb12ebe1e971fd6dc3ae55a4df5c253b4e1788b789bdf2dfa6 - md5: 8ccf913aaba749a5496c17629d859ed1 + size: 116718 + timestamp: 1780598398659 +- conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.9.14-h78948cc_2.conda + sha256: 06a0e2af439b21c94adff8fac5dd66dbda5f182fc80ac635c4903959ea306cbb + md5: fe81235aae00f32df8584267b4f2daf8 depends: - __glibc >=2.17,<3.0.a0 - - brotli-bin 1.2.0 hb03c661_1 - - libbrotlidec 1.2.0 hb03c661_1 - - libbrotlienc 1.2.0 hb03c661_1 + - aws-c-common >=0.14.0,<0.14.1.0a0 - libgcc >=14 - license: MIT - license_family: MIT + - openssl >=3.5.6,<4.0a0 + license: Apache-2.0 + license_family: Apache purls: [] - size: 20103 - timestamp: 1764017231353 -- conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-1.2.0-hf139dec_1.conda - sha256: c838c71ded28ada251589f6462fc0f7c09132396799eea2701277566a1a863bf - md5: 149d8ee7d6541a02a6117d8814fd9413 + size: 57011 + timestamp: 1780566647051 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.9.14-hcb77be1_2.conda + sha256: d36ca9a9d031d381f2270480d834833e0fdb71d4793307b0a11b0ed7e45b63a0 + md5: 18708874716ed71706c80769e8ba5409 depends: - - __osx >=10.13 - - brotli-bin 1.2.0 h8616949_1 - - libbrotlidec 1.2.0 h8616949_1 - - libbrotlienc 1.2.0 h8616949_1 - license: MIT - license_family: MIT + - __osx >=11.0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: Apache purls: [] - size: 20194 - timestamp: 1764017661405 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.2.0-h7d5ae5b_1.conda - sha256: 422ac5c91f8ef07017c594d9135b7ae068157393d2a119b1908c7e350938579d - md5: 48ece20aa479be6ac9a284772827d00c + size: 45674 + timestamp: 1780567082039 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.9.14-h81c6212_2.conda + sha256: 557bc47cbfd01dc569b930c102cd56ca5ba67750bd51a4fcee445246e7e536cd + md5: dcac0aa854a1f7f58a59226f5309a44e depends: - __osx >=11.0 - - brotli-bin 1.2.0 hc919400_1 - - libbrotlidec 1.2.0 hc919400_1 - - libbrotlienc 1.2.0 hc919400_1 - license: MIT - license_family: MIT + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: Apache purls: [] - size: 20237 - timestamp: 1764018058424 -- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda - sha256: 64b137f30b83b1dd61db6c946ae7511657eead59fdf74e84ef0ded219605aa94 - md5: af39b9a8711d4a8d437b52c1d78eb6a1 + size: 45764 + timestamp: 1780567235337 +- conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.14.0-hb03c661_0.conda + sha256: 6d2b33965bf6daeffd3ad336f41410053ff06ed6f2b2ce62c1ec27c0a39b4e7e + md5: f1c005b2e3b618706112ddd7f3af4521 depends: - __glibc >=2.17,<3.0.a0 - - libbrotlidec 1.2.0 hb03c661_1 - - libbrotlienc 1.2.0 hb03c661_1 - libgcc >=14 - license: MIT - license_family: MIT + license: Apache-2.0 + license_family: Apache purls: [] - size: 21021 - timestamp: 1764017221344 -- conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-bin-1.2.0-h8616949_1.conda - sha256: dcb5a2b29244b82af2545efad13dfdf8dddb86f88ce64ff415be9e7a10cc0383 - md5: 34803b20dfec7af32ba675c5ccdbedbf + size: 242497 + timestamp: 1780160843944 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.14.0-ha1e9b39_0.conda + sha256: c07dca511740b30b3bb26d9d5d14ce2577e65c422bc0afb875581792242a4514 + md5: 983f44cf7123c92ddbb19e9398f577ea depends: - - __osx >=10.13 - - libbrotlidec 1.2.0 h8616949_1 - - libbrotlienc 1.2.0 h8616949_1 - license: MIT - license_family: MIT + - __osx >=11.0 + license: Apache-2.0 + license_family: Apache purls: [] - size: 18589 - timestamp: 1764017635544 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.2.0-hc919400_1.conda - sha256: e2d142052a83ff2e8eab3fe68b9079cad80d109696dc063a3f92275802341640 - md5: 377d015c103ad7f3371be1777f8b584c + size: 232296 + timestamp: 1780161157428 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.14.0-h84a0fba_0.conda + sha256: 223f67551038366555e6934802d8b375547b142157aad3fc3654c720ac1525c0 + md5: 3a49923f2b3987a833a264caca603f84 depends: - __osx >=11.0 - - libbrotlidec 1.2.0 hc919400_1 - - libbrotlienc 1.2.0 hc919400_1 - license: MIT - license_family: MIT + license: Apache-2.0 + license_family: Apache + purls: [] + size: 226438 + timestamp: 1780161234587 +- conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-compression-0.3.2-haa0cbde_2.conda + sha256: 0e4952f9be8de7f281ca7d734a3a8f05ad0db856c6ef1e0897798c4afbcd9a54 + md5: 595911421e25551e36fde7027bf33f38 + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 22007 + timestamp: 1780566239465 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.3.2-ha04291d_2.conda + sha256: 7e3de1e42fb88192f1e39bb3d9024d3b228ad06b94508056d0d2175448387706 + md5: a7163d39a3e639901fc1ce4865e11b47 + depends: + - __osx >=11.0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 21517 + timestamp: 1780566351431 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-0.3.2-h61d3404_2.conda + sha256: 4289ff476103d109623bd413b12d61307d6267e87fc6a8c29b0aec71dfa8fd84 + md5: 497edff11fcb32865d8c5d6ab3aef6e0 + depends: + - __osx >=11.0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 21529 + timestamp: 1780566290492 +- conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.7.1-h9cf6be0_2.conda + sha256: 6b893ba3173206e17fef1b9c8b683c6f6ecbca7127770c8d0f3ba13d123f8d4c + md5: 2c304605f9074f072c92c0d8de175a1a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - aws-checksums >=0.2.10,<0.2.11.0a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 59271 + timestamp: 1780586883495 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.7.1-hf02f33c_2.conda + sha256: 52166148575189fb6fcbe272900ab3e1066cbf2af6e2d81d4408fe366211dc54 + md5: ea1fd47007bf4362c1d17e388af42479 + depends: + - __osx >=11.0 + - libcxx >=19 + - aws-checksums >=0.2.10,<0.2.11.0a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 54060 + timestamp: 1780586926676 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-event-stream-0.7.1-h7e6a3cf_2.conda + sha256: 5e0c69837e21fc17cc26ad6c252e842a96bb16f5be2c6f06f48a13b8a56fc56f + md5: 608685880a69722c685d1729c57409f6 + depends: + - __osx >=11.0 + - libcxx >=19 + - aws-checksums >=0.2.10,<0.2.11.0a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 53730 + timestamp: 1780586998748 +- conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-http-0.11.0-h6488f85_2.conda + sha256: d2b844db1a4dfbc20b5129b7df4a656c1459c5fb16745101bbd802813ba8d411 + md5: da0be1e8cb4a43c876f26d9d812dea06 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - aws-c-compression >=0.3.2,<0.3.3.0a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 230293 + timestamp: 1780586764553 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.11.0-he315c99_2.conda + sha256: 181d69666b6d7dab3669c2bf964971495c0b1dfa6a5823bf0626d8f53e1f56fb + md5: aa2b61bf50c3c666683488fef3187436 + depends: + - __osx >=11.0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - aws-c-compression >=0.3.2,<0.3.3.0a0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 197085 + timestamp: 1780586807052 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-0.11.0-h0a63974_2.conda + sha256: 06d3b08ed19cd63fd75750e325f19ebf7183b22ee27cbe2ca7b7dd6725d34885 + md5: f0fc8139091eb8245209bb9ee8911a82 + depends: + - __osx >=11.0 + - aws-c-compression >=0.3.2,<0.3.3.0a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 177282 + timestamp: 1780586850553 +- conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.26.3-h5b668fc_4.conda + sha256: c27b972325342f062da00b7aa2d5abf6f3ce55668a05703a175be958745cc226 + md5: 555400dce62f2d989ff77761c010d166 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - s2n >=1.7.3,<1.7.4.0a0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 181627 + timestamp: 1780575920109 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.26.3-hd35ae92_4.conda + sha256: 14903b20e23b9dbf8fc828ad1bffb46b68f1b100aee4a10beb6fbb5eb0068288 + md5: 3888bd82cc3a8f6bfa8ae0e4261b69cb + depends: + - __osx >=11.0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 182726 + timestamp: 1780575986786 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-0.26.3-h58c0f83_4.conda + sha256: 18f51bdc45eabe01ca68edf5ccc73369b3201639790575e6776f3efaea6e4356 + md5: b33f51eca94f6ccbd772ca4043fe1718 + depends: + - __osx >=11.0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 176913 + timestamp: 1780576001260 +- conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-mqtt-0.15.2-h0d2f46f_4.conda + sha256: c81aa872f74baf6bd2bb82cc87815895b3a654ef7831177a5c3d851ee27c05ea + md5: c66a882d62800e451a651b9b002f5066 + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - aws-c-http >=0.11.0,<0.11.1.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 221640 + timestamp: 1780598982374 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.15.2-h60a7cf6_4.conda + sha256: 6d035740e2a61a8bdec8405c68d78e5ac7e23582071bb6fc82d83f34191db5b6 + md5: bfdfb69208c68204ebe3fefa640efb32 + depends: + - __osx >=11.0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + - aws-c-http >=0.11.0,<0.11.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 193321 + timestamp: 1780599069085 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-mqtt-0.15.2-ha70999f_4.conda + sha256: ab15db26173d775b92503808bd4c29bfca484d5feb6b639793f8adba3004c56e + md5: 24f47ec268da87f530058df459de3dad + depends: + - __osx >=11.0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - aws-c-http >=0.11.0,<0.11.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 156284 + timestamp: 1780599082085 +- conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-s3-0.12.5-hb916526_1.conda + sha256: 8f193173f1dccb25ff86a95543db27f0c762cccfe93157b02cf20bd5b4c11a92 + md5: 70bc8e5e8cefd19407423733e7ebf540 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - aws-checksums >=0.2.10,<0.2.11.0a0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + - openssl >=3.5.6,<4.0a0 + - aws-c-auth >=0.10.3,<0.10.4.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - aws-c-http >=0.11.0,<0.11.1.0a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 153453 + timestamp: 1780609553521 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.12.5-h8cc6e82_1.conda + sha256: 2077da563f7e81f007a4eac4b233931c8500b3ca3aae50ef37001fa90e133792 + md5: 75914204f2c708212f2185abeca539b4 + depends: + - __osx >=11.0 + - aws-c-auth >=0.10.3,<0.10.4.0a0 + - aws-checksums >=0.2.10,<0.2.11.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - aws-c-http >=0.11.0,<0.11.1.0a0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 135785 + timestamp: 1780609654545 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-0.12.5-h43def2a_1.conda + sha256: 0a99b506bbe21f00f21047db50b2eea2ff8a0b1146ff0fba7d04b39a568453f4 + md5: 7dc63973f9fe772985b8c2f8ba5958ce + depends: + - __osx >=11.0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - aws-checksums >=0.2.10,<0.2.11.0a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + - aws-c-auth >=0.10.3,<0.10.4.0a0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.11.0,<0.11.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 132141 + timestamp: 1780609600116 +- conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-sdkutils-0.2.4-haa0cbde_6.conda + sha256: 123c4325b16f1f6db95846d51e5e4201399ee29c0325f8b5a8db2e7d732b9151 + md5: 4b66ac29a7e917a629b790c3d239d110 + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 59085 + timestamp: 1780568538653 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.2.4-ha04291d_6.conda + sha256: 44bca0a25e978729b995f2f265e0576d32292a4cc23953beafa233fec8f6184e + md5: 2d3f039770cab013521cc78e84b34e64 + depends: + - __osx >=11.0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 55961 + timestamp: 1780568586569 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-0.2.4-h61d3404_6.conda + sha256: ef53cd1e30bc8c865c44df6f097f36361945665157e63957d68fe90aa7e4d66c + md5: 127bce41f9e6cc3bdb9e6daed95896d9 + depends: + - __osx >=11.0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 53659 + timestamp: 1780568618924 +- conda: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.2.10-haa0cbde_2.conda + sha256: ad49333d96a5f9bcce02752a6515cbb077d7513e358a8fb1a832f4e772d54bac + md5: 5c05a63452bf73c50aa272a6f961c4fc + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 101627 + timestamp: 1780568539 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.2.10-ha04291d_2.conda + sha256: 5ba7da95d95800d1fcd21397a7ddcea505faee420b2efb21b35cd12a50ad7154 + md5: 81edba692bcff370dbf8e64660097c8d + depends: + - __osx >=11.0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 96023 + timestamp: 1780568602293 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.2.10-h61d3404_2.conda + sha256: 9af1483700bb29870297e2390838d3c31293e8cf80fd8a8a9bd9a1446020a8d8 + md5: 7c5f6a6efce80e728c1f743e064ab657 + depends: + - __osx >=11.0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 91975 + timestamp: 1780568646105 +- conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.40.0-h41299d8_1.conda + sha256: cc8eade570327e97ea458dd47dad9845fce5be070024a3fdaffe5aa4f68d2126 + md5: b4fbfcaea33878c12f0e035f5814280b + depends: + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + - aws-c-auth >=0.10.3,<0.10.4.0a0 + - aws-c-http >=0.11.0,<0.11.1.0a0 + - aws-c-event-stream >=0.7.1,<0.7.2.0a0 + - aws-c-mqtt >=0.15.2,<0.15.3.0a0 + - aws-c-s3 >=0.12.5,<0.12.6.0a0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + - aws-c-sdkutils >=0.2.4,<0.2.5.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 415624 + timestamp: 1780917918279 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.40.0-h29c3229_1.conda + sha256: 9592201c5e533e031542fc06c546afb1535b7731a11828d7fd24a8df2717ffa4 + md5: 5f3b48a9b1420e24f156f2aab77cb6fa + depends: + - libcxx >=19 + - __osx >=11.0 + - aws-c-s3 >=0.12.5,<0.12.6.0a0 + - aws-c-mqtt >=0.15.2,<0.15.3.0a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.11.0,<0.11.1.0a0 + - aws-c-event-stream >=0.7.1,<0.7.2.0a0 + - aws-c-auth >=0.10.3,<0.10.4.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - aws-c-sdkutils >=0.2.4,<0.2.5.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 352519 + timestamp: 1780918017140 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.40.0-hd6eb0f7_1.conda + sha256: 258cea4855f3d289dce09ab197bf2abfb5e983fefce371e4d100ec1a8d015277 + md5: 522e7961ac3402ab3814d9759f7c54de + depends: + - __osx >=11.0 + - libcxx >=19 + - aws-c-event-stream >=0.7.1,<0.7.2.0a0 + - aws-c-auth >=0.10.3,<0.10.4.0a0 + - aws-c-cal >=0.9.14,<0.9.15.0a0 + - aws-c-s3 >=0.12.5,<0.12.6.0a0 + - aws-c-sdkutils >=0.2.4,<0.2.5.0a0 + - aws-c-io >=0.26.3,<0.26.4.0a0 + - aws-c-http >=0.11.0,<0.11.1.0a0 + - aws-c-mqtt >=0.15.2,<0.15.3.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 275283 + timestamp: 1780917960902 +- conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.747-h6154047_6.conda + sha256: 224c461787555e92a1111b8a5c7f65db0559da631f05b0e29d06e79a267cc130 + md5: 9096d36ad4522d330bd6a5bdbd458275 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - aws-crt-cpp >=0.40.0,<0.40.1.0a0 + - libzlib >=1.3.2,<2.0a0 + - libcurl >=8.20.0,<9.0a0 + - aws-c-event-stream >=0.7.1,<0.7.2.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 3624840 + timestamp: 1781003610286 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.747-h6b5c32a_6.conda + sha256: 6e94795256fded99749f3e76ed98c5e5b289d2d64ef53b5ac0c3e424c97c261c + md5: 472743e866a6dbff31a9b784be804501 + depends: + - __osx >=11.0 + - libcxx >=19 + - aws-c-event-stream >=0.7.1,<0.7.2.0a0 + - libcurl >=8.20.0,<9.0a0 + - aws-crt-cpp >=0.40.0,<0.40.1.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - libzlib >=1.3.2,<2.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 3477227 + timestamp: 1781003677904 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.747-h55dad5a_6.conda + sha256: 9fa8fcc0da0b26269e488f8db252d416062671b55fbb57bc81c049343567ac37 + md5: 391aa9618724ce3a08901de5ae43c447 + depends: + - libcxx >=19 + - __osx >=11.0 + - libcurl >=8.20.0,<9.0a0 + - aws-c-event-stream >=0.7.1,<0.7.2.0a0 + - aws-c-common >=0.14.0,<0.14.1.0a0 + - libzlib >=1.3.2,<2.0a0 + - aws-crt-cpp >=0.40.0,<0.40.1.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 3261009 + timestamp: 1781003677069 +- conda: https://conda.anaconda.org/conda-forge/linux-64/azure-core-cpp-1.16.2-h206d751_0.conda + sha256: 321d1070905e467b6bc6f5067b97c1868d7345c272add82b82e08a0224e326f0 + md5: 5492abf806c45298ae642831c670bba0 + depends: + - __glibc >=2.17,<3.0.a0 + - libcurl >=8.18.0,<9.0a0 + - libgcc >=14 + - libstdcxx >=14 + - openssl >=3.5.4,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 348729 + timestamp: 1768837519361 +- conda: https://conda.anaconda.org/conda-forge/osx-64/azure-core-cpp-1.16.2-h87f1c7e_0.conda + sha256: bc2cde0d7204b3574084de1d83d80bceb7eb1550a17a0f0ccedbb312145475d3 + md5: 24997c4c96d1875956abd9ce37f262eb + depends: + - __osx >=10.13 + - libcurl >=8.18.0,<9.0a0 + - libcxx >=19 + - openssl >=3.5.4,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 298273 + timestamp: 1768837905794 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-core-cpp-1.16.2-he5ae378_0.conda + sha256: d9a04af33d9200fcd9f6c954e2a882c5ac78af4b82025623e59cb7f7e590b451 + md5: 7efe92d28599c224a24de11bb14d395e + depends: + - __osx >=11.0 + - libcurl >=8.18.0,<9.0a0 + - libcxx >=19 + - openssl >=3.5.4,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 290928 + timestamp: 1768837810218 +- conda: https://conda.anaconda.org/conda-forge/linux-64/azure-identity-cpp-1.13.3-hed0cdb0_1.conda + sha256: 2beb6ae8406f946b8963a67e72fe74453e1411c5ae7e992978340de6c512d13c + md5: 68bfb556bdf56d56e9f38da696e752ca + depends: + - __glibc >=2.17,<3.0.a0 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - libgcc >=14 + - libstdcxx >=14 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 250511 + timestamp: 1770344967948 +- conda: https://conda.anaconda.org/conda-forge/osx-64/azure-identity-cpp-1.13.3-h1135191_1.conda + sha256: 182769c18c23e2b29bb35f6fca4c233f0125f84418dacb2c36912298dafbe42e + md5: 14d2491d2dfcbb127fa0ff6219704ab5 + depends: + - __osx >=10.13 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - libcxx >=19 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 175167 + timestamp: 1770345309347 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-identity-cpp-1.13.3-h810541e_1.conda + sha256: 428fa73808a688a252639080b6751953ad7ecd8a4cbd8f23147b954d6902b31b + md5: ca46cc84466b5e05f15a4c4f263b6e80 + depends: + - __osx >=11.0 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - libcxx >=19 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 167424 + timestamp: 1770345338067 +- conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-blobs-cpp-12.17.0-hf824e48_1.conda + sha256: be3680fb1ee53451383a942ce70e2463c97d278eadd8b7251f27241d48a12eea + md5: 7fffabaef945a7d1794dfe884cc71d2f + depends: + - __glibc >=2.17,<3.0.a0 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - azure-storage-common-cpp >=12.13.0,<12.13.1.0a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + size: 587104 + timestamp: 1778840673576 +- conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-blobs-cpp-12.17.0-hefc3566_1.conda + sha256: bb0b60f062a30eb46c84f09ed6266a4fd2550aa9fe38902668e18409861cb26f + md5: 462274475c7e0de7b4e3e4bd600c8383 + depends: + - __osx >=11.0 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - azure-storage-common-cpp >=12.13.0,<12.13.1.0a0 + - libcxx >=19 + license: MIT + license_family: MIT + purls: [] + size: 442119 + timestamp: 1778841001503 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-blobs-cpp-12.17.0-h5446563_1.conda + sha256: 006adead59236b7bbf55da1e98c8a5147312b2eebd13f6f1be334a1c10cd8c59 + md5: 64665660d15e88c0214007f57e4cbe36 + depends: + - __osx >=11.0 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - azure-storage-common-cpp >=12.13.0,<12.13.1.0a0 + - libcxx >=19 + license: MIT + license_family: MIT + purls: [] + size: 434440 + timestamp: 1778841366650 +- conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-common-cpp-12.13.0-ha7a2c86_0.conda + sha256: 67fa6937bc2f6400f5ff19727f5d926fdc68d7fce3aaeab4016f49bb93d89cbb + md5: a7e8cca395e0a1616b389749580b7804 + depends: + - __glibc >=2.17,<3.0.a0 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - libgcc >=14 + - libstdcxx >=14 + - libxml2 + - libxml2-16 >=2.14.6 + - openssl >=3.5.6,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 159140 + timestamp: 1778661935076 +- conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-common-cpp-12.13.0-h74781cd_0.conda + sha256: 21cf4bc77e20a4a4874452dc5438fdae86f2cccfa2ffa29e920b2be0450e906b + md5: 7d4ec20278fbc5159c0899787a8afea3 + depends: + - __osx >=11.0 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - libcxx >=19 + - libxml2 + - libxml2-16 >=2.14.6 + - openssl >=3.5.6,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 133457 + timestamp: 1778662369219 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-common-cpp-12.13.0-he467506_0.conda + sha256: bc73ce983d90baa732e6f64e4d8b4ddbb8e671c5d6e7b9475d33dbd118ddd5b6 + md5: 4cfc08976cf62fef7736a763652987cb + depends: + - __osx >=11.0 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - libcxx >=19 + - libxml2 + - libxml2-16 >=2.14.6 + - openssl >=3.5.6,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 128808 + timestamp: 1778662321258 +- conda: https://conda.anaconda.org/conda-forge/linux-64/azure-storage-files-datalake-cpp-12.15.0-h1e5b466_0.conda + sha256: b6d0c80a01c9c3d652b47fd894ce32bcb2aad49829824a63235ede9375b8ae25 + md5: c9186aa979528963657db3e63c25e987 + depends: + - __glibc >=2.17,<3.0.a0 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - azure-storage-blobs-cpp >=12.17.0,<12.17.1.0a0 + - azure-storage-common-cpp >=12.13.0,<12.13.1.0a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + size: 303841 + timestamp: 1778870507280 +- conda: https://conda.anaconda.org/conda-forge/osx-64/azure-storage-files-datalake-cpp-12.15.0-haae7687_0.conda + sha256: a409db604fef0edb99b9bf9f3208f64c433184686f890a4adb2db46ca0e4ada3 + md5: db657cfeb64d33244726cf1b30930edd + depends: + - __osx >=11.0 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - azure-storage-blobs-cpp >=12.17.0,<12.17.1.0a0 + - azure-storage-common-cpp >=12.13.0,<12.13.1.0a0 + - libcxx >=19 + license: MIT + license_family: MIT + purls: [] + size: 208419 + timestamp: 1778871005257 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/azure-storage-files-datalake-cpp-12.15.0-hfea7fb9_0.conda + sha256: 75a7567556dc579ac2a6e07f7046b4ca1a18871aa207351d1e9dff6be0770d03 + md5: cdd2b09a96d66def91b0539282803cfc + depends: + - __osx >=11.0 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - azure-storage-blobs-cpp >=12.17.0,<12.17.1.0a0 + - azure-storage-common-cpp >=12.13.0,<12.13.1.0a0 + - libcxx >=19 + license: MIT + license_family: MIT + purls: [] + size: 201824 + timestamp: 1778871097416 +- conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + sha256: a14a9ad02101aab25570543a59c5193043b73dc311a25650134ed9e6cb691770 + md5: f1976ce927373500cc19d3c0b2c85177 + depends: + - python >=3.10 + - python + constrains: + - pytz >=2015.7 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/babel?source=hash-mapping + size: 7684321 + timestamp: 1772555330347 +- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.5.0-py312h90b7ffd_0.conda + sha256: a2b08a4e5e549b5f67c38edffd175437e2208547a7e67b5fa5373b67ef419e50 + md5: b31dba71fe091e7201826e57e0f7b261 + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 239928 + timestamp: 1778594049826 +- conda: https://conda.anaconda.org/conda-forge/osx-64/backports.zstd-1.5.0-py312h5f4ecc6_0.conda + sha256: f6166347ee8dd7e5c71029c27e89cc5d4a84ccb3f374761363d5bce08ce92227 + md5: c987aba92ae6e528ed495f1ea71d4834 + depends: + - python + - __osx >=11.0 + - python_abi 3.12.* *_cp312 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 240621 + timestamp: 1778594129022 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.5.0-py312h87c4bb7_0.conda + sha256: a492dcf07b1c58797b3192f11aef7e3beb18ec91646d6a5acfe5c6e61e66118d + md5: 6ec306e02579965dc9c01092a5f4ce4c + depends: + - python + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=compressed-mapping + size: 240840 + timestamp: 1778594074672 +- conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.15.0-pyha770c72_0.conda + sha256: aed4b9dcf68ec2a75e5645fed14d77fd884d38d2e52bfa6ef4b278d90cd88781 + md5: 3b261da3fe9b4168738712832410b022 + depends: + - python >=3.10 + - soupsieve >=1.2 + - typing-extensions + license: MIT + license_family: MIT + purls: + - pkg:pypi/beautifulsoup4?source=hash-mapping + size: 92704 + timestamp: 1780853175566 +- conda: https://conda.anaconda.org/conda-forge/noarch/biothings_client-0.5.0-pyhcf101f3_0.conda + sha256: 93b3f5782a46773e6e16d96c3fcd37f52a4ec0f8c4c28ec2427596b1dc7a2a7c + md5: e6a300dfd0e778f3f7c8a25b8894c56f + depends: + - python >=3.10 + - httpx >=0.22.0 + - pandas >=1.1.5 + - pyld >=0.7.2 + - python + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/biothings-client?source=hash-mapping + size: 38022 + timestamp: 1775024557715 +- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.4.0-pyhcf101f3_0.conda + sha256: 0c786f3e571bd58ac73d730d06314716663884d848ae320de0b438fae5e0bea9 + md5: 93009c29cdd6f2500468f2502fff9209 + depends: + - python >=3.10 + - webencodings + - python + constrains: + - tinycss2 >=1.1.0,<1.5 + license: Apache-2.0 AND MIT + purls: + - pkg:pypi/bleach?source=compressed-mapping + size: 142246 + timestamp: 1780675823953 +- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.4.0-hac0b51c_0.conda + sha256: ede77e412304cd080e23967352a7904932207d0167ecdccd6a9e210530942be6 + md5: 5f710eab1f3c4e773c75686f5e8e6481 + depends: + - bleach ==6.4.0 pyhcf101f3_0 + - tinycss2 + license: Apache-2.0 AND MIT + purls: [] + size: 4406 + timestamp: 1780675823953 +- conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda + sha256: f7efd22b5c15b400ed84a996d777b6327e5c402e79e3c534a7e086236f1eb2dc + md5: 42834439227a4551b939beeeb8a4b085 + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/blinker?source=hash-mapping + size: 13934 + timestamp: 1731096548765 +- conda: https://conda.anaconda.org/conda-forge/noarch/bottle-0.13.4-pyhe01879c_0.conda + sha256: 2a7c5d93059cc656de4af20d533f91fcf3aa063596f95aa93245553249b69030 + md5: ddb34ae9ba36f9479bf605302adf54e2 + depends: + - python >=3.9 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/bottle?source=hash-mapping + size: 58208 + timestamp: 1754876199648 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda + sha256: e511644d691f05eb12ebe1e971fd6dc3ae55a4df5c253b4e1788b789bdf2dfa6 + md5: 8ccf913aaba749a5496c17629d859ed1 + depends: + - __glibc >=2.17,<3.0.a0 + - brotli-bin 1.2.0 hb03c661_1 + - libbrotlidec 1.2.0 hb03c661_1 + - libbrotlienc 1.2.0 hb03c661_1 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 20103 + timestamp: 1764017231353 +- conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-1.2.0-hf139dec_1.conda + sha256: c838c71ded28ada251589f6462fc0f7c09132396799eea2701277566a1a863bf + md5: 149d8ee7d6541a02a6117d8814fd9413 + depends: + - __osx >=10.13 + - brotli-bin 1.2.0 h8616949_1 + - libbrotlidec 1.2.0 h8616949_1 + - libbrotlienc 1.2.0 h8616949_1 + license: MIT + license_family: MIT + purls: [] + size: 20194 + timestamp: 1764017661405 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.2.0-h7d5ae5b_1.conda + sha256: 422ac5c91f8ef07017c594d9135b7ae068157393d2a119b1908c7e350938579d + md5: 48ece20aa479be6ac9a284772827d00c + depends: + - __osx >=11.0 + - brotli-bin 1.2.0 hc919400_1 + - libbrotlidec 1.2.0 hc919400_1 + - libbrotlienc 1.2.0 hc919400_1 + license: MIT + license_family: MIT + purls: [] + size: 20237 + timestamp: 1764018058424 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda + sha256: 64b137f30b83b1dd61db6c946ae7511657eead59fdf74e84ef0ded219605aa94 + md5: af39b9a8711d4a8d437b52c1d78eb6a1 + depends: + - __glibc >=2.17,<3.0.a0 + - libbrotlidec 1.2.0 hb03c661_1 + - libbrotlienc 1.2.0 hb03c661_1 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 21021 + timestamp: 1764017221344 +- conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-bin-1.2.0-h8616949_1.conda + sha256: dcb5a2b29244b82af2545efad13dfdf8dddb86f88ce64ff415be9e7a10cc0383 + md5: 34803b20dfec7af32ba675c5ccdbedbf + depends: + - __osx >=10.13 + - libbrotlidec 1.2.0 h8616949_1 + - libbrotlienc 1.2.0 h8616949_1 + license: MIT + license_family: MIT + purls: [] + size: 18589 + timestamp: 1764017635544 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.2.0-hc919400_1.conda + sha256: e2d142052a83ff2e8eab3fe68b9079cad80d109696dc063a3f92275802341640 + md5: 377d015c103ad7f3371be1777f8b584c + depends: + - __osx >=11.0 + - libbrotlidec 1.2.0 hc919400_1 + - libbrotlienc 1.2.0 hc919400_1 + license: MIT + license_family: MIT purls: [] size: 18628 timestamp: 1764018033635 @@ -6182,6 +7964,40 @@ packages: purls: [] size: 548309 timestamp: 1774986047281 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-h5888daf_1005.conda + sha256: 6c33bf0c4d8f418546ba9c250db4e4221040936aef8956353bc764d4877bc39a + md5: d411fc29e338efb48c5fd4576d71d881 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libstdcxx >=13 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 119654 + timestamp: 1726600001928 +- conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hac325c4_1005.conda + sha256: c0bea66f71a6f4baa8d4f0248e17f65033d558d9e882c0af571b38bcca3e4b46 + md5: a26de8814083a6971f14f9c8c3cb36c2 + depends: + - __osx >=10.13 + - libcxx >=17 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 84946 + timestamp: 1726600054963 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hf9b8971_1005.conda + sha256: fd56ed8a1dab72ab90d8a8929b6f916a6d9220ca297ff077f8f04c5ed3408e20 + md5: 57a511a5905caa37540eb914dfcbf1fb + depends: + - __osx >=11.0 + - libcxx >=17 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 82090 + timestamp: 1726600145480 - conda: https://conda.anaconda.org/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_2.conda sha256: 40fdf5a9d5cc7a3503cd0c33e1b90b1e6eab251aaaa74e6b965417d089809a15 md5: 93f742fe078a7b34c29a182958d4d765 @@ -6237,6 +8053,31 @@ packages: purls: [] size: 4889040 timestamp: 1777214915812 +- conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda + sha256: dbbec21a369872c8ebe23cb9a3b9d63638479ee30face165aa0fccc96e93eec3 + md5: 7c14f3706e099f8fcd47af2d494616cc + depends: + - python >=3.9 + - smmap >=3.0.1,<6 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/gitdb?source=hash-mapping + size: 53136 + timestamp: 1735887290843 +- conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda + sha256: 718c9d0cc287ffda978996c4105ddd2863dd7bad7fb5794cdd365bd809ef2fa5 + md5: 98958318a01373a615f119b1040b3027 + depends: + - gitdb >=4.0.1,<5 + - python >=3.10 + - typing_extensions >=3.10.0.2 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/gitpython?source=hash-mapping + size: 162193 + timestamp: 1778065820061 - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.88.1-hee1de02_2.conda sha256: ae41fd5c867bc4e713a8cc1dc06f5b418026fec116cc222abe33e94235c6b241 md5: e5a459d2bb98edb88de5a44bfad66b9d @@ -6273,6 +8114,42 @@ packages: purls: [] size: 204902 timestamp: 1778508895255 +- conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.1-hbabe93e_0.conda + sha256: dc824dc1d0aa358e28da2ecbbb9f03d932d976c8dca11214aa1dcdfcbd054ba2 + md5: ff862eebdfeb2fd048ae9dc92510baca + depends: + - gflags >=2.2.2,<2.3.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 143452 + timestamp: 1718284177264 +- conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.1-h2790a97_0.conda + sha256: dd56547db8625eb5c91bb0a9fbe8bd6f5c7fbf5b6059d46365e94472c46b24f9 + md5: 06cf91665775b0da395229cd4331b27d + depends: + - __osx >=10.13 + - gflags >=2.2.2,<2.3.0a0 + - libcxx >=16 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 117017 + timestamp: 1718284325443 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.1-heb240a5_0.conda + sha256: 9fc77de416953aa959039db72bc41bfa4600ae3ff84acad04a7d0c1ab9552602 + md5: fef68d0a95aa5b84b5c1a4f6f3bf40e1 + depends: + - __osx >=11.0 + - gflags >=2.2.2,<2.3.0a0 + - libcxx >=16 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 112215 + timestamp: 1718284365403 - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda sha256: a240fa87f988d73863e5f0e49abc85103cba8bd8caf3d1df92c8999a26a50ef2 md5: 794487e5353f8ea5bf3b6bb55e460791 @@ -6751,6 +8628,47 @@ packages: - pkg:pypi/httpcore?source=hash-mapping size: 49483 timestamp: 1745602916758 +- conda: https://conda.anaconda.org/conda-forge/linux-64/httptools-0.8.0-py312h4c3975b_0.conda + sha256: c2a9f3bdc3708555c0e7d4125d0c544a3ddfad75b86d683ce7903778b326bb43 + md5: b71b691f15371ef1628fc6229df9fd39 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/httptools?source=compressed-mapping + size: 103105 + timestamp: 1779757517448 +- conda: https://conda.anaconda.org/conda-forge/osx-64/httptools-0.8.0-py312h933eb07_0.conda + sha256: 8399c7ac507dbb18c425684e362f58e76980bf8df48701ca2751f40f013d8d5c + md5: 1e730af039a43e2a85ec730c326f6d89 + depends: + - __osx >=11.0 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/httptools?source=hash-mapping + size: 91728 + timestamp: 1779757774471 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/httptools-0.8.0-py312h2bbb03f_0.conda + sha256: e9f593b0480db19f92b5f51990d2144f4192cc49b67e180f8b49ca5dcd3f839b + md5: 6059c5018f728489df82e9f5647eb4d0 + depends: + - __osx >=11.0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/httptools?source=hash-mapping + size: 92162 + timestamp: 1779757961181 - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda sha256: cd0f1de3697b252df95f98383e9edb1d00386bfdd03fdf607fa42fe5fcb09950 md5: d6989ead454181f4f9bc987d3dc4e285 @@ -7037,6 +8955,17 @@ packages: - pkg:pypi/ipython?source=hash-mapping size: 652893 timestamp: 1780654403616 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipython_genutils-0.2.0-pyhd8ed1ab_2.conda + sha256: 45821a8986b4cb2421f766b240dbe6998a3c3123f012dd566720c1322e9b6e18 + md5: 2f0ba4bc12af346bc6c99bdc377e8944 + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipython-genutils?source=hash-mapping + size: 28153 + timestamp: 1733399692864 - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda sha256: 894682a42a7d659ae12878dbcb274516a7031bbea9104e92f8e88c1f2765a104 md5: bd80ba060603cc228d9d81c257093119 @@ -7049,22 +8978,23 @@ packages: - pkg:pypi/ipython-pygments-lexers?source=hash-mapping size: 13993 timestamp: 1737123723464 -- conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-8.1.8-pyhd8ed1ab_0.conda - sha256: 6bb58afb7eabc8b4ac0c7e92707fb498313cc0164cf04e7ba1090dbf49af514b - md5: d68e3f70d1f068f1b66d94822fdc644e +- conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-7.8.5-pyhd8ed1ab_0.conda + sha256: 8cc67e44137bb779c76d92952fdc4d8cd475605f4f0d13e8d0f04f25c056939b + md5: 47672c493015ab57d5fcde9531ab18ef depends: - comm >=0.1.3 - - ipython >=6.1.0 - - jupyterlab_widgets >=3.0.15,<3.1.0 - - python >=3.10 + - ipython >=4.0.0 + - ipython_genutils >=0.2.0,<0.3.0 + - jupyterlab_widgets >=1.0.0,<3 + - python >=3.3 - traitlets >=4.3.1 - - widgetsnbextension >=4.0.14,<4.1.0 + - widgetsnbextension >=3.6.10,<3.7.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/ipywidgets?source=hash-mapping - size: 114376 - timestamp: 1762040524661 + size: 104860 + timestamp: 1729599554932 - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda sha256: 08e838d29c134a7684bca0468401d26840f41c92267c4126d7b43a6b533b0aed md5: 0b0154421989637d424ccf0f104be51a @@ -7077,6 +9007,17 @@ packages: - pkg:pypi/isoduration?source=hash-mapping size: 19832 timestamp: 1733493720346 +- conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda + sha256: 1684b7b16eec08efef5302ce298c606b163c18272b69a62b666fbaa61516f170 + md5: 7ac5f795c15f288984e32add616cdc59 + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/itsdangerous?source=hash-mapping + size: 19180 + timestamp: 1733308353037 - conda: https://conda.anaconda.org/conda-forge/noarch/jax-0.9.0-pyhd8ed1ab_0.conda sha256: 35935c2883ce138f2f8ae87cd6a30723838a8b7b54f5be71d6698399f2c61941 md5: eb556c579bf757f95f65f01146d99e92 @@ -7543,20 +9484,19 @@ packages: - pkg:pypi/jupyterlab-server?source=hash-mapping size: 51621 timestamp: 1761145478692 -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-3.0.16-pyhcf101f3_1.conda - sha256: 5c03de243d7ae6247f39a402f4785d95e61c3be79ef18738e8f17155585d31a8 - md5: dbf8b81974504fa51d34e436ca7ef389 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-1.1.11-pyhd8ed1ab_0.conda + sha256: 639544e96969c7513b33bf3201a4dc3095625e34cff16c187f5dec9bee2dfb2f + md5: 05a08b368343304618b6a88425aa851a depends: - - python >=3.10 - - python + - python >=3.7 constrains: - jupyterlab >=3,<5 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jupyterlab-widgets?source=hash-mapping - size: 216779 - timestamp: 1762267481404 + size: 113654 + timestamp: 1729586559116 - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 md5: b38117a3c920364aff79f870c984b4a3 @@ -7793,6 +9733,338 @@ packages: purls: [] size: 1229639 timestamp: 1770863511331 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-24.0.0-h8ff9baf_5_cpu.conda + build_number: 5 + sha256: 0720ac20811d24386ae49f12818955a4f8bf8614248eaf8710661d113e69dad0 + md5: c53e71fb57a7bc476d9d39b3b20ff01f + depends: + - __glibc >=2.17,<3.0.a0 + - aws-crt-cpp >=0.40.0,<0.40.1.0a0 + - aws-sdk-cpp >=1.11.747,<1.11.748.0a0 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - azure-identity-cpp >=1.13.3,<1.13.4.0a0 + - azure-storage-blobs-cpp >=12.17.0,<12.17.1.0a0 + - azure-storage-files-datalake-cpp >=12.15.0,<12.15.1.0a0 + - bzip2 >=1.0.8,<2.0a0 + - glog >=0.7.1,<0.8.0a0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libgcc >=14 + - libgoogle-cloud >=3.5.0,<3.6.0a0 + - libgoogle-cloud-storage >=3.5.0,<3.6.0a0 + - libopentelemetry-cpp >=1.27.0,<1.28.0a0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - libstdcxx >=14 + - libzlib >=1.3.2,<2.0a0 + - lz4-c >=1.10.0,<1.11.0a0 + - orc >=2.3.0,<2.3.1.0a0 + - snappy >=1.2.2,<1.3.0a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - apache-arrow-proc =*=cpu + - parquet-cpp <0.0a0 + - arrow-cpp <0.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 6502448 + timestamp: 1781069558661 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-24.0.0-h9e06b3e_5_cpu.conda + build_number: 5 + sha256: 1a1f6f149ef2f6dfcabbdef6f91497304f506bbf228e939cd3cc3b0db635fb48 + md5: 379fbe62b5aec5d09d8a3a6390d405da + depends: + - __osx >=11.0 + - aws-crt-cpp >=0.40.0,<0.40.1.0a0 + - aws-sdk-cpp >=1.11.747,<1.11.748.0a0 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - azure-identity-cpp >=1.13.3,<1.13.4.0a0 + - azure-storage-blobs-cpp >=12.17.0,<12.17.1.0a0 + - azure-storage-files-datalake-cpp >=12.15.0,<12.15.1.0a0 + - bzip2 >=1.0.8,<2.0a0 + - glog >=0.7.1,<0.8.0a0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libcxx >=21 + - libgoogle-cloud >=3.5.0,<3.6.0a0 + - libgoogle-cloud-storage >=3.5.0,<3.6.0a0 + - libopentelemetry-cpp >=1.27.0,<1.28.0a0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - lz4-c >=1.10.0,<1.11.0a0 + - orc >=2.3.0,<2.3.1.0a0 + - snappy >=1.2.2,<1.3.0a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - parquet-cpp <0.0a0 + - arrow-cpp <0.0a0 + - apache-arrow-proc =*=cpu + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 4379910 + timestamp: 1781071412907 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-24.0.0-h91214ac_5_cpu.conda + build_number: 5 + sha256: 4385e30de42c00b1b9af19c8739cdbd071db681efa5565834d582da1dfdf6b9f + md5: 966e0004af993d89ab1c3419907cd121 + depends: + - __osx >=11.0 + - aws-crt-cpp >=0.40.0,<0.40.1.0a0 + - aws-sdk-cpp >=1.11.747,<1.11.748.0a0 + - azure-core-cpp >=1.16.2,<1.16.3.0a0 + - azure-identity-cpp >=1.13.3,<1.13.4.0a0 + - azure-storage-blobs-cpp >=12.17.0,<12.17.1.0a0 + - azure-storage-files-datalake-cpp >=12.15.0,<12.15.1.0a0 + - bzip2 >=1.0.8,<2.0a0 + - glog >=0.7.1,<0.8.0a0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libcxx >=21 + - libgoogle-cloud >=3.5.0,<3.6.0a0 + - libgoogle-cloud-storage >=3.5.0,<3.6.0a0 + - libopentelemetry-cpp >=1.27.0,<1.28.0a0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - lz4-c >=1.10.0,<1.11.0a0 + - orc >=2.3.0,<2.3.1.0a0 + - snappy >=1.2.2,<1.3.0a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - arrow-cpp <0.0a0 + - apache-arrow-proc =*=cpu + - parquet-cpp <0.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 4243237 + timestamp: 1781071364885 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-acero-24.0.0-h635bf11_5_cpu.conda + build_number: 5 + sha256: 4a1fd8e83ad082e272b141a004126a32b5224a5db5fd644c49a298e4897790e7 + md5: dc27f196e5195d49b05b85a085c93cbe + depends: + - __glibc >=2.17,<3.0.a0 + - libarrow 24.0.0 h8ff9baf_5_cpu + - libarrow-compute 24.0.0 h53684a4_5_cpu + - libgcc >=14 + - libstdcxx >=14 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 591772 + timestamp: 1781069800881 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-24.0.0-h91633f5_5_cpu.conda + build_number: 5 + sha256: 8d8aabe8eb2bda6731659bbe5a4943e8eaf36834df27a846bc428271d3e53ad2 + md5: 979ccf6d3b2c82e4955afc972aa03660 + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libarrow 24.0.0 h9e06b3e_5_cpu + - libarrow-compute 24.0.0 hb38465b_5_cpu + - libcxx >=21 + - libopentelemetry-cpp >=1.27.0,<1.28.0a0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 543993 + timestamp: 1781072348441 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-acero-24.0.0-ha4f4840_5_cpu.conda + build_number: 5 + sha256: f27843d66a5bb27616746a1aaf62b71887b01251b09bc1f8794fc5ef298fda66 + md5: 80ca2ca7d2d34e25fc7397610ebef405 + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libarrow 24.0.0 h91214ac_5_cpu + - libarrow-compute 24.0.0 h8d10c55_5_cpu + - libcxx >=21 + - libopentelemetry-cpp >=1.27.0,<1.28.0a0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 519823 + timestamp: 1781072090303 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-compute-24.0.0-h53684a4_5_cpu.conda + build_number: 5 + sha256: 0649d1cee07d5a357cb43886bc8a11d8e128ebf5e28bdebe1f9c52f46ba417a6 + md5: 1715725b98c02d522654e46ad4995711 + depends: + - __glibc >=2.17,<3.0.a0 + - libarrow 24.0.0 h8ff9baf_5_cpu + - libgcc >=14 + - libre2-11 >=2025.11.5 + - libstdcxx >=14 + - libutf8proc >=2.11.3,<2.12.0a0 + - re2 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 2990989 + timestamp: 1781069683178 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-compute-24.0.0-hb38465b_5_cpu.conda + build_number: 5 + sha256: 2b88a48288f7e0646dee7804eef37026ecd1040102d4008034f5ef141afa7d7f + md5: 3e72d9888a970f0f62663ff371e94c40 + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libarrow 24.0.0 h9e06b3e_5_cpu + - libcxx >=21 + - libopentelemetry-cpp >=1.27.0,<1.28.0a0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - libre2-11 >=2025.11.5 + - libutf8proc >=2.11.3,<2.12.0a0 + - re2 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 2386508 + timestamp: 1781071790833 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-compute-24.0.0-h8d10c55_5_cpu.conda + build_number: 5 + sha256: c72e24ae9ac552db7282cb9c3be0802efdfd244e1fcbf79bf6b81aa7eeab1d55 + md5: a1c861ce771d8706e3ac7c56786556ca + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libarrow 24.0.0 h91214ac_5_cpu + - libcxx >=21 + - libopentelemetry-cpp >=1.27.0,<1.28.0a0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - libre2-11 >=2025.11.5 + - libutf8proc >=2.11.3,<2.12.0a0 + - re2 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 2240777 + timestamp: 1781071586006 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-dataset-24.0.0-h635bf11_5_cpu.conda + build_number: 5 + sha256: 808e63b6321a6fba8f6a8abf2d9e15a6463b850b2f963004f99114df789c2ad8 + md5: 57ced4ba426e4d34da4ce4b3c8154f06 + depends: + - __glibc >=2.17,<3.0.a0 + - libarrow 24.0.0 h8ff9baf_5_cpu + - libarrow-acero 24.0.0 h635bf11_5_cpu + - libarrow-compute 24.0.0 h53684a4_5_cpu + - libgcc >=14 + - libparquet 24.0.0 h7376487_5_cpu + - libstdcxx >=14 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 592166 + timestamp: 1781069880155 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-24.0.0-h91633f5_5_cpu.conda + build_number: 5 + sha256: 1c63b0aabc202738ea8ac16006bc699a7d02da8064a017486bb4245cf6e20417 + md5: bf30bcab956adac1b10f9c8abd3b7d8b + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libarrow 24.0.0 h9e06b3e_5_cpu + - libarrow-acero 24.0.0 h91633f5_5_cpu + - libarrow-compute 24.0.0 hb38465b_5_cpu + - libcxx >=21 + - libopentelemetry-cpp >=1.27.0,<1.28.0a0 + - libparquet 24.0.0 h0f82bca_5_cpu + - libprotobuf >=6.33.5,<6.33.6.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 534330 + timestamp: 1781072712273 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-dataset-24.0.0-ha4f4840_5_cpu.conda + build_number: 5 + sha256: 91f710702c3d0c5b1a42dd03fb73e3a6304be6002e5f13ee8bdf3e7104edaf5e + md5: 899673e361a9426cdee5da86cda0cbed + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libarrow 24.0.0 h91214ac_5_cpu + - libarrow-acero 24.0.0 ha4f4840_5_cpu + - libarrow-compute 24.0.0 h8d10c55_5_cpu + - libcxx >=21 + - libopentelemetry-cpp >=1.27.0,<1.28.0a0 + - libparquet 24.0.0 h840b369_5_cpu + - libprotobuf >=6.33.5,<6.33.6.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 518863 + timestamp: 1781072345132 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-substrait-24.0.0-hb4dd7c2_5_cpu.conda + build_number: 5 + sha256: 25fe77e28b0e0cb1f11052e09527854a51aa214e94c8ab9c900a221d27e3c139 + md5: 712928bbdab0db3daa909d880a467565 + depends: + - __glibc >=2.17,<3.0.a0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libarrow 24.0.0 h8ff9baf_5_cpu + - libarrow-acero 24.0.0 h635bf11_5_cpu + - libarrow-dataset 24.0.0 h635bf11_5_cpu + - libgcc >=14 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - libstdcxx >=14 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 501578 + timestamp: 1781069908655 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-24.0.0-h613493e_5_cpu.conda + build_number: 5 + sha256: 8d88c6e43e256d8bbaca3d1f54b925cf2f71d960d68d834b534a14da0254c93e + md5: 97822771bac27cdbcbbd440b7df21fab + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libarrow 24.0.0 h9e06b3e_5_cpu + - libarrow-acero 24.0.0 h91633f5_5_cpu + - libarrow-dataset 24.0.0 h91633f5_5_cpu + - libcxx >=21 + - libprotobuf >=6.33.5,<6.33.6.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 448698 + timestamp: 1781072796877 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-substrait-24.0.0-h05be00f_5_cpu.conda + build_number: 5 + sha256: acc4750d71c4551b627386ee421407a3dc84440070651949e9e88bba130856b6 + md5: 2168b56c5615b338e6ce5787e223d333 + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libarrow 24.0.0 h91214ac_5_cpu + - libarrow-acero 24.0.0 ha4f4840_5_cpu + - libarrow-dataset 24.0.0 ha4f4840_5_cpu + - libcxx >=21 + - libprotobuf >=6.33.5,<6.33.6.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 454306 + timestamp: 1781072440866 - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda build_number: 7 sha256: 081c850f99bc355821fac9c6e3727d40b3f8ce3beb50a5437cf03726b611ff39 @@ -8004,6 +10276,37 @@ packages: purls: [] size: 12827971 timestamp: 1778479852868 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 + sha256: fd1d153962764433fe6233f34a72cdeed5dcf8a883a85769e8295ce940b5b0c5 + md5: c965a5aa0d5c1c37ffc62dff36e28400 + depends: + - libgcc-ng >=9.4.0 + - libstdcxx-ng >=9.4.0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 20440 + timestamp: 1633683576494 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 + sha256: 3043869ac1ee84554f177695e92f2f3c2c507b260edad38a0bf3981fce1632ff + md5: 23d6d5a69918a438355d7cbc4c3d54c9 + depends: + - libcxx >=11.1.0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 20128 + timestamp: 1633683906221 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 + sha256: 58477b67cc719060b5b069ba57161e20ba69b8695d154a719cb4b60caf577929 + md5: 32bd82a6a625ea6ce090a81c3d34edeb + depends: + - libcxx >=11.1.0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18765 + timestamp: 1633683992603 - conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda sha256: 205c4f19550f3647832ec44e35e6d93c8c206782bdd620c1d7cf66237580ff9c md5: 49c553b47ff679a6a1e9fc80b9c5a2d4 @@ -8018,6 +10321,55 @@ packages: purls: [] size: 4518030 timestamp: 1770902209173 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.20.0-hcf29cc6_0.conda + sha256: 75963a5dd913311f59a35dbd307592f4fa754c4808aff9c33edb430c415e38eb + md5: c3cc2864f82a944bc90a7beb4d3b0e88 + depends: + - __glibc >=2.17,<3.0.a0 + - krb5 >=1.22.2,<1.23.0a0 + - libgcc >=14 + - libnghttp2 >=1.68.1,<2.0a0 + - libssh2 >=1.11.1,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.6,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: curl + license_family: MIT + purls: [] + size: 468706 + timestamp: 1777461492876 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.20.0-h8f0b9e4_0.conda + sha256: 5d3d8a82ca43347e96f1d79048921f3a7c25e32514bc7feb53ed2a040dcca54d + md5: 4a0085ccf90dc514f0fc0909a874045e + depends: + - __osx >=11.0 + - krb5 >=1.22.2,<1.23.0a0 + - libnghttp2 >=1.68.1,<2.0a0 + - libssh2 >=1.11.1,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.6,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: curl + license_family: MIT + purls: [] + size: 419676 + timestamp: 1777462238769 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.20.0-hd5a2499_0.conda + sha256: 38c0bc634b61e542776e97cfd15d5d41edd304d4e47c333004d2d622439b2381 + md5: 2f57b7d0c6adda88957586b7afd78438 + depends: + - __osx >=11.0 + - krb5 >=1.22.2,<1.23.0a0 + - libnghttp2 >=1.68.1,<2.0a0 + - libssh2 >=1.11.1,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.6,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: curl + license_family: MIT + purls: [] + size: 400568 + timestamp: 1777462251987 - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.5-h19cb2f5_1.conda sha256: 8f3d495df4427d9285ae25a51d32123ca251c32abebcef020fddb8ac1f200894 md5: 56fa8b3e43d26c97da88aea4e958f616 @@ -8126,20 +10478,77 @@ packages: - libglvnd 1.7.0 ha4b6fd6_2 license: LicenseRef-libglvnd purls: [] - size: 44840 - timestamp: 1731330973553 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_2.conda - sha256: f6e7095260305dc05238062142fb8db4b940346329b5b54894a90610afa6749f - md5: b513eb83b3137eca1192c34bf4f013a7 + size: 44840 + timestamp: 1731330973553 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_2.conda + sha256: f6e7095260305dc05238062142fb8db4b940346329b5b54894a90610afa6749f + md5: b513eb83b3137eca1192c34bf4f013a7 + depends: + - __glibc >=2.17,<3.0.a0 + - libegl 1.7.0 ha4b6fd6_2 + - libgl-devel 1.7.0 ha4b6fd6_2 + - xorg-libx11 + license: LicenseRef-libglvnd + purls: [] + size: 30380 + timestamp: 1731331017249 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + sha256: 1cd6048169fa0395af74ed5d8f1716e22c19a81a8a36f934c110ca3ad4dd27b4 + md5: 172bf1cd1ff8629f2b1179945ed45055 + depends: + - libgcc-ng >=12 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 112766 + timestamp: 1702146165126 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + sha256: 0d238488564a7992942aa165ff994eca540f687753b4f0998b29b4e4d030ff43 + md5: 899db79329439820b7e8f8de41bca902 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 106663 + timestamp: 1702146352558 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + sha256: 95cecb3902fbe0399c3a7e67a5bed1db813e5ab0e22f4023a5e0f722f2cc214f + md5: 36d33e440c31857372a72137f78bacf5 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 107458 + timestamp: 1702146414478 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda + sha256: 2e14399d81fb348e9d231a82ca4d816bf855206923759b69ad006ba482764131 + md5: a1cfcc585f0c42bf8d5546bb1dfb668d + depends: + - libgcc-ng >=12 + - openssl >=3.1.1,<4.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 427426 + timestamp: 1685725977222 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda + sha256: e0bd9af2a29f8dd74309c0ae4f17a7c2b8c4b89f875ff1d6540c941eefbd07fb + md5: e38e467e577bd193a7d5de7c2c540b04 + depends: + - openssl >=3.1.1,<4.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 372661 + timestamp: 1685726378869 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda + sha256: 8c136d7586259bb5c0d2b913aaadc5b9737787ae4f40e3ad1beaf96c80b919b7 + md5: 1a109764bff3bdc7bdd84088347d71dc depends: - - __glibc >=2.17,<3.0.a0 - - libegl 1.7.0 ha4b6fd6_2 - - libgl-devel 1.7.0 ha4b6fd6_2 - - xorg-libx11 - license: LicenseRef-libglvnd + - openssl >=3.1.1,<4.0a0 + license: BSD-3-Clause + license_family: BSD purls: [] - size: 30380 - timestamp: 1731331017249 + size: 368167 + timestamp: 1685726248899 - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.0-hecca717_0.conda sha256: ea33c40977ea7a2c3658c522230058395bc2ee0d89d99f0711390b6a1ee80d12 md5: a3b390520c563d78cc58974de95a03e5 @@ -8624,6 +11033,119 @@ packages: purls: [] size: 603817 timestamp: 1778268942614 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-3.5.0-h8d2ee43_1.conda + sha256: 42c8ca362013d0378ba58afb61940d23c94e0f7127004190dcd12fe4a3072953 + md5: 8ae0593085ca8148fdbf0bc8f62e79c1 + depends: + - __glibc >=2.17,<3.0.a0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libcurl >=8.20.0,<9.0a0 + - libgcc >=14 + - libgrpc >=1.78.1,<1.79.0a0 + - libopentelemetry-cpp >=1.27.0,<1.28.0a0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - libstdcxx >=14 + - openssl >=3.5.6,<4.0a0 + constrains: + - libgoogle-cloud 3.5.0 *_1 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 2647694 + timestamp: 1780029060448 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-3.5.0-h8b848e0_1.conda + sha256: f6f23551b2f4b9c9b3e0c72398e4995702e832ee03b717e4d9802ce695f6938a + md5: 323f0d14ccec33e69a6c16a11f3ec7c1 + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libcurl >=8.20.0,<9.0a0 + - libcxx >=19 + - libgrpc >=1.78.1,<1.79.0a0 + - libopentelemetry-cpp >=1.27.0,<1.28.0a0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - openssl >=3.5.6,<4.0a0 + constrains: + - libgoogle-cloud 3.5.0 *_1 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 1882201 + timestamp: 1780030929238 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-3.5.0-h688a705_1.conda + sha256: 20235ded7b8d125461a9ed5e02f174eae89e85a271d3343167015f779ebc4714 + md5: 3899a5a69da373a85e7f53be3d32b814 + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libcurl >=8.20.0,<9.0a0 + - libcxx >=19 + - libgrpc >=1.78.1,<1.79.0a0 + - libopentelemetry-cpp >=1.27.0,<1.28.0a0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - openssl >=3.5.6,<4.0a0 + constrains: + - libgoogle-cloud 3.5.0 *_1 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 1812401 + timestamp: 1780031033935 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-3.5.0-hdbdcf42_1.conda + sha256: 6914f9b0f2d5bb0c5687b880c6c352a2333449d03ce80e6826230675062b57f1 + md5: 6f79d5f72cfcdd3509112233a8aedc2e + depends: + - __glibc >=2.17,<3.0.a0 + - libabseil + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl + - libgcc >=14 + - libgoogle-cloud 3.5.0 h8d2ee43_1 + - libstdcxx >=14 + - libzlib >=1.3.2,<2.0a0 + - openssl + license: Apache-2.0 + license_family: Apache + purls: [] + size: 779116 + timestamp: 1780029183339 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-3.5.0-hea209c6_1.conda + sha256: 086374067de8b3fd6198f87f8a7879d5042e35a7816e2a570155a3590e480a0d + md5: 8c84b06d18a3c83c28eb89bca378daad + depends: + - __osx >=11.0 + - libabseil + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl + - libcxx >=19 + - libgoogle-cloud 3.5.0 h8b848e0_1 + - libzlib >=1.3.2,<2.0a0 + - openssl + license: Apache-2.0 + license_family: Apache + purls: [] + size: 541328 + timestamp: 1780031289207 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-storage-3.5.0-ha114238_1.conda + sha256: 40b7074e3837fe3dcebef0e93f1f40fb995abd94787e51d231d31142e157dadd + md5: ecc3983f92594b3863a7e5d47d1a71ba + depends: + - __osx >=11.0 + - libabseil + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl + - libcxx >=19 + - libgoogle-cloud 3.5.0 h688a705_1 + - libzlib >=1.3.2,<2.0a0 + - openssl + license: Apache-2.0 + license_family: Apache + purls: [] + size: 527597 + timestamp: 1780031485452 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.78.1-h1d1128b_0.conda sha256: 5bb935188999fd70f67996746fd2dca85ec6204289e11695c316772e19451eb8 md5: b5fb6d6c83f63d83ef2721dca6ff7091 @@ -8865,6 +11387,55 @@ packages: purls: [] size: 92472 timestamp: 1775825802659 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda + sha256: 663444d77a42f2265f54fb8b48c5450bfff4388d9c0f8253dd7855f0d993153f + md5: 2a45e7f8af083626f009645a6481f12d + depends: + - __glibc >=2.17,<3.0.a0 + - c-ares >=1.34.6,<2.0a0 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libgcc >=14 + - libstdcxx >=14 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 663344 + timestamp: 1773854035739 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h70048d4_0.conda + sha256: 899551e16aac9dfb85bfc2fd98b655f4d1b7fea45720ec04ccb93d95b4d24798 + md5: dba4c95e2fe24adcae4b77ebf33559ae + depends: + - __osx >=11.0 + - c-ares >=1.34.6,<2.0a0 + - libcxx >=19 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 606749 + timestamp: 1773854765508 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda + sha256: 2bc7bc3978066f2c274ebcbf711850cc9ab92e023e433b9631958a098d11e10a + md5: 6ea18834adbc3b33df9bd9fb45eaf95b + depends: + - __osx >=11.0 + - c-ares >=1.34.6,<2.0a0 + - libcxx >=19 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 576526 + timestamp: 1773854624224 - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 md5: d864d34357c3b65a4b731f78c0801dc4 @@ -8941,6 +11512,144 @@ packages: purls: [] size: 50757 timestamp: 1731330993524 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopentelemetry-cpp-1.27.0-h9692893_0.conda + sha256: 247b99f5dd32363d7231c9c5a6ad113e0b58ad3e85d68227999b5933d5005a6d + md5: 2a44700a9857b49a3fe72aca643d0921 + depends: + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libcurl >=8.20.0,<9.0a0 + - libgrpc >=1.78.1,<1.79.0a0 + - libopentelemetry-cpp-headers 1.27.0 ha770c72_0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - nlohmann_json + - prometheus-cpp >=1.3.0,<1.4.0a0 + constrains: + - cpp-opentelemetry-sdk =1.27.0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 943253 + timestamp: 1778721388532 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libopentelemetry-cpp-1.27.0-h7a0a166_0.conda + sha256: 5ba2acb247c3f967c72391a912bcb4fd697de27c3e5033c6e5fa83797a4d14f2 + md5: 2b6d466bf0d5c0fba290e168eae7ac4a + depends: + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libcurl >=8.20.0,<9.0a0 + - libgrpc >=1.78.1,<1.79.0a0 + - libopentelemetry-cpp-headers 1.27.0 h694c41f_0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - nlohmann_json + - prometheus-cpp >=1.3.0,<1.4.0a0 + constrains: + - cpp-opentelemetry-sdk =1.27.0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 604491 + timestamp: 1778721948053 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopentelemetry-cpp-1.27.0-h08d5cc3_0.conda + sha256: db60a4d6eb5be208f8a0be686909b1f10635b3913a7c1ce391d4d26d991115c3 + md5: 35e93c8c0edb8dff7f9ebeb55ec4e6a6 + depends: + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libcurl >=8.20.0,<9.0a0 + - libgrpc >=1.78.1,<1.79.0a0 + - libopentelemetry-cpp-headers 1.27.0 hce30654_0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - nlohmann_json + - prometheus-cpp >=1.3.0,<1.4.0a0 + constrains: + - cpp-opentelemetry-sdk =1.27.0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 582427 + timestamp: 1778721505645 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopentelemetry-cpp-headers-1.27.0-ha770c72_0.conda + sha256: 4a55bd84d166395a117592bb6139cf645eb402416987b856b41f96ba7b9d15d6 + md5: f8dcb0cff8f84f428bf76f1169bf50a7 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 392177 + timestamp: 1778721367721 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libopentelemetry-cpp-headers-1.27.0-h694c41f_0.conda + sha256: 887e0e2f9864b3a4f2565222a07d2d6544ce16f62b2a5637211d2e022dcdf777 + md5: 56d102b4190f3170dad25651544e6263 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 393506 + timestamp: 1778721872019 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopentelemetry-cpp-headers-1.27.0-hce30654_0.conda + sha256: 64724bf5c5c48ecbc92a7d561654c6305d6dc819e0773c8989877f0613e52542 + md5: f8039fbb88b31890de23c8a16ae03d92 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 394303 + timestamp: 1778721455052 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libparquet-24.0.0-h7376487_5_cpu.conda + build_number: 5 + sha256: 0c627751bfc2e3fd35ada8a54e3c5b9f906a3dc0b9a1c02d9a9a488303babd8b + md5: e5b85d3c6fac8b8b713a93aedce28364 + depends: + - __glibc >=2.17,<3.0.a0 + - libarrow 24.0.0 h8ff9baf_5_cpu + - libgcc >=14 + - libstdcxx >=14 + - libthrift >=0.22.0,<0.22.1.0a0 + - openssl >=3.5.6,<4.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 1428207 + timestamp: 1781069771394 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libparquet-24.0.0-h0f82bca_5_cpu.conda + build_number: 5 + sha256: 8c97c80b54074117d3cb2e8de32167fab7f1f14fc430f60680c9fa3168a176c0 + md5: d53c4977b9e32579267ef6d47809a926 + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libarrow 24.0.0 h9e06b3e_5_cpu + - libcxx >=21 + - libopentelemetry-cpp >=1.27.0,<1.28.0a0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - libthrift >=0.22.0,<0.22.1.0a0 + - openssl >=3.5.6,<4.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 1120282 + timestamp: 1781072235499 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libparquet-24.0.0-h840b369_5_cpu.conda + build_number: 5 + sha256: e5337f70681a6d8aea93b36d8ef27958a04840eb83f7aa2bc7ab823ccbecde2c + md5: 3a10960f0a306683037cb93533e18604 + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libarrow 24.0.0 h91214ac_5_cpu + - libcxx >=21 + - libopentelemetry-cpp >=1.27.0,<1.28.0a0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - libthrift >=0.22.0,<0.22.1.0a0 + - openssl >=3.5.6,<4.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 1097984 + timestamp: 1781072012333 - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.19-hb03c661_0.conda sha256: f41721636a7c2e51bc2c642e1127955ab9c81145470714fdaac44d4d09e4af41 md5: 33082e13b4769b48cfeb648e15bfe3fc @@ -9263,6 +11972,49 @@ packages: purls: [] size: 27776 timestamp: 1778269074600 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.22.0-h7d032f7_2.conda + sha256: af6025aa4a4fc3f4e71334000d2739d927e2f678607b109ec630cc17d716918a + md5: b6e326fbe1e3948da50ec29cee0380db + depends: + - __glibc >=2.17,<3.0.a0 + - libevent >=2.1.12,<2.1.13.0a0 + - libgcc >=14 + - libstdcxx >=14 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.6,<4.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 423861 + timestamp: 1777018957474 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libthrift-0.22.0-hebea4ca_2.conda + sha256: 89a20cb35e0f32d59a7080c934a56120591cb962d4fab1cba3a795a094bc8256 + md5: 36d5479e1b5967c2eb9824b953317e41 + depends: + - __osx >=11.0 + - libcxx >=19 + - libevent >=2.1.12,<2.1.13.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.6,<4.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 332270 + timestamp: 1777019812419 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libthrift-0.22.0-h1fb9c8a_2.conda + sha256: 568bb23db02b050c3903bec05edbcab84960c8c7e5a1710dac3109df997ac7f1 + md5: d006875f9a58a44f92aec9a7ebeb7150 + depends: + - __osx >=11.0 + - libcxx >=19 + - libevent >=2.1.12,<2.1.13.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.6,<4.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 323017 + timestamp: 1777019893083 - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda sha256: e5f8c38625aa6d567809733ae04bb71c161a42e44a9fa8227abe61fa5c60ebe0 md5: cd5a90476766d53e901500df9215e927 @@ -9315,6 +12067,37 @@ packages: purls: [] size: 373892 timestamp: 1762022345545 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.11.3-hfe17d71_0.conda + sha256: ecbf4b7520296ed580498dc66a72508b8a79da5126e1d6dc650a7087171288f9 + md5: 1247168fe4a0b8912e3336bccdbf98a5 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 85969 + timestamp: 1768735071295 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libutf8proc-2.11.3-hc282952_0.conda + sha256: 626db214208e8da6aa9a904518a0442e5bff7b4602cc295dd5ce1f4a98844c1d + md5: 2c49b6f6ec9a510bbb75ecbd2a572697 + depends: + - __osx >=10.13 + license: MIT + license_family: MIT + purls: [] + size: 84535 + timestamp: 1768735249136 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libutf8proc-2.11.3-h2431656_0.conda + sha256: ae1a82e62cd4e3c18e005ae7ff4358ed72b2bfbfe990d5a6a5587f81e9a100dc + md5: 2255add2f6ae77d0a96624a5cbde6d45 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 87916 + timestamp: 1768735311947 - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda sha256: bc1b08c92626c91500fd9f26f2c797f3eb153b627d53e9c13cd167f1e12b2829 md5: 38ffe67b78c9d4de527be8315e5ada2c @@ -9754,6 +12537,40 @@ packages: - pkg:pypi/lxml?source=hash-mapping size: 1349054 timestamp: 1776512963897 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda + sha256: 47326f811392a5fd3055f0f773036c392d26fdb32e4d8e7a8197eed951489346 + md5: 9de5350a85c4a20c685259b889aa6393 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libstdcxx >=13 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 167055 + timestamp: 1733741040117 +- conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda + sha256: 8da3c9d4b596e481750440c0250a7e18521e7f69a47e1c8415d568c847c08a1c + md5: d6b9bd7e356abd7e3a633d59b753495a + depends: + - __osx >=10.13 + - libcxx >=18 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 159500 + timestamp: 1733741074747 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda + sha256: 94d3e2a485dab8bdfdd4837880bde3dd0d701e2b97d6134b8806b7c8e69c8652 + md5: 01511afc6cc1909c5303cf31be17b44f + depends: + - __osx >=11.0 + - libcxx >=18 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 148824 + timestamp: 1733741047892 - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.12-pyhcf101f3_0.conda sha256: d06d02574be3892020262464b49360a749c1d448ed9f0de52fe8a08bc1483261 md5: a73036dabdd6dfe9679ed893baa8b230 @@ -10369,6 +13186,36 @@ packages: - pkg:pypi/networkx?source=hash-mapping size: 1587439 timestamp: 1765215107045 +- conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda + sha256: fd2cbd8dfc006c72f45843672664a8e4b99b2f8137654eaae8c3d46dca776f63 + md5: 16c2a0e9c4a166e53632cfca4f68d020 + constrains: + - nlohmann_json-abi ==3.12.0 + license: MIT + license_family: MIT + purls: [] + size: 136216 + timestamp: 1758194284857 +- conda: https://conda.anaconda.org/conda-forge/osx-64/nlohmann_json-3.12.0-h06076ce_1.conda + sha256: 8e1b8ac88e07da2910c72466a94d1fc77aa13c722f8ddbc7ae3beb7c19b41fc7 + md5: 97d7a1cda5546cb0bbdefa3777cb9897 + constrains: + - nlohmann_json-abi ==3.12.0 + license: MIT + license_family: MIT + purls: [] + size: 137081 + timestamp: 1768670842725 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda + sha256: 1945fd5b64b74ef3d57926156fb0bfe88ee637c49f3273067f7231b224f1d26d + md5: 755cfa6c08ed7b7acbee20ccbf15a47c + constrains: + - nlohmann_json-abi ==3.12.0 + license: MIT + license_family: MIT + purls: [] + size: 137595 + timestamp: 1768670878127 - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-7.5.7-pyhcf101f3_1.conda sha256: f4974b9984376f75fe8cabab06b25e23addaa7d962e8a713da3f4a213ded8c7b md5: 92b46e8c96039d3d7c4958f426bca753 @@ -10770,15 +13617,73 @@ packages: sha256: 90afae35aede3e3d779976ca9baa7af192bd21e9365ba51b1962933796f49b79 md5: 1ccdb985da56ab7f200856642163bf3a depends: - - bottle >=0.13.0 - - optuna >=3.6.0 - - python >=3.10 - license: MIT - license_family: MIT - purls: - - pkg:pypi/optuna-dashboard?source=hash-mapping - size: 6659356 - timestamp: 1762756075150 + - bottle >=0.13.0 + - optuna >=3.6.0 + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/optuna-dashboard?source=hash-mapping + size: 6659356 + timestamp: 1762756075150 +- conda: https://conda.anaconda.org/conda-forge/linux-64/orc-2.3.0-h21090e2_0.conda + sha256: a60c2578c8422e0c67206d269767feb4d3e627511558b6866e5daf2231d5214d + md5: 8027fce94fdfdf2e54f9d18cbae496df + depends: + - tzdata + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - lz4-c >=1.10.0,<1.11.0a0 + - snappy >=1.2.2,<1.3.0a0 + - libabseil >=20260107.1,<20260108.0a0 + - libabseil * cxx17* + - libprotobuf >=6.33.5,<6.33.6.0a0 + - zstd >=1.5.7,<1.6.0a0 + - libzlib >=1.3.1,<2.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 1468651 + timestamp: 1773230208923 +- conda: https://conda.anaconda.org/conda-forge/osx-64/orc-2.3.0-hb9b210e_0.conda + sha256: c4872822be78b2503bba06b906604c87000e3a63c7b7b8cb459463d46c55814b + md5: 292d30447800bc51a0d3e0e9738f5730 + depends: + - tzdata + - libcxx >=19 + - __osx >=11.0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - libzlib >=1.3.1,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + - snappy >=1.2.2,<1.3.0a0 + - lz4-c >=1.10.0,<1.11.0a0 + - libabseil >=20260107.1,<20260108.0a0 + - libabseil * cxx17* + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 594601 + timestamp: 1773230256637 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-2.3.0-hd11884d_0.conda + sha256: 8594f064828cca9b8d625e2ebe79436fd4ffc030c950573380c54a8f4329f955 + md5: 77bfe521901c1a247cc66c1276826a85 + depends: + - tzdata + - libcxx >=19 + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libzlib >=1.3.1,<2.0a0 + - snappy >=1.2.2,<1.3.0a0 + - libprotobuf >=6.33.5,<6.33.6.0a0 + - libabseil >=20260107.1,<20260108.0a0 + - libabseil * cxx17* + - lz4-c >=1.10.0,<1.11.0a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 548180 + timestamp: 1773230270828 - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda sha256: 1840bd90d25d4930d60f57b4f38d4e0ae3f5b8db2819638709c36098c6ba770c md5: e51f1e4089cad105b6cac64bd8166587 @@ -11323,6 +14228,49 @@ packages: - pkg:pypi/ppft?source=hash-mapping size: 35537 timestamp: 1769007436649 +- conda: https://conda.anaconda.org/conda-forge/linux-64/prometheus-cpp-1.3.0-ha5d0236_0.conda + sha256: 013669433eb447548f21c3c6b16b2ed64356f726b5f77c1b39d5ba17a8a4b8bc + md5: a83f6a2fdc079e643237887a37460668 + depends: + - __glibc >=2.17,<3.0.a0 + - libcurl >=8.10.1,<9.0a0 + - libgcc >=13 + - libstdcxx >=13 + - libzlib >=1.3.1,<2.0a0 + - zlib + license: MIT + license_family: MIT + purls: [] + size: 199544 + timestamp: 1730769112346 +- conda: https://conda.anaconda.org/conda-forge/osx-64/prometheus-cpp-1.3.0-h7802330_0.conda + sha256: af754a477ee2681cb7d5d77c621bd590d25fe1caf16741841fc2d176815fc7de + md5: f36107fa2557e63421a46676371c4226 + depends: + - __osx >=10.13 + - libcurl >=8.10.1,<9.0a0 + - libcxx >=18 + - libzlib >=1.3.1,<2.0a0 + - zlib + license: MIT + license_family: MIT + purls: [] + size: 179103 + timestamp: 1730769223221 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/prometheus-cpp-1.3.0-h0967b3e_0.conda + sha256: 851a77ae1a8e90db9b9f3c4466abea7afb52713c3d98ceb0d37ba6ff27df2eff + md5: 7172339b49c94275ba42fec3eaeda34f + depends: + - __osx >=11.0 + - libcurl >=8.10.1,<9.0a0 + - libcxx >=18 + - libzlib >=1.3.1,<2.0a0 + - zlib + license: MIT + license_family: MIT + purls: [] + size: 173220 + timestamp: 1730769371051 - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda sha256: 4d7ec90d4f9c1f3b4a50623fefe4ebba69f651b102b373f7c0e9dbbfa43d495c md5: a11ab1f31af799dd93c3a39881528884 @@ -11358,6 +14306,64 @@ packages: purls: [] size: 7212 timestamp: 1756321849562 +- conda: https://conda.anaconda.org/conda-forge/linux-64/protobuf-6.33.5-py312ha7b3241_2.conda + sha256: 53997629b27a2465989f23e3a6212cfcc19f51c474d8f89905bb99859140ee88 + md5: 0aee4f9ff95fc4bc78264a93e2a74adf + depends: + - __glibc >=2.17,<3.0.a0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libgcc >=14 + - libstdcxx >=14 + - libzlib >=1.3.1,<2.0a0 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - libprotobuf 6.33.5 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/protobuf?source=hash-mapping + size: 481654 + timestamp: 1773265949321 +- conda: https://conda.anaconda.org/conda-forge/osx-64/protobuf-6.33.5-py312hf5f8d9f_2.conda + sha256: e0cf97e208c236656576c8eace665c756e0e1f840b6191169f22b758d63633e8 + md5: fcf0fc2b6f794dc454a5521542b97e90 + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libcxx >=19 + - libzlib >=1.3.1,<2.0a0 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - libprotobuf 6.33.5 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/protobuf?source=hash-mapping + size: 469618 + timestamp: 1773265967461 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/protobuf-6.33.5-py312h857ab9a_2.conda + sha256: 3e8720f23829f60103f61fc5e53ac36535da5896855a98d2bbbc6a35e78be430 + md5: db3dd88ca6652ab2485d11f88a2b1d59 + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20260107.1,<20260108.0a0 + - libcxx >=19 + - libzlib >=1.3.1,<2.0a0 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - libprotobuf 6.33.5 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/protobuf?source=hash-mapping + size: 465012 + timestamp: 1773265421534 - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py312h5253ce2_0.conda sha256: d834fd656133c9e4eaf63ffe9a117c7d0917d86d89f7d64073f4e3a0020bd8a7 md5: dd94c506b119130aef5a9382aed648e7 @@ -11466,6 +14472,116 @@ packages: - scipy ; extra == 'scipy' - wand ; extra == 'wand' - parakimo ; extra == 'parakimo' +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-24.0.0-py312h7900ff3_0.conda + sha256: ce11f466f0dcfc41bd0ef3719adb396fbffa6b866aac75c9242938fa58e546d5 + md5: f9ced0be11f0d3120336e4171a121c2a + depends: + - libarrow-acero 24.0.0.* + - libarrow-dataset 24.0.0.* + - libarrow-substrait 24.0.0.* + - libparquet 24.0.0.* + - pyarrow-core 24.0.0 *_0_* + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 26787 + timestamp: 1776927989772 +- conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-24.0.0-py312hb401068_0.conda + sha256: 9f34bf129e8a618b6a8fecdfafa509823695b945d2618205758fab529ee9b88f + md5: 3301b7a88750f114aa09fc2a28db2435 + depends: + - libarrow-acero 24.0.0.* + - libarrow-dataset 24.0.0.* + - libarrow-substrait 24.0.0.* + - libparquet 24.0.0.* + - pyarrow-core 24.0.0 *_0_* + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 26749 + timestamp: 1776929273540 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-24.0.0-py312h1f38498_0.conda + sha256: c7cc2c75525c6522f9b948cd9ead2d5ceec55ba8b78cfd6f222fbc581219d0ff + md5: 2b3892c12915851e12955ee753eaedbb + depends: + - libarrow-acero 24.0.0.* + - libarrow-dataset 24.0.0.* + - libarrow-substrait 24.0.0.* + - libparquet 24.0.0.* + - pyarrow-core 24.0.0 *_0_* + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 26799 + timestamp: 1776928498495 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-core-24.0.0-py312h2054cf2_0_cpu.conda + sha256: cb2c89aeb97a97572869200e37c153098c5877c7be4774f045459976e0f70233 + md5: fe5033add07e3cf4876fd091b5fecf31 + depends: + - __glibc >=2.17,<3.0.a0 + - libarrow 24.0.0.* *cpu + - libarrow-compute 24.0.0.* *cpu + - libgcc >=14 + - libstdcxx >=14 + - libzlib >=1.3.2,<2.0a0 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - numpy >=1.23,<3 + - apache-arrow-proc * cpu + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/pyarrow?source=hash-mapping + size: 5401544 + timestamp: 1776927982900 +- conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-core-24.0.0-py312h3987635_0_cpu.conda + sha256: dddbcf6e50454794ebd8ba77e892a099dbee4ad9727562e140f765ce0c08552d + md5: 40fe539ada22b325955f3590aefe39a9 + depends: + - __osx >=11.0 + - libarrow 24.0.0.* *cpu + - libarrow-compute 24.0.0.* *cpu + - libcxx >=21 + - libzlib >=1.3.2,<2.0a0 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - numpy >=1.23,<3 + - apache-arrow-proc * cpu + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/pyarrow?source=hash-mapping + size: 4055527 + timestamp: 1776929225059 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-core-24.0.0-py312h21b41d0_0_cpu.conda + sha256: 38049b8b098fa02446e97bedebdde2ff4cae4b579581a7125da3e751bcf5a54d + md5: 7020684cfd5c066e86cee8affad06e83 + depends: + - __osx >=11.0 + - libarrow 24.0.0.* *cpu + - libarrow-compute 24.0.0.* *cpu + - libcxx >=21 + - libzlib >=1.3.2,<2.0a0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + constrains: + - apache-arrow-proc * cpu + - numpy >=1.23,<3 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/pyarrow?source=hash-mapping + size: 4322018 + timestamp: 1776928464897 - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda sha256: e27e0473fc6723311a0bd48b89b616fa1b996a2f7a2b555338cbbcfb9c640568 md5: 9c5491066224083c41b6d5635ed7107b @@ -11478,6 +14594,23 @@ packages: - pkg:pypi/pycparser?source=compressed-mapping size: 55886 timestamp: 1779293633166 +- conda: https://conda.anaconda.org/conda-forge/noarch/pydeck-0.9.2-pyhd8ed1ab_0.conda + sha256: 25a4fb0acf8a1eb3eb0f1ebc1c5610dd9efe5f29616c625d1ee84a9a76eeb5df + md5: 18301be1ab749bc57ae189377836cc47 + depends: + - jinja2 >=2.10.1 + - numpy >=1.16.4 + - python >=3.10 + constrains: + - ipywidgets >=7,<8 + - traitlets >=4.3.2 + - ipykernel >=5.1.2 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/pydeck?source=hash-mapping + size: 8360396 + timestamp: 1776371116205 - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda sha256: af7213a8ca077895e7e10c8f33d5de3436b8a26828422e8a113cc59c9277a3e2 md5: 15f6d0866b0997c5302fc230a566bc72 @@ -11951,6 +15084,18 @@ packages: - pkg:pypi/python-json-logger?source=hash-mapping size: 18969 timestamp: 1777318679482 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.32-pyhcf101f3_0.conda + sha256: 7dde902994a99993b616d597783fcd0ce3265a550feffbd0890b1329c9dff7e0 + md5: f54d00b369042e8e0e235b1a1a817487 + depends: + - python >=3.10 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/python-multipart?source=compressed-mapping + size: 38132 + timestamp: 1780610429919 - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda sha256: e943f9c15a6bdba2e1b9f423ab913b3f6b02197b0ef9f8e6b7464d78b59965b9 md5: f6ad7450fc21e00ecc23812baed6d2e4 @@ -12378,6 +15523,18 @@ packages: - pkg:pypi/rpds-py?source=compressed-mapping size: 294437 timestamp: 1779977098659 +- conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.7.3-hc5a330e_0.conda + sha256: 150a0a5254e8b15ad737549721c7d13406cd96432f3f446e07073dbd98bb2491 + md5: f2bd09e21c5844a12e2f5eefcd075555 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - openssl >=3.5.6,<4.0a0 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 388111 + timestamp: 1778113913631 - conda: https://conda.anaconda.org/conda-forge/noarch/salib-1.5.2-pyhd8ed1ab_0.conda sha256: fc971e80731e39b4e09d05430ccb434cf72cb6a98dd6fcd7db806f59d5e87c6e md5: 2b46f618a11ce94c030d371707350991 @@ -12615,6 +15772,53 @@ packages: - pkg:pypi/six?source=hash-mapping size: 18455 timestamp: 1753199211006 +- conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + sha256: bc86861086db65c9b56dd6a1605755f41a9875b94fc3b69e137f686700d91aa1 + md5: b899f1195be56d8215ed1973a8f409c3 + depends: + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/smmap?source=compressed-mapping + size: 27262 + timestamp: 1781021238494 +- conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda + sha256: 48f3f6a76c34b2cfe80de9ce7f2283ecb55d5ed47367ba91e8bb8104e12b8f11 + md5: 98b6c9dc80eb87b2519b97bcf7e578dd + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - libgcc >=14 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 45829 + timestamp: 1762948049098 +- conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.2.2-h01f5ddf_1.conda + sha256: 1525e6d8e2edf32dabfe2a8e2fc8bf2df81c5ef9f0b5374a3d4ccfa672bfd949 + md5: 2e993292ec18af5cd480932d448598cf + depends: + - libcxx >=19 + - __osx >=10.13 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 40023 + timestamp: 1762948053450 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda + sha256: cb9305ede19584115f43baecdf09a3866bfcd5bcca0d9e527bd76d9a1dbe2d8d + md5: fca4a2222994acd7f691e57f94b750c5 + depends: + - libcxx >=19 + - __osx >=11.0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 38883 + timestamp: 1762948066818 - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda sha256: dce518f45e24cd03f401cb0616917773159a210c19d601c5f2d4e0e5879d30ad md5: 03fe290994c5e4ec17293cfb6bdce520 @@ -12698,6 +15902,19 @@ packages: - pkg:pypi/stack-data?source=hash-mapping size: 26988 timestamp: 1733569565672 +- conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.3.0-pyhcf101f3_0.conda + sha256: 4db81efb63dd859e695a09f279a42d96173a4bcbdbc553390917666a4769e104 + md5: cc5611d8c1b50aeaac99848acec6612e + depends: + - anyio >=3.6.2,<5 + - python >=3.10 + - typing_extensions >=4.10.0 + - python + license: BSD-3-Clause + purls: + - pkg:pypi/starlette?source=compressed-mapping + size: 64167 + timestamp: 1781176104669 - conda: https://conda.anaconda.org/conda-forge/linux-64/statsmodels-0.14.6-py312h4f23490_0.conda sha256: 0c61eccf3f71b9812da8ced747b1f22bafd6f66f9a64abe06bbe147a03b7322e md5: 423b8676bd6eed60e97097b33f13ea3f @@ -12757,6 +15974,54 @@ packages: - pkg:pypi/statsmodels?source=hash-mapping size: 11537488 timestamp: 1764984166760 +- conda: https://conda.anaconda.org/conda-forge/noarch/streamlit-1.58.0-pyhd8ed1ab_0.conda + sha256: f7a65e5dfd04160d44e9d1410f75f69eee16c82843abd56c3a71e31e6664dde3 + md5: a1e5b0b9f0097b9411cbf477eec37f7c + depends: + - altair >=4.0,<7,!=5.4.0,!=5.4.1 + - anyio >=4.0.0 + - blinker >=1.5.0,<2 + - cachetools >=5.5,<8 + - click >=7.0,<9 + - gitpython >=3.0.7,<4,!=3.1.19 + - httptools >=0.6.3 + - itsdangerous >=2.1.2 + - numpy >=1.23,<3 + - packaging >=20 + - pandas >=1.4.0,<4 + - pillow >=7.1.0,<13 + - protobuf >=3.20,<8 + - pyarrow >=7.0 + - pydeck >=0.8.0b4,<1 + - python >=3.10 + - python-multipart >=0.0.10 + - requests >=2.27,<3 + - starlette >=0.40.0 + - tenacity >=8.1.0,<10 + - toml >=0.10.1,<2 + - tornado >=6.0.3,<7,!=6.5.0 + - typing_extensions >=4.10.0,<5 + - uvicorn >=0.30.0 + - watchdog >=2.1.5,<7 + - websockets >=12.0.0 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/streamlit?source=compressed-mapping + size: 7387864 + timestamp: 1780060644912 +- conda: https://conda.anaconda.org/conda-forge/noarch/tenacity-9.1.4-pyhcf101f3_0.conda + sha256: 32e75900d6a094ffe4290a8c9f1fa15744d9da8ff617aba4acaa0f057a065c34 + md5: 043f0599dc8aa023369deacdb5ac24eb + depends: + - python >=3.10 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/tenacity?source=hash-mapping + size: 31404 + timestamp: 1770510172846 - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda sha256: 6b6727a13d1ca6a23de5e6686500d0669081a117736a87c8abf444d60c1e40eb md5: 17b43cee5cc84969529d5d0b0309b2cb @@ -12835,6 +16100,18 @@ packages: purls: [] size: 3127137 timestamp: 1769460817696 +- conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda + sha256: fd30e43699cb22ab32ff3134d3acf12d6010b5bbaa63293c37076b50009b91f8 + md5: d0fc809fa4c4d85e959ce4ab6e1de800 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/toml?source=hash-mapping + size: 24017 + timestamp: 1764486833072 - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda sha256: 91cafdb64268e43e0e10d30bd1bef5af392e69f00edd34dfaf909f69ab2da6bd md5: b5325cf06a000c5b14970462ff5e4d58 @@ -13035,6 +16312,22 @@ packages: - pkg:pypi/urllib3?source=hash-mapping size: 103560 timestamp: 1778188657149 +- conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.49.0-pyhc90fa1f_0.conda + sha256: dc7477d200432bf07aab5218d305d88771c52fb8d449cf82869cdceae291f100 + md5: 29a950390b7de7577d8c0ebc946055b9 + depends: + - __unix + - click >=7.0 + - h11 >=0.8 + - python >=3.10 + - typing_extensions >=4.0 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/uvicorn?source=compressed-mapping + size: 56228 + timestamp: 1780574319325 - conda: https://conda.anaconda.org/conda-forge/noarch/vulture-2.16-pyhd8ed1ab_0.conda sha256: 8110ce046263dfaf60b79f81e6b58189352ce0332dc9410e3e0f5dd05a6c17f0 md5: 07eb801541c33aef793e6ce25de33eab @@ -13158,6 +16451,47 @@ packages: - pkg:pypi/websocket-client?source=hash-mapping size: 61391 timestamp: 1759928175142 +- conda: https://conda.anaconda.org/conda-forge/linux-64/websockets-16.0-py312h5253ce2_1.conda + sha256: dd598cab9175a9ab11c8a1798c49ccabe923263d12aababa84a296cb18206464 + md5: e35ffb48178b20ee1a43fbe7abc93746 + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/websockets?source=hash-mapping + size: 358659 + timestamp: 1768087389177 +- conda: https://conda.anaconda.org/conda-forge/osx-64/websockets-16.0-py312hf7082af_1.conda + sha256: f829712bdea8354b2f8a839f424c30a9105f244224539eb70a0bdbbe3daf66ea + md5: 87a96153ad92bee0cac8461ce243fa83 + depends: + - python + - __osx >=10.13 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/websockets?source=hash-mapping + size: 359204 + timestamp: 1768087387150 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/websockets-16.0-py312hb3ab3e3_1.conda + sha256: 4b15497f3cbc40c6fc9e0f155e9cd31aa13e8d2cb1930355da934af22816a73a + md5: 3da07548ed0e08634abf2b3b878eabc1 + depends: + - python + - python 3.12.* *_cpython + - __osx >=11.0 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/websockets?source=hash-mapping + size: 362390 + timestamp: 1768087403337 - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.47.0-pyhd8ed1ab_0.conda sha256: 9e156ffaefb8463437144326ada4b85d1de17961b9997ac5f1cbbaf747bd8bed md5: d0e3b2f0030cf4fca58bde71d246e94c @@ -13170,17 +16504,18 @@ packages: - pkg:pypi/wheel?source=hash-mapping size: 33491 timestamp: 1776878563806 -- conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-4.0.15-pyhd8ed1ab_0.conda - sha256: 826af5e2c09e5e45361fa19168f46ff524e7a766022615678c3a670c45895d9a - md5: dc257b7e7cad9b79c1dfba194e92297b +- conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-3.6.10-pyhd8ed1ab_0.conda + sha256: 6aeb16d2aacdae68ba7afd980925264f5d0459dd165e3406f13f23949df346c1 + md5: 4d52bbdb661dc1b5a1c2aeb1afcd9a67 depends: - - python >=3.10 + - notebook >=4.4.1 + - python >=3.7 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/widgetsnbextension?source=hash-mapping - size: 889195 - timestamp: 1762040404362 + size: 633673 + timestamp: 1729587712065 - conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-2.1.2-py312h4c3975b_0.conda sha256: 5bf21e14a364018a36869a16d9f706fb662c6cb6da3066100ba6822a70f93d2d md5: 7f2ef073d94036f8b16b6ee7d3562a88 @@ -13697,6 +17032,39 @@ packages: - pkg:pypi/zipp?source=hash-mapping size: 24461 timestamp: 1776131454755 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_2.conda + sha256: 245c9ee8d688e23661b95e3c6dd7272ca936fabc03d423cdb3cdee1bbcf9f2f2 + md5: c2a01a08fc991620a74b32420e97868a + depends: + - __glibc >=2.17,<3.0.a0 + - libzlib 1.3.2 h25fd6f3_2 + license: Zlib + license_family: Other + purls: [] + size: 95931 + timestamp: 1774072620848 +- conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.2-hbb4bfdb_2.conda + sha256: 5dd728cebca2e96fa48d41661f1a35ed0ee3cb722669eee4e2d854c6745655eb + md5: 6276aa61ffc361cbf130d78cfb88a237 + depends: + - __osx >=11.0 + - libzlib 1.3.2 hbb4bfdb_2 + license: Zlib + license_family: Other + purls: [] + size: 92411 + timestamp: 1774073075482 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_2.conda + sha256: 8dd2ac25f0ba714263aac5832d46985648f4bfb9b305b5021d702079badc08d2 + md5: f1c0bce276210bed45a04949cfe8dc20 + depends: + - __osx >=11.0 + - libzlib 1.3.2 h8088a28_2 + license: Zlib + license_family: Other + purls: [] + size: 81123 + timestamp: 1774072974535 - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda sha256: ea4e50c465d70236408cb0bfe0115609fd14db1adcd8bd30d8918e0291f8a75f md5: 2aadb0d17215603a82a2a6b0afd9a4cb diff --git a/pixi.toml b/pixi.toml index cdd2ab7..9580212 100644 --- a/pixi.toml +++ b/pixi.toml @@ -26,6 +26,7 @@ plotly = "*" openpyxl = "*" xlsxwriter = "*" adjusttext = "*" +ansi2html = "*" # Optimization, sensitivity analysis, and modeling utilities pymoo = "*" From 4cced1fe91fadbbf296677bb78af6a7a2aac6399 Mon Sep 17 00:00:00 2001 From: bibymaths Date: Thu, 11 Jun 2026 16:07:41 +0200 Subject: [PATCH 18/42] fixed the frontend no code dashboard, testing networmodel and protwise done --- dashboard/app.py | 10 ++- dashboard/components/download_panel.py | 45 ++++++++++-- dashboard/components/result_browser.py | 98 ++++++++++++++++++++++---- networkmodel/runner.py | 43 ++++++++++- networkmodel/sensitivity.py | 2 +- 5 files changed, 173 insertions(+), 25 deletions(-) diff --git a/dashboard/app.py b/dashboard/app.py index 9591079..008de5b 100644 --- a/dashboard/app.py +++ b/dashboard/app.py @@ -56,7 +56,10 @@ def _render_browser_panel(default_directory: Path | None = None) -> None: if not inventory.has_content: st.warning("This directory exists, but no standard PhosKinTime result files were discovered.") - render_result_browser(inventory) + render_result_browser( + inventory, + key_prefix=f"browser-{inventory.root.name}", + ) render_workflow_tabs(inventory.root) @@ -138,7 +141,10 @@ def _render_launcher_panel() -> None: st.success("Run completed. The result directory is shown below.") try: inventory = discover_result_directory(built.outdir) - render_result_browser(inventory) + render_result_browser( + inventory, + key_prefix=f"launcher-{workflow.key}-{safe_run_name}", + ) render_workflow_tabs(inventory.root) except (FileNotFoundError, NotADirectoryError) as exc: st.warning(f"Run finished, but the result directory could not be opened: {exc}") diff --git a/dashboard/components/download_panel.py b/dashboard/components/download_panel.py index b69e477..8f8b054 100644 --- a/dashboard/components/download_panel.py +++ b/dashboard/components/download_panel.py @@ -1,23 +1,54 @@ from __future__ import annotations +from hashlib import md5 +from pathlib import Path + from dashboard.file_utils import create_result_zip from dashboard.result_parser import ResultInventory -def render_download_panel(inventory: ResultInventory) -> None: +def _path_key(path: Path) -> str: + return md5(str(path.resolve()).encode("utf-8")).hexdigest()[:12] + + +def _safe_key_part(value: object) -> str: + text = str(value) + return "".join(ch if ch.isalnum() or ch in {"-", "_", "."} else "_" for ch in text) + + +def _widget_key(prefix: str, *parts: object) -> str: + return "::".join([prefix, *(_safe_key_part(part) for part in parts if part is not None)]) + + +def render_download_panel(inventory: ResultInventory, key_prefix: str = "download-panel") -> None: import streamlit as st + root = Path(inventory.root) + root_key = _widget_key(key_prefix, _path_key(root)) + zip_state_key = _widget_key(root_key, "zip-bytes") + st.subheader("Download") - st.caption("Create a ZIP archive of the selected result directory. The archive is generated in memory and not written to disk.") - if st.button("Prepare ZIP archive", help="Package all files in this result directory for download."): + st.caption( + "Create a ZIP archive of the selected result directory. " + "The archive is generated in memory and not written to disk." + ) + + if st.button( + "Prepare ZIP archive", + key=_widget_key(root_key, "prepare-zip"), + help="Package all files in this result directory for download.", + ): try: - zip_bytes = create_result_zip(inventory.root) + st.session_state[zip_state_key] = create_result_zip(root) except (FileNotFoundError, NotADirectoryError, ValueError) as exc: st.error(f"Could not create result ZIP: {exc}") return + + if zip_state_key in st.session_state: st.download_button( "Download result ZIP", - data=zip_bytes, - file_name=f"{inventory.root.name or 'phoskintime_results'}.zip", + data=st.session_state[zip_state_key], + file_name=f"{root.name or 'phoskintime_results'}.zip", mime="application/zip", - ) + key=_widget_key(root_key, "download-zip"), + ) \ No newline at end of file diff --git a/dashboard/components/result_browser.py b/dashboard/components/result_browser.py index 9bc8c7c..8e09be0 100644 --- a/dashboard/components/result_browser.py +++ b/dashboard/components/result_browser.py @@ -1,5 +1,8 @@ from __future__ import annotations +from hashlib import md5 +from pathlib import Path + from dashboard.components.download_panel import render_download_panel from dashboard.components.log_viewer import render_logs, render_text_file from dashboard.components.metadata_viewer import render_metadata @@ -10,16 +13,31 @@ from dashboard.result_parser import ResultInventory, discover_result_directory +def _path_key(path: Path) -> str: + return md5(str(path.resolve()).encode("utf-8")).hexdigest()[:12] + + +def _safe_key_part(value: object) -> str: + text = str(value) + return "".join(ch if ch.isalnum() or ch in {"-", "_", "."} else "_" for ch in text) + + +def _widget_key(prefix: str, *parts: object) -> str: + return "::".join([prefix, *(_safe_key_part(part) for part in parts if part is not None)]) + + def _summary_metric(label: str, value: int) -> None: import streamlit as st st.metric(label, value) -def render_result_browser(inventory: ResultInventory) -> None: +def render_result_browser(inventory: ResultInventory, key_prefix: str = "results-browser") -> None: """Render all discovered result-directory content.""" import streamlit as st + root_key = _widget_key(key_prefix, _path_key(inventory.root)) + workflow = infer_workflow(inventory) st.header("Result browser") st.caption(f"Directory: `{inventory.root}`") @@ -40,45 +58,93 @@ def render_result_browser(inventory: ResultInventory) -> None: _summary_metric("Child runs", len(inventory.child_runs)) if inventory.missing_expected: - with st.expander("Missing standard contract files/folders", expanded=False): - st.write("The browser can still show recognised legacy outputs, but these standard items were not found:") + with st.expander( + "Missing standard contract files/folders", + expanded=False, + ): + st.write( + "The browser can still show recognised legacy outputs, " + "but these standard items were not found:" + ) st.code("\n".join(inventory.missing_expected)) - tabs = st.tabs(["Metadata", "Tables", "Plots", "Logs", "Reports", "Artifacts", "Child runs", "Download"]) + tabs = st.tabs( + [ + "Metadata", + "Tables", + "Plots", + "Logs", + "Reports", + "Artifacts", + "Child runs", + "Download", + ] + ) + with tabs[0]: render_metadata(inventory.metadata) render_text_file("Command", inventory.command, language="bash") render_text_file("Resolved config", inventory.config, language="yaml") + with tabs[1]: render_tables(inventory.tables) + with tabs[2]: render_plots(inventory.plots) + with tabs[3]: render_logs(inventory.logs) + with tabs[4]: render_reports(inventory.reports) + with tabs[5]: - _render_downloadable_list("Artifacts", inventory.artifacts) + _render_downloadable_list( + "Artifacts", + inventory.artifacts, + key_prefix=_widget_key(root_key, "artifacts"), + ) + with tabs[6]: - _render_child_runs(inventory) + _render_child_runs( + inventory, + key_prefix=_widget_key(root_key, "child-runs"), + ) + with tabs[7]: - render_download_panel(inventory) + render_download_panel( + inventory, + key_prefix=_widget_key(root_key, "download"), + ) -def _render_downloadable_list(label: str, files) -> None: +def _render_downloadable_list(label: str, files, key_prefix: str) -> None: import streamlit as st st.subheader(label) if not files: st.info(f"No {label.lower()} were found in the selected result directory.") return - selected = st.selectbox(label, files, format_func=lambda item: item.relative_path) + + selected = st.selectbox( + label, + files, + format_func=lambda item: item.relative_path, + key=_widget_key(key_prefix, "select"), + ) + st.write(f"Selected: `{selected.relative_path}`") + with selected.path.open("rb") as handle: - st.download_button("Download", data=handle.read(), file_name=selected.name, key=f"download-{label}-{selected.relative_path}") + st.download_button( + "Download", + data=handle.read(), + file_name=selected.name, + key=_widget_key(key_prefix, "download", selected.relative_path), + ) -def _render_child_runs(inventory: ResultInventory) -> None: +def _render_child_runs(inventory: ResultInventory, key_prefix: str) -> None: import streamlit as st st.subheader("Child workflow result folders") @@ -94,12 +160,18 @@ def _render_child_runs(inventory: ResultInventory) -> None: if path.is_relative_to(inventory.root) else str(path) ), - key=f"child-run-{inventory.root}", + key=_widget_key(key_prefix, "select", _path_key(inventory.root)), ) + st.caption(f"Opening `{selected}`") + try: child_inventory = discover_result_directory(selected) except (FileNotFoundError, NotADirectoryError) as exc: st.warning(f"Child result directory could not be opened: {exc}") return - render_result_browser(child_inventory) + + render_result_browser( + child_inventory, + key_prefix=_widget_key(key_prefix, "child", _path_key(selected)), + ) \ No newline at end of file diff --git a/networkmodel/runner.py b/networkmodel/runner.py index d88a219..c54464e 100644 --- a/networkmodel/runner.py +++ b/networkmodel/runner.py @@ -864,11 +864,50 @@ def _proxy_score(orphan: str, candidate: str) -> float: xu=xu, data_mode=mode, ) + + n_protein_obs = int(loss_data.get("n_p", 0)) + n_rna_obs = int(loss_data.get("n_r", 0)) + n_phospho_obs = int(loss_data.get("n_ph", 0)) + n_total_obs = n_protein_obs + n_rna_obs + n_phospho_obs + + n_protein_entities = int(df_prot["protein"].nunique()) if "protein" in df_prot.columns else 0 + n_rna_entities = int(df_rna["protein"].nunique()) if "protein" in df_rna.columns else 0 + + if {"protein", "psite"}.issubset(df_pho.columns): + n_phospho_sites = int(df_pho[["protein", "psite"]].drop_duplicates().shape[0]) + elif "psite" in df_pho.columns: + n_phospho_sites = int(df_pho["psite"].nunique()) + else: + n_phospho_sites = 0 + + n_protein_times = int(df_prot["time"].nunique()) if "time" in df_prot.columns else 0 + n_rna_times = int(df_rna["time"].nunique()) if "time" in df_rna.columns else 0 + n_phospho_times = int(df_pho["time"].nunique()) if "time" in df_pho.columns else 0 + logger.info( - f"[Data] Number of points: {loss_data['n_p']} protein, {loss_data['n_r']} RNA, " - f"{loss_data['n_ph']} phospho | Total {loss_data['n_p'] + loss_data['n_r'] + loss_data['n_ph']} data points" + "[Data] Loss observations: " + "%d protein rows, %d RNA rows, %d phospho rows | Total %d observation rows", + n_protein_obs, + n_rna_obs, + n_phospho_obs, + n_total_obs, ) + + logger.info( + "[Data] Loss entities: " + "%d protein entities × %d time points, " + "%d RNA entities × %d time points, " + "%d phosphosites × %d time points", + n_protein_entities, + n_protein_times, + n_rna_entities, + n_rna_times, + n_phospho_sites, + n_phospho_times, + ) + configure_jax_parallelism(max_workers=args.cores, logger_obj=logger) + ctx = InferenceContext( objective_fun=problem.objective, theta0=theta0, diff --git a/networkmodel/sensitivity.py b/networkmodel/sensitivity.py index b1bf3bc..85c4c55 100644 --- a/networkmodel/sensitivity.py +++ b/networkmodel/sensitivity.py @@ -424,7 +424,7 @@ def run_sensitivity_analysis(sys, idx, fitted_params, output_dir, metric="l2_nor mp_ctx = _get_process_context() - with ProcessPoolExecutor(max_workers=n_workers, mp_context=mp_ctx) as executor: + with ProcessPoolExecutor(max_workers=n_workers, mp_context=mp_ctx, max_tasks_per_child=1) as executor: futures = { executor.submit(_worker_simulation, task): task[0] for task in tasks From 4a037b6d242a74f53aea012b77754d1d4dffb59a Mon Sep 17 00:00:00 2001 From: bibymaths Date: Thu, 11 Jun 2026 16:18:02 +0200 Subject: [PATCH 19/42] add backward alias for old pymooo results to display in legacy mode and added imageio and gravis libs, module levelling for scripts --- global_model/__init__.py | 31 +++++++++++++++++++++++++++++ pixi.lock | 37 +++++++++++++++++++++++++++++++++++ pixi.toml | 2 ++ scripts/compare_mechanisms.py | 9 +++++++++ 4 files changed, 79 insertions(+) create mode 100644 global_model/__init__.py diff --git a/global_model/__init__.py b/global_model/__init__.py new file mode 100644 index 0000000..f577501 --- /dev/null +++ b/global_model/__init__.py @@ -0,0 +1,31 @@ +"""Backward-compatibility package for old pickled dashboard bundles. + +Old dashboard_bundle.pkl files may reference modules such as: + global_model.network + global_model.params + global_model.simulate +These have moved under networkmodel.*. +""" + +from __future__ import annotations + +import importlib +import sys + +_MODULE_ALIASES = { + "global_model.network": "networkmodel.network", + "global_model.params": "networkmodel.params", + "global_model.simulate": "networkmodel.simulate", + "global_model.utils": "networkmodel.utils", + "global_model.backend": "networkmodel.backend", + "global_model.export": "networkmodel.export", + "global_model.optproblem": "networkmodel.OptimizationProblem", + "global_model.OptimizationProblem": "networkmodel.OptimizationProblem", + "global_model.dashboard_bundle": "networkmodel.dashboard_bundle", +} + +for old_name, new_name in _MODULE_ALIASES.items(): + try: + sys.modules.setdefault(old_name, importlib.import_module(new_name)) + except ModuleNotFoundError: + pass diff --git a/pixi.lock b/pixi.lock index 151f8b5..7d1b83a 100644 --- a/pixi.lock +++ b/pixi.lock @@ -103,6 +103,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphviz-14.1.2-h8b86629_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gravis-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/greenlet-3.5.0-py312h8285ef7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gtk3-3.24.52-ha5ea40c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gts-0.7.6-h977cf35_4.conda @@ -117,6 +118,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda @@ -466,6 +468,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphite2-1.3.14-h21dd04a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphviz-14.1.2-h44fc223_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gravis-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/greenlet-3.5.0-py312h4075484_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gtk3-3.24.52-hf2d442a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gts-0.7.6-h53e17e3_4.conda @@ -480,6 +483,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda @@ -778,6 +782,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.14-hec049ff_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphviz-14.1.2-hec8c438_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gravis-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/greenlet-3.5.0-py312h6510ced_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gtk3-3.24.52-hc0f3e19_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gts-0.7.6-he42f4ea_4.conda @@ -792,6 +797,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda @@ -1118,6 +1124,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphviz-14.1.2-h8b86629_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gravis-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/greenlet-3.5.0-py312h8285ef7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gtk3-3.24.52-ha5ea40c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gts-0.7.6-h977cf35_4.conda @@ -1132,6 +1139,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-7.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda @@ -1547,6 +1555,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphite2-1.3.14-h21dd04a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphviz-14.1.2-h44fc223_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gravis-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/greenlet-3.5.0-py312h4075484_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gtk3-3.24.52-hf2d442a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gts-0.7.6-h53e17e3_4.conda @@ -1561,6 +1570,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-7.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda @@ -1927,6 +1937,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.14-hec049ff_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphviz-14.1.2-hec8c438_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gravis-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/greenlet-3.5.0-py312h6510ced_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gtk3-3.24.52-hc0f3e19_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gts-0.7.6-he42f4ea_4.conda @@ -1941,6 +1952,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-7.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda @@ -2307,6 +2319,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphviz-14.1.2-h8b86629_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gravis-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/greenlet-3.5.0-py312h8285ef7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/griffe-2.0.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/griffecli-2.0.2-pyhcf101f3_0.conda @@ -2324,6 +2337,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda @@ -2687,6 +2701,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphite2-1.3.14-h21dd04a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/graphviz-14.1.2-h44fc223_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gravis-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/greenlet-3.5.0-py312h4075484_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/griffe-2.0.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/griffecli-2.0.2-pyhcf101f3_0.conda @@ -2704,6 +2719,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda @@ -3016,6 +3032,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/graphemeu-0.7.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.14-hec049ff_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphviz-14.1.2-hec8c438_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gravis-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/greenlet-3.5.0-py312h6510ced_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/griffe-2.0.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/griffecli-2.0.2-pyhcf101f3_0.conda @@ -3033,6 +3050,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda @@ -3391,6 +3409,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-7.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda @@ -3840,6 +3859,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-7.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda @@ -4240,6 +4260,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-7.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda @@ -4634,6 +4655,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda @@ -5001,6 +5023,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda @@ -5317,6 +5340,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda @@ -8838,6 +8862,19 @@ packages: - sphinx-gallery>=0.14.0 ; extra == 'doc' - pydoctor>=23.4.0 ; extra == 'doc' requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda + sha256: 8ef69fa00c68fad34a3b7b260ea774fda9bd9274fd706d3baffb9519fd0063fe + md5: b5577bc2212219566578fd5af9993af6 + depends: + - numpy + - pillow >=8.3.2 + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/imageio?source=hash-mapping + size: 293226 + timestamp: 1738273949742 - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda sha256: 82ab2a0d91ca1e7e63ab6a4939356667ef683905dea631bc2121aa534d347b16 md5: 080594bf4493e6bae2607e65390c520a diff --git a/pixi.toml b/pixi.toml index 9580212..8181d8e 100644 --- a/pixi.toml +++ b/pixi.toml @@ -43,6 +43,8 @@ graphviz = "*" python-graphviz = "*" pydot = "*" networkx = "*" +gravis = "*" +imageio = "*" # Bioinformatics / annotation utilities mygene = "*" diff --git a/scripts/compare_mechanisms.py b/scripts/compare_mechanisms.py index ddffb61..d9e4b1d 100644 --- a/scripts/compare_mechanisms.py +++ b/scripts/compare_mechanisms.py @@ -1,3 +1,12 @@ +from __future__ import annotations + +import sys +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parents[1] +if str(REPO_ROOT) not in sys.path: + sys.path.insert(0, str(REPO_ROOT)) + import streamlit as st import streamlit.components.v1 as components From 0a20779eeaf6eacc9387d800537ed947c39638f0 Mon Sep 17 00:00:00 2001 From: bibymaths Date: Thu, 11 Jun 2026 20:25:38 +0200 Subject: [PATCH 20/42] fix: cached rhs in model ode solving, and forward simulation script --- networkmodel/simulate.py | 14 ++++- scripts/compare_mechanisms.py | 107 ++++++++++++++++++++-------------- 2 files changed, 74 insertions(+), 47 deletions(-) diff --git a/networkmodel/simulate.py b/networkmodel/simulate.py index cd8b376..8cbdf61 100644 --- a/networkmodel/simulate.py +++ b/networkmodel/simulate.py @@ -35,9 +35,19 @@ def simulate_diffrax(sys, t_eval, rtol=None, atol=None, max_steps=None, solver_n ) params = (sys.c_k, sys.A_i, sys.B_i, sys.C_i, sys.D_i, sys.Dp_i, sys.E_i, np.asarray([sys.tf_scale], dtype=np.float64)) + rhs = getattr(sys, "_cached_jax_rhs", None) + if rhs is None: + rhs = make_networkmodel_rhs(sys) + sys._cached_jax_rhs = rhs + return np.asarray( - solve_diffrax(y0, np.asarray(t_eval, dtype=np.float64), params=params, rhs=make_networkmodel_rhs(sys), - config=cfg), + solve_diffrax( + y0, + np.asarray(t_eval, dtype=np.float64), + params=params, + rhs=rhs, + config=cfg, + ), dtype=np.float64, ) diff --git a/scripts/compare_mechanisms.py b/scripts/compare_mechanisms.py index d9e4b1d..388a877 100644 --- a/scripts/compare_mechanisms.py +++ b/scripts/compare_mechanisms.py @@ -291,26 +291,44 @@ def run_sim(sys, idx, mod_params): # --- UI Setup --- st.title("🧪 Global Signaling & Transcriptional Knockout Explorer") -sys, idx, best_params, df_tf_model, s_rates = load_system() +st.caption("This dashboard builds the networkmodel system and runs WT/KO simulations on demand.") + +with st.sidebar: + if st.button("Clear cached model", key="clear-compare-cache"): + st.cache_resource.clear() + st.session_state.pop("compare_mechanisms_started", None) + st.rerun() + + start_dashboard = st.button( + "Load model and start dashboard", + type="primary", + key="start-compare-mechanisms", + ) + +if start_dashboard: + st.session_state["compare_mechanisms_started"] = True + +if not st.session_state.get("compare_mechanisms_started", False): + st.info("Click **Load model and start dashboard** in the sidebar. First load may take several minutes.") + st.stop() + +with st.spinner("Loading data, building network matrices, and reconstructing fitted parameters..."): + sys, idx, best_params, df_tf_model, s_rates = load_system() st.sidebar.header("🕹️ Control Panel") + ko_type = st.sidebar.selectbox("1. Choose Perturbation Type", ["None", "Protein (Synthesis)", "Kinase (Activity)"]) ko_params = {k: v.copy() if isinstance(v, np.ndarray) else v for k, v in best_params.items()} Kmat_backup = None # default - def restore_Kinase(): - """ - Restores the state or data related to Kinase to its default or initial configuration. + """No-op retained for old graph code compatibility. - This function is designed to reset or reconstruct necessary elements connected - to Kinase, which can include internal systems, data, or processes, based on - the implementation. - - Returns: - None: This function does not return any value. + Do not mutate sys.kin.Kmat in this dashboard. simulate.py now caches the + JAX RHS, and the RHS captures kinase input arrays as static topology. + Kinase inhibition should therefore be represented through c_k only. """ return None @@ -319,46 +337,29 @@ def restore_Kinase(): target = st.sidebar.selectbox("Select Target Protein", idx.proteins) p_idx = idx.p2i[target] scale = st.sidebar.slider("Protein Synthesis Scale (0 = KO, 1 = WT)", 0.0, 1.0, 0.0, 0.05) - ko_params["A_i"][p_idx] *= scale # scale synthesis rate - sys.update(**ko_params) + + ko_params["A_i"][p_idx] *= scale elif ko_type == "Kinase (Activity)": target = st.sidebar.selectbox("Select Kinase to Inhibit", idx.kinases) k_idx = idx.k2i[target] scale = st.sidebar.slider("Kinase Activity Scale (0 = KO, 1 = WT)", 0.0, 1.0, 0.0, 0.05) - # Backup Kmat and c_k for later restoration - Kmat_backup = sys.kin.Kmat.copy() - c_k_backup = sys.c_k.copy() - - # Apply multiplicative inhibition to both dynamic and static components - sys.kin.Kmat[k_idx, :] *= scale + # Important: do not mutate sys.kin.Kmat here. + # The cached JAX RHS captures kin_Kmat statically. + # Use c_k as the dynamic kinase-activity control. ko_params["c_k"][k_idx] *= scale - - # Restore both after KO simulation - def restore_Kinase(): - """ - Restores the kinase matrix and kinase concentration values to their original backup states. - - This function resets specific global system variables to their previously saved states using backup - values. It is particularly useful for restoring system consistency after temporary modifications. - - Raises: - AttributeError: If any of the required backup attributes are not available or have been removed - from the system. - """ - sys.kin.Kmat = Kmat_backup - sys.c_k = c_k_backup - - - sys.update(**ko_params) else: target = None # --- Simulation Logic --- -wt_dfp, wt_dfr, wt_pho = run_sim(sys, idx, best_params) -ko_dfp, ko_dfr, ko_pho = run_sim(sys, idx, ko_params) +with st.spinner("Running WT and KO simulations..."): + wt_dfp, wt_dfr, wt_pho = run_sim(sys, idx, best_params) + ko_dfp, ko_dfr, ko_pho = run_sim(sys, idx, ko_params) + +# Leave the mutable System in a known baseline state after the comparison. +sys.update(**best_params) # --- Versatile Visualization: The Impact Scatter --- st.header("🎯 System-Wide Impact Analysis") @@ -590,11 +591,24 @@ def restore_Kinase(): step=60 ) -n_points = 10000 +n_points = st.select_slider( + "Forward simulation resolution", + options=[250, 500, 1000, 2500, 5000, 10000], + value=1000, +) + +run_forward_panel = st.button( + "Run detailed WT/KO forward simulation", + key="run-forward-simulation-panel", +) -# Simulate WT to steady state -t_fine, Y_wt = simulate_until_steady(sys, t_max=t_max, n_points=n_points) +if not run_forward_panel: + st.info("Click the button above to run the detailed forward simulation panel.") + st.stop() +with st.spinner(f"Running WT forward simulation with {n_points} time points..."): + sys.update(**best_params) + t_fine, Y_wt = simulate_until_steady(sys, t_max=t_max, n_points=n_points) # Extract per-protein output def extract_fc_from_Y(Y, idx, t, protein, normalize=True): @@ -654,11 +668,14 @@ def extract_fc_from_Y(Y, idx, t, protein, normalize=True): # WT values df_wt = extract_fc_from_Y(Y_wt, idx, t_fine, selected_p) -# KO simulation -sys.update(**ko_params) -t_ko, Y_ko = simulate_until_steady(sys, t_max=t_max, n_points=n_points) +with st.spinner(f"Running KO forward simulation with {n_points} time points..."): + sys.update(**ko_params) + t_ko, Y_ko = simulate_until_steady(sys, t_max=t_max, n_points=n_points) + df_ko = extract_fc_from_Y(Y_ko, idx, t_ko, selected_p) -sys.update(**best_params) # restore baseline + +# Restore baseline after KO simulation. +sys.update(**best_params) # --- Plot mRNA col1, col2 = st.columns(2) From 519e9dedba94f5f1cbd836f82d3da8c13246208d Mon Sep 17 00:00:00 2001 From: bibymaths Date: Fri, 12 Jun 2026 12:44:07 +0200 Subject: [PATCH 21/42] fix: formatting python code --- config.toml | 8 ++-- dashboard/app.py | 7 ++-- dashboard/command_builder.py | 32 ++++++++------- dashboard/components/config_panel.py | 16 +++++--- dashboard/components/console_panel.py | 2 + dashboard/components/download_panel.py | 8 ++-- dashboard/components/metadata_viewer.py | 3 +- dashboard/components/plot_viewer.py | 3 +- dashboard/components/preset_panel.py | 3 +- dashboard/components/report_viewer.py | 9 +++-- dashboard/components/result_browser.py | 6 +-- dashboard/components/table_viewer.py | 6 ++- dashboard/components/workflow_selector.py | 3 +- dashboard/registry.py | 48 +++++++++++++++-------- dashboard/runner.py | 20 +++++----- dashboard/workflow_panels/analysis.py | 3 +- dashboard/workflow_panels/kinopt.py | 3 +- dashboard/workflow_panels/networkmodel.py | 6 ++- dashboard/workflow_panels/protwise.py | 9 +++-- dashboard/workflow_panels/tfopt.py | 3 +- networkmodel/BayesianInference.py | 19 ++++----- networkmodel/OptimizationProblem.py | 2 + networkmodel/ProfileWorker.py | 12 +++--- networkmodel/runner.py | 27 ++++++++----- 24 files changed, 156 insertions(+), 102 deletions(-) diff --git a/config.toml b/config.toml index e327196..7c3db5f 100644 --- a/config.toml +++ b/config.toml @@ -273,13 +273,13 @@ tfopt = "data/tfopt_results.xlsx" # ------------------------------------------------------------ # RUN SETTINGS # ------------------------------------------------------------ -output_dir = "results_model_global_distributive_jax" # Output directory +output_dir = "results_network_distributive" # Output directory cores = 80 # 0 or leave out to use all available cores seed = 42 # ------------------------------------------------------------ # OPTIMIZATION PARAMETERS (JAXopt) # ------------------------------------------------------------ -n_gen = 30 # Maximum local optimizer iterations (runner arg: --n-gen) +n_gen = 100 # Maximum local optimizer iterations (runner arg: --n-gen) loss = 2 # Loss type (0: MSE, 1:Huber, 2:Psuedo-Huber, 3:Log-Cosh, 4:Cauchy, 5:Poisson, 6:Geman-McClure) # -1 for Charbonnier Loss @@ -342,10 +342,10 @@ sensitivity_metric = "l2_norm" # ["total_signal", "mean", "variance", # INFERENCE / POST-OPTIMIZATION ANALYSES # ------------------------------------------------------------ # --- Inference / Multistart --- -n_starts = 1 # int: restarts; 1 = single-start (current behaviour) +n_starts = 10 # int: restarts; 1 = single-start (current behaviour) # --- Profile Likelihood (post-optimization) --- profile_likelihood = false -profile_indices = "88" # , 93, 95, 103, 108, 69, 78, 80, 116, 125, 135, 136, 139" # comma-separated parameter indices e.g. "0,1,5" +profile_indices = "" # 88, 93, 95, 103, 108, 69, 78, 80, 116, 125, 135, 136, 139" # comma-separated parameter indices e.g. "0,1,5" profile_grid_size = 5 # --- Posterior Sampling (post-optimization, requires numpyro) --- posterior_sampling = false diff --git a/dashboard/app.py b/dashboard/app.py index 008de5b..d81748e 100644 --- a/dashboard/app.py +++ b/dashboard/app.py @@ -2,7 +2,6 @@ from pathlib import Path - from dashboard.command_builder import build_workflow_command, sanitize_run_name from dashboard.components.command_preview import render_command_preview from dashboard.components.config_panel import render_config_panel @@ -42,7 +41,8 @@ def _render_browser_panel(default_directory: Path | None = None) -> None: candidates.insert(0, default_directory) if candidates: index = candidates.index(default_directory) if default_directory in candidates else 0 - choice = st.selectbox("Select folder", candidates, index=index, format_func=lambda path: str(path), key="browser-choice") + choice = st.selectbox("Select folder", candidates, index=index, format_func=lambda path: str(path), + key="browser-choice") directory_text = st.text_input("Selected result directory", value=str(choice), key="browser-directory") else: st.info("No selectable folders found under the base path. Enter a result directory manually.") @@ -155,7 +155,8 @@ def main() -> None: st.set_page_config(page_title="PhosKinTime Dashboard", layout="wide") st.title("PhosKinTime Dashboard") - st.write("Browse existing result directories or launch registered CLI workflows without reimplementing scientific logic.") + st.write( + "Browse existing result directories or launch registered CLI workflows without reimplementing scientific logic.") launcher_tab, browser_tab = st.tabs(["Run workflow", "Browse results"]) with launcher_tab: diff --git a/dashboard/command_builder.py b/dashboard/command_builder.py index 9368bb5..0a0144d 100644 --- a/dashboard/command_builder.py +++ b/dashboard/command_builder.py @@ -31,7 +31,8 @@ def sanitize_run_name(name: str) -> str: return cleaned or "run" -def build_output_dir(repo_root: str | Path, workflow_key: str, run_name: str, output_base: str | Path = "results") -> Path: +def build_output_dir(repo_root: str | Path, workflow_key: str, run_name: str, + output_base: str | Path = "results") -> Path: """Build a project-local output directory for a workflow run.""" root = Path(repo_root).resolve() base = Path(output_base).expanduser() @@ -73,8 +74,8 @@ def workflow_arguments(workflow: WorkflowDescriptor, values: dict[str, Any] | No return args - -def arguments_from_input_assignments(workflow: WorkflowDescriptor, input_assignments: dict[str, str | Path] | None = None) -> dict[str, str]: +def arguments_from_input_assignments(workflow: WorkflowDescriptor, + input_assignments: dict[str, str | Path] | None = None) -> dict[str, str]: """Map workflow input roles to supported CLI argument names.""" input_assignments = input_assignments or {} specs = {spec.role: spec for spec in workflow.input_assignments} @@ -94,9 +95,9 @@ def arguments_from_input_assignments(workflow: WorkflowDescriptor, input_assignm def merge_argument_sources( - workflow: WorkflowDescriptor, - argument_values: dict[str, Any] | None = None, - input_assignments: dict[str, str | Path] | None = None, + workflow: WorkflowDescriptor, + argument_values: dict[str, Any] | None = None, + input_assignments: dict[str, str | Path] | None = None, ) -> dict[str, Any]: """Merge structured parameters with input assignments without inventing CLI options.""" merged = dict(argument_values or {}) @@ -104,16 +105,17 @@ def merge_argument_sources( merged[name] = value return merged + def build_workflow_command( - workflow_key: str, - *, - repo_root: str | Path = ".", - pixi_environment: str = "default", - run_name: str = "run", - output_base: str | Path = "results", - argument_values: dict[str, Any] | None = None, - input_assignments: dict[str, str | Path] | None = None, - use_pixi: bool = True, + workflow_key: str, + *, + repo_root: str | Path = ".", + pixi_environment: str = "default", + run_name: str = "run", + output_base: str | Path = "results", + argument_values: dict[str, Any] | None = None, + input_assignments: dict[str, str | Path] | None = None, + use_pixi: bool = True, ) -> BuiltCommand: """Build a workflow command as argv list without shell interpolation.""" workflow = get_workflow(workflow_key) diff --git a/dashboard/components/config_panel.py b/dashboard/components/config_panel.py index a27d3e6..dd14b29 100644 --- a/dashboard/components/config_panel.py +++ b/dashboard/components/config_panel.py @@ -3,12 +3,12 @@ from pathlib import Path from typing import Any - from dashboard.config_utils import parse_config_file from dashboard.registry import WorkflowDescriptor -def render_config_panel(workflow: WorkflowDescriptor, available_files: list[Path]) -> tuple[dict[str, Any], dict[str, str]]: +def render_config_panel(workflow: WorkflowDescriptor, available_files: list[Path]) -> tuple[ + dict[str, Any], dict[str, str]]: import streamlit as st """Render structured parameter and workflow-specific input assignment controls.""" @@ -26,20 +26,24 @@ def render_config_panel(workflow: WorkflowDescriptor, available_files: list[Path if spec.kind == "bool": arguments[spec.name] = st.checkbox(spec.flag, value=bool(spec.default), help=help_text) else: - arguments[spec.name] = st.text_input(spec.flag, value=default, help=help_text, key=f"arg-{workflow.key}-{spec.name}") + arguments[spec.name] = st.text_input(spec.flag, value=default, help=help_text, + key=f"arg-{workflow.key}-{spec.name}") if workflow.input_assignments: with st.expander("Input assignments", expanded=True): labels = ["Do not pass"] + [str(path) for path in available_files] for spec in workflow.input_assignments: - selected = st.selectbox(spec.label, labels, help=spec.description or None, key=f"input-{workflow.key}-{spec.role}") - custom = st.text_input(f"Existing path for {spec.label}", value="", key=f"input-path-{workflow.key}-{spec.role}") + selected = st.selectbox(spec.label, labels, help=spec.description or None, + key=f"input-{workflow.key}-{spec.role}") + custom = st.text_input(f"Existing path for {spec.label}", value="", + key=f"input-path-{workflow.key}-{spec.role}") if custom.strip(): assignments[spec.role] = custom.strip() elif selected != "Do not pass": assignments[spec.role] = selected - config_paths = [Path(path) for path in assignments.values() if Path(path).suffix.lower() in {".json", ".yaml", ".yml", ".toml", ".txt"}] + config_paths = [Path(path) for path in assignments.values() if + Path(path).suffix.lower() in {".json", ".yaml", ".yml", ".toml", ".txt"}] if config_paths: with st.expander("Config preview", expanded=False): selected_config = st.selectbox("Config file", config_paths, format_func=lambda path: path.name) diff --git a/dashboard/components/console_panel.py b/dashboard/components/console_panel.py index 92b71c3..54749bb 100644 --- a/dashboard/components/console_panel.py +++ b/dashboard/components/console_panel.py @@ -1,5 +1,6 @@ from __future__ import annotations + def render_console(lines: list[str], height: int = 360) -> None: """Render streamed ANSI-colored console output in Streamlit.""" import streamlit as st @@ -33,6 +34,7 @@ def render_console(lines: list[str], height: int = 360) -> None: unsafe_allow_html=True, ) + def render_cancellation_note() -> None: """Explain the current cancellation boundary without exposing unsafe controls.""" import streamlit as st diff --git a/dashboard/components/download_panel.py b/dashboard/components/download_panel.py index 8f8b054..ce07271 100644 --- a/dashboard/components/download_panel.py +++ b/dashboard/components/download_panel.py @@ -34,9 +34,9 @@ def render_download_panel(inventory: ResultInventory, key_prefix: str = "downloa ) if st.button( - "Prepare ZIP archive", - key=_widget_key(root_key, "prepare-zip"), - help="Package all files in this result directory for download.", + "Prepare ZIP archive", + key=_widget_key(root_key, "prepare-zip"), + help="Package all files in this result directory for download.", ): try: st.session_state[zip_state_key] = create_result_zip(root) @@ -51,4 +51,4 @@ def render_download_panel(inventory: ResultInventory, key_prefix: str = "downloa file_name=f"{root.name or 'phoskintime_results'}.zip", mime="application/zip", key=_widget_key(root_key, "download-zip"), - ) \ No newline at end of file + ) diff --git a/dashboard/components/metadata_viewer.py b/dashboard/components/metadata_viewer.py index d020f66..c246944 100644 --- a/dashboard/components/metadata_viewer.py +++ b/dashboard/components/metadata_viewer.py @@ -12,7 +12,8 @@ def render_metadata(path: Path | None) -> None: st.subheader("Metadata") if path is None: - st.info("No metadata.json file was found. The run can still be browsed, but provenance details are unavailable.") + st.info( + "No metadata.json file was found. The run can still be browsed, but provenance details are unavailable.") return try: st.json(json.loads(path.read_text(encoding="utf-8"))) diff --git a/dashboard/components/plot_viewer.py b/dashboard/components/plot_viewer.py index 5c911c8..bc99881 100644 --- a/dashboard/components/plot_viewer.py +++ b/dashboard/components/plot_viewer.py @@ -11,7 +11,8 @@ def render_plots(plots: list[DisplayFile]) -> None: if not plots: st.info("No PNG, JPG, JPEG, SVG, or HTML plots were found in plots/ or recognised legacy plot folders.") return - selected = st.selectbox("Plot", plots, format_func=lambda item: f"{item.relative_path} ({human_size(item.size_bytes)})") + selected = st.selectbox("Plot", plots, + format_func=lambda item: f"{item.relative_path} ({human_size(item.size_bytes)})") if selected.suffix in {".png", ".jpg", ".jpeg", ".svg"}: st.image(str(selected.path), caption=selected.relative_path, use_container_width=True) elif selected.suffix in {".html", ".htm"}: diff --git a/dashboard/components/preset_panel.py b/dashboard/components/preset_panel.py index 3d50b8a..0b9218a 100644 --- a/dashboard/components/preset_panel.py +++ b/dashboard/components/preset_panel.py @@ -11,7 +11,8 @@ def render_preset_panel(selection: DashboardSelection, repo_root: Path) -> None: import streamlit as st st.subheader("Preset") - preset_name = st.text_input("Preset filename", value=f"{selection.run_name}.json", help="Save the current dashboard selections for reproducibility.") + preset_name = st.text_input("Preset filename", value=f"{selection.run_name}.json", + help="Save the current dashboard selections for reproducibility.") if st.button("Save preset"): target = repo_root / "dashboard_uploads" / selection.run_name / preset_name try: diff --git a/dashboard/components/report_viewer.py b/dashboard/components/report_viewer.py index 1577251..c5703e9 100644 --- a/dashboard/components/report_viewer.py +++ b/dashboard/components/report_viewer.py @@ -14,17 +14,20 @@ def render_reports(reports: list[DisplayFile]) -> None: if not reports: st.info("No HTML, Markdown, or PDF reports were found in reports/.") return - selected = st.selectbox("Report", reports, format_func=lambda item: f"{item.relative_path} ({human_size(item.size_bytes)})") + selected = st.selectbox("Report", reports, + format_func=lambda item: f"{item.relative_path} ({human_size(item.size_bytes)})") if selected.suffix in {".html", ".htm"}: html, truncated = read_text_preview(selected.path, max_bytes=2_000_000) components.html(html, height=700, scrolling=True) if truncated: - st.warning("HTML report preview was truncated because the file is large. Download the file for the full report.") + st.warning( + "HTML report preview was truncated because the file is large. Download the file for the full report.") elif selected.suffix == ".md": markdown, truncated = read_text_preview(selected.path, max_bytes=1_000_000) st.markdown(markdown) if truncated: - st.warning("Markdown report preview was truncated because the file is large. Download the file for the full report.") + st.warning( + "Markdown report preview was truncated because the file is large. Download the file for the full report.") elif selected.suffix == ".pdf": pdf_bytes = selected.path.read_bytes() encoded = base64.b64encode(pdf_bytes).decode("ascii") diff --git a/dashboard/components/result_browser.py b/dashboard/components/result_browser.py index 8e09be0..d9da5d8 100644 --- a/dashboard/components/result_browser.py +++ b/dashboard/components/result_browser.py @@ -59,8 +59,8 @@ def render_result_browser(inventory: ResultInventory, key_prefix: str = "results if inventory.missing_expected: with st.expander( - "Missing standard contract files/folders", - expanded=False, + "Missing standard contract files/folders", + expanded=False, ): st.write( "The browser can still show recognised legacy outputs, " @@ -174,4 +174,4 @@ def _render_child_runs(inventory: ResultInventory, key_prefix: str) -> None: render_result_browser( child_inventory, key_prefix=_widget_key(key_prefix, "child", _path_key(selected)), - ) \ No newline at end of file + ) diff --git a/dashboard/components/table_viewer.py b/dashboard/components/table_viewer.py index f6ecebb..82cbca9 100644 --- a/dashboard/components/table_viewer.py +++ b/dashboard/components/table_viewer.py @@ -30,7 +30,8 @@ def render_tables(tables: list[DisplayFile]) -> None: if not tables: st.info("No CSV, TSV, or Excel tables were found in tables/ or recognised legacy locations.") return - selected = st.selectbox("Table", tables, format_func=lambda item: f"{item.relative_path} ({human_size(item.size_bytes)})") + selected = st.selectbox("Table", tables, + format_func=lambda item: f"{item.relative_path} ({human_size(item.size_bytes)})") sheet_name = None if selected.suffix in {".xlsx", ".xls"}: try: @@ -42,4 +43,5 @@ def render_tables(tables: list[DisplayFile]) -> None: try: st.dataframe(_read_table(str(selected.path), selected.suffix, sheet_name), use_container_width=True) except Exception as exc: - st.error(f"Could not load table {selected.relative_path}. Check that it is a readable CSV, TSV, or Excel file: {exc}") + st.error( + f"Could not load table {selected.relative_path}. Check that it is a readable CSV, TSV, or Excel file: {exc}") diff --git a/dashboard/components/workflow_selector.py b/dashboard/components/workflow_selector.py index c89900d..86d82b8 100644 --- a/dashboard/components/workflow_selector.py +++ b/dashboard/components/workflow_selector.py @@ -17,5 +17,6 @@ def render_workflow_selector(repo_root: Path) -> tuple[WorkflowDescriptor, str, envs = pixi_environments(repo_root / "pixi.toml") env = st.selectbox("Pixi environment", envs, index=0, help="Choose a Pixi environment defined in pixi.toml.") - run_name = st.text_input("Run name", value=f"{workflow.key}-run", help="Used to name the result and upload folders; unsafe characters are sanitized.") + run_name = st.text_input("Run name", value=f"{workflow.key}-run", + help="Used to name the result and upload folders; unsafe characters are sanitized.") return workflow, env, run_name diff --git a/dashboard/registry.py b/dashboard/registry.py index 9c73741..8726a5d 100644 --- a/dashboard/registry.py +++ b/dashboard/registry.py @@ -140,9 +140,12 @@ class WorkflowDescriptor: ), required_inputs=("protein CSV", "phosphosite Excel", "RNA Excel"), input_assignments=( - InputSpec("config", "TOML config file", "conf", "Optional ProtWise TOML config file.", extensions=(".toml",)), - InputSpec("protein_file", "Protein CSV file", "input_excel_protein", "Protein input CSV file read by ProtWise.", extensions=(".csv",)), - InputSpec("phosphosite_file", "Phosphosite file", "input_excel_psite", "Phosphosite input Excel file.", extensions=(".xlsx",)), + InputSpec("config", "TOML config file", "conf", "Optional ProtWise TOML config file.", + extensions=(".toml",)), + InputSpec("protein_file", "Protein CSV file", "input_excel_protein", + "Protein input CSV file read by ProtWise.", extensions=(".csv",)), + InputSpec("phosphosite_file", "Phosphosite file", "input_excel_psite", "Phosphosite input Excel file.", + extensions=(".xlsx",)), InputSpec("rna_file", "RNA/mRNA file", "input_excel_rna", "RNA input Excel file.", extensions=(".xlsx",)), ), output_dir_arg="--outdir", @@ -178,15 +181,24 @@ class WorkflowDescriptor: ), required_inputs=("kinase network", "TF network", "MS/protein data", "RNA data", "phospho data"), input_assignments=( - InputSpec("config", "TOML config file", "conf", "Optional networkmodel TOML config file.", extensions=(".toml",)), - InputSpec("kinase_network", "Kinase network CSV file", "kinase_net", "Kinase network CSV file read by networkmodel.", extensions=(".csv",)), - InputSpec("tf_network", "TF network CSV file", "tf_net", "TF network CSV file read by networkmodel.", extensions=(".csv",)), - InputSpec("protein_file", "Protein/MS CSV file", "ms", "Protein/MS CSV data file read by networkmodel.", extensions=(".csv",)), - InputSpec("rna_file", "RNA/mRNA CSV file", "rna", "RNA CSV data file read by networkmodel.", extensions=(".csv",)), - InputSpec("phosphosite_file", "Phosphoproteomics CSV file", "phospho", "Phosphoproteomics CSV data file read by networkmodel.", extensions=(".csv",)), - InputSpec("previous_kinopt", "Previous KinOpt result", "kinopt", "Previous kinopt Excel result.", extensions=(".xlsx",)), - InputSpec("previous_tfopt", "Previous TFOpt result", "tfopt", "Previous tfopt Excel result.", extensions=(".xlsx",)), - InputSpec("networkmodel_result_dir", "Networkmodel result directory", None, "Reference result directory for browsing; not passed to CLI."), + InputSpec("config", "TOML config file", "conf", "Optional networkmodel TOML config file.", + extensions=(".toml",)), + InputSpec("kinase_network", "Kinase network CSV file", "kinase_net", + "Kinase network CSV file read by networkmodel.", extensions=(".csv",)), + InputSpec("tf_network", "TF network CSV file", "tf_net", "TF network CSV file read by networkmodel.", + extensions=(".csv",)), + InputSpec("protein_file", "Protein/MS CSV file", "ms", "Protein/MS CSV data file read by networkmodel.", + extensions=(".csv",)), + InputSpec("rna_file", "RNA/mRNA CSV file", "rna", "RNA CSV data file read by networkmodel.", + extensions=(".csv",)), + InputSpec("phosphosite_file", "Phosphoproteomics CSV file", "phospho", + "Phosphoproteomics CSV data file read by networkmodel.", extensions=(".csv",)), + InputSpec("previous_kinopt", "Previous KinOpt result", "kinopt", "Previous kinopt Excel result.", + extensions=(".xlsx",)), + InputSpec("previous_tfopt", "Previous TFOpt result", "tfopt", "Previous tfopt Excel result.", + extensions=(".xlsx",)), + InputSpec("networkmodel_result_dir", "Networkmodel result directory", None, + "Reference result directory for browsing; not passed to CLI."), ), output_dir_arg="--output-dir", expected_output_folder="results/networkmodel", @@ -207,9 +219,12 @@ class WorkflowDescriptor: ArgumentSpec("model_conf", "--model-conf", "path", "ProtWise config file."), ), input_assignments=( - InputSpec("tf_config", "TFOpt TOML config file", "tf_conf", "TOML config for TFOpt stage.", extensions=(".toml",)), - InputSpec("kin_config", "KinOpt TOML config file", "kin_conf", "TOML config for KinOpt stage.", extensions=(".toml",)), - InputSpec("model_config", "ProtWise TOML config file", "model_conf", "TOML config for ProtWise stage.", extensions=(".toml",)), + InputSpec("tf_config", "TFOpt TOML config file", "tf_conf", "TOML config for TFOpt stage.", + extensions=(".toml",)), + InputSpec("kin_config", "KinOpt TOML config file", "kin_conf", "TOML config for KinOpt stage.", + extensions=(".toml",)), + InputSpec("model_config", "ProtWise TOML config file", "model_conf", "TOML config for ProtWise stage.", + extensions=(".toml",)), ), output_dir_arg="--outdir", expected_output_folder="results/phoskintime-all", @@ -230,7 +245,8 @@ def get_workflow(key: str) -> WorkflowDescriptor: def launchable_workflows() -> list[WorkflowDescriptor]: """Return dashboard-safe workflows that have an executable Python module.""" - return [wf for wf in sorted(WORKFLOWS.values(), key=lambda item: item.key) if wf.safe_for_dashboard and wf.python_module] + return [wf for wf in sorted(WORKFLOWS.values(), key=lambda item: item.key) if + wf.safe_for_dashboard and wf.python_module] def infer_workflow(inventory: ResultInventory) -> WorkflowDescriptor: diff --git a/dashboard/runner.py b/dashboard/runner.py index 9eb4c9e..c6b902a 100644 --- a/dashboard/runner.py +++ b/dashboard/runner.py @@ -52,12 +52,12 @@ def prepare_run_provenance(built: BuiltCommand, extra: dict | None = None) -> Pa def stream_command( - command: list[str], - *, - cwd: str | Path, - outdir: str | Path, - env: dict[str, str] | None = None, - cancel_check: Callable[[], bool] | None = None, + command: list[str], + *, + cwd: str | Path, + outdir: str | Path, + env: dict[str, str] | None = None, + cancel_check: Callable[[], bool] | None = None, ) -> Iterator[RunEvent]: """Run a command with shell=False, streaming merged stdout/stderr and writing console.log.""" root = ensure_result_dir(outdir)["root"] @@ -96,10 +96,10 @@ def stream_command( def run_built_command( - built: BuiltCommand, - *, - repo_root: str | Path, - cancel_check: Callable[[], bool] | None = None, + built: BuiltCommand, + *, + repo_root: str | Path, + cancel_check: Callable[[], bool] | None = None, ) -> Iterator[RunEvent]: """Prepare provenance, execute a built workflow command, and update run metadata.""" outdir = prepare_run_provenance(built) diff --git a/dashboard/workflow_panels/analysis.py b/dashboard/workflow_panels/analysis.py index 1b3b6d6..0d70ecd 100644 --- a/dashboard/workflow_panels/analysis.py +++ b/dashboard/workflow_panels/analysis.py @@ -118,7 +118,8 @@ def render(root: str | Path) -> None: import streamlit as st st.subheader("Advanced analyses") - st.caption("Analyses are not run automatically. Build a command, review it, and run via the launcher or terminal when appropriate.") + st.caption( + "Analyses are not run automatically. Build a command, review it, and run via the launcher or terminal when appropriate.") task = st.selectbox("Analysis", list(ANALYSIS_TASKS.values()), format_func=lambda item: item.label) st.write(task.description) values: dict[str, Any] = {} diff --git a/dashboard/workflow_panels/kinopt.py b/dashboard/workflow_panels/kinopt.py index fb130c5..7338613 100644 --- a/dashboard/workflow_panels/kinopt.py +++ b/dashboard/workflow_panels/kinopt.py @@ -14,7 +14,8 @@ def discover_kinopt_panel(root: str | Path) -> WorkflowPanelData: result = _first_existing(root, ("kinopt_results.xlsx",)) tables = {"kinopt_results": result} if result else {} messages = [] if result else ["No kinopt_results.xlsx file found in the result directory or tables/."] - return WorkflowPanelData(root=root, primary_result=result, tables=tables, plots=inventory.plots, reports=inventory.reports, artifacts=inventory.artifacts, messages=messages) + return WorkflowPanelData(root=root, primary_result=result, tables=tables, plots=inventory.plots, + reports=inventory.reports, artifacts=inventory.artifacts, messages=messages) def render(root: str | Path) -> None: diff --git a/dashboard/workflow_panels/networkmodel.py b/dashboard/workflow_panels/networkmodel.py index 89dfffb..df63ae9 100644 --- a/dashboard/workflow_panels/networkmodel.py +++ b/dashboard/workflow_panels/networkmodel.py @@ -27,8 +27,10 @@ def discover_networkmodel_panel(root: str | Path) -> WorkflowPanelData: for item in inventory.tables: if item.relative_path.startswith(("optimization/", "profiles/", "posterior/")): tables[item.relative_path] = item.path - messages = [] if (bundle or tables or inventory.plots) else ["No networkmodel bundle, scalar objective, predictions, or inference outputs were found."] - return WorkflowPanelData(root=root, primary_result=bundle, tables=tables, plots=inventory.plots, reports=inventory.reports, artifacts=inventory.artifacts, messages=messages) + messages = [] if (bundle or tables or inventory.plots) else [ + "No networkmodel bundle, scalar objective, predictions, or inference outputs were found."] + return WorkflowPanelData(root=root, primary_result=bundle, tables=tables, plots=inventory.plots, + reports=inventory.reports, artifacts=inventory.artifacts, messages=messages) def render(root: str | Path) -> None: diff --git a/dashboard/workflow_panels/protwise.py b/dashboard/workflow_panels/protwise.py index 05aa56f..db93dda 100644 --- a/dashboard/workflow_panels/protwise.py +++ b/dashboard/workflow_panels/protwise.py @@ -16,9 +16,12 @@ def discover_protwise_panel(root: str | Path) -> WorkflowPanelData: for item in inventory.tables if any(key in item.name.lower() for key in PROTWISE_KEYWORDS) or item.suffix in {".xlsx", ".csv"} } - plots = [item for item in inventory.plots if any(key in item.name.lower() for key in PROTWISE_KEYWORDS)] or inventory.plots - messages = [] if (tables or plots or inventory.reports) else ["No ProtWise-specific outputs were discovered; run the model first or select another result directory."] - return WorkflowPanelData(root=root, tables=tables, plots=plots, reports=inventory.reports, artifacts=inventory.artifacts, messages=messages) + plots = [item for item in inventory.plots if + any(key in item.name.lower() for key in PROTWISE_KEYWORDS)] or inventory.plots + messages = [] if (tables or plots or inventory.reports) else [ + "No ProtWise-specific outputs were discovered; run the model first or select another result directory."] + return WorkflowPanelData(root=root, tables=tables, plots=plots, reports=inventory.reports, + artifacts=inventory.artifacts, messages=messages) def render(root: str | Path) -> None: diff --git a/dashboard/workflow_panels/tfopt.py b/dashboard/workflow_panels/tfopt.py index 4e588a2..7a1c00a 100644 --- a/dashboard/workflow_panels/tfopt.py +++ b/dashboard/workflow_panels/tfopt.py @@ -14,7 +14,8 @@ def discover_tfopt_panel(root: str | Path) -> WorkflowPanelData: result = _first_existing(root, ("tfopt_results.xlsx",)) tables = {"tfopt_results": result} if result else {} messages = [] if result else ["No tfopt_results.xlsx file found in the result directory or tables/."] - return WorkflowPanelData(root=root, primary_result=result, tables=tables, plots=inventory.plots, reports=inventory.reports, artifacts=inventory.artifacts, messages=messages) + return WorkflowPanelData(root=root, primary_result=result, tables=tables, plots=inventory.plots, + reports=inventory.reports, artifacts=inventory.artifacts, messages=messages) def render(root: str | Path) -> None: diff --git a/networkmodel/BayesianInference.py b/networkmodel/BayesianInference.py index d21f0ee..af4c3c5 100644 --- a/networkmodel/BayesianInference.py +++ b/networkmodel/BayesianInference.py @@ -9,7 +9,6 @@ from concurrent.futures import ThreadPoolExecutor, as_completed from dataclasses import dataclass, replace import json -import multiprocessing as mp import os import sys from pathlib import Path @@ -312,14 +311,15 @@ def _plot_multistart(summary: pd.DataFrame, params: pd.DataFrame, names: Sequenc fig.savefig(plot_dir / "parameter_objective_tradeoff.png", dpi=300) plt.close(fig) + def run_profile_likelihood_standalone_processes( - *, - run_config_path: str | Path, - output_dir: str | Path, - parameter_indices: Sequence[int], - grid_size: int = 5, - max_workers: int = 1, - timeout_seconds: int | None = None, + *, + run_config_path: str | Path, + output_dir: str | Path, + parameter_indices: Sequence[int], + grid_size: int = 5, + max_workers: int = 1, + timeout_seconds: int | None = None, ) -> dict: """Run profile likelihood in standalone subprocesses. @@ -480,7 +480,7 @@ def _start_worker(param_idx: int): .transform("min") ) summary.loc[finite_mask, "delta_objective"] = ( - summary.loc[finite_mask, "objective_value"].to_numpy() - mins.to_numpy() + summary.loc[finite_mask, "objective_value"].to_numpy() - mins.to_numpy() ) summary.to_csv(out / "profile_likelihood_summary.csv", index=False) @@ -506,6 +506,7 @@ def _start_worker(param_idx: int): "output_dir": out, } + def run_profile_likelihood(ctx: InferenceContext, *, parameter_indices: Sequence[int], grid_size: int = 5) -> dict: out = Path(ctx.output_dir) / "profiles" plot_dir = Path(ctx.output_dir) / "plots" / "profile_likelihood" diff --git a/networkmodel/OptimizationProblem.py b/networkmodel/OptimizationProblem.py index 01d690a..4f6d2ae 100644 --- a/networkmodel/OptimizationProblem.py +++ b/networkmodel/OptimizationProblem.py @@ -18,6 +18,7 @@ logger = setup_logger(log_dir=RESULTS_DIR) + def _validate_slice_layout_covers_bounds(slices, bounds_size: int) -> int: """Validate that non-empty theta slices cover [0, bounds_size) exactly once.""" bounds_size = int(bounds_size) @@ -87,6 +88,7 @@ def _validate_slice_layout_covers_bounds(slices, bounds_size: int) -> int: return bounds_size + def build_weight_functions(method_protein="uniform", method_rna="uniform", time_grid=None): """Build placeholder weight functions for scalar optimization diff --git a/networkmodel/ProfileWorker.py b/networkmodel/ProfileWorker.py index 4faff62..feedd55 100644 --- a/networkmodel/ProfileWorker.py +++ b/networkmodel/ProfileWorker.py @@ -57,10 +57,10 @@ def _cleanup_after_grid_step(*objs) -> None: def run_one_parameter_profile( - *, - run_config_path: str | Path, - parameter_index: int, - grid_size: int, + *, + run_config_path: str | Path, + parameter_index: int, + grid_size: int, ) -> dict: run_config_path = Path(run_config_path) @@ -213,7 +213,7 @@ def run_one_parameter_profile( if not finite.empty: finite_min = finite["objective_value"].min() partial_df["delta_objective"] = ( - partial_df["objective_value"] - finite_min + partial_df["objective_value"] - finite_min ) else: partial_df["delta_objective"] = np.inf @@ -282,4 +282,4 @@ def main() -> None: if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/networkmodel/runner.py b/networkmodel/runner.py index c54464e..1e056c9 100644 --- a/networkmodel/runner.py +++ b/networkmodel/runner.py @@ -52,7 +52,6 @@ def _close_log_handlers(): pass - def _jsonable_runtime(value: Any) -> Any: """Convert runtime configuration values to JSON/YAML-safe primitives.""" if isinstance(value, Path): @@ -111,7 +110,8 @@ def _model_code(model: Any) -> int: if isinstance(model, int): return model name = str(model).strip().lower() - mapping = {"distributive": 0, "sequential": 1, "successive": 1, "combinatorial": 2, "saturating": 4, "saturation": 4} + mapping = {"distributive": 0, "sequential": 1, "successive": 1, "combinatorial": 2, "saturating": 4, + "saturation": 4} return mapping.get(name, 4) @@ -171,7 +171,8 @@ def _config_defaults(config: Any, resolved_config_path: Path, supplied_conf_path def build_parser(config_defaults: dict[str, Any]) -> argparse.ArgumentParser: """Build the full parser after config-backed defaults are known.""" parser = argparse.ArgumentParser() - parser.add_argument("--conf", default=config_defaults["conf"], help="Path to TOML config used for networkmodel defaults.") + parser.add_argument("--conf", default=config_defaults["conf"], + help="Path to TOML config used for networkmodel defaults.") parser.add_argument("--kinase-net", default=config_defaults["kinase_net"]) parser.add_argument("--tf-net", default=config_defaults["tf_net"]) parser.add_argument("--ms", default=config_defaults["ms"]) @@ -188,10 +189,15 @@ def build_parser(config_defaults: dict[str, Any]) -> argparse.ArgumentParser: parser.add_argument("--lambda-rna", type=float, default=config_defaults["lambda_rna"]) parser.add_argument("--lambda-phospho", type=float, default=config_defaults["lambda_phospho"]) parser.add_argument("--normalize-fc-steady", action="store_true", default=config_defaults["normalize_fc_steady"]) - parser.add_argument("--use-initial-condition-from-data", action="store_true", default=config_defaults["use_initial_condition_from_data"]) - parser.add_argument("--scan", action="store_true", help="Run a hyperparameter scan using Optuna to find the best regularization parameters.", default=config_defaults["scan"]) - parser.add_argument("--sensitivity", action="store_true", help="Run a sensitivity analysis after optimization.", default=config_defaults["sensitivity"]) - parser.add_argument("--solver", type=str, choices=["jaxopt", "pymoo", "optuna"], default=config_defaults["solver"], help="Choice of optimization solver. Legacy pymoo/optuna values map to jaxopt.") + parser.add_argument("--use-initial-condition-from-data", action="store_true", + default=config_defaults["use_initial_condition_from_data"]) + parser.add_argument("--scan", action="store_true", + help="Run a hyperparameter scan using Optuna to find the best regularization parameters.", + default=config_defaults["scan"]) + parser.add_argument("--sensitivity", action="store_true", help="Run a sensitivity analysis after optimization.", + default=config_defaults["sensitivity"]) + parser.add_argument("--solver", type=str, choices=["jaxopt", "pymoo", "optuna"], default=config_defaults["solver"], + help="Choice of optimization solver. Legacy pymoo/optuna values map to jaxopt.") return parser @@ -256,7 +262,8 @@ def _runtime_metadata_extra(args: argparse.Namespace) -> dict[str, Any]: def initialize_run_contract(args: argparse.Namespace) -> argparse.Namespace: """Create output/provenance files after config and CLI precedence are resolved.""" - from common.results import attach_file_console_logger, ensure_result_dir, write_command, write_metadata, write_resolved_config + from common.results import attach_file_console_logger, ensure_result_dir, write_command, write_metadata, \ + write_resolved_config from config.config import setup_logger global logger @@ -329,6 +336,7 @@ def _import_runtime_dependencies() -> None: from networkmodel.simulate import simulate_and_measure from networkmodel.utils import _base_idx, calculate_bio_bounds, get_optimized_sets, normalize_fc_to_t0 + def main(): """Run the networkmodel entry point @@ -1201,7 +1209,8 @@ def _proxy_score(orphan: str, candidate: str) -> float: f"[Output] Saved phosphorylation rates report for picked solution {args.output_dir}/S_rates_report.pdf.") # 12) Export picked solution - dfp, dfr, dfph = simulate_and_measure(sys, idx, args.time_points_protein, args.time_points_rna, args.time_points_phospho) + dfp, dfr, dfph = simulate_and_measure(sys, idx, args.time_points_protein, args.time_points_rna, + args.time_points_phospho) # Save raw preds if dfp is not None: dfp.to_csv(os.path.join(args.output_dir, "pred_prot_picked.csv"), index=False) From 310a22551599a08e4fd296551b753c7fc5ea7d2b Mon Sep 17 00:00:00 2001 From: bibymaths Date: Fri, 12 Jun 2026 12:52:51 +0200 Subject: [PATCH 22/42] add: density plots for posterior with gaussian smoothing --- config.toml | 6 +- networkmodel/BayesianInference.py | 488 +++++++++++++++++++++++++++--- 2 files changed, 447 insertions(+), 47 deletions(-) diff --git a/config.toml b/config.toml index 7c3db5f..85a7c2a 100644 --- a/config.toml +++ b/config.toml @@ -348,9 +348,9 @@ profile_likelihood = false profile_indices = "" # 88, 93, 95, 103, 108, 69, 78, 80, 116, 125, 135, 136, 139" # comma-separated parameter indices e.g. "0,1,5" profile_grid_size = 5 # --- Posterior Sampling (post-optimization, requires numpyro) --- -posterior_sampling = false -posterior_num_warmup = 20 -posterior_num_samples = 30 +posterior_sampling = true +posterior_num_warmup = 300 +posterior_num_samples = 500 # MODEL & BOUNDS CONFIGURATION # ------------------------------------------------------------ diff --git a/networkmodel/BayesianInference.py b/networkmodel/BayesianInference.py index af4c3c5..799bd6c 100644 --- a/networkmodel/BayesianInference.py +++ b/networkmodel/BayesianInference.py @@ -584,6 +584,136 @@ def _plot_profile(df: pd.DataFrame, path: Path) -> None: fig.savefig(path, dpi=300) plt.close(fig) +def _requires_nonnegative_posterior_support(name: str) -> bool: + """Return True for model parameters that are physically non-negative. + + These are kinetic/rate/scale parameters. Signed regulatory parameters, + if any, are intentionally left unconstrained. + """ + name = str(name) + + return ( + name.startswith("c_k[") + or name.startswith("A_i[") + or name.startswith("B_i[") + or name.startswith("C_i[") + or name.startswith("D_i[") + or name.startswith("Dp_i[") + or name.startswith("E_i[") + or name == "tf_scale" + ) + + +def _sanitize_numpyro_posterior_bounds( + lower, + upper, + names, + *, + eps: float = 1e-8, +) -> tuple[np.ndarray, np.ndarray]: + """Sanitize posterior bounds before constructing NumPyro priors. + + NumPyro samples directly from these bounds. Therefore, for parameters that + are physically non-negative, the posterior lower bound must be >= 0. + + This function intentionally raises on impossible intervals rather than + silently producing invalid posterior samples. + """ + lower = np.asarray(lower, dtype=np.float64).copy() + upper = np.asarray(upper, dtype=np.float64).copy() + names = list(names) + + if len(names) != len(lower): + raise ValueError( + f"Parameter name count does not match bounds: " + f"len(names)={len(names)}, len(lower)={len(lower)}" + ) + + if lower.shape != upper.shape: + raise ValueError( + f"Posterior lower/upper shape mismatch: " + f"lower={lower.shape}, upper={upper.shape}" + ) + + bad_finite = ~np.isfinite(lower) | ~np.isfinite(upper) + if np.any(bad_finite): + bad_names = [names[i] for i in np.where(bad_finite)[0]] + raise ValueError( + "Posterior bounds contain non-finite values for parameters: " + f"{bad_names}" + ) + + for i, name in enumerate(names): + if _requires_nonnegative_posterior_support(name): + if upper[i] <= 0.0: + raise ValueError( + f"Invalid posterior bounds for non-negative parameter {name}: " + f"lower={lower[i]}, upper={upper[i]}. " + "The upper bound must be > 0. Fix calculate_bio_bounds() " + "or init_raw_params() upstream." + ) + + lower[i] = max(lower[i], 0.0) + + if upper[i] <= lower[i]: + raise ValueError( + f"Invalid posterior interval for non-negative parameter {name}: " + f"lower={lower[i]}, upper={upper[i]}." + ) + + bad_interval = upper <= lower + if np.any(bad_interval): + bad_names = [names[i] for i in np.where(bad_interval)[0]] + raise ValueError( + "Posterior bounds contain invalid intervals with upper <= lower: " + f"{bad_names}" + ) + + too_narrow = (upper - lower) < eps + if np.any(too_narrow): + bad_names = [names[i] for i in np.where(too_narrow)[0]] + raise ValueError( + "Posterior bounds are too narrow for stable NUTS initialization: " + f"{bad_names}" + ) + + return lower, upper + + +def _make_interior_initial_value(theta0, lower, upper, *, eps: float = 1e-8) -> np.ndarray: + """Clip theta0 safely inside the NumPyro Uniform support.""" + theta0 = np.asarray(theta0, dtype=np.float64) + lower = np.asarray(lower, dtype=np.float64) + upper = np.asarray(upper, dtype=np.float64) + + width = upper - lower + interior_eps = np.minimum(eps, 0.25 * width) + + return np.clip( + theta0, + lower + interior_eps, + upper - interior_eps, + ) + + +def _assert_no_negative_nonnegative_samples(sample_df: pd.DataFrame, names: Sequence[str]) -> None: + """Fail if NumPyro produced negative samples for non-negative parameters.""" + nonnegative_cols = [ + name for name in names + if name in sample_df.columns and _requires_nonnegative_posterior_support(name) + ] + + if not nonnegative_cols: + return + + mins = sample_df[nonnegative_cols].min(axis=0) + leaked = mins[mins < -1e-10] + + if not leaked.empty: + raise RuntimeError( + "Posterior produced negative samples for parameters that should be " + f"non-negative: {leaked.to_dict()}" + ) def run_numpyro_posterior( ctx: InferenceContext, @@ -602,57 +732,80 @@ def run_numpyro_posterior( from numpyro.infer import MCMC, NUTS except ImportError as exc: raise RuntimeError( - "NumPyro posterior inference requires the optional 'numpyro' dependency. Install numpyro to run posterior analysis.") from exc + "NumPyro posterior inference requires the optional 'numpyro' dependency. " + "Install numpyro to run posterior analysis." + ) from exc + out = Path(ctx.output_dir) / "posterior" plot_dir = Path(ctx.output_dir) / "plots" / "posterior" out.mkdir(parents=True, exist_ok=True) plot_dir.mkdir(parents=True, exist_ok=True) + + names = _param_names(len(ctx.theta0), ctx.parameter_names) + lower_np = np.asarray(ctx.lower, dtype=np.float64).copy() upper_np = np.asarray(ctx.upper, dtype=np.float64).copy() - bad = upper_np <= lower_np - if np.any(bad): - upper_np[bad] = lower_np[bad] + 1e-12 + # Critical fix: + # NumPyro samples directly from these bounds, so physical non-negativity + # must be enforced before constructing the Uniform prior. + lower_np, upper_np = _sanitize_numpyro_posterior_bounds( + lower_np, + upper_np, + names, + ) - theta_center_np = np.clip( - np.asarray(ctx.theta0, dtype=np.float64), - lower_np + 1e-8, - upper_np - 1e-8, + theta_center_np = _make_interior_initial_value( + ctx.theta0, + lower_np, + upper_np, ) theta_center = jnp.asarray(theta_center_np, dtype=jnp.float64) lower = jnp.asarray(lower_np, dtype=jnp.float64) upper = jnp.asarray(upper_np, dtype=jnp.float64) + if ctx.fixed_mask is not None: + fixed_mask_np = np.asarray(ctx.fixed_mask, dtype=bool) + else: + fixed_mask_np = None + + if ctx.fixed_values is not None: + fixed_values_np = _make_interior_initial_value( + ctx.fixed_values, + lower_np, + upper_np, + ) + else: + fixed_values_np = None + def model(): theta = numpyro.sample( "theta", dist.Uniform(lower, upper).to_event(1), ) - if ctx.fixed_mask is not None and ctx.fixed_values is not None: - fixed_mask = jnp.asarray(ctx.fixed_mask, dtype=bool) - fixed_values = jnp.clip( - jnp.asarray(ctx.fixed_values, dtype=jnp.float64), - lower, - upper, - ) + if fixed_mask_np is not None and fixed_values_np is not None: + fixed_mask = jnp.asarray(fixed_mask_np, dtype=bool) + fixed_values = jnp.asarray(fixed_values_np, dtype=jnp.float64) theta = jnp.where(fixed_mask, fixed_values, theta) sigma = numpyro.sample("sigma", dist.Exponential(1.0)) + objective = ctx.objective_fun(theta) numpyro.deterministic("scalar_objective", objective) - numpyro.factor("objective_likelihood", -0.5 * objective / (sigma * sigma + 1e-6)) + + numpyro.factor( + "objective_likelihood", + -0.5 * objective / (sigma * sigma + 1e-6), + ) kernel = NUTS( model, init_strategy=numpyro.infer.init_to_value( - values= - { - "theta": theta_center - } - ) + values={"theta": theta_center} + ), ) mcmc = MCMC( @@ -673,37 +826,67 @@ def model(): arr = np.asarray(value) if arr.ndim <= 1: diagnostics[key] = arr.tolist() + with open(out / "posterior_extra_fields.json", "w") as f: json.dump(diagnostics, f, indent=2) samples = mcmc.get_samples(group_by_chain=False) - names = _param_names(len(ctx.theta0), ctx.parameter_names) - theta_samples = np.asarray(samples["theta"]) + theta_samples = np.asarray(samples["theta"], dtype=np.float64) sample_df = pd.DataFrame(theta_samples, columns=names) - sample_df["sigma"] = np.asarray(samples["sigma"]) + + sample_df["sigma"] = np.asarray(samples["sigma"], dtype=np.float64) if "scalar_objective" in samples: - sample_df["scalar_objective"] = np.asarray(samples["scalar_objective"]) + sample_df["scalar_objective"] = np.asarray( + samples["scalar_objective"], + dtype=np.float64, + ) + sample_df["data_mode"] = ctx.mode.data_mode + + # Fail loudly if anything escaped the intended physical support. + _assert_no_negative_nonnegative_samples(sample_df, names) + sample_df.to_csv(out / "posterior_samples.csv", index=False) + summary_rows = [] for col in names + ["sigma"]: vals = sample_df[col].to_numpy(dtype=np.float64) - summary_rows.append({"parameter": col, "mean": vals.mean(), "median": np.median(vals), "sd": vals.std(ddof=0), - "ci_05": np.quantile(vals, 0.05), "ci_95": np.quantile(vals, 0.95), - "ess": float(len(vals)), "r_hat": np.nan, "data_mode": ctx.mode.data_mode}) + + summary_rows.append( + { + "parameter": col, + "mean": float(vals.mean()), + "median": float(np.median(vals)), + "sd": float(vals.std(ddof=0)), + "ci_05": float(np.quantile(vals, 0.05)), + "ci_95": float(np.quantile(vals, 0.95)), + "ess": float(len(vals)), + "r_hat": np.nan, + "data_mode": ctx.mode.data_mode, + } + ) summary = pd.DataFrame(summary_rows) summary.to_csv(out / "posterior_summary.csv", index=False) - predictive = sample_df[ - ["scalar_objective", "data_mode"]].copy() if "scalar_objective" in sample_df else pd.DataFrame( - {"data_mode": [ctx.mode.data_mode]}) + + if "scalar_objective" in sample_df.columns: + predictive = sample_df[["scalar_objective", "data_mode"]].copy() + else: + predictive = pd.DataFrame({"data_mode": [ctx.mode.data_mode]}) + predictive.to_csv(out / "posterior_predictive.csv", index=False) + _plot_posterior(sample_df, summary, plot_dir) - return {"samples": sample_df, "summary": summary, "posterior_predictive": predictive, "output_dir": out} + return { + "samples": sample_df, + "summary": summary, + "posterior_predictive": predictive, + "output_dir": out, + } def _run_single_numpyro_chain_process( ctx: InferenceContext, @@ -967,18 +1150,215 @@ def run_numpyro_posterior_standalone_processes( "output_dir": out, } +def _safe_plot_name(name: str, max_len: int = 140) -> str: + """Make parameter names safe for filenames.""" + safe = ( + str(name) + .replace("/", "_") + .replace("\\", "_") + .replace("[", "_") + .replace("]", "_") + .replace("(", "_") + .replace(")", "_") + .replace(",", "_") + .replace(" ", "_") + .replace(":", "_") + .replace(";", "_") + ) + return safe[:max_len] -def _plot_posterior(samples: pd.DataFrame, summary: pd.DataFrame, plot_dir: Path) -> None: - numeric = [ - c for c in samples.columns - if pd.api.types.is_numeric_dtype(samples[c]) + +def _smooth_density_1d(values: np.ndarray, grid_size: int = 256) -> tuple[np.ndarray, np.ndarray]: + """Small NumPy-only Gaussian KDE. + + Avoids scipy/seaborn dependency. + Returns x_grid, density. + """ + values = np.asarray(values, dtype=np.float64) + values = values[np.isfinite(values)] + + if values.size == 0: + return np.array([0.0, 1.0]), np.array([0.0, 0.0]) + + if values.size == 1 or np.allclose(values, values[0]): + center = float(values[0]) + span = max(abs(center) * 0.05, 1e-3) + x_grid = np.linspace(center - span, center + span, grid_size) + density = np.exp(-0.5 * ((x_grid - center) / (span / 4.0)) ** 2) + density = density / max(float(density.max()), 1e-12) + return x_grid, density + + vmin = float(np.min(values)) + vmax = float(np.max(values)) + span = vmax - vmin + + pad = 0.1 * span + x_grid = np.linspace(vmin - pad, vmax + pad, grid_size) + + sd = float(np.std(values, ddof=1)) + n = values.size + + # Silverman's rule. Safe fallback for near-zero variance. + bandwidth = 1.06 * sd * (n ** (-1.0 / 5.0)) + bandwidth = max(bandwidth, span / 200.0, 1e-8) + + z = (x_grid[:, None] - values[None, :]) / bandwidth + density = np.exp(-0.5 * z * z).mean(axis=1) + density = density / (bandwidth * np.sqrt(2.0 * np.pi)) + + max_density = float(np.max(density)) + if max_density > 0: + density = density / max_density + + return x_grid, density + + +def _plot_ridgeline_parameter_distributions( + samples: pd.DataFrame, + summary: pd.DataFrame, + plot_dir: Path, + *, + max_params_per_fig: int = 25, + include_sigma: bool = False, +) -> None: + """Plot elegant batched ridgeline posterior distributions. + + Each parameter is normalized to its own posterior range on the x-axis. + This makes the plot readable even when parameters have very different scales. + Individual density plots still preserve the real parameter scale. + """ + ridge_dir = plot_dir / "ridge" + ridge_dir.mkdir(parents=True, exist_ok=True) + + if summary.empty or "parameter" not in summary.columns: + logger.warning("[Posterior] Empty summary; skipping ridgeline posterior plot.") + return + + params = [ + str(p) + for p in summary["parameter"].astype(str).tolist() + if str(p) in samples.columns + and pd.api.types.is_numeric_dtype(samples[str(p)]) ] + if not include_sigma: + params = [p for p in params if p != "sigma"] + + if not params: + logger.warning("[Posterior] No numeric parameters available for ridgeline plot.") + return + + batches = [ + params[i:i + max_params_per_fig] + for i in range(0, len(params), max_params_per_fig) + ] + + for batch_id, batch in enumerate(batches): + fig_height = max(6.0, 0.38 * len(batch) + 1.5) + fig, ax = plt.subplots(figsize=(11, fig_height)) + + y_positions = np.arange(len(batch))[::-1] + + for y, param in zip(y_positions, batch): + values = samples[param].to_numpy(dtype=np.float64) + values = values[np.isfinite(values)] + + if values.size == 0: + continue + + vmin = float(np.min(values)) + vmax = float(np.max(values)) + + if np.isclose(vmin, vmax): + x_norm = np.linspace(0.45, 0.55, 256) + density = np.exp(-0.5 * ((x_norm - 0.5) / 0.015) ** 2) + density = density / max(float(density.max()), 1e-12) + else: + x_grid, density = _smooth_density_1d(values) + x_norm = (x_grid - vmin) / (vmax - vmin) + x_norm = np.clip(x_norm, 0.0, 1.0) + + ridge_height = 0.75 + y_curve = y + ridge_height * density + + ax.fill_between( + x_norm, + y, + y_curve, + alpha=0.55, + linewidth=0.0, + ) + + ax.plot( + x_norm, + y_curve, + linewidth=1.0, + ) + + q05, q50, q95 = np.quantile(values, [0.05, 0.5, 0.95]) + + if not np.isclose(vmin, vmax): + q05n = (q05 - vmin) / (vmax - vmin) + q50n = (q50 - vmin) / (vmax - vmin) + q95n = (q95 - vmin) / (vmax - vmin) + + ax.plot( + [q05n, q95n], + [y + 0.05, y + 0.05], + linewidth=2.0, + ) + + ax.scatter( + [q50n], + [y + 0.05], + s=18, + zorder=3, + ) + + ax.text( + 1.03, + y + 0.05, + f"median={q50:.3g}", + va="center", + ha="left", + fontsize=8, + ) + + ax.set_yticks(y_positions) + ax.set_yticklabels(batch, fontsize=8) + + ax.set_xlim(0.0, 1.22) + ax.set_xlabel("Normalized posterior range per parameter") + ax.set_title("Posterior parameter distributions") + ax.set_frame_on(False) + + ax.tick_params(axis="y", length=0) + ax.grid(axis="x", alpha=0.25) + + fig.tight_layout() + fig.savefig( + ridge_dir / f"posterior_ridge_{batch_id:03d}.png", + dpi=300, + bbox_inches="tight", + ) + plt.close(fig) + +def _plot_posterior(samples: pd.DataFrame, summary: pd.DataFrame, plot_dir: Path) -> None: density_dir = plot_dir / "density" density_dir.mkdir(parents=True, exist_ok=True) - for col in numeric: - values = samples[col].to_numpy() + if summary.empty or "parameter" not in summary.columns: + logger.warning("[Posterior] Empty posterior summary; skipping posterior plots.") + return + + plot_cols = [ + str(p) for p in summary["parameter"].astype(str).tolist() + if str(p) in samples.columns + and pd.api.types.is_numeric_dtype(samples[str(p)]) + ] + + for col in plot_cols: + values = samples[col].to_numpy(dtype=np.float64) fig, ax = plt.subplots(figsize=(6, 4)) ax.plot(values) @@ -998,21 +1378,33 @@ def _plot_posterior(samples: pd.DataFrame, summary: pd.DataFrame, plot_dir: Path fig.savefig(density_dir / f"density_{col}.png", dpi=300) plt.close(fig) - n_params = len(summary) + summary_plot = summary[ + summary["parameter"].astype(str).isin(plot_cols) + ].copy() + + if summary_plot.empty: + logger.warning("[Posterior] No numeric posterior parameters available for interval plot.") + return + + n_params = len(summary_plot) fig_width = max(10, 0.75 * n_params) fig_height = 5 fig, ax = plt.subplots(figsize=(fig_width, fig_height)) - x = range(n_params) + x = np.arange(n_params) + + median = summary_plot["median"].to_numpy(dtype=np.float64) + ci_05 = summary_plot["ci_05"].to_numpy(dtype=np.float64) + ci_95 = summary_plot["ci_95"].to_numpy(dtype=np.float64) ax.errorbar( x, - summary["median"], + median, yerr=[ - summary["median"] - summary["ci_05"], - summary["ci_95"] - summary["median"], + median - ci_05, + ci_95 - median, ], fmt="o", capsize=4, @@ -1020,7 +1412,7 @@ def _plot_posterior(samples: pd.DataFrame, summary: pd.DataFrame, plot_dir: Path ax.set_xticks(list(x)) ax.set_xticklabels( - summary["parameter"].astype(str), + summary_plot["parameter"].astype(str), rotation=60, ha="right", rotation_mode="anchor", @@ -1040,3 +1432,11 @@ def _plot_posterior(samples: pd.DataFrame, summary: pd.DataFrame, plot_dir: Path fig.savefig(plot_dir / "credible_intervals.png", dpi=300) plt.close(fig) + + _plot_ridgeline_parameter_distributions( + samples=samples, + summary=summary, + plot_dir=plot_dir, + max_params_per_fig=25, + include_sigma=False, + ) \ No newline at end of file From 5140ccf5fde39063e7fc500c9138ea83d9777e25 Mon Sep 17 00:00:00 2001 From: bibymaths Date: Fri, 12 Jun 2026 13:36:25 +0200 Subject: [PATCH 23/42] fix: directories path --- networkmodel/dashboard_bundle.py | 4 ++-- scripts/compare_mechanisms.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/networkmodel/dashboard_bundle.py b/networkmodel/dashboard_bundle.py index fd942af..10cf060 100644 --- a/networkmodel/dashboard_bundle.py +++ b/networkmodel/dashboard_bundle.py @@ -76,7 +76,7 @@ def save_dashboard_bundle( "df_pho_obs": df_pho, } - bundle_path = out / "dashboard_bundle.pkl" + bundle_path = out / "artifacts" / "dashboard_bundle.pkl" with bundle_path.open("wb") as f: pickle.dump(bundle, f, protocol=pickle.HIGHEST_PROTOCOL) @@ -92,6 +92,6 @@ def load_dashboard_bundle(output_dir: str | Path) -> dict: Returns: Computed result from this routine. """ - p = Path(output_dir) / "dashboard_bundle.pkl" + p = Path(output_dir) / "artifacts" / "dashboard_bundle.pkl" with p.open("rb") as f: return pickle.load(f) diff --git a/scripts/compare_mechanisms.py b/scripts/compare_mechanisms.py index 388a877..e34ebbd 100644 --- a/scripts/compare_mechanisms.py +++ b/scripts/compare_mechanisms.py @@ -178,7 +178,7 @@ def load_system(): # IMPORTANT: ensure model selection matches run *before* building System config.MODEL = 0 - results_dir = Path("./results_model_global_distributive") + results_dir = Path("./results_network_distributive") class Args: kinase_net, tf_net = config.KINASE_NET_FILE, config.TF_NET_FILE From e2e3016a8135f910346b053fc58b94e98ae44c7e Mon Sep 17 00:00:00 2001 From: bibymaths Date: Fri, 12 Jun 2026 13:39:46 +0200 Subject: [PATCH 24/42] fix: posterior params conversion fix --- networkmodel/BayesianInference.py | 304 +++++++++++++++++------------- 1 file changed, 168 insertions(+), 136 deletions(-) diff --git a/networkmodel/BayesianInference.py b/networkmodel/BayesianInference.py index 799bd6c..163be36 100644 --- a/networkmodel/BayesianInference.py +++ b/networkmodel/BayesianInference.py @@ -584,12 +584,37 @@ def _plot_profile(df: pd.DataFrame, path: Path) -> None: fig.savefig(path, dpi=300) plt.close(fig) -def _requires_nonnegative_posterior_support(name: str) -> bool: - """Return True for model parameters that are physically non-negative. +def _np_softplus(x: np.ndarray) -> np.ndarray: + """Stable NumPy softplus: log(1 + exp(x)).""" + x = np.asarray(x, dtype=np.float64) + return np.log1p(np.exp(-np.abs(x))) + np.maximum(x, 0.0) - These are kinetic/rate/scale parameters. Signed regulatory parameters, - if any, are intentionally left unconstrained. - """ + +def _theta_to_unit_interval(theta, lower, upper, *, eps: float = 1e-6) -> np.ndarray: + """Map raw theta into unit interval for NumPyro initialization.""" + theta = np.asarray(theta, dtype=np.float64) + lower = np.asarray(lower, dtype=np.float64) + upper = np.asarray(upper, dtype=np.float64) + + width = upper - lower + + if np.any(~np.isfinite(lower)) or np.any(~np.isfinite(upper)): + bad = np.where(~np.isfinite(lower) | ~np.isfinite(upper))[0].tolist() + raise ValueError( + f"Posterior raw bounds contain non-finite values at indices: {bad}. " + "Check inv_softplus(0.0); use a small positive lower bound such as 1e-8." + ) + + if np.any(width <= 0): + bad = np.where(width <= 0)[0].tolist() + raise ValueError(f"Posterior raw bounds have upper <= lower at indices: {bad}") + + unit = (theta - lower) / width + return np.clip(unit, eps, 1.0 - eps) + + +def _is_softplus_raw_parameter(name: str) -> bool: + """Parameters stored in theta as raw softplus coordinates.""" name = str(name) return ( @@ -604,117 +629,42 @@ def _requires_nonnegative_posterior_support(name: str) -> bool: ) -def _sanitize_numpyro_posterior_bounds( - lower, - upper, - names, - *, - eps: float = 1e-8, -) -> tuple[np.ndarray, np.ndarray]: - """Sanitize posterior bounds before constructing NumPyro priors. - - NumPyro samples directly from these bounds. Therefore, for parameters that - are physically non-negative, the posterior lower bound must be >= 0. - - This function intentionally raises on impossible intervals rather than - silently producing invalid posterior samples. - """ - lower = np.asarray(lower, dtype=np.float64).copy() - upper = np.asarray(upper, dtype=np.float64).copy() - names = list(names) - - if len(names) != len(lower): - raise ValueError( - f"Parameter name count does not match bounds: " - f"len(names)={len(names)}, len(lower)={len(lower)}" - ) - - if lower.shape != upper.shape: - raise ValueError( - f"Posterior lower/upper shape mismatch: " - f"lower={lower.shape}, upper={upper.shape}" - ) +def _raw_theta_samples_to_physical_df( + theta_raw_samples: np.ndarray, + names: Sequence[str], +) -> pd.DataFrame: + """Convert raw posterior theta samples to physical parameter samples.""" + theta_raw_samples = np.asarray(theta_raw_samples, dtype=np.float64) - bad_finite = ~np.isfinite(lower) | ~np.isfinite(upper) - if np.any(bad_finite): - bad_names = [names[i] for i in np.where(bad_finite)[0]] - raise ValueError( - "Posterior bounds contain non-finite values for parameters: " - f"{bad_names}" - ) + out = {} for i, name in enumerate(names): - if _requires_nonnegative_posterior_support(name): - if upper[i] <= 0.0: - raise ValueError( - f"Invalid posterior bounds for non-negative parameter {name}: " - f"lower={lower[i]}, upper={upper[i]}. " - "The upper bound must be > 0. Fix calculate_bio_bounds() " - "or init_raw_params() upstream." - ) - - lower[i] = max(lower[i], 0.0) - - if upper[i] <= lower[i]: - raise ValueError( - f"Invalid posterior interval for non-negative parameter {name}: " - f"lower={lower[i]}, upper={upper[i]}." - ) - - bad_interval = upper <= lower - if np.any(bad_interval): - bad_names = [names[i] for i in np.where(bad_interval)[0]] - raise ValueError( - "Posterior bounds contain invalid intervals with upper <= lower: " - f"{bad_names}" - ) - - too_narrow = (upper - lower) < eps - if np.any(too_narrow): - bad_names = [names[i] for i in np.where(too_narrow)[0]] - raise ValueError( - "Posterior bounds are too narrow for stable NUTS initialization: " - f"{bad_names}" - ) - - return lower, upper - - -def _make_interior_initial_value(theta0, lower, upper, *, eps: float = 1e-8) -> np.ndarray: - """Clip theta0 safely inside the NumPyro Uniform support.""" - theta0 = np.asarray(theta0, dtype=np.float64) - lower = np.asarray(lower, dtype=np.float64) - upper = np.asarray(upper, dtype=np.float64) - - width = upper - lower - interior_eps = np.minimum(eps, 0.25 * width) + if _is_softplus_raw_parameter(name): + out[name] = _np_softplus(theta_raw_samples[:, i]) + else: + out[name] = theta_raw_samples[:, i] - return np.clip( - theta0, - lower + interior_eps, - upper - interior_eps, - ) + return pd.DataFrame(out) -def _assert_no_negative_nonnegative_samples(sample_df: pd.DataFrame, names: Sequence[str]) -> None: - """Fail if NumPyro produced negative samples for non-negative parameters.""" - nonnegative_cols = [ +def _assert_physical_samples_valid(sample_df: pd.DataFrame, names: Sequence[str]) -> None: + """Check that softplus-constrained parameters are non-negative after transform.""" + cols = [ name for name in names - if name in sample_df.columns and _requires_nonnegative_posterior_support(name) + if name in sample_df.columns and _is_softplus_raw_parameter(name) ] - if not nonnegative_cols: + if not cols: return - mins = sample_df[nonnegative_cols].min(axis=0) - leaked = mins[mins < -1e-10] + mins = sample_df[cols].min(axis=0) + bad = mins[mins < -1e-12] - if not leaked.empty: + if not bad.empty: raise RuntimeError( - "Posterior produced negative samples for parameters that should be " - f"non-negative: {leaked.to_dict()}" + "Physical posterior samples contain negative values after softplus " + f"conversion: {bad.to_dict()}" ) - def run_numpyro_posterior( ctx: InferenceContext, *, @@ -743,27 +693,39 @@ def run_numpyro_posterior( names = _param_names(len(ctx.theta0), ctx.parameter_names) - lower_np = np.asarray(ctx.lower, dtype=np.float64).copy() - upper_np = np.asarray(ctx.upper, dtype=np.float64).copy() + lower_raw_np = np.asarray(ctx.lower, dtype=np.float64).copy() + upper_raw_np = np.asarray(ctx.upper, dtype=np.float64).copy() + theta0_raw_np = np.asarray(ctx.theta0, dtype=np.float64).copy() - # Critical fix: - # NumPyro samples directly from these bounds, so physical non-negativity - # must be enforced before constructing the Uniform prior. - lower_np, upper_np = _sanitize_numpyro_posterior_bounds( - lower_np, - upper_np, - names, - ) + width_raw_np = upper_raw_np - lower_raw_np + + if np.any(~np.isfinite(lower_raw_np)) or np.any(~np.isfinite(upper_raw_np)): + bad = np.where(~np.isfinite(lower_raw_np) | ~np.isfinite(upper_raw_np))[0] + bad_names = [names[i] for i in bad] + raise ValueError( + "Posterior raw bounds contain non-finite values for parameters: " + f"{bad_names}. " + "Likely cause: inv_softplus(0.0). Use lower bound 1e-8 instead of 0.0." + ) + + if np.any(width_raw_np <= 0): + bad = np.where(width_raw_np <= 0)[0] + bad_names = [names[i] for i in bad] + raise ValueError( + f"Posterior raw bounds have upper <= lower for parameters: {bad_names}" + ) - theta_center_np = _make_interior_initial_value( - ctx.theta0, - lower_np, - upper_np, + theta_unit_center_np = _theta_to_unit_interval( + theta0_raw_np, + lower_raw_np, + upper_raw_np, ) - theta_center = jnp.asarray(theta_center_np, dtype=jnp.float64) - lower = jnp.asarray(lower_np, dtype=jnp.float64) - upper = jnp.asarray(upper_np, dtype=jnp.float64) + lower_raw = jnp.asarray(lower_raw_np, dtype=jnp.float64) + upper_raw = jnp.asarray(upper_raw_np, dtype=jnp.float64) + width_raw = upper_raw - lower_raw + + theta_unit_center = jnp.asarray(theta_unit_center_np, dtype=jnp.float64) if ctx.fixed_mask is not None: fixed_mask_np = np.asarray(ctx.fixed_mask, dtype=bool) @@ -771,29 +733,38 @@ def run_numpyro_posterior( fixed_mask_np = None if ctx.fixed_values is not None: - fixed_values_np = _make_interior_initial_value( - ctx.fixed_values, - lower_np, - upper_np, + fixed_values_raw_np = np.clip( + np.asarray(ctx.fixed_values, dtype=np.float64), + lower_raw_np, + upper_raw_np, ) else: - fixed_values_np = None + fixed_values_raw_np = None def model(): - theta = numpyro.sample( - "theta", - dist.Uniform(lower, upper).to_event(1), + # Sample in unit box, then map into valid raw softplus-theta bounds. + theta_unit = numpyro.sample( + "theta_unit", + dist.Uniform( + jnp.zeros_like(lower_raw), + jnp.ones_like(upper_raw), + ).to_event(1), ) - if fixed_mask_np is not None and fixed_values_np is not None: + theta_raw = lower_raw + width_raw * theta_unit + + if fixed_mask_np is not None and fixed_values_raw_np is not None: fixed_mask = jnp.asarray(fixed_mask_np, dtype=bool) - fixed_values = jnp.asarray(fixed_values_np, dtype=jnp.float64) - theta = jnp.where(fixed_mask, fixed_values, theta) + fixed_values_raw = jnp.asarray(fixed_values_raw_np, dtype=jnp.float64) + theta_raw = jnp.where(fixed_mask, fixed_values_raw, theta_raw) sigma = numpyro.sample("sigma", dist.Exponential(1.0)) - objective = ctx.objective_fun(theta) + # Important: + # objective_fun expects raw softplus theta, not physical theta. + objective = ctx.objective_fun(theta_raw) + numpyro.deterministic("theta_raw", theta_raw) numpyro.deterministic("scalar_objective", objective) numpyro.factor( @@ -804,7 +775,7 @@ def model(): kernel = NUTS( model, init_strategy=numpyro.infer.init_to_value( - values={"theta": theta_center} + values={"theta_unit": theta_unit_center} ), ) @@ -832,8 +803,44 @@ def model(): samples = mcmc.get_samples(group_by_chain=False) - theta_samples = np.asarray(samples["theta"], dtype=np.float64) - sample_df = pd.DataFrame(theta_samples, columns=names) + if "theta_raw" in samples: + theta_raw_samples = np.asarray(samples["theta_raw"], dtype=np.float64) + else: + theta_unit_samples = np.asarray(samples["theta_unit"], dtype=np.float64) + theta_raw_samples = lower_raw_np + width_raw_np * theta_unit_samples + + if fixed_mask_np is not None and fixed_values_raw_np is not None: + theta_raw_samples[:, fixed_mask_np] = fixed_values_raw_np[fixed_mask_np] + + # Safety check: raw samples must stay inside raw bounds. + theta_raw_min = theta_raw_samples.min(axis=0) + theta_raw_max = theta_raw_samples.max(axis=0) + + below = theta_raw_min < (lower_raw_np - 1e-10) + above = theta_raw_max > (upper_raw_np + 1e-10) + + if np.any(below) or np.any(above): + bad = np.where(below | above)[0] + bad_names = [names[i] for i in bad] + raise RuntimeError( + "Raw posterior samples escaped saved raw bounds for parameters: " + f"{bad_names}" + ) + + raw_sample_df = pd.DataFrame(theta_raw_samples, columns=names) + raw_sample_df["sigma"] = np.asarray(samples["sigma"], dtype=np.float64) + + if "scalar_objective" in samples: + raw_sample_df["scalar_objective"] = np.asarray( + samples["scalar_objective"], + dtype=np.float64, + ) + + raw_sample_df["data_mode"] = ctx.mode.data_mode + raw_sample_df.to_csv(out / "posterior_samples_raw.csv", index=False) + + # Main posterior output: physical biological parameter scale. + sample_df = _raw_theta_samples_to_physical_df(theta_raw_samples, names) sample_df["sigma"] = np.asarray(samples["sigma"], dtype=np.float64) @@ -845,8 +852,7 @@ def model(): sample_df["data_mode"] = ctx.mode.data_mode - # Fail loudly if anything escaped the intended physical support. - _assert_no_negative_nonnegative_samples(sample_df, names) + _assert_physical_samples_valid(sample_df, names) sample_df.to_csv(out / "posterior_samples.csv", index=False) @@ -866,12 +872,36 @@ def model(): "ess": float(len(vals)), "r_hat": np.nan, "data_mode": ctx.mode.data_mode, + "scale": "physical", } ) summary = pd.DataFrame(summary_rows) summary.to_csv(out / "posterior_summary.csv", index=False) + raw_summary_rows = [] + + for col in names + ["sigma"]: + vals = raw_sample_df[col].to_numpy(dtype=np.float64) + + raw_summary_rows.append( + { + "parameter": col, + "mean": float(vals.mean()), + "median": float(np.median(vals)), + "sd": float(vals.std(ddof=0)), + "ci_05": float(np.quantile(vals, 0.05)), + "ci_95": float(np.quantile(vals, 0.95)), + "ess": float(len(vals)), + "r_hat": np.nan, + "data_mode": ctx.mode.data_mode, + "scale": "raw_softplus", + } + ) + + raw_summary = pd.DataFrame(raw_summary_rows) + raw_summary.to_csv(out / "posterior_summary_raw.csv", index=False) + if "scalar_objective" in sample_df.columns: predictive = sample_df[["scalar_objective", "data_mode"]].copy() else: @@ -883,7 +913,9 @@ def model(): return { "samples": sample_df, + "raw_samples": raw_sample_df, "summary": summary, + "raw_summary": raw_summary, "posterior_predictive": predictive, "output_dir": out, } From ab909f254de20f0ed2272cbbc7e84c909834c8f2 Mon Sep 17 00:00:00 2001 From: bibymaths Date: Fri, 12 Jun 2026 13:59:51 +0200 Subject: [PATCH 25/42] fix: network sweep and forward simulation --- scripts/compare_mechanisms.py | 2328 +++++++++++++++++++-------------- 1 file changed, 1352 insertions(+), 976 deletions(-) diff --git a/scripts/compare_mechanisms.py b/scripts/compare_mechanisms.py index e34ebbd..fbcde2d 100644 --- a/scripts/compare_mechanisms.py +++ b/scripts/compare_mechanisms.py @@ -288,6 +288,56 @@ def run_sim(sys, idx, mod_params): return simulate_and_measure(sys, idx, config.TIME_POINTS_PROTEIN, config.TIME_POINTS_RNA, config.TIME_POINTS_PHOSPHO) +def extract_fc_from_Y(Y, idx, t, protein, normalize=True): + """Extract RNA, total protein, and phospho-site trajectories for one protein.""" + p_idx = idx.p2i[protein] + st_y = idx.offset_y[p_idx] + + rna_vals = Y[:, st_y] + prot_vals = Y[:, st_y + 1] + + ns = idx.n_sites[p_idx] + site_names = idx.sites[p_idx] + + if ns > 0: + psite_vals = Y[:, st_y + 2: st_y + 2 + ns] + phos_sum = np.sum(psite_vals, axis=1) + total_prot = prot_vals + phos_sum + else: + psite_vals = np.zeros((len(t), 0)) + total_prot = prot_vals + + if normalize: + rna_base = rna_vals[0] if abs(rna_vals[0]) > 1e-12 else 1.0 + prot_base = total_prot[0] if abs(total_prot[0]) > 1e-12 else 1.0 + + rna_vals = rna_vals / rna_base + total_prot = total_prot / prot_base + + if ns > 0: + site_base = psite_vals[0, :].copy() + site_base[np.abs(site_base) < 1e-12] = 1.0 + psite_vals = psite_vals / site_base + + df = pd.DataFrame( + { + "time": t, + "rna": rna_vals, + "protein": total_prot, + } + ) + + if ns > 0: + df_ps = pd.DataFrame(psite_vals, columns=site_names) + df_ps["time"] = t + df_long = df_ps.melt( + id_vars="time", + var_name="psite", + value_name="psite_value", + ) + df = df.merge(df_long, on="time", how="left") + + return df # --- UI Setup --- st.title("🧪 Global Signaling & Transcriptional Knockout Explorer") @@ -596,195 +646,207 @@ def restore_Kinase(): options=[250, 500, 1000, 2500, 5000, 10000], value=1000, ) - run_forward_panel = st.button( "Run detailed WT/KO forward simulation", key="run-forward-simulation-panel", ) -if not run_forward_panel: - st.info("Click the button above to run the detailed forward simulation panel.") - st.stop() - -with st.spinner(f"Running WT forward simulation with {n_points} time points..."): - sys.update(**best_params) - t_fine, Y_wt = simulate_until_steady(sys, t_max=t_max, n_points=n_points) - -# Extract per-protein output -def extract_fc_from_Y(Y, idx, t, protein, normalize=True): - """ - Extracts and processes feature components from a dataset for a given protein. - - This function retrieves RNA, protein, and phosphorylation site data associated with - a specified protein from a dataset. It supports normalization of input data and - returns a processed DataFrame containing time-series data for RNA, total protein, - and (if available) phosphorylation site values. - - Args: - Y: ndarray - Input dataset containing RNA, protein, and phosphorylation site measurements. - The dimensions of `Y` include time points as rows and feature components as - columns. - idx: object - An""" - p_idx = idx.p2i[protein] - st_y = idx.offset_y[p_idx] - rna_vals = Y[:, st_y] - prot_vals = Y[:, st_y + 1] - ns = idx.n_sites[p_idx] - site_names = idx.sites[p_idx] - - if ns > 0: - psite_vals = Y[:, st_y + 2: st_y + 2 + ns] - phos_sum = np.sum(psite_vals, axis=1) - total_prot = prot_vals + phos_sum - else: - psite_vals = np.zeros((len(t), 0)) - total_prot = prot_vals - - if normalize: - rna_vals = rna_vals / rna_vals[0] - total_prot = total_prot / total_prot[0] - if ns > 0: - psite_vals = psite_vals / psite_vals[0, :] # normalize each site - - # Base result - df = pd.DataFrame({ - "time": t, - "rna": rna_vals, - "protein": total_prot, - }) - - # Add phospho sites in long format - if ns > 0: - df_ps = pd.DataFrame(psite_vals, columns=site_names) - df_ps["time"] = t - df_long = df_ps.melt(id_vars="time", var_name="psite", value_name="psite_value") - df = df.merge(df_long, on="time", how="left") - - return df +forward_cache_key = ( + selected_p, + float(t_max), + int(n_points), + str(ko_type), + str(target), + float(scale) if ko_type != "None" else 1.0, +) +if run_forward_panel: + with st.spinner(f"Running WT forward simulation with {n_points} time points..."): + sys.update(**best_params) + t_fine, Y_wt = simulate_until_steady(sys, t_max=t_max, n_points=n_points) -# WT values -df_wt = extract_fc_from_Y(Y_wt, idx, t_fine, selected_p) + with st.spinner(f"Running KO forward simulation with {n_points} time points..."): + sys.update(**ko_params) + t_ko, Y_ko = simulate_until_steady(sys, t_max=t_max, n_points=n_points) -with st.spinner(f"Running KO forward simulation with {n_points} time points..."): - sys.update(**ko_params) - t_ko, Y_ko = simulate_until_steady(sys, t_max=t_max, n_points=n_points) + sys.update(**best_params) -df_ko = extract_fc_from_Y(Y_ko, idx, t_ko, selected_p) + st.session_state["forward_panel_cache_key"] = forward_cache_key + st.session_state["forward_panel_results"] = { + "t_fine": t_fine, + "Y_wt": Y_wt, + "t_ko": t_ko, + "Y_ko": Y_ko, + } -# Restore baseline after KO simulation. -sys.update(**best_params) +has_forward_results = ( + st.session_state.get("forward_panel_cache_key") == forward_cache_key + and "forward_panel_results" in st.session_state +) -# --- Plot mRNA -col1, col2 = st.columns(2) +if not has_forward_results: + st.info("Click **Run detailed WT/KO forward simulation** to show the detailed simulation panel.") +else: + cached = st.session_state["forward_panel_results"] -with col1: - fig_fine_r = go.Figure() - fig_fine_r.add_trace(go.Scatter(x=df_wt["time"], y=df_wt["rna"], name="WT", line=dict(color="black", dash="dash"))) - fig_fine_r.add_trace(go.Scatter(x=df_ko["time"], y=df_ko["rna"], name="KO", line=dict(color="red"))) - fig_fine_r.update_layout(title="mRNA Simulation", xaxis_title="Time", yaxis_title="Fold Change", - template="plotly_white") - fig_fine_r.update_xaxes(type="log") - st.plotly_chart(fig_fine_r, use_container_width=True) + t_fine = cached["t_fine"] + Y_wt = cached["Y_wt"] + t_ko = cached["t_ko"] + Y_ko = cached["Y_ko"] -# --- Plot Protein -with col2: - fig_fine_p = go.Figure() - fig_fine_p.add_trace( - go.Scatter(x=df_wt["time"], y=df_wt["protein"], name="WT", line=dict(color="black", dash="dash"))) - fig_fine_p.add_trace(go.Scatter(x=df_ko["time"], y=df_ko["protein"], name="KO", line=dict(color="blue"))) - fig_fine_p.update_layout(title="Protein Simulation", xaxis_title="Time", yaxis_title="Fold Change", - template="plotly_white") - fig_fine_p.update_xaxes(type="log") - st.plotly_chart(fig_fine_p, use_container_width=True) + df_wt = extract_fc_from_Y(Y_wt, idx, t_fine, selected_p) + df_ko = extract_fc_from_Y(Y_ko, idx, t_ko, selected_p) -col1, col2 = st.columns(2) + # --- Plot mRNA + col1, col2 = st.columns(2) -# --- Signaling Drive Panel (Phosphorylation S) -with col1: - if selected_p in idx.p2i: - p_idx = idx.p2i[selected_p] - ns = idx.n_sites[p_idx] - - # Simulate WT again (ensures S is from WT context) - t_S, Y_S = t_ko, Y_ko # Use already simulated KO values - kin_vals = Y_S[:, [idx.k2i[k] for k in idx.kinases]].T # (n_kinases, time) - kin_scaled = kin_vals * sys.c_k[:, None] - S_t = sys.W_global @ kin_scaled # (n_sites, time) - - site_names, site_rows = [], [] - - # Recompute correct global site indices for selected_p - site_counter = 0 - for i, p in enumerate(idx.proteins): - for j, site in enumerate(idx.sites[i]): - if p == selected_p: - site_names.append(site) - site_rows.append(site_counter) - site_counter += 1 - - fig_s_time = go.Figure() - - for site_name, site_idx in zip(site_names, site_rows): - color = px.colors.qualitative.Plotly[hash(site_name) % len(px.colors.qualitative.Plotly)] - fig_s_time.add_trace(go.Scatter( - x=t_S, - y=S_t[site_idx, :], - name=site_name, - mode="lines", - line=dict(dash="solid", color=color), - opacity=0.9, - )) - - fig_s_time.update_layout( - title=f"{selected_p} – Phosphorylation (S)", - xaxis_title="Time (min)", - yaxis_title="S (Signaling Rate)", - template="plotly_white" + with col1: + fig_fine_r = go.Figure() + fig_fine_r.add_trace( + go.Scatter( + x=df_wt["time"], + y=df_wt["rna"], + name="WT", + line=dict(color="black", dash="dash"), + ) ) - fig_s_time.update_xaxes(type="log") - st.plotly_chart(fig_s_time, use_container_width=True) - else: - st.warning(f"{selected_p} not found in protein index.") + fig_fine_r.add_trace( + go.Scatter( + x=df_ko["time"], + y=df_ko["rna"], + name="KO", + line=dict(color="red"), + ) + ) + fig_fine_r.update_layout( + title="mRNA Simulation", + xaxis_title="Time", + yaxis_title="Fold Change", + template="plotly_white", + ) + fig_fine_r.update_xaxes(type="log") + st.plotly_chart(fig_fine_r, use_container_width=True) -# Plot Phospho-sites states from simulation -with col2: - fig_sites_fine = go.Figure() + # --- Plot Protein + with col2: + fig_fine_p = go.Figure() + fig_fine_p.add_trace( + go.Scatter( + x=df_wt["time"], + y=df_wt["protein"], + name="WT", + line=dict(color="black", dash="dash"), + ) + ) + fig_fine_p.add_trace( + go.Scatter( + x=df_ko["time"], + y=df_ko["protein"], + name="KO", + line=dict(color="blue"), + ) + ) + fig_fine_p.update_layout( + title="Protein Simulation", + xaxis_title="Time", + yaxis_title="Fold Change", + template="plotly_white", + ) + fig_fine_p.update_xaxes(type="log") + st.plotly_chart(fig_fine_p, use_container_width=True) + + col1, col2 = st.columns(2) + + # --- Signaling Drive Panel + with col1: + if selected_p in idx.p2i: + t_S, Y_S = t_ko, Y_ko + + kin_vals = Y_S[:, [idx.k2i[k] for k in idx.kinases]].T + kin_scaled = kin_vals * sys.c_k[:, None] + S_t = sys.W_global @ kin_scaled + + site_names, site_rows = [], [] + site_counter = 0 + + for i, p in enumerate(idx.proteins): + for site in idx.sites[i]: + if p == selected_p: + site_names.append(site) + site_rows.append(site_counter) + site_counter += 1 + + fig_s_time = go.Figure() + + for site_name, site_idx in zip(site_names, site_rows): + color = px.colors.qualitative.Plotly[ + hash(site_name) % len(px.colors.qualitative.Plotly) + ] + fig_s_time.add_trace( + go.Scatter( + x=t_S, + y=S_t[site_idx, :], + name=site_name, + mode="lines", + line=dict(dash="solid", color=color), + opacity=0.9, + ) + ) - # Safety check for valid data - if "psite" in df_wt.columns and not df_wt["psite"].isna().all(): - for site in df_wt["psite"].dropna().unique(): - site_wt = df_wt[df_wt["psite"] == site] - site_ko = df_ko[df_ko["psite"] == site] - color = px.colors.qualitative.Plotly[hash(site) % len(px.colors.qualitative.Plotly)] + fig_s_time.update_layout( + title=f"{selected_p} – Phosphorylation (S)", + xaxis_title="Time (min)", + yaxis_title="S (Signaling Rate)", + template="plotly_white", + ) + fig_s_time.update_xaxes(type="log") + st.plotly_chart(fig_s_time, use_container_width=True) + else: + st.warning(f"{selected_p} not found in protein index.") + + # --- Phospho-site state panel + with col2: + fig_sites_fine = go.Figure() + + if "psite" in df_wt.columns and not df_wt["psite"].isna().all(): + for site in df_wt["psite"].dropna().unique(): + site_wt = df_wt[df_wt["psite"] == site] + site_ko = df_ko[df_ko["psite"] == site] + + color = px.colors.qualitative.Plotly[ + hash(site) % len(px.colors.qualitative.Plotly) + ] + + if not site_wt.empty: + fig_sites_fine.add_trace( + go.Scatter( + x=site_wt["time"], + y=site_wt["psite_value"], + name=f"WT {site}", + line=dict(dash="dash", color=color), + ) + ) + + if not site_ko.empty: + fig_sites_fine.add_trace( + go.Scatter( + x=site_ko["time"], + y=site_ko["psite_value"], + name=f"KO {site}", + line=dict(color=color), + ) + ) - if not site_wt.empty: - fig_sites_fine.add_trace(go.Scatter( - x=site_wt["time"], - y=site_wt["psite_value"], - name=f"WT {site}", - line=dict(dash="dash", color=color) - )) - if not site_ko.empty: - fig_sites_fine.add_trace(go.Scatter( - x=site_ko["time"], - y=site_ko["psite_value"], - name=f"KO {site}", - line=dict(color=color) - )) - - fig_sites_fine.update_layout( - title=f"{selected_p} Phospho-site State Dynamics", - xaxis_title="Time (min)", - yaxis_title="Phospho-site Level (a.u.)", - template="plotly_white" - ) - fig_sites_fine.update_xaxes(type="log") - st.plotly_chart(fig_sites_fine, use_container_width=True) - else: - st.info("No phospho site data available for this protein.") + fig_sites_fine.update_layout( + title=f"{selected_p} Phospho-site State Dynamics", + xaxis_title="Time (min)", + yaxis_title="Phospho-site Level (a.u.)", + template="plotly_white", + ) + fig_sites_fine.update_xaxes(type="log") + st.plotly_chart(fig_sites_fine, use_container_width=True) + else: + st.info("No phospho site data available for this protein.") st.divider() @@ -2120,810 +2182,1124 @@ def _prepare_edges_for_mode_at_time(mode: str, t_eval_local: float): key="sweep_edges_csv", ) -# # ========================= -# # TIME-RESOLVED ANIMATED NETWORK (pre-steady state) -# # ========================= +# ========================= +# TIME-RESOLVED ANIMATED NETWORK (pre-steady-state) +# Button-driven + session-state cached. +# Does NOT recompute on every Streamlit rerun. +# ========================= -# # ------------------------- -# # SAFE animation export (no kaleido hard-fail) -# # ------------------------- -# def _export_plotly_animation(fig: go.Figure, fmt: str = "gif", fps: int = 6, scale: int = 2) -> bytes: -# """ -# Render Plotly animation frames -> GIF/MP4 bytes. -# -# Preferred: Plotly+kaleido (fig.to_image). -# Fallback: raises a clean RuntimeError with actionable instructions. -# -# Notes: -# - GIF: uses imageio.mimsave -# - MP4: requires ffmpeg available to imageio (imageio-ffmpeg) -# """ -# frames = list(fig.frames or []) -# if not frames: -# raise RuntimeError("No frames found in the figure. Nothing to export.") -# -# images = [] -# for fr in frames: -# f = go.Figure(data=fr.data, layout=fig.layout) -# try: -# png_bytes = f.to_image(format="png", scale=scale, engine="kaleido") -# except Exception as e: -# raise RuntimeError( -# "Export requires Plotly image export support (kaleido). " -# "If kaleido is installed but Plotly can't see it, ensure you are installing it " -# "inside the SAME environment where Streamlit runs.\n" -# "Conda: conda install -c conda-forge python-kaleido\n" -# "Pip: pip install -U kaleido\n" -# f"Original error: {repr(e)}" -# ) -# images.append(imageio.imread(png_bytes)) -# -# buf = io.BytesIO() -# -# fmt_l = fmt.lower() -# if fmt_l == "gif": -# imageio.mimsave(buf, images, format="GIF", fps=fps) -# return buf.getvalue() -# -# if fmt_l == "mp4": -# # imageio writes mp4 via ffmpeg -# writer = imageio.get_writer(buf, format="FFMPEG", mode="I", fps=fps, codec="libx264") -# for im in images: -# writer.append_data(im) -# writer.close() -# return buf.getvalue() -# -# raise ValueError("fmt must be 'gif' or 'mp4'") -# -# -# # ------------------------- -# # State extractors -# # ------------------------- -# def _extract_mrna_vec_from_y(y_row: np.ndarray, idx: Index) -> np.ndarray: -# out = np.zeros(len(idx.proteins), dtype=float) -# for i in range(len(idx.proteins)): -# st_y = idx.offset_y[i] -# out[i] = float(y_row[st_y + 0]) -# return out -# -# -# def _extract_total_protein_vec_from_y(y_row: np.ndarray, idx: Index) -> np.ndarray: -# out = np.zeros(len(idx.proteins), dtype=float) -# for i in range(len(idx.proteins)): -# st_y = idx.offset_y[i] -# prot = float(y_row[st_y + 1]) -# ns = int(idx.n_sites[i]) -# if ns > 0: -# phos_sum = float(np.sum(y_row[st_y + 2 : st_y + 2 + ns])) -# out[i] = prot + phos_sum -# else: -# out[i] = prot -# return out -# -# -# def _delta_log2_fc(ko: np.ndarray, wt: np.ndarray, eps: float = 1e-9) -> np.ndarray: -# """log2(KO/WT)""" -# return np.log2((ko + eps) / (wt + eps)) -# -# -# def _total_protein_from_Y_row(y_row: np.ndarray, idx: Index, protein: str) -> float: -# p_i = idx.p2i[protein] -# st_y = idx.offset_y[p_i] -# prot = float(y_row[st_y + 1]) -# ns = int(idx.n_sites[p_i]) -# if ns > 0: -# return prot + float(np.sum(y_row[st_y + 2 : st_y + 2 + ns])) -# return prot -# -# -# # ------------------------- -# # Edges at time t -# # ------------------------- -# def _edge_tables_at_time( -# sys: System, -# idx: Index, -# df_tf_model: pd.DataFrame | None, -# y_row: np.ndarray, -# t: float, -# ) -> tuple[pd.DataFrame, pd.DataFrame]: -# """ -# signaling: kinase -> protein, weight = Σ_sites beta(site,k) * Kt_k(t) -# transcription: tf -> target, weight = tf_scale * tf_mat[target,tf] * TF_total(t) -# """ -# # --- signaling --- -# Kt = sys.kin.eval(float(t)) * sys.c_k # (nK,) -# W = sys.W_global.tocoo() -# edge_contrib = W.data * Kt[W.col] # per-site contribution -# -# prot_idx = np.searchsorted(idx.offset_s, W.row, side="right") - 1 -# prot_idx = np.clip(prot_idx, 0, len(idx.proteins) - 1) -# -# df_sig = pd.DataFrame( -# { -# "src": np.asarray(idx.kinases, dtype=object)[W.col], -# "tgt": np.asarray(idx.proteins, dtype=object)[prot_idx], -# "weight": edge_contrib.astype(float), -# } -# ) -# df_sig = df_sig.groupby(["src", "tgt"], as_index=False).agg(weight=("weight", "sum")) -# df_sig["type"] = "signaling" -# -# # --- transcription --- -# df_tf_edges = pd.DataFrame(columns=["src", "tgt", "weight", "type"]) -# if df_tf_model is not None and not df_tf_model.empty: -# tf_mat = sys.tf_mat -# tf_scale = float(getattr(sys, "tf_scale", 1.0)) -# -# rows = [] -# for r in df_tf_model.itertuples(index=False): -# tf = getattr(r, "tf") -# tgt = getattr(r, "target") -# if tf not in idx.p2i or tgt not in idx.p2i: -# continue -# -# i_tgt = idx.p2i[tgt] -# j_tf = idx.p2i[tf] -# -# try: -# coeff = float(tf_mat[i_tgt, j_tf]) -# except Exception: -# coeff = float(np.asarray(tf_mat[i_tgt, j_tf]).squeeze()) -# -# if abs(coeff) < 1e-14: -# continue -# -# tf_level = _total_protein_from_Y_row(y_row, idx, tf) -# drive = tf_scale * coeff * tf_level -# rows.append((tf, tgt, float(drive))) -# -# if rows: -# df_tf_edges = pd.DataFrame(rows, columns=["src", "tgt", "weight"]) -# df_tf_edges["type"] = "transcription" -# -# return df_sig, df_tf_edges -# -# -# def _filter_edges( -# df_sig: pd.DataFrame, -# df_tf: pd.DataFrame, -# include_tf: bool, -# min_abs_w: float, -# top_k: int, -# edge_scale: float = 1.0, -# ) -> pd.DataFrame: -# df_all = df_sig.copy() -# if include_tf and df_tf is not None and not df_tf.empty: -# df_all = pd.concat([df_all, df_tf], ignore_index=True) -# -# if df_all.empty: -# return df_all -# -# df_all["weight"] = pd.to_numeric(df_all["weight"], errors="coerce") * float(edge_scale) -# df_all = df_all.replace([np.inf, -np.inf], np.nan).dropna(subset=["src", "tgt", "weight"]) -# -# df_all["absw"] = df_all["weight"].abs() -# df_all = df_all[df_all["absw"] >= float(min_abs_w)].copy() -# df_all = df_all.sort_values("absw", ascending=False).head(int(top_k)).copy() -# return df_all -# -# -# def _build_union_graph(edge_frames: list[pd.DataFrame]) -> nx.DiGraph: -# G = nx.DiGraph() -# for df in edge_frames: -# if df is None or df.empty: -# continue -# for r in df.itertuples(index=False): -# G.add_edge(r.src, r.tgt, etype=r.type) -# return G -# -# -# def _node_activity_frames(edge_frames: list[pd.DataFrame], nodes: list[str]) -> list[np.ndarray]: -# node2i = {n: i for i, n in enumerate(nodes)} -# frames = [] -# for df in edge_frames: -# active = np.zeros(len(nodes), dtype=float) -# if df is not None and not df.empty: -# act_nodes = pd.unique(pd.concat([df["src"], df["tgt"]], ignore_index=True)) -# for n in act_nodes: -# j = node2i.get(n) -# if j is not None: -# active[j] = 1.0 -# frames.append(active) -# return frames -# -# -# def _aligned_node_colors_for_frame( -# nodes: list[str], -# idx: Index, -# wt_vec: np.ndarray, -# ko_vec: np.ndarray, -# eps: float = 1e-9, -# ) -> np.ndarray: -# """ -# Returns log2(KO/WT) aligned to `nodes`. -# Unknown nodes (e.g., kinases not in idx.p2i) get NaN. -# """ -# out = np.full(len(nodes), np.nan, dtype=float) -# for i, n in enumerate(nodes): -# if n in idx.p2i: -# j = idx.p2i[n] -# out[i] = float(np.log2((float(ko_vec[j]) + eps) / (float(wt_vec[j]) + eps))) -# return out -# -# -# # ------------------------- -# # Plotly animated network (fixed: no array line widths; aligned node colors) -# # ------------------------- -# def _plotly_animated_network( -# edge_frames: list[pd.DataFrame], -# times: np.ndarray, -# title: str, -# node_color_frames: list[np.ndarray] | None = None, -# node_cmax: float = 2.0, -# highlight_nodes: bool = True, -# ) -> go.Figure: -# G = _build_union_graph(edge_frames) -# if G.number_of_nodes() == 0: -# return go.Figure() -# -# pos = nx.spring_layout(G, k=0.8, seed=42) -# nodes = list(G.nodes()) -# -# activity_frames = _node_activity_frames(edge_frames, nodes) if highlight_nodes else None -# -# node_x = [pos[n][0] for n in nodes] -# node_y = [pos[n][1] for n in nodes] -# -# base_size = 10.0 -# boost_size = 18.0 -# -# init_act = activity_frames[0] if activity_frames is not None else np.ones(len(nodes), dtype=float) -# init_sizes = base_size + boost_size * init_act -# -# init_colors = None -# if node_color_frames is not None and len(node_color_frames) > 0: -# init_colors = node_color_frames[0] -# -# # IMPORTANT: Plotly does NOT support array-valued marker.line.width. Keep it scalar. -# node_trace = go.Scatter( -# x=node_x, -# y=node_y, -# mode="markers+text", -# text=nodes, -# textposition="top center", -# hoverinfo="text", -# marker=dict( -# size=init_sizes, # array OK -# line=dict(width=1, color="black"), -# color=init_colors if init_colors is not None else None, -# colorscale="RdBu_r", -# cmin=-float(node_cmax), -# cmax=float(node_cmax), -# colorbar=dict(title="log2(KO/WT)", thickness=15) if init_colors is not None else None, -# ), -# showlegend=False, -# ) -# -# union_edges = list(G.edges()) -# edge_meta = {(u, v): G.edges[u, v].get("etype", "signaling") for (u, v) in union_edges} -# -# def _edge_traces_for_frame(df_edges: pd.DataFrame): -# if df_edges is None or df_edges.empty: -# return [ -# go.Scatter(x=[], y=[], mode="lines", line=dict(width=1, color="#3498db"), opacity=0.2, hoverinfo="none"), -# go.Scatter(x=[], y=[], mode="lines", line=dict(width=1, color="#e67e22"), opacity=0.2, hoverinfo="none"), -# ] -# -# wmap = {(r.src, r.tgt): float(r.weight) for r in df_edges.itertuples(index=False)} -# -# # Build per-type traces (performance-first) -# traces = [] -# for etype, color in [("signaling", "#3498db"), ("transcription", "#e67e22")]: -# x_e, y_e, widths = [], [], [] -# for (u, v) in union_edges: -# if edge_meta[(u, v)] != etype: -# continue -# w = wmap.get((u, v), 0.0) -# if abs(w) <= 0: -# continue -# x0, y0 = pos[u] -# x1, y1 = pos[v] -# x_e += [x0, x1, None] -# y_e += [y0, y1, None] -# widths.append(float(np.clip(np.log10(1.0 + abs(w)) * 3.0, 0.2, 6.0))) -# -# w_med = float(np.median(widths)) if widths else 0.2 -# traces.append( -# go.Scatter( -# x=x_e, -# y=y_e, -# mode="lines", -# line=dict(width=w_med, color=color), -# opacity=0.55, -# hoverinfo="none", -# showlegend=False, -# ) -# ) -# return traces -# -# init_edge_traces = _edge_traces_for_frame(edge_frames[0]) -# -# frames = [] -# for i, (df_e, t) in enumerate(zip(edge_frames, times)): -# edge_traces_i = _edge_traces_for_frame(df_e) -# -# if activity_frames is not None: -# act = activity_frames[i] -# sizes_i = base_size + boost_size * act -# else: -# sizes_i = base_size -# -# if node_color_frames is not None: -# colors_i = node_color_frames[i] -# node_trace_i = go.Scatter( -# x=node_x, -# y=node_y, -# mode="markers+text", -# text=nodes, -# textposition="top center", -# hoverinfo="text", -# marker=dict( -# size=sizes_i if np.iterable(sizes_i) else float(sizes_i), -# line=dict(width=1, color="black"), -# color=colors_i, -# colorscale="RdBu_r", -# cmin=-float(node_cmax), -# cmax=float(node_cmax), -# ), -# showlegend=False, -# ) -# else: -# node_trace_i = go.Scatter( -# x=node_x, y=node_y, -# mode="markers+text", -# text=nodes, -# textposition="top center", -# hoverinfo="text", -# marker=dict(size=sizes_i if np.iterable(sizes_i) else float(sizes_i), line=dict(width=1, color="black")), -# showlegend=False, -# ) -# -# frames.append( -# go.Frame( -# data=edge_traces_i + [node_trace_i], -# name=str(i), -# layout=go.Layout(title=f"{title} (t={float(t):.1f} min)"), -# ) -# ) -# -# fig = go.Figure( -# data=init_edge_traces + [node_trace], -# layout=go.Layout( -# title=f"{title} (t={float(times[0]):.1f} min)", -# hovermode="closest", -# margin=dict(b=0, l=0, r=0, t=50), -# xaxis=dict(showgrid=False, zeroline=False, showticklabels=False), -# yaxis=dict(showgrid=False, zeroline=False, showticklabels=False), -# template="plotly_white", -# updatemenus=[ -# dict( -# type="buttons", -# showactive=False, -# buttons=[ -# dict(label="Play", method="animate", -# args=[None, dict(frame=dict(duration=250, redraw=True), fromcurrent=True)]), -# dict(label="Pause", method="animate", -# args=[[None], dict(frame=dict(duration=0, redraw=False), mode="immediate")]), -# ], -# ) -# ], -# sliders=[ -# dict( -# active=0, -# currentvalue=dict(prefix="Frame: "), -# steps=[ -# dict(method="animate", -# args=[[str(i)], dict(mode="immediate", frame=dict(duration=0, redraw=True))], -# label=f"{float(t):.0f}") -# for i, t in enumerate(times) -# ], -# ) -# ], -# ), -# frames=frames, -# ) -# return fig -# -# -# # ========================= -# # STREAMLIT PANEL -# # ========================= -# st.divider() -# st.header("🕸️ Time-Resolved Animated Network (pre-steady-state)") -# -# c1, c2, c3, c4 = st.columns(4) -# with c1: -# view_mode = st.selectbox("View", ["WT", "KO", "Δ(KO−WT)"], index=1, key="anim_net_view_mode") -# with c2: -# t_end = st.slider("End time (min)", min_value=120, max_value=24 * 7 * 60, value=120, step=100, key="anim_net_t_end") -# with c3: -# n_frames = st.slider("Frames", min_value=10, max_value=1000, value=30, step=5, key="anim_net_n_frames") -# with c4: -# include_tf_edges = st.checkbox("Include TF edges", value=True, key="anim_net_include_tf_edges") -# -# min_abs_w = st.number_input("Min |weight| filter", min_value=0.0, value=0.001, step=0.001, -# format="%.4f", key="anim_net_min_abs_w") -# -# top_k = st.slider("Top edges per frame", min_value=50, max_value=800, value=250, step=50, key="anim_net_top_k") -# -# node_metric = st.selectbox("Node color metric", ["None", "ΔmRNA (log2 KO/WT)", "ΔProtein (log2 KO/WT)"], -# index=2, key="anim_net_node_metric") -# -# node_cmax = st.slider("Node color range (± log2)", min_value=1.1, max_value=10.0, value=2.0, step=0.1, -# key="anim_net_node_cmax") -# -# edge_scale = st.slider("Edge weight scaling", min_value=0.1, max_value=100.0, value=1.0, step=0.1, -# key="anim_net_edge_scale") -# -# -# def _simulate_state_series(params: dict, t_end: float, n_points: int): -# sys_local, idx_local, _, df_tf_local, _ = load_system() -# sys_local.update(**params) -# -# t_grid = np.linspace(0.0, float(t_end), int(n_points)) -# t_sim, Y = simulate_until_steady(sys_local, t_max=float(t_end), n_points=int(n_points)) -# -# if len(t_sim) != len(t_grid): -# Yg = np.empty((len(t_grid), Y.shape[1]), dtype=float) -# for j in range(Y.shape[1]): -# Yg[:, j] = np.interp(t_grid, t_sim, Y[:, j]) -# Y = Yg -# t_sim = t_grid -# -# return sys_local, idx_local, df_tf_local, t_sim, Y -# -# -# # trajectories -# sys_wt, idx_wt, df_tf_wt, t_wt, Y_wt = _simulate_state_series(best_params, t_end=float(t_end), n_points=int(n_frames)) -# sys_ko, idx_ko, df_tf_ko, t_ko, Y_ko = _simulate_state_series(ko_params, t_end=float(t_end), n_points=int(n_frames)) -# -# # edge frames -# edge_frames: list[pd.DataFrame] = [] -# times = t_wt # same grid -# -# for i, t in enumerate(times): -# df_sig_wt, df_tf_e_wt = _edge_tables_at_time(sys_wt, idx_wt, df_tf_wt, Y_wt[i], t) -# df_sig_ko, df_tf_e_ko = _edge_tables_at_time(sys_ko, idx_ko, df_tf_ko, Y_ko[i], t) -# -# if view_mode == "WT": -# df_e = _filter_edges(df_sig_wt, df_tf_e_wt, include_tf_edges, min_abs_w, top_k, edge_scale) -# elif view_mode == "KO": -# df_e = _filter_edges(df_sig_ko, df_tf_e_ko, include_tf_edges, min_abs_w, top_k, edge_scale) -# else: -# # Δ(KO−WT) -# df_w = pd.concat([df_sig_wt, df_tf_e_wt], ignore_index=True) -# df_k = pd.concat([df_sig_ko, df_tf_e_ko], ignore_index=True) -# key = ["src", "tgt", "type"] -# -# df_w = df_w[key + ["weight"]].rename(columns={"weight": "w_wt"}) -# df_k = df_k[key + ["weight"]].rename(columns={"weight": "w_ko"}) -# -# df_d = df_k.merge(df_w, on=key, how="outer") -# df_d["w_ko"] = df_d["w_ko"].fillna(0.0) -# df_d["w_wt"] = df_d["w_wt"].fillna(0.0) -# df_d["weight"] = df_d["w_ko"] - df_d["w_wt"] -# df_d = df_d[key + ["weight"]] -# -# df_sig_d = df_d[df_d["type"] == "signaling"].copy() -# df_tf_d = df_d[df_d["type"] == "transcription"].copy() -# -# df_e = _filter_edges(df_sig_d, df_tf_d, include_tf_edges, min_abs_w, top_k, edge_scale) -# -# edge_frames.append(df_e) -# -# # build union node list for alignment -# G_union = _build_union_graph(edge_frames) -# nodes_union = list(G_union.nodes()) -# -# # aligned node colors per frame -# node_color_frames = None -# if node_metric != "None" and len(nodes_union) > 0: -# node_color_frames = [] -# for i in range(len(times)): -# if "mRNA" in node_metric: -# wt_vec = _extract_mrna_vec_from_y(Y_wt[i], idx_wt) -# ko_vec = _extract_mrna_vec_from_y(Y_ko[i], idx_ko) -# else: -# wt_vec = _extract_total_protein_vec_from_y(Y_wt[i], idx_wt) -# ko_vec = _extract_total_protein_vec_from_y(Y_ko[i], idx_ko) -# -# node_color_frames.append(_aligned_node_colors_for_frame(nodes_union, idx_wt, wt_vec, ko_vec)) -# -# # edge dynamics long table -# edge_long = [] -# for i, t in enumerate(times): -# df = edge_frames[i].copy() -# if df.empty: -# continue -# df["time"] = float(t) -# edge_long.append(df) -# -# df_edge_time = ( -# pd.concat(edge_long, ignore_index=True) -# if edge_long -# else pd.DataFrame(columns=["src", "tgt", "type", "weight", "absw", "time"]) -# ) -# -# fig_anim = _plotly_animated_network( -# edge_frames=edge_frames, -# times=times, -# title=f"{view_mode} network (0–{t_end} min)", -# node_color_frames=node_color_frames, -# node_cmax=node_cmax, -# highlight_nodes=True, -# ) -# st.plotly_chart(fig_anim, use_container_use_container_width=True, key="anim_net_plot") -# -# c_dl1, c_dl2 = st.columns(2) -# with c_dl1: -# st.download_button( -# "Download edge dynamics CSV", -# data=df_edge_time.to_csv(index=False), -# file_name=f"edge_dynamics_{view_mode.lower()}_t0-{int(t_end)}_frames{int(n_frames)}.csv", -# mime="text/csv", -# key="dl_edge_csv", -# ) -# with c_dl2: -# st.download_button( -# "Download edge dynamics JSON", -# data=df_edge_time.to_json(orient="records"), -# file_name=f"edge_dynamics_{view_mode.lower()}_t0-{int(t_end)}_frames{int(n_frames)}.json", -# mime="application/json", -# key="dl_edge_json", -# ) -# -# # ========================= -# # Matplotlib-based video export (drop-in) -# # - NO kaleido -# # - Exports MP4 (ffmpeg) or GIF -# # - Input: edge_frames (list[pd.DataFrame]), times (array), node_color_frames (optional) -# # ========================= -# import io -# import numpy as np -# import pandas as pd -# import networkx as nx -# -# def _export_network_animation_matplotlib( -# edge_frames: list[pd.DataFrame], -# times: np.ndarray, -# fmt: str = "mp4", # "mp4" or "gif" -# fps: int = 6, -# dpi: int = 160, -# node_cmap: str = "RdBu_r", -# node_cmax: float = 2.0, -# node_color_frames: list[np.ndarray] | None = None, # aligned to nodes_union ordering -# figsize: tuple[float, float] = (9.0, 7.0), -# ) -> bytes: -# """ -# Matplotlib animation exporter that avoids plotly/kaleido entirely. -# Requires: -# - matplotlib -# - imageio -# - for mp4: ffmpeg available via imageio-ffmpeg or system ffmpeg -# """ -# import matplotlib.pyplot as plt -# from matplotlib.animation import FuncAnimation, FFMpegWriter, PillowWriter -# import imageio.v2 as imageio -# -# if len(edge_frames) == 0: -# raise RuntimeError("edge_frames is empty.") -# if len(times) != len(edge_frames): -# raise RuntimeError(f"times ({len(times)}) != edge_frames ({len(edge_frames)})") -# -# # ---- build stable union graph + layout (fixed for all frames) ---- -# G_union = nx.DiGraph() -# for df in edge_frames: -# if df is None or df.empty: -# continue -# for r in df.itertuples(index=False): -# G_union.add_edge(r.src, r.tgt, etype=r.type) -# -# if G_union.number_of_nodes() == 0: -# raise RuntimeError("Union graph has no nodes (all frames empty after filtering).") -# -# nodes = list(G_union.nodes()) -# pos = nx.spring_layout(G_union, k=0.8, seed=42) -# -# # helpers -# node_xy = np.array([pos[n] for n in nodes], dtype=float) # (N,2) -# node2i = {n: i for i, n in enumerate(nodes)} -# -# # ---- precompute per-frame edge sets + widths for fast drawing ---- -# # We draw edges as 2 LineCollections: signaling + transcription -# from matplotlib.collections import LineCollection -# from matplotlib.colors import Normalize -# -# def _edges_to_segments(df: pd.DataFrame, etype: str): -# if df is None or df.empty: -# return np.zeros((0, 2, 2), dtype=float), np.zeros((0,), dtype=float) -# sub = df[df["type"] == etype] -# if sub.empty: -# return np.zeros((0, 2, 2), dtype=float), np.zeros((0,), dtype=float) -# -# segs = [] -# widths = [] -# for r in sub.itertuples(index=False): -# u, v = r.src, r.tgt -# if u not in node2i or v not in node2i: -# continue -# x0, y0 = pos[u] -# x1, y1 = pos[v] -# w = float(r.weight) -# segs.append([[x0, y0], [x1, y1]]) -# # stable width scaling -# widths.append(float(np.clip(np.log10(1.0 + abs(w)) * 2.5, 0.3, 4.5))) -# if not segs: -# return np.zeros((0, 2, 2), dtype=float), np.zeros((0,), dtype=float) -# return np.asarray(segs, dtype=float), np.asarray(widths, dtype=float) -# -# sig_segments, sig_widths = [], [] -# tf_segments, tf_widths = [], [] -# for df in edge_frames: -# s_seg, s_w = _edges_to_segments(df, "signaling") -# t_seg, t_w = _edges_to_segments(df, "transcription") -# sig_segments.append(s_seg); sig_widths.append(s_w) -# tf_segments.append(t_seg); tf_widths.append(t_w) -# -# # ---- node colors ---- -# use_node_colors = node_color_frames is not None and len(node_color_frames) == len(edge_frames) -# norm = Normalize(vmin=-float(node_cmax), vmax=float(node_cmax)) -# -# # ---- matplotlib figure ---- -# fig, ax = plt.subplots(figsize=figsize) -# ax.set_axis_off() -# -# # two edge layers -# lc_sig = LineCollection([], linewidths=1.0, alpha=0.55) # color set per-update -# lc_tf = LineCollection([], linewidths=1.0, alpha=0.55) -# lc_sig.set_color("#3498db") -# lc_tf.set_color("#e67e22") -# ax.add_collection(lc_sig) -# ax.add_collection(lc_tf) -# -# # nodes -# node_sizes = np.full(len(nodes), 60.0, dtype=float) -# sc = ax.scatter(node_xy[:, 0], node_xy[:, 1], s=node_sizes, edgecolors="black", linewidths=0.6) -# -# # labels (simple; turn off if too slow) -# texts = [] -# for n in nodes: -# x, y = pos[n] -# texts.append(ax.text(x, y, str(n), fontsize=7, ha="center", va="bottom")) -# -# title_obj = ax.text(0.01, 0.99, "", transform=ax.transAxes, va="top") -# -# # fit bounds -# pad = 0.08 -# xmin, ymin = node_xy.min(axis=0) - pad -# xmax, ymax = node_xy.max(axis=0) + pad -# ax.set_xlim(xmin, xmax) -# ax.set_ylim(ymin, ymax) -# -# # optional colorbar -# if use_node_colors: -# import matplotlib.cm as cm -# mappable = cm.ScalarMappable(norm=norm, cmap=node_cmap) -# cbar = fig.colorbar(mappable, ax=ax, fraction=0.035, pad=0.02) -# cbar.set_label("log2(KO/WT)") -# -# def _update(i: int): -# # edges -# lc_sig.set_segments(sig_segments[i]) -# lc_sig.set_linewidths(sig_widths[i] if len(sig_widths[i]) else 0.2) -# -# lc_tf.set_segments(tf_segments[i]) -# lc_tf.set_linewidths(tf_widths[i] if len(tf_widths[i]) else 0.2) -# -# # nodes colors -# if use_node_colors: -# colors_i = node_color_frames[i] -# # ensure aligned length; if not, disable -# if isinstance(colors_i, np.ndarray) and colors_i.shape[0] == len(nodes): -# sc.set_array(colors_i.astype(float)) -# sc.set_cmap(node_cmap) -# sc.set_norm(norm) -# -# title_obj.set_text(f"Network (t={float(times[i]):.1f} min)") -# return (lc_sig, lc_tf, sc, title_obj, *texts) -# -# anim = FuncAnimation(fig, _update, frames=len(edge_frames), interval=1000 / max(1, fps), blit=False) -# -# # ---- write to bytes ---- -# buf = io.BytesIO() -# fmt_l = fmt.lower() -# -# if fmt_l == "mp4": -# # Preferred: stream directly to BytesIO using FFMpegWriter (works in many environments). -# try: -# writer = FFMpegWriter(fps=fps, codec="libx264", bitrate=1800) -# anim.save(buf, writer=writer, dpi=dpi) -# plt.close(fig) -# return buf.getvalue() -# except Exception: -# # Fallback: write to temp file then read bytes (more robust). -# import tempfile, os -# with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmp: -# tmp_path = tmp.name -# try: -# writer = FFMpegWriter(fps=fps, codec="libx264", bitrate=1800) -# anim.save(tmp_path, writer=writer, dpi=dpi) -# with open(tmp_path, "rb") as f: -# data = f.read() -# finally: -# try: os.remove(tmp_path) -# except Exception: pass -# plt.close(fig) -# return data -# -# if fmt_l == "gif": -# try: -# writer = PillowWriter(fps=fps) -# anim.save(buf, writer=writer, dpi=dpi) -# plt.close(fig) -# return buf.getvalue() -# except Exception: -# # fallback: temp file -# import tempfile, os -# with tempfile.NamedTemporaryFile(suffix=".gif", delete=False) as tmp: -# tmp_path = tmp.name -# try: -# writer = PillowWriter(fps=fps) -# anim.save(tmp_path, writer=writer, dpi=dpi) -# with open(tmp_path, "rb") as f: -# data = f.read() -# finally: -# try: os.remove(tmp_path) -# except Exception: pass -# plt.close(fig) -# return data -# -# plt.close(fig) -# raise ValueError("fmt must be 'mp4' or 'gif'") -# -# -# # ------------------------- -# # Streamlit drop-in UI (replace your export block) -# # ------------------------- -# st.subheader("Export animation (Matplotlib)") -# -# cE1, cE2, cE3, cE4 = st.columns(4) -# with cE1: -# export_fmt = st.selectbox("Format", ["mp4", "gif"], index=0, key="mpl_export_fmt") -# with cE2: -# export_fps = st.slider("FPS", min_value=2, max_value=20, value=6, step=1, key="mpl_export_fps") -# with cE3: -# export_dpi = st.slider("DPI", min_value=80, max_value=300, value=160, step=10, key="mpl_export_dpi") -# with cE4: -# export_node_cmax = st.slider("Node color range (± log2)", min_value=1.1, max_value=10.0, value=float(node_cmax), -# step=0.1, key="mpl_export_node_cmax") -# -# if st.button("Render export file (Matplotlib)", key="mpl_export_btn"): -# try: -# video_bytes = _export_network_animation_matplotlib( -# edge_frames=edge_frames, -# times=times, -# fmt=export_fmt, -# fps=int(export_fps), -# dpi=int(export_dpi), -# node_cmax=float(export_node_cmax), -# node_color_frames=node_color_frames, # can be None -# ) -# st.download_button( -# f"Download {export_fmt.upper()}", -# data=video_bytes, -# file_name=f"network_{view_mode.lower()}_t0-{int(t_end)}_frames{int(n_frames)}.{export_fmt}", -# mime=("video/mp4" if export_fmt == "mp4" else "image/gif"), -# key="mpl_export_download", -# ) -# except Exception as e: -# st.error(str(e)) +st.divider() +st.header("🕸️ Time-Resolved Animated Network") + +# ------------------------- +# State/vector helpers +# ------------------------- +def _extract_mrna_vec_from_y(y_row: np.ndarray, idx: Index) -> np.ndarray: + out = np.zeros(len(idx.proteins), dtype=float) + for i in range(len(idx.proteins)): + st_y = idx.offset_y[i] + out[i] = float(y_row[st_y]) + return out + + +def _extract_total_protein_vec_from_y(y_row: np.ndarray, idx: Index) -> np.ndarray: + out = np.zeros(len(idx.proteins), dtype=float) + + for i in range(len(idx.proteins)): + st_y = idx.offset_y[i] + prot = float(y_row[st_y + 1]) + ns = int(idx.n_sites[i]) + + if ns > 0: + phos_sum = float(np.sum(y_row[st_y + 2: st_y + 2 + ns])) + out[i] = prot + phos_sum + else: + out[i] = prot + + return out + + +def _total_protein_from_Y_row(y_row: np.ndarray, idx: Index, protein: str) -> float: + p_i = idx.p2i[protein] + st_y = idx.offset_y[p_i] + + prot = float(y_row[st_y + 1]) + ns = int(idx.n_sites[p_i]) + + if ns > 0: + return prot + float(np.sum(y_row[st_y + 2: st_y + 2 + ns])) + + return prot + + +def _aligned_log2_ko_wt_for_nodes( + nodes: list[str], + idx: Index, + wt_vec: np.ndarray, + ko_vec: np.ndarray, + eps: float = 1e-9, +) -> np.ndarray: + """Return log2(KO/WT), aligned to Plotly/NetworkX node order. + + Unknown nodes are set to 0.0 so they appear neutral instead of breaking + the color scale. + """ + out = np.zeros(len(nodes), dtype=float) + + for i, node in enumerate(nodes): + if node in idx.p2i: + j = idx.p2i[node] + out[i] = float(np.log2((float(ko_vec[j]) + eps) / (float(wt_vec[j]) + eps))) + + out = np.nan_to_num(out, nan=0.0, posinf=0.0, neginf=0.0) + return out + + +# ------------------------- +# Time-resolved simulation +# ------------------------- +def _simulate_state_series(params: dict, t_end: float, n_points: int): + """Simulate one parameterization once and return a regular time grid.""" + sys_local, idx_local, _, df_tf_local, _ = load_system() + sys_local.update(**params) + + t_end = float(t_end) + n_points = int(n_points) + + t_target = np.linspace(0.0, t_end, n_points, dtype=float) + + t_sim, Y = simulate_until_steady( + sys_local, + t_max=t_end, + n_points=n_points, + ) + + t_sim = np.asarray(t_sim, dtype=float) + Y = np.asarray(Y, dtype=float) + + if Y.ndim != 2: + raise RuntimeError(f"Expected 2D state matrix from simulation, got shape={Y.shape}") + + if len(t_sim) != len(t_target) or not np.allclose(t_sim, t_target): + Y_interp = np.empty((len(t_target), Y.shape[1]), dtype=float) + + for j in range(Y.shape[1]): + Y_interp[:, j] = np.interp(t_target, t_sim, Y[:, j]) + + t_sim = t_target + Y = Y_interp + + return sys_local, idx_local, df_tf_local, t_sim, Y + + +# ------------------------- +# Edge construction at one frame +# ------------------------- +def _edge_tables_from_state_at_time( + sys_local: System, + idx_local: Index, + df_tf_local: pd.DataFrame | None, + y_row: np.ndarray, + t: float, +) -> tuple[pd.DataFrame, pd.DataFrame]: + """Build signaling and TF edge tables from an already-simulated state row.""" + t = float(t) + + # Signaling edges: kinase -> target protein. + # Kinase activity is represented through external/interpolated kinase input + # multiplied by fitted/scaled c_k. + Kt = sys_local.kin.eval(t) * sys_local.c_k + + W = sys_local.W_global.tocoo() + edge_contrib = W.data * Kt[W.col] + + prot_idx = np.searchsorted(idx_local.offset_s, W.row, side="right") - 1 + prot_idx = np.clip(prot_idx, 0, len(idx_local.proteins) - 1) + + df_sig = pd.DataFrame( + { + "src": np.asarray(idx_local.kinases, dtype=object)[W.col], + "tgt": np.asarray(idx_local.proteins, dtype=object)[prot_idx], + "weight": edge_contrib.astype(float), + "type": "signaling", + } + ) + + if not df_sig.empty: + df_sig = ( + df_sig.groupby(["src", "tgt", "type"], as_index=False) + .agg(weight=("weight", "sum")) + ) + + # Transcription edges: TF protein level -> target. + df_tf_edges = pd.DataFrame(columns=["src", "tgt", "weight", "type"]) + + if df_tf_local is not None and not df_tf_local.empty: + tf_mat = sys_local.tf_mat + tf_scale = float(getattr(sys_local, "tf_scale", 1.0)) + + rows = [] + + for r in df_tf_local.itertuples(index=False): + tf = getattr(r, "tf") + tgt = getattr(r, "target") + + if tf not in idx_local.p2i or tgt not in idx_local.p2i: + continue + + i_tgt = idx_local.p2i[tgt] + j_tf = idx_local.p2i[tf] + + try: + coeff = float(tf_mat[i_tgt, j_tf]) + except Exception: + coeff = float(np.asarray(tf_mat[i_tgt, j_tf]).squeeze()) + + if abs(coeff) < 1e-14: + continue + + tf_level = _total_protein_from_Y_row(y_row, idx_local, tf) + drive = tf_scale * coeff * tf_level + + rows.append((tf, tgt, float(drive), "transcription")) + + if rows: + df_tf_edges = pd.DataFrame( + rows, + columns=["src", "tgt", "weight", "type"], + ) + + return df_sig, df_tf_edges + + +def _filter_edges_for_animation( + df_sig: pd.DataFrame, + df_tf: pd.DataFrame, + *, + include_tf: bool, + min_abs_weight: float, + top_k: int, + edge_scale: float, +) -> pd.DataFrame: + """Merge, clean, scale, threshold, and rank edges for one frame.""" + if df_sig is None or df_sig.empty: + df_all = pd.DataFrame(columns=["src", "tgt", "weight", "type"]) + else: + df_all = df_sig.copy() + + if include_tf and df_tf is not None and not df_tf.empty: + df_all = pd.concat([df_all, df_tf], ignore_index=True) + + if df_all.empty: + df_all["absw"] = [] + return df_all + + df_all["src"] = df_all["src"].astype(str) + df_all["tgt"] = df_all["tgt"].astype(str) + df_all["type"] = df_all["type"].astype(str) + df_all["weight"] = pd.to_numeric(df_all["weight"], errors="coerce") + + df_all = ( + df_all.replace([np.inf, -np.inf], np.nan) + .dropna(subset=["src", "tgt", "type", "weight"]) + .copy() + ) + + df_all["weight"] = df_all["weight"] * float(edge_scale) + df_all["absw"] = df_all["weight"].abs() + + df_all = df_all[df_all["absw"] >= float(min_abs_weight)].copy() + df_all = df_all.sort_values("absw", ascending=False).head(int(top_k)).copy() + + return df_all + + +def _delta_edges_for_frame(df_wt_all: pd.DataFrame, df_ko_all: pd.DataFrame) -> pd.DataFrame: + """Align WT and KO edges and compute KO - WT edge weight.""" + key_cols = ["src", "tgt", "type"] + + if df_wt_all.empty and df_ko_all.empty: + return pd.DataFrame(columns=["src", "tgt", "type", "weight"]) + + if df_wt_all.empty: + df_w = pd.DataFrame(columns=key_cols + ["w_wt"]) + else: + df_w = df_wt_all[key_cols + ["weight"]].rename(columns={"weight": "w_wt"}) + + if df_ko_all.empty: + df_k = pd.DataFrame(columns=key_cols + ["w_ko"]) + else: + df_k = df_ko_all[key_cols + ["weight"]].rename(columns={"weight": "w_ko"}) + + df_d = df_k.merge(df_w, on=key_cols, how="outer") + df_d["w_ko"] = df_d["w_ko"].fillna(0.0) + df_d["w_wt"] = df_d["w_wt"].fillna(0.0) + df_d["weight"] = df_d["w_ko"] - df_d["w_wt"] + + return df_d[key_cols + ["weight"]].copy() + + +def _build_animation_frames( + *, + view_mode: str, + best_params: dict, + ko_params: dict, + include_tf_edges: bool, + min_abs_weight: float, + top_k: int, + edge_scale: float, + t_end: float, + n_frames: int, + node_metric: str, +): + """Generate all animation data once.""" + sys_wt, idx_wt, df_tf_wt, t_wt, Y_wt = _simulate_state_series( + best_params, + t_end=float(t_end), + n_points=int(n_frames), + ) + + sys_ko, idx_ko, df_tf_ko, t_ko, Y_ko = _simulate_state_series( + ko_params, + t_end=float(t_end), + n_points=int(n_frames), + ) + + times = np.asarray(t_wt, dtype=float) + + if len(t_ko) != len(times) or not np.allclose(t_ko, times): + raise RuntimeError("WT and KO simulations produced incompatible time grids.") + + edge_frames = [] + + for i, tt in enumerate(times): + df_sig_wt, df_tf_e_wt = _edge_tables_from_state_at_time( + sys_wt, + idx_wt, + df_tf_wt, + Y_wt[i], + float(tt), + ) + + df_sig_ko, df_tf_e_ko = _edge_tables_from_state_at_time( + sys_ko, + idx_ko, + df_tf_ko, + Y_ko[i], + float(tt), + ) + + df_wt_all = _filter_edges_for_animation( + df_sig_wt, + df_tf_e_wt, + include_tf=include_tf_edges, + min_abs_weight=0.0, + top_k=10_000_000, + edge_scale=1.0, + ) + + df_ko_all = _filter_edges_for_animation( + df_sig_ko, + df_tf_e_ko, + include_tf=include_tf_edges, + min_abs_weight=0.0, + top_k=10_000_000, + edge_scale=1.0, + ) + + if view_mode == "WT": + df_e = _filter_edges_for_animation( + df_sig_wt, + df_tf_e_wt, + include_tf=include_tf_edges, + min_abs_weight=min_abs_weight, + top_k=top_k, + edge_scale=edge_scale, + ) + + elif view_mode == "KO": + df_e = _filter_edges_for_animation( + df_sig_ko, + df_tf_e_ko, + include_tf=include_tf_edges, + min_abs_weight=min_abs_weight, + top_k=top_k, + edge_scale=edge_scale, + ) + + else: + df_d = _delta_edges_for_frame(df_wt_all, df_ko_all) + + df_sig_d = df_d[df_d["type"] == "signaling"].copy() + df_tf_d = df_d[df_d["type"] == "transcription"].copy() + + df_e = _filter_edges_for_animation( + df_sig_d, + df_tf_d, + include_tf=include_tf_edges, + min_abs_weight=min_abs_weight, + top_k=top_k, + edge_scale=edge_scale, + ) + + edge_frames.append(df_e) + + # Build union graph for stable node order. + G_union = nx.DiGraph() + + for df in edge_frames: + if df is None or df.empty: + continue + + for r in df.itertuples(index=False): + G_union.add_edge(str(r.src), str(r.tgt), etype=str(r.type)) + + nodes_union = list(G_union.nodes()) + + node_color_frames = None + + if node_metric != "None" and len(nodes_union) > 0: + node_color_frames = [] + + for i in range(len(times)): + if "mRNA" in node_metric: + wt_vec = _extract_mrna_vec_from_y(Y_wt[i], idx_wt) + ko_vec = _extract_mrna_vec_from_y(Y_ko[i], idx_ko) + else: + wt_vec = _extract_total_protein_vec_from_y(Y_wt[i], idx_wt) + ko_vec = _extract_total_protein_vec_from_y(Y_ko[i], idx_ko) + + node_color_frames.append( + _aligned_log2_ko_wt_for_nodes( + nodes_union, + idx_wt, + wt_vec, + ko_vec, + ) + ) + + edge_long = [] + + for tt, df in zip(times, edge_frames): + if df is None or df.empty: + continue + + tmp = df.copy() + tmp["time"] = float(tt) + edge_long.append(tmp) + + df_edge_time = ( + pd.concat(edge_long, ignore_index=True) + if edge_long + else pd.DataFrame(columns=["src", "tgt", "type", "weight", "absw", "time"]) + ) + + return { + "edge_frames": edge_frames, + "times": times, + "nodes_union": nodes_union, + "node_color_frames": node_color_frames, + "df_edge_time": df_edge_time, + } + + +# ------------------------- +# Plotly animated network +# ------------------------- +def _build_union_graph_from_edge_frames(edge_frames: list[pd.DataFrame]) -> nx.DiGraph: + G = nx.DiGraph() + + for df in edge_frames: + if df is None or df.empty: + continue + + for r in df.itertuples(index=False): + G.add_edge(str(r.src), str(r.tgt), etype=str(r.type)) + + return G + + +def _node_activity_frames(edge_frames: list[pd.DataFrame], nodes: list[str]) -> list[np.ndarray]: + node2i = {n: i for i, n in enumerate(nodes)} + frames = [] + + for df in edge_frames: + active = np.zeros(len(nodes), dtype=float) + + if df is not None and not df.empty: + act_nodes = pd.unique(pd.concat([df["src"], df["tgt"]], ignore_index=True).astype(str)) + + for n in act_nodes: + j = node2i.get(n) + if j is not None: + active[j] = 1.0 + + frames.append(active) + + return frames + + +def _plotly_animated_network( + edge_frames: list[pd.DataFrame], + times: np.ndarray, + title: str, + node_color_frames: list[np.ndarray] | None = None, + node_cmax: float = 2.0, +) -> go.Figure: + G = _build_union_graph_from_edge_frames(edge_frames) + + if G.number_of_nodes() == 0: + fig = go.Figure() + fig.update_layout( + title="No edges passed the current filters", + template="plotly_white", + ) + return fig + + pos = nx.spring_layout(G, k=0.8, seed=42) + nodes = list(G.nodes()) + + activity_frames = _node_activity_frames(edge_frames, nodes) + + node_x = [pos[n][0] for n in nodes] + node_y = [pos[n][1] for n in nodes] + + base_size = 10.0 + boost_size = 18.0 + + union_edges = list(G.edges()) + edge_type = {(u, v): G.edges[u, v].get("etype", "signaling") for (u, v) in union_edges} + + def _edge_traces_for_frame(df_edges: pd.DataFrame): + traces = [] + + if df_edges is None or df_edges.empty: + for color in ("#3498db", "#e67e22"): + traces.append( + go.Scatter( + x=[], + y=[], + mode="lines", + line=dict(width=1, color=color), + hoverinfo="none", + showlegend=False, + ) + ) + return traces + + wmap = { + (str(r.src), str(r.tgt)): float(r.weight) + for r in df_edges.itertuples(index=False) + } + + for etype, color, label in [ + ("signaling", "#3498db", "Signaling"), + ("transcription", "#e67e22", "Transcription"), + ]: + x_e, y_e, widths = [], [], [] + + for u, v in union_edges: + if edge_type[(u, v)] != etype: + continue + + w = wmap.get((u, v), 0.0) + + if abs(w) <= 0.0: + continue + + x0, y0 = pos[u] + x1, y1 = pos[v] + + x_e += [x0, x1, None] + y_e += [y0, y1, None] + widths.append(float(np.clip(np.log10(1.0 + abs(w)) * 3.0, 0.5, 6.0))) + + # Plotly cannot assign different line widths within one trace. + # Use median width per edge type for stable rendering. + line_width = float(np.median(widths)) if widths else 0.5 + + traces.append( + go.Scatter( + x=x_e, + y=y_e, + mode="lines", + line=dict(width=line_width, color=color), + opacity=0.6, + hoverinfo="none", + name=label, + showlegend=False, + ) + ) + + return traces + + def _node_trace_for_frame(i: int): + activity = activity_frames[i] + sizes = base_size + boost_size * activity + + marker = dict( + size=sizes, + line=dict(width=1, color="black"), + ) + + if node_color_frames is not None: + colors = np.asarray(node_color_frames[i], dtype=float) + + marker.update( + color=colors, + colorscale="RdBu_r", + cmin=-float(node_cmax), + cmax=float(node_cmax), + colorbar=dict(title="log2(KO/WT)", thickness=15), + ) + + return go.Scatter( + x=node_x, + y=node_y, + mode="markers+text", + text=nodes, + textposition="top center", + hovertext=[f"{n}" for n in nodes], + hoverinfo="text", + marker=marker, + showlegend=False, + ) + + init_data = _edge_traces_for_frame(edge_frames[0]) + [_node_trace_for_frame(0)] + + frames = [] + + for i, (df_e, tt) in enumerate(zip(edge_frames, times)): + frames.append( + go.Frame( + data=_edge_traces_for_frame(df_e) + [_node_trace_for_frame(i)], + name=str(i), + layout=go.Layout( + title=f"{title} — t={float(tt):.1f} min" + ), + ) + ) + + fig = go.Figure( + data=init_data, + frames=frames, + ) + + fig.update_layout( + title=f"{title} — t={float(times[0]):.1f} min", + hovermode="closest", + margin=dict(b=0, l=0, r=0, t=60), + xaxis=dict(showgrid=False, zeroline=False, showticklabels=False), + yaxis=dict(showgrid=False, zeroline=False, showticklabels=False), + template="plotly_white", + updatemenus=[ + dict( + type="buttons", + showactive=False, + buttons=[ + dict( + label="Play", + method="animate", + args=[ + None, + dict( + frame=dict(duration=250, redraw=True), + fromcurrent=True, + transition=dict(duration=0), + ), + ], + ), + dict( + label="Pause", + method="animate", + args=[ + [None], + dict( + frame=dict(duration=0, redraw=False), + mode="immediate", + transition=dict(duration=0), + ), + ], + ), + ], + ) + ], + sliders=[ + dict( + active=0, + currentvalue=dict(prefix="Time: ", suffix=" min"), + steps=[ + dict( + method="animate", + args=[ + [str(i)], + dict( + mode="immediate", + frame=dict(duration=0, redraw=True), + transition=dict(duration=0), + ), + ], + label=f"{float(tt):.0f}", + ) + for i, tt in enumerate(times) + ], + ) + ], + ) + + return fig + + +# ------------------------- +# Matplotlib export +# ------------------------- +def _export_network_animation_matplotlib( + edge_frames: list[pd.DataFrame], + times: np.ndarray, + *, + fmt: str = "gif", + fps: int = 6, + dpi: int = 150, + node_cmax: float = 2.0, + node_color_frames: list[np.ndarray] | None = None, + figsize: tuple[float, float] = (9.0, 7.0), +) -> bytes: + import os + import tempfile + + import matplotlib.pyplot as plt + from matplotlib.animation import FuncAnimation, FFMpegWriter, PillowWriter + from matplotlib.collections import LineCollection + from matplotlib.colors import Normalize + import matplotlib.cm as cm + + if not edge_frames: + raise RuntimeError("No animation frames available. Generate the animated network first.") + + if len(times) != len(edge_frames): + raise RuntimeError(f"times length {len(times)} != edge_frames length {len(edge_frames)}") + + G = _build_union_graph_from_edge_frames(edge_frames) + + if G.number_of_nodes() == 0: + raise RuntimeError("No nodes available. Lower Min |weight| or increase top edges.") + + nodes = list(G.nodes()) + pos = nx.spring_layout(G, k=0.8, seed=42) + + node_xy = np.array([pos[n] for n in nodes], dtype=float) + node2i = {n: i for i, n in enumerate(nodes)} + + def _segments_for_type(df: pd.DataFrame, etype: str): + if df is None or df.empty: + return np.zeros((0, 2, 2), dtype=float), np.zeros((0,), dtype=float) + + sub = df[df["type"].astype(str) == etype] + + if sub.empty: + return np.zeros((0, 2, 2), dtype=float), np.zeros((0,), dtype=float) + + segs = [] + widths = [] + + for r in sub.itertuples(index=False): + u = str(r.src) + v = str(r.tgt) + + if u not in node2i or v not in node2i: + continue + + x0, y0 = pos[u] + x1, y1 = pos[v] + w = float(r.weight) + + segs.append([[x0, y0], [x1, y1]]) + widths.append(float(np.clip(np.log10(1.0 + abs(w)) * 2.5, 0.3, 4.5))) + + if not segs: + return np.zeros((0, 2, 2), dtype=float), np.zeros((0,), dtype=float) + + return np.asarray(segs, dtype=float), np.asarray(widths, dtype=float) + + sig_segments, sig_widths = [], [] + tf_segments, tf_widths = [], [] + + for df in edge_frames: + s_seg, s_w = _segments_for_type(df, "signaling") + t_seg, t_w = _segments_for_type(df, "transcription") + + sig_segments.append(s_seg) + sig_widths.append(s_w) + tf_segments.append(t_seg) + tf_widths.append(t_w) + + use_node_colors = ( + node_color_frames is not None + and len(node_color_frames) == len(edge_frames) + ) + + norm = Normalize(vmin=-float(node_cmax), vmax=float(node_cmax)) + + fig, ax = plt.subplots(figsize=figsize) + ax.set_axis_off() + + lc_sig = LineCollection([], linewidths=1.0, alpha=0.60, color="#3498db") + lc_tf = LineCollection([], linewidths=1.0, alpha=0.60, color="#e67e22") + + ax.add_collection(lc_sig) + ax.add_collection(lc_tf) + + sc = ax.scatter( + node_xy[:, 0], + node_xy[:, 1], + s=np.full(len(nodes), 65.0), + edgecolors="black", + linewidths=0.6, + ) + + labels = [ + ax.text( + pos[n][0], + pos[n][1], + str(n), + fontsize=7, + ha="center", + va="bottom", + ) + for n in nodes + ] + + title_obj = ax.text( + 0.01, + 0.99, + "", + transform=ax.transAxes, + va="top", + fontsize=11, + ) + + pad = 0.08 + xmin, ymin = node_xy.min(axis=0) - pad + xmax, ymax = node_xy.max(axis=0) + pad + + ax.set_xlim(xmin, xmax) + ax.set_ylim(ymin, ymax) + + if use_node_colors: + mappable = cm.ScalarMappable(norm=norm, cmap="RdBu_r") + cbar = fig.colorbar(mappable, ax=ax, fraction=0.035, pad=0.02) + cbar.set_label("log2(KO/WT)") + + def _update(i: int): + lc_sig.set_segments(sig_segments[i]) + lc_sig.set_linewidths(sig_widths[i] if len(sig_widths[i]) else 0.2) + + lc_tf.set_segments(tf_segments[i]) + lc_tf.set_linewidths(tf_widths[i] if len(tf_widths[i]) else 0.2) + + if use_node_colors: + colors_i = np.asarray(node_color_frames[i], dtype=float) + + if colors_i.shape[0] == len(nodes): + sc.set_array(colors_i) + sc.set_cmap("RdBu_r") + sc.set_norm(norm) + + title_obj.set_text(f"Network at t={float(times[i]):.1f} min") + + return (lc_sig, lc_tf, sc, title_obj, *labels) + + anim = FuncAnimation( + fig, + _update, + frames=len(edge_frames), + interval=1000 / max(1, int(fps)), + blit=False, + ) + + fmt = fmt.lower().strip() + + if fmt not in {"gif", "mp4"}: + plt.close(fig) + raise ValueError("fmt must be 'gif' or 'mp4'") + + suffix = f".{fmt}" + + with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp: + tmp_path = tmp.name + + try: + if fmt == "gif": + writer = PillowWriter(fps=int(fps)) + else: + writer = FFMpegWriter(fps=int(fps), codec="libx264", bitrate=1800) + + anim.save(tmp_path, writer=writer, dpi=int(dpi)) + + with open(tmp_path, "rb") as f: + data = f.read() + + finally: + try: + os.remove(tmp_path) + except Exception: + pass + + plt.close(fig) + + return data + + +# ------------------------- +# Streamlit controls +# ------------------------- +if target is None: + st.info("No KO target is selected. WT view works, but KO/Δ views will be identical or uninformative.") + +c1, c2, c3, c4 = st.columns(4) + +with c1: + anim_view_mode = st.selectbox( + "View", + ["WT", "KO", "Δ(KO−WT)"], + index=1, + key="anim_net_view_mode", + ) + +with c2: + anim_t_end = st.slider( + "End time (min)", + min_value=120, + max_value=24 * 7 * 60, + value=960, + step=120, + key="anim_net_t_end", + ) + +with c3: + anim_n_frames = st.slider( + "Frames", + min_value=10, + max_value=120, + value=30, + step=5, + key="anim_net_n_frames", + ) + +with c4: + anim_include_tf = st.checkbox( + "Include TF edges", + value=True, + key="anim_net_include_tf_edges", + ) + +c5, c6, c7, c8 = st.columns(4) + +with c5: + anim_min_abs_w = st.number_input( + "Min |weight| filter", + min_value=0.0, + value=0.001, + step=0.001, + format="%.4f", + key="anim_net_min_abs_w", + ) + +with c6: + anim_top_k = st.slider( + "Top edges per frame", + min_value=50, + max_value=800, + value=250, + step=50, + key="anim_net_top_k", + ) + +with c7: + anim_node_metric = st.selectbox( + "Node color metric", + ["None", "ΔmRNA (log2 KO/WT)", "ΔProtein (log2 KO/WT)"], + index=2, + key="anim_net_node_metric", + ) + +with c8: + anim_node_cmax = st.slider( + "Node color range (± log2)", + min_value=1.1, + max_value=10.0, + value=2.0, + step=0.1, + key="anim_net_node_cmax", + ) + +anim_edge_scale = st.slider( + "Edge weight scaling", + min_value=0.1, + max_value=100.0, + value=1.0, + step=0.1, + key="anim_net_edge_scale", +) + +anim_cache_key = ( + str(anim_view_mode), + float(anim_t_end), + int(anim_n_frames), + bool(anim_include_tf), + float(anim_min_abs_w), + int(anim_top_k), + str(anim_node_metric), + float(anim_node_cmax), + float(anim_edge_scale), + str(ko_type), + str(target), + float(scale) if ko_type != "None" else 1.0, +) + +generate_anim = st.button( + "Generate animated network", + key="anim_net_generate_btn", + type="primary", +) + +if generate_anim: + with st.spinner("Simulating WT/KO trajectories and building time-resolved network frames..."): + anim_payload = _build_animation_frames( + view_mode=str(anim_view_mode), + best_params=best_params, + ko_params=ko_params, + include_tf_edges=bool(anim_include_tf), + min_abs_weight=float(anim_min_abs_w), + top_k=int(anim_top_k), + edge_scale=float(anim_edge_scale), + t_end=float(anim_t_end), + n_frames=int(anim_n_frames), + node_metric=str(anim_node_metric), + ) + + st.session_state["anim_net_cache_key"] = anim_cache_key + st.session_state["anim_net_payload"] = anim_payload + +has_anim_payload = ( + st.session_state.get("anim_net_cache_key") == anim_cache_key + and "anim_net_payload" in st.session_state +) + +if not has_anim_payload: + st.info("Click **Generate animated network** to compute and display this section.") +else: + anim_payload = st.session_state["anim_net_payload"] + + edge_frames = anim_payload["edge_frames"] + times = anim_payload["times"] + node_color_frames = anim_payload["node_color_frames"] + df_edge_time = anim_payload["df_edge_time"] + + fig_anim = _plotly_animated_network( + edge_frames=edge_frames, + times=times, + title=f"{anim_view_mode} network", + node_color_frames=node_color_frames, + node_cmax=float(anim_node_cmax), + ) + + st.plotly_chart(fig_anim, use_container_width=True, key="anim_net_plot") + + c_dl1, c_dl2 = st.columns(2) + + with c_dl1: + st.download_button( + "Download edge dynamics CSV", + data=df_edge_time.to_csv(index=False), + file_name=( + f"edge_dynamics_{str(anim_view_mode).lower()}" + f"_t0-{int(anim_t_end)}_frames{int(anim_n_frames)}.csv" + ), + mime="text/csv", + key="anim_net_edge_csv", + ) + + with c_dl2: + st.download_button( + "Download edge dynamics JSON", + data=df_edge_time.to_json(orient="records"), + file_name=( + f"edge_dynamics_{str(anim_view_mode).lower()}" + f"_t0-{int(anim_t_end)}_frames{int(anim_n_frames)}.json" + ), + mime="application/json", + key="anim_net_edge_json", + ) + + with st.expander("Preview edge dynamics table"): + st.dataframe(df_edge_time.head(500), use_container_width=True) + + st.subheader("Export animation file") + + cE1, cE2, cE3, cE4 = st.columns(4) + + with cE1: + export_fmt = st.selectbox( + "Format", + ["gif", "mp4"], + index=0, + key="anim_export_fmt", + ) + + with cE2: + export_fps = st.slider( + "FPS", + min_value=2, + max_value=20, + value=6, + step=1, + key="anim_export_fps", + ) + + with cE3: + export_dpi = st.slider( + "DPI", + min_value=80, + max_value=300, + value=150, + step=10, + key="anim_export_dpi", + ) + + with cE4: + export_node_cmax = st.slider( + "Export node color range (± log2)", + min_value=1.1, + max_value=10.0, + value=float(anim_node_cmax), + step=0.1, + key="anim_export_node_cmax", + ) + + if st.button("Render export file", key="anim_export_btn"): + try: + with st.spinner("Rendering animation export..."): + export_bytes = _export_network_animation_matplotlib( + edge_frames=edge_frames, + times=times, + fmt=str(export_fmt), + fps=int(export_fps), + dpi=int(export_dpi), + node_cmax=float(export_node_cmax), + node_color_frames=node_color_frames, + ) + + st.download_button( + f"Download {str(export_fmt).upper()}", + data=export_bytes, + file_name=( + f"network_{str(anim_view_mode).lower()}" + f"_t0-{int(anim_t_end)}_frames{int(anim_n_frames)}.{export_fmt}" + ), + mime=("image/gif" if export_fmt == "gif" else "video/mp4"), + key="anim_export_download_btn", + ) + + except Exception as exc: + st.error(f"Animation export failed: {exc}") \ No newline at end of file From 25c635e2577d2a06f38581369383ffaf78ebb35e Mon Sep 17 00:00:00 2001 From: bibymaths Date: Fri, 12 Jun 2026 17:01:32 +0200 Subject: [PATCH 26/42] fixing: phosphosite dynamics 4th panel in forward simulation --- config.toml | 6 +- scripts/compare_mechanisms.py | 411 +++++++++++++++++++++++----------- 2 files changed, 288 insertions(+), 129 deletions(-) diff --git a/config.toml b/config.toml index 85a7c2a..320aacd 100644 --- a/config.toml +++ b/config.toml @@ -273,7 +273,7 @@ tfopt = "data/tfopt_results.xlsx" # ------------------------------------------------------------ # RUN SETTINGS # ------------------------------------------------------------ -output_dir = "results_network_distributive" # Output directory +output_dir = "results_network_sequential" # Output directory cores = 80 # 0 or leave out to use all available cores seed = 42 # ------------------------------------------------------------ @@ -348,7 +348,7 @@ profile_likelihood = false profile_indices = "" # 88, 93, 95, 103, 108, 69, 78, 80, 116, 125, 135, 136, 139" # comma-separated parameter indices e.g. "0,1,5" profile_grid_size = 5 # --- Posterior Sampling (post-optimization, requires numpyro) --- -posterior_sampling = true +posterior_sampling = false posterior_num_warmup = 300 posterior_num_samples = 500 @@ -393,7 +393,7 @@ tf_scale = [2.0, 10.0] [networkmodel.models] available_models = ["distributive", "sequential", "combinatorial", "saturation"] -default_model = "distributive" +default_model = "sequential" [networkmodel.solver] absolute_tolerance = 1e-8 diff --git a/scripts/compare_mechanisms.py b/scripts/compare_mechanisms.py index fbcde2d..c333a67 100644 --- a/scripts/compare_mechanisms.py +++ b/scripts/compare_mechanisms.py @@ -7,6 +7,7 @@ if str(REPO_ROOT) not in sys.path: sys.path.insert(0, str(REPO_ROOT)) +import json import streamlit as st import streamlit.components.v1 as components @@ -33,7 +34,7 @@ from networkmodel.utils import normalize_fc_to_t0 st.set_page_config(page_title="PhoskinTime Global Knockout", layout="wide") - +RESULTS_DIR_PICKED = Path("./results_network_sequential") def _standardize_tf_columns(df_tf: pd.DataFrame) -> pd.DataFrame: """ @@ -162,6 +163,69 @@ def _mechanistic_phospho_filter(df_kin: pd.DataFrame, df_pho: pd.DataFrame) -> p keep = np.fromiter(((p, s) in kin_site_pairs for (p, s) in pairs), dtype=bool, count=len(pairs)) return df_pho2.loc[keep].copy() +def _first_existing(*paths: Path) -> Path: + for p in paths: + if p.exists(): + return p + raise FileNotFoundError("None of these files exist:\n" + "\n".join(str(p) for p in paths)) + + +def _load_fitted_params_picked(results_dir: Path, defaults: dict) -> dict: + path = _first_existing( + results_dir / "fitted_params_picked.json", + results_dir / "tables" / "fitted_params_picked.json", + ) + + with open(path, "r") as f: + raw = json.load(f) + + # Handle either flat JSON or nested export JSON. + if "params" in raw and isinstance(raw["params"], dict): + raw = raw["params"] + elif "best_params" in raw and isinstance(raw["best_params"], dict): + raw = raw["best_params"] + elif "fitted_params" in raw and isinstance(raw["fitted_params"], dict): + raw = raw["fitted_params"] + + params = {} + + for key, default_value in defaults.items(): + if key not in raw: + raise KeyError(f"{path} does not contain fitted parameter key: {key}") + + value = raw[key] + + if isinstance(default_value, np.ndarray): + arr = np.asarray(value, dtype=float) + + if arr.shape != default_value.shape: + raise ValueError( + f"Shape mismatch for {key}: JSON has {arr.shape}, " + f"expected {default_value.shape}" + ) + + params[key] = arr + else: + params[key] = float(value) + + return params + +def _load_picked_predictions(results_dir: Path): + wt_dfp = pd.read_csv(results_dir / "pred_prot_picked.csv") + wt_dfr = pd.read_csv(results_dir / "pred_rna_picked.csv") + wt_pho = pd.read_csv(results_dir / "pred_phospho_picked.csv") + + for df in (wt_dfp, wt_dfr, wt_pho): + if "protein" in df.columns: + df["protein"] = df["protein"].astype(str).str.strip().str.upper() + if "psite" in df.columns: + df["psite"] = df["psite"].astype(str).str.strip() + if "time" in df.columns: + df["time"] = pd.to_numeric(df["time"], errors="coerce") + if "pred_fc" in df.columns: + df["pred_fc"] = pd.to_numeric(df["pred_fc"], errors="coerce") + + return wt_dfp, wt_dfr, wt_pho @st.cache_resource def load_system(): @@ -176,9 +240,9 @@ def load_system(): Returns: tuple: A tuple containing the""" # IMPORTANT: ensure model selection matches run *before* building System - config.MODEL = 0 + config.MODEL = 1 - results_dir = Path("./results_network_distributive") + results_dir = RESULTS_DIR_PICKED class Args: kinase_net, tf_net = config.KINASE_NET_FILE, config.TF_NET_FILE @@ -188,11 +252,6 @@ class Args: df_kin, df_tf_raw, df_prot, df_pho, df_rna, kin_beta_map, tf_beta_map = load_data(Args()) - # optional (runner has a flag; keep identical default behavior = False) - if getattr(Args, "normalize_fc_steady", False): - df_prot = normalize_fc_to_t0(df_prot) - df_pho = normalize_fc_to_t0(df_pho) - # runner: strict mechanistic phospho filter df_pho = _mechanistic_phospho_filter(df_kin, df_pho) @@ -245,21 +304,9 @@ class Args: sys = System(idx, W_global, tf_mat, kin_in, defaults, tf_deg) - # slices/schema must match the run that produced pareto_X.npy - _, slices, _, _ = init_raw_params(defaults) - - X = np.load(results_dir / "pareto_X.npy") - theta = X[0].astype(float) - - expected_dim = max(s.stop for s in slices.values()) - if theta.size != expected_dim: - raise ValueError( - f"Incompatible pareto_X dimension: got {theta.size}, expected {expected_dim}. " - "Dashboard reconstruction does not match optimization run. " - "Fix compare_mechanisms reconstruction or re-run optimization." - ) - - best_params = unpack_params(theta, slices) + # Load the exact parameter set used by the pipeline-selected solution. + # Do not use pareto_X[0]; it may not be the picked/best solution. + best_params = _load_fitted_params_picked(results_dir, defaults) s_rates_path = results_dir / "S_rates_picked.csv" s_rates = pd.read_csv(s_rates_path) if s_rates_path.exists() else pd.DataFrame() @@ -367,46 +414,205 @@ def extract_fc_from_Y(Y, idx, t, protein, normalize=True): st.sidebar.header("🕹️ Control Panel") -ko_type = st.sidebar.selectbox("1. Choose Perturbation Type", ["None", "Protein (Synthesis)", "Kinase (Activity)"]) +ko_params = { + k: v.copy() if isinstance(v, np.ndarray) else float(v) if np.isscalar(v) else v + for k, v in best_params.items() +} -ko_params = {k: v.copy() if isinstance(v, np.ndarray) else v for k, v in best_params.items()} +st.sidebar.subheader("Perturbations") -Kmat_backup = None # default +def _scale_protein_param(param_name: str, proteins: list[str], factor: float) -> None: + if param_name not in ko_params or not proteins: + return + ids = [idx.p2i[p] for p in proteins if p in idx.p2i] + if ids: + ko_params[param_name][ids] *= float(factor) -def restore_Kinase(): - """No-op retained for old graph code compatibility. - Do not mutate sys.kin.Kmat in this dashboard. simulate.py now caches the - JAX RHS, and the RHS captures kinase input arrays as static topology. - Kinase inhibition should therefore be represented through c_k only. - """ - return None +def _scale_kinase_param(param_name: str, kinases: list[str], factor: float) -> None: + if param_name not in ko_params or not kinases: + return + ids = [idx.k2i[k] for k in kinases if k in idx.k2i] + if ids: + ko_params[param_name][ids] *= float(factor) -if ko_type == "Protein (Synthesis)": - target = st.sidebar.selectbox("Select Target Protein", idx.proteins) - p_idx = idx.p2i[target] - scale = st.sidebar.slider("Protein Synthesis Scale (0 = KO, 1 = WT)", 0.0, 1.0, 0.0, 0.05) +def _site_rows_for_proteins(proteins: list[str]) -> list[int]: + rows: list[int] = [] + for p in proteins: + if p not in idx.p2i: + continue - ko_params["A_i"][p_idx] *= scale + p_i = idx.p2i[p] + start = int(idx.offset_s[p_i]) + stop = start + int(idx.n_sites[p_i]) + rows.extend(range(start, stop)) -elif ko_type == "Kinase (Activity)": - target = st.sidebar.selectbox("Select Kinase to Inhibit", idx.kinases) - k_idx = idx.k2i[target] - scale = st.sidebar.slider("Kinase Activity Scale (0 = KO, 1 = WT)", 0.0, 1.0, 0.0, 0.05) + return rows - # Important: do not mutate sys.kin.Kmat here. - # The cached JAX RHS captures kin_Kmat statically. - # Use c_k as the dynamic kinase-activity control. - ko_params["c_k"][k_idx] *= scale -else: - target = None +def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: float) -> None: + if param_name not in ko_params or not proteins: + return + rows = _site_rows_for_proteins(proteins) + if rows: + ko_params[param_name][rows] *= float(factor) + + +with st.sidebar.expander("Kinase activity", expanded=True): + kinase_activity_targets = st.multiselect( + "Inhibit kinase activity", + options=list(idx.kinases), + key="ko_kinase_activity_targets", + ) + kinase_activity_scale = st.slider( + "Kinase activity scale", + 0.0, 1.0, 0.0, 0.05, + key="ko_kinase_activity_scale", + help="0 = full kinase activity inhibition, 1 = WT", + ) + +with st.sidebar.expander("mRNA kinetics", expanded=False): + mrna_synthesis_targets = st.multiselect( + "Inhibit mRNA synthesis", + options=list(idx.proteins), + key="ko_mrna_synthesis_targets", + ) + mrna_synthesis_scale = st.slider( + "mRNA synthesis scale", + 0.0, 1.0, 1.0, 0.05, + key="ko_mrna_synthesis_scale", + ) + + mrna_degradation_targets = st.multiselect( + "Inhibit mRNA degradation", + options=list(idx.proteins), + key="ko_mrna_degradation_targets", + ) + mrna_degradation_scale = st.slider( + "mRNA degradation scale", + 0.0, 1.0, 1.0, 0.05, + key="ko_mrna_degradation_scale", + ) + +with st.sidebar.expander("Protein kinetics", expanded=True): + protein_synthesis_targets = st.multiselect( + "Inhibit protein synthesis / translation", + options=list(idx.proteins), + key="ko_protein_synthesis_targets", + ) + protein_synthesis_scale = st.slider( + "Protein synthesis scale", + 0.0, 1.0, 0.0, 0.05, + key="ko_protein_synthesis_scale", + help="0 = full translation/protein synthesis inhibition, 1 = WT", + ) + + protein_degradation_targets = st.multiselect( + "Inhibit protein degradation", + options=list(idx.proteins), + key="ko_protein_degradation_targets", + ) + protein_degradation_scale = st.slider( + "Protein degradation scale", + 0.0, 1.0, 1.0, 0.05, + key="ko_protein_degradation_scale", + ) + +with st.sidebar.expander("Phospho-site turnover", expanded=False): + phospho_loss_targets = st.multiselect( + "Inhibit dephosphorylation / phosphodegradation for proteins", + options=list(idx.proteins), + key="ko_phospho_loss_targets", + ) + phospho_loss_scale = st.slider( + "Phospho-loss scale", + 0.0, 1.0, 1.0, 0.05, + key="ko_phospho_loss_scale", + help="0 = block phospho-site loss, 1 = WT", + ) + +with st.sidebar.expander("Transcriptional regulation", expanded=False): + tf_efficacy_targets = st.multiselect( + "Inhibit TF/transcriptional efficacy", + options=list(idx.proteins), + key="ko_tf_efficacy_targets", + ) + tf_efficacy_scale = st.slider( + "TF efficacy scale", + 0.0, 1.0, 1.0, 0.05, + key="ko_tf_efficacy_scale", + ) + + tf_global_scale = st.slider( + "Global TF-drive scale", + 0.0, 1.0, 1.0, 0.05, + key="ko_tf_global_scale", + ) + + +# Apply perturbations. +# Do not mutate sys.kin.Kmat or W_global. +# Keep topology fixed; perturb only fitted dynamic parameters. + +_scale_kinase_param("c_k", kinase_activity_targets, kinase_activity_scale) + +_scale_protein_param("A_i", mrna_synthesis_targets, mrna_synthesis_scale) +_scale_protein_param("B_i", mrna_degradation_targets, mrna_degradation_scale) + +_scale_protein_param("C_i", protein_synthesis_targets, protein_synthesis_scale) +_scale_protein_param("D_i", protein_degradation_targets, protein_degradation_scale) + +_scale_site_param_by_protein("Dp_i", phospho_loss_targets, phospho_loss_scale) + +_scale_protein_param("E_i", tf_efficacy_targets, tf_efficacy_scale) + +if "tf_scale" in ko_params: + ko_params["tf_scale"] = float(ko_params["tf_scale"]) * float(tf_global_scale) + + +all_selected_targets = ( + list(kinase_activity_targets) + + list(mrna_synthesis_targets) + + list(mrna_degradation_targets) + + list(protein_synthesis_targets) + + list(protein_degradation_targets) + + list(phospho_loss_targets) + + list(tf_efficacy_targets) +) + +has_global_tf_perturbation = abs(float(tf_global_scale) - 1.0) > 1e-12 +has_perturbation = bool(all_selected_targets) or has_global_tf_perturbation + +ko_type = "Multi-perturbation" if has_perturbation else "None" +target = all_selected_targets[0] if all_selected_targets else None +scale = 1.0 + +perturbation_signature = { + "kinase_activity": (tuple(kinase_activity_targets), float(kinase_activity_scale)), + "mrna_synthesis": (tuple(mrna_synthesis_targets), float(mrna_synthesis_scale)), + "mrna_degradation": (tuple(mrna_degradation_targets), float(mrna_degradation_scale)), + "protein_synthesis": (tuple(protein_synthesis_targets), float(protein_synthesis_scale)), + "protein_degradation": (tuple(protein_degradation_targets), float(protein_degradation_scale)), + "phospho_loss": (tuple(phospho_loss_targets), float(phospho_loss_scale)), + "tf_efficacy": (tuple(tf_efficacy_targets), float(tf_efficacy_scale)), + "tf_global": float(tf_global_scale), +} + +with st.spinner("Loading picked WT predictions and running perturbation..."): + wt_dfp, wt_dfr, wt_pho = _load_picked_predictions(RESULTS_DIR_PICKED) + + if ko_type == "None": + ko_dfp = wt_dfp.copy() + ko_dfr = wt_dfr.copy() + ko_pho = wt_pho.copy() + else: + ko_dfp, ko_dfr, _ko_pho_bad_fc = run_sim(sys, idx, ko_params) + + # Do not trust phospho pred_fc from simulate_and_measure here. + # It is using a different/too-small FC denominator in this dashboard path. + ko_pho = _ko_pho_bad_fc.copy() -# --- Simulation Logic --- -with st.spinner("Running WT and KO simulations..."): - wt_dfp, wt_dfr, wt_pho = run_sim(sys, idx, best_params) - ko_dfp, ko_dfr, ko_pho = run_sim(sys, idx, ko_params) # Leave the mutable System in a known baseline state after the comparison. sys.update(**best_params) @@ -655,9 +861,7 @@ def restore_Kinase(): selected_p, float(t_max), int(n_points), - str(ko_type), - str(target), - float(scale) if ko_type != "None" else 1.0, + str(perturbation_signature), ) if run_forward_panel: @@ -694,8 +898,27 @@ def restore_Kinase(): t_ko = cached["t_ko"] Y_ko = cached["Y_ko"] - df_wt = extract_fc_from_Y(Y_wt, idx, t_fine, selected_p) - df_ko = extract_fc_from_Y(Y_ko, idx, t_ko, selected_p) + normalize_forward_states = st.checkbox( + "Normalize forward states to t0", + value=True, + key="normalize_forward_states", + ) + + df_wt = extract_fc_from_Y( + Y_wt, idx, t_fine, selected_p, + normalize=normalize_forward_states, + ) + + df_ko = extract_fc_from_Y( + Y_ko, idx, t_ko, selected_p, + normalize=normalize_forward_states, + ) + + y_label = ( + "Phospho-site state normalized to t0" + if normalize_forward_states + else "Raw phospho-site state" + ) # --- Plot mRNA col1, col2 = st.columns(2) @@ -763,7 +986,7 @@ def restore_Kinase(): t_S, Y_S = t_ko, Y_ko kin_vals = Y_S[:, [idx.k2i[k] for k in idx.kinases]].T - kin_scaled = kin_vals * sys.c_k[:, None] + kin_scaled = kin_vals * ko_params["c_k"][:, None] S_t = sys.W_global @ kin_scaled site_names, site_rows = [], [] @@ -840,7 +1063,7 @@ def restore_Kinase(): fig_sites_fine.update_layout( title=f"{selected_p} Phospho-site State Dynamics", xaxis_title="Time (min)", - yaxis_title="Phospho-site Level (a.u.)", + yaxis_title=y_label, template="plotly_white", ) fig_sites_fine.update_xaxes(type="log") @@ -886,67 +1109,6 @@ def restore_Kinase(): yaxis_title="Fold Change", template="plotly_white") st.plotly_chart(fig_insp_p, use_container_width=True) -# st.divider() -# col1, col2 = st.columns(2) -# -# # --- Signaling Drive Panel (Phosphorylation S) -# with col1: -# if selected_p in idx.p2i: -# p_idx = idx.p2i[selected_p] -# -# # Pre-filter WT S once for the selected protein (faster than filtering per-site) -# wt_s = s_rates.loc[s_rates["protein"].astype(str).str.strip() == selected_p, ["psite", "time", "S"]].copy() -# wt_s["psite"] = wt_s["psite"].astype(str).str.strip() -# -# # Simulate KO S -# kin_vals_ko = Y_ko[:, [idx.k2i[k] for k in idx.kinases]].T -# kin_scaled_ko = kin_vals_ko * ko_params["c_k"][:, None] -# S_ko = sys.W_global @ kin_scaled_ko -# -# # Get site indices for the selected protein -# site_names, site_rows = [], [] -# site_counter = 0 -# for i, p in enumerate(idx.proteins): -# for j, site in enumerate(idx.sites[i]): -# if p == selected_p: -# site_names.append(site) -# site_rows.append(site_counter) -# site_counter += 1 -# -# fig_s_time = go.Figure() -# -# for site_name, site_idx in zip(site_names, site_rows): -# color = px.colors.qualitative.Plotly[hash(site_name) % len(px.colors.qualitative.Plotly)] -# -# wt_site = wt_s.loc[wt_s["psite"] == site_name].sort_values("time") -# if not wt_site.empty: -# fig_s_time.add_trace(go.Scatter( -# x=wt_site["time"].to_numpy(), -# y=wt_site["S"].to_numpy(), -# name=f"WT {site_name}", -# line=dict(color=color, dash="dash"), -# opacity=0.9, -# )) -# -# fig_s_time.add_trace(go.Scatter( -# x=t_ko, -# y=S_ko[site_idx, :], -# name=f"KO {site_name}", -# line=dict(color=color), -# opacity=0.9, -# )) -# -# fig_s_time.update_layout( -# title=f"{selected_p} – Phosphorylation (S)", -# xaxis_title="Time (min)", -# yaxis_title="S (Signaling Rate)", -# template="plotly_white" -# ) -# st.plotly_chart(fig_s_time, use_container_width=True) -# else: -# st.warning(f"{selected_p} not found in protein index.") - - with col3: if wt_pho_data.empty: st.info("No phospho-site data available for this protein.") @@ -987,7 +1149,7 @@ def restore_Kinase(): current_layer_nodes = {target} processed_nodes = set() - final_kin_act = sys.kin.Kmat[:, -1] * sys.c_k + final_kin_act = sys.kin.Kmat[:, -1] * ko_params["c_k"] S_final = sys.W_global.dot(final_kin_act) for d in range(depth): @@ -995,8 +1157,7 @@ def restore_Kinase(): if not current_layer_nodes: break - if ko_type == "Kinase (Activity)" or d > 0: - restore_Kinase() + if any(k in idx.kinases for k in current_layer_nodes): for k_name in current_layer_nodes: if k_name in idx.kinases: k_idx = idx.k2i[k_name] @@ -3152,9 +3313,7 @@ def _update(i: int): str(anim_node_metric), float(anim_node_cmax), float(anim_edge_scale), - str(ko_type), - str(target), - float(scale) if ko_type != "None" else 1.0, + str(perturbation_signature), ) generate_anim = st.button( From 84a734a4150caa05c6f62167b33cddccb27b0285 Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Fri, 12 Jun 2026 20:39:23 +0530 Subject: [PATCH 27/42] Fix forward phosphosite ODE panel --- scripts/compare_mechanisms.py | 98 ++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 8 deletions(-) diff --git a/scripts/compare_mechanisms.py b/scripts/compare_mechanisms.py index c333a67..fecbf6f 100644 --- a/scripts/compare_mechanisms.py +++ b/scripts/compare_mechanisms.py @@ -386,6 +386,55 @@ def extract_fc_from_Y(Y, idx, t, protein, normalize=True): return df +def _safe_min_max(values: np.ndarray) -> tuple[float, float]: + """Return finite min/max values for dashboard diagnostics.""" + arr = np.asarray(values, dtype=float) + finite = arr[np.isfinite(arr)] + if finite.size == 0: + return float("nan"), float("nan") + return float(np.min(finite)), float(np.max(finite)) + + +def extract_phosphosite_states_from_Y( + Y: np.ndarray, + idx: Index, + t: np.ndarray, + protein: str, + normalize_to_t0: bool = False, +) -> tuple[pd.DataFrame, np.ndarray, np.ndarray]: + """Extract raw or t0-normalized phosphosite ODE states for one protein. + + This intentionally reads directly from the ODE state vector. It does not use + exported fitted predictions, pred_fc, or simulate_and_measure() output. + """ + p_idx = idx.p2i[protein] + ns = int(idx.n_sites[p_idx]) + site_names = list(idx.sites[p_idx]) + + if ns <= 0: + empty = pd.DataFrame(columns=["time", "psite", "psite_value"]) + return empty, np.zeros((len(t), 0)), np.zeros((len(t), 0)) + + start = int(idx.offset_y[p_idx]) + 2 + stop = start + ns + raw_states = np.asarray(Y[:, start:stop], dtype=float) + plotted_states = raw_states.copy() + + if normalize_to_t0: + denom = raw_states[0, :].copy() + denom[np.abs(denom) < 1e-12] = 1.0 + plotted_states = raw_states / denom + + df = pd.DataFrame(plotted_states, columns=site_names) + df["time"] = t + df_long = df.melt( + id_vars="time", + var_name="psite", + value_name="psite_value", + ) + return df_long, raw_states, plotted_states + + # --- UI Setup --- st.title("🧪 Global Signaling & Transcriptional Knockout Explorer") st.caption("This dashboard builds the networkmodel system and runs WT/KO simulations on demand.") @@ -903,6 +952,11 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f value=True, key="normalize_forward_states", ) + normalize_forward_phosphosite_states = st.checkbox( + "Normalize forward phosphosite states to t0", + value=False, + key="normalize_forward_phosphosite_states", + ) df_wt = extract_fc_from_Y( Y_wt, idx, t_fine, selected_p, @@ -914,10 +968,19 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f normalize=normalize_forward_states, ) + df_wt_phosphosite, raw_wt_phosphosite, plotted_wt_phosphosite = extract_phosphosite_states_from_Y( + Y_wt, idx, t_fine, selected_p, + normalize_to_t0=normalize_forward_phosphosite_states, + ) + df_ko_phosphosite, raw_ko_phosphosite, plotted_ko_phosphosite = extract_phosphosite_states_from_Y( + Y_ko, idx, t_ko, selected_p, + normalize_to_t0=normalize_forward_phosphosite_states, + ) + y_label = ( - "Phospho-site state normalized to t0" - if normalize_forward_states - else "Raw phospho-site state" + "Phosphosite ODE state normalized to t0" + if normalize_forward_phosphosite_states + else "Raw phosphosite ODE state" ) # --- Plot mRNA @@ -1031,10 +1094,10 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f with col2: fig_sites_fine = go.Figure() - if "psite" in df_wt.columns and not df_wt["psite"].isna().all(): - for site in df_wt["psite"].dropna().unique(): - site_wt = df_wt[df_wt["psite"] == site] - site_ko = df_ko[df_ko["psite"] == site] + if not df_wt_phosphosite.empty: + for site in df_wt_phosphosite["psite"].dropna().unique(): + site_wt = df_wt_phosphosite[df_wt_phosphosite["psite"] == site] + site_ko = df_ko_phosphosite[df_ko_phosphosite["psite"] == site] color = px.colors.qualitative.Plotly[ hash(site) % len(px.colors.qualitative.Plotly) @@ -1061,13 +1124,32 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f ) fig_sites_fine.update_layout( - title=f"{selected_p} Phospho-site State Dynamics", + title=f"{selected_p} Phosphosite State Dynamics", xaxis_title="Time (min)", yaxis_title=y_label, template="plotly_white", ) fig_sites_fine.update_xaxes(type="log") st.plotly_chart(fig_sites_fine, use_container_width=True) + + raw_wt_min, raw_wt_max = _safe_min_max(raw_wt_phosphosite) + raw_ko_min, raw_ko_max = _safe_min_max(raw_ko_phosphosite) + plotted_wt_min, plotted_wt_max = _safe_min_max(plotted_wt_phosphosite) + plotted_ko_min, plotted_ko_max = _safe_min_max(plotted_ko_phosphosite) + debug_df = pd.DataFrame( + { + "series": [ + "raw WT phosphosite", + "raw KO phosphosite", + "plotted WT phosphosite", + "plotted KO phosphosite", + ], + "min": [raw_wt_min, raw_ko_min, plotted_wt_min, plotted_ko_min], + "max": [raw_wt_max, raw_ko_max, plotted_wt_max, plotted_ko_max], + } + ) + with st.expander("Forward phosphosite state debug", expanded=False): + st.dataframe(debug_df, use_container_width=True, hide_index=True) else: st.info("No phospho site data available for this protein.") From 70887de433871e6800d072bc6a747148a61416b9 Mon Sep 17 00:00:00 2001 From: bibymaths Date: Fri, 12 Jun 2026 18:11:04 +0200 Subject: [PATCH 28/42] fixed: phosphosite dynamics 4th panel in forward simulation & data fit inspector --- scripts/compare_mechanisms.py | 834 ++++++++++++++++++++++++++++------ 1 file changed, 689 insertions(+), 145 deletions(-) diff --git a/scripts/compare_mechanisms.py b/scripts/compare_mechanisms.py index fecbf6f..2f8bca9 100644 --- a/scripts/compare_mechanisms.py +++ b/scripts/compare_mechanisms.py @@ -8,6 +8,7 @@ sys.path.insert(0, str(REPO_ROOT)) import json +import inspect import streamlit as st import streamlit.components.v1 as components @@ -21,17 +22,12 @@ import networkx as nx from pathlib import Path -import io -import imageio.v2 as imageio - from networkmodel import config from networkmodel.network import Index, KinaseInput, System from networkmodel.simulate import simulate_and_measure from networkmodel.SteadyStateAnalysis import simulate_until_steady -from networkmodel.params import init_raw_params, unpack_params from networkmodel.io import load_data from networkmodel.BuildMatrix import build_W_parallel, build_tf_matrix -from networkmodel.utils import normalize_fc_to_t0 st.set_page_config(page_title="PhoskinTime Global Knockout", layout="wide") RESULTS_DIR_PICKED = Path("./results_network_sequential") @@ -385,7 +381,6 @@ def extract_fc_from_Y(Y, idx, t, protein, normalize=True): df = df.merge(df_long, on="time", how="left") return df - def _safe_min_max(values: np.ndarray) -> tuple[float, float]: """Return finite min/max values for dashboard diagnostics.""" arr = np.asarray(values, dtype=float) @@ -395,17 +390,151 @@ def _safe_min_max(values: np.ndarray) -> tuple[float, float]: return float(np.min(finite)), float(np.max(finite)) +def _simulate_until_steady_optional_y0(sys_obj, t_max: float, n_points: int, y0: np.ndarray | None = None): + """ + Call simulate_until_steady with a fixed initial state if the installed function exposes + such an argument. Otherwise fall back to the normal call. + + This keeps compare_mechanisms.py script-only and avoids modifying networkmodel modules. + """ + sig = inspect.signature(simulate_until_steady) + kwargs = { + "t_max": float(t_max), + "n_points": int(n_points), + } + + used_fixed_y0 = False + + if y0 is not None: + for y0_name in ("y0", "initial_state", "initial_conditions", "y_init"): + if y0_name in sig.parameters: + kwargs[y0_name] = np.asarray(y0, dtype=float) + used_fixed_y0 = True + break + + t, Y = simulate_until_steady(sys_obj, **kwargs) + return t, Y, used_fixed_y0 + + +def _align_Y_to_reference_initial( + Y: np.ndarray, + Y_ref: np.ndarray, + eps: float = 1e-12, +) -> np.ndarray: + """ + Align a trajectory to the reference initial state. + + This removes artificial t=0 inflation caused by separately initialized + perturbation trajectories. Multiplicative alignment preserves non-negativity + and relative dynamic shape better than a blind additive shift. + """ + Y = np.asarray(Y, dtype=float) + Y_ref = np.asarray(Y_ref, dtype=float) + + if Y.ndim != 2 or Y_ref.ndim != 2: + raise ValueError(f"Expected 2D trajectories, got Y={Y.shape}, Y_ref={Y_ref.shape}") + + if Y.shape[1] != Y_ref.shape[1]: + raise ValueError( + f"State dimension mismatch: KO has {Y.shape[1]} states, WT has {Y_ref.shape[1]} states" + ) + + Y_aligned = Y.copy() + + ko0 = Y[0, :].astype(float) + wt0 = Y_ref[0, :].astype(float) + + scale = np.ones_like(ko0, dtype=float) + can_scale = np.abs(ko0) > eps + + scale[can_scale] = wt0[can_scale] / ko0[can_scale] + Y_aligned[:, can_scale] = Y[:, can_scale] * scale[can_scale] + + # If a KO initial state is numerically zero but WT is not, use additive correction. + cannot_scale = ~can_scale + if np.any(cannot_scale): + Y_aligned[:, cannot_scale] = Y[:, cannot_scale] + (wt0[cannot_scale] - ko0[cannot_scale]) + + # Enforce exact equality at t=0 after numerical alignment. + Y_aligned[0, :] = wt0 + + return Y_aligned + + +def _run_forward_wt_ko_for_display( + sys_obj, + best_params: dict, + ko_params: dict, + t_max: float, + n_points: int, +): + """ + Run WT and KO forward simulations for the dashboard. + + WT is the fitted baseline. + KO is simulated with perturbed parameters, then displayed from the WT fitted + initial state. If simulate_until_steady supports y0, that is used directly. + Otherwise the KO trajectory is state-aligned for display. + """ + sys_obj.update(**best_params) + t_wt, Y_wt, _ = _simulate_until_steady_optional_y0( + sys_obj, + t_max=t_max, + n_points=n_points, + y0=None, + ) + + Y_wt = np.asarray(Y_wt, dtype=float) + wt_y0 = Y_wt[0, :].copy() + + sys_obj.update(**ko_params) + t_ko, Y_ko_raw, used_fixed_y0 = _simulate_until_steady_optional_y0( + sys_obj, + t_max=t_max, + n_points=n_points, + y0=wt_y0, + ) + + Y_ko_raw = np.asarray(Y_ko_raw, dtype=float) + + if used_fixed_y0: + Y_ko_plot = Y_ko_raw.copy() + Y_ko_plot[0, :] = wt_y0 + alignment_mode = "fixed y0 passed to simulate_until_steady" + else: + Y_ko_plot = _align_Y_to_reference_initial(Y_ko_raw, Y_wt) + alignment_mode = "post-simulation WT-initial-state alignment" + + sys_obj.update(**best_params) + + return { + "t_fine": np.asarray(t_wt, dtype=float), + "Y_wt": Y_wt, + "t_ko": np.asarray(t_ko, dtype=float), + "Y_ko_raw": Y_ko_raw, + "Y_ko_plot": Y_ko_plot, + "used_fixed_y0": used_fixed_y0, + "alignment_mode": alignment_mode, + } + + def extract_phosphosite_states_from_Y( - Y: np.ndarray, - idx: Index, - t: np.ndarray, - protein: str, - normalize_to_t0: bool = False, + Y: np.ndarray, + idx: Index, + t: np.ndarray, + protein: str, + normalize_to_t0: bool = False, + reference_raw_states: np.ndarray | None = None, ) -> tuple[pd.DataFrame, np.ndarray, np.ndarray]: - """Extract raw or t0-normalized phosphosite ODE states for one protein. + """ + Extract raw or reference-normalized phosphosite ODE states for one protein. This intentionally reads directly from the ODE state vector. It does not use exported fitted predictions, pred_fc, or simulate_and_measure() output. + + If reference_raw_states is provided, normalization uses its t0 denominator. + That is required for intervention plots: WT and KO must use the same WT + t0 phosphosite reference. """ p_idx = idx.p2i[protein] ns = int(idx.n_sites[p_idx]) @@ -417,23 +546,234 @@ def extract_phosphosite_states_from_Y( start = int(idx.offset_y[p_idx]) + 2 stop = start + ns + raw_states = np.asarray(Y[:, start:stop], dtype=float) plotted_states = raw_states.copy() if normalize_to_t0: - denom = raw_states[0, :].copy() + ref = raw_states if reference_raw_states is None else np.asarray(reference_raw_states, dtype=float) + + if ref.shape[1] != raw_states.shape[1]: + raise ValueError( + f"Reference phosphosite state dimension mismatch: ref={ref.shape}, raw={raw_states.shape}" + ) + + denom = ref[0, :].copy() denom[np.abs(denom) < 1e-12] = 1.0 plotted_states = raw_states / denom df = pd.DataFrame(plotted_states, columns=site_names) - df["time"] = t + df["time"] = np.asarray(t, dtype=float) + df_long = df.melt( id_vars="time", var_name="psite", value_name="psite_value", ) + return df_long, raw_states, plotted_states +def _extract_raw_phosphosite_matrix( + Y: np.ndarray, + idx: Index, + protein: str, +) -> tuple[list[str], np.ndarray]: + """Return raw phosphosite ODE states for one protein as (site_names, matrix).""" + p_idx = idx.p2i[protein] + ns = int(idx.n_sites[p_idx]) + site_names = list(idx.sites[p_idx]) + + if ns <= 0: + return [], np.zeros((Y.shape[0], 0), dtype=float) + + start = int(idx.offset_y[p_idx]) + 2 + stop = start + ns + + return site_names, np.asarray(Y[:, start:stop], dtype=float) + + +def _interp_state_matrix( + t_src: np.ndarray, + values_src: np.ndarray, + t_target: np.ndarray, +) -> np.ndarray: + """Interpolate each state column onto requested target times.""" + t_src = np.asarray(t_src, dtype=float) + t_target = np.asarray(t_target, dtype=float) + values_src = np.asarray(values_src, dtype=float) + + if values_src.size == 0: + return np.zeros((len(t_target), 0), dtype=float) + + order = np.argsort(t_src) + t_src = t_src[order] + values_src = values_src[order, :] + + out = np.empty((len(t_target), values_src.shape[1]), dtype=float) + + for j in range(values_src.shape[1]): + out[:, j] = np.interp(t_target, t_src, values_src[:, j]) + + return out + + +def _build_inspector_ko_phosphosite_intervention_df( + sys_obj, + idx: Index, + best_params: dict, + ko_params: dict, + protein: str, + wt_pho_data: pd.DataFrame, + n_points: int = 1000, +) -> tuple[pd.DataFrame, pd.DataFrame]: + """ + Build KO phosphosite inspector values on the same scale as WT picked pred_fc. + + Correct scale rule: + KO_display_fc(t) = WT_picked_pred_fc(t) * KO_raw_state(t) / WT_raw_state(t) + + This avoids the bad t0 normalization: + KO_raw_state(t) / WT_raw_state(t0) + + which can inflate values to 20-50 when WT t0 state is around 0.01. + """ + if wt_pho_data is None or wt_pho_data.empty: + empty = pd.DataFrame(columns=["time", "psite", "psite_value"]) + debug = pd.DataFrame() + return empty, debug + + required = {"protein", "psite", "time", "pred_fc"} + missing = required - set(wt_pho_data.columns) + if missing: + raise ValueError( + f"wt_pho_data is missing columns required for phosphosite inspector: {missing}" + ) + + target_times = np.asarray( + sorted(wt_pho_data["time"].dropna().unique()), + dtype=float, + ) + + if target_times.size == 0: + empty = pd.DataFrame(columns=["time", "psite", "psite_value"]) + debug = pd.DataFrame() + return empty, debug + + t_max_local = float(np.max(target_times)) + n_points_local = max(int(n_points), int(target_times.size) * 50) + + forward = _run_forward_wt_ko_for_display( + sys_obj=sys_obj, + best_params=best_params, + ko_params=ko_params, + t_max=t_max_local, + n_points=n_points_local, + ) + + t_wt = np.asarray(forward["t_fine"], dtype=float) + Y_wt = np.asarray(forward["Y_wt"], dtype=float) + + t_ko = np.asarray(forward["t_ko"], dtype=float) + Y_ko_plot = np.asarray(forward["Y_ko_plot"], dtype=float) + + site_names, raw_wt_full = _extract_raw_phosphosite_matrix(Y_wt, idx, protein) + _, raw_ko_full = _extract_raw_phosphosite_matrix(Y_ko_plot, idx, protein) + + if not site_names: + empty = pd.DataFrame(columns=["time", "psite", "psite_value"]) + debug = pd.DataFrame() + return empty, debug + + raw_wt_at_obs = _interp_state_matrix(t_wt, raw_wt_full, target_times) + raw_ko_at_obs = _interp_state_matrix(t_ko, raw_ko_full, target_times) + + rows = [] + eps = 1e-12 + + for j, site in enumerate(site_names): + wt_site = wt_pho_data[wt_pho_data["psite"].astype(str) == str(site)].copy() + + if wt_site.empty: + continue + + wt_site["time"] = pd.to_numeric(wt_site["time"], errors="coerce") + wt_site["pred_fc"] = pd.to_numeric(wt_site["pred_fc"], errors="coerce") + wt_site = wt_site.dropna(subset=["time", "pred_fc"]) + + if wt_site.empty: + continue + + # Map observation time -> row in target_times. + time_to_i = {float(t): i for i, t in enumerate(target_times)} + + for r in wt_site.itertuples(index=False): + t_val = float(r.time) + i = time_to_i[t_val] + + wt_raw = float(raw_wt_at_obs[i, j]) + ko_raw = float(raw_ko_at_obs[i, j]) + wt_picked_fc = float(r.pred_fc) + + if abs(wt_raw) < eps: + # Do not divide by a near-zero state. If WT raw is too small, + # treat KO effect ratio as neutral rather than creating inflation. + effect_ratio = 1.0 + else: + effect_ratio = ko_raw / wt_raw + + ko_display_fc = wt_picked_fc * effect_ratio + + rows.append( + { + "protein": protein, + "psite": str(site), + "time": t_val, + "psite_value": ko_display_fc, + "wt_picked_fc": wt_picked_fc, + "wt_raw_state": wt_raw, + "ko_raw_state": ko_raw, + "effect_ratio_ko_over_wt": effect_ratio, + } + ) + + ko_long = pd.DataFrame(rows) + + if raw_wt_full.shape == raw_ko_full.shape and raw_wt_full.size: + t0_max_abs_diff = float(np.max(np.abs(raw_wt_full[0, :] - raw_ko_full[0, :]))) + else: + t0_max_abs_diff = float("nan") + + if ko_long.empty: + debug = pd.DataFrame() + else: + debug = pd.DataFrame( + { + "metric": [ + "WT raw phosphosite min", + "WT raw phosphosite max", + "KO displayed raw phosphosite min", + "KO displayed raw phosphosite max", + "KO/WT raw effect ratio min", + "KO/WT raw effect ratio max", + "KO inspector displayed FC min", + "KO inspector displayed FC max", + "max abs WT-vs-KO phosphosite difference at t0", + ], + "value": [ + float(np.nanmin(raw_wt_full)), + float(np.nanmax(raw_wt_full)), + float(np.nanmin(raw_ko_full)), + float(np.nanmax(raw_ko_full)), + float(np.nanmin(ko_long["effect_ratio_ko_over_wt"])), + float(np.nanmax(ko_long["effect_ratio_ko_over_wt"])), + float(np.nanmin(ko_long["psite_value"])), + float(np.nanmax(ko_long["psite_value"])), + t0_max_abs_diff, + ], + } + ) + + return ko_long, debug # --- UI Setup --- st.title("🧪 Global Signaling & Transcriptional Knockout Explorer") @@ -882,18 +1222,140 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f st.divider() +st.header("Data - Fit Inspector") selected_p = st.selectbox("Select a protein to inspect in detail:", idx.proteins) +wt_p_data = wt_dfp[wt_dfp["protein"] == selected_p] +ko_p_data = ko_dfp[ko_dfp["protein"] == selected_p] +wt_r_data = wt_dfr[wt_dfr["protein"] == selected_p] +ko_r_data = ko_dfr[ko_dfr["protein"] == selected_p] +wt_pho_data = wt_pho[wt_pho["protein"] == selected_p] +ko_pho_data = ko_pho[ko_pho["protein"] == selected_p] + +col1, col2, col3 = st.columns(3) + +with col1: + fig_insp_r = go.Figure() + fig_insp_r.add_trace( + go.Scatter(x=wt_r_data["time"], y=wt_r_data["pred_fc"], name="Wild Type", + line=dict(dash="dash", color="black", width=2)) + ) + fig_insp_r.add_trace( + go.Scatter(x=ko_r_data["time"], y=ko_r_data["pred_fc"], name="Knockout", line=dict(color="red", width=3)) + ) + fig_insp_r.update_layout(title=f"{selected_p} mRNA Response", xaxis_title="Time (min)", yaxis_title="Fold Change", + template="plotly_white") + st.plotly_chart(fig_insp_r, use_container_width=True) + +with col2: + fig_insp_p = go.Figure() + fig_insp_p.add_trace( + go.Scatter(x=wt_p_data["time"], y=wt_p_data["pred_fc"], name="Wild Type", + line=dict(dash="dash", color="black", width=2)) + ) + fig_insp_p.add_trace( + go.Scatter(x=ko_p_data["time"], y=ko_p_data["pred_fc"], name="Knockout", line=dict(color="blue", width=3)) + ) + fig_insp_p.update_layout(title=f"{selected_p} Protein Abundance", xaxis_title="Time (min)", + yaxis_title="Fold Change", template="plotly_white") + st.plotly_chart(fig_insp_p, use_container_width=True) + +with col3: + if wt_pho_data.empty: + st.info("No phospho-site data available for this protein.") + else: + fig_sites = go.Figure() + + phospho_times = wt_pho_data["time"].dropna().unique() + + if ko_type != "None": + ko_phosphosite_inspector_df, ko_phosphosite_debug_df = ( + _build_inspector_ko_phosphosite_intervention_df( + sys_obj=sys, + idx=idx, + best_params=best_params, + ko_params=ko_params, + protein=selected_p, + wt_pho_data=wt_pho_data, + n_points=1000, + ) + ) + else: + ko_phosphosite_inspector_df = pd.DataFrame( + columns=["time", "psite", "psite_value"] + ) + ko_phosphosite_debug_df = pd.DataFrame() + + for site in wt_pho_data["psite"].dropna().unique(): + color = px.colors.qualitative.Plotly[ + hash(site) % len(px.colors.qualitative.Plotly) + ] + + site_wt = wt_pho_data[wt_pho_data["psite"] == site] + + fig_sites.add_trace( + go.Scatter( + x=site_wt["time"], + y=site_wt["pred_fc"], + name=f"Wild Type {site}", + mode="lines", + line=dict(dash="dash", color=color, width=2), + ) + ) + + if ko_type != "None": + site_ko = ko_phosphosite_inspector_df[ + ko_phosphosite_inspector_df["psite"] == site + ] + + if not site_ko.empty: + fig_sites.add_trace( + go.Scatter( + x=site_ko["time"], + y=site_ko["psite_value"], + name=f"Knockout {site}", + mode="lines", + line=dict(color=color, width=3), + ) + ) + else: + fig_sites.add_trace( + go.Scatter( + x=site_wt["time"], + y=site_wt["pred_fc"], + name=f"Knockout {site}", + mode="lines", + line=dict(color=color, width=3), + ) + ) + + fig_sites.update_layout( + title=f"{selected_p} Phosphosite Dynamics", + xaxis_title="Time (min)", + yaxis_title="Fold Change", + template="plotly_white", + ) + + st.plotly_chart(fig_sites, use_container_width=True) + + if ko_type != "None" and not ko_phosphosite_debug_df.empty: + with st.expander("Data inspector phosphosite intervention debug", expanded=False): + st.dataframe( + ko_phosphosite_debug_df, + use_container_width=True, + hide_index=True, + ) + +st.divider() # --- Forward Simulation Panel with Finer Resolution --- st.subheader(f"🔁 Forward Simulation of {selected_p}") -# Slider for t_max (in minutes): range from 1 hour to 14 days t_max = st.slider( "Simulation Time (minutes)", min_value=2, - max_value=14 * 24 * 60, # 14 days - value=960, # default: 16 hrs - step=60 + max_value=14 * 24 * 60, + value=960, + step=60, ) n_points = st.select_slider( @@ -901,6 +1363,7 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f options=[250, 500, 1000, 2500, 5000, 10000], value=1000, ) + run_forward_panel = st.button( "Run detailed WT/KO forward simulation", key="run-forward-simulation-panel", @@ -914,23 +1377,17 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f ) if run_forward_panel: - with st.spinner(f"Running WT forward simulation with {n_points} time points..."): - sys.update(**best_params) - t_fine, Y_wt = simulate_until_steady(sys, t_max=t_max, n_points=n_points) - - with st.spinner(f"Running KO forward simulation with {n_points} time points..."): - sys.update(**ko_params) - t_ko, Y_ko = simulate_until_steady(sys, t_max=t_max, n_points=n_points) - - sys.update(**best_params) + with st.spinner(f"Running WT/KO forward simulation with {n_points} time points..."): + forward_results = _run_forward_wt_ko_for_display( + sys_obj=sys, + best_params=best_params, + ko_params=ko_params, + t_max=float(t_max), + n_points=int(n_points), + ) st.session_state["forward_panel_cache_key"] = forward_cache_key - st.session_state["forward_panel_results"] = { - "t_fine": t_fine, - "Y_wt": Y_wt, - "t_ko": t_ko, - "Y_ko": Y_ko, - } + st.session_state["forward_panel_results"] = forward_results has_forward_results = ( st.session_state.get("forward_panel_cache_key") == forward_cache_key @@ -944,46 +1401,69 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f t_fine = cached["t_fine"] Y_wt = cached["Y_wt"] + t_ko = cached["t_ko"] - Y_ko = cached["Y_ko"] + Y_ko_raw = cached.get("Y_ko_raw", cached.get("Y_ko")) + Y_ko_plot = cached.get("Y_ko_plot", Y_ko_raw) + + used_fixed_y0 = bool(cached.get("used_fixed_y0", False)) + alignment_mode = cached.get("alignment_mode", "legacy cache / no alignment metadata") normalize_forward_states = st.checkbox( "Normalize forward states to t0", - value=True, + value=False, key="normalize_forward_states", ) + normalize_forward_phosphosite_states = st.checkbox( - "Normalize forward phosphosite states to t0", + "Normalize forward phosphosite states to WT t0", value=False, key="normalize_forward_phosphosite_states", ) + # Use Y_ko_plot for all displayed KO forward-state panels. + # This removes artificial KO t0 inflation while preserving the perturbation trajectory shape. df_wt = extract_fc_from_Y( - Y_wt, idx, t_fine, selected_p, + Y_wt, + idx, + t_fine, + selected_p, normalize=normalize_forward_states, ) df_ko = extract_fc_from_Y( - Y_ko, idx, t_ko, selected_p, + Y_ko_plot, + idx, + t_ko, + selected_p, normalize=normalize_forward_states, ) df_wt_phosphosite, raw_wt_phosphosite, plotted_wt_phosphosite = extract_phosphosite_states_from_Y( - Y_wt, idx, t_fine, selected_p, + Y_wt, + idx, + t_fine, + selected_p, normalize_to_t0=normalize_forward_phosphosite_states, + reference_raw_states=None, ) + df_ko_phosphosite, raw_ko_phosphosite, plotted_ko_phosphosite = extract_phosphosite_states_from_Y( - Y_ko, idx, t_ko, selected_p, + Y_ko_plot, + idx, + t_ko, + selected_p, normalize_to_t0=normalize_forward_phosphosite_states, + reference_raw_states=raw_wt_phosphosite, ) y_label = ( - "Phosphosite ODE state normalized to t0" + "Phosphosite ODE state normalized to WT t0" if normalize_forward_phosphosite_states else "Raw phosphosite ODE state" ) - # --- Plot mRNA + # --- Plot mRNA and protein col1, col2 = st.columns(2) with col1: @@ -1007,13 +1487,12 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f fig_fine_r.update_layout( title="mRNA Simulation", xaxis_title="Time", - yaxis_title="Fold Change", + yaxis_title="Fold Change" if normalize_forward_states else "Raw mRNA ODE state", template="plotly_white", ) fig_fine_r.update_xaxes(type="log") st.plotly_chart(fig_fine_r, use_container_width=True) - # --- Plot Protein with col2: fig_fine_p = go.Figure() fig_fine_p.add_trace( @@ -1035,7 +1514,7 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f fig_fine_p.update_layout( title="Protein Simulation", xaxis_title="Time", - yaxis_title="Fold Change", + yaxis_title="Fold Change" if normalize_forward_states else "Raw total protein ODE state", template="plotly_white", ) fig_fine_p.update_xaxes(type="log") @@ -1046,7 +1525,7 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f # --- Signaling Drive Panel with col1: if selected_p in idx.p2i: - t_S, Y_S = t_ko, Y_ko + t_S, Y_S = t_ko, Y_ko_plot kin_vals = Y_S[:, [idx.k2i[k] for k in idx.kinases]].T kin_scaled = kin_vals * ko_params["c_k"][:, None] @@ -1090,126 +1569,191 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f else: st.warning(f"{selected_p} not found in protein index.") - # --- Phospho-site state panel + # --- Phosphosite calibrated fine-grid ODE dynamics panel with col2: fig_sites_fine = go.Figure() - if not df_wt_phosphosite.empty: - for site in df_wt_phosphosite["psite"].dropna().unique(): - site_wt = df_wt_phosphosite[df_wt_phosphosite["psite"] == site] - site_ko = df_ko_phosphosite[df_ko_phosphosite["psite"] == site] + wt_pho_forward_data = wt_pho[wt_pho["protein"] == selected_p].copy() + + if not df_wt_phosphosite.empty and not wt_pho_forward_data.empty: + p_idx = idx.p2i[selected_p] + site_order = list(idx.sites[p_idx]) + + raw_wt_matrix = np.asarray(raw_wt_phosphosite, dtype=float) + raw_ko_matrix = np.asarray(raw_ko_phosphosite, dtype=float) + + t_wt_grid = np.asarray(t_fine, dtype=float) + t_ko_grid = np.asarray(t_ko, dtype=float) + + eps = 1e-12 + debug_rows = [] + + for j, site in enumerate(site_order): + site_wt_picked = wt_pho_forward_data[ + wt_pho_forward_data["psite"].astype(str) == str(site) + ].copy() + + if site_wt_picked.empty: + continue + + site_wt_picked["time"] = pd.to_numeric( + site_wt_picked["time"], errors="coerce" + ) + site_wt_picked["pred_fc"] = pd.to_numeric( + site_wt_picked["pred_fc"], errors="coerce" + ) + site_wt_picked = site_wt_picked.dropna(subset=["time", "pred_fc"]) + site_wt_picked = site_wt_picked.sort_values("time") + + if site_wt_picked.empty: + continue + + picked_t = site_wt_picked["time"].to_numpy(dtype=float) + picked_fc = site_wt_picked["pred_fc"].to_numpy(dtype=float) + + wt_raw_fine = raw_wt_matrix[:, j] + ko_raw_fine = raw_ko_matrix[:, j] + + # Interpolate only the smooth raw WT ODE state to picked model times + # for estimating one scalar measurement calibration. This does NOT + # create a time-dependent coarse calibration curve. + wt_raw_at_picked_t = np.interp( + picked_t, + t_wt_grid, + wt_raw_fine, + ) + + valid = ( + np.isfinite(wt_raw_at_picked_t) + & np.isfinite(picked_fc) + & (np.abs(wt_raw_at_picked_t) > eps) + ) + + if np.any(valid): + # Robust scalar calibration: median picked_FC / raw_state. + # This puts the fine ODE trajectory on the same magnitude scale + # as the pipeline-picked phosphosite prediction without using + # tiny t0 denominators or piecewise interpolation. + ratios = picked_fc[valid] / wt_raw_at_picked_t[valid] + ratios = ratios[np.isfinite(ratios)] + + if ratios.size: + calibration = float(np.median(ratios)) + else: + calibration = 1.0 + else: + calibration = 1.0 + + wt_fc_fine = wt_raw_fine * calibration + + if ko_type != "None": + ko_fc_fine = ko_raw_fine * calibration + else: + ko_fc_fine = wt_fc_fine.copy() color = px.colors.qualitative.Plotly[ hash(site) % len(px.colors.qualitative.Plotly) ] - if not site_wt.empty: - fig_sites_fine.add_trace( - go.Scatter( - x=site_wt["time"], - y=site_wt["psite_value"], - name=f"WT {site}", - line=dict(dash="dash", color=color), - ) + fig_sites_fine.add_trace( + go.Scatter( + x=t_wt_grid, + y=wt_fc_fine, + name=f"Wild Type {site}", + mode="lines", + line=dict(dash="dash", color=color, width=2), ) + ) - if not site_ko.empty: - fig_sites_fine.add_trace( - go.Scatter( - x=site_ko["time"], - y=site_ko["psite_value"], - name=f"KO {site}", - line=dict(color=color), - ) + fig_sites_fine.add_trace( + go.Scatter( + x=t_ko_grid, + y=ko_fc_fine, + name=f"Knockout {site}", + mode="lines", + line=dict(color=color, width=3), + ) + ) + + # Optional picked WT model points, useful for checking alignment. + fig_sites_fine.add_trace( + go.Scatter( + x=picked_t, + y=picked_fc, + name=f"Picked WT model {site}", + mode="markers", + marker=dict(size=6, color=color, symbol="circle-open"), + showlegend=False, ) + ) + + debug_rows.append( + { + "psite": site, + "WT raw min": float(np.nanmin(wt_raw_fine)), + "WT raw max": float(np.nanmax(wt_raw_fine)), + "KO raw min": float(np.nanmin(ko_raw_fine)), + "KO raw max": float(np.nanmax(ko_raw_fine)), + "WT calibrated FC min": float(np.nanmin(wt_fc_fine)), + "WT calibrated FC max": float(np.nanmax(wt_fc_fine)), + "KO calibrated FC min": float(np.nanmin(ko_fc_fine)), + "KO calibrated FC max": float(np.nanmax(ko_fc_fine)), + "picked WT FC min": float(np.nanmin(picked_fc)), + "picked WT FC max": float(np.nanmax(picked_fc)), + "scalar calibration": calibration, + } + ) fig_sites_fine.update_layout( - title=f"{selected_p} Phosphosite State Dynamics", + title=f"{selected_p} Phosphosite Dynamics", xaxis_title="Time (min)", - yaxis_title=y_label, + yaxis_title="Fold Change", template="plotly_white", ) fig_sites_fine.update_xaxes(type="log") st.plotly_chart(fig_sites_fine, use_container_width=True) - raw_wt_min, raw_wt_max = _safe_min_max(raw_wt_phosphosite) - raw_ko_min, raw_ko_max = _safe_min_max(raw_ko_phosphosite) - plotted_wt_min, plotted_wt_max = _safe_min_max(plotted_wt_phosphosite) - plotted_ko_min, plotted_ko_max = _safe_min_max(plotted_ko_phosphosite) - debug_df = pd.DataFrame( - { - "series": [ - "raw WT phosphosite", - "raw KO phosphosite", - "plotted WT phosphosite", - "plotted KO phosphosite", - ], - "min": [raw_wt_min, raw_ko_min, plotted_wt_min, plotted_ko_min], - "max": [raw_wt_max, raw_ko_max, plotted_wt_max, plotted_ko_max], - } - ) - with st.expander("Forward phosphosite state debug", expanded=False): - st.dataframe(debug_df, use_container_width=True, hide_index=True) - else: - st.info("No phospho site data available for this protein.") - -st.divider() - -st.header("Data - Fit Inspector") -wt_p_data = wt_dfp[wt_dfp["protein"] == selected_p] -ko_p_data = ko_dfp[ko_dfp["protein"] == selected_p] -wt_r_data = wt_dfr[wt_dfr["protein"] == selected_p] -ko_r_data = ko_dfr[ko_dfr["protein"] == selected_p] -wt_pho_data = wt_pho[wt_pho["protein"] == selected_p] -ko_pho_data = ko_pho[ko_pho["protein"] == selected_p] - -col1, col2, col3 = st.columns(3) - -with col1: - fig_insp_r = go.Figure() - fig_insp_r.add_trace( - go.Scatter(x=wt_r_data["time"], y=wt_r_data["pred_fc"], name="Wild Type", - line=dict(dash="dash", color="black", width=2)) - ) - fig_insp_r.add_trace( - go.Scatter(x=ko_r_data["time"], y=ko_r_data["pred_fc"], name="Knockout", line=dict(color="red", width=3)) - ) - fig_insp_r.update_layout(title=f"{selected_p} mRNA Response", xaxis_title="Time (min)", yaxis_title="Fold Change", - template="plotly_white") - st.plotly_chart(fig_insp_r, use_container_width=True) + if raw_wt_matrix.shape == raw_ko_matrix.shape and raw_wt_matrix.size: + phosphosite_t0_max_abs_diff = float( + np.max(np.abs(raw_wt_matrix[0, :] - raw_ko_matrix[0, :])) + ) + else: + phosphosite_t0_max_abs_diff = float("nan") + + with st.expander("Forward phosphosite calibrated dynamics debug", expanded=False): + st.write( + { + "alignment_mode": alignment_mode, + "used_fixed_y0_argument": used_fixed_y0, + "max_abs_t0_difference_WT_vs_displayed_KO_phosphosite": phosphosite_t0_max_abs_diff, + "calibration_mode": "single robust per-site scalar: median(picked WT FC / WT raw ODE state)", + } + ) -with col2: - fig_insp_p = go.Figure() - fig_insp_p.add_trace( - go.Scatter(x=wt_p_data["time"], y=wt_p_data["pred_fc"], name="Wild Type", - line=dict(dash="dash", color="black", width=2)) - ) - fig_insp_p.add_trace( - go.Scatter(x=ko_p_data["time"], y=ko_p_data["pred_fc"], name="Knockout", line=dict(color="blue", width=3)) - ) - fig_insp_p.update_layout(title=f"{selected_p} Protein Abundance", xaxis_title="Time (min)", - yaxis_title="Fold Change", template="plotly_white") - st.plotly_chart(fig_insp_p, use_container_width=True) + if debug_rows: + st.dataframe( + pd.DataFrame(debug_rows), + use_container_width=True, + hide_index=True, + ) -with col3: - if wt_pho_data.empty: - st.info("No phospho-site data available for this protein.") - else: - fig_sites = go.Figure() - for site in wt_pho_data["psite"].unique(): - color = px.colors.qualitative.Plotly[hash(site) % len(px.colors.qualitative.Plotly)] - site_wt = wt_pho_data[wt_pho_data["psite"] == site] - site_ko = ko_pho_data[ko_pho_data["psite"] == site] - fig_sites.add_trace( - go.Scatter(x=site_wt["time"], y=site_wt["pred_fc"], name=f"WT Site: {site}", - line=dict(dash="dash", color=color)) - ) - fig_sites.add_trace( - go.Scatter(x=site_ko["time"], y=site_ko["pred_fc"], name=f"KO Site: {site}", line=dict(color=color)) - ) - fig_sites.update_layout(title=f"{selected_p} Phospho-site Dynamics", xaxis_title="Time (min)", - yaxis_title="Fold Change", template="plotly_white") - st.plotly_chart(fig_sites, use_container_width=True) + if Y_ko_raw is not None: + _, raw_ko_unaligned_phosphosite, _ = extract_phosphosite_states_from_Y( + Y_ko_raw, + idx, + t_ko, + selected_p, + normalize_to_t0=False, + ) + unaligned_min, unaligned_max = _safe_min_max(raw_ko_unaligned_phosphosite) + st.write( + { + "raw_unaligned_KO_phosphosite_min": unaligned_min, + "raw_unaligned_KO_phosphosite_max": unaligned_max, + } + ) + else: + st.info("No phospho site data available for this protein.") st.divider() From 3ba6ab19d924cc55e2dabb8de14cc2a29713fe8d Mon Sep 17 00:00:00 2001 From: bibymaths Date: Fri, 12 Jun 2026 18:48:33 +0200 Subject: [PATCH 29/42] chore: update changelog and docs config file --- CHANGELOG.md | 100 +++++++++++++++++++++++ docs/Documentation/CHANGELOG.md | 138 -------------------------------- mkdocs.yml | 6 +- 3 files changed, 104 insertions(+), 140 deletions(-) delete mode 100644 docs/Documentation/CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cb86e5..35d068d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,26 @@ All notable changes to this project are documented here. - Workers in sensitivity simulations +- Equations in notebooks + +- Console display, posterior log, workflow testing for frontend + +- Fixed the frontend no code dashboard, testing networmodel and protwise done + +- Cached rhs in model ode solving, and forward simulation script + +- Formatting python code + +- Directories path + +- Posterior params conversion fix + +- Network sweep and forward simulation + +- Phosphosite dynamics 4th panel in forward simulation + +- Phosphosite dynamics 4th panel in forward simulation & data fit inspector + ### Maintenance @@ -594,6 +614,84 @@ Migrate networkmodel scalar path to JAX/Diffrax/JAXopt and update docs/CLI - Figures dpi set to 300 +- Update changelog and documentation + +- Update README.md + +- Add notebook readiness tests across modules + +- Revert KinOpt and TFOpt notebook refactor + +- Validate networkmodel slice layouts exactly + +- Merge pull request #63 from bibymaths/codex/fix-failing-tests-and-increase-coverage + +Introduce notebook-safe projected finite-difference optimizers, lightweight LinearConstraint, tests and docs updates + +- Added coverage badge, fixed slice bounds tests, removed old pypi README.md + +- Dead scripts for thermal extension + +- Add executable educational notebooks + +- Add SALib to CI test dependencies + +- Merge pull request #64 from bibymaths/codex/create-educational-jupyter-notebooks-for-modules + +Add executable educational notebooks and CI/tests for KinOpt, TFOpt, protwise, and networkmodel + +- Pixi and README.md + +- Merge pull request #65 from bibymaths/missing-data-scenarios + +Missing data scenarios + +- Frontend plan + +- Frontend plan renamed + +- Standardize dashboard-ready output contract + +- Add dashboard result browser + +- Add dashboard CLI launcher + +- Add dashboard upload and configuration UI + +- Integrate workflow-specific dashboard panels + +- Add dashboard tests and documentation + +- Fix networkmodel custom config handling + +- Fix dashboard input extension validation + +- Fix ProtWise custom config handling + +- Add dashboard user, developer, and troubleshooting guides + +- Fix dashboard result discovery for reports and child runs + +- Restrict dashboard config inputs to TOML + +- Serialize run metadata with JSON-safe arrays + +- Fix advanced analysis dashboard commands + +- Merge pull request #67 from bibymaths/codex/standardize-dashboard-ready-output-contract + +Standardize dashboard-ready output contract + +- Add backward alias for old pymooo results to display in legacy mode and added imageio and gravis libs, module levelling for scripts + +- Density plots for posterior with gaussian smoothing + +- Fix forward phosphosite ODE panel + +- Merge pull request #68 from bibymaths/codex/fix-phosphosite-state-dynamics-panel + +Fix forward phosphosite ODE panel + ### Tests @@ -605,6 +703,8 @@ Migrate networkmodel scalar path to JAX/Diffrax/JAXopt and update docs/CLI - Testing network model with posterior sampling, removed history video +- Notebooks are working + ## [0.4.0] - 2025-05-06 diff --git a/docs/Documentation/CHANGELOG.md b/docs/Documentation/CHANGELOG.md deleted file mode 100644 index acea46a..0000000 --- a/docs/Documentation/CHANGELOG.md +++ /dev/null @@ -1,138 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres -to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -> **Note for contributors:** The canonical changelog is `CHANGELOG.md` at the repository root. -> This file (`docs/Documentation/CHANGELOG.md`) is a mirror kept in sync for the documentation site. -> Always update the root `CHANGELOG.md` first, then propagate changes here. - -## [0.1.0] - 2025-04-19 - -### Added - -- Initial release of **PhosKinTime**, a Python toolkit for ODE-based modeling of phosphorylation kinetics and - transcriptional time-series. -- Features include: - - Parameter estimation. - - Sensitivity analysis. - - Steady-state computation. - - Interactive visualization. -- Support for Python 3.10, 3.11, and 3.12. -- Dependencies include `numpy`, `pandas`, `seaborn`, `matplotlib`, `scipy`, and more. -- CLI entry point `phoskintime` via `bin.main:main` in root. -- Packaged directories: `bin`, `config`, `kinopt`, `models`, `paramest`, `plotting`, `sensitivity`, `steady`, `tfopt`, - and `utils`. -- Documentation and homepage available - at [https://bibymaths.github.io/phoskintime/](https://bibymaths.github.io/phoskintime/). - -## [0.2.0] - 2025-04-24 - -### Added - -- Added light grid in plotting of model. -- Added `CHANGELOG.md`. -- Added direct link to open file from CLI. -- Added CLI wrappers for entry point. -- Added deployment configuration file. -- Added support for network via Cytoscape. -- Added configuration file for PhosKinTime settings. -- Enhanced analysis and plotting functions: added upper bound parameter, updated loss type defaults, and improved legend - formatting. - -### Changed - -- Updated parameter bounds and model settings in configuration files. -- Refactored logging statements and improved data filtering in main processing files. - -### Fixed - -- Fixed display of missing kinases in output before optimization in `kinopt`. - -### Removed - -- Removed clipping of predicted expression. -- Deleted `abopt` directory. - -## [0.3.0] - 2025-04-24 - -### Added - -- Support for non-psite time series in kinase data. -- New results directory for structured output saving. -- Detailed docstrings and inline documentation for key functions. - -### Changed - -- Refactored `powell.jl`: cleaner function names, improved parameter handling, and threading support. -- Updated threading configuration and residuals calculation. -- Replaced print statements with logger output in Python modules. -- Adjusted beta bounds and default loss function settings. -- Improved ODE system equations, plotting aesthetics, and documentation structure. - -### Fixed - -- LaTeX formatting in README.md. -- Sheet name for estimated values in Excel export. - -### Removed - -- Obsolete `abopt` directory. -- Outdated module references and unused code. -- Removed julia implementation of kinopt -- Removed Project.toml for Julia dependency management. - -## [0.4.0] - alpha - -Added -- Phase space plots and strip plots for state distributions in sensitivity analysis. -- Time-state grid visualization replacing old time-wise plots. -- Enhanced logging format for parameter bounds and model configuration. -- Increased number of trajectories to 10,000 for improved sensitivity resolution. -- Support for parameter relationship plots and top parameter pair visualizations. - -Changed -- Refactored sensitivity analysis functions and configuration parameters. -- Updated site parameter labels and adjusted development mode flags. -- Improved aesthetics of phase space and strip plots. -- Adjusted ODE model references (`ODE_MODEL`) and refined output normalization logic. -- Replaced hardcoded values with computed perturbations for sensitivity analysis. - -Fixed -- Markdown formatting in README and PYPI_README. -- Sheet name bug in Excel export for estimated values. - -Removed -- Deprecated analysis modes and unused constants. -- Combined time-weight calculation from data preprocessing. - -## [0.4.0] – 2025-06-05 - -### Added - -* Model error plotting in the visualization pipeline. -* Detailed descriptions for new `Y_METRIC` options in metric reports. - -### Changed - -* Streamlined argument parsing and enhanced logging details (now logs additional configuration parameters). -* Updated default ODE model constant from `randmod` to `succmod` for improved simulation accuracy. -* Disabled development mode by default; enhanced HTML‐report structure and log‐file handling. -* Refactored output‐directory parameter to a list format and reorganized output files with improved naming conventions across display and plotting modules. -* Updated upper bound ranges and default values for key parameters in config files. -* Adjusted figure sizing and label management in plotting functions; updated regex for parameter‐label matching to support multi‐digit labels. -* Improved plotting file naming and handling of perturbation values. -* Enhanced Excel sheet processing for parameter imports and added regularization checks during data import. -* Improved confidence‐interval logging format and enhanced regularization‐term computation in `normest.py`. -* Updated lambda‐range handling in `normest.py`. - -### Fixed - -*None yet.* - -### Removed - -*None.* - diff --git a/mkdocs.yml b/mkdocs.yml index 58fd93a..67a3c9d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -35,8 +35,10 @@ theme: nav: - Home: index.md - - Reference: reference.md - - Changelog: Documentation/CHANGELOG.md + - Terms of use: ../TERMS_OF_USE.md + - Contributing: ../CONTRIBUTING.md + - API Reference: reference.md + - Changelog: ../CHANGELOG.md - Documentation: - Architecture & Data Flow: Documentation/architecture.md - Configuration Reference: Documentation/configuration.md From a845fec4bf2302e16b397807fef5927d89499b75 Mon Sep 17 00:00:00 2001 From: bibymaths Date: Tue, 16 Jun 2026 14:23:09 +0200 Subject: [PATCH 30/42] add: memory issue fixing --- docs/Combinatorial_Model_Memory_Issue.md | 281 +++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 docs/Combinatorial_Model_Memory_Issue.md diff --git a/docs/Combinatorial_Model_Memory_Issue.md b/docs/Combinatorial_Model_Memory_Issue.md new file mode 100644 index 0000000..3a30e66 --- /dev/null +++ b/docs/Combinatorial_Model_Memory_Issue.md @@ -0,0 +1,281 @@ +# Memory Audit and Safe Fix Plan for Combinatorial Model OOM in phoskintime + +## 1. Executive Summary + +The `phoskintime` repository implements three network‑based models of phosphorylation: distributive (MODEL=0), sequential (MODEL=1) and combinatorial (MODEL=2). The first two models run within the available memory, but the combinatorial model exhausts available RAM and crashes the server. In a reported run the server had ~503 GB of RAM and `network.runner` alone consumed ~173 GB before failing. This audit inspects the `global` branch and pinpoints specific code paths where the combinatorial model materializes extremely large arrays and keeps them in memory. The planned fixes are conservative: they reduce memory amplification without changing the underlying biological equations or optimization objectives. They focus on streaming, chunking and down‑casting data instead of fully materializing combinatorial state spaces and trajectories, and on avoiding retention of large intermediate results. Only memory‑safe fixes are proposed; no changes to model semantics, optimization logic or public APIs are allowed. + +## 2. Observed Failure + +1. **Symptom** – The combinatorial model (MODEL=2) causes the server to run out of memory. During a multi‑start optimization the process consumes ~173 GB of RAM (much higher than the distributive/sequential models) and eventually crashes. +2. **Scale** – Memory growth appears to scale exponentially with the number of phosphorylation sites per protein: the state dimension for each protein is `1 + 2^n_sites`[\[1\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/network.py#:~:text=,i), and the simulation stores the entire trajectory `Y` of shape `(time_points, total_state_dim)`[\[2\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/simulate.py#:~:text=ns%20%3D%20int%28idx.n_states,p0%20%3D%20st%20%2B%201). +3. **Immediate cause** – The combinatorial model precomputes all possible phosphorylation states and transitions for every protein using dense arrays. During simulation it materializes these states for all time points and computes per‑site signals using a dense bit‑mask matrix. These arrays can easily reach hundreds of gigabytes when proteins have more than a handful of phosphosites. + +## 3. Root‑Cause Hypotheses Checked + +| Hypothesis | Evidence | Outcome | +|---------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------| +| **3.1 Large state dimension due to 2^n_sites** | The `Index` class sets `n_states[i] = 1 << n_sites[i]` for combinatorial models, so each protein has `1 + 2^n_sites` dynamic states[\[1\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/network.py#:~:text=,i). | Confirmed. This exponential growth is inherent to the model. | +| **3.2 Dense hypercube transitions stored in memory** | `build_random_transitions` enumerates all dephosphorylation/phosphorylation transitions for each state and appends them to `trans_from`, `trans_to` and `trans_site` arrays[\[3\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/models.py#:~:text=def%20build_random_transitions%28idx%29%3A%20,for%20combinatorial%20topology). These arrays scale with `2^n_sites × n_sites`. | Confirmed. For `n_sites=6` this yields ~384 transitions per protein; for `n_sites=10` it becomes ~10,240 transitions. | +| **3.3 Dense** `bits` **matrix used to extract signals** | During simulation output extraction, the code constructs `bits = ((np.arange(ns)[:,None] >> np.arange(n_sites)[None,:]) & 1).astype(float)` and multiplies the state trajectories with this `(2^n_sites × n_sites)` matrix to compute per‑site phosphorylation counts[\[2\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/simulate.py#:~:text=ns%20%3D%20int%28idx.n_states,p0%20%3D%20st%20%2B%201). | Confirmed. The `bits` matrix is dense and duplicates weight vectors for each site. | +| **3.4 Full trajectory materialization for all proteins and multi‑starts** | `simulate_diffrax` returns the entire trajectory `Y` for all dynamic states and time points. In `simulate_and_measure`, the code slices `Y` to extract per‑protein states and does not free them. Sensitivity analysis and multi‑start keep DataFrames of all trajectories and metrics in memory. | Confirmed. These arrays are not released before the next iteration. | +| **3.5 JAX backend uses global max array sizes** | The JAX RHS constructs arrays with `jnp.arange(max_states)` and loops over `max_trans` for all proteins[\[4\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/backend.py#:~:text=). `max_states` is the maximum 2^n_sites across proteins. | Confirmed. On GPUs this increases host memory and JAX compilation time. | +| **3.6** `S_cache` **allocated densely for all phosphorylation sites** | In combinatorial mode, `System.__init__` allocates `S_cache = np.zeros((n_W_rows, kin_Kmat.shape[1]))` where `n_W_rows` equals the total number of phosphosites across all proteins[\[5\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/network.py#:~:text=,1%5D%29%2C%20dtype%3Dnp.float64). If there are many sites or time bins this array is large. | Partially confirmed – moderate memory, but not the main issue compared with exponential state/transition explosion. | +| **3.7 Retention of multistart/sensitivity history** | Multi‑start results and sensitivity analyses accumulate large DataFrames containing trajectories, parameter sets and metrics. These are not cleared until all starts finish. | Confirmed. This retention amplifies memory usage but is secondary to the exponential state/transition costs. | + +## 4. Confirmed Memory‑Amplification Points + +1. **Exponential state space** – `Index.__init__` computes `self.n_states[i] = 1 << n_sites[i]`[\[1\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/network.py#:~:text=,i). Each protein’s ODE segment includes `1 + 2^n_sites` states, leading to a `state_dim` that grows exponentially with `n_sites`. Running several proteins with more than 6 sites saturates memory quickly. + +2. **Dense transition lists** – `build_random_transitions` iterates over all possible states `m` (`0..2^n_sites-1`) and for each site `j` appends `m`, `m|(1<> np.arange(n_sites)[None,:]) & 1).astype(float)` and performing `states @ bits`[\[2\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/simulate.py#:~:text=ns%20%3D%20int%28idx.n_states,p0%20%3D%20st%20%2B%201). For `ns = 2^n_sites`, `bits` is a float matrix of size `ns × n_sites`. When `ns` is large this matrix alone can occupy tens of gigabytes. + +4. **Full trajectory retention** – `simulate_diffrax` returns the complete trajectory `Y` across all time points. `simulate_and_measure` slices `Y` and constructs DataFrames for each protein, keeping the full arrays alive until the end of optimization or sensitivity analysis. Multi‑start and sensitivity analysis store these DataFrames in lists, multiplying memory usage by the number of starts or samples. + +5. **Global JAX array sizes** – In the JAX backend, `make_networkmodel_rhs` constructs arrays of size `max_states` and `max_trans` across all proteins[\[4\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/backend.py#:~:text=). This amplifies memory usage when even one protein has a large number of states. + +6. `S_cache` **zero‑initialization** – For combinatorial models, `System.__init__` allocates `S_cache` as a dense zero array sized `(number_of_sites, number_of_time_bins)`[\[5\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/network.py#:~:text=,1%5D%29%2C%20dtype%3Dnp.float64). Although smaller than the state trajectory, it is unnecessary to pre‑allocate the entire matrix when only a few columns are needed at a time. + +## 5. Files and Exact Lines to Change + +The following modifications reduce memory usage without altering the scientific equations or optimization logic. Line numbers refer to the `global` branch as inspected. Only the listed changes should be made; other code must remain unchanged. + +### File: `networkmodel/models.py` + +Current lines: + +- **L454‑498** – Function `build_random_transitions` enumerates all forward transitions for combinatorial models. It loops over each state `m` (`0..2^n-1`) and for each site `j` not set in `m`, appends `m` (from state), `m|(1<> np.arange(n_sites)[None,:]) & 1).astype(float)`; then computes `states @ bits` to get per‑site phosphorylated counts[\[2\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/simulate.py#:~:text=ns%20%3D%20int%28idx.n_states,p0%20%3D%20st%20%2B%201). + +Required change: + +- **Replace** the dense `bits` matrix with per‑site streaming. For each site `j` (0..n_sites‑1), compute a weight vector `w_j = ((np.arange(ns) >> j) & 1).astype(np.float32)` on‑the‑fly and calculate `states @ w_j` for that site. Or compute contributions sequentially within the loss function without constructing `w_j` at all, by using bitwise operations in the loop over states. Accumulate results into a `(times,)` vector for each site. This avoids allocating the `(ns × n_sites)` matrix and reduces memory by a factor of `n_sites`. Since each `w_j` is computed identically to a column of `bits`, the numerical outputs remain unchanged. + +- **Free** the sliced `states` array as soon as per‑site and total protein signals are computed. Convert per‑site results to `float32` before storing in DataFrames. Do not keep `states` or intermediate arrays beyond the extraction step. + +### File: `networkmodel/backend.py` + +Current lines: + +- **L303‑405** – In `make_networkmodel_rhs` for combinatorial models, the JAX RHS preallocates arrays like `m = jnp.arange(max_states)` and loops over `max_states` and `max_trans` to compute phosphorylation and dephosphorylation fluxes[\[4\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/backend.py#:~:text=). + +Required change: + +- **Refactor** the JAX RHS to operate per protein rather than over a global `max_states`. For each protein, compute `jnp.arange(n_states[i])` locally and loop only over its own transitions (via the generator from `build_random_transitions`). Use `jax.lax.scan` or `while_loop` to iterate over states and transitions without materializing large arrays. Avoid storing `m` or `trans` arrays of size `max_states`. This reduces the memory footprint of compiled JAX functions while preserving identical dynamics. Because the per‑protein loops compute the same flux contributions, the model equations remain unchanged. + +- **Downcast** intermediate arrays to `float32` where safe, and ensure outputs are cast back to `float64` if required. Provide a configuration option to enable downcasting for memory‑constrained runs. + +### File: `networkmodel/sensitivity.py` (and similar modules storing trajectories) + +Current lines: + +- The `morris_analysis` function (approx lines 271‑400) stores every trajectory’s DataFrames (`prot_df`, `rna_df`, `phos_df`) in a list `trajectory_storage`, along with simulation metrics. Only the top‐ranked curves are used later, but all DataFrames remain in memory. + +Required change: + +- **Replace** the list of full DataFrames with an on‑disk store or stream the metrics. For example, write each simulation’s results to a temporary file (CSV/Parquet) and store only file paths and summary statistics in memory. After ranking, load only the necessary top trajectories. This ensures memory usage does not scale with the number of sensitivity samples. The numerical metrics remain identical. + +### File: `networkmodel/runner.py` (multi‑start logic) + +Current lines: + +- The `run_multistart` branch collects a pandas DataFrame with columns `X` and `F` for every start and appends them to a list. It may also keep entire simulation histories from each run. + +Required change: + +- **Modify** `run_multistart` so that after computing the objective value for a start, it retains only the parameter vector and objective scalar (or other minimal summary) in memory. Intermediate trajectories (`Y`, `states`, DataFrames) should be freed or written to disk immediately after evaluation. Optionally maintain an upper bound on the number of stored starts or use a streaming reducer to keep only the best `k` parameter sets. This change does not alter the optimization algorithm but prevents accumulating large data structures. + +## 6. Required Fixes + +### A. Fixes that only reduce memory materialization + +1. **Stream transitions** – Convert `build_random_transitions` to a generator and update ODE RHS and JAX backends to iterate over transitions lazily. + +2. Safe: ✅ + +3. Risk: low + +4. Reason: the same transitions are computed; only the storage strategy changes. + +5. **Lazy** `bits` **computation** – Replace the dense `bits` matrix with per‑site weight vectors computed on demand in `simulate_and_measure`. + +6. Safe: ✅ + +7. Risk: low + +8. Reason: computations use the same bitwise masks; results are identical. + +9. **Lazy** `S_cache` **and downcasting** – Allocate `S_cache` one column at a time or as a memory‑mapped array; downcast to `float32` where appropriate. + +10. Safe: ✅ + +11. Risk: low + +12. Reason: `S_cache` is an intermediate used for event times; using a smaller dtype or on‑disk storage does not change results. + +13. **Per‑protein JAX loops** – Refactor JAX RHS to avoid global `max_states` arrays; use per‑protein loops and `jax.lax.scan`. + +14. Safe: ✅ (with careful testing) + +15. Risk: medium + +16. Reason: requires rewriting the JAX function; while math is the same, subtle errors could occur. Comprehensive tests must be run. + +17. **Memory guard on n_sites** – Add a guard that raises an informative error if `2^n_sites` exceeds a safe threshold (e.g., 256 states). + +18. Safe: ✅ + +19. Risk: low + +20. Reason: prevents impossible runs; does not change correct behaviour for feasible models. + +### B. Fixes that prevent result/history retention + +1. **Streaming multi‑start results** – In `runner.py`, retain only essential summaries (parameter vector and objective) for each start; discard full trajectories and DataFrames after evaluation. + +2. Safe: ✅ + +3. Risk: low + +4. Reason: the optimization algorithm uses only objective values; storing less history does not alter optimization logic. + +5. **Stream sensitivity trajectories** – In `sensitivity.py`, write each simulation’s results to disk and load only top trajectories when needed. + +6. Safe: ✅ + +7. Risk: low + +8. Reason: analysis uses only selected trajectories; external storage preserves results without affecting ranking. + +### C. Fixes that add chunking or streaming + +1. **Chunked simulation extraction** – For very large `ns`, process subsets of states when computing per‑site signals. For example, divide `states` columns into manageable chunks and compute contributions sequentially. + +2. Safe: ✅ (provided chunk boundaries are handled correctly) + +3. Risk: medium + +4. Reason: chunking introduces additional loops; careful accumulation is required to avoid numerical drift. + +5. **Chunked hypercube enumeration** – When `build_random_transitions` is called for proteins with many sites, generate transitions in chunks (e.g., by enumerating states up to a maximum memory footprint). + +6. Safe: ✅ + +7. Risk: medium + +8. Reason: enumeration order must remain consistent for reproducibility. Implementation should test chunk boundaries thoroughly. + +### D. Fixes that add safety guards + +1. **Early error on infeasible state sizes** – After calculating `n_states[i]`, check if `n_states[i] × time_points` would exceed a memory threshold (e.g., \>10^8 elements) and raise a `MemoryError` with guidance. + +2. Safe: ✅ + +3. Risk: low + +4. Reason: prevents crashes by aborting early; does not alter valid runs. + +5. **Warn when JAX fallback is used** – If the JAX RHS cannot be compiled without full array materialization, print a warning and fall back to the numba implementation. + +6. Safe: ✅ + +7. Risk: low + +8. Reason: does not change outputs; simply switches to a slower but safer backend. + +### E. Fixes that improve logging/profiling without changing computation + +1. **Diagnostic logging** – Add optional logging to report estimated memory for state vectors, transitions and bit masks before simulation. This allows the user to adjust parameters. + +2. Safe: ✅ + +3. Risk: low + +4. Reason: adds diagnostics only. + +5. **Profile multi‑start memory usage** – Insert debug prints that show current memory usage after each start and automatically stop new starts if usage exceeds a threshold. + +6. Safe: ✅ + +7. Risk: low + +8. Reason: does not alter optimization results; just aborts early to avoid crashes. + +## 7. What Must Not Change + +- **Model equations and mechanistic logic** – The differential equations for translation, dephosphorylation and phosphorylation in the combinatorial model must remain exactly as implemented. Only the representation of transitions and states may change. +- **Optimization and ranking algorithms** – Multistart and sensitivity routines must still compute objective values and rank parameter sets identically. Only memory handling around these computations may change. +- **Data formats and API** – Input file formats, command‑line interfaces and output data structures must be preserved. Any downcasting must be optional and off by default to maintain precision. +- **Public semantics of combinatorial vs sequential/distributive models** – The conditions under which each model is selected must not change; the user must explicitly choose the combinatorial model. + +## 8. Validation Plan + +1. **Tiny combinatorial smoke test** – Create a minimal network with one protein and two phosphorylation sites (`n_sites=2`). Run the combinatorial model with and without the fixes and ensure that ODE trajectories, per‑site signals and objective values match to within numerical tolerance. +2. **Medium‑size memory test** – Construct a network with three proteins, each with `n_sites=6`, and run a single simulation. Measure peak memory usage using `tracemalloc` or `psutil` before and after the fixes. The fixed version should consume significantly less memory (ideally \<1 GB for simulation extraction). +3. **Comparison with distributive/sequential models** – Run the distributive and sequential models for the same network pre‑ and post‑fix. Confirm that their outputs and performance remain unchanged, demonstrating that the fixes are isolated to the combinatorial path. +4. **Combinatorial numerical fidelity** – For a network with `n_sites=3`, compute the loss values and gradients using both the original and the fixed code paths. Assert that differences are below a small tolerance (e.g., `1e‑10` for loss and `1e‑8` for gradients). +5. **Peak memory scaling** – Vary `n_sites` from 2 to 10 and record peak memory usage. Verify that memory scales roughly linearly with `2^n_sites` only while computing per‑site signals, not multiplied by the number of sites or time bins. Ensure there is no global `max_states` explosion. +6. **Retention test** – Run a multistart optimization with 10 starts on the medium network and monitor memory usage across starts. Confirm that memory remains bounded and does not accumulate across starts. + +## 9. Expected Memory Impact + +Implementing the above fixes should dramatically reduce memory usage: + +- **Transition storage** – By streaming transitions instead of storing dense arrays, memory consumption drops from `O(2^n_sites × n_sites)` per protein to `O(1)` plus a small generator overhead. +- **Bit‑mask computation** – Per‑site streaming removes the need for an `ns × n_sites` matrix; memory used becomes proportional to `ns` at most. For `n_sites=10`, this saves `2^10 × 10 × 8 bytes ≈ 80 KB` per protein per time point. +- **Trajectory extraction** – Freeing state slices and storing only necessary signals reduces retained memory by orders of magnitude, especially in multistart and sensitivity loops. +- **JAX backend** – Per‑protein loops avoid global arrays of size `max_states`; memory overhead becomes proportional to the largest protein rather than all proteins. +- **Overall** – With these changes, running a medium combinatorial model (e.g., three proteins with `n_sites=6`) should require \<2 GB of RAM, enabling multi‑start optimization on typical servers. + +## 10. Implementation Checklist + +1. \[ \] Refactor `build_random_transitions` to yield transitions instead of returning dense arrays. +2. \[ \] Update all RHS implementations (Numba and JAX) to iterate over transition generators. +3. \[ \] Modify `System.__init__` to store transition iterators and allocate `S_cache` lazily or as a memory‑mapped array. +4. \[ \] Add a memory guard in `Index.__init__` to warn or abort when `2^n_sites` exceeds a safe threshold. +5. \[ \] Replace dense `bits` matrix construction with per‑site streaming in `simulate_and_measure` and free intermediate arrays promptly. +6. \[ \] Refactor JAX combinatorial RHS to use per‑protein loops without global `max_states` arrays; test with `jax.lax.scan`. +7. \[ \] Downcast intermediate combinatorial arrays to `float32` with a configuration flag and cast outputs back to `float64` when necessary. +8. \[ \] Stream DataFrame and trajectory storage in sensitivity analysis; write temporary results to disk and keep only summaries in memory. +9. \[ \] Stream multistart results; retain only top parameter sets and objective values in memory. +10. \[ \] Add diagnostic logging and memory profiling utilities to inform users of estimated memory footprints and warn when thresholds are exceeded. +11. \[ \] Write unit tests implementing the validation plan; ensure outputs match the original code and memory usage is reduced. + +[\[1\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/network.py#:~:text=,i) [\[5\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/network.py#:~:text=,1%5D%29%2C%20dtype%3Dnp.float64) [\[6\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/network.py#:~:text=,1%5D%29%2C%20dtype%3Dnp.float64) raw.githubusercontent.com + + + +[\[2\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/simulate.py#:~:text=ns%20%3D%20int%28idx.n_states,p0%20%3D%20st%20%2B%201) raw.githubusercontent.com + + + +[\[3\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/models.py#:~:text=def%20build_random_transitions%28idx%29%3A%20,for%20combinatorial%20topology) raw.githubusercontent.com + + + +[\[4\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/backend.py#:~:text=) raw.githubusercontent.com + + From 1cb05b3ac56c42e2558661bfc8aebc68f1d0ce82 Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Tue, 16 Jun 2026 18:18:05 +0530 Subject: [PATCH 31/42] Make combinatorial model memory safe --- docs/Combinatorial_Model_Memory_Issue.md | 21 +++++ networkmodel/backend.py | 35 +++----- networkmodel/models.py | 103 ++++++++++++----------- networkmodel/network.py | 58 ++++++++++--- networkmodel/sensitivity.py | 7 ++ networkmodel/simulate.py | 32 +++++-- tests/test_combinatorial_memory_safe.py | 76 +++++++++++++++++ 7 files changed, 239 insertions(+), 93 deletions(-) create mode 100644 tests/test_combinatorial_memory_safe.py diff --git a/docs/Combinatorial_Model_Memory_Issue.md b/docs/Combinatorial_Model_Memory_Issue.md index 3a30e66..3d7a3d5 100644 --- a/docs/Combinatorial_Model_Memory_Issue.md +++ b/docs/Combinatorial_Model_Memory_Issue.md @@ -279,3 +279,24 @@ Implementing the above fixes should dramatically reduce memory usage: [\[4\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/networkmodel/backend.py#:~:text=) raw.githubusercontent.com + +## 11. Implemented Memory-Safe Behavior + +The combinatorial implementation now keeps the same biological equations, objective values, ranking semantics, CLI options, input formats and output tables, while reducing unnecessary materialization: + +- `MODEL=2` still has an inherent `2^n_sites` state space. `Index` now validates each protein after computing `n_states = 1 << n_sites` and raises an informative `MemoryError` before simulation when the per-protein or total state dimension is unsafe. The error explains the exponential scaling and recommends reducing sites, choosing sequential/distributive models, or lowering workload. +- Combinatorial transition order is unchanged: transitions are enumerated by state mask first and site index second, yielding only unset-bit phosphorylation edges. Large proteins no longer require dense `trans_from`, `trans_to` and `trans_site` arrays for RHS evaluation; dense arrays are retained only for small compatibility cases. +- Combinatorial phosphosite signal extraction no longer builds the dense `ns x n_sites` bit matrix. Each site is aggregated with the equivalent bit-mask vector and temporaries are released immediately after use. This changes only memory materialization, not returned DataFrame columns or values. +- `S_cache` for combinatorial mode is now a reusable current-site-rate buffer rather than an unconditional site-by-time dense matrix. The RHS receives the same current rates used by the previous time-bucketed calculation. +- The JAX/Diffrax combinatorial RHS now generates phosphorylation edges per protein from local `n_states`/`n_sites` metadata instead of depending on global dense transition arrays. It still uses JAX-compatible loops and preserves differentiability through kinase scales and site rates. +- Sensitivity trajectory retention is bounded to the configured top-curve count during simulation collection, so all trajectory DataFrames are not accumulated in memory. Output files and ranking/reporting semantics are preserved. +- Multistart optimization already stores only bounded summaries and parameter vectors for starts (`summary`, `parameters`, `best` tables) rather than full trajectories or histories; no trajectory retention is introduced. + +### Interpreting guard errors + +A guard error means the requested combinatorial topology is too large to run safely in this process. Because every additional phosphosite doubles the number of protein state variables, safe settings depend primarily on the maximum number of sites on any single protein and the number of requested output time points. Recommended actions are: + +1. reduce the number of phosphosites included for high-degree proteins; +2. use `MODEL=0` (distributive) or `MODEL=1` (sequential) when combinatorial state occupancy is not required; +3. reduce workload such as the number of starts, sensitivity trajectories, or output times; and +4. rerun after checking the combinatorial diagnostics in the log, which report proteins, `n_sites`, `n_states`, estimated total state dimension, estimated trajectory memory and the dense transition memory that is now avoided. diff --git a/networkmodel/backend.py b/networkmodel/backend.py index bc9ba5b..9ef6626 100644 --- a/networkmodel/backend.py +++ b/networkmodel/backend.py @@ -254,12 +254,6 @@ def make_networkmodel_rhs(sys, slices=None): N = int(idx.N) max_sites = int(np.max(idx.n_sites)) if idx.N else 0 max_states = int(np.max(getattr(idx, "n_states", np.ones(idx.N, dtype=np.int32)))) if idx.N else 1 - trans_from = jnp.asarray(getattr(sys, "trans_from", np.zeros(0, dtype=np.int32)), dtype=jnp.int32) - trans_to = jnp.asarray(getattr(sys, "trans_to", np.zeros(0, dtype=np.int32)), dtype=jnp.int32) - trans_site = jnp.asarray(getattr(sys, "trans_site", np.zeros(0, dtype=np.int32)), dtype=jnp.int32) - trans_off = jnp.asarray(getattr(sys, "trans_off", np.zeros(N, dtype=np.int32)), dtype=jnp.int32) - trans_n = jnp.asarray(getattr(sys, "trans_n", np.zeros(N, dtype=np.int32)), dtype=jnp.int32) - max_trans = int(np.max(getattr(sys, "trans_n", np.zeros(N, dtype=np.int32)))) if N else 0 def _params(args): if isinstance(args, dict): @@ -348,21 +342,20 @@ def _stepwise(row): dp_rate = dp_rate + jnp.where(valid_bit, par["Dp_i"][flat_j] + par["D_i"][i], 0.0) dy = dy.at[pos_m].add(-dp_rate * Pm) - # Explicit phosphorylation transitions from the precomputed sparse - # hypercube graph. Use S_all at the flattened site index so rates - # remain differentiable through kinase scales and site parameters. - for k in range(max_trans): - tr_idx = jnp.minimum(trans_off[i] + k, trans_from.shape[0] - 1) - valid_tr = k < trans_n[i] - frm = trans_from[tr_idx] - to = trans_to[tr_idx] - j = trans_site[tr_idx] - pos_frm = jnp.minimum(p0 + frm, y.shape[0] - 1) - pos_to = jnp.minimum(p0 + to, y.shape[0] - 1) - flat_j = jnp.minimum(s_off + j, S_all.shape[0] - 1) - flux = jnp.where(valid_tr, S_all[flat_j] * y[pos_frm], 0.0) - dy = dy.at[pos_frm].add(-flux) - dy = dy.at[pos_to].add(flux) + # Explicit phosphorylation transitions, generated per protein + # in the same mask/site order as the historical dense arrays. + for m in range(max_states): + valid_m = m < nst + for j in range(max_sites): + bit_unset = ((m >> j) & 1) == 0 + valid_tr = valid_m & (j < ns) & bit_unset + to = m | (1 << j) + pos_frm = jnp.minimum(p0 + m, y.shape[0] - 1) + pos_to = jnp.minimum(p0 + to, y.shape[0] - 1) + flat_j = jnp.minimum(s_off + j, S_all.shape[0] - 1) + flux = jnp.where(valid_tr, S_all[flat_j] * y[pos_frm], 0.0) + dy = dy.at[pos_frm].add(-flux) + dy = dy.at[pos_to].add(flux) else: P = y[off + 1] ar = jnp.arange(max_sites, dtype=jnp.int32) diff --git a/networkmodel/models.py b/networkmodel/models.py index 8284048..97eaf42 100644 --- a/networkmodel/models.py +++ b/networkmodel/models.py @@ -316,10 +316,9 @@ def _bit_index_from_lsb(lsb): def combinatorial_rhs( y, dy, A_i, B_i, C_i, D_i, Dp_i, E_i, tf_scale, - TF_inputs, S_cache, jb, + TF_inputs, S_rates, offset_y, offset_s, - n_sites, n_states, - trans_from, trans_to, trans_site, trans_off, trans_n + n_sites, n_states ): """Evaluate the combinatorial topology right-hand side @@ -334,21 +333,13 @@ def combinatorial_rhs( E_i: Input value used by this routine. tf_scale: Input value used by this routine. TF_inputs: Input value used by this routine. - S_cache: Input value used by this routine. - jb: Input value used by this routine. + S_rates: Current per-site kinase signal vector. offset_y: Input value used by this routine. offset_s: Input value used by this routine. n_sites: Input value used by this routine. n_states: Input value used by this routine. - trans_from: Input value used by this routine. - trans_to: Input value used by this routine. - trans_site: Input value used by this routine. - trans_off: Input value used by this routine. - trans_n: Input value used by this routine. """ N = A_i.shape[0] - jb_loc = jb # local binding helps Numba - for i in range(N): y_start = offset_y[i] s_start = offset_s[i] @@ -421,59 +412,70 @@ def combinatorial_rhs( dy[base + m] -= dp_rate * Pm # --- Phosphorylation Loop (Forward Transitions) --- - # Uses pre-calculated sparse graph structure - off = trans_off[i] - ntr = trans_n[i] - for k in range(ntr): - frm = trans_from[off + k] - to = trans_to[off + k] - j = trans_site[off + k] + # Enumerate the same hypercube edges in the same order as the former + # dense transition arrays, but do not materialize O(2^n_sites*n_sites) + # arrays. + for m in range(nstates): + for j in range(ns): + bit = 1 << j + if (m & bit) == 0: + to = m | bit + rate = S_rates[s_start + j] + flux = rate * y[base + m] - # Rate depends on time bucket 'jb_loc' - rate = S_cache[s_start + j, jb_loc] - flux = rate * y[base + frm] + dy[base + m] -= flux + dy[base + to] += flux - dy[base + frm] -= flux - dy[base + to] += flux +def iter_random_transitions_for_sites(n_sites): + """Yield combinatorial forward transitions for one protein lazily. -def build_random_transitions(idx): - """Build transition arrays for combinatorial topology - - Args: - idx: Input value used by this routine. - - Returns: - Computed result from this routine. + The order is identical to the historical dense implementation: state mask + first, then site index, yielding only unset-bit phosphorylation edges. + """ + ns = int(n_sites) + if ns <= 0: + return + nstates = 1 << ns + for m in range(nstates): + for j in range(ns): + if (m & (1 << j)) == 0: + yield m, m | (1 << j), j + + +def count_random_transitions_for_sites(n_sites): + """Return the number of combinatorial forward transitions for n sites.""" + ns = int(n_sites) + return 0 if ns <= 0 else ns * (1 << (ns - 1)) + + +def build_random_transitions(idx, *, dense_threshold_sites=4): + """Build small dense transition arrays for compatibility. + + Large proteins are represented by metadata only; callers that need all + transitions should use :func:`iter_random_transitions_for_sites` instead. """ trans_from = [] trans_to = [] trans_site = [] trans_off = np.zeros(idx.N, dtype=np.int32) trans_n = np.zeros(idx.N, dtype=np.int32) + dense_available = np.zeros(idx.N, dtype=np.bool_) cur = 0 for i in range(idx.N): ns = int(idx.n_sites[i]) trans_off[i] = cur - - if ns == 0: - trans_n[i] = 0 - continue - - nstates = 1 << ns - for m in range(nstates): - for j in range(ns): - # If bit j is NOT set in m, we can transition to m | (1< COMBINATORIAL_MAX_STATES_PER_PROTEIN: + raise MemoryError( + f"Unsafe combinatorial MODEL=2 state space for protein {protein!r}: " + f"n_sites={ns} requires n_states=2^n_sites={nstates:,}. " + "MODEL=2 scales exponentially as 2^n_sites; reduce the number of sites, " + "use sequential/distributive models, or lower the workload." + ) + n_states_list.append(nstates) + self.n_states = np.asarray(n_states_list, dtype=np.int64) # Offsets map standard indices to the flattened y-vector self.offset_y = np.zeros(self.N, dtype=np.int32) @@ -126,6 +142,22 @@ def __init__(self, self.state_dim = curr_y self.total_sites = int(curr_s) + if MODEL == 2: + if self.state_dim > COMBINATORIAL_MAX_TOTAL_STATE_DIM: + raise MemoryError( + f"Unsafe combinatorial MODEL=2 total state dimension: {self.state_dim:,} state variables. " + "MODEL=2 scales as 2^n_sites per protein; reduce sites, use sequential/distributive " + "models, or lower workload." + ) + transition_count = int(sum((int(ns) * (1 << (int(ns) - 1))) if int(ns) > 0 else 0 for ns in self.n_sites)) + dense_transition_mb = transition_count * 3 * np.dtype(np.int32).itemsize / (1024 ** 2) + traj_mb = self.state_dim * len(TIME_POINTS_PROTEIN) * np.dtype(np.float64).itemsize / (1024 ** 2) + logger.warning( + "[Model] Combinatorial MODEL=2 diagnostics: proteins=%d n_sites=%s n_states=%s " + "total_state_dim=%d estimated_trajectory=%.2f MiB dense_transition_arrays=%.2f MiB. " + "MODEL=2 scales exponentially as 2^n_sites.", + self.N, self.n_sites.tolist(), self.n_states.tolist(), self.state_dim, traj_mb, dense_transition_mb + ) self.kinase_indices_in_P = [self.p2i[k] for k in self.kinases if k in self.p2i] self.p2k = {k: i for i, k in enumerate(self.kinases)} @@ -269,18 +301,22 @@ def __init__(self, idx, W_global, tf_mat, kin_input, defaults, tf_deg): # MODEL == 2 specific setup # ------------------------------------------------------------ if MODEL == 2: - # reusable work buffers (NO allocs in RHS) + # reusable work buffers (NO allocs in RHS). S_cache is a one-column + # compatibility buffer populated from the current kinase signal, not + # a dense site-by-time cache. self.P_vec_work = np.zeros(self.n_TF_rows, dtype=np.float64) self.TF_in_work = np.zeros(self.n_TF_rows, dtype=np.float64) - self.S_cache = np.zeros((self.n_W_rows, self.kin_Kmat.shape[1]), dtype=np.float64) + self.S_cache = np.zeros(self.n_W_rows, dtype=np.float64) - # precomputed transition lists for the combinatorial hypercube graph + # Dense transitions are retained only for small compatibility tests; + # RHS evaluation streams transitions from n_sites/n_states metadata. ( self.trans_from, self.trans_to, self.trans_site, self.trans_off, self.trans_n, + self.trans_dense_available, ) = build_random_transitions(idx) def update(self, c_k, A_i, B_i, C_i, D_i, Dp_i, E_i, tf_scale): @@ -418,22 +454,16 @@ def rhs(self, t, y): elif MODEL == 2: if self.S_cache is None: - raise ValueError("MODEL==2: System.S_cache is None. simulate_diffrax must set it.") - - jb = int(np.searchsorted(self.kin_grid, t, side="right") - 1) - if jb < 0: - jb = 0 - elif jb >= self.kin_grid.size: - jb = self.kin_grid.size - 1 + raise ValueError("MODEL==2: System.S_cache is None.") + self.S_cache[:] = S_all combinatorial_rhs( y, dy, self.A_i, self.B_i, self.C_i, self.D_i, self.Dp_i, self.E_i, self.tf_scale, TF_inputs, - self.S_cache, jb, + self.S_cache, self.idx.offset_y, self.idx.offset_s, - self.idx.n_sites, self.idx.n_states, - self.trans_from, self.trans_to, self.trans_site, self.trans_off, self.trans_n + self.idx.n_sites, self.idx.n_states ) return dy diff --git a/networkmodel/sensitivity.py b/networkmodel/sensitivity.py index 85c4c55..baa2ace 100644 --- a/networkmodel/sensitivity.py +++ b/networkmodel/sensitivity.py @@ -447,6 +447,13 @@ def run_sensitivity_analysis(sys, idx, fitted_params, output_dir, metric="l2_nor "phos_df": dfph, } ) + # Keep only the bounded set needed for identical top-curve + # reporting instead of retaining every trajectory DataFrame. + if len(trajectory_storage) > int(SENSITIVITY_TOP_CURVES): + trajectory_storage = _select_top_trajectories( + trajectory_storage, + max_items=SENSITIVITY_TOP_CURVES, + ) except Exception as exc: failed_rows.append( diff --git a/networkmodel/simulate.py b/networkmodel/simulate.py index 8cbdf61..5dedcc9 100644 --- a/networkmodel/simulate.py +++ b/networkmodel/simulate.py @@ -11,6 +11,22 @@ from networkmodel.backend import DiffraxSolverConfig, make_networkmodel_rhs, solve_diffrax +def combinatorial_site_signals_streaming(states, n_sites): + """Return per-site combinatorial signals without building an ns x n_sites bit matrix.""" + state_view = np.asarray(states, dtype=np.float64) + if state_view.ndim != 2: + raise ValueError("states must be a two-dimensional time-by-state array") + ns = state_view.shape[1] + n_sites = int(n_sites) + out = np.empty((state_view.shape[0], n_sites), dtype=np.float64) + masks = np.arange(ns, dtype=np.uint64) + for site in range(n_sites): + weights = ((masks >> np.uint64(site)) & np.uint64(1)).astype(np.float64, copy=False) + out[:, site] = state_view @ weights + del weights + return out + + def simulate_diffrax(sys, t_eval, rtol=None, atol=None, max_steps=None, solver_name="Kvaerno4"): """Simulate a System over requested time points with Diffrax @@ -103,20 +119,20 @@ def _bidx(t0: float) -> int: fc_p = np.maximum(tot, 1e-12) / np.maximum(tot[prot_b], 1e-12) rows_p.append(pd.DataFrame({"protein": gene, "time": times, "pred_fc": fc_p})) - # Phospho Sites: Bitwise aggregation - # We map states to sites using a matrix multiplication (State x Bitmask) + # Phospho Sites: Bitwise aggregation, streamed one site at a time + # to avoid an ns x n_sites dense bit matrix. if n_sites > 0: - m = np.arange(ns, dtype=np.uint32)[:, None] - j = np.arange(n_sites, dtype=np.uint32)[None, :] - bits = ((m >> j) & 1).astype(np.float64) # (ns, n_sites) - pho_sites = states @ bits # (T, n_sites) - + masks = np.arange(ns, dtype=np.uint64) for s_idx, psite in enumerate(idx.sites[i]): - sig = pho_sites[:, s_idx] + weights = ((masks >> np.uint64(s_idx)) & np.uint64(1)).astype(np.float64, copy=False) + sig = states @ weights fc = np.maximum(sig, 1e-12) / np.maximum(sig[pho_b], 1e-12) rows_pho.append(pd.DataFrame({ "protein": gene, "psite": psite, "time": times, "pred_fc": fc })) + del weights, sig + del masks + del states else: # --- Standard Model Extraction (Distributive/Sequential) --- diff --git a/tests/test_combinatorial_memory_safe.py b/tests/test_combinatorial_memory_safe.py new file mode 100644 index 0000000..8ae881e --- /dev/null +++ b/tests/test_combinatorial_memory_safe.py @@ -0,0 +1,76 @@ +import numpy as np +import pandas as pd +import pytest + +from networkmodel.models import iter_random_transitions_for_sites, build_random_transitions +from networkmodel.simulate import combinatorial_site_signals_streaming + + +def _dense_transitions(n_sites): + out = [] + for m in range(1 << n_sites): + for j in range(n_sites): + if (m & (1 << j)) == 0: + out.append((m, m | (1 << j), j)) + return out + + +@pytest.mark.parametrize("n_sites", [2, 3, 4]) +def test_streaming_bit_extraction_matches_dense(n_sites): + rng = np.random.default_rng(123 + n_sites) + states = rng.normal(size=(5, 1 << n_sites)) + m = np.arange(1 << n_sites, dtype=np.uint32)[:, None] + j = np.arange(n_sites, dtype=np.uint32)[None, :] + bits = ((m >> j) & 1).astype(np.float64) + expected = states @ bits + actual = combinatorial_site_signals_streaming(states, n_sites) + np.testing.assert_allclose(actual, expected, rtol=0.0, atol=1e-12) + + +@pytest.mark.parametrize("n_sites", [0, 1, 2, 3, 4]) +def test_transition_iterator_matches_dense_order(n_sites): + assert list(iter_random_transitions_for_sites(n_sites)) == _dense_transitions(n_sites) + + +def test_build_random_transitions_keeps_small_dense_compatibility(): + class Idx: + N = 1 + n_sites = np.array([2], dtype=np.int32) + + frm, to, site, off, ntr, dense = build_random_transitions(Idx()) + expected = _dense_transitions(2) + assert off.tolist() == [0] + assert ntr.tolist() == [len(expected)] + assert dense.tolist() == [True] + assert list(zip(frm.tolist(), to.tolist(), site.tolist())) == expected + + +def test_build_random_transitions_avoids_large_dense_storage(): + class Idx: + N = 1 + n_sites = np.array([5], dtype=np.int32) + + frm, to, site, off, ntr, dense = build_random_transitions(Idx(), dense_threshold_sites=4) + assert frm.size == to.size == site.size == 0 + assert off.tolist() == [0] + assert ntr.tolist() == [5 * (1 << 4)] + assert dense.tolist() == [False] + + +def test_tiny_combinatorial_smoke_signals(): + states = np.array([[1.0, 2.0, 3.0, 4.0], [2.0, 3.0, 5.0, 7.0]]) + signals = combinatorial_site_signals_streaming(states, 2) + expected = np.array([[6.0, 7.0], [10.0, 12.0]]) + np.testing.assert_allclose(signals, expected, rtol=0.0, atol=1e-12) + + +def test_memory_guard_message(monkeypatch): + import networkmodel.network as network + + monkeypatch.setattr(network, "MODEL", 2) + monkeypatch.setattr(network, "COMBINATORIAL_MAX_STATES_PER_PROTEIN", 4) + interactions = pd.DataFrame( + {"protein": ["P", "P", "P"], "psite": ["S1", "S2", "S3"], "kinase": ["K", "K", "K"]} + ) + with pytest.raises(MemoryError, match="MODEL=2 scales"): + network.Index(interactions) From bcc32133a5b38b3582c725ee393662795e46fb87 Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Tue, 16 Jun 2026 18:31:31 +0530 Subject: [PATCH 32/42] Fix combinatorial S-rate export cache shape --- networkmodel/export.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/networkmodel/export.py b/networkmodel/export.py index 8c24474..d5b9eff 100644 --- a/networkmodel/export.py +++ b/networkmodel/export.py @@ -1052,9 +1052,11 @@ def export_S_rates(sys, idx, output_dir, filename="S_rates_picked.csv", long=Tru # ---- compute S matrix: shape (total_sites, n_bins) ---- if MODEL == 2: - # Ensure cache matches current optimized c_k - build_S_cache_into(sys.S_cache, sys.W_indptr, sys.W_indices, sys.W_data, sys.kin_Kmat, sys.c_k) - S_mat = np.asarray(sys.S_cache, dtype=np.float64) + # The combinatorial RHS may use a 1-D current-rate work buffer for + # memory safety, but S_rates_picked.csv preserves the historical dense + # site-by-time export shape. Build that dense matrix only for export. + S_mat = np.empty((int(sys.n_W_rows), int(sys.kin_Kmat.shape[1])), dtype=np.float64) + build_S_cache_into(S_mat, sys.W_indptr, sys.W_indices, sys.W_data, sys.kin_Kmat, sys.c_k) times = np.asarray(sys.kin_grid, dtype=float) else: # Dense kinase signal scaled by c_k From 0504c1fd11499e77cf232925764e670f6f3767dc Mon Sep 17 00:00:00 2001 From: bibymaths Date: Tue, 16 Jun 2026 18:10:18 +0200 Subject: [PATCH 33/42] fix: combinatorial model state phase explosion down to O(1) runtime, no memory explosion in for loop, vectorized RHS for combinatorial model. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Example: 10 multi-starts 17 protein entities × 14 time points, 17 RNA entities × 9 time points, 36 phosphosites × 14 time points 238 protein rows, 153 RNA rows, 504 phospho rows | Total 895 observation rows Parameter vector size: 149 Memory is use: 18 GB RAM on server --- config.toml | 4 +- networkmodel/backend.py | 154 +++++++++++++++++++++++++++------------- 2 files changed, 108 insertions(+), 50 deletions(-) diff --git a/config.toml b/config.toml index 320aacd..1609153 100644 --- a/config.toml +++ b/config.toml @@ -273,7 +273,7 @@ tfopt = "data/tfopt_results.xlsx" # ------------------------------------------------------------ # RUN SETTINGS # ------------------------------------------------------------ -output_dir = "results_network_sequential" # Output directory +output_dir = "results_network_combinatorial" # Output directory cores = 80 # 0 or leave out to use all available cores seed = 42 # ------------------------------------------------------------ @@ -393,7 +393,7 @@ tf_scale = [2.0, 10.0] [networkmodel.models] available_models = ["distributive", "sequential", "combinatorial", "saturation"] -default_model = "sequential" +default_model = "combinatorial" [networkmodel.solver] absolute_tolerance = 1e-8 diff --git a/networkmodel/backend.py b/networkmodel/backend.py index 9ef6626..1daf266 100644 --- a/networkmodel/backend.py +++ b/networkmodel/backend.py @@ -273,6 +273,17 @@ def _synth(Ai, tf_scale, u_raw): Ai / (1.0 + tf_scale * jnp.abs(u)), ) + # Static metadata for compact MODEL == 2 JAX tracing. + # Do not use global max_states/max_sites loops inside the jitted RHS. + offsets_list = [int(x) for x in np.asarray(idx.offset_y)] + site_offsets_list = [int(x) for x in np.asarray(idx.offset_s)] + n_sites_list = [int(x) for x in np.asarray(idx.n_sites)] + n_states_list = [ + int(x) for x in np.asarray( + getattr(idx, "n_states", np.ones(idx.N, dtype=np.int32)) + ) + ] + def rhs(t, y, args): par = _params(args) @@ -290,11 +301,9 @@ def _stepwise(row): off = offsets[i] drv = driver_map[i] if model_id == 2: - ar = jnp.arange(max_states, dtype=jnp.int32) - valid = ar < n_states[i] - pos = jnp.minimum(off + 1 + ar, y.shape[0] - 1) - vals = jnp.where(valid, y[pos], 0.0) - total_p = jnp.sum(vals) + p0 = offsets_list[i] + 1 + nst_i = n_states_list[i] + total_p = jnp.sum(y[p0:p0 + nst_i]) else: ar = jnp.arange(max_sites, dtype=jnp.int32) valid = ar < n_sites[i] @@ -313,49 +322,99 @@ def _stepwise(row): R = y[off] synth = _synth(par["A_i"][i], par["tf_scale"], TF_inputs[i]) dy = dy.at[off].set(synth - par["B_i"][i] * R) + # if model_id == 2: + # # Combinatorial model: mirror models.combinatorial_rhs for the + # # Diffrax/JAX path. Translation feeds only mask 0, while explicit + # # phosphorylation transitions and implicit bit dephosphorylation + # # transitions move mass among all 2^n mask states. + # p0 = off + 1 + # nst = n_states[i] + # if max_states > 0: + # P0 = y[p0] + # dy = dy.at[p0].add(par["C_i"][i] * R - par["D_i"][i] * P0) + # + # # Dephosphorylation and per-site phospho-state decay for masks m > 0. + # for m in range(1, max_states): + # valid_m = m < nst + # pos_m = jnp.minimum(p0 + m, y.shape[0] - 1) + # Pm = jnp.where(valid_m, y[pos_m], 0.0) + # dp_rate = 0.0 + # for j in range(max_sites): + # bit_set = ((m >> j) & 1) != 0 + # valid_bit = valid_m & (j < ns) & bit_set + # flat_j = jnp.minimum(s_off + j, par["Dp_i"].shape[0] - 1) + # to = m ^ (1 << j) + # pos_to = jnp.minimum(p0 + to, y.shape[0] - 1) + # flux = jnp.where(valid_bit, par["E_i"][i] * Pm, 0.0) + # dy = dy.at[pos_m].add(-flux) + # dy = dy.at[pos_to].add(flux) + # dp_rate = dp_rate + jnp.where(valid_bit, par["Dp_i"][flat_j] + par["D_i"][i], 0.0) + # dy = dy.at[pos_m].add(-dp_rate * Pm) + # + # # Explicit phosphorylation transitions, generated per protein + # # in the same mask/site order as the historical dense arrays. + # for m in range(max_states): + # valid_m = m < nst + # for j in range(max_sites): + # bit_unset = ((m >> j) & 1) == 0 + # valid_tr = valid_m & (j < ns) & bit_unset + # to = m | (1 << j) + # pos_frm = jnp.minimum(p0 + m, y.shape[0] - 1) + # pos_to = jnp.minimum(p0 + to, y.shape[0] - 1) + # flat_j = jnp.minimum(s_off + j, S_all.shape[0] - 1) + # flux = jnp.where(valid_tr, S_all[flat_j] * y[pos_frm], 0.0) + # dy = dy.at[pos_frm].add(-flux) + # dy = dy.at[pos_to].add(flux) if model_id == 2: - # Combinatorial model: mirror models.combinatorial_rhs for the - # Diffrax/JAX path. Translation feeds only mask 0, while explicit - # phosphorylation transitions and implicit bit dephosphorylation - # transitions move mass among all 2^n mask states. - p0 = off + 1 - nst = n_states[i] - if max_states > 0: - P0 = y[p0] - dy = dy.at[p0].add(par["C_i"][i] * R - par["D_i"][i] * P0) - - # Dephosphorylation and per-site phospho-state decay for masks m > 0. - for m in range(1, max_states): - valid_m = m < nst - pos_m = jnp.minimum(p0 + m, y.shape[0] - 1) - Pm = jnp.where(valid_m, y[pos_m], 0.0) - dp_rate = 0.0 - for j in range(max_sites): - bit_set = ((m >> j) & 1) != 0 - valid_bit = valid_m & (j < ns) & bit_set - flat_j = jnp.minimum(s_off + j, par["Dp_i"].shape[0] - 1) - to = m ^ (1 << j) - pos_to = jnp.minimum(p0 + to, y.shape[0] - 1) - flux = jnp.where(valid_bit, par["E_i"][i] * Pm, 0.0) - dy = dy.at[pos_m].add(-flux) - dy = dy.at[pos_to].add(flux) - dp_rate = dp_rate + jnp.where(valid_bit, par["Dp_i"][flat_j] + par["D_i"][i], 0.0) - dy = dy.at[pos_m].add(-dp_rate * Pm) - - # Explicit phosphorylation transitions, generated per protein - # in the same mask/site order as the historical dense arrays. - for m in range(max_states): - valid_m = m < nst - for j in range(max_sites): - bit_unset = ((m >> j) & 1) == 0 - valid_tr = valid_m & (j < ns) & bit_unset - to = m | (1 << j) - pos_frm = jnp.minimum(p0 + m, y.shape[0] - 1) - pos_to = jnp.minimum(p0 + to, y.shape[0] - 1) - flat_j = jnp.minimum(s_off + j, S_all.shape[0] - 1) - flux = jnp.where(valid_tr, S_all[flat_j] * y[pos_frm], 0.0) - dy = dy.at[pos_frm].add(-flux) - dy = dy.at[pos_to].add(flux) + # Vectorized combinatorial MODEL == 2 RHS. + # This avoids Python loops over max_states inside JAX tracing. + p0 = offsets_list[i] + 1 + s_off_i = site_offsets_list[i] + ns_i = n_sites_list[i] + nst_i = n_states_list[i] + + P = y[p0:p0 + nst_i] + states = jnp.arange(nst_i, dtype=jnp.int32) + + dy_block = jnp.zeros_like(P) + + # Translation feeds only mask 0. + dy_block = dy_block.at[0].add( + par["C_i"][i] * R - par["D_i"][i] * P[0] + ) + + # Site-wise vectorized transitions. + # Keep loop over sites only; do not loop over states in Python. + for j in range(ns_i): + bit = np.int32(1 << j) + flat_j = s_off_i + j + + bit_set = (states & bit) != 0 + bit_unset = ~bit_set + + # Dephosphorylation transition: + # m -> m ^ bit for states where bit is set. + from_set = jnp.where(bit_set, P, 0.0) + to_clear = states ^ bit + flux_back = par["E_i"][i] * from_set + + dy_block = dy_block - flux_back + dy_block = dy_block.at[to_clear].add(flux_back) + + # Per-site phospho-state decay for states where bit is set. + decay = (par["Dp_i"][flat_j] + par["D_i"][i]) * from_set + dy_block = dy_block - decay + + # Phosphorylation transition: + # m -> m | bit for states where bit is unset. + from_unset = jnp.where(bit_unset, P, 0.0) + to_set = states | bit + flux_fwd = S_all[flat_j] * from_unset + + dy_block = dy_block - flux_fwd + dy_block = dy_block.at[to_set].add(flux_fwd) + + dy = dy.at[p0:p0 + nst_i].add(dy_block) else: P = y[off + 1] ar = jnp.arange(max_sites, dtype=jnp.int32) @@ -379,7 +438,6 @@ def _stepwise(row): return rhs - def solve_diffrax(y0, t_eval, params=None, rhs=None, config: DiffraxSolverConfig | None = None): """Solve an ODE trajectory with Diffrax From b931c96e0589caae8776d8b0383b781f1fcb9947 Mon Sep 17 00:00:00 2001 From: bibymaths Date: Wed, 17 Jun 2026 12:08:23 +0200 Subject: [PATCH 34/42] fix: ambiguity in model loading for forward simulation-KO/WT dashboard --- scripts/compare_mechanisms.py | 38 ++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/scripts/compare_mechanisms.py b/scripts/compare_mechanisms.py index 2f8bca9..fc89cf4 100644 --- a/scripts/compare_mechanisms.py +++ b/scripts/compare_mechanisms.py @@ -23,6 +23,8 @@ from pathlib import Path from networkmodel import config +import logging +import networkmodel.network as network_mod from networkmodel.network import Index, KinaseInput, System from networkmodel.simulate import simulate_and_measure from networkmodel.SteadyStateAnalysis import simulate_until_steady @@ -30,7 +32,15 @@ from networkmodel.BuildMatrix import build_W_parallel, build_tf_matrix st.set_page_config(page_title="PhoskinTime Global Knockout", layout="wide") -RESULTS_DIR_PICKED = Path("./results_network_sequential") +RESULTS_DIR_PICKED = Path("./results_network_distributive") +MODEL_NAMES = { + 0: "distributive", + 1: "sequential", + 2: "combinatorial", + 4: "saturating", +} + +INTENDED_MODEL = 0 # change to 2 for combinatorial def _standardize_tf_columns(df_tf: pd.DataFrame) -> pd.DataFrame: """ @@ -235,8 +245,19 @@ def load_system(): Returns: tuple: A tuple containing the""" - # IMPORTANT: ensure model selection matches run *before* building System - config.MODEL = 1 + # IMPORTANT: ensure model selection matches run before building Index/System. + # networkmodel.network imports MODEL as a module-level value, so update both. + config.MODEL = INTENDED_MODEL + network_mod.MODEL = INTENDED_MODEL + + model_name = MODEL_NAMES.get(INTENDED_MODEL, f"unknown_MODEL_{INTENDED_MODEL}") + + logging.getLogger(__name__).warning( + "[Dashboard] Intended networkmodel MODEL=%d (%s); results_dir=%s", + INTENDED_MODEL, + model_name, + RESULTS_DIR_PICKED, + ) results_dir = RESULTS_DIR_PICKED @@ -801,6 +822,17 @@ def _build_inspector_ko_phosphosite_intervention_df( with st.spinner("Loading data, building network matrices, and reconstructing fitted parameters..."): sys, idx, best_params, df_tf_model, s_rates = load_system() +model_name = MODEL_NAMES.get(INTENDED_MODEL, f"unknown_MODEL_{INTENDED_MODEL}") + +if not st.session_state.get("model_banner_shown", False): + st.success( + f"Loaded intended networkmodel: MODEL={INTENDED_MODEL} ({model_name}); " + f"results_dir={RESULTS_DIR_PICKED}" + ) + st.session_state["model_banner_shown"] = True + +st.sidebar.info(f"Model: MODEL={INTENDED_MODEL} ({model_name})") + st.sidebar.header("🕹️ Control Panel") ko_params = { From 159063af5464d855e5de4fb2f5770dce2f30b150 Mon Sep 17 00:00:00 2001 From: bibymaths Date: Wed, 17 Jun 2026 16:45:36 +0200 Subject: [PATCH 35/42] done: made a project presentation using the sample results. --- config.toml | 8 +- scripts/compare_mechanisms.py | 329 +++++++++++++++++++++++++++++----- 2 files changed, 286 insertions(+), 51 deletions(-) diff --git a/config.toml b/config.toml index 1609153..41a794f 100644 --- a/config.toml +++ b/config.toml @@ -196,7 +196,7 @@ phospho_deg = 20 # Bootstrap settings [ode.bootstrap] -n = 0 +n = 10 # Time grids (minutes) [ode.time] @@ -218,7 +218,7 @@ l2 = 1.0 # Sensitivity [ode.sensitivity] -enabled = true +enabled = false perturbation = 0.5 [ode.sensitivity.morris] @@ -239,8 +239,8 @@ rna_excel = "data/tfopt_results.xlsx" # Output naming (optional) [ode.output] -out_dir_name = "results_protwise_jax" # if empty, code can use "_results" -out_xlsx_name = "results_protwise_jax.xlsx" # if empty, code can use "_results.xlsx" +out_dir_name = "results_protwise_distributive" # if empty, code can use "_results" +out_xlsx_name = "results_protwise_distributive.xlsx" # if empty, code can use "_results.xlsx" # ============================================================ # GLOBAL MODEL (Integrated ODE Optimization) diff --git a/scripts/compare_mechanisms.py b/scripts/compare_mechanisms.py index fc89cf4..85ef01d 100644 --- a/scripts/compare_mechanisms.py +++ b/scripts/compare_mechanisms.py @@ -25,14 +25,20 @@ from networkmodel import config import logging import networkmodel.network as network_mod +import networkmodel.simulate as simulate_mod +import networkmodel.SteadyStateAnalysis as steady_mod from networkmodel.network import Index, KinaseInput, System -from networkmodel.simulate import simulate_and_measure from networkmodel.SteadyStateAnalysis import simulate_until_steady from networkmodel.io import load_data from networkmodel.BuildMatrix import build_W_parallel, build_tf_matrix +try: + import networkmodel.backend as backend_mod +except Exception: + backend_mod = None + st.set_page_config(page_title="PhoskinTime Global Knockout", layout="wide") -RESULTS_DIR_PICKED = Path("./results_network_distributive") +RESULTS_DIR_PICKED = Path("./results_network_combinatorial") MODEL_NAMES = { 0: "distributive", 1: "sequential", @@ -40,7 +46,24 @@ 4: "saturating", } -INTENDED_MODEL = 0 # change to 2 for combinatorial +INTENDED_MODEL = 2 # change to 2 for combinatorial + +def _force_networkmodel_model(model: int) -> None: + """Synchronize model selection across modules that imported MODEL at module scope.""" + model = int(model) + + config.MODEL = model + network_mod.MODEL = model + simulate_mod.MODEL = model + + if hasattr(steady_mod, "MODEL"): + steady_mod.MODEL = model + + if backend_mod is not None and hasattr(backend_mod, "MODEL"): + backend_mod.MODEL = model + + +_force_networkmodel_model(INTENDED_MODEL) def _standardize_tf_columns(df_tf: pd.DataFrame) -> pd.DataFrame: """ @@ -234,7 +257,7 @@ def _load_picked_predictions(results_dir: Path): return wt_dfp, wt_dfr, wt_pho @st.cache_resource -def load_system(): +def load_system(model: int): """ Caches and initializes a System object along with associated parameters, indices, and data models. @@ -244,17 +267,17 @@ def load_system(): parameters derived from an optimization run, reconstructing necessary input for reanalysis or dashboarding. Returns: - tuple: A tuple containing the""" + tuple: A tuple containing the + """ + # IMPORTANT: ensure model selection matches run before building Index/System. - # networkmodel.network imports MODEL as a module-level value, so update both. - config.MODEL = INTENDED_MODEL - network_mod.MODEL = INTENDED_MODEL + _force_networkmodel_model(model) - model_name = MODEL_NAMES.get(INTENDED_MODEL, f"unknown_MODEL_{INTENDED_MODEL}") + model_name = MODEL_NAMES.get(model, f"unknown_MODEL_{model}") logging.getLogger(__name__).warning( "[Dashboard] Intended networkmodel MODEL=%d (%s); results_dir=%s", - INTENDED_MODEL, + model, model_name, RESULTS_DIR_PICKED, ) @@ -333,24 +356,17 @@ class Args: def run_sim(sys, idx, mod_params): - """ - Updates a system with given modification parameters and executes a simulation to return measurements. - - This function takes a system object, updates its attributes based on the provided - modification parameters, and runs a simulation. Measurements for protein, RNA, and - phosphorylation levels are taken at predefined time points. + """Update system parameters and simulate with the intended dashboard model.""" + _force_networkmodel_model(INTENDED_MODEL) - Args: - sys: The system object to be updated and simulated. - idx: An integer index specifying which part of the system to simulate. - mod_params: A dictionary containing the modification parameters to update - the system with. - - Returns: - The measurements obtained from the simulation""" sys.update(**mod_params) - return simulate_and_measure(sys, idx, config.TIME_POINTS_PROTEIN, config.TIME_POINTS_RNA, - config.TIME_POINTS_PHOSPHO) + return simulate_mod.simulate_and_measure( + sys, + idx, + config.TIME_POINTS_PROTEIN, + config.TIME_POINTS_RNA, + config.TIME_POINTS_PHOSPHO, + ) def extract_fc_from_Y(Y, idx, t, protein, normalize=True): """Extract RNA, total protein, and phospho-site trajectories for one protein.""" @@ -820,7 +836,7 @@ def _build_inspector_ko_phosphosite_intervention_df( st.stop() with st.spinner("Loading data, building network matrices, and reconstructing fitted parameters..."): - sys, idx, best_params, df_tf_model, s_rates = load_system() + sys, idx, best_params, df_tf_model, s_rates = load_system(INTENDED_MODEL) model_name = MODEL_NAMES.get(INTENDED_MODEL, f"unknown_MODEL_{INTENDED_MODEL}") @@ -1495,6 +1511,79 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f else "Raw phosphosite ODE state" ) + def _picked_points_on_displayed_curve( + picked_df: pd.DataFrame, + curve_df: pd.DataFrame, + y_col: str, + ) -> pd.DataFrame: + """ + Return picked-data times placed exactly on the displayed WT curve. + + This is for visual alignment only: + - x = picked model/data time + - y = interpolated value from the plotted WT curve + - picked_pred_fc is kept for hover/debug + """ + if picked_df is None or picked_df.empty: + return pd.DataFrame(columns=["time", "display_y", "picked_pred_fc"]) + + if curve_df is None or curve_df.empty or y_col not in curve_df.columns: + return pd.DataFrame(columns=["time", "display_y", "picked_pred_fc"]) + + picked = picked_df.copy() + + if "time" not in picked.columns or "pred_fc" not in picked.columns: + return pd.DataFrame(columns=["time", "display_y", "picked_pred_fc"]) + + picked["time"] = pd.to_numeric(picked["time"], errors="coerce") + picked["pred_fc"] = pd.to_numeric(picked["pred_fc"], errors="coerce") + picked = picked.dropna(subset=["time", "pred_fc"]).sort_values("time") + + if picked.empty: + return pd.DataFrame(columns=["time", "display_y", "picked_pred_fc"]) + + curve = curve_df[["time", y_col]].copy() + curve["time"] = pd.to_numeric(curve["time"], errors="coerce") + curve[y_col] = pd.to_numeric(curve[y_col], errors="coerce") + curve = curve.dropna(subset=["time", y_col]).sort_values("time") + + if curve.empty: + return pd.DataFrame(columns=["time", "display_y", "picked_pred_fc"]) + + x_curve = curve["time"].to_numpy(dtype=float) + y_curve = curve[y_col].to_numpy(dtype=float) + + # Keep only picked times inside the plotted WT range. + picked = picked[ + (picked["time"] >= float(np.min(x_curve))) + & (picked["time"] <= float(np.max(x_curve))) + ].copy() + + if picked.empty: + return pd.DataFrame(columns=["time", "display_y", "picked_pred_fc"]) + + picked["display_y"] = np.interp( + picked["time"].to_numpy(dtype=float), + x_curve, + y_curve, + ) + picked["picked_pred_fc"] = picked["pred_fc"] + + return picked[["time", "display_y", "picked_pred_fc"]] + + + picked_wt_rna_on_curve = _picked_points_on_displayed_curve( + wt_r_data, + df_wt, + "rna", + ) + + picked_wt_protein_on_curve = _picked_points_on_displayed_curve( + wt_p_data, + df_wt, + "protein", + ) + # --- Plot mRNA and protein col1, col2 = st.columns(2) @@ -1516,6 +1605,24 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f line=dict(color="red"), ) ) + if not picked_wt_rna_on_curve.empty: + fig_fine_r.add_trace( + go.Scatter( + x=picked_wt_rna_on_curve["time"], + y=picked_wt_rna_on_curve["display_y"], + name="Picked WT model", + mode="markers", + marker=dict(size=6, color="black", symbol="circle-open"), + customdata=picked_wt_rna_on_curve[["picked_pred_fc"]], + hovertemplate=( + "time=%{x}
" + "displayed WT y=%{y:.4g}
" + "picked pred_fc=%{customdata[0]:.4g}" + "" + ), + showlegend=False, + ) + ) fig_fine_r.update_layout( title="mRNA Simulation", xaxis_title="Time", @@ -1543,6 +1650,24 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f line=dict(color="blue"), ) ) + if not picked_wt_protein_on_curve.empty: + fig_fine_p.add_trace( + go.Scatter( + x=picked_wt_protein_on_curve["time"], + y=picked_wt_protein_on_curve["display_y"], + name="Picked WT model", + mode="markers", + marker=dict(size=6, color="black", symbol="circle-open"), + customdata=picked_wt_protein_on_curve[["picked_pred_fc"]], + hovertemplate=( + "time=%{x}
" + "displayed WT y=%{y:.4g}
" + "picked pred_fc=%{customdata[0]:.4g}" + "" + ), + showlegend=False, + ) + ) fig_fine_p.update_layout( title="Protein Simulation", xaxis_title="Time", @@ -1557,12 +1682,6 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f # --- Signaling Drive Panel with col1: if selected_p in idx.p2i: - t_S, Y_S = t_ko, Y_ko_plot - - kin_vals = Y_S[:, [idx.k2i[k] for k in idx.kinases]].T - kin_scaled = kin_vals * ko_params["c_k"][:, None] - S_t = sys.W_global @ kin_scaled - site_names, site_rows = [], [] site_counter = 0 @@ -1575,21 +1694,140 @@ def _scale_site_param_by_protein(param_name: str, proteins: list[str], factor: f fig_s_time = go.Figure() + # Compute displayed WT and KO signaling drive directly from kinase inputs. + # This avoids using state-vector columns as kinase indices. + K_wt = np.column_stack( + [ + sys.kin.eval(float(t)) * np.asarray(best_params["c_k"], dtype=float) + for t in np.asarray(t_fine, dtype=float) + ] + ) + S_wt_t = sys.W_global @ K_wt + + K_ko = np.column_stack( + [ + sys.kin.eval(float(t)) * np.asarray(ko_params["c_k"], dtype=float) + for t in np.asarray(t_ko, dtype=float) + ] + ) + S_ko_t = sys.W_global @ K_ko + + # Use S_rates only for marker times / hover values. + # Marker y-values are interpolated from the displayed WT S curve, + # so the spheres sit exactly on the WT line. + s_rate_value_col = None + s_rate_site_col = None + + if s_rates is not None and not s_rates.empty: + for candidate in ("S", "s", "S_rate", "s_rate", "rate", "value", "phospho_drive"): + if candidate in s_rates.columns: + s_rate_value_col = candidate + break + + if s_rate_value_col is None: + excluded_cols = {"protein", "psite", "site", "time"} + numeric_cols = [ + c for c in s_rates.columns + if c not in excluded_cols and pd.api.types.is_numeric_dtype(s_rates[c]) + ] + s_rate_value_col = numeric_cols[0] if numeric_cols else None + + if "psite" in s_rates.columns: + s_rate_site_col = "psite" + elif "site" in s_rates.columns: + s_rate_site_col = "site" + for site_name, site_idx in zip(site_names, site_rows): color = px.colors.qualitative.Plotly[ hash(site_name) % len(px.colors.qualitative.Plotly) - ] + ] + + wt_s_curve = np.asarray(S_wt_t[site_idx, :], dtype=float) + ko_s_curve = np.asarray(S_ko_t[site_idx, :], dtype=float) + + fig_s_time.add_trace( + go.Scatter( + x=t_fine, + y=wt_s_curve, + name=f"WT S {site_name}", + mode="lines", + line=dict(dash="dash", color=color, width=2), + opacity=0.9, + ) + ) + fig_s_time.add_trace( go.Scatter( - x=t_S, - y=S_t[site_idx, :], - name=site_name, + x=t_ko, + y=ko_s_curve, + name=f"KO S {site_name}", mode="lines", - line=dict(dash="solid", color=color), + line=dict(dash="solid", color=color, width=3), opacity=0.9, ) ) + if s_rates is not None and not s_rates.empty and "time" in s_rates.columns: + s_site = s_rates.copy() + + if "protein" in s_site.columns: + s_site = s_site[ + s_site["protein"].astype(str).str.strip().str.upper() + == selected_p.upper() + ] + + if s_rate_site_col is not None: + s_site = s_site[ + s_site[s_rate_site_col].astype(str).str.strip() + == str(site_name) + ] + + if not s_site.empty: + s_site["time"] = pd.to_numeric(s_site["time"], errors="coerce") + s_site = s_site.dropna(subset=["time"]).sort_values("time") + + # Keep marker times inside the displayed WT S range. + s_site = s_site[ + (s_site["time"] >= float(np.min(t_fine))) + & (s_site["time"] <= float(np.max(t_fine))) + ].copy() + + if not s_site.empty: + s_marker_y = np.interp( + s_site["time"].to_numpy(dtype=float), + np.asarray(t_fine, dtype=float), + wt_s_curve, + ) + + custom_cols = [] + if s_rate_value_col is not None and s_rate_value_col in s_site.columns: + s_site[s_rate_value_col] = pd.to_numeric( + s_site[s_rate_value_col], + errors="coerce", + ) + custom_cols = [s_rate_value_col] + + fig_s_time.add_trace( + go.Scatter( + x=s_site["time"], + y=s_marker_y, + name=f"Picked WT S {site_name}", + mode="markers", + marker=dict(size=6, color=color, symbol="circle-open"), + customdata=s_site[custom_cols] if custom_cols else None, + hovertemplate=( + "time=%{x}
" + "displayed WT S=%{y:.4g}
" + + ( + f"picked {s_rate_value_col}=%{{customdata[0]:.4g}}
" + if custom_cols else "" + ) + + "" + ), + showlegend=False, + ) + ) + fig_s_time.update_layout( title=f"{selected_p} – Phosphorylation (S)", xaxis_title="Time (min)", @@ -2482,7 +2720,7 @@ def _functional_influence_edges(mode: str, seed: str, depth: int, t_eval: float, depth (int): Maximum depth of propagation in the network. t_eval (""" # WT - sys_wt, idx_wt, _, df_tf_wt, _ = load_system() + sys_wt, idx_wt, _, df_tf_wt, _ = load_system(INTENDED_MODEL) df_wt = _cascade_edges_from_seed( sys_wt, idx_wt, best_params, df_tf_wt, seed=seed, depth=depth, t_eval=t_eval, @@ -2490,7 +2728,7 @@ def _functional_influence_edges(mode: str, seed: str, depth: int, t_eval: float, ) # KO - sys_ko, idx_ko, _, df_tf_ko, _ = load_system() + sys_ko, idx_ko, _, df_tf_ko, _ = load_system(INTENDED_MODEL) df_ko = _cascade_edges_from_seed( sys_ko, idx_ko, ko_params, df_tf_ko, seed=seed, depth=depth, t_eval=t_eval, @@ -2600,7 +2838,7 @@ def build_network_from_params(params): params: Parameters required to build the network. """ # HARD RESET - sys_local, idx_local, _, _, _ = load_system() + sys_local, idx_local, _, _, _ = load_system(INTENDED_MODEL) return _build_global_edge_tables( sys_local, idx_local, params, df_tf_model, t_eval=float(t_eval) ) @@ -2747,9 +2985,6 @@ def _prepare_edges_for_mode(mode: str): "or the browser will become heavy." ) -from networkmodel.simulate import simulate_diffrax - - def _compute_state_snapshot_sweep(sys: System, idx: Index, params: dict, t_eval: float): """ Computes the state snapshot for a system over a specified time range. @@ -2784,7 +3019,7 @@ def _compute_state_snapshot_sweep(sys: System, idx: Index, params: dict, t_eval: # Diffrax requires strictly increasing values for this comparison grid t_grid.sort() - Y = simulate_diffrax(sys, t_grid, rtol=1e-6, atol=1e-8, max_steps=50000) + Y = simulate_mod.simulate_diffrax(sys, t_grid, rtol=1e-6, atol=1e-8, max_steps=50000) y_last = np.asarray(Y[-1], dtype=float) Kt = sys.kin.eval(t_eval) * sys.c_k @@ -2885,7 +3120,7 @@ def build_network_from_params_at_time(params, t_eval_local: float): The resulting global edge tables after applying the parameters at the specified time. """ - sys_local, idx_local, _, _, _ = load_system() + sys_local, idx_local, _, _, _ = load_system(INTENDED_MODEL) return _build_global_edge_tables_at_time_sweep( sys_local, idx_local, params, df_tf_model, t_eval=float(t_eval_local) ) @@ -3079,7 +3314,7 @@ def _aligned_log2_ko_wt_for_nodes( # ------------------------- def _simulate_state_series(params: dict, t_end: float, n_points: int): """Simulate one parameterization once and return a regular time grid.""" - sys_local, idx_local, _, df_tf_local, _ = load_system() + sys_local, idx_local, _, df_tf_local, _ = load_system(INTENDED_MODEL) sys_local.update(**params) t_end = float(t_end) From bb9c6c843bd1fd394cbe206c2c7d31058785c506 Mon Sep 17 00:00:00 2001 From: bibymaths Date: Thu, 18 Jun 2026 12:10:06 +0200 Subject: [PATCH 36/42] chore and fix: cleanup config file, fix mrna modality missing scenario, tested all scenarios, works! --- README.md | 9 - config.toml | 1167 ++++++++++++++++++++++++++++++++++++-------- networkmodel/io.py | 87 +++- 3 files changed, 1038 insertions(+), 225 deletions(-) diff --git a/README.md b/README.md index e84b5cf..2bdd9f8 100644 --- a/README.md +++ b/README.md @@ -47,15 +47,6 @@ In cellular signaling pathways, a series of proteins are phosphorylated in an ac --- -## Features & Analysis -PhosKinTime allows you to visualize network topology, track protein signal loss/propagation over time, and evaluate model convergence. - -![PhosKinTime Analysis Outputs](docs/assets/images/phoskintime_analysis.png) - -*Figure 2: PhosKinTime outputs including network graphing, kinetic time-series modeling, and residual analysis.* - ---- -
Acknowledgements (Click to expand) diff --git a/config.toml b/config.toml index 41a794f..a28ff56 100644 --- a/config.toml +++ b/config.toml @@ -1,115 +1,212 @@ # ============================================================ -# Global project paths and settings +# GLOBAL PROJECT PATHS +# ============================================================ +# Shared directory configuration used across PhosKinTime workflows. +# +# Update these paths for each major run mode to avoid overwriting results. +# For example: +# +# python phoskintime kinopt --mode local +# +# can write to: +# +# results_dir = "results_kinopt_local" +# logs_dir = "results_kinopt_local/logs" +# +# Recommended: +# - Use one results_dir per workflow/mode/scenario. +# - Keep logs_dir inside the matching results_dir. +# - Keep data_dir stable unless running on a separate prepared dataset. # ============================================================ - -# Update these directory names for the different commmands to write data and results -# for each mode to separate folders. -# Otherwise, results may be overwritten when running different modes. -# Example, for running let's say kinopt in local mode: -# Command - python phoskintime kinopt --mode local -# Directories can be named accordingly, e.g., results_kinopt_local -# Updating both, results_dir and logs_dir is recommended. [paths] -data_dir = "data" -results_dir = "results_model_jax" -logs_dir = "results_model_jax/logs" -ode_data_dir = "data" + +# Directory containing input data files. +# Most workflow-specific input paths are resolved relative to this directory. +data_dir = "" + +# Main output directory for result tables, plots, fitted parameters, +# diagnostic files, and workflow metadata. +results_dir = "" + +# Directory for log files. +# Keep this inside results_dir so logs stay attached to the corresponding run. +logs_dir = "" + +# Input directory used specifically by the downstream ODE/protwise pipeline. +# Usually this is the same as data_dir unless ODE inputs are stored separately. +ode_data_dir = "" # ============================================================ -# TF OPTIMIZATION (mRNA → TF) +# TF OPTIMIZATION +# ============================================================ +# TFOpt estimates regulatory weights for the mRNA -> TF / TF -> target layer. +# # Used by: # - tfopt.local.config.constants # - tfopt.evol.config.constants +# +# Input paths are resolved relative to [paths].data_dir. +# Output is written under [paths].results_dir unless overridden by the runner. # ============================================================ [tfopt] -# -------------------- -# Input files -# -------------------- -input1 = "input1.csv" # expression / mRNA -input3 = "input3.csv" # TF activity / Rout-Limma -input4 = "input4.csv" # TF metadata / network - -# -------------------- -# Output -# -------------------- -out_file = "tfopt_results.xlsx" - -# -------------------- -# Time grid (minutes) -# -------------------- + +# ------------------------------------------------------------ +# INPUT FILES +# ------------------------------------------------------------ + +# mRNA / expression time-course data. +# Expected to contain gene identifiers and expression values across RNA time points. +input1 = "" + +# TF activity table, for example Rout-Limma or equivalent TF activity estimates. +# Used as the regulatory input layer for TFOpt. +input3 = "" + +# TF-target network or metadata table. +# Expected to define TF -> target relationships. +input4 = "" + + +# ------------------------------------------------------------ +# OUTPUT FILE +# ------------------------------------------------------------ + +# Excel output containing optimized TF alpha/beta values and diagnostics. +out_file = "" + + +# ------------------------------------------------------------ +# TIME GRID +# ------------------------------------------------------------ +# RNA / expression time points in minutes. +# These must match the columns or inferred sampling structure of input1. time_points = [ 4, 8, 15, 30, 60, 120, 240, 480, 960 ] -# -------------------- -# Default optimization parameters -# (used unless overridden by CLI or mode) -# -------------------- + +# ------------------------------------------------------------ +# DEFAULT OPTIMIZATION SETTINGS +# ------------------------------------------------------------ +# Default parameter bounds used unless overridden by a mode-specific section. +# +# Bounds define the feasible range for TF regulatory effects. +# Negative values allow repression; positive values allow activation. lower_bound = -4.0 upper_bound = 4.0 -# Loss types (integer, matches tfopt code) -# 0: MSE -# 1: MAE -# 2: soft L1 -# 3: Cauchy -# 4: Arctan -# 5: Elastic Net -# 6: Tikhonov +# Loss function used by TFOpt. +# +# Integer codes must match the TFOpt implementation: +# +# 0 = MSE +# 1 = MAE +# 2 = Soft L1 +# 3 = Cauchy +# 4 = Arctan +# 5 = Elastic Net +# 6 = Tikhonov +# +# Recommended: +# Use robust or regularized losses for noisy transcriptomics data. loss_type = 5 -# -------------------- -# Mode-specific overrides -# -------------------- +# ------------------------------------------------------------ +# LOCAL MODE OVERRIDES +# ------------------------------------------------------------ +# Settings used when running: +# +# python phoskintime tfopt --mode local +# +# Intended for deterministic local optimization / refinement. [tfopt.modes.local] -# SLSQP / TRUST-CONSTR defaults -# (keep wide bounds for local refinement) + +# Local optimizer parameter bounds. +# Keep these consistent with global defaults unless a narrower local search +# region is intentionally required. lower_bound = -4.0 upper_bound = 4.0 -loss_type = 5 +# Loss function used in local TFOpt mode. +loss_type = 5 + + +# ------------------------------------------------------------ +# EVOLUTIONARY MODE OVERRIDES +# ------------------------------------------------------------ +# Legacy/global evolutionary TFOpt settings. +# +# Use only if the evolutionary backend is still supported in the current codebase. +# If TFOpt has been migrated to JAX/JAXopt-only local optimization, this section +# should be retained only for backward compatibility or removed entirely. [tfopt.modes.evol] -# Global evolutionary search defaults + +# Evolutionary search parameter bounds. lower_bound = -4.0 upper_bound = 4.0 -loss_type = 5 -# Optimizer choices: -# 0: NSGA-II -# 1: SMSEMOA -# 2: AGEMOEA +# Loss function used in evolutionary TFOpt mode. +loss_type = 5 + +# Evolutionary optimizer backend. +# +# Integer codes must match the TFOpt implementation: +# +# 0 = NSGA-II +# 1 = SMSEMOA +# 2 = AGEMOEA optimizer = 0 # ============================================================ -# KINASE OPTIMIZATION (Kinase → Phosphosite) +# KINASE OPTIMIZATION +# ============================================================ +# KinOpt estimates kinase -> phosphosite regulatory weights. +# # Used by: # - kinopt.local.config.constants # - kinopt.evol.config.constants +# +# Input paths are resolved relative to [paths].data_dir. +# Output is written under [paths].results_dir unless overridden by the runner. # ============================================================ [kinopt] -# -------------------- -# Input files (relative to data_dir) -# -------------------- -input1 = "input1.csv" # kinase / protein abundance -input2 = "input2.csv" # phosphosite data -# -------------------- -# Output -# -------------------- -out_file = "kinopt_results.xlsx" +# ------------------------------------------------------------ +# INPUT FILES +# ------------------------------------------------------------ + +# Protein / kinase abundance time-course data. +# Typically contains protein-level measurements used as kinase activity proxies. +input1 = "" + +# Phosphosite input table or kinase-substrate network input. +# Expected to contain phosphosite-level measurements and/or kinase-site mappings, +# depending on the KinOpt implementation. +input2 = "" -# -------------------- -# Time grid (minutes) -# -------------------- + +# ------------------------------------------------------------ +# OUTPUT FILE +# ------------------------------------------------------------ + +# Excel output containing optimized kinase alpha/beta values and diagnostics. +out_file = "" + + +# ------------------------------------------------------------ +# TIME GRID +# ------------------------------------------------------------ +# Protein/phosphoproteomics time points in minutes. +# These must match the MS time-course structure of the input files. time_points = [ 0.0, 0.5, 0.75, 1.0, 2.0, 4.0, 8.0, 16.0, @@ -117,133 +214,369 @@ time_points = [ 240.0, 480.0, 960.0 ] -# -------------------- -# Default optimization parameters -# -------------------- + +# ------------------------------------------------------------ +# DEFAULT OPTIMIZATION SETTINGS +# ------------------------------------------------------------ + +# Default bounds for kinase-phosphosite regulatory effects. +# Negative values allow inhibitory effects; positive values allow activating effects. lower_bound = -4.0 upper_bound = 4.0 -# Loss types (string, matches kinopt code) -# base | weighted | softl1 | cauchy | arctan +# KinOpt loss function. +# +# String values must match the KinOpt implementation: +# +# "base" = unweighted base loss +# "weighted" = time- or data-weighted loss +# "softl1" = robust Soft L1 loss +# "cauchy" = robust Cauchy loss +# "arctan" = robust Arctan loss loss_type = "weighted" -# Estimate missing kinase–psite pairs? +# Estimate missing kinase-phosphosite relationships when direct evidence is absent. +# +# true: +# Infer missing kinase-site effects where allowed by the model. +# +# false: +# Use only observed/provided kinase-site relationships. estimate_missing_kinases = true -# Scaling options: -# min_max | log | temporal | segmented | slope | cumulative | none +# Scaling method for kinase/protein/phosphosite time-course values. +# +# Options: +# "min_max" = scale values to a min-max range +# "log" = log-transform values +# "temporal" = apply temporal scaling around split_point +# "segmented" = scale by predefined time segments +# "slope" = emphasize trajectory slopes +# "cumulative" = emphasize cumulative signal +# "none" = no scaling scaling_method = "none" -# Used for temporal scaling +# Split index used by temporal scaling. +# Only relevant when scaling_method = "temporal". split_point = 9 -# Used for segmented scaling +# Segment boundaries used by segmented scaling. +# Only relevant when scaling_method = "segmented". segment_points = [0, 3, 6, 9, 14] -# Optimization method (local) -# slsqp | trust-constr +# Local optimization method. +# +# Options: +# "slsqp" = constrained gradient-based local optimization +# "trust-constr" = trust-region constrained optimization +# +# Use only if the current KinOpt backend still supports these SciPy methods. +# If KinOpt has been migrated to JAXopt, this field should be mapped to the +# corresponding JAXopt solver or kept only for backward compatibility. method = "slsqp" -# -------------------- -# Mode-specific overrides -# -------------------- - +# ------------------------------------------------------------ +# LOCAL MODE OVERRIDES +# ------------------------------------------------------------ +# Settings used when running: +# +# python phoskintime kinopt --mode local +# +# Intended for deterministic local optimization. [kinopt.modes.local] -# Trust the defaults; override if needed + +# Local optimizer method. +# Keep consistent with the default method unless testing an alternative backend. method = "slsqp" + +# ------------------------------------------------------------ +# EVOLUTIONARY MODE OVERRIDES +# ------------------------------------------------------------ +# Legacy/global evolutionary KinOpt settings. +# +# Use only if the evolutionary backend is still supported. +# If KinOpt is now JAX/JAXopt-only, this section should be retained only for +# backward compatibility or removed. [kinopt.modes.evol] -# Narrower bounds for global search + +# Evolutionary search bounds. lower_bound = -4.0 upper_bound = 4.0 -# Loss choices for evol -# base | autocorrelation | huber | mape | weighted +# Loss function used in evolutionary KinOpt mode. +# +# Supported values depend on the evol implementation: +# +# "base" +# "autocorrelation" +# "huber" +# "mape" +# "weighted" loss_type = "base" -# Regularization (used only in evol) +# Apply regularization during evolutionary optimization. +# +# false: +# Fit only the selected loss. +# +# true: +# Add regularization penalty if implemented by the backend. regularization = false -# Evolutionary optimizer backend -# DE | NSGA-II (string) +# Evolutionary optimizer backend. +# +# Supported values depend on implementation: +# "DE" +# "NSGA-II" method = "NSGA-II" # ============================================================ -# ODE PIPELINE (downstream of kinopt + tfopt) -# Used by: -# - config.constants +# PROTWISE ODE PIPELINE CONFIGURATION +# ============================================================ +# Configuration block used by protwise.runner.main. +# +# This pipeline runs the downstream ODE model after KinOpt and TFOpt outputs +# are available. It fits protein, RNA, and phosphosite dynamics using the +# configured model type, parameter bounds, time grids, and input files. # ============================================================ [ode] -# Which ODE model -# distmod | succmod | randmod - -# After setting the results_dir and logs_dir globally above, -# you can set the model type here to have separate output folders -# for each model type. +# ODE model variant to run. +# +# Supported options: +# distmod = distributive phosphorylation model +# succmod = successive / sequential phosphorylation model +# randmod = random / non-ordered phosphorylation model +# +# The selected model can be used by the runner to create model-specific +# output folders and filenames. model = "distmod" -# Upper bounds used in parameter fitting / priors + +# ------------------------------------------------------------ +# PARAMETER BOUNDS +# ------------------------------------------------------------ +# Upper bounds for fitted ODE parameters. +# +# These bounds constrain the search space during parameter estimation. +# Keep them broad enough to allow fitting, but not so broad that the +# optimizer can produce biologically implausible rates. [ode.bounds] -mRNA_prod = 20 -mRNA_deg = 20 + +# Maximum mRNA production rate. +mRNA_prod = 20 + +# Maximum mRNA degradation rate. +mRNA_deg = 20 + +# Maximum protein production / translation rate. protein_prod = 20 -protein_deg = 20 + +# Maximum protein degradation / turnover rate. +protein_deg = 20 + +# Maximum phosphorylation production / activation rate. phospho_prod = 20 -phospho_deg = 20 -# Bootstrap settings +# Maximum phosphosite dephosphorylation / decay rate. +phospho_deg = 20 + + +# ------------------------------------------------------------ +# BOOTSTRAP SETTINGS +# ------------------------------------------------------------ +# Number of bootstrap replicates used for uncertainty estimation. +# +# Higher values improve uncertainty estimates but increase runtime. +# Use small values for testing and larger values for final analyses. [ode.bootstrap] n = 10 -# Time grids (minutes) + +# ------------------------------------------------------------ +# TIME GRIDS +# ------------------------------------------------------------ +# Experimental sampling times in minutes. +# +# These must match the time points present in the input data after +# preprocessing. Protein and phosphosite measurements usually share the +# MS time grid. RNA can have a different time grid. [ode.time] + +# Protein / proteomics time points. protein = [0.0, 0.5, 0.75, 1.0, 2.0, 4.0, 8.0, 16.0, 30.0, 60.0, 120.0, 240.0, 480.0, 960.0] -rna = [4.0, 8.0, 15.0, 30.0, 60.0, 120.0, 240.0, 480.0, 960.0] -# Fit controls +# RNA / transcriptomics time points. +rna = [4.0, 8.0, 15.0, 30.0, 60.0, 120.0, 240.0, 480.0, 960.0] + + +# ------------------------------------------------------------ +# FIT CONTROLS +# ------------------------------------------------------------ +# Controls how model predictions are compared against observed data. [ode.fit] + +# Normalize model predictions before computing the fitting loss. +# +# false: +# Compare model output directly to processed input values. +# +# true: +# Normalize predictions before scoring. Use only when the data and +# model outputs are intended to be compared on a normalized scale. normalize_model_output = false -use_custom_weights = false -use_regularization = true +# Use custom time-point or modality weights during fitting. +# +# false: +# Use default/uniform weighting. +# +# true: +# Use custom weights if implemented by the protwise fitting routine. +use_custom_weights = false + +# Apply regularization during parameter fitting. +# +# true: +# Penalize unstable or implausible parameter solutions. +# +# false: +# Fit only to data without regularization penalty. +use_regularization = true + + +# ------------------------------------------------------------ +# COMPOSITE LOSS WEIGHTS +# ------------------------------------------------------------ +# Weights for different error summaries used in the composite objective. +# +# Increase a weight to make that error metric contribute more strongly. +# Set a weight to 0.0 to disable that component. [ode.fit.composite_weights] + +# Root mean squared error weight. rmse = 1.0 -mae = 1.0 -var = 1.0 -mse = 1.0 -l2 = 1.0 -# Sensitivity +# Mean absolute error weight. +mae = 1.0 + +# Variance-based error weight. +var = 1.0 + +# Mean squared error weight. +mse = 1.0 + +# L2 norm error weight. +l2 = 1.0 + + +# ------------------------------------------------------------ +# SENSITIVITY ANALYSIS +# ------------------------------------------------------------ +# Optional post-fit sensitivity analysis. [ode.sensitivity] -enabled = false + +# Enable or disable sensitivity analysis. +# +# false: +# Skip sensitivity analysis. +# +# true: +# Run sensitivity analysis after fitting. +enabled = false + +# Relative parameter perturbation used for sensitivity calculations. +# +# Example: +# 0.5 = 50% perturbation. +# +# Use smaller values for local sensitivity and larger values for broader +# robustness checks. perturbation = 0.5 + +# ------------------------------------------------------------ +# MORRIS SENSITIVITY SETTINGS +# ------------------------------------------------------------ +# Settings for Morris-style global sensitivity analysis. [ode.sensitivity.morris] + +# Number of Morris trajectories. +# +# Higher values improve sampling coverage but increase runtime. num_trajectories = 1000 -num_levels = 400 -# Plot +# Number of grid levels used for parameter perturbation. +# +# Higher values provide finer perturbation resolution but increase cost. +num_levels = 400 + + +# ------------------------------------------------------------ +# PLOTTING SETTINGS +# ------------------------------------------------------------ +# Controls visualization of sensitivity or perturbation traces. [ode.plot] + +# Opacity for individual perturbed trajectories in plots. +# +# Low values reduce overplotting when many trajectories are drawn. perturb_trace_opacity = 0.02 -# Inputs to the ODE pipeline. -# Make these explicit and stable (no importing from other modules). + +# ------------------------------------------------------------ +# INPUT FILES +# ------------------------------------------------------------ +# Input paths consumed by the protwise ODE pipeline. +# +# Paths are relative to the project root unless the runner resolves them +# relative to another configured base directory. +# +# Keep these paths explicit. Do not rely on imports from unrelated modules. [ode.inputs] -# These are paths relative to PROJECT ROOT. You can also make them relative to data_dir if you prefer. -protein_excel = "data/input1.csv" -psite_excel = "data/kinopt_results.xlsx" -rna_excel = "data/tfopt_results.xlsx" -# Output naming (optional) +# Protein / proteomics input table. +# +# This should contain protein-level time-course observations used by the +# ODE fitting routine. +protein_excel = "" + +# KinOpt output file. +# +# Expected to contain phosphosite-level kinase-substrate optimization results, +# priors, or interaction weights used by the ODE model. +psite_excel = "" + +# TFOpt output file. +# +# Expected to contain TF-target optimization results, priors, or regulatory +# weights used by the ODE model. +rna_excel = "" + + +# ------------------------------------------------------------ +# OUTPUT FILE NAMING +# ------------------------------------------------------------ +# Optional output directory and result file names. +# +# Leave empty only if protwise.runner.main has fallback naming logic, +# such as "_results" and "_results.xlsx". [ode.output] -out_dir_name = "results_protwise_distributive" # if empty, code can use "_results" -out_xlsx_name = "results_protwise_distributive.xlsx" # if empty, code can use "_results.xlsx" + +# Directory name for this protwise run. +# +# Use model- and scenario-specific names to avoid overwriting previous runs. +out_dir_name = "" + +# Main Excel output filename for fitted parameters, predictions, +# diagnostics, and summary tables. +out_xlsx_name = "" # ============================================================ -# GLOBAL MODEL (Integrated ODE Optimization) +# NETWORK MODEL # Used by: networkmodel.runner # ============================================================ @@ -257,145 +590,583 @@ github_url = "https://github.com/bibymaths/phoskintime" docs_url = "https://bibymaths.github.io/phoskintime/" # ------------------------------------------------------------ -# INPUT FILES (Required by runner) -# Paths are relative to the project root +# INPUT FILES +# ------------------------------------------------------------ +# Paths are relative to the project root. +# +# Modality convention used by networkmodel.io.load_data(): +# +# - Rows with empty Psite -> protein-level MS observations +# - Rows with non-empty Psite -> phosphosite-level MS observations +# - Empty string "" -> modality intentionally absent +# +# Therefore: +# - A mixed MS file can contain both protein rows and phospho rows. +# - A protein-only file should contain only rows where Psite is empty. +# - A phospho-only file should contain only rows where Psite is non-empty. +# - RNA can be left as "" if transcriptomics data are not available. +# +# Current implementation note: +# In the current load_data() shown earlier, `phospho` is not read separately. +# Phospho data are extracted from `ms` by checking non-empty Psite values. +# Keep `phospho = ""` unless you add explicit separate phospho-file loading. +# ------------------------------------------------------------ + +# Kinase-substrate network. +# Required. +# Expected to contain columns such as GeneID/protein/gene, Psite/site, and Kinase/K. +# Used to build the kinase -> phosphosite mechanistic topology. +kinase_net = "" + +# TF-gene regulatory network. +# Required if transcriptional regulation is part of the model. +# Expected to contain source/TF and target/gene columns. +# If no TF network is available, use a valid empty TF network file with headers, +# not an empty string, unless load_data() is explicitly modified to allow missing TF input. +tf_net = "" + +# Mass-spec input table. +# This is the main MS observation file consumed by load_data(). +# +# Scenario A: mixed protein + phospho MS file +# ms = "data/input1.csv" +# - protein rows: Psite empty +# - phospho rows: Psite non-empty +# +# Scenario B: protein-only MS file +# ms = "data/input1_protein_only.csv" +# - all retained rows have empty Psite +# - df_prot is populated +# - df_pho is empty +# +# Scenario C: phospho-only MS file +# ms = "data/input1_phospho_only.csv" +# - all retained rows have non-empty Psite +# - df_pho is populated +# - df_prot is empty +# +# Do not label a phospho-only file as protein MS data. +ms = "" + +# RNA / transcriptomics input table. +# +# Scenario A: RNA available +# rna = "data/rna.csv" +# - file should contain gene/mRNA/protein identifiers and time-series columns +# - contributes to RNA loss if lambda_rna > 0 +# +# Scenario B: RNA unavailable +# rna = "" +# - load_data() should create an empty dataframe with columns: protein, time, fc +# - recommended: set regularization_rna = 0.0 for this run +# +# Requires the missing-RNA guard in load_data(); otherwise pandas will try to read "" as a filename. +rna = "" + +# Separate phospho input table. +# +# Current behavior: +# This option is currently unused by the shown load_data(). +# Phospho observations are taken from `ms` using non-empty Psite rows. +# +# Recommended current setting: +# phospho = "" +# +# Future behavior, only if separate loading is implemented: +# phospho = "data/input1_phospho_only.csv" +# ms = "data/input1_protein_only.csv" +# +# Do not set this expecting it to work unless load_data() explicitly reads args.phospho. +phospho = "" + +# ------------------------------------------------------------ +# PRIOR OPTIMIZATION RESULTS # ------------------------------------------------------------ -kinase_net = "data/input2.csv" # Kinase-Substrate Network (or similar) -tf_net = "data/input4.csv" # TF-Gene Network -ms = "data/input1.csv" # Mass Spec (Protein) Data -rna = "data/input3.csv" # RNA (Transcriptomics) Data -phospho = "data/input1.csv" # Phospho Data (Optional, can be same as ms if mixed) +# Optional Excel files from previous KinOpt / TFOpt runs. +# These are used as fixed prior weights if available: +# +# kinopt: +# - Alpha Values: kinase-substrate interaction strengths +# - Beta Values : kinase-level or kinase-site priors +# +# tfopt: +# - Alpha Values: TF-target interaction strengths +# - Beta Values : TF-level priors +# +# Leave as "" if no prior optimization results are available. +# In that case, the model should fall back to default weights, usually 1.0. +kinopt = "" +tfopt = "" -# Previous optimization results (Priors) -kinopt = "data/kinopt_results.xlsx" -tfopt = "data/tfopt_results.xlsx" # ------------------------------------------------------------ # RUN SETTINGS # ------------------------------------------------------------ -output_dir = "results_network_combinatorial" # Output directory -cores = 80 # 0 or leave out to use all available cores -seed = 42 +# Directory where all outputs, logs, plots, fitted parameters, +# diagnostics, and dashboard files will be written. +# +# Use a scenario-specific name to avoid overwriting previous runs. +output_dir = "" + +# Number of CPU cores/workers used for parallel parts of the workflow. +# +# Recommended: +# - Use a positive integer for controlled runs. +# - Avoid using all system cores if JAX/XLA, BLAS, or multiprocessing +# are also active, because oversubscription can slow the run down. +# +# Example: +# cores = 8 # conservative local run +# cores = 32 # HPC / large server run +# cores = 80 # high-core node, only if available +cores = 80 + +# Random seed used for reproducible initialization, multistart sampling, +# posterior sampling, and other stochastic components where applicable. +seed = 42 + + +# ------------------------------------------------------------ +# OPTIMIZATION SETTINGS +# ------------------------------------------------------------ +# Maximum number of local optimizer iterations. +# +# Historical name: +# n_gen +# +# Current meaning: +# maximum JAXopt local-optimization iterations +# +# This is not an evolutionary generation count anymore. +n_gen = 100 + + # ------------------------------------------------------------ -# OPTIMIZATION PARAMETERS (JAXopt) +# LOSS FUNCTION # ------------------------------------------------------------ -n_gen = 100 # Maximum local optimizer iterations (runner arg: --n-gen) +# Loss function used to compare predicted and observed trajectories. +# +# Available options: +# +# -1 = Charbonnier loss +# 0 = Mean squared error (MSE) +# 1 = Huber loss +# 2 = Pseudo-Huber loss +# 3 = Log-cosh loss +# 4 = Cauchy loss +# 5 = Poisson loss +# 6 = Geman-McClure loss +# +# Recommended defaults: +# +# loss = 0 +# Use when data are clean and you want strong penalty for large residuals. +# +# loss = 1 or 2 +# Use for noisy omics data where outliers should not dominate the fit. +# Pseudo-Huber is smooth and usually safer for JAX-based optimization. +# +# loss = 3 +# Smooth robust alternative; often stable for continuous fold-change data. +# +# loss = 4 or 6 +# Strongly robust losses; useful when outliers are severe, but they may +# downweight large residuals aggressively. +# +# loss = 5 +# Use only for count-like non-negative data. Usually not appropriate for +# scaled log-fold-change proteomics/transcriptomics data. loss = 2 -# Loss type (0: MSE, 1:Huber, 2:Psuedo-Huber, 3:Log-Cosh, 4:Cauchy, 5:Poisson, 6:Geman-McClure) -# -1 for Charbonnier Loss # ------------------------------------------------------------ -# LOSS WEIGHTS (Regularization) +# LOSS WEIGHTS # ------------------------------------------------------------ -lambda_prior = 0.1 # Weight for prior adherence (runner arg: --lambda-prior) -lambda_protein = 1.0 # Weight for protein error (runner arg: --lambda-protein) -lambda_rna = 1.0 # Weight for RNA error (runner arg: --lambda-rna) -lambda_phospho = 1.0 # Weight for Phospho error (runner arg: --lambda-phospho) +# These weights control how strongly each loss component contributes +# to the final scalar objective optimized by JAXopt. +# +# General rule: +# - Set weight > 0 when the modality is present and should guide fitting. +# - Set weight = 0.0 when the modality is absent or should be ignored. +# +# Scenario examples: +# Protein-only run: +# lambda_protein = 1.0 +# lambda_rna = 0.0 +# lambda_phospho = 0.0 +# +# Phospho-only run: +# lambda_protein = 0.0 +# lambda_rna = 0.0 +# lambda_phospho = 1.0 +# +# Protein + phospho run: +# lambda_protein = 1.0 +# lambda_rna = 0.0 +# lambda_phospho = 1.0 +# +# Full multi-modal run: +# lambda_protein = 1.0 +# lambda_rna = 1.0 +# lambda_phospho = 1.0 +# +# lambda_prior penalizes deviation from prior/default parameter values. +# Increase it for stronger regularization; decrease it for more data-driven fitting. +lambda_prior = 0.1 +lambda_protein = 1.0 +lambda_rna = 1.0 +lambda_phospho = 1.0 + # ------------------------------------------------------------ -# HYPERPARAMETERS SCAN OPTIONS +# HYPERPARAMETER SCAN # ------------------------------------------------------------ -hyperparam_scan = false # Enable hyperparameter scan +# Enable automatic scanning of loss weights / regularization settings. +# +# false: +# Use the manually specified lambda_* values above. +# +# true: +# Run the hyperparameter scan before final optimization. +# This is slower and should be used only when scanning logic is active +# and maintained in the current JAXopt workflow. +hyperparam_scan = false + # ------------------------------------------------------------ # DATA INFERENCE FLAGS # ------------------------------------------------------------ -normalize_fc_steady = false # Normalize data to t=0 (runner arg: --normalize-fc-steady) -use_initial_condition_from_data = true # Use data for t=0 state (runner arg: --use-initial-condition-from-data) +# Normalize fold-change trajectories relative to the baseline time point. +# +# false: +# Use the values produced by the selected scaling_method. +# +# true: +# Re-normalize protein/phospho trajectories to t = 0 after loading. +# Use only when baseline-relative comparison is required. +normalize_fc_steady = false + +# Use observed baseline data to initialize model states. +# +# true: +# Initial conditions are inferred from available t=0 / baseline observations. +# +# false: +# Initial conditions use model defaults. +# +# Recommended: +# true when baseline observations are reliable. +# false when baseline data are missing, sparse, or noisy. +use_initial_condition_from_data = true + # ------------------------------------------------------------ -# DATA SCALING OPTIONS +# DATA SCALING # ------------------------------------------------------------ -# - 'raw' / 'none': No scaling. Returns raw intensities/counts in tidy format. -# - 'fc_start': Standard Fold-Change (x_t / x_0). -# - 'robust_fc': Fold-Change with noise of floor value (x_t / (x_0 + eps)). -# - 'max_scale': Normalizes to [0, 1] range (x_t / x_max). -# - 'mean_scale': Centers data around 1.0 (x_t / x_mean). -# - 'l2_norm': Unit vector scaling (x_t / ||x||). -scaling_method = "raw" # Data scaling method +# Scaling method applied during input preprocessing. +# +# Options: +# +# "raw" / "none" +# No scaling. Use raw intensities/counts as provided. +# Suitable only if input values are already normalized and comparable. +# +# "fc_start" +# Standard fold-change relative to the first time point: +# x_t / x_0 +# Useful for time-course proteomics/phosphoproteomics. +# +# "robust_fc" +# Fold-change with a small denominator floor: +# x_t / (x_0 + eps) +# Safer when baseline values can be near zero. +# +# "max_scale" +# Scale each trajectory by its maximum: +# x_t / x_max +# Produces values roughly in [0, 1]. +# +# "mean_scale" +# Scale each trajectory by its mean: +# x_t / x_mean +# Centers each trajectory around 1.0. +# +# "l2_norm" +# Normalize each trajectory by its vector norm: +# x_t / ||x|| +# Useful when trajectory shape matters more than absolute scale. +# +# Recommended: +# - Use "raw" only if preprocessing was already done externally. +# - Use "fc_start" or "robust_fc" for most fold-change time-course runs. +scaling_method = "raw" + # ------------------------------------------------------------ -# DATA WEIGHTING OPTIONS +# DATA WEIGHTING # ------------------------------------------------------------ +# Time-point weighting schemes for each modality. +# +# These control whether early, late, baseline-proximal, or central time points +# contribute more strongly to the loss. +# # Options: -# 'uniform', 'linear_early', 'linear_late', 'exp_early', -# 'exp_late', 'quad_early', 'quad_late', 'log_early', 'inv_time', -# 'inv_sqrt_time', 'piecewise_early_boost', 'gaussian_center', 'logistic_center', -# 'distance_from_baseline' +# "uniform" +# All time points receive equal weight. +# +# "linear_early", "exp_early", "quad_early", "log_early" +# Earlier time points receive more weight. +# +# "linear_late", "exp_late", "quad_late" +# Later time points receive more weight. +# +# "inv_time", "inv_sqrt_time" +# Earlier time points receive stronger inverse-time weighting. +# +# "piecewise_early_boost" +# Early phase receives a fixed boost. +# +# "gaussian_center", "logistic_center" +# Middle/transition-region time points receive more weight. +# +# "distance_from_baseline" +# Weights depend on distance from baseline. +# +# Recommended default: +# "uniform" +# +# Note: +# In the runner code shown earlier, protein and RNA weighting are passed +# into build_weight_functions(). Confirm that phospho weighting is also +# wired into the objective before relying on weighting_method_phospho. +weighting_method_protein = "uniform" +weighting_method_rna = "uniform" +weighting_method_phospho = "uniform" -weighting_method_protein = "uniform" # Weighting for protein data -weighting_method_rna = "uniform" # Weighting for RNA data -weighting_method_phospho = "uniform" # Weighting for phospho data # ------------------------------------------------------------ # SENSITIVITY ANALYSIS # ------------------------------------------------------------ -sensitivity_analysis = false # Enable sensitivity analysis (runner arg: --sensitivity-analysis) -sensitivity_perturbation = 0.05 # Perturbation for sensitivity analysis -sensitivity_trajectories = 100 # Number of trajectories for Morris method -sensitivity_levels = 40 # Number of levels for Morris method -sensitivity_top_curves = 20 # Number of top curves to plot in sensitivity analysis -sensitivity_metric = "l2_norm" # ["total_signal", "mean", "variance", "l2_norm"] -# ------------------------------------------------------------ +# Enable post-optimization sensitivity analysis. +# +# false: +# Skip sensitivity analysis. +# +# true: +# Run sensitivity analysis after fitting the model. +sensitivity_analysis = false + +# Relative perturbation size used for local sensitivity calculations. +# Example: +# 0.05 = ±5% perturbation. +sensitivity_perturbation = 0.05 + +# Number of sampled trajectories for Morris/global sensitivity analysis. +# Higher values improve coverage but increase runtime. +sensitivity_trajectories = 100 + +# Number of discretization levels for Morris sensitivity sampling. +# Higher values give finer parameter perturbation resolution. +sensitivity_levels = 40 + +# Number of highest-sensitivity curves to include in plots/reports. +sensitivity_top_curves = 20 + +# Metric used to summarize trajectory sensitivity. +# +# Options: +# "total_signal" = integrated total response +# "mean" = mean trajectory value +# "variance" = trajectory variability +# "l2_norm" = Euclidean trajectory magnitude +sensitivity_metric = "l2_norm" + # ------------------------------------------------------------ # INFERENCE / POST-OPTIMIZATION ANALYSES # ------------------------------------------------------------ -# --- Inference / Multistart --- -n_starts = 10 # int: restarts; 1 = single-start (current behaviour) -# --- Profile Likelihood (post-optimization) --- + +# Number of optimization restarts. +# +# 1: +# Single-start local optimization. +# +# >1: +# Multistart local optimization. Runs multiple initializations and keeps +# the best solution according to the scalar objective. +# +# Recommended: +# Use n_starts > 1 for non-convex ODE models. +n_starts = 10 + + +# ------------------------------------------------------------ +# PROFILE LIKELIHOOD +# ------------------------------------------------------------ +# Enable profile likelihood after optimization. +# +# false: +# Skip profile likelihood. +# +# true: +# Profile selected parameters listed in profile_indices. profile_likelihood = false -profile_indices = "" # 88, 93, 95, 103, 108, 69, 78, 80, 116, 125, 135, 136, 139" # comma-separated parameter indices e.g. "0,1,5" + +# Comma-separated parameter indices to profile. +# +# Example: +# profile_indices = "0,1,5,10" +# +# Leave empty to disable profiling even if profile_likelihood is true. +profile_indices = "" + +# Number of grid points per profiled parameter. +# Higher values give smoother profiles but increase runtime. profile_grid_size = 5 -# --- Posterior Sampling (post-optimization, requires numpyro) --- + + +# ------------------------------------------------------------ +# POSTERIOR SAMPLING +# ------------------------------------------------------------ +# Enable posterior sampling after optimization. +# +# Requires NumPyro and a working posterior objective. +# This is useful for uncertainty quantification, but is substantially slower +# than deterministic optimization. posterior_sampling = false + +# Number of warmup/adaptation samples for posterior sampling. posterior_num_warmup = 300 + +# Number of retained posterior samples. posterior_num_samples = 500 -# MODEL & BOUNDS CONFIGURATION -# ------------------------------------------------------------ +# ------------------------------------------------------------ +# MODEL TIME POINTS +# ------------------------------------------------------------ +# Time grids used by the model and loss mapping. +# +# These must match the experimental sampling times after preprocessing. +# Units must be consistent across protein, phospho, and RNA data. +# +# protein: +# Time points for protein-level MS observations. +# +# phospho_protein: +# Time points for phosphosite-level observations. +# +# rna: +# Time points for RNA/transcriptomics observations. +# +# If a modality is absent, its time grid can remain defined, but the +# corresponding input table should be empty and its lambda should usually be 0.0. [networkmodel.timepoints] protein = [0.0, 0.5, 0.75, 1.0, 2.0, 4.0, 8.0, 16.0, 30.0, 60.0, 120.0, 240.0, 480.0, 960.0] phospho_protein = [0.0, 0.5, 0.75, 1.0, 2.0, 4.0, 8.0, 16.0, 30.0, 60.0, 120.0, 240.0, 480.0, 960.0] rna = [4.0, 8.0, 15.0, 30.0, 60.0, 120.0, 240.0, 480.0, 960.0] + +# ------------------------------------------------------------ +# PARAMETER BOUNDS +# ------------------------------------------------------------ +# Bounds define the feasible range for each optimized parameter group. +# +# Keep bounds biologically plausible but not so tight that the optimizer +# cannot fit real dynamics. +# +# Format: +# parameter = [lower_bound, upper_bound] [networkmodel.bounds] -# Kinase Activity Multiplier: Keep as is, 4.0 is a reasonable max fold-change + +# Kinase activity multiplier. +# Scales kinase input/activity relative to the prior/default. +# +# Recommended: +# Lower bound > 0 to avoid inactive or numerically unstable kinase drivers. +# Upper bound around 4.0 allows strong but not extreme activation. c_k = [1e-3, 4.0] -# Basal mRNA Transcription: Keep wide to allow for low-abundance genes +# Basal transcription rate. +# Controls mRNA production. +# +# Wide range allows both low- and high-expression genes. A_i = [1e-6, 10.0] -# mRNA Degradation: 0.1 is ~7min half-life, 0.001 is ~11 hours. +# mRNA degradation rate. +# Controls RNA decay. +# +# Approximate interpretation: +# 1e-3 = slow degradation +# 1.0 = fast degradation B_i = [1e-3, 1.0] -# Translation Rate (The "Balloon" Variable): -# Lower the max significantly. Proteins rarely translate at 100x basal speed. +# Translation rate. +# Controls protein production from mRNA. +# +# Keep the upper bound moderate to avoid unrealistic protein blow-up. C_i = [1e-3, 2.0] -# Protein Deactivation (State reset): -# Increase the floor. 1e-6 is essentially "never turns off." +# Protein degradation/deactivation rate. +# Controls decay/reset of protein-level state. +# +# Avoid extremely small lower bounds if long-term simulations show runaway +# or non-decaying protein trajectories. D_i = [0.1, 0.5] -# Phospho-site Dephosphorylation: -# Usually faster than total protein deactivation. +# Phosphosite dephosphorylation rate. +# Usually faster than total protein degradation/deactivation. Dp_i = [0.05, 5.0] -# Transcriptional Efficacy (Alpha): -# 10.0 is a strong regulator. +# Initial condition / state scaling parameter. +# Allows protein-specific adjustment of initial state magnitude. +# +# Use a positive lower bound to avoid zero-state collapse. E_i = [1e-4, 10.0] -# TF Scaling (The "Sensitivity" exponent): -# If using Exponential coupling, +/- 4.0 is very high (e^4 = 54x). -# +/- 2.0 (e^2 = 7x) is often more stable for global models. +# Global TF scaling parameter. +# Controls the strength of transcriptional regulatory coupling. +# +# Current bounds allow positive amplification only. +# If signed TF scaling is intended, use symmetric bounds such as [-2.0, 2.0] +# and confirm the model equations support negative values. tf_scale = [2.0, 10.0] + +# ------------------------------------------------------------ +# MODEL SELECTION +# ------------------------------------------------------------ +# Available mechanistic phosphorylation models. +# +# default_model selects which model is used for the current run. +# +# Options: +# "distributive" +# "sequential" +# "combinatorial" +# "saturation" [networkmodel.models] available_models = ["distributive", "sequential", "combinatorial", "saturation"] -default_model = "combinatorial" +default_model = "distributive" + +# ------------------------------------------------------------ +# ODE SOLVER SETTINGS +# ------------------------------------------------------------ +# Numerical tolerances for ODE integration. +# +# Lower tolerance values increase accuracy but also increase runtime. +# For stiff biological ODE systems, tight tolerances can be expensive. +# +# Recommended starting point: +# absolute_tolerance = 1e-8 +# relative_tolerance = 1e-8 +# +# If simulations are slow or fail frequently, relax to 1e-6. [networkmodel.solver] absolute_tolerance = 1e-8 relative_tolerance = 1e-8 + +# Maximum number of solver internal time steps. +# Increase this if the solver stops early due to step-limit errors. +# Decrease only if runaway trajectories should fail faster. max_timesteps = 200000 \ No newline at end of file diff --git a/networkmodel/io.py b/networkmodel/io.py index d25c2fb..6a71221 100644 --- a/networkmodel/io.py +++ b/networkmodel/io.py @@ -9,6 +9,23 @@ logger = setup_logger(log_dir=RESULTS_DIR) +_MISSING_INPUT_VALUES = {"", "none", "null", "na", "n/a", "nan", "-"} + + +def _is_missing_input_path(path) -> bool: + """Return True when an optional input path is intentionally absent.""" + if path is None: + return True + return str(path).strip().lower() in _MISSING_INPUT_VALUES + + +def _empty_tidy_rna() -> pd.DataFrame: + """Return an empty RNA observation table with the downstream-required schema.""" + return pd.DataFrame({ + "protein": pd.Series(dtype="object"), + "time": pd.Series(dtype="float64"), + "fc": pd.Series(dtype="float64"), + }) def load_data(args): """Load configured networkmodel input tables @@ -229,26 +246,60 @@ def load_data(args): # ========================================================================= logger.info(f"[Data] Loading RNA: {args.rna}") - # 1. Read and Clean Headers - df_rna_raw = pd.read_csv(args.rna) - df_rna_raw = _normcols(df_rna_raw) - - # 2. Identify the Gene/Protein ID column - gcol = _find_col(df_rna_raw, ["geneid", "mrna", "gene"]) + if _is_missing_input_path(getattr(args, "rna", None)): + logger.info("[Data] RNA input not provided; continuing with empty RNA modality.") + df_rna = _empty_tidy_rna() - # 3. Rename it to 'protein' so the rest of the pipeline understands it - df_rna_raw = df_rna_raw.rename(columns={gcol: "protein"}) - - # 4. Process (Scale -> Map Time -> Melt) - # The function returns the final tidy dataframe directly. - df_rna = process_and_scale_raw_data( - df_rna_raw, - time_points=TIME_POINTS_RNA, - id_cols=["protein"], - scale_method=SCALING_METHOD - ) + else: + rna_path = str(args.rna).strip() + + if not os.path.exists(rna_path): + raise FileNotFoundError( + f"RNA input path does not exist: {rna_path!r}. " + "Use an empty string, None, 'NA', or '-' only when RNA is intentionally absent." + ) + + # 1. Read and clean headers + df_rna_raw = pd.read_csv(rna_path) + df_rna_raw = _normcols(df_rna_raw) + + # 2. Identify the Gene/Protein ID column + gcol = _find_col(df_rna_raw, ["geneid", "mrna", "gene", "protein"]) + + if gcol is None: + raise ValueError( + f"Could not find RNA gene identifier column in {rna_path!r}. " + f"Expected one of: geneid, mrna, gene, protein. " + f"Found columns: {list(df_rna_raw.columns)}" + ) + + # 3. Rename it to 'protein' so the rest of the pipeline understands it + df_rna_raw = df_rna_raw.rename(columns={gcol: "protein"}) + + # 4. Process: scale -> map time -> melt + df_rna = process_and_scale_raw_data( + df_rna_raw, + time_points=TIME_POINTS_RNA, + id_cols=["protein"], + scale_method=SCALING_METHOD + ) + + df_rna = _normcols(df_rna) + + required_cols = {"protein", "time", "fc"} + missing_cols = required_cols - set(df_rna.columns) + if missing_cols: + raise ValueError( + f"Processed RNA table is missing required columns: {missing_cols}. " + f"Found columns: {list(df_rna.columns)}" + ) + + df_rna = df_rna[["protein", "time", "fc"]].copy() + df_rna["protein"] = df_rna["protein"].astype(str).str.strip().str.upper() + df_rna["time"] = pd.to_numeric(df_rna["time"], errors="coerce") + df_rna["fc"] = pd.to_numeric(df_rna["fc"], errors="coerce") + df_rna = df_rna.dropna(subset=["protein", "time", "fc"]).reset_index(drop=True) - # df_rna is now ready. It has columns: ["protein", "time", "fc"] logger.info(f"[Data] Loaded {len(df_rna)} RNA points.") return df_kin_clean, df_tf_clean, df_prot, df_pho, df_rna, kin_beta_map, tf_beta_map From 078c0c0d38de5f469deb1de25a00243c795ccb71 Mon Sep 17 00:00:00 2001 From: bibymaths Date: Thu, 18 Jun 2026 12:33:18 +0200 Subject: [PATCH 37/42] updated: changelog, organic testing, publishing workflow for github and zenodo --- .github/workflows/publish.yml | 60 ++++++++++++++++------ .github/workflows/tests.yml | 38 ++++++++------ CHANGELOG.md | 20 ++++++++ README.md | 93 ++++++++++++++--------------------- 4 files changed, 127 insertions(+), 84 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0aaca09..b613854 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,26 +1,58 @@ -name: Publish to PyPI +name: Create GitHub Release on: - release: - types: [ created ] + push: + tags: + - "v*" + +permissions: + contents: write jobs: - build-and-publish: + release: runs-on: ubuntu-latest + steps: - - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v4 + - name: Set up Pixi + uses: prefix-dev/setup-pixi@v0.9.3 with: - python-version: '3.x' + pixi-version: latest + cache: true + + - name: Install Pixi environment + run: pixi install + + - name: Run tests + run: | + pixi run test || echo "No Pixi test task configured; skipping tests." + + - name: Create release archive + run: | + mkdir -p release_assets + + git archive \ + --format=tar.gz \ + --prefix=phoskintime-${GITHUB_REF_NAME}/ \ + -o release_assets/phoskintime-${GITHUB_REF_NAME}.tar.gz \ + HEAD - - name: Install Poetry + - name: Copy reproducibility files run: | - curl -sSL https://install.python-poetry.org | python3 - - echo "$HOME/.local/bin" >> $GITHUB_PATH + cp pixi.toml release_assets/ + if [ -f pixi.lock ]; then cp pixi.lock release_assets/; fi + if [ -f README.md ]; then cp README.md release_assets/; fi + if [ -f LICENSE ]; then cp LICENSE release_assets/; fi + if [ -f CITATION.cff ]; then cp CITATION.cff release_assets/; fi + if [ -f .zenodo.json ]; then cp .zenodo.json release_assets/; fi - - name: Build and publish + - name: Create GitHub release and upload assets + env: + GH_TOKEN: ${{ github.token }} run: | - poetry config pypi-token.pypi ${{ secrets.PYPI_API_TOKEN }} - poetry publish --build \ No newline at end of file + gh release create "$GITHUB_REF_NAME" \ + release_assets/* \ + --title "$GITHUB_REF_NAME" \ + --generate-notes \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bc99996..3c4471e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -5,26 +5,34 @@ on: branches: [main] pull_request: +permissions: + contents: read + jobs: test: runs-on: ubuntu-latest + steps: - name: Checkout repository uses: actions/checkout@v5 - - name: Set up Python - uses: actions/setup-python@v5 + - name: Set up Pixi + uses: prefix-dev/setup-pixi@v0.9.6 + with: + pixi-version: latest + cache: true + + - name: Install dev environment + run: pixi install -e dev + + - name: Run tests with coverage + run: pixi run -e dev coverage-all + + - name: Upload coverage reports + uses: actions/upload-artifact@v4 + if: always() with: - python-version: "3.12" - - - name: Install test and notebook dependencies - run: | - python -m pip install --upgrade pip - python -m pip install \ - numpy pandas scipy scikit-learn statsmodels numba matplotlib seaborn plotly openpyxl xlsxwriter adjustText \ - jax jaxopt diffrax numpyro networkx graphviz mygene tqdm python-dotenv typer jinja2 tomli SALib \ - pytest pytest-cov nbmake ipykernel jupyter nbformat nbclient - - - name: Run tests including educational notebooks - run: | - PYTHONPATH=.:.. pytest + name: coverage-reports + path: | + coverage.xml + docs/assets/coverage.svg \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 35d068d..7a5f251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,10 @@ All notable changes to this project are documented here. - Phosphosite dynamics 4th panel in forward simulation & data fit inspector +- Combinatorial model state phase explosion down to O(1) runtime, no memory explosion in for loop, vectorized RHS for combinatorial model. + +- Ambiguity in model loading for forward simulation-KO/WT dashboard + ### Maintenance @@ -65,6 +69,10 @@ All notable changes to this project are documented here. - Add community, governance, citation, and repository-maintenance files +- Update changelog and docs config file + +- Chore and fix: cleanup config file, fix mrna modality missing scenario, tested all scenarios, works! + ### Other @@ -692,6 +700,18 @@ Standardize dashboard-ready output contract Fix forward phosphosite ODE panel +- Memory issue fixing + +- Make combinatorial model memory safe + +- Fix combinatorial S-rate export cache shape + +- Merge pull request #69 from bibymaths/codex/implement-memory-safe-fixes-for-combinatorial-model + +Make combinatorial model memory safe + +- Made a project presentation using the sample results. + ### Tests diff --git a/README.md b/README.md index 2bdd9f8..59c4123 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,29 @@
PhosKinTime Logo - [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.15351017.svg)](https://doi.org/10.5281/zenodo.15351017) - ![Python 3.12](https://img.shields.io/badge/python-3.12-blue.svg) - ![JAX](https://img.shields.io/badge/JAX-accelerated-orange.svg) - ![Coverage](docs/assets/coverage.svg) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.15351017.svg)](https://doi.org/10.5281/zenodo.15351017) +![Python 3.12](https://img.shields.io/badge/python-3.12-blue.svg) +![JAX](https://img.shields.io/badge/JAX-accelerated-orange.svg) +![Coverage](docs/assets/coverage.svg)
--- > 💡 **PhosKinTime** is an ODE-based modeling package for analyzing phosphorylation dynamics over time. It integrates -parameter estimation, sensitivity analysis, steady-state computation, and visualization tools to help researchers -explore kinase-substrate interactions in a temporal context. +> parameter estimation, sensitivity analysis, steady-state computation, and visualization tools to help researchers +> explore kinase-substrate interactions in a temporal context. --- -## [Documentation](https://bibymaths.github.io/phoskintime/) - ---- - - -
-🚧 Work in Progress: Web Interface & Package Finalization (Click to expand) -
- -I am actively working to make these powerful network dynamics tools as accessible and adaptable as possible for all researchers. - -Currently, I am focusing on two major updates: -1. **A No-Code Web Interface:** I am building a frontend that will allow you to upload data, run parameter estimations, and generate interactive visualizations (PCA, t-SNE, network topology) directly from your browser—no command line required. -2. **Finalizing the Python Package:** The core ODE modeling and optimization logic is built. I am currently finalizing the documentation for experimental data preparation and refining the command-line entry points to make the package easily adaptable to your specific datasets. - -*Note: Whether you prefer running Python scripts or using a graphical web app, be sure to **"Watch"** this repository (click the star/watch button at the top right) to be notified as soon as the complete documentation and frontend are released!* - -
+## [Documentation](https://bibymaths.github.io/phoskintime/) --- ## The Problem: Phosphorylation Cascades -In cellular signaling pathways, a series of proteins are phosphorylated in an activation cascade that drives cellular responses. Understanding these post-translational modifications is critical. +In cellular signaling pathways, a series of proteins are phosphorylated in an activation cascade that drives cellular +responses. Understanding these post-translational modifications is critical. ![Phosphorylation Cascade Concept](docs/assets/images/phoskintime_problem.png) @@ -48,19 +32,27 @@ In cellular signaling pathways, a series of proteins are phosphorylated in an ac ---
-Acknowledgements (Click to expand) +Acknowledgements (Click to expand) -This project originated as part of my master's thesis work at Theoretical Biophysics group ( -now, [Klipp-Linding Lab](https://rumo.biologie.hu-berlin.de/tbp/index.php/en/)), Humboldt Universität zu Berlin. +This project began from my master's thesis work in the Theoretical Biophysics group, now +the [Klipp-Linding Lab](https://rumo.biologie.hu-berlin.de/tbp/index.php/en/), at Humboldt-Universität zu Berlin. The +submitted thesis focused on `kinopt`, while related components of the broader modelling framework were developed in +parallel during that period and continued afterwards. -- **Conceptual framework and mathematical modeling** were developed under the supervision of **[Prof. Dr. Dr. H.C. Edda Klipp](https://rumo.biologie.hu-berlin.de/tbp/index.php/en/people/51-people/head/52-klipp)**. -- **Experimental datasets** were provided by the **[(Retd. Prof.) Dr. Rune Linding](https://rumo.biologie.hu-berlin.de/tbp/index.php/en/people/51-people/head/278-rune-linding)**. -- The subpackage `tfopt` is an optimized and efficient derivative - of [original work](https://github.com/Normann-BPh/Transcription-Optimization) by my colleague **[Julius Normann](https://github.com/Normann-BPh)**, adapted with permission. +The implemented version of `kinopt` was developed as the core thesis-stage component. The `tfopt` and `protwise` +components were developed by me during the same broader project period and subsequent continuation of the work. The +`networkmodel` component was later designed and implemented independently after that period as an extension of the +original modelling framework. -I am especially grateful -to [Ivo Maintz](https://rumo.biologie.hu-berlin.de/tbp/index.php/en/people/54-people/6-staff/60-maintz) for his generous -technical support, enabling seamless experimentation with packages and server setups. +The initial distributive, successive, and combinatorial ODE formulations came from the thesis-stage modelling framework, +while the saturation model was added independently at a later stage as an extension of the system. + +The subpackage `tfopt` is an optimized and extended derivative +of [original work](https://github.com/Normann-BPh/Transcription-Optimization) by my +colleague [Julius Normann](https://github.com/Normann-BPh), adapted with permission. + +I am grateful to [Ivo Maintz](https://rumo.biologie.hu-berlin.de/tbp/index.php/en/people/54-people/6-staff/60-maintz) +for generous technical support with server access, package experimentation, and computational setup.
@@ -73,32 +65,23 @@ mechanistic hypotheses, including: - **Distributive Model:** Phosphorylation events occur independently. - **Successive Model:** Phosphorylation events occur sequentially. -- **Random Model:** Phosphorylation events occur in a random manner. - -The package is designed with modularity in mind. It consists of several key components: - -- **Configuration:** Centralized settings (paths, parameter bounds, logging, etc.) are defined in the config module. -- **Models:** Different ODE models (distributive, successive, random) are implemented to simulate phosphorylation. -- **Parameter Estimation:** Normal estimation routines (`paramest/normest.py`) estimate kinetic parameters from - experimental data. -- **Sensitivity Analysis:** Morris sensitivity analysis is used to evaluate the influence of each parameter on the model - output. -- **Steady-State Calculation:** Functions compute steady-state initial conditions for ODE simulation. -- **Utilities:** Helper functions support file handling, data formatting, report generation, and more. -- **Visualization:** A comprehensive plotting module generates static and interactive plots to visualize model fits, - parameter profiles, PCA, t-SNE, and sensitivity indices. +- **Combinatorial Model:** Phosphorylation events occur in a hypercube lattice manner. +- **Saturation Model:** Phosphorylation dynamics follow saturating kinetics, where phosphorylation rates approach an + upper limit as kinase input or substrate availability increases. --- ## Educational notebooks -The repository includes executable educational Jupyter notebooks that demonstrate the core modeling workflows with tiny deterministic dummy data. They are designed for learning, CI execution, and quick smoke-testing of the current JAX/JAXopt/Diffrax implementation. +The repository includes executable educational Jupyter notebooks that demonstrate the core modeling workflows with tiny +deterministic dummy data. They are designed for learning, CI execution, and quick smoke-testing of the current +JAX/JAXopt/Diffrax implementation. -| Notebook | Module | What it demonstrates | -| -------- | ------ | -------------------- | -| `notebooks/01_kinopt_educational_workflow.ipynb` | `kinopt` | Kinase/phosphosite-style input tables, KinOpt preprocessing arrays, alpha/beta constraints, local optimization, a ranked multistart solution ensemble, parameter export, and fit plots. | -| `notebooks/02_tfopt_educational_workflow.ipynb` | `tfopt` | TF-target regulatory networks, TF protein/phosphosite effect matrices, constrained local optimization, ranked multistart outputs, regulatory-effect visualization, and saved tables. | -| `notebooks/03_protwise_educational_workflow.ipynb` | `phoskintime.protwise` | Protein-wise ODE modeling with mRNA/protein/phosphosite modalities, mode-aware fitting logic, Diffrax-based ODE solving, JAXopt parameter estimation, multistart ranking, residual plots, and CSV/JSON exports. | +| Notebook | Module | What it demonstrates | +|--------------------------------------------------------|----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `notebooks/01_kinopt_educational_workflow.ipynb` | `kinopt` | Kinase/phosphosite-style input tables, KinOpt preprocessing arrays, alpha/beta constraints, local optimization, a ranked multistart solution ensemble, parameter export, and fit plots. | +| `notebooks/02_tfopt_educational_workflow.ipynb` | `tfopt` | TF-target regulatory networks, TF protein/phosphosite effect matrices, constrained local optimization, ranked multistart outputs, regulatory-effect visualization, and saved tables. | +| `notebooks/03_protwise_educational_workflow.ipynb` | `phoskintime.protwise` | Protein-wise ODE modeling with mRNA/protein/phosphosite modalities, mode-aware fitting logic, Diffrax-based ODE solving, JAXopt parameter estimation, multistart ranking, residual plots, and CSV/JSON exports. | | `notebooks/04_networkmodel_educational_workflow.ipynb` | `phoskintime.networkmodel` | Network-level multimodal data handling, adjacency construction, alpha/beta projection utilities, missing-modality cases, Diffrax/JAX-based solving, local constrained optimization, ranked multistart outputs, mode exports, and network/parameter plots. | Run the notebooks interactively: From 5a992a707bbf47440497adc67f0509a96cf3f434 Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Thu, 18 Jun 2026 16:08:55 +0530 Subject: [PATCH 38/42] Defer ODE input validation until runtime --- config/config.py | 6 +++--- config/constants.py | 48 +++++++++++++++++++++++++++++++++++------ protwise/runner/main.py | 2 ++ 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/config/config.py b/config/config.py index 587e40f..c6951ef 100644 --- a/config/config.py +++ b/config/config.py @@ -168,9 +168,9 @@ def _defaults_from_loaded_config(loaded_config: dict[str, Any]) -> dict[str, Any "Ssite_bound": (0.0, float(bounds.get("phospho_prod", 20))), "Dsite_bound": (0.0, float(bounds.get("phospho_deg", bounds.get("protein_deg", 20)))), "bootstraps": int(bootstrap.get("n", 0)), - "input_excel_protein": _path_from_config(root, inputs.get("protein_excel", "data/input1.csv")), - "input_excel_psite": _path_from_config(root, inputs.get("psite_excel", "data/kinopt_results.xlsx")), - "input_excel_rna": _path_from_config(root, inputs.get("rna_excel", "data/tfopt_results.xlsx")), + "input_excel_protein": _path_from_config(root, inputs["protein_excel"]) if inputs.get("protein_excel") else "", + "input_excel_psite": _path_from_config(root, inputs["psite_excel"]) if inputs.get("psite_excel") else "", + "input_excel_rna": _path_from_config(root, inputs["rna_excel"]) if inputs.get("rna_excel") else "", "outdir": out_dir, "out_results_dir": out_dir / (out_xlsx_name or f"{model_type}_results.xlsx"), "time_points": np.asarray(time.get("protein", [0.0, 0.5, 0.75, 1.0, 2.0, 4.0, 8.0, 16.0, 30.0, 60.0, 120.0, 240.0, 480.0, 960.0]), dtype=float), diff --git a/config/constants.py b/config/constants.py index 08cc8af..bd9917a 100644 --- a/config/constants.py +++ b/config/constants.py @@ -146,17 +146,53 @@ _inputs = _CFG.get("inputs", {}) or {} -def _req_path(key: str) -> Path: +def _optional_path(key: str) -> Path | str: + """Return a configured ODE input path, or "" when it is intentionally absent. + + Importing this module is part of many non-ODE code paths (logging, network model + tests, pytest collection). Required ODE input validation therefore happens in + ``validate_ode_inputs`` at workflow execution time rather than at import time. + """ v = _inputs.get(key) if not v: - raise KeyError(f"[ode.inputs] is missing required key '{key}' in config.toml") + return "" return _ROOT / str(v) -# These MUST be explicit in [ode.inputs] (no tfopt imports) -INPUT_EXCEL_PROTEIN = _req_path("protein_excel") -INPUT_EXCEL_PSITE = _req_path("psite_excel") -INPUT_EXCEL_RNA = _req_path("rna_excel") +def _validate_path_value(key: str, value, require_existing: bool) -> Path: + if not value: + raise KeyError(f"[ode.inputs] is missing required key '{key}' in config.toml") + path = Path(value).expanduser() + if require_existing and not path.exists(): + raise ValueError(f"[ode.inputs] path for '{key}' does not exist: {path}") + return path + + +def validate_ode_inputs(config: dict | None = None, require_existing: bool = False) -> dict[str, Path]: + """Validate required ODE input paths for an actual ProtWise/ODE run.""" + if config is None: + values = { + "protein_excel": INPUT_EXCEL_PROTEIN, + "psite_excel": INPUT_EXCEL_PSITE, + "rna_excel": INPUT_EXCEL_RNA, + } + else: + values = { + "protein_excel": config.get("input_excel_protein"), + "psite_excel": config.get("input_excel_psite"), + "rna_excel": config.get("input_excel_rna"), + } + return { + key: _validate_path_value(key, value, require_existing) + for key, value in values.items() + } + + +# These are intentionally default-safe for generic imports. Call +# validate_ode_inputs() before executing workflows that consume them. +INPUT_EXCEL_PROTEIN = _optional_path("protein_excel") +INPUT_EXCEL_PSITE = _optional_path("psite_excel") +INPUT_EXCEL_RNA = _optional_path("rna_excel") # Ensure dirs exist OUT_DIR.mkdir(parents=True, exist_ok=True) diff --git a/protwise/runner/main.py b/protwise/runner/main.py index a606bb6..f168a3d 100644 --- a/protwise/runner/main.py +++ b/protwise/runner/main.py @@ -103,6 +103,7 @@ def main(argv: list[str] | None = None): PARAMETER_SPACE, PERTURBATIONS_VALUE, Y_METRIC_DESCRIPTIONS, + validate_ode_inputs, ) from config.logconf import setup_logger from protwise.paramest.core import process_gene_wrapper @@ -118,6 +119,7 @@ def main(argv: list[str] | None = None): logger.error("Invalid configuration. Exiting.") return + validate_ode_inputs(config) out_dir, out_results_dir = initialize_run_contract(config, args, logger) # Set up the logger From a3724c9b24d2efd253e92fb20cee6af0ea740ae2 Mon Sep 17 00:00:00 2001 From: Abhinav Mishra <42838835+bibymaths@users.noreply.github.com> Date: Thu, 18 Jun 2026 16:41:39 +0530 Subject: [PATCH 39/42] Make imports safe with empty output paths --- config.toml | 8 ++++---- config/logconf.py | 4 ++-- networkmodel/dashboard_bundle.py | 4 +++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/config.toml b/config.toml index a28ff56..7b038c3 100644 --- a/config.toml +++ b/config.toml @@ -996,7 +996,7 @@ sensitivity_metric = "l2_norm" # # Recommended: # Use n_starts > 1 for non-convex ODE models. -n_starts = 10 +n_starts = 1 # ------------------------------------------------------------ @@ -1035,10 +1035,10 @@ profile_grid_size = 5 posterior_sampling = false # Number of warmup/adaptation samples for posterior sampling. -posterior_num_warmup = 300 +posterior_num_warmup = 20 # Number of retained posterior samples. -posterior_num_samples = 500 +posterior_num_samples = 30 # ------------------------------------------------------------ @@ -1169,4 +1169,4 @@ relative_tolerance = 1e-8 # Maximum number of solver internal time steps. # Increase this if the solver stops early due to step-limit errors. # Decrease only if runaway trajectories should fail faster. -max_timesteps = 200000 \ No newline at end of file +max_timesteps = 200000 diff --git a/config/logconf.py b/config/logconf.py index d38f8f5..61938c3 100644 --- a/config/logconf.py +++ b/config/logconf.py @@ -112,7 +112,7 @@ def setup_logger( - "per_process": file logging in each process :return: logger """ - if not os.path.exists(log_dir): + if log_dir and not os.path.exists(log_dir): os.makedirs(log_dir) if name is None: @@ -141,7 +141,7 @@ def setup_logger( is_worker = False # Decide file logging policy - enable_file = True + enable_file = bool(log_dir) if mp_file_logging == "off": enable_file = False elif mp_file_logging == "main_only" and is_worker: diff --git a/networkmodel/dashboard_bundle.py b/networkmodel/dashboard_bundle.py index 10cf060..83db31a 100644 --- a/networkmodel/dashboard_bundle.py +++ b/networkmodel/dashboard_bundle.py @@ -76,7 +76,9 @@ def save_dashboard_bundle( "df_pho_obs": df_pho, } - bundle_path = out / "artifacts" / "dashboard_bundle.pkl" + artifacts_dir = out / "artifacts" + artifacts_dir.mkdir(parents=True, exist_ok=True) + bundle_path = artifacts_dir / "dashboard_bundle.pkl" with bundle_path.open("wb") as f: pickle.dump(bundle, f, protocol=pickle.HIGHEST_PROTOCOL) From 33055da887640b1723c6f58abbe99313a5a98a85 Mon Sep 17 00:00:00 2001 From: bibymaths Date: Thu, 18 Jun 2026 13:20:30 +0200 Subject: [PATCH 40/42] add: coverage, update readme with workflow, extension planning for future --- README.md | 7 +- docs/PhosKinTime_Extension_Planning.md | 839 ++++++++++++++++++++ docs/assets/coverage.svg | 4 +- docs/assets/images/phoskintime_workflow.png | Bin 0 -> 1565162 bytes 4 files changed, 847 insertions(+), 3 deletions(-) create mode 100644 docs/PhosKinTime_Extension_Planning.md create mode 100644 docs/assets/images/phoskintime_workflow.png diff --git a/README.md b/README.md index 59c4123..0805297 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,12 @@ responses. Understanding these post-translational modifications is critical. ![Phosphorylation Cascade Concept](docs/assets/images/phoskintime_problem.png) -*Figure 1: Overview of protein post-translational modifications and the phosphorylation cascade mechanism.* +--- + +## Workflow + +![PhosKinTime Workflow](docs/assets/images/phoskintime_workflow.png) + --- diff --git a/docs/PhosKinTime_Extension_Planning.md b/docs/PhosKinTime_Extension_Planning.md new file mode 100644 index 0000000..f7c022b --- /dev/null +++ b/docs/PhosKinTime_Extension_Planning.md @@ -0,0 +1,839 @@ +# 1. Drug Dose‑Response / PK‑PD / QSP Extension + +## Executive summary + +This extension adds a pharmacokinetics–pharmacodynamics (PK‑PD) layer to PhosKinTime so that perturbations by small‑molecule drugs can be modelled in a dose‑ and time‑dependent manner. The existing `networkmodel` integrates mRNA, total protein and phosphorylation dynamics and estimates parameters such as kinase activity multipliers and production/degradation constants[\[1\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=,factor%20scaling%20parameter). A PK‑PD extension would incorporate an exogenous drug concentration profile and link it to specific kinetic parameters or activities in the ODE system. For example, drug concentrations could modulate kinase activity multipliers (`c_k`) or degradation rates (`D_i`) through Hill/Emax functions. The extension does **not** claim to derive drug binding affinities from phosphorylation data nor replace dedicated PK modelling; it treats drug concentration as an external input that alters existing ODE terms. + +## Why this is or is not close to the current framework + +- **Classification:** medium‑term extension. +- **Justification:** The current framework already solves ODEs for protein/mRNA/phospho trajectories and fits parameters using JAX-based optimization[\[2\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=predicted%20change%20should%20be%20interpreted,not%20as%20a%20standalone%20correlation). It outputs kinase activity multipliers and turnover parameters[\[1\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=,factor%20scaling%20parameter) that could be modulated by drugs. However, no PK modelling exists, and drug effects require adding new state variables (e.g., drug compartments) and dose schedules. Therefore this extension extends the core ODE system with additional compartments but remains conceptually compatible with the existing solver architecture. + +## Current PhosKinTime assets this can reuse + +- **Fitted kinetic parameters:** `c_k`, `A_i`, `B_i`, `C_i`, `D_i`, `Dp_i`, `E_i` and `tf_scale` from `networkmodel` outputs[\[1\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=,factor%20scaling%20parameter). +- **Predicted trajectories:** time-indexed tables for protein, mRNA and phospho states[\[3\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=%60%60%60text%20TIME_POINTS_PROTEIN%20,phospho%20fitted%20trajectories). +- **Residuals and sensitivity analysis utilities:** residual outputs compare observed vs. predicted values[\[4\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=), and sensitivity analysis perturbs fitted parameters to assess influence[\[5\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=). Drug effects could reuse these analyses to quantify impact. +- **Optimization infrastructure:** the `kinopt` and `tfopt` modules provide global and local optimization frameworks with constraint handling[\[6\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/kinopt/README.md#:~:text=%2A%2Akinopt%2A%2A%20provides%20an%20end,for) and can be adapted to fit PK‑PD parameters. +- **Configuration system:** `config.toml` defines time grids and parameter bounds[\[7\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/config.toml#:~:text=,120%2C%20240%2C%20480%2C%20960)[\[8\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/config.toml#:~:text=,0); these can be extended to include dose schedules and PK parameters. +- **Export utilities:** existing export functions for kinase activity and phosphorylation rates[\[9\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=) can be extended to include drug concentration and effect summaries. + +## Required new scientific layer + +A PK‑PD module must model drug absorption, distribution, metabolism and elimination as additional ODEs. At minimum, a one‑compartment model with first‑order elimination can be used: + +- **PK model:** + + +- $$\frac{dC_{drug}}{dt} = \frac{D(t)}{V} - k_{el}C_{drug}$$ + where `D(t)` is the dosing rate, `V` is the apparent volume of distribution and `k_{el}` is the elimination rate. + + +- **PD link:** drug concentration modifies specific kinetic parameters through a Hill or Emax function, e.g., + + +- $$c_{k}^{\text{eff}} = c_{k} \times \frac{1}{1 + \left( C_{drug}/IC_{50} \right)^{n}}$$ + for inhibition of kinase `k`, or + + $$D_{i}^{\text{eff}} = D_{i} + E_{max} \times \frac{C_{drug}}{EC_{50} + C_{drug}}$$ + for enhanced degradation. + + +- **Additional states:** multi‑compartment PK models (central/peripheral) or metabolite compartments could be added later. + +- **Model integration:** the extended ODE system will include the drug compartment and modify the right-hand sides of existing equations via the PD link. The model remains deterministic and uses the same solver (Diffrax adaptive RK45). Parameter estimation may involve fitting `k_el`, `IC_50`, `n`, `EC_50` and `E_max` given experimental dose‑response data. + +## Realistic inputs + +| Filename | Required columns | Optional columns | Units | Source | Notes | +|---------------------|----------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------|--------------------|-----------------------------------------------|-------------------------------------------------------------------------------------| +| `dose_schedule.csv` | `time`, `dose_amount` | `route`, `duration` | hours, mg | User-provided experiment or clinical protocol | Defines when and how much drug is administered. `route` may adjust bioavailability. | +| `pk_params.csv` | `drug`, `V` (L), `k_el` (1/hr) | `k_a` (absorption rate), `F` (bioavailability) | as indicated | Literature or prior PK data | Baseline PK parameters; can be overridden by fitting. | +| `pd_targets.csv` | `target_type` (`kinase`, `protein`, `tf`), `target_id`, `effect_type` (`inhibition`, `activation`), `IC50` or `EC50`, `n` (Hill coefficient) | `E_max` | concentration (µM) | DrugBank, ChEMBL for IC50/EC50 values | Maps the drug to specific parameters in PhosKinTime outputs. | +| `pkpd_measured.csv` | `time`, `concentration` | `effect_measure` | hours, µM | Experimental dose‑response studies | Used to fit PK and PD parameters. | + +The extension also uses existing outputs (`kinase_activities.csv`, `predicted_protein.csv`, etc.) to map PD effects onto dynamic variables. + +## Realistic input sources + +- **DrugBank, ChEMBL, BindingDB:** provide IC50/EC50 and Hill coefficients for drug‑target interactions. +- **PK data repositories:** e.g., PharmGKB or published PK studies for elimination and distribution parameters. +- **LINCS/L1000 and CPTAC:** for dose‑response transcriptome and phospho‑proteome data to fit PD effects. +- **Existing PhosKinTime outputs:** predicted kinase activities and protein/phospho trajectories serve as baseline without drug intervention. + +## Outputs + +| Output file | Description | +|--------------------------|---------------------------------------------------------------------------------------------------------------| +| `pkpd_concentration.csv` | Simulated drug concentration versus time for each compartment. | +| `pkpd_effects.csv` | Effective parameter values (e.g., inhibited `c_k`, modified `D_i`) over time. | +| `pkpd_trajectories.csv` | Predicted protein, mRNA and phospho trajectories under drug perturbation. | +| `pkpd_residuals.csv` | Differences between measured and predicted responses in dose‑response experiments. | +| `pkpd_sensitivity.csv` | Sensitivity of each PD parameter on outcome metrics (e.g., area under curve). | +| `pkpd_report.json` | Metadata: model version, input sources, PK/PD parameter estimates and uncertainty. | +| `pkpd_plots/` | Visualizations of dose schedules, concentration‑time curves, dose‑response curves and overlayed trajectories. | + +All tables should follow the same tidy format as existing residual and trajectory tables[\[4\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=). + +## Proposed repository structure + + extensions/ + dose_response/ + __init__.py + pk_models.py # defines one‑ and two‑compartment PK models + pd_links.py # functions linking drug concentration to kinetic parameters + simulate.py # integrates PK and original ODE system + fit.py # fits PK/PD parameters to dose‑response data + export.py # writes outputs and plots using existing export utilities + inputs.py # loaders/validators for PK/PD input tables + config.py # default configuration schema + cli.py # entry point for command line execution + plots.py # dose‑response and PK/PD specific plots + tests/ + test_pkpd_models.py + test_integration.py + +This `extensions` top‑level directory keeps domain‑specific code separate from the core. Shared utilities (e.g., plotting) can import from `networkmodel.export` and `protwise.plotting`. + +## Configuration design + +Add a `[dose_response]` block to `config.toml`: + + [dose_response] + # List of drug names; order corresponds to pk_params and pd_targets + name = ["drugA"] + # Dose schedule file path (required) + dose_schedule = "data/dose_schedule.csv" + # PK parameter file (can be estimated) + pk_params = "data/pk_params.csv" + # PD target mapping file + d_targets = "data/pd_targets.csv" + # Measured concentration and response data for fitting (optional) + data = "data/pkpd_measured.csv" + # Default PK model: one_compartment, two_compartment + model = "one_compartment" + # Solver options for PK integration + solver = {atol = 1e-6, rtol = 1e-5} + # Output directory relative to run directory + outdir = "results/pkpd/" + +Comments follow the style of existing config sections[\[7\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/config.toml#:~:text=,120%2C%20240%2C%20480%2C%20960). Additional keys (e.g., `bounds` for `IC50`) can be added later. + +## CLI design + +- **Python module:** `phoskintime.extensions.dose_response.cli` with click/argparse interface. +- **Command:** + + +- python -m phoskintime dose-response --conf config.toml + + +- **Pixi task:** Add to `pixi.toml`: + + +- [[task]] + name = "dose-response" + cmd = "python -m phoskintime dose-response --conf config.toml" + category = "analysis" + + +- Arguments: `--fit` to estimate PK/PD parameters; `--simulate` to run simulation with fixed parameters; `--plot` to generate plots. +- Output directory: created as `//` with subfolders `trajectories`, `plots`, `metrics`, following existing result conventions. + +## Minimal viable implementation + +- **Inputs:** `dose_schedule.csv` with a single bolus dose; `pd_targets.csv` with one kinase target and an `IC50` value; baseline model outputs. +- **Algorithm:** One‑compartment PK with fixed `V` and `k_el`; compute drug concentration; apply a simple Emax inhibition to `c_k`; re-simulate networkmodel ODE to obtain trajectories; compute residuals vs. baseline. +- **Outputs:** Concentration curve; inhibited `c_k` values over time; perturbed trajectories; simple plots. +- **Tests:** unit tests for PK differential equation; integration test verifying that increasing dose decreases phosphorylation output; tests verifying correct loading of input tables. + +## Full implementation roadmap + +- **v0.1:** Add file loaders, one‑compartment PK model, Emax PD link and CLI wrapper; produce concentration and effect outputs; include minimal tests. +- **v0.2:** Support multi‑compartment PK, Hill functions and multiple targets; allow fitting `k_el`, `IC50` using measured data; integrate with `kinopt`/`tfopt` optimization to co‑fit PD parameters. +- **v0.3:** Add plotting utilities (dose‑response curves, sensitivity analysis) and export to dashboard; implement configuration validation. +- **v0.4:** Include advanced QSP features such as metabolite compartments or saturable elimination; integrate with `BayesianInference` to estimate posterior distributions; provide example notebooks. +- **v1.0:** Stable release with documentation, reproducible examples and cross‑validation on published drug perturbation datasets. + +## Validation strategy + +- **Unit tests:** verify PK ODE solutions against analytical solutions for bolus dosing; check PD scaling functions produce expected limiting values. +- **Integration tests:** run simulation with and without drug and ensure the model output changes appropriately (e.g., decreased phosphorylation when inhibiting kinases). +- **Synthetic data tests:** generate synthetic dose‑response curves using known PK/PD parameters and ensure the fitter recovers them within tolerance. +- **Regression tests:** fix a seed and verify that changes in implementation do not alter existing results. +- **Biological sanity checks:** compare predicted IC50 and elimination half‑lives with literature values; check that predicted changes in kinase activity multipliers are plausible relative to measured potency. +- **External benchmarks:** where possible, compare simulated responses to LINCS/CPTAC dose‑response experiments for the same drugs. + +## Risks and failure modes + +- **Parameter non‑identifiability:** PK and PD parameters may be poorly identifiable from limited dose‑response data, leading to wide uncertainty. +- **Scale mismatch:** integrating PK models can introduce timescales (minutes/hours) different from cellular phosphorylation timescales (minutes); solver stiffness may increase. +- **Insufficient data:** high‑quality dose‑response phosphoproteomics is scarce; the extension may rely on assumptions about potency. +- **Overfitting:** fitting PK/PD parameters concurrently with network parameters may overfit small datasets. +- **Improper mapping:** incorrect mapping of drug targets to model parameters could misrepresent mechanism of action. + +## What not to do + +- Do **not** infer drug binding affinities from phosphorylation data alone. +- Do **not** claim that the PK model is physiologically accurate beyond the simple compartment(s) defined. +- Do **not** hard‑code drug‑specific values; keep parameters configurable. +- Do **not** alter the core `networkmodel` equations; extend them through a wrapper. +- Do **not** ignore parameter bounds defined in existing configuration files[\[8\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/config.toml#:~:text=,0). + +## Recommended priority + +**Second**. Extending PhosKinTime with a PK‑PD layer is technically feasible and directly relevant for pharmacological studies. The required ODE and optimization infrastructure aligns with the existing framework, but the development effort is moderate due to new compartments and external data dependencies. + +# 2. mRNA Vaccine / Antigen‑Expression / Immune‑Response Extension + +## Executive summary + +This extension models how synthetic mRNA vaccines or gene therapy constructs drive antigen expression and trigger innate immune responses. PhosKinTime currently simulates endogenous mRNA, protein and phosphorylation dynamics[\[3\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=%60%60%60text%20TIME_POINTS_PROTEIN%20,phospho%20fitted%20trajectories). The vaccine extension would add an exogenous mRNA species encoding an antigen; its translation would produce antigenic protein, which could be processed and presented to immune effectors. The framework would then simulate downstream signalling pathways (e.g., interferon responses) by introducing additional state variables for cytokines and immune modulators. The extension does **not** claim to model adaptive immunity (e.g., T cell clonal expansion) or to predict vaccine efficacy; it focuses on early antigen expression and innate signalling in the same timescale as phospho‑proteomics experiments. + +## Why this is or is not close to the current framework + +- **Classification:** downstream annotation layer / medium-term extension. +- **Justification:** The current ODE system describes gene expression and post‑translational modifications within cells. Adding an exogenous mRNA vaccine is conceptually similar to adding a new mRNA/protein species but introduces novel processes: exogenous mRNA uptake, translation, antigen processing and innate immune sensing. A minimal model could reuse existing translation and degradation parameters but needs new states for antigen and cytokine species and may require coupling to pattern‑recognition receptor pathways. Therefore it sits at a medium distance from the core but remains within dynamic modelling. + +## Current PhosKinTime assets this can reuse + +- **Translation kinetics:** existing parameters for mRNA degradation (`B_i`) and protein production (`C_i`) and turnover (`D_i`)[\[1\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=,factor%20scaling%20parameter) can be reused to simulate antigen translation and degradation. +- **Predicted trajectories and residual analyses:** existing pipeline writes mRNA and protein fitted trajectories[\[3\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=%60%60%60text%20TIME_POINTS_PROTEIN%20,phospho%20fitted%20trajectories) and residuals[\[4\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=). These utilities can be reused to visualise antigen expression and immune response curves. +- **Sensitivity analysis infrastructure:** to quantify which kinetic parameters (e.g., vaccine dose, translation rate) most influence antigen peak concentration[\[5\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=). +- **Dashboard and export functions:** can be extended to include antigen and cytokine trajectories in interactive dashboards. +- **Configuration and CLI patterns:** reuse the `config.toml` schema and CLI skeleton for new tasks[\[7\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/config.toml#:~:text=,120%2C%20240%2C%20480%2C%20960). + +## Required new scientific layer + +- **Exogenous mRNA uptake and decay:** a new state variable `M_v(t)` representing vaccine mRNA copies with uptake kinetics and degradation rate `k_dec_v`. + +$$\frac{dM_{v}}{dt} = u_{v}(t) - k_{dec\_ v}M_{v}$$ + +where `u_v(t)` is the dosing schedule. + +- **Antigen translation and degradation:** a new protein state `P_v(t)` produced from `M_v` with translation rate `k_trans_v` and degraded at `k_deg_v`. + +- **Innate immune sensing:** simplified pattern‑recognition receptor activation triggered by `M_v` or `P_v` could be modelled as a sigmoidal function producing an interferon or cytokine state `I(t)`. + +$$\frac{dI}{dt} = k_{I}\frac{M_{v}^{h}}{K_{I}^{h} + M_{v}^{h}} - k_{clear}I$$ + +- **Impact on network:** cytokine signalling could modulate transcription factors (`tf_scale`), basal production (`A_i`) or degradation parameters (`B_i`,`C_i`) for select genes. A mapping file would specify which PhosKinTime parameters are impacted. + +- **Optional modules:** translation efficiency modifiers for codon optimisation, mRNA secondary structure stability, or lipid nanoparticle delivery could be incorporated in later versions. + +## Realistic inputs + +| Filename | Required columns | Optional columns | Units | Source | Notes | +|--------------------------|-----------------------------------------------------------------|------------------------|--------------------|--------------------------------------------------------------|-------------------------------------------------------------------------------| +| `vaccine_schedule.csv` | `time`, `dose_mRNA` | `formulation`, `route` | hours, µg | User‑provided | Specifies injection time and dose; `formulation` may affect uptake rate. | +| `vaccine_params.csv` | `k_uptake`, `k_dec_v`, `k_trans_v`, `k_deg_v` | `codon_opt_score` | rate constants | Literature on mRNA vaccine kinetics; pre‑clinical PK/PD data | Parameter guesses or priors for vaccine mRNA translation and degradation. | +| `immune_params.csv` | `k_I`, `K_I`, `h`, `k_clear` | `target_mapping` | as indicated | Immunology literature | Defines cytokine dynamics. | +| `antigen_annotation.csv` | `gene`, `antigen_peptide`, `MHC_allele`, `immunogenicity_score` | | sequences/affinity | IEDB, ImmPort | Connects antigen translation products to known epitopes. | +| `immune_targets.csv` | `target_type`, `target_id`, `effect`, `magnitude` | | dimensionless | Expert‑curated | Maps cytokine levels to modifications of PhosKinTime parameters. | +| `vaccination_data.csv` | `time`, `measured_antigen`, `measured_cytokine` | | hours | Experimental data | For fitting vaccine kinetic parameters and validating immune response curves. | + +## Realistic input sources + +- **Immune Epitope Database (IEDB):** epitope sequences, MHC binding affinities and immunogenicity scores. +- **ImmPort and Expression Atlas:** innate immune response time courses after mRNA vaccination. +- **GEO / ArrayExpress:** transcriptomic and proteomic datasets post‑vaccination for parameter fitting. +- **Vaccine PK studies:** published data on mRNA stability and translation kinetics. + +## Outputs + +| Output file | Description | +|--------------------------------|---------------------------------------------------------------------------------------------| +| `vaccine_antigen.csv` | Simulated antigen mRNA and protein levels vs. time. | +| `vaccine_immune.csv` | Innate immune mediator (e.g., interferon) levels vs. time. | +| `vaccine_effects.csv` | Effective modifications to PhosKinTime parameters (e.g., `tf_scale` modulation). | +| `vaccination_trajectories.csv` | Predicted trajectories of endogenous mRNA, protein and phospho species under vaccination. | +| `vaccine_residuals.csv` | Differences between measured and predicted antigen and cytokine levels. | +| `vaccine_plots/` | Plots of antigen expression and immune response; overlay with experimental data. | +| `vaccine_report.json` | Metadata summarizing vaccine kinetics parameters, immunogenicity annotation and provenance. | + +## Proposed repository structure + + extensions/ + vaccine/ + __init__.py + mRNA.py # vaccine mRNA uptake and decay models + antigen.py # translation and degradation of antigen protein + immune.py # innate immune sensing and cytokine dynamics + coupling.py # maps immune mediators to PhosKinTime parameters + simulate.py # integrates vaccine and network ODEs + fit.py # fits kinetic parameters using experimental data + export.py # writes outputs and generates plots + inputs.py # validators for vaccine-related tables + config.py # configuration schema + cli.py # command-line interface + tests/ + test_vaccine_models.py + test_coupling.py + +The folder lives under `extensions` to avoid polluting core modules. `simulate.py` will import the existing `networkmodel` solver and apply parameter modifications. + +## Configuration design + +Add a `[vaccine]` section to `config.toml`: + + [vaccine] + # Path to dosing schedule + dose_schedule = "data/vaccine_schedule.csv" + # Parameter files + vaccine_params = "data/vaccine_params.csv" + immune_params = "data/immune_params.csv" + antigen_annotation = "data/antigen_annotation.csv" + immune_targets = "data/immune_targets.csv" + # Output directory + outdir = "results/vaccine/" + # Flags + fit = true # fit kinetic parameters if data present + use_codons = false # apply codon optimisation modifiers + +Each parameter file contains columns described above. Comments and keys follow existing style[\[7\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/config.toml#:~:text=,120%2C%20240%2C%20480%2C%20960). + +## CLI design + +- **Python module:** `phoskintime.extensions.vaccine.cli`. +- **Command:** + + +- python -m phoskintime vaccine --conf config.toml [--fit] [--simulate] + + +- **Pixi task:** add `vaccine` under `[[task]]` with the same command. +- Optional flags: `--fit` fits kinetic parameters, `--simulate` runs simulation with given parameters, `--plot` draws antigen and immune curves. +- Output directories follow the pattern `//` with subdirectories for trajectories, plots and metrics. + +## Minimal viable implementation + +- **Inputs:** A single vaccine dose schedule; default parameter values for uptake, translation and immune sensing; mapping file linking interferon to a global transcription factor scaling parameter. +- **Algorithm:** Solve additional ODEs for `M_v`, `P_v` and `I` using explicit Euler or Diffrax integrator; update `tf_scale` or `A_i` in `networkmodel` with a linear function of `I`; run simulation; produce antigen and immune curves and overlay with any measured data. +- **Outputs:** Antigen and immune trajectories; predicted modifications to gene expression; simple plots. +- **Tests:** unit tests ensuring the antigen ODE yields expected exponential decay; integration test verifying that increasing vaccine dose increases antigen levels; test that immune coupling modifies network parameters. + +## Full implementation roadmap + +- **v0.1:** Implement basic mRNA and antigen ODEs and coupling to `tf_scale`; produce antigen and immune plots; write CLI and configuration; include tests. +- **v0.2:** Include innate immune sensing via Hill kinetics; allow parameter fitting to measured cytokine data; support multiple antigens; integrate codon optimisation modifiers. +- **v0.3:** Add mapping between antigen sequences and immunogenicity scores using IEDB; export epitope annotation; include interactive dashboard elements. +- **v0.4:** Extend to poly‑epitope constructs; include simulation of memory cytokines; provide example notebooks with vaccination time courses. +- **v1.0:** Publish validated extension with real vaccine datasets and cross‑validated predictions. + +## Validation strategy + +- **Unit tests:** check ODE solutions and coupling functions; ensure codon optimisation multiplier behaves correctly. +- **Integration tests:** simulate a simple vaccination scenario and verify that antigen and immune curves follow expected kinetics; ensure coupling modifies gene expression in network outputs. +- **Synthetic data tests:** create synthetic vaccine and immune time courses; test that fitting recovers the known parameters. +- **Biological sanity checks:** compare simulated antigen half‑life and interferon dynamics with published data; ensure predicted modulation of transcription factor scaling falls within realistic bounds. +- **External benchmarks:** if datasets from vaccine studies are available, fit the model and compare predicted cytokine profiles and gene expression changes. + +## Risks and failure modes + +- **Complexity of immune responses:** innate immune signalling involves many pathways; the simplified model may capture only a subset of dynamics. +- **Data scarcity:** high‑quality time‑series data for antigen translation and cytokine levels are limited; parameter estimates may be uncertain. +- **Coupling assumptions:** mapping interferon to transcription factor scaling may be simplistic; real regulatory effects are gene‑specific. +- **Parameter identifiability:** multiple parameters (uptake, degradation, translation) might yield similar antigen trajectories. +- **Numerical stiffness:** addition of rapid immune reactions could stiffen the ODE system and require careful solver settings. + +## What not to do + +- Do **not** attempt to model adaptive immunity or antibody affinity maturation; this extension focuses on early cellular responses. +- Do **not** claim to predict vaccine efficacy or protective immunity from phosphorylation data. +- Do **not** incorporate proprietary vaccine formulation details; only publicly available parameters should be included. +- Do **not** modify core `networkmodel` files; implement coupling through wrappers. +- Do **not** ignore mRNA translation and degradation parameters when simulating antigen production. + +## Recommended priority + +**Later.** While scientifically interesting, this extension introduces new biological domains (vaccine delivery and innate immunity) and requires external data and assumptions. It should be implemented after a PK‑PD extension and structural annotations are in place. + +# 3. Antibody Perturbation / Antibody‑Response Extension + +## Executive summary + +This extension models how exogenous antibodies bind to cellular proteins or phospho‑epitopes and perturb signalling dynamics. PhosKinTime currently predicts phosphorylation rates and kinase activities[\[9\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=), but does not represent antibody binding or immune responses. The antibody extension would introduce binding kinetics (association and dissociation) between antibodies and their targets, reducing the availability or activity of the bound proteins. It can simulate neutralisation (removal of active protein) or crosslinking (aggregation). The extension does **not** perform antibody design; it uses user‑supplied binding parameters and epitope mapping. + +## Why this is or is not close to the current framework + +- **Classification:** downstream annotation layer / external pipeline integration. +- **Justification:** PhosKinTime focuses on intracellular kinetics; antibody perturbation acts at the extracellular or cell‑surface level and may not be captured by existing parameters. However, some antibodies (e.g., phospho‑specific antibodies) directly sequester phospho‑sites and can be represented as an additional inhibitory term on phosphorylation rates. Thus the extension can leverage existing phosphorylation dynamics but requires new state variables for antibody‑antigen complexes and new input mapping. It remains outside the core but can interface through targeted parameter modifications. + +## Current PhosKinTime assets this can reuse + +- **Phosphorylation rates and kinase activity outputs:** predicted phosphorylation rates per site[\[10\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=%23%23%20Phosphorylation) and kinase activities[\[9\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=) can be targeted by antibodies. +- **Residue-level mapping:** data preprocessing produces mappings of kinase‑phosphorylation interactions and gene identifiers[\[11\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/processing/README.md#:~:text=,mapping%20files%20for%20further%20analysis); this can be extended to map antibody targets. +- **Sensitivity analysis:** can identify phospho‑sites or proteins whose perturbation significantly alters network behaviour[\[5\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=), guiding antibody targeting strategies. +- **Optimization and simulation engine:** the same ODE solver can incorporate additional binding ODEs; the export and dashboard modules can display perturbed trajectories. + +## Required new scientific layer + +- **Binding kinetics:** For each antibody/epitope pair, introduce variables for free antibody (`Ab`), free antigen (`Ag`) and bound complex (`AbAg`). Mass‑action kinetics: + +$$\frac{dAb}{dt} = - k_{on}Ab \times Ag + k_{off}AbAg - k_{clear}Ab$$ + +$$\frac{dAg}{dt} = - k_{on}Ab \times Ag + k_{off}AbAg + ...$$ + +$$\frac{dAbAg}{dt} = k_{on}Ab \times Ag - k_{off}AbAg - k_{clear\_ complex}AbAg$$ + +`Ag` corresponds to the concentration of a specific protein or phospho‑site predicted by PhosKinTime; `Ab` is the antibody concentration input; `k_on`, `k_off`, `k_clear` are binding and clearance rates. + +- **Effect on signalling:** Bound antigen is considered inactive. For kinase targets, effective kinase activity multiplier is reduced; for phospho‑site targets, forward phosphorylation rate scaling `kappa_{g,s}` could be modulated. + +- **Epitope mapping:** A mapping file linking antibody names to gene symbols, phosphorylation site positions or domains (e.g., Y1234) is required. For antibodies targeting conformational epitopes, integration with the structural extension (Section 4) may be necessary. + +- **Antibody clearance:** Antibody pharmacokinetics may be modelled similarly to the PK extension (Section 1) but often with longer half‑life; optional compartments can be added. + +## Realistic inputs + +| Filename | Required columns | Optional columns | Units | Source | Notes | +|-----------------------|-----------------------------------------------------------------------------------|-------------------------|-----------------|-------------------------------|-----------------------------------------------------------------------------------------------------------| +| `antibody_dose.csv` | `time`, `dose_concentration` | `isotype` | hours, µM | User-provided dosing protocol | Defines when antibodies are administered and at what concentration. | +| `antibody_params.csv` | `antibody`, `target_type`, `target_id`, `k_on`, `k_off`, `k_clear`, `effect_type` | `Kd`, `stoichiometry` | 1/(µM hr), hr⁻¹ | Literature, BindingDB | Binding kinetics per antibody-target pair; `effect_type` describes how binding modifies model parameters. | +| `epitope_mapping.csv` | `antibody`, `gene`, `psite_position`, `residue`, `affinity_score` | `structure_id` | | IEDB, PDB | Maps antibodies to specific proteins or phospho‑sites; may include structural annotations. | +| `antibody_pk.csv` | `k_abs`, `k_el`, `volume` | | hr⁻¹, hr⁻¹, L | Pharmacokinetic studies | Optional PK model for antibody clearance. | +| `antibody_data.csv` | `time`, `antigen_activity` | `complex_concentration` | hours | Experimental data | For fitting binding parameters and validating model predictions. | + +## Realistic input sources + +- **IEDB and ImmPort:** epitope and monoclonal antibody binding data. +- **BindingDB and DrugBank:** affinity constants (`Kd`), association/dissociation rates for antibody‑protein pairs. +- **Therapeutic antibody databases (e.g., Thera‑SAbDab):** sequences, isotypes and kinetic parameters. +- **Bioinformatics tools:** predicted epitopes using Bepipred, DiscoTope; structural mapping via PDB or AlphaFold; cross‑reference with `processing/map.py` outputs[\[11\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/processing/README.md#:~:text=,mapping%20files%20for%20further%20analysis). + +## Outputs + +| Output file | Description | +|-----------------------------|--------------------------------------------------------------------------------------------| +| `antibody_binding.csv` | Simulated free and bound antibody/antigen concentrations over time. | +| `antibody_effects.csv` | Effective modifications to kinase activities or phosphorylation rate constants over time. | +| `antibody_trajectories.csv` | Predicted mRNA, protein and phospho trajectories under antibody perturbation. | +| `antibody_residuals.csv` | Differences between measured and predicted antigen activities and phosphorylation signals. | +| `antibody_sensitivity.csv` | Sensitivity of binding parameters (e.g., `k_on`, `k_off`) on signalling outcomes. | +| `antibody_report.json` | Metadata summarizing binding parameters, epitope mapping, and provenance. | +| `antibody_plots/` | Plots of antibody concentration, binding kinetics, and perturbed trajectories. | + +## Proposed repository structure + + extensions/ + antibody/ + __init__.py + binding.py # defines mass‑action binding kinetics and antibody PK + coupling.py # maps bound complexes to PhosKinTime parameter modifications + simulate.py # integrates binding ODEs with network model + fit.py # fits binding parameters to experimental data + export.py # writes outputs and plots + inputs.py # validates antibody-related tables + config.py # configuration schema + cli.py + tests/ + test_binding.py + test_coupling.py + +## Configuration design + +Add `[antibody]` to `config.toml`: + + [antibody] + dose_schedule = "data/antibody_dose.csv" + params = "data/antibody_params.csv" + epitopes = "data/epitope_mapping.csv" + ab_pk = "data/antibody_pk.csv" # optional + fit = false + outdir = "results/antibody/" + +This minimal section points to the input files; optional flags can enable parameter fitting or PK modelling. + +## CLI design + +- **Python module:** `phoskintime.extensions.antibody.cli`. +- **Command:** + + +- python -m phoskintime antibody --conf config.toml [--fit] [--simulate] + + +- **Pixi task:** add an `antibody` task with the same command. +- Flags: `--fit` to estimate `k_on`, `k_off` and clearance; `--simulate` to run with fixed parameters; `--plot` to generate binding and trajectory plots. +- Output directories: `//` with subfolders for binding, trajectories and plots. + +## Minimal viable implementation + +- **Inputs:** Single antibody targeting one phospho‑site; known `k_on` and `k_off`; a simple dose schedule. +- **Algorithm:** Simulate binding kinetics using ordinary differential equations; compute effective reduction in phosphorylation rate scaling; run `networkmodel` with modified `kappa_{g,s}`; output perturbed trajectories. +- **Outputs:** Antibody binding curve; reduction in target phosphorylation; predicted time courses of protein/phospho levels; simple plots. +- **Tests:** unit test for binding ODE; integration test verifying that increased antibody concentration reduces phosphorylation output; test that mapping between epitope and parameter works. + +## Full implementation roadmap + +- **v0.1:** Implement binding kinetics and simple inhibitory coupling; create CLI and configuration; provide tests. +- **v0.2:** Support multiple antibodies and multiple targets; incorporate stoichiometry and crosslinking effects; optional PK model for antibody clearance. +- **v0.3:** Enable fitting of binding parameters using measured binding or functional data; integrate with sensitivity analysis to prioritise targets. +- **v0.4:** Incorporate structural epitope mapping from Section 4; include antibody isotype effects (e.g., Fc‑mediated clearance); add example notebooks. +- **v1.0:** Provide a validated extension with documentation and tested on therapeutic antibody perturbation datasets. + +## Validation strategy + +- **Unit tests:** check mass‑action binding solutions; ensure that the mapping of bound complex reduces the corresponding kinetic parameter. +- **Integration tests:** simulate a scenario with known binding parameters and verify expected reduction in phosphorylation; ensure that adding more antibodies intensifies inhibition. +- **Synthetic data tests:** generate synthetic binding and signalling data; fit `k_on`, `k_off` and verify recovery. +- **Biological sanity checks:** compare predicted binding half‑life and occupancy with literature; ensure that the model does not predict antibody levels beyond plausible physiological range. +- **External benchmarks:** use published antibody perturbation proteomics datasets to validate predicted effects on phosphorylation and downstream transcription. + +## Risks and failure modes + +- **Mapping uncertainty:** epitope mapping may be uncertain; mismapping an antibody to the wrong site could mislead predictions. +- **Data limitations:** kinetic constants are often unavailable for specific antibodies and conditions; may require assumptions. +- **In vivo complexity:** antibody effects include immune effector functions (e.g., ADCC) not modelled here; ignoring them may oversimplify biological outcomes. +- **Non‑identifiability:** `k_on` and `k_off` may be correlated, leading to poorly constrained fits. +- **Numerical stiffness:** adding binding kinetics may increase stiffness, requiring careful solver settings. + +## What not to do + +- Do **not** claim to design antibodies or predict epitope sequences; rely on external epitope mapping and kinetics. +- Do **not** assume that antibody binding always results in complete inhibition; allow partial occupancy. +- Do **not** ignore clearance of antibodies or complexes when modelling long time courses. +- Do **not** modify core ODEs; implement binding through additional compartments. +- Do **not** embed proprietary antibody sequences. + +## Recommended priority + +**Later / downstream integration.** Although antibody perturbations are biologically relevant, the complexity of binding kinetics and scarcity of high‑quality time‑course data make this a lower priority. It should be developed after PK‑PD and structural annotation extensions are established. + +# 4. Structural Bioinformatics Extension + +## Executive summary + +This extension provides structural annotations for proteins and phosphorylation sites represented in PhosKinTime. It does not alter the dynamic model but enriches outputs with domain, secondary structure, solvent accessibility and homology information. These annotations can aid interpretation of fitted parameters and prioritise targets for experimental validation or MD simulations. The extension maps each protein (gene) to a UniProt accession, retrieves or predicts a structure (PDB or AlphaFold), and uses tools such as DSSP or FreeSASA to compute per‑residue features. It also maps phosphorylation sites to 3D coordinates and determines whether they lie in ordered domains, disordered regions or interfaces. The extension does **not** perform structural modelling or design; it annotates existing structures. + +## Why this is or is not close to the current framework + +- **Classification:** downstream annotation layer. +- **Justification:** The current model does not use structural information; outputs are purely temporal and quantitative. Structural annotation does not change the ODE system but adds metadata and derived metrics. It can be implemented as a separate post‑processing step that reads existing outputs (phosphorylation rates, sensitivities, mapping tables) and enriches them. Therefore it is conceptually decoupled and safe to implement without altering core models. + +## Current PhosKinTime assets this can reuse + +- **Mapped gene and phosphorylation site identifiers:** The preprocessing mapping step produces tables `mapping.csv` and `nodes.csv` linking kinases, genes and phospho‑sites[\[12\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/processing/README.md#:~:text=,). +- **Phosphorylation rate outputs:** `export_S_rates` summarises phosphorylation rates by protein and site[\[10\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=%23%23%20Phosphorylation). These can be annotated with structural features. +- **Sensitivity rankings:** sensitivity analysis identifies influential parameters or sites[\[5\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=); structural annotation can prioritise high‑impact sites. +- **Configuration system:** a new section can be added without affecting existing modules. Export utilities and dashboard can be extended to include structural columns. + +## Required new scientific layer + +- **Sequence-to-structure mapping:** map each gene symbol to a UniProt accession using external databases (e.g., MyGeneInfo) and retrieve structures: + +- If a resolved structure exists in the Protein Data Bank, download the PDB file. + +- Otherwise, retrieve an AlphaFold model from AlphaFold DB or EBI PDB. Use the highest‑confidence model for the species of interest. + +- **Phosphosite mapping:** use the residue number and amino acid from the phosphorylation site (from `psite_position` and `residue` fields) to locate the corresponding residue in the structure. Consider isoform numbering; if mapping fails, flag the site for manual curation. + +- **Feature computation:** compute per‑residue annotations: + +- Secondary structure (helix, sheet, loop) using DSSP. + +- Solvent accessible surface area (SASA) using FreeSASA or DSSP output. + +- Domain and motif annotations via Pfam/InterPro. + +- Disorder prediction using tools like IUPred or by absence of structure. + +- **Integrative summary:** join computed features with phosphorylation rate and sensitivity tables. Provide summary statistics (e.g., average SASA for high‑sensitivity sites). Optionally export PyMOL session scripts to visualise highlighted sites. + +## Realistic inputs + +| Filename | Required columns | Optional columns | Units | Source | Notes | +|-------------------------|------------------------------------------------------------------------------|------------------|-------|-----------------------------|-----------------------------------------------------------------------| +| `structure_sources.csv` | `gene`, `uniprot_id`, `preferred_pdb_id` | `isoform` | | UniProt, MyGeneInfo | Map gene to structure; `preferred_pdb_id` can be blank for AlphaFold. | +| `psite_mapping.csv` | `gene`, `residue`, `position`, `structure_chain`, `structure_residue_number` | | | Generated by mapping script | Connects phospho‑sites to structure residues. | +| `features_config.csv` | `feature`, `tool`, `parameters` | | | User configuration | Lists which structural features to compute and tool settings. | +| `structures/` | downloaded PDB or mmCIF files | | | RCSB PDB, AlphaFold DB | Local storage for structures. | + +## Realistic input sources + +- **UniProt and MyGeneInfo:** mapping from gene symbol to UniProt accession and isoform information. +- **Protein Data Bank (PDB):** resolved protein structures. +- **AlphaFold DB:** predicted structures when no PDB exists. +- **Pfam / InterPro:** domain and motif annotations. +- **DSSP / FreeSASA:** tools for secondary structure and SASA computation. +- **Disorder prediction servers:** IUPred, MobiDB-lite for intrinsic disorder. + +## Outputs + +| Output file | Description | +|-----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `structure_annotations.csv` | Per‑residue table with secondary structure, SASA, domain and disorder information. | +| `psite_structural.csv` | Phosphorylation sites annotated with structural features and mapped coordinates. | +| `site_prioritization.csv` | Ranked list of phospho‑sites combining sensitivity score, phosphorylation rate[\[10\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=%23%23%20Phosphorylation) and structural features (e.g., surface exposure). | +| `protein_models/` | Downloaded PDB/mmCIF or AlphaFold structures, renumbered and trimmed to match sequences. | +| `pymol_sessions/` | PyMOL or ChimeraX session files highlighting high‑impact sites. | +| `structural_report.json` | Metadata summarizing methods, data sources and versioning. | + +## Proposed repository structure + + extensions/ + structural/ + __init__.py + fetch_structures.py # download PDB/AlphaFold models given UniProt IDs + map_sites.py # map phospho positions to structure residue numbers + compute_features.py # run DSSP, FreeSASA and disorder predictors + prioritize.py # rank sites combining structural and dynamic metrics + export.py # write annotation tables and PyMOL scripts + config.py # configuration schema + cli.py + tests/ + test_mapping.py + test_feature_computation.py + +The structural extension is separated from dynamic modelling; it reads existing outputs and writes annotation files. + +## Configuration design + +Add `[structural]` to `config.toml`: + + [structural] + # Path to mapping of genes to UniProt accessions + source_map = "data/structure_sources.csv" + # Directory to store downloaded structures + structure_dir = "data/structures/" + # Feature configuration file + features = "data/features_config.csv" + # Whether to compute disorder predictions + compute_disorder = true + # Output directory + outdir = "results/structural/" + +## CLI design + +- **Python module:** `phoskintime.extensions.structural.cli`. +- **Command:** + + +- python -m phoskintime structural --conf config.toml [--fetch] [--annotate] [--prioritize] + + +- **Pixi task:** add `structural` command with the same options. +- Flags: `--fetch` downloads structures; `--annotate` maps sites and computes features; `--prioritize` ranks sites; `--plot` could generate structural summaries. +- Output directories follow `//` for gene‑specific annotations. + +## Minimal viable implementation + +- **Inputs:** Mapping file for a small set of genes; list of phospho‑sites; simple feature configuration (secondary structure and SASA only). +- **Algorithm:** Fetch structures from PDB/AlphaFold; map phospho‑site positions to residue numbers; run DSSP to compute secondary structure and SASA; join with phosphorylation rate table; export annotated table. +- **Outputs:** `psite_structural.csv` with columns for residue, secondary structure and SASA; simple ranking combining high SASA and high phosphorylation rate. +- **Tests:** unit tests for mapping (correct residue numbers), feature computation (expected output length) and prioritisation (ties broken consistently). + +## Full implementation roadmap + +- **v0.1:** Implement structure fetching and site mapping; compute secondary structure and SASA; basic ranking; include tests. +- **v0.2:** Add disorder prediction and domain/motif annotations from Pfam/InterPro; support isoforms; compute solvent exposure categories (buried vs. exposed). +- **v0.3:** Integrate sensitivity scores[\[5\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=) and phosphorylation rate rankings[\[10\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=%23%23%20Phosphorylation); export combined ranking; generate PyMOL sessions; include interactive dashboards. +- **v0.4:** Provide precomputed annotations for common organisms; support alternative structural sources (e.g., Swiss‑Model); implement caching and update mechanisms. +- **v1.0:** Stable release with documentation, validated mapping on test datasets and reproducible examples. + +## Validation strategy + +- **Unit tests:** verify that residue mapping correctly handles numbering offsets and missing residues; check that feature computation tools are invoked and outputs match expected dimensions. +- **Integration tests:** run the full pipeline on a test dataset (e.g., a small set of proteins) and check that outputs contain expected columns and values; verify that high‑SASA sites are correctly identified. +- **Cross‑validation:** compare computed secondary structure and SASA with annotations from existing resources (e.g., DSSP or PDBsum); confirm mapping accuracy using manual inspection for a subset. +- **Regression tests:** ensure that adding new features or updating databases does not break existing functionality. + +## Risks and failure modes + +- **Mapping errors:** mismatches between gene isoforms, sequence numbering and structure numbering can lead to incorrect site annotations. +- **Data availability:** some proteins may lack resolved structures; AlphaFold predictions may have low confidence in certain regions. +- **Tool dependencies:** DSSP, FreeSASA and disorder predictors must be installed; version differences can yield different results. +- **Computational cost:** large numbers of proteins/sites could slow computation; caching and parallelisation may be needed. +- **Overinterpretation:** structural annotation does not confirm functional importance; high SASA does not guarantee accessibility to kinases or antibodies. + +## What not to do + +- Do **not** attempt de novo structure prediction or MD simulations; rely on existing structures or AlphaFold models. +- Do **not** override core outputs; structural annotation is supplementary. +- Do **not** claim that structural features alone determine phosphorylation or druggability; use them in combination with dynamic metrics. +- Do **not** embed large structural files in the repository; download and cache them externally. +- Do **not** mix isoforms without explicit mapping. + +## Recommended priority + +**First.** Structural annotation is independent of dynamic modelling and provides immediate value by contextualising fitted parameters. It requires no changes to core ODE models and can be implemented as a post‑processing pipeline using publicly available tools and databases. + +# 5. Molecular Dynamics Simulation Prioritization Extension + +## Executive summary + +This extension prioritises proteins or phosphorylation sites for detailed molecular dynamics (MD) simulations based on PhosKinTime outputs and structural annotations. It does **not** perform MD simulations itself; rather, it generates ranking tables, prepares input files and optionally runs lightweight energy minimisations to check structural feasibility. The goal is to select a manageable subset of sites or protein complexes that show high phosphorylation flux, sensitivity or drug/antibody targeting potential for further in silico or in vitro study. The extension leverages structural annotations from Section 4 and dynamic metrics from PhosKinTime to produce an integrated prioritisation. + +## Why this is or is not close to the current framework + +- **Classification:** downstream annotation layer / external pipeline integration. +- **Justification:** MD simulations operate on atomistic timescales and are outside the scope of the ODE-based model. However, the extension can use dynamic outputs (phosphorylation rates, sensitivities)[\[10\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=%23%23%20Phosphorylation)[\[5\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=) and structural annotations to guide MD simulation planning. It does not modify the dynamic model; therefore it is a downstream integration aimed at bridging PhosKinTime with molecular simulation pipelines. + +## Current PhosKinTime assets this can reuse + +- **Phosphorylation rate and kinase activity outputs:** used to identify sites with high flux[\[10\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=%23%23%20Phosphorylation). +- **Sensitivity analysis:** identifies parameters whose perturbation most affects outcomes[\[5\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=); sites with high sensitivity may be prioritised. +- **Structural annotations:** generated by the structural extension; provide PDB/AlphaFold structures and per‑residue features. +- **Mapping tables:** `mapping.csv` and `psite_structural.csv` link dynamic entities to structure residues[\[12\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/processing/README.md#:~:text=,). +- **Configuration and export utilities:** to read dynamic outputs and write ranking tables. + +## Required new scientific layer + +- **Ranking criteria:** define a composite score for each phospho‑site or protein combining: + +- Normalised phosphorylation rate magnitude[\[10\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=%23%23%20Phosphorylation). + +- Sensitivity score[\[5\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=). + +- Structural accessibility (e.g., high SASA) and disorder from structural annotations. + +- Potential druggability or antibody targeting (if mapped in other extensions). Weights for each criterion can be user‑defined. + +- **MD readiness assessment:** check whether the structure covers the phospho‑site (no missing residues), whether the environment is conducive to MD (no unresolved loops) and whether post‑translational modifications (phosphorylation) can be parameterised with available force fields. + +- **Preparation of simulation files:** generate coordinate (PDB) and topology (e.g., CHARMM or AMBER) inputs for the selected sites or proteins. Use existing tools (e.g., BioPandas or MDAnalysis) to extract segments and optionally apply phosphorylation modifications using libraries like ParmEd. Provide instructions or scripts for running MD in GROMACS or OpenMM, but do not run them within PhosKinTime. + +- **Integration with docking or coarse‑grained simulation pipelines (optional):** prepare mutated or modified structures for further analysis. + +## Realistic inputs + +| Filename | Required columns | Optional columns | Units | Source | Notes | +|---------------------------------|---------------------------------------------------------------------------|---------------------------------------|-------|-----------------------------|--------------------------------------------------------------------------------| +| `md_prioritization_params.toml` | `weights.rate`, `weights.sensitivity`, `weights.sasa`, `weights.disorder` | `weights.druggability`, `max_targets` | | User-defined | Defines how to weigh different criteria and how many targets to select. | +| `psite_structural.csv` | `gene`, `psite`, `rate`, `sensitivity`, `sasa`, `disorder` | `druggability_score` | | From structural extension | Contains all metrics needed for ranking. | +| `forcefield_params.csv` | `residue`, `phosphorylated_topology` | | | Force-field parameter files | To ensure that selected phospho‑sites are supported by chosen MD force fields. | +| `md_templates/` | Predefined MD system templates (e.g., water box, ion parameters) | | | Provided by user | Templates for MD simulation preparation. | + +## Realistic input sources + +- **Outputs from PhosKinTime:** phosphorylation rates and sensitivity analyses[\[10\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=%23%23%20Phosphorylation)[\[5\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=). +- **Structural extension outputs:** `psite_structural.csv` with SASA and disorder scores. +- **Force field libraries:** AMBER, CHARMM, GROMOS; parameters for phosphorylated residues. +- **MD tools:** MDAnalysis, BioPandas, ParmEd for structure manipulation; GROMACS or OpenMM for simulation templates. + +## Outputs + +| Output file | Description | +|------------------------|--------------------------------------------------------------------------------------------------| +| `md_priority_list.csv` | Ranked list of sites or proteins with composite scores and selection rationale. | +| `md_ready_structures/` | Directory containing extracted PDB files of selected sites/proteins prepared for MD. | +| `md_input_scripts/` | Template simulation scripts (e.g., GROMACS `.mdp` files) with system setup parameters. | +| `md_report.json` | Metadata summarising ranking criteria, selected targets and provenance. | +| `md_plots/` | Bar plots or scatter plots of composite scores vs. criteria weights to visualise prioritisation. | + +## Proposed repository structure + + extensions/ + md_prioritization/ + __init__.py + rank.py # compute composite scores and produce ranking + prepare.py # generate MD-ready structure files + export.py # write rankings, scripts and plots + config.py # configuration schema + cli.py + tests/ + test_rank.py + test_prepare.py + +This extension depends on outputs from the structural extension; it should be placed under `extensions` and can be run separately. + +## Configuration design + +Add `[md_prioritization]` to `config.toml` or create a separate TOML file: + + [md_prioritization] + # Weights for ranking criteria (must sum to 1) + weights = {rate = 0.4, sensitivity = 0.3, sasa = 0.2, disorder = 0.1} + # Maximum number of targets to select + max_targets = 10 + # Force-field parameter file for phosphorylated residues + forcefield_params = "data/forcefield_params.csv" + # MD template directory + templates = "data/md_templates/" + # Output directory + outdir = "results/md_prioritization/" + +Users can adjust weights depending on the research question; the extension will normalise them. + +## CLI design + +- **Python module:** `phoskintime.extensions.md_prioritization.cli`. +- **Command:** + + +- python -m phoskintime md-prioritization --conf config.toml [--rank] [--prepare] + + +- **Pixi task:** add `md-prioritization` task with the same command. +- Flags: `--rank` generates the ranking list; `--prepare` creates MD-ready files for the top `max_targets`; `--plot` generates visualisations. +- Output directories follow `/` with subdirectories `rankings`, `structures`, `scripts` and `plots`. + +## Minimal viable implementation + +- **Inputs:** `psite_structural.csv` with rate and sensitivity; user‑defined weights; basic force‑field parameter list for phosphorylated serine and tyrosine. +- **Algorithm:** Normalise each criterion; compute a weighted sum to obtain composite scores; sort sites; select top N; extract the corresponding residues and their structural environment (e.g., ±10 residues) using MDAnalysis; save as PDB files; generate placeholder MD simulation scripts referencing those PDBs. +- **Outputs:** `md_priority_list.csv` with ranking and scores; `md_ready_structures/` with extracted PDB segments; simple bar plot of scores. +- **Tests:** unit tests verifying scoring and ranking; integration test ensuring that extracted PDB segments contain the correct residues; test that missing force‑field parameters raise warnings. + +## Full implementation roadmap + +- **v0.1:** Implement ranking based on dynamic and structural metrics; prepare simple PDB extracts; generate template scripts; include tests. +- **v0.2:** Support ranking at protein level and include druggability/antibody targeting scores if available; add interactive plots; implement user-defined scoring functions. +- **v0.3:** Automate checking of force‑field compatibility; add optional energy minimisation using OpenMM; export results in formats ready for MD packages. +- **v0.4:** Integrate with docking or coarse‑grained simulation pipelines; provide example notebooks and cross‑validation on known benchmark proteins. +- **v1.0:** Mature extension with documentation and published use cases. + +## Validation strategy + +- **Unit tests:** verify correct computation of composite scores; ensure that ranking is reproducible and respects `max_targets` constraint. +- **Integration tests:** run the full pipeline on a small dataset; confirm that extracted PDB segments correspond to the intended residues and that template scripts reference the correct files. +- **Cross‑validation:** compare rankings to known importance of phospho‑sites from literature; confirm that high‑ranked sites often correspond to functional hotspots. +- **Regression tests:** ensure that modifications (e.g., weight changes) produce expected differences but not unintended side effects. + +## Risks and failure modes + +- **Subjective weighting:** composite scores depend on chosen weights; different users may prioritise different criteria. +- **Force-field limitations:** some modifications may not be supported; manual parameterisation may be needed. +- **Structural coverage:** structures may not include the region of interest, leading to ranking based on incomplete information. +- **Overinterpretation:** ranking does not guarantee functional importance; experimental validation is required. +- **Complex pipelines:** preparing MD-ready systems may require manual inspection; automation can fail on edge cases (e.g., hetero-oligomers). + +## What not to do + +- Do **not** run full-scale MD simulations within the extension; focus on preparing inputs and rankings. +- Do **not** claim that the top-ranked sites will always yield meaningful MD insights; they are suggestions based on available metrics. +- Do **not** assign equal weight to all criteria without justification; encourage users to tailor weights. +- Do **not** embed large MD templates or parameter files in the repository; provide links or instructions. +- Do **not** alter core PhosKinTime ODE models. + +## Recommended priority + +**Only as a downstream integration.** This extension relies on structural annotations and dynamic metrics; it does not feed back into the modelling. It should be developed after structural annotation and PK/PD modules are in place. Its value lies in guiding external MD studies rather than enhancing PhosKinTime core functionality. + +# Recommended Implementation Order + +1. **Structural Bioinformatics Extension (Section 4)** — This is the most straightforward to implement because it operates as a separate post‑processing pipeline. It does not modify the core ODE model and relies on well‑established tools and publicly available databases. Structural annotation immediately enhances interpretability and enables downstream prioritisation of sites without requiring new experimental data. + +2. **Drug Dose‑Response / PK‑PD / QSP Extension (Section 1)** — Extending the model to include drug effects is highly relevant for pharmacological studies. The conceptual and implementation complexity is moderate; it leverages existing ODE infrastructure and parameter outputs. Implementing PK/PD will open the door to modelling other perturbations and is grounded in widely used PK models. + +3. **mRNA Vaccine / Antigen‑Expression / Immune‑Response Extension (Section 2)** — This extension requires adding new biological layers (exogenous mRNA, antigen translation and cytokine signalling) and depends on external kinetic data. While feasible, it introduces more assumptions and new state variables. It should follow once PK/PD modelling and structural annotation are stable. + +4. **Antibody Perturbation / Antibody‑Response Extension (Section 3)** — Modelling antibody binding kinetics is biologically interesting but demands detailed binding parameters and epitope mapping. Data scarcity and mapping uncertainties make this a lower priority. It can be implemented as a separate module after PK/PD and structural modules are mature. + +5. **Molecular Dynamics Simulation Prioritization Extension (Section 5)** — This is purely a downstream integration for ranking and preparing MD simulations. It depends on structural annotations and dynamic metrics, offering no direct feedback to the core model. It should be considered only after earlier extensions are in place and when there is specific interest in atomistic simulations. + +[\[1\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=,factor%20scaling%20parameter) [\[2\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=predicted%20change%20should%20be%20interpreted,not%20as%20a%20standalone%20correlation) [\[3\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=%60%60%60text%20TIME_POINTS_PROTEIN%20,phospho%20fitted%20trajectories) [\[4\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=) [\[5\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=) [\[9\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=) [\[10\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/networkmodel/INTERPRETATION.md#:~:text=%23%23%20Phosphorylation) raw.githubusercontent.com + + + +[\[6\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/kinopt/README.md#:~:text=%2A%2Akinopt%2A%2A%20provides%20an%20end,for) raw.githubusercontent.com + + + +[\[7\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/config.toml#:~:text=,120%2C%20240%2C%20480%2C%20960) [\[8\]](https://raw.githubusercontent.com/bibymaths/phoskintime/global/config.toml#:~:text=,0) raw.githubusercontent.com + + + +[\[11\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/processing/README.md#:~:text=,mapping%20files%20for%20further%20analysis) [\[12\]](https://raw.githubusercontent.com/bibymaths/phoskintime/main/processing/README.md#:~:text=,) raw.githubusercontent.com + + diff --git a/docs/assets/coverage.svg b/docs/assets/coverage.svg index 012a849..ffd257b 100644 --- a/docs/assets/coverage.svg +++ b/docs/assets/coverage.svg @@ -15,7 +15,7 @@ coverage coverage - 70% - 70% + 71% + 71% diff --git a/docs/assets/images/phoskintime_workflow.png b/docs/assets/images/phoskintime_workflow.png new file mode 100644 index 0000000000000000000000000000000000000000..f2bb2ab0f0995515aa8dae7628b4d2e9ef436b4b GIT binary patch literal 1565162 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

gZERG4@ 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 %N@nf9zp;=ylW{9N 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 j)k-(&=>) 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 S6_P7(xw*GKUmtc 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%0D_W{5FefJx9%M-2f9=W8q%&1BAHgZ4vesC00n_! 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

)UTUzh0LX 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

M)mjmXfnceE0008Bd&f<9F6&5=M3q9^ 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≻-6N_Ja*3}C~#>>)Z_XcY}91)ekT=Mw!AH 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
  • ;t(xA+WoI_=kMv>If+BA2;}D3_}qlz*$4h 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%0A1EUqCYB=LX&IpwRA_8VY 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 z

    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

    A(lb{%Y>W( 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

    3t>3rC+8Quz$IF- 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 z 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μX| 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�zFlf^Rb!p8|=_QpAOofF-43_e1&_^Nj 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 z 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�A=#J{$zAwmIPTa3Gv030b(-T62J~PSlzA06-@OIO^_9%q%$F&jTCvj*>-LI=E=FGwag~e)>5a28okcFvBSu1v5hfO2%#PXV|Adi zVt_)iH>pu^T+Q1h6yu>| z$79<gfcO%V{ZoX)@7LTMBYT&A~k=we9NmGDngmVWud#*vW{i1???*${1*BSK@oCF7o!tTO^gr5qqyH(z7GgX$ms2gjSd%EF;ipM-f(8|<98Tv?Z-g;_i@v6gSWsE2eCY z5JM`(0s!FLp!%7g|Mly?@WsJkemXgZ6o%%>rMlCZzW=BM?$VfF{Oz5RR|KJMOyc=#fL0U3v*3OeS%D zga|DH#H>uQKV55097@{c6B%?A8~ike%d>YE8PFJ(+=$$WOf!K9Ek|j#A#ufJ9|fYZ zg6uCmbrvi9V?IJsf}yojr%ip|Zaoh6v__$d^3{|KkF(tPms(A$0rjp@lm88IB z;&%?9XFz3O5JZKqde83b+|@lxSSXFhcZ*!)9l`_>U->O~;MXPEcxVlbX(HXAMqop7 zp1-Na;6&GkZp|%oj1Cj96wm)>-l?#zM!OoN^5~a+H@|eFZqlg#qNt-MrEA7m729oiKK0G^&!&UsD(^BRp;5RGt5j#T_aSc zx`99~H4ViULkK#(mA+UaWd=u%4&zb0tZn(pdTEa3ob91ZpYgd;x)=8o+325CTkA+Q~HE&%hjsARsI*4Z;B8m?q1gxQNrdGC)?mU*T|3FasyqP5acnX+0f0LxXrHUE{ZO|tH4u9BIk+XD-Ilr`5Z z4dK%;QS{}(Co8TciZN1bW79N14aHM;?ELAsy>V1mLP7EKu#R){Z~Bo4iWEUh7)c

    K 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

    0G&wDq>}H9 zA*-Y&>}_K+|LF=B+@Lv6X}$pOc;_7J{~7v89-A&ifJpnMkv(Qi=B?5>j}+H0Zg?C@q4SVqey<8h@WzublWF3DYNHk|4=!$|R8*=T~z=C;}t1R@~Fs0sx_A zO$^M$$c)4$;3bHlkS{ElH@&W)RyW1`f*FMLN6KL#z(q4B%Q;g3pcY2MQG}{!_nceyR&6#Z=0c180yhc5<+Okrb4d0G)WO?B7xA>6aawI ztcekUhzo(=Jjqv@Yl;zoO*N)4u9nHGu>b&xqa$H1fLT*}eAx>`qt)7AMS}E%0HwK9 zEcz`_3ptEH3e*I?6zwfVVu&;=&6232Ifnp|iUQB?YAXQ1LyxRhwbA7#p443Qhs%|` zCjurtJ^pkQ4$ND)2!WM?z&HE4aJ+WkdfC|}uEG+t0r`U!JVzK`4xVJ$ zrt#JI%|r+ZQn$x;5;9g0Vl3d`rr5T+`78T?q{_!YD&w9L5eZ^a6yId4lbl?EF~U}` z0Ko1-WW8#eVzo?8Njr9e8kP<1=Y0{C7gg_}W+rXje znE<7u!}|~IJFs7C@;wnnbpQ;|2aS=|%q*pp!UF_NN`v0BZ`ZB=ykpw5slWW)O}%}S za{*S>h!CiBq_iStMDWm)GFh&Mq==Y3DT!Hy5eW1>Uq^}oeCZK!U4;NBr3|DGD74Z_ zD+Clmcv4!T8_R<#iikBMODUv~6k|0;5Uel?wbq(+q;iB(NGXfOJdtK1gHZ@#wP(c1 zGC(R4$=XU=%F?hoBqaF{OuiT|NMNw*1Yb@d+9o)eW!EgCam}y&MgYVWV@W~=(}Ewn zi9rg;9nj)x5e7=|2*(weX+Nw0$D#g4<k!%7cO*Y;LrWg=_G@&qAJGA}e zba4#WjNU|&o`pmS)N8~pS>aFT9kYW-?!;tH)3JbG60_%bPG8W8rYZ`V6tr{)SAXOc zW8bapJv^u?RBR4D^5yg99@}&0ZR=jzbP$MpdfVT8Q%I24>9+QK&9?$Fc35!Oees zX8ndeT19Wua>B@H^{#(B``qdsg!+=p&Y3@J+HJQz)-tK!1yU)xx9o|mqp1x}!xRv$^#nnc6k|r747@V6jb5WK3 zBGDLRn_$fHmg|hTJv2BVHjnmiVt10w-vJSzHCJfybAG;n#2|nO1#)X^>De9oS5BWi zC+Bb6y|)sE#83~Fi~~>_nOR^+G+3?g861hih*+~$C@}Ad#nYy>7Mp~#osBTMmJxyL z^-wVwA!T4q8ZTh5^yYG2u^X@&G!;XCL?knGV{>dvUk@AH+cIJ$*t-U>; z10j%fp-{N`veypP#vXa%=?9;BroXf0zd!KqI`E(W@|UPq9SK!yF8AgCdi$Kd{yXpc z*RwCZ=o8PIGxw54J*TPK~k+z04tF3wpvcfquN4Ire9 zl{I^#oXCrkwz3XrMuf&zx}~?{$j@Dho5|A&5N749!~G+z54Rk z&+VTSDxET|qg@+NmW68RgrZ39a^(OW61qgir0jdV@pPXufo*Nj=#4^$3Dirji!of5 z__isw&RE7ZG-fba9|>{RIo2!2eh~np5W=kWVgX=QaWf-;1n>}Tku4-pB(|@K0y4d^ zz?EK$BJ;V-(d6?%Th2|G}}bGB7h~MkElXO9<#mX$})J z7D#DkA7NJH(H>FGEukzDLRe2lMQ zc0%`VZDulBORN;jT1^#3s5GLGGLR9u`l2VYFiu%keilS;50!nizZ9;O$ z>dNGm;0=Hzp)>(!#XaTp6C@;ZK`vSc$Po>;!DJ*JttbYT@h0~%#59{|m`+5BYIOyO zGS2xJva>HerPNSV6|4aT3eWfLj*7+?Br#TvMzv-ZEF=R;fy`oLG#oY=4S@pDGwVGW z#;SS@$oGUNK{G^A1OQS95OHWDQo35#0uhB20u6c-4n8(Jj0*(mdrIq}a!oKHFrhD{ z(AEf!)goe+LP~*3qd=&WuGC4OFlGM~Q7u%&)KUy~?LBbcLr*;W+@`<$`X}AJQ%^nZ zG(!$w#1U4MQV>e%5yJ^fj{ndnzj5iSF3^n9lPCm}f&JzzPjqe#OsVle15G-37r`OL6kaO>>TixSTeebe92v*yQ=x9`cx4g*bk1 zJ~~31Xkkn)>;#5%{sPyDQVmh zn&2yvwH2{^vsvjZno0#kJmvJ2-~P`3sz}x9wRIcUUvtg158d<7ZMWTa;rSP~7TW|% zO;nA>3i(27sSNIikcu4)1iP%;q!5eg=b!tjD~FZk=<|2TO{e^a5zOl^f$1W^xb2;5R^ z5yDq09IKCkBoycizo}Tt7YlyiFFa;`Yq4Xjb~K9Wk&2{{&ABGe%ahi%uv(95fgd0u zGUReOU|FqK0IVX=Y>&KYpzynT5Hl8;>tU#9?Vu4G4PI8 zb~=VP<_UwUZNe5Z49;=kYlimNC}$H$#LK~rI6x?bKp{{FVKz*+;X{$RF6LB5KooH` zBsXkIld&I`y(fG+g9E}0x=Fk(w}dybCu!o?!R~Hy)m&yU7ZI8Lv%v1-&P+hS!ulGq zggTO#Ce)1U+*se_%-Y1`K`Y&6&M_;bwZ+Y*^b6>r1;K&#eb#|4e%a2g&Ym$iI3@%%mx}$fT0sC4yyor8PQQ3w z-{f{+D0Kwy|J*r2&g-Any5y|hT{}+9=W~;%w70bv!WxlAg?#R%^G;aVpKtaGO@3Hr zki6`yDGQhO?A~*9*pQsn$RGHF5rj0}Zp4Ic# z8*%b`8O?>jj8Y2C1O%@;@2pdnozUCXTC3M3!fVeybIGCwle@aAN(m5krRVnd|M(04 zQz+#7+FNUyiqd=Silrycnttf$U@@1U+%st;jApd8e(vpWx%})iN5fD97lQocN!?Ap zHyVcR%`IPh-@7%6zV`MSu_uMndft@&|NZd$x4v$7RF68_T4qn5J~BG?%B9EkwzW|d zX`;U7mXBTj`q!R*^3dq0Cq!3!`?Q{JjI`D?rK9!w_r7!6t6mv+{*>-ct?B$_CoH`7 z^Ifeib#0KcR+_H7=)9#1=FaTxkwSz@8`4+m_4!l#zW9!}?z;HAk+BLZ>TGMBJ*A(c zDAHPp@oq{CUmL|LV>ci*5iW(?R}z6@hhXWa7|KDqyl9*c&M?7;)Cgw!0x^ztMa|x3 ztw+X?CcQ}f_Sm6Ng~oAz?Y85o%i%;3#=Vl%wY@W%bO}VjZ_@>8Kef(peetON?FMr{Szx&G{!bqU! zdAXtvt6JBJO|5<|2U^uCWvxPANCpIfI*K9&KVS5MJQJy~5=Ei!#b>Vt&FxA>VWsTn zOMb2ZD8ky9j%uEl?9-Q0f*B&E(9h*cO+t7&3RPHPA}Ix;BqF6rsi_43 z>b0?`UXj3>0AgN=(^jp0^GwDx!>Jt}VeBRP!C+713Giah}r9Nx+v=f#u z%N2?M`qQ8L+$FERgF;ig@Vu~Ik7{E88Wx^aq=lC*8S zz#vtv$PHeRWlBe!EoT}ra2Aut9A@ve49Dq5&bFE~oG@F`LIa~Ee` z*9i>7{48SbHPe%pnXn~+>03+-BBhltxucXv0f#ChFC5rAFnoBVQdUa)o>%bm?M5Z{rw38U=1+)Br+wLV)KHgVvyJ zEwc1|(`zFbW_x@jMu7q)14hIG08t{K26u&rke=yeEHeVxloKa)fgs{Zlb#1G)A4e= z4>cm2U9l3e(g29U><1UcKtP}nDpH=5&u!TD-=Fwe`M`^%j_#}9{hpO8j)@}edw%R< z2mvTOAxs738(wqX<*&aWkWh=*_oNB#0-!KKXAw`8bBZ{m8BPlI=;XNWk^s+z=bbB48daEGTCHv$~U+0SN$25-hIHLo^4o5U@6xoKs)1`3)~V z`oLp5ckDiJc>mFsi`q$M`ouzI70?=D_?(#jHJh>+itwXh84}H=)C;eQZy%LS?-m^0w_q^0m{<@d8k18NH{TNgFxk|M!@hNFz7J&AM5=>ElEI6E?3EQm{iy(kWsi7HsW?ZzF%uDlydV<=m7w& z;zR;7k_Lq|d+{WSpfXA<#Mr3zJnWm(J{-WX$7@10YYs|`FVNF@_v*6f@`%plUlfRGAXE62_=RhbB=mvw)D@Ripm(0KsdB)sM00`?*&y@C_DeVBDBd(SeYeY|K4TVyEc6XjNgf&e7 ztgt++awRc;aZlW`qH3AhF3!l1G^I6z&1``En2@lMOOlT!>(RI*+p?&0Lng%Qwvr~D zteG$d%Dgc<#Im))oV^>1(z?5lYin+L zX7Aqarq&|nTMPLh=T)mUDRAxXy)_k%MOq?oqzOQ4V&Eu@y4%}|xj<>1lcFieA?6SS z3J@TGfk*?BJ=ZA7NyM3~rcx6Fgj(0?;Yhu{Z~ws}im6>aT2rW$(vfDJm$DE@&l5EQ z6{?&N&26p4VpEJH5dct_Og$1>FG2taNSHwg(D6vEe~`>@tb=X!Y^*FD44*|HV9P*~ zyEAbLyRy>WY;=v)EetWSfdv2&QD1xetV!MVNLTB14KTU0Yi{qP8bQ5Y2Lw`7D&$U_ zGlv1Hnv~KA3?ycCcFykXWPpm&^(d-`%J;ovXHI8h-Wb9#tc6M-`o3H^Z8`(g>LC+J zMAkYY-BT=1U${^JD1fnAt*elKXeP1q`Hq}EA0Ggo|MVd(ptcOug zbMur%3(fdP>tT0uOJ7S%1Ta<)nSl_s*3HHIxhEW3(|W907jZQ`0`TxywGjA=W=u2L zbt0-%YnsW_H)nwyr0Cg^xTNybnRQq063PmvB7^~w?Pt-7NCJLiJ1~J0mx^1)rX`PJ z+fpO`1c;Nc1{NSru)$P=O~A&t2&wySgjEQS>Q%3~r}K=<_Uzw$^zh*zClEy>W&1H_ z=BF>=C`9Q43WgN(Q*wX8mS9e^9X|TwU;H)*g15f;P49i*2biL$9u<7={PSP= zwJ#36{w-JDde6Pb1CIqpA zC+0%?B;e@K{=@aK-qF$4)Y1hIQgw_;gO|@YHG!@jKCl;nTU$$o)=sXCm*R4x>~m9LZ=)X2VCMZ)tK0nme!#|ZLm&C z%t&NiH?+i#8@0@2NKcmE?N$saeoTbJ0bzg$YxsB632F7C?Zg5Sk z1$)W*<}_g8l*ZXd#uanefH;!Y9Ecic{}MaI?saY#?K8&t44Azrk@eIYNUU0VxeLeR zFUC6~6E-gegb_CtV8yXh?|JC?U3(86I@;e}%K5%bMiUb;!DJSYP`s0RtQF%z26IwG zVoy1FCxL;8g$FZx+eYV4-@a}4x<1; z5s=N9)g0#rz}D{Bc(FECC$6F}tMXJ^DUUurv;CzfpI^Ok$4mQ;?i;QQ*TSlfG$VS_ zZz(pn6`N;Ip1ETFaVIZY-rv#zz++X#jKl=UIZsF-0D+h_fg&bm0m5-k8r=rRZE?AQ z4Ia$UDKU?kN~7dA!{Kp|%SnHw_R`LTEuu*5a~xg*xay< zA;m~G0zA%7%9vXSwqef3|tF|?UxDLCDDPbBjMn5>(M5L z*&Sqtew?LzqD9;!f;CnD;pI;1f6$Qea~R^qCD2F`fbps-!=mgkh565HgSFe8X%&p-u8};_R+jz1f1B37)YO!lvvA(WKJ?-F3+GoVV+FrR zpl`hC=Xc(9*Us%b@`c=zWlP_A)jO7*uw*nG&ie%^;rbh{yZ!dNcJJC%%oncuuXi5U ze*geL+U*Nt4olDZX<$;AKmr_@!^VrDK`*oY)vmv?C3>0XI9kiHIio-Z03oCh@k%cS zkV2wa0VYLKSC5E9B&Dd=Yhxp$eh>)X%jfgH=PN~a193YLV|kP8iZh~ycy}rfZZ|W- z%-WBJ0;N=`rc#cMhis7#nxJF6k&I&~(uO9~LT)nL`Pp&DCem^fkSvMKrXVOY6ikK- zfDqO-X$ApO3L9%>W(YM`#v*1EAed1|sT7S4M!*b$L9q0UML-1fJwIQRD8<-F7%GK` zD8TbPL}4^fWmEx@=L;bu*y0i?K@(KRB28wkF-T8%5?Pb+IslI=i9(MM{Yu`Le+|j)wHQ^w+j*=VK-aa=&1b(%w0mF z3DIuGE6?80h@4>jXL}{t_}@g&aK3YUWo;2>uXcY1mk-SlE$g9U+7JbRIW3{lVK#Sb z4gx%L;i7+Uda+QXg$Pu zemD?9NRetu=kNGJ5U`LFlgVaGFl|OSGVK^Dr1m0pga6-{)Om2yN<*I#Iy-sf2K>sI zI~*@4`HClOGuysEBu!z|apG(Jj%np>>xHfgUwX}xnr5FQTP9OjMHv7v0x`#>ZUE*q zV{3RAOcKb#NdqJpfPplS0w(h#FPZ=W002ouK~!Wi7lHMjfC)&)&@}7iI++hhv=6w| zPDwZ~jZw$9#BN!PsEz4F0F%vRkaF8g&u`kWY3kJe4}b98ETB9zxANcT;DSfYa#etL*|Lqb?(OSdICt*V?|ZM%__;5BX>efwcdox~`qU{PalV5S+#kbye>%I5T&7GFMsK)9*9?*x$>*u{N~L!-+beZKmYvaKGoXX ze8UfZ^2F+A5XBQuJ^R)x{;RjM<+|&yd;Y~2zx}`0UHO(bzx(~~QVfM4zk1c9zx>S~ zo_c!q=cvokgj?e_nPQbR@-!PM@HuD z%3xzKVvU8V5Ka6Xi^$`dc88D2IxVmsEjkoUSIs-!$x_C&>d3HZNB{z2sPt>kS#bZO z&)@gh*5_Z?HKnVitGzW0BS;i~+y`K06lOJO8~~A0pp+;CD<-9gnAx7($LvJ;&5`9I zs;PWFXfG9;@`b$zD?9fbozvH>6q#&uL&>gi+zO*(1ezU*;votIle$Aetd-Jaispp* zP9UPt?$j_Kky1)X=x8l$AK3fPRd+wQX4U?I{b3YFk*=$dhysxlzE_O~H5~M1@a)db z|62F>u~Q#8=lIjkUv@@MOVO4xz?kBSikQiho)9t@AZVzCWNVNOF-+1VRkD`EZhbXl zB7x32LqlcZ_=%SF(IGo0t5yNPz^aT8TjXM$nKa^>JU_O-hOPo!jzWgG?jtEVG=ds; z0n;d193vx0Vuiq_tj;Xbv}b~V>t3f}#iYYlRHRchMseXNry2OTE|HU)jBGd|ek|8{ z%GBQXz4LVlAONZnj8?Ri0E`SmK%8lfw}>IADvlHX7!Q#t3C*#!ak1pb`+3@m6I;S& z6L{HaN&A?JX54wJA`zV196iC#ykue2IL(uNNtCFK{T3 z(QOFiBBYob>~rF`B59hzskV+|#lXM<1OW*^%^E>4YbF-bWav3w@JjI*iCGX3q9&y^ zv4(iFUDg0ZOdm!Gb^z`<0bad_9vFl&=JP_8x_rL!=Jzah4Hmv{b z=e~H??RVw!!Lk)gcJJB$(;xnH`MGEIKK96}Jv;XN?$D)Qc>o|_ zAyAMoVhsQSL|g-A%vZeL)3RR{k(=B}#<9o>zZEx#nu(KVq5uM8CxtYN zS&i3coHryy!M5UznWQJHm5RswmN&lcw9`+0@R3LVaoe4q=eM-9hLN5?{L@eI)-jC2 zDt_BT>j7m#mZHI#%3!*50I~8(AfScuad|EpX^%^SMC^MDNK|5`N#JC9z;!P;_O}~# z3#R?dbk!kDYBJeb*3^J@lBJG`D`HYQCL~8XUISsQo7upT2<-CQco8x%01^s7v-dL# zU;1O^QSwBt-~~A!P&ivvo9)3_pa2xiK*VX508t7l0`Oz{FaU785rEnDTOfcZfq_}a zmk8e!w#3Oq;R#_(3tErOj}uA4)MyG6IT4f90S;1vu(K)rkO0i+D4o-Jb+DRf+0%07)T_8MK(B52vJk|v>7v3Oq;%W zV4&323ZYWw5h#S905FPleEOk4DaCNPeCmSvr_GtgL^=t&r2~&`7opjzie(}iW^KGD z|FG)m)mwKIo0^1x^5{rjijL+|-uFF5)Bu{|_$;6%1`0I^1Y#93>Ey`pxIse|WRXt1 zsgyTbIQA0aiVw3M$MOU^1a|5(n8DdPE~Y|euCw$)=LfWPRFJV-%zCqz5vo;bdlv zw^5FtD-b;|R$K8jS-z6e^XyPHfC(LM#irclyZisw== z#0wu%0EplMa|6f-Y`8R;dq}$LfcTVR7DSrS;RM8V>1ymv1IZnfoW4!W9k{<{EPQ&4 z9Sx+DV}46k7G=9(`Yn-F9sFF&!dJ8`JR2wifdDyRP1R9E1|fk606`exHVz5LCY0?A zv)TO>tf?lG_GhyMAU>$r)pKB#IAl6&JBD`dIjK3y>Q=C(+EtL8UPnMkBIZcbb5gK+ z?RwIxueWc`oH^yOQ5lpF(aRyL8V14HXRLf`^_rKqY)8Zww{E@To(CR(`q|;5Lz5@> zcK1$N_2imWPd>9_$DSL1`ordymU^VF`SLZ_-SFce5GS5=;-LcrKl<5Ck3Y5gFMs&; zoJEUw@7sIJZMXY=@Y_G%+*HW-Pn-P0)*X*MwR->lgTMXtO>OP1QC&qOi5V#hg5s`i zTR;BsPdxVcQ&T4QPn|Y-tFoxm%e+$4?8CXJ_{8md_S}5i9g6fXe*eev@W_l=(|7FI`}pc-cJA8wn?K#6INJ35`f{zp z0EhSOtJSMJ=S&CiRz3FQeGfeR>WeNu{}pGI%Om>_9MHtYf*;jtVOY%P@@t=6|HLzE zmo8lzg;Z#6z2~2|e)db(tXa3Qzqfbk35y?p;)y%%`B$kacjY_ZqbdialrCorm*10c zkUe~m8PZZO2iBq8Q&89)3sV^6xONDLLV%6vV2o4HR*+!Qu*Cok5@JeMoE2HnD0dC= zl=TG>v9U>8ADtM8m(>!Dts??}m*lV={pQBx+(~+wmfSA7I%s^($hMPGz>LvRgRUqy zJT++>osZ6BXI}&)z>{LMqG$Isox5Vz)9d!{+IMuM7WVp5D=j>W225)N!t;bDNRyNj zfHcw3;mX0`v0A0x+1fOzvn|QDnFyqxxn2ajw7YRP&1H_(kf0MV5Oo$&hr9!_p=ZG>A_pqZe2?NMZeI|+}=_w z_4iEbYHlmnszc?Ge7xK}^ImothYS##~^#C9J|S`isU}*JQOe0svAxelb?jqfCfQiijZZOF#)=j-H5# zlv@AzJWXgIk4XM77^p0yG+`SP$rCAkGMa8;?d3+&t<_CGxKjZWd=W>a$F5d#r1uqpEe0uwRGOh|HSnZ+MHL$7qk=?G3$i;jXZ-p*NIM#d14v}UEQy7H|b{n&@QySvUg>$K@p zCg1eiKOQ-Hw7sK)G;1P}I$ep2A#9F3K9b38Hw6^qDkEZTl=x~+upwps)D)nIW9bOS zYZgLEiBd=*n9wL4L^kWzgoTq?Kr#-4#C}~vWrq8AB0nihfW$(%qa1&e`G=ATVq3AF zRM^IGv9x^@W(P?CVb7F7lmbY@gB#ahPOa z;6xE(RNydYqWdSRu5k%8kpxYMOvk?(yjV#4lKIu`viZt+U}oV>Bj|~x%eFj0w^C=< zTwsU?LI`0~(Po{1-FS)!1b_x$WQd=UV*=7Lh8Af=E} z0y8mtLP#kkBAXRoZ0SucRV>;z^ORlOX= zxv^nz6;=w<;{0w(aI|WH669j;WwVh$yyn9?w(&qr)rQ?fCh_ec4j@}#!Es*2K0VcC zY^V|Eo*5usfN9GzY$RG(ljK^KqzSZpe`dng<_C`Vu`vpR*#0t3V8Lcs&?;YpPEDjV z1(%6d8m~sv3PsnJj(d)4G3;ZVfU&8e;FwL>39BV^!jzIpr#NZai33gmf*o4NE@q~Z zG9wsCVHx7M3sPH>WVrx{1OSIMU8|z>QA%J0t}$yXbjT>|3e`9Tk4dEp+9gV0^?A&1 zWC~Hi{-4R&O(QPa5FmtI&tZ3vn@H~^I=<0DrtdK&ku}K-3>0^ph=l+ZMSJ({2Y{C5 zX0w>gFpvO}o+mtSa(^EHRH}6$#N??{J zYj3;#@^@VQ$lbSHcf*e+^>qL87e71xge6Cg41W64pSt7DyKlVlXW#hF_Yg%#N5|mM z@cCz-^YKr9qPxFm=g#dP`oM>8zw5qrYo0s(yz_{ZCMHHwx~Zl8frlS_>gm;UX3zZ7 zpZ?H2sdvxL?JqpPVd>K2ga{sa;O?(~`}(2bk*|K?(-*wzHEkX3J6?Ke_0vyGn=z}Y zrKP{WzgigsA;HVtecM02_k$lVTe|c+*MDdJg84hP?)>`Kuf6?_JC^?DcVE8t_@+Wr ze_!uQTemKnKkq&7x%z}<%Xe+v`jL-)^4CqMJ? z6?~9>As=|2H!?gjcj2)=`Pt8Z`ja1i_Vd?Vc>cNn^O?^S+d8I9nJR$H5fd_B z*u7)d^*8)r&AN?myZo{bedMEa=gnF3^b`O3*ZuS6&H)_?bLzG0sAXhqoR*xp26ZAx ziV!a>G3-sQnjFtg*_NEuV2#$c!G2?UOQN%4CH%5Iv(e@MUtj;}N)N;Y7a*9kh>WI8 zYT-;uXrh6$^Um(%lqiG*g*okKV4th89pKPl`jYucv{l-Q(en@&{Md6=3CzAHz;M!% zS^XW)Z9X_QFdEJUnF~Bc%8Rq6NJM_#KQda`vg<$;>5kT>ASZn<*u8J?`R)6wmFfu# zW^{J8nR5p?Ug;j&vE;-U%`7Dl(Ba|g=xA+LUu#E4vvx|_#!Z}2xrq`@*0$G@PyyoR6;}@)`v#xA3pzru+GwjCW&$4B-NbFIDu9B&NPfSC&q>( zJKQ0FIfE5|37}Z;b3Rn+5Y`E;7&9_bTxAiL+amy*&D|2_V7C``g3&Ra*4C!TyAfq; zP5GRc&p|DOFd_qUZ@|S&21%fa9zyxR6dD10z}LClg}0EOrqo_Ae3QeTk$H z2!a{%IWFb|G1Nl_WHFidb>aw)ib4ucO5gX}+FH9idKghDrIpF7BOsHe*SzM^Pk-#Q00baLt0TYv)gOk2 zMur9l`?{vim^mGoJkxv?SJ2HHL5j@ZP_-8(T&e`V!sCQiPwjX@&$43~x z_Vus4;Wcm4P(5bR{F`q4)e9S+KX~v^sOo?H%PsX<_2Nq}x#EhqBM6v0^?e_B$CFP! z`Q#H%*TU*U4?jFIQhxi}-gfmn-UFZ+__Lq=^qsfevwrPbX+lAEm6U_Yv+QXlDvKH# zFU$a0PQVK!ZrZr(F!K$@|FfDqD<-xYBQ9r(9isSl1Rx^mdBa2HX?;CcUG=u^?yduS z_VoAledbdin=@zDb>I8R=55=%ySjz%E2V5!Tv%7mt@cmeq~%0btehb`hmI$8DpoCI z9i!AEHRqi%n2p{=@-l7%o6~yZwChAl$~4T@BWgr=j)#`i=vgh1MULa>HSrgz@8P<6 z?6}8?Qxe~AyFj*7!)W-pvLdeW5P&Ecp|ihmkTtbbG2HHKYr zNX}Wki^f)&l3*KRKpTrdj)`hF<^q$)N~|6OBO{wbq}?e*yLW~4f2}oVN){ln*`yN? z;**WYLVl6bEMX7GKERoLTWXYWCt_+z?Odf@y{VpDw@KOyxs0Wjf8PQSGL2X@!V_|lj{F;~SAx)|e91Q6P+n=@pC zm@eomj+_mQFDcfS3tpZe_o@;>y!i#lTlXG*YQv6lxgrEHV=nN6AXkql zpUah6no$THDU6GEjUkR*WfRl@*3Heqfup0Fx9mtNU(Z#@(gB% zcypI{BF&ypo)FA%+r3YI39 z)~Yw&^{1O3y@fbxD>m0E;R&-AuULHimVKLnR8L!HA;^zahR4FOrd-pp)8@?Vo!Zel z>E9dIS9G;f3yW=~9lH+hA3Tf*lL~Fkg(lDU%hg&P^hm9G@bKZ0DRqDRSW+aBK#{DG zi!sW|cu&Qx{i|TPurz2$}%|00Ek{L(GQ`4-s=~Yb%)q5^z$76FX-D5WpNe zn2^bAp34l<117%b{#6?`JpbC)Tsn2iq)NzAU=~ZbYgv;RY$MilRYLY{gGzW=4bk{5 zV-|(RAUDM?;1mL4OzoG~S@ArZtd6kD-T@GV5b56W1VE5%`AM@4{d(kSy#3eJI3nexQEFEV(jo*=w>FyEII&Z z-c6bk(sko#L=bIl3Zf98<8hl)STqp;sCs>LXqcIEdH>w=&Rluw$!~x26|?8e0DxRB zh*Z?m(>-;{lu%Xn5A2!NGdqkz^914Hz5{zVZ{9j*)~r)ko*1d};lX``diJb2D_5R$ z^WSdYwR_L}`SS^=si}DK$tNR-!Lh?l`O+W%@~3OQcx`7_2Lbs~67j{CUijT_exD)@ z5Eo|wuqF)v9o^kbyl-%4S6g>3$Pp1oL`o~F4jerK2wLf*14G!3dk*Y5w0B_E{JG0d zS~5IxaI}83qcvK%V9}iUv$njn^YFo=a-k%kTo5c-dIGaPIJmb|DiUd>$&+4xe{ZDf zqxB=m*woxKI50SO_Kb3QXs9+&lr3%TEt-gl>#F+VOPhrktXs40^{;<}ilSUT7%q<< zIdU|LqLIqb;UhGu>%SVMIv0tnZQx4g(eWZ@120RoWTgf|#hh#5c;Q zE2qclNe{^g65s{nE_R&|GXn&G$@%W7A|_kf%fM`^p3P~xCKzWDeT*0{)(6cjK}sNH z_9Kor-*Ws@Oi##20;LvNTh>dWUN}CH0s?Ht2hmQ8*#V0o-m=5iYS^Q&Fl{OsW3uz} zc$y-ECMK;JP)HQgR#Xr&nvJq;Wn!{N5`oYKwVAQ!J#V`nElOFwA%V&d0-0`!?n zY>0t@IF4U~E4TJybbwYGS7orc!j30h4gPYt3A1l7u{I4?vmr~Ii9%wC%jyxhR;!&p zZ(b>%yZ`wYcN{sQ6#Ib(nn7R`MMNqu{L|*ndfoC9CN&kuYISK!`vDv{1_()|g?)V1 z6N?updtT1>WZ+2w0{nnjppXdpAn-h2dK~yt3gHKS-t)B9o3Jq|tcj7q1N6Y| z>40dq&Lq24GbECSajaf|*=qp7#u0Ixx<<%wiaT@I5c`=x@J$@Zjqzm`qY$$u#$+>0 z0I-QQvT)paZu&OSQOF>GBc(O7*`0u56zL+gxB_1Yv)c-qAew003?wr|gG_CR3X|!> zM0Y~GbSUYt{jNdKlF0!kG7(Y_CC7A#s}&K5fh}9aLgFV%E^Ye|#ksfEW`!nHf&DyEP`ht)&?ehX#kDdNn-*3K;;1xl*kHU_PHW ztD+HM=ImLyVsm}$2q_&jb)0j~ncukXdxs7ms#JzIZQde;eE5-7Z@BEWf;b3rciY z=d4+`@hxw?^5R#Wck+spPh7rY#@w0Ayl?+L6{)k&J|ifUqOqf-N#=@-B%}mj5I_um z5CFiA9Xk>6H^2G)zaM%;N1>MskomyDgL#Q#V`V?^6{*(Nme$r*t;Yrr>}v0wT`U$6 zxmK%FRAUj1j*bGr;J|=V!=s~v?Zx&;MPT;CAq7NZqr(U=Ffe%J;K4#`lOG5(zfyPr zc=+&v@>q4rlEqVJOjoKlHZw@FW`Hj$}_$-l=@j~d@1*zRyq5F{nuJXWB?(s8d66|yzh!rx9mBxY5U&C zTZ(m6pWfYC2s|KSA<8wqb6NE1>}vJ~hC|_X8*}c=DzuoQ_eYcNy&pSq9c{+&+q=rEsy=9xusYcs)!oD?u?5r zIrZWxJ)J+j>$h8XZ5b_(dQCX0YdV0DsH%wuMn)?kopZ{WzK5H(Y|Xb6TSR+J);%px zoVRFlb2B0iSF78P9D3}9O>OPL8H3_?40pA9VE^GN;jAMm$vNr+O^;5>+bsO=RQ>|1=TuvLc~YP zLR=%4;21=^#}a~pMv5RW@W7$NU;XOWx4yXPtTWGdbq7Q&m5oi9ECOX!1sN`xXz9lG()9Ysg^5k?ahUfuXMeoxlN*wK6i9>)N1u= zwPwnb7`YaXF>~Mt2+-NtdCF-ki^aTB3K(j&u&1XF0OBJ_0U*(y0JX3V2tiQrr5A-Y zFer?{6Ta^SzyLx>Kk&RZ0qR4X;l^8zkbs>7Nz6OGmC(i1^YAgx0k0f5#_T2(7`V5nCs>(;JkNm9yu zP&oO-<=wqqrF;`;VkYSeVwKAU0)^J9e{vt#NGRC&gJa|zmF2h+n0(=~w_TWIuW^Fn zwlPjTTu9daH24WtZ$_=)IWE+zwJITcVA8G#`Z&y+MkHc%t%-*No zo|}HtdoK`3LJ1Hc^eVjwQdLAzRK$W^DfWs2N)u6#j)a~B2t5!2p(KR#cI#=o&8+8- z*|W>J7r&q1>)B%NIcK*iYu0+NI$=CMXUJF_EM-t$+<<}gzfWUW=IXT88@WQ`q&6Zz zBsI{(HOUaEKmmZT7&4Gb5fL!PMfhl?6okQofEY#+Fm9ZhN?(ACh5b=cLMZfaASei3 zNfd?lCdEA(poYZ2Y9V~7i*!}e|LoXkRaD>w(n6p>_VsjkSDdO7*g`mt*V)^vNC_bX=X*OlD~_wom~@v) zySjV)d|q#SzrCxwr{+o(7w!NPM9&$R8k@RltX?bWM>Yx4G7}TAGQF$;S(19RH#kB* zal#)&wf_X7EtmxGbpVb=CfdCdh4I$0p#)K*-cb{=kj-$!Y7hj97%~E43gd;2U6ru=NV%IN($VaUI5;FkK?3R{@?+CkYV&e2tk66E1&&i=g0xR5+N5786sRzc! zgNRZ}BFT}Ff`An0-NKXOJ`gL82R&ZgiR+R!?$93;_RY{~0w|`Rj}d?VR5PIF8!5S- zxGqZjWl^&dmJEaEBD4(%3A3y|shgdQg-d)eE+zs%NdU+Yh$v7*gjRuPn*ad7mF1n@ z_D{Ud9m;b+`VdG2#ViXmMc&XR8r!YLL0A|Hz?D~_N}q-X2$D0#ks*`FKmh~Bbn)hX zj_ZM(kQDLF8UJ(XI8Wg40CklR2+BoW!WA8oXR z7(93|00?0NFiA290?W>z&4FV!o8z3huIE*&m2#B{%VO}!N1sS?g|Gy(4q3c-M8{Ar zvYc^5BvQWX7n`}A$qB)|z#{_hh6!Q-Zr~GWQ<{G zmS<>XcqR{EYa^}Rr40g!h{a+)Yje(+m1`h{Znb6$Vw`KuJtc7C1(4A0%qcRSyM(qB zlQ+bCEh&M)ERZx=5yV!iPeo!TGNr!-KlxxtvjX$1|3{GQ|9YTdk^ir2MRK7hTd5Ll ziXG9PvKgyhI58xvA9hHMX;SB|>rb6@3qyJb=s>y^y0^v(q@_d%F$jS&0?ReI|CILc zeesCz{qfmXU;l8&uI@?WM~)iY+K>~(*_NHX>)!cr*UsHX9X9LugT^%#GXP9jY{i?K zZ@GU>Ur&`GS~mAQPic=85CU<*N;S8yse$EBJ?gk44>;74nZWfGNuJ|e2*wy# z1eRi4B4b;-I^Wy2c}d5JA%$YOt!!noe3Z4Nb7ynDaKzj>EsQA%$e`k@gC|ZUf-%E} zJ6>|@>j)cCl!Tk4U={Bz5M7^|L;{HNf)$0yBU%mOD4D4p%@ID{@ZnppuiCuz434@A zvkJ@c0%#v1OBfr_WD@A)V=}3H+RSTmghPcjlH*D8Cas3*D*B{s1{*hi{K~3_=gpfB z>I7i{VZab2u>iONK&4ADnG(XGY)pgVREWAJ*@*B%fEw=lZG>yIEHK(em4V**NB|Il zA`Fmn7It;+dFZ}-rcR#pm9JgdfR>U{@2I53A#!6x1R#vJ7S}wM02N6jzUh-~Yu;GB zXyM`s<41Zj5R4cor7t(lR;IpQazbNARyv|3(SvxY8oU_uj1YsS1}Anfhl~U3i6_BG z(rhVyTLKlPnY3ZIEF2UD43NcvZJ~}1W;fILrC^98VrjuF3V~j-7imSzFi^knsxB5+V( zX9PeL38RZMLE)50m#o7fhU8dS0b83k z;+*EB=!Y=uBr+kPah2BvKO~k<9KVhTdcPxmr3$}=Tw6g@lwHSLpj1I2pRHD%-~HwG zk2i1m*4M9^HG5XMT zP0Rbqj_6~Q{9=BMZC6n|1xcy3In;b!DI(6o&{$-Q*%=EFGg)C-A{t9YT7Cc-tVar5 zC!m0Y5XuB10|HY3XmYCnlK;e!bFoSlsa4TdWgB5=`;dK0Hk80#cT!= zz$E0#fMfs+kqbZ;dRderV8D1749Eb87!UVJ0Fod>dP-`mwzd#}&e77g6V1~7a%EI=#9@;ER4Nm@l^K@{W6_F0zk&3QX`s+J>_DdkQWS9&O)NBWpRM9 zt<95L8+!}ck&T6dEd~{GV+XYaKumA}EE70Gni@IhM8JTCG!{!vOH(!*C`AAQf`Tmq zr9@c0F=i}`>3x71gta!q5)p<>Q#==l~be@HMBLQ;i^r`uLuCu%AvB#b|`?DAI zb#7JCBgQgKgSPM3y!`2v!1#iF=L3ZM0PWtpR|w(NBn4ikA=lZ{hlrM)ZD?*ToMN+1QZhR#r(bd^=-dA!v|Fd#n`!C{&V>Gy_1sTRZC5)8@>X z_u6Z(yz%Cm=bwA=$>(1v^?hf*{pTZbBKqK?O@J&2qzoK8+n8%?RUi>vm@s@AsFZJR&f3Vp2_24gb)Q{RE-_vkxQj5FZ2&;b! zx9?y`im+Pqk66%=%^valyI**+dZ!Q`)h_JFCQ8loq( zHZ|P;_}lMo+_rIiM?P;g6*Ca-KBjD2^w!*UAMMz&vnQ9c6sWzOrCocvZRTHk+WuFa zx3D?Sd#lnGOc~%}niWw*7<+3%#)uiK2g6W~Ap;_i0W6p?dclm*`T;!^Z}poW-1F#* z%U^iylbw5heaA!VKG=B9Nrz^$L5s+Ae!OSWm`N9&bk@vqlRnRxPL9OZ(to)$n=H|v?Pr0(Qr|YG4?<^ia*>eI*a64m79WfjM%C6MO z6^VJmehVjFZ4m9XpiM+9N#y`W1}P%X51sjeR7wUM6*46RAp(~`K)HOL^PDAY0+2Ew zr33>mIOj}bV*Q^|W~WNcSQyt-sdRNVMS+y06h}ZrCb(c65s)a53IK#arBh=_0Vt-o zj|T<-*{sb)ix3&5KuYQRJ~AW}##Dv~zzL*MzLb&ej|&lHgN8F6tx=`*AOH$&CrV0b z3=j+%=TT+=kfcB<&KV*qCABV#j0w*5Wn74sww8v*W+0GCdae%yOmHotnJ!8uB_aqB zMpj{1%>xw>MfA3!}hb#EC7H6 zfs_ro*0q~g-?RMYsw`V}#%5M;&z>P|BTrrWxnZrNe9vJh04R>V2JN#ay-Nktt2!){ z#nark-Yggntr28swE>g?08~m9DV@G*$#nvzcVEnKseG-=htbOfdh?0UA_IU3 z(hE994WBe+{Du!VJ^k#;>67P;8a|PM{q%E>KmXjyj*bx%Cya9(SB2hM0)RkD&OmU> z;w&`n5J!f}54as#1~i;iN(E8^07(U)q*OAD{s91Ezcpj6?OUTpbaadxy=U9b|32~5 zg=b$>EHnaGk3Rmd58nHrWl-ysN#g^lgwR>s0HBCS5lNyjzJ^F!8>I?gqyv()j?b6? zAm4W^Zcmyxe$6Ydy|wn8?|*lk;F&t=>gX691oF{GAHU?HOWRwA0KmH+zW4m|D*!-P zR%9(Ocj%ym}5iNwa2BioIE!*NcI1ZVPkmHuj+7@SmGXWM5 zK%j5sOqmoV0v(jBl#<#kSMxkjtg$g)tp&d8Tb77qxe0HJm}TlP?5j@CzzFK~>j^*< z)D=sQRN8O4+r&BK8|^(?%OAb91 z##X0CfD%fxj>t;Ho{^F7fZB6ODxh3J?D(Yg+ym=Ad}p&Soii>yWa8`*@4vlcNJsOa z!G*w6DY2!ZfHi_p^0JulqQ=+HMRL&N0UwC?{twrnDO54=gq!jT;cJr*`!thYtlaj~ zQ)A7C4M<>V62kb`hyy7-;iM20gu{=C#zpg{X+wn)rl(r9g~(Y}!Lk?&%Wp`fsx=3I zbgUdAFwzELt-evJ!)D^^V{8xzKoEWP*kxtM(LH2D46vhpup{NNd9$aF8Yw}wHa6xM zTRL;v%uyo)3T?Tr?+t5dLxyE9u$Z{yu!F0f&qJ+IDWbv6&00}4gJy_RwQnwr>6GDJRSr zIlR|#EnST#vb!anqzM8H0UjlSJj}?1&(~qDVP`46I}G~MyptgiGL{j1<=S^2e)5@p z=FdL!&?Pbm@tZbfGDK3Un6b(MJ@e|CO}lp5HXqqO_>g%sZGpbFUL=o!STBZ!LbMi^ zu2rA779d_9^;b~8r8yuMNjD@B51)v62@x&FH(!0ycZ$DjG|FXC9V^!|MfS4^%WEtZMI3Y*{6i8L=k)7SNX+1!Y z$yxcfp@q>?vt#Bq?)Mq1p&9H(rFu9B09u^xqqQ@!Kg=rp(`eKL7;ay*-`R|NN#cn?9L2W9AV@9!eyo9{{NJ@2>y& zqxEAaOaTC;{5$UYMnGWtpRDllwqdP{uxcZeBUwHA%v(7PUBuKX!NEZxO zW?cIZwD*K`q+1a9db=Bvk}fj9$6RCfG>W(}Rtam3TBH@^J# zmQ6c)yGsr-Y#d#fHg@`XCoPyds-d^!`cf%Lz;M{0!U;=ftiSo`r=EOa&#tjkCJt*U z~*= zzq{_eMf)#4VAekCKVH9kZ`Z6TLpX8*0l);~hzyCL0`14Hcs1mVbHO=pZ)qMeq}B0) zuF>v>xAr`@;k}W=hK+4(@tnZ%RmqWnAUNj?6{I{MsWJ}g1(CH`Ai5N$-_umF$m3;3_uYoDYG_a zt#JEYUrNuDj5EfVRAAf8;yfUbQs&JTy?&q^Nen_HuSOrQhLV!A) z5D|Rpqq!>vC9$y{LxoQz@eZ2uY$0?ZbFKc0kwETuVEXkT7Bu&UDmWqlF;htfQ+GtY zGVmrcswd5o$(Hs%(h`G!&<}#fe9Ok2>u!Ja58ai$nS54os8vfjkvrqiOXrPS-fNlaM_3IJM&pM)1XA@bLWmy6_GA?Xe=qkYk zicrgGg#?0e#yAm>lB5&>3MMSevMt;7-0@?^pL)vi-~0AYe{s{Va&~6k?0rAnu>QuI zez|++&Qnf5dD6H^d%O2C#yH~|HV5Pj5?)ZNcuJSjVZcElB5Sf607wWypcE*nBu8cm zq5Y6jY6BV*LU6`)&jja|u(SzAl0SOns7t?a!MDG9-Oqmbb3ip=)Wi=y`tbUn{laye z6HYy0>cr{QN+p-gGRC|>0w77L8G$Vr7d$NLLE1WwoQJ#CA|Yce!!03%3>0VVtg}vi z?2*SF{m;Xfec|(`opQQm;RhSmzxvYa2QFE7{y7&fS#m)8&_OS)c=775f9;&J&I>&6 zCqMt$#tk0{AsF&7WY#R5m>UitGX5up)&EX$U;{*QG=VVsVTk@xJsEQll~V*speqpR zU4a#V3GM~}9ewEgfe?Je(BbPo*!Y!iUAJlT*2^xvsBKVNcXxL#n>qF56UUDmd&5n? zePsDFxm+%n&G=rRF?$M!NBa#L`5vK%I4mGyNnt4;B4gjxEJZ4n%jJs2LLjA5fEdPQ zGR_$(Lg*@0%T*#%F_Q=}t2K+4;t{~)^<>ta zAz)3t367l{Pu=H4UDJeBG^7Pgc(Gy>oqBrGUlW1w_$r9C6(iWlTxx1P>Nc`4lsq)- z8*pd5%Mp)3WSsj-d9Dkg=tk{m6uPKcxLD)324q0QQo7qfN|T;Dr4&b)K72S&pRGw* z^Mm&0rjC{t1yGei&Gm-1v~&z=j~FX5bOPzRo>Gc)K55u6h6tpqKoCQ80^jum0AQTy z2zm%@a2RH?0x}LV9#xFiVV&lZ80R=KKod(EI%sngA%w}RjG4|xmndZkQ9*e4nN^Sd z>){DgCLA|=YCy!10}!J`&I*OeuqqLYr}srwpp;acu}ZD>jDSq~Xv#vSwWQHiE)WJPbIZzcxprT==WEgC$e5aYTnL}gsNzSubj4ExM!{npl zz}LjOOgufJ93vhQ+%NsakXlSwZt7;E^lGM+V#}suQQi=Q>|7~HXf?ExESKK6uXptW zrMI6BI(Ku-iENfNwlU6;D{Va+(yMR0 zy=Lv(7hZVDWtU$#a`f0zZ{OpOKYr&w{?*pn{Jm?w);?sAlAe?j8Q-;Y$LB7-^lMjN zoi7xgTK@RG|GvMiwduTb&IFJbf9`_EpLpuF+wREQxnqt$!Lr!8w_acQ+^R2Je!-HX zKLY@aF_Hn}0AZ0nWeF~XrAQHR1;Pg)V5Gc;#-_XfcFXU6|CdDz7c4sXpiI8utv6rW zv1|9Zkt4X3JO8t1{pZ1l-dq3P)mMMxoU_hsY-w8a#v7|wt^U<-ZWujgv}ProDFC?a zk_%V8xbk;@xVfddanXT?DCw+w>z&oBU%vRWXDvJVOd!TMXG-V2>M#`!K$d0c#0LON zVW1SPeDOsD>AUV(=bg`lu!LaR!UzD0kO?jEx1+_ERu5eocT+ZEV}dF2fzP= zA9t5a!-oxD`P{QFtbXP5mwoPtWk&~YCugXPtcbBpg4QwiJ{fjMF|miNLZ41~F{0-r zwJy@Z-4rf`c$t0*UhbDS8y(67)hE_%YR$&RuEY@v=sLck8?R46nrKrhVaM+|Qq@O}jfL!p!Fd7DQH{I;h2cfWK>TU*0Tx7}N_#D_adKl}6j*IjYmH!r!;@!V}Y zxB0$oC>AZtLgdIeM-gg+$cRW`5Gd&>MTk1+thpfv0Wk$LJ4UYGvE`Kw>;C=fi)ZeC z(8yww;{;rA4J)+v)Gz!fvaFa@k;boPj#AqRYp)Fe0Mgd&d$SpP=#a);yK8T}`4LAo ze)NbD!v~cr6_S9+EFl1>*pSQTGw*%4rBZbpvYCmKIxGu(Uor%xsF>vd@X5CBy?b^c z!r;M!M-FQ(d*rwQ5hBT^rp%_z-P^Zq4!l}(Q{#jQlbVXc@qu&LxOK1ey@_LompyoQ z-Fnw?MhqJ~Zp?6tpf3os>Hq=-Zmv+=x~Ff$rma~kGjYPWVi7CV0D%HuHRLSY!jCuY z*|mEIW7yu_K4$b#$AfCkw=5nJs#Z)00TgkjD;WjN4Ym)ke#6eb-mZp*;)L;|3OVlj zQc1D}t9kyW9i2l4w>B2-jaxc*@7dju&rh5{Eq)*x@RyENpn6Ud8tB6O zz;KJ!0m5(-=!zg=Kfxr~N0*qT&LUue$o#-<%(d<6-ukykf4j41b2gvlfUf5Ro;>r& z%NI{M)bY!{3>X(-AD9UzWRfw?P%&M`BaY@wi;=p)Pl&ph?*aiTLQtf1XnLhm_Wht% za{x$z1XRFOxUnHA0Q5b-Qm*vXYG`rNRTTmK!1aBZU5`dcUVFA)YZ5E<*@&t9-`)5g1R`}gP0zO>lf zQ0^%K;u+_jdF|ET03-shYtP=U?k>*@AOz4L1KHix+11$zLWeJtQmVVFyHqOapjM6y z2`c51>v}#Bp?~m_g+KhswZHl0pKkf{t#{w?PcEq3R|SB%`^^hvZQR%~Klt&tZ}{o2 z{(j5tcis8Vz;)Y)4BBVGKCiv}THt#;+yq!9;d??OgT%_Io7FV)?MJ2QgVJPAb$5h? zHud{3{FkD8&AXM376%2SqUbhr2?B&JR>qi8&;uXedWr_I!2B1 zoLafBZ|)!wL_4&m@&JP035?S(bnj#>~r-=HAktZ%H01<8-r+*6F zKZ+oi%{4VOTA56~&``+bxe&-0Fl5L>)}@0_kx5duYVEmIt7Slpu|NfqND(NK6a*5b zg$x*$DwSQkcRlgsQ=2w_^7)I-%@!=D=Gt}!nXYnUm_c$@C`P9JW~H8$^}i?v5d9%T z3@<2Ov|fL1%k|%Q@cp;8OrJa9_;dCvHsm*N?0M<=%{M&p49l>Krp)JnUZ0dM>iuUm zTt`60bPfyWN@X&+f@QPF+CmWSZl%?_$O1q*^$n$pY(p6RKlX`+K~`EZFuB@cp)M@| zk%;sTnOY_w3*SfpD$phJ5J&}*000>>0YKops?d;m`=w8we|&96$B4_ne$>d>`3Y0o z{`#{g)~?&IeQPI3qwfh}fhDX)Vq9Jk%11z5t(^O25P9muoLxdUDFT`j}5l9ksRVrXg80*4? zoN+{`)Z88!C>{IGuUfckB?Hcn55Gh59GX_9@AQ__I9FTE<&`}7a$g*?U z#!(}i8e76Q5}*!WXG{_0xVZVLXaDlozYiWVD#+k-S6$*Epj=lsSTKx46an#`^*rL zBM=hPH6ufo4GI_uj&`1~K?Pp#+bjFly^ynVXlJA}5w=7oBTRwbOAQhW0gZ4U*lsZ3 zC{rY7600OC2ZaEDS{IV;!o`b!{mbir^{d~mc;V&Gf9dMzS^LbJb=jq#JLS|9YkfVL zT!XeljT|v@+m@}ToOF_vu}h`uq;aFKzUoU04m?zO<;gSV|K``f_}Ndd|NWnD{^MV6 zu`F<1*)gR3tJy060e!Exw-2(mQeo6E04T2(1itTix`YHW1Y|@UnD8BM>y912{?o0$ z{?o0xJ!3`;`|h{Dna{A9bLag0$KSr`*Ec`%=;Mz(`nWzjW!z|PWf90J_qbl5OHLek z*pWZ~$@hPL!>@k$lN*J&kt9fhk;4Xm;nE8M7)e>#yEmUNaLz!-_5e7QvhVx8>o5jH zc;wP0%b$4W=D*y2^IvY?Z`PDkPd%+#>GOji@O)j!Mf$!U1ioA2mJP@NnCH5_?<+|F zvU$+pE5H1uuI`@4o_zlKRV!Otn!37s2e-9e^4YVr11J;_0ChT|wjY?K7EfV3%_a#U zk+@9>vX2jh$m|O#M4Gsu->1Y`OrA_Fa1*QcsX7(=Kagx)OHDIBWs`>ZECPVgVn^Sr z2NJ{jiKe~L&hJL8B??_{5x934smB5;Pi6@@5sHjW$K5DpnZ#R+;nty-Xx07%H7ucq=@_Jy++&X_Xt zzU6Dyyt`%3-oDPRGAhd2c0OY-Svciu7cZGUs=@IgX8{0|YC)ioYqK`Rwb@gael0B$ zF~*5`(fvW4c|icA13AL_7RWiz5Ga6BP3AM~igS)|q`dy-yLr~$)mOXfr@!s(?fL9+ z%LX+zJC18{hZO3q;sxVEWEgNjRHP(HS4mHj3>X0Vz7hrDI8u5tlM}Otj(+3A_g{Q( zJxDxd{(i%oTBX!=<4NgKRUtxAfSA}%O;2&EfY)iO~*VvG~|KS(@@~1z% z_R1@@sylR8`@ZvLTye!$7VbYQQ0)6ZxM|0(-DjS8>dF->9{ca}zEhn$bNs1ioPOqK zPAKFv03bmEvMt+p{^n1&Kk?`zZ?Ao4SbN*z0}s3G^A}EBYCQPh#pj=Y&OUP{)|^0aw&I0Xum9Pvjymed#>R%5Z@ziQ&OJlhTaQ2S_=_(* zd+3P4;phTNMfqIj!wnyO<*V0C7&q>kZ(TKfXnUpNwzlM-erE0UKmXClj3nTKU#XDJ}s5+N~dE8x9<;2a)F(BC<@dGc@_GdPTBu-!)y@%p{YC z#eoQ;mr%$IF?LSJ#%j`45CH&@6hjQP3jy2@yu97eQ{DUbCw{wO_q(}#jx$D*Dt+FG z2c2=q>|_1F4`jd?HwqaLkS>7?M4U0HT0i!UT zgA^bOsJ3AL1*e?0d*Pz}eB~)p#3TU{C|#7!ljRW|L(jeVtVxq67m8U=`IcpSvNCq! z=rhkhea=4f@`YU4Esq%4@#CNTV8)!;D^{%P+0(P{;{EsAf5ACtoY66SL@g*6irHh2 zJ9^~kjuE4Wda8m92_yla0ttu=2^0fVK%T6O8$a%>i_V%cV}=*hn4rTBUsCh@0}kA; z7F2`~p684hG3@+{&l@&kcrIuAsy1ZE;4?pa`lwN3GPZ??t{)6;9s27VZdx#J(aKdX z^mg|&78~|kxc_HPIb~RTdo`#s3y(N*>DUPq$BiH5sv06n6)?fhIq&Sw?w+ATT0QA1 zP{{G3OF!GwS85y7q)_Tc9)Iewh zZ0YeQAL|4z`t0KKE*?2-)T598ckAY@xqRWwGfpoyWd8Q|yJpXwAu$M}HA8zdCGv$L zQjQ`a5?DNWKEe|5F9Sx80zkCO&8MJY{fowO`XbU>lo-hrFMv>Mjq(vOtSqC8X#pTs ztJQ{l#vvPB? zh&ZT$o8jQ4CNv$NrDw_@m_&?S;(-ynRF=)Uchvs;vu8eff9Ijc&A<4XCDZmD3IIVL zy!zbc=bzg+fAI(auyU-Jw`xTuGO1uAqNokZLeTqMMp_jp)POGxWg`Lt&M=b^zNe(l z*&&m|A0kL31`G+p+Wur`n8*kOkV;9Zh!8mffRYLk>Sh{sR)s2{YKb~5%{h| zhPk`|M9&L?fEZ(>fQWYP*ey%J=xKxYJ9@<6F*zVQ{@evahPO=FXS51*-Z@BLA!E4= z0|eY43nH&07w*lkF%ST=Obdk2ssZ>S|O^FX;k?7 z7nz%NJSHR_k&@7>3k*?E^S5xN`+Aqk&M?Vs=D^Amczz@r~R** zXb@2;3Y5|-F5J@;k?SfUhzwH>J`;ZzN-jjEi;^hK2#r|fLTCZ5)fclR1u@2Ko&g9g z2!eCYxRH5rLXB3sY~w3Mi1-1b(NL0@M>o(YFrUg@&DfjB()j++@JwdFBlfF|Mq@NG z)TU0<;Fy%nh0QZrOQ=%GC(kG8RviR=S_+PtjKvWZk>mT46w?(m6iKBxVlHC~hJjLU zAYG{ngi^_J)p1>?=6Ix3PVgLOzVFF^^iCHTMoSWTJ}K3ju`Gs;?*~c=E{KKcl2R&$ zn9JA*Op&VkzEp}ap*!bGNko?5Hs=UX^L-#{^n9CA?CnX~yDKmm+ z1XBc{l;c(v5kukt5)dfdIT}cN2H?pTRu%HO6HYt!2cJ8WG3)$1d-8XGTK)FAgJw)+ z3KXkb2~lw?G~t=3Ki93D)Ur&n?ewz2a1Dp*S@^I-I3$Hm)dPd}$|IEl2#X?` z2G@^th|g2CH0m!jjJe+m#Bi%`T_BnYu@he?kyH_(`QUw zcH|Lr_u0qk?E)nM0>-$Ka>}GB-}&CR@B8PSJw1Jc2M;~)paYLQ<^<{0WPnQ64mJQ)h(D&u=VMC5S^2j5OS{k@+xwGrkv(KL}Y5M&S zKKRiG9~04($rH~y`|OTUqd?ZKxZ?8euD`{+W~Z+jlNGy__@6N28(uA#O`dD@LdX6ZBul zInzHNnl)@nhlGXZ6V4M1H92$R09F?B7Zb~)pR}%{FpSqy;$KMJFhEqwrye1?HNXkM z$Uc3Dey$-h;<+A*tlhHcW;dpH5Tj{OUJ1U;l$^?R;+Tyag8LFTMQY3(r5kYxmx7ed~%`)~?okB9w$$Mlw*G z0TQ(}=U#nt!&krdwN=kNFnZ$b#fuj0+O^{kzq;|+=brohAAWbp!kGZ@&bs$jJpG?H zUR#|n<~v3XUNC>g%d21d(f6+E>FK-fdtYs9Dh7%Su#=6=EuDL}ty%r#5z7uAf70Q; zL!^SIo_u1}vk#qi#zlkM@{Z#p04ZXqlmfvy0jz(2lUwbaK4Vs~Ai7JnjNswS4zNCB zhp<_biEUxhVmDgmhA~G7oRUw&n8?$F6TQM*5XS+e&l@=Fe*&2`IOA7>`5NzaRliXlD=|(dpLpUKC!SuCm5N)kZ0>or5hI4)cJs{=WW}jegX;LPdRmGqJ@?t9oO}MVNbbw)Y4^#FFmAG zb}S)^*#bbu@p?QW1l3n99d-Dz%ML%>C*Q^_04VSdJ@Al@LE{XtiXz*staUCwKj?tt4`|QfK zYu~=+sxN)!v{Unid~es@Orhc0Z(Ox=_nzDS{*PgU2P>(J{9_^cMkeJ{#E_Beq4k*n z5@5)PA|lFWGRWBE$rG>s%I60UY8hxy{y!X2DbCp5?(SNpdcgdBa)sQDzx{&@=*mk! z*Vf)r>Z@9o#W*HqUqZh~Ju0%t^bey;j(yC>l8;FsR5IH}i40%$*v7YC-!frB$K}^9 zoiu-t)LXAL;KJiaEj)gdewQNfRp3kCaEgAh$J&&VY?ZNMkV11>*%s^CtGh*bSdzfC~966RgJzWZ-86FBA(T zWx49=@hjN2$XMM~N4ahxUnpj6%a;V?6Sz_ap3fO$j5&+}Vnd-IgP>G%bYQpwU_vxD zH894?QsuZPr3fnY`d7tdQw##k28=8Y|F~nqN=FRbr?b+ zpUW!hsX9XQbz}iiE}OGB>nxSCmL)g~0@+$DcmO5WL1cq$VOv=xrBU8YJr4lVVbK8X zg9f=JC!e*4T9yOAkt9bun^Floll(@P-gD_JzfDjJvhxksS z1c-xyo)tgC_^}57!TsNpP_aU6*Uv7T(7shbEZ+=N>U`qQdmi|$EOqkMAs&zy_&}0z z5L^Hv1%dLaN_ij{*aaqRV2ntqz*B*v=Y&~VE(8(=Qc5Xx@GJnzuv!Ws0F%VL8h}jJ zqDVA7mA)Q-ObSsn_(%s>M+@BO!||Pw;-Eh;BvMZI-U*W?e|gGmP*vXm(m*Z0msW-Y z*dYB%=T3nP8ITHu-~hla+;9Iy`|ZCdnrhE2GhiqLQ&6jv#!sC3m9Jf!9D3)DF{S=<~cP|%CfQ-U;c%QF8G`mP{y`A*Zs_? zr=5QKXQWaxs8UdwJ8%Bn{SO83WwnM%kzZSKGYx`rZd)&5=v35d{J^GL@FOd^GulhF?mq^H|%#Vsrn6|2M%=9Ma72%HxNSz z|78QU4FKvbXaCPDqF8FGJ0+rD_2x^d!WdCY;wTXSJsbv2BqR$WeoByDN_<7`*@0Lg zB?I)rKgkfqHF9S4nu6D?*mrOgn4a}J<4Qv;@S5d?rlWV(K+ZK0HGcbAv9 z*^>Dq4&HZ!RDcX@1Pj3Rskh>X`_C|8>39T15!f=ph{+>q9*rAL1}CMuN{L=z6ppQp z3Ca@W`IO0sZ(ev@p-}k!-S>5s%XY5q`a2%jzH`r)&OT-M;NgKQK`Qcn3q?kV!1IBj zLJ26P@<>Vwg1}Q8S{j~d^#`Mn9_$KUkp8|N>Ww|(o5>wfa9hwu93^*8?dfW@~J zvVw~YLmDw+_)l;A$-xI7kjt{0etXX^zWU3}=NciegN*kO%3_w>ECX5HAa zV>kzgids+V5& z`HL<(Z|vAH|9W`k559KsBlq2V!Fi`2eb|Cq{_(^gfAzEW!L8r?!LLp|^=N_k;A1O) zbnRFE@avyWpE~uNb5B&n3OT_INicw#1mE+!%FfTOzkby-4;+8m`QQ4^cjwI**V*IU zbmOmY{P8tEzu`Ai|NM)g?G3qHq0rEtx5O7NyZrJiFK=qF@40vR*RQ0C;;Sw*J{q>aU)JU^PHbtd)13CymZ2`hcz~2KKyvc%9T$ww+=evoC_O^V)IU~ zkmHIJM^KV7Sy8U}Z@jfeh|IJplL0_V02=^|l0lSSd`i{n5%m`sU}1C*gcPj!A4(5| z!5Rq0Lam<`s~o8X62(Oi_{ccY$gHKLOi1yi`Y>Ew7zfE{FvbpoVZ4r{AY6dQqxkP-SS5NH91f3LXpg}0x|Wiu)u!Lhr$Xa3a1XC8h*R^)4L4H>G) z&qS1DAql3O(hox3r3iScQzmgL?3#-8#ux%B?cN0Nq_6cOGf<2H0Rv?QMoLwwR8)wS zP=RE?eP4FEoruV|;0!nyRmZ7HCzr`J6dD8H>+<#jf^As@*g?5y-KAmm|mIT5c`9H45L zmxl-lyLxwLtV}MGAyU27ZpZU2%MzRuA|dVR+ab8Hg{aD^=X=PQ#RM>=V<_N|&fYB2{x7&UqlA>UaSWDUtx3qvNvM^GDOxgVL&gGA+bsRZm#)w0Yn?8Pe`|hp1Pc2{n^nc#XipCwAOTYZlBU9%LJNf+i z>(+GMbK5J2A3f!eV<(gEXN%UJPbyE{zjn=Qn;plWyZ?k)bH=P)^U3z@T_>J3XVToE zwMxJRn0OLXEx(_%!gxNFq15XXqRK@*Q6Q~ zxvyB#7HqWP&}3&eSsus}ABsIAL;*Cn(>aL{YF;6~B|ngo2pMOHQUOCGNm8kXOa?5m zr&Q|gEIGa>IJ3EE%IBI2#g<%-0_pl55iw*9mdylr349e00B1aFq3d}{R}Kngcv$$(M-d>P=wE#sa%74~h6NLJWUdNt(N;%NL<*B-u_M5a ziK$4lme9HoOY<~2q)-tdASudl&V_jXy$>IM;gzj>y9T$k>^o0aJd&vZ3vhVKc+VSklC!Sf+&`_8= zZPGCd_aEEV+UL3!V|LcwQ*|C%`O*t(-tH^)wKg^EH+Sx`1@oKp`I_T!VRbv+idSBL zW8J&kcke|AW=)!O^x}mbLx$8G*An=|ORv89&bkwp9#ZPRf#OLj=CR72ch069cB9R|9W2oO}DSiYJ3?p+UDzvtnlWBxa&JoDFlU_ zAy81RDbHmYJKHiO*FM@FK3NPI!;8&~b45~B`~04r&Yn%qu1!JLHdX4em=Ku^6FiU- zw7?HbF)>sDvn{KAG+BA=y*6g~^!TT_A=a;(RCiJ=GF-Z`rh##+Is;OO+!EaB=?Wxb zHp`HCu0zgVBxzYTL!D|vI`M=^1-0(Lb$BML2$ck3XMiCiLPnekr&0ZB~az#Q#*QI2L6b9rl;0%1fTG=6iqh&Ef^7~leT9(k>fQ+!J zU7d;vX6F#O3QC-Turd&UFG~m@bQlGqKvnDOC1IfuK%{(^krI|*$f)K9K^Xz`Zh@eP z0rUFGiWEm;2*9}VoSIW(RtA}H9G58>NJ)aBl8gu$^Q$#gt|8}~S;RRJ3o2Ct(!tJz zoH6c{dn5t3bBO3yx>?}a7H7PEiX)mOvy>BbnxJ(wAsQhsO+ue&k{JL+USJh7Q8Ja< z>SbvCk=PtP;>ghtk$NFN`%hsb>oG~nI}|gK=qdG# zgAMF>`1ICBXA>`q6j9Tt5X!I^LZIP>$-C0=t%=jdESZ#m2}fEK(Pn0Y#VKj1fCNXu zEnmt#Jw8Ja91yXrh=2rRLhu31q%qbp?MTrV7zQ0*o*s_q5%DF->47kU8Y~N4UuFee zedeJfhP3|V=D%<0>~3x!e)n^)t=qio%wrEfdCB6IoSk8oCs~GDfpQ5@kt9hZW#GCt z^5$Yw4&?Tpp6*KdgB?3JcJE&C_Uql%((&^bUA}Z#TP{~~Bm&nudC~-<(U0+BCd3d8 zJn6B$(wIun?7l3eFTwiZ4L2OKbYG|D4V^afx^I8=rDvAE`NrEHZ|xk?T0jQA?_GGw z=Z`<~AVq*OxZu1~Z~pynw{F|n)$5EN3Af+z50d^l7oC6nq5G3kRmWYrc-Fa}z2y7X zeCg?@o;~uAxs45Z*Q4&vt?#XUGcRTjZErsI@Pz;%1D|t{z9)UU>T6f+KWBpLIvLBl z;<9sAJpJF-UwQMxjXM_YGc{vdey#8D6VLw9556;~QBA5FgePiu$M=tULzf#(L z+UZwbd(D*qilkb$bn)H$ELi=*D}8+>0MJ_{3c+>NpoI(eZEPO?@~V|vw(OiSY4{s& ztX=c^D+ez*eBT8#d&-_A!kw@6&YG5GZQZ=>rI%kFJY?j|S+jHs3lT~JKn(Z2F)KbD zoE6E%nDi<6V=_<@Q^Y;sk>XAR1+3TIimA`o|HtHA7@z%AmJ|ivncB}x>5?g$5uws4 zqLPBFC=&PI`tbE^rZ8dDWY_h4>1u-om|!`r-y))v#E@q*xyN7o*YX$t!z?Zp2+n&t z`zDW`an8|~G*~TFuM&mbC4>@1QDr(vN^d)C>@pNJxZax@Mgvl4y#O*>swOQ!6jt*A zP!K4kbg39~cbaD*Dq^}U7n$D}05Sm#Oq8GEoFPNUcdA|$5rq(1OD6zCR0xt(XwZrE zSp6lL#fgkD6^2;tZKB+`v&(0{|g7FeH-U za4|>};tt20aZ}gKP&nf{ULH+5f$3O3<2OUZY&NTuDtTojV2ow6Hie~^01<54R-_#1 z0)d^ei9nLnyZptt{ZojS0MbJB(?0h*BCsA`9erm2GLrjsauZ^&JL)Ph=0E*M?>VA( z`Hm8>A?=e$y>y0zMYi}t_f8(&$xaKCc7uUam*w6t{h_TF&Q?;m~q$)?5z zMJg_-0TJm_1kjQljs_h}SSo}uFR^Pex<>DFoyph)$T>$ahPeS9qGkZJ4W1DZF#^)n z%`L%&ZA(d2#~C$h_;E^5(Xg1`Gz&u{Ai8=asA3S2u*2>JI(Ypj zA8)hr&cVyZacd}mikERX$P`2HkhbDE=r6VmrA0H`Z&(KqS@n;>dhi+^35`4Tw)hrJ z3H9#J@Cr1564TeD>;<1Hib2J~1ry>3%rg-Hge?>xC{@g4r3^~0Lj)X|l!~NmE);f_ z`c}UA-imeWcJ%D=9Tz#Xh27j(95HC{eiJ4voH%J%u@U@$TcWdCTldM14Lx0D$5Tq# zmY6R-DxC2C0c6+8IMv1BvHHOOhxaGC60_6ePmAVqgWJo!uNEXWNgw zy5`Hj_~XZ$w>AzP>PfhJ)ytfa=W`Y+0O+kbKfdkGzu$g0Z)$GNH*|J({o`K`zH{1% z-?{9rp`UP zf$-LUKXCpjCw}Xq&y8zo@}y#xT_O7IKmNUS>(-&!T(4Wb_5S-`Id<8Pzwr6N#Ucvc zS*d;VFSq~m-}ftI%?(YvJNMlB;A5A4=A>_a_MDb%#zVN{iRZrmv!Ag-LsMg8Z>jgb ze?7cn**{?@v6 z#bTq#n=>(-8&H{;X`Kl8WS@4Nh_KlSa{(F**EFMVO& zq;VO}vUaB8dx2Cjg-6D+<5qbWy5Qg_gB|8yy5NL!noj>JOC=Gba*W?AgN?Fo0+yB zD+~$xwsCHUix^{%K>vQlx<=wh)Q*Tqa3)5;aOz|}Bm#tLJR(?`3|F9JKuQWw%(f6M zP-MU#Cjv#}`$}YTw_ z84GJP=w1r}ruYv45F+QCsmLrrjB`X%fk(>aj3Hx068wN6L(Tz+F&(_jjaxx+#z^n( zq`?7@5P}m)uS!bUjIpfEfXv3rWJr^e(-K2EvltPQ7sYd*Hklb^A;D_HVTk@Se-nmk z=y#;nkf}&SIKX*x=qLYAtX+S{|HbsL;)R+*zW_ueV&;HooTRZauOG^&V`{0E6PbQe z-JNj}&H7Ov@L5>*J$X-Z+4h4tX8t25SVRJK+GvP0%tpv?|kv~gt%^-*X8E~Ul zAw(1gA*aBIP$E!QKTmbNM5rq+lnC=P90?8ZGX$zDVSpv18%Uw#S%=OU*4l8*?{8VZ zWpmq*LGNzc{r#Ko*tT=WaZ46d9dA(cpa#fE?&Lry$Fl&6R&G#3lW#*w`m5i0bM?FH zwwF40?Ag=nm747083!!A;E<&)mQ^m-EN(NV1Y?qvv83sSVKjj8vciFgJDQBd&}Asu7J?|u2z&6~IEKWkK=0t6-m_q@OZo?#I9l5q@N z7g3cR+O}o0QexK3sew|YFi<=QX&Z!9W3Y?%IjSX3UzJ$%x+Ga=GRgi@}2VGxEhDTeodRk}s@&$bD^8g<mRWJJwa5-hNM1I;xeOdMKlcI({!0yvsi76mbN~vVlnYIMPp$*9qj!jP~ z6(GJ>|AqjZv&3(qzGK!p0)o(`*TaOM5J#W}V)~h=Nbjp^>Fr_(DB9AK2taRamrzWS zTpE&ATq5KsC^R@S1Y(%Z@TJ&TrXR;lReM6xlV;RF2pnVE#=wbRy{)dXW&} z(*&rYoUjFYj>w=73X{_Ms}lX>qn?i_4h0Q*(55-g%${F$kI|uQAh;l+uHK$vCU@?+ zXMg!CU+m}@*1cyh0ksVpv}x1kAN~B7|GNKSE0f7(GgA5p2!y)2nQla6AA!_|)Wn1X ztX+l3A%cxc0q44~2G<*u5kue*l>!SfVZ6d95lcg+L>3wkpmALi6U_5`Db?IL(|&s0 zHQ)QmP4_?iNU2o%$@jiJdGa`?=1QeFN1gkbj7^P!BE@u{l=y}Yk}IN)nWeCh{=+#d zm1?zekhL>~<}Bl=f)Fhr2Sm;ohWm`^ekm1JzR$Xf#;@JHtg@fC9)s zQz6R(*;KTf+Ot3aKDae-Ycgy;14YWtv2t(lryHMH_3Veo9ly^B=g( zLt6sCKmPFQ-G6;)(V|J`e174`iOpL->i+AmSN#6xPYoH`aLn1$1L?Q5wB|BBn>Ot{ z@bIYzES=6QanD^ZJ@()$i~lqAqN@-7&d<)CIO?^({^H4f_Z#<}bB>3C*Vvxth@+a? zvz7$}o}=!$W%Yyiy}tDDITu}Z$dFM@Pd&2kzB|?cTBn?~|J;S+l&``Por!^tg@IW$ z$;pV-Kf`C~eotgnP2G{r|@kEgrS8l#Id2;k#e|0QoNZrW3+-J!HDUX zM3<(&>P9P4p?wxLMF0?iB4A2q%y417vT@TJn?5e&3qu(-QNj%{TuMH0dBr9|cX-lGkLL+8yu=io!f4<5GulT8o5wPwvHTXs8D zAdUnT*PYVd_LDQu9Np5aJTIwL5aYMMuwr9RpKaMp8>r28P5M89$QffCIU*usMg%GV zNu>Lwh@_IBkT8z$+*9h=w`24f^XJ%>@O%jzB!DE6ie$JMacWBg!;AaRdw&L-Bmnaz z(i`+&1O!wnXw2r`-PL*BU+>tm;p5MJ?%ZVy7xYwW53X48*yB%UtxVRk0HCX{Z|BZk z2k*b&^wUlrGicB|TXy{FZ+HIZu_qVLpLN+0OCNsq%{%V7w`2U6D=)in@`$1DY~1wv zn`@^|7!3dtfN@qWmp53P2IhJzUv=%-}lheiIcu@;<0X^2%ualXE^`j z>8G7?=s}*Mi`dC!YQLUH_OpecFX*o;ImtiN3+RvO+DOXG7()?L7PCe=PDPu=%-`oBByZ-g`@@M}wW5##SJ*}_ig0Oh= z;8)&$Z|;~;U-;}f<2!~sfxP-pe|_uqHAftG%;!!xmTc?aPe1?oGtVJm!VwtqMus32 z<+tb{vqKst zj%t{AC>^q=Z~cm{R~{_C{j9%dhn>v{VFkJ#IU|lt%AoSWYfbY$7R|$CwTFcp4~3w_ z@GMGkr#g@a$ziD191Q0(8gi~bWBGpvPH#HVV4jlpnh{VFw zdN*`Snl>;UDjU9qP@2>OU1?Lpk7yf7*{i?drBnUK4ry4 zvK|w>7qv1&n0Q2e8x!b@!dw1_3j6=pp(RUdSJr_dzw|aEm^eGIHPB4Oz|mvT2aL1I z4c#Pni%(8aautTBA`d_)(~>-|E{!%ijgYX;N3@#Qgg#u{VHR)rd$ht*s|i3?`3yH% zBr@4BDO*IMzHa#B)F_x?=$9}&5StHaKyw0!qdT+<4F$Dy!Q3vV#5ij%w&ZxDu(DO@1)M(I@$svh)~;FedUvH{ z=kplwi9{uEQYUI+e;8Uv36va9gKrrk*Z7k_ zWGqW?##q)4`Bbr(L-4zM`@*q7<#_?;+(P7lGLV5+1K%S>HHQM%B~pcq#StYV#*r~* zWwV?k0F#O)bPW5&FMjfuX){+m^~nAA-*^AN{yt~lLvFh1`hynE0S?mhkQ6iAODW(0 zg?s@ZsFbUwuYv121ZdkFqy*$dibw%s03ZXOfGoifnPs8nF+{Yp8Os(3ASDhO)OzHh zi)z)9ozDo)eBYfoX<9yOxo!X;o0=L6g#swDI1(wwz|Q3my}rIO07zc~1l3B70J#tr zM*xsgDitWH06-Ud;0!Ish+xFv#={O>^7wylduQD{`yX`R^DCYn)IMs-p@$HWK(vLn z5HP892?cm}{YOD<@61_qTN~`{T@~B1rP*Mpo?*pnJTcj61=NVyB(Ts7Z6J<`Awt14 z`|B@(u}=Mn*mM0;^+l?FWto&f^G=9TS_qUPrIbRY>t2KYl7J402N5zR9$IzBL(kqT z3RY0*z3cIted!-Q|2RPA2QEWYqyQu$k|I#pP-uMZ! z9^F2^ui8u6%x@AR>RGJrscsS~rIb|h-dzdU8vci=S5{1ER3HTTntH8vasUB(IqWxddX%Z`SPgP)+#V%THCNXE} zgAAI+Iy#TwUCf!%VyEsM)bE!84g+QDMRmxZ^ylz-bt4fj2c?uY+J*`AF%!&i_T-yy z{r$OT3oR{7se`6YI`6;(_Z>6FtyS%8e&q)r{OsO)Kis*!wYjme&&51q?!XmPYkZtYip3pj2 zo82T35e7s)Q4mU8ZM)Xo0;2z-IR!}2f{9b_hkJ~$NKi_Is1+$hMu<3@$U|@V+?h52j2lt3?eo5|>4~RTZ946AbZdWm=+WWBhFyC8IhP-@ z2mp?lHUS8~d;JX$KDF|~qmFLPT3{R$La_14=Te7I2|T0maltH3#M z@qWMf(q)rI46y zN&41p_uO*#eInbKYiJr*jm5RQ9>m47gUH6SIUViZ0nSKyNmMkxAtZ5X z#5_Zhqrn4x>MDyMSiIQ5*V;?*B5`4}c8-dC?n#m!EEngOmwAX30>p0zul z{^Q<9Z?$q6mbIksaSj|gO5dxM*pSg}2c0=|$=O!hC|T_ZdUsI}Aadju<4h-y00598 zzoxvJ0sC9ed->n1@2+BgHIpqU831F9af_hx@}oN;JL+@4BD_DFKpr?&k;>UhKL3%VTe7cvs!v zL{?%-Bv&Jmj`84(OM;RkXN?>7mv3G5i#zXq{DtRBUOCrfZ`-}Y$}oTRE4xa4Lz|ns zs(U;A%+v3__xw8_zOnxOcQ=31+uNJ7^34s+$g^`MPQBo;WeX-x5g=Vh4Qj}tz}+=x z<=VHT@|Mk>m*GOGh%bdrN^8FTr!p2!(Ug)I8-|F8!m|9{9!X$v;k!Y`;sIh;XBR0y zpUDD%PSVlNex-mIN-2ZD2UIc$iUpP{HUiZ4bao*kNkuYX%-XSYk5j7@3R&B>0ATi% zF~7UcTXRIvIMWWK}%EC@q?W^wh&QcV*vnM&j*m6=LdjNDy4vwk}8N9paKL! zr9hG-5&-+|Gq0&-{EIKH$~6z)ux{PbWyj2&GtHCAwwOSYz=&a>Fq;uQ73Y=LU$N}$ z%xO~yKn4I7NG%pa_CU()}@yb(~d?ueOazsCn4?J~;KsaRH zu?(0S)O0XAk%T}t6`R(6{Q8}b{;}efERkh^uHy)1pLOiTv&POTIemn{i6kl1J4)*o z*M}pKB*hh1OiERsW@I9pG?!xWKvA^Pq5+EKa||D2PDTcdU|OhZW~v_(nMopH9LtNu zXQRGE-ivsaA|a77goJp^B*#ZlA%@CgwhR#*F$9-nF9skapf8#BV3Zjg-W!Jx8QK5@ zi~^VqJfkp;CRGA8>{cxADSos$A39wV5-V|eYym_wj%gEgB-kQ)j^2xjL527eX|GT6 zLncwry3r3cq$eebQ%tvY!<1CW5Rqz* zTPZoxS3#gSa;7V|GXP0|3VP1|?$9=K@IxVbG-s#>p`ZM3KDH)P7x!5co>vv+TK?3iM$ z<_ZB*<_-fJc5f-Q4k-dtf@7`bD@jUGwbw(SzLL|myP72{SF`{L7!qCMHw)xD?WI?^g|q96uVDjBewoSJ@alKLZ!lK)RfObLmIp2S*B z%sWEDM-pEkF{Gur(Xxaec&?H) z*Y#`u?(WLwzTV|)-pu6r(DotIM~pda+O&?=W+Ek(%39Wt#-bMlD(WHup#ll#EZV;k z1eUNF5dd*SMBt1GM6MHB(bQy!ohF@EeD&%f}E zpR>acUO1y;_o(q5yl8FQwr%w%pKRK-hcUip{U%B12R;BWMy~Xj=Pq5a&y3-NH+6QmWV0V{ z+lql4H)6!R@nbgkReY&NG!>56Z=aPiZ_F)3xBJ-R7Jo49D?;bQ{$hl{n zl*#9Byz#eRzWN7^zxnZT`|tb6Q_t^x=Y99$OE{t*>G1L7#3dHZEEzeQ1Sv7^PA;ny z1Mlx?PQinL4}vI?Iu%=|pBOGn1TfgUj)Ky#I1D5*LNkThLO3NASdFdK_n+AP$jumd zR!fubxts%I9DUDmYuTBLhoAh-hDl4L(;IYd1p>wySeeiTOA-_SuyAK|V4P_#A<5|r zYQ1RXn&zI_G-dJjhkv*CsXMUNV;74`Nkjl)TX`(M{zPZTZ`w|{E>ON{D8)^T2c~{F zQz%AXUN`)So+g8SB5XwQ{2~AlD$s_%(Af(l<>0}CFa7+LAj`5^Mi6=cRhT_*xPJ(q zBHM~eEPMTCO8RdSXe{0S_#>v9A6=#)2}a2?QNE!8NfGTB92~NF3`rp5KUzyqi;YkN zN`z2Tie@5a7P*h228P7cAHT%68D@sj4UmdFkLDpU>xRS=>n1&9W)LZw(D+M=e3GL% zAkcycghBEOO0_C#Lfp)lCq&3ObwLt`4ji_Y>?s)Ud&o@?`tcb65aHBd>RwEYXFNA4 z+vlewl_EsJ6Y&{+WpV=a85T}9^kZ;Te>)_HG5*Q$t?(7m&+#7w!@H7m8cjVRMTDbc z;z7rSBn;e%B^6R_jE)j(Gh&SO%spX+HcbV9coRa5mqT&{DDfGSKNCP$^cMku1w>r0 zO9nPVx#kURv~T#rc?Zm!@z3Rtt=se=0FxAK*|qbdZJ!8%nVikD)=TefsFf?e^ch&g z8i%$uws-Y*3fn&Vz(eLw8oy=lF2+ROwmNH-t-amPeYoz?SD(o;95tkU(WnVES2D(; zXdTi_ChlcY+J(Gj08xd=091sZEQ{RQ-S_p%hm4#tZ2|xQ z5$8F^1pp`&rWgPrav_y0Sg`-Xg==41e&_9XAG~?6IIeVsU ziH|?owyUc=Va&+M<3~&$f9mna9{14)@2`1v^`5StF{6e{0s!~+yYCw}W<w0D&Kh4R z7C+d$^Pl(JtpacUz6;u0bA46U^QB-hf%-mcZm{>AKYjN61uw38Zu!%z&N}U=w!y6y z!2J(A{lfE)4(^ydbNW;O2&6(}j9X!aZjDqBfpg>x02o7Lf?FA33C>UvO_?}m$+Bfn zJoK-RHtn!&YySQRwl!J36~_|V>#QdSGXgej-0{My7l#iYGkfk_PZ4siX(}XZW*81e z)0#Bwd>SYE-{@q3tId+b`V*M2ZA7+_v?NHx^oQgHVFMG)o}xz@RuHepSuI z)(^L@yY0c>cbB@dxtt`W$Wehj`76;GwgD(j=WL)_Xo&$g=wBO8taX*?FpwM1uhCUPxA!`Sy(_WLtIy0}a zG(i*0BZ)|9jgJ`9AxjF7MUinKN&o~C6cxT6Bh3_*(t)mAHyx8)mf}H-htix2S78_n z7X<~T%z&xEOv;2;G4)5&gzU^;!{q}c%>8nc;+OiO6U44=XnasgaqvO-t|o%%gw zaO=;m`{v~FV}E<|U#|T6wWVvX{mjWn5ulPXtUW~ln%yRyg8gt~-4CWtUraakN}>WH zkiN?1Ejx=|AUA#7c>tS0L7*4_Lq$p{6jsDfhyWS!z#{;VlC*bELpA^if*_De2B4%; zije{!Mv5_|$m4_B@+X}+TM;pfwtUd}U;>#t`)GEIO&& ztNNZ34DM(U7UP^{^4xKu+T%48!F2+!MoohXj4{qxuEAo0<+D~pHs?B>o~KA@1srST zfPApCwy+rxszCXUk_s3@VR2NP*|wFlgkXrk7$R3;Y)7D^uSApJf^)&_yg)!?U|Ad# z*N)8uhf6XnNG@u#03tA+w28%6rDwEX`dTEmqU#eFp8BKXPp6H2?PugK?m}Nl0av+V%Qs& z=8&P((#o`crXrGni0Jr%>-*9Kk%!7Jf(%DPg?71ElEmt7N>zyFIXSA48k}Umk+Ojx z2{>bwN~Nn@QMQ#8Tq>2ZY+G1F%4Ptd0x1DtQ&-Q;|9$d5|6TsUwyi?3T(Ln3&hvR+ zNdTBWs^c4%pa1K>+_~cU7oK~5MO%CO;Ro!0;b|uwJaIgb;+zqX9|XWeA!BDa5&|jZ z`91*zlB86~L^hWrWCdFY&ZVTrhP*3PXQf*8mGpyrL%u1OWt=zXIY-uF^C5$pHgDSD z`mRUx`^TQS^{#)sw`n7Iftdu$^L^7}iBcj`$@Lg8OYn;8D5V-3iZTc+n`c1yfQ5X9 zICFeY$8750XCkmHdrNoumVZ82Xv|-D?x{aI>m&qN|MABU{QA#7{mq|UUs?=@>@#!5 z)bWxMl>ig-A3GA$c7qgT`9B>x4KAVA)ve*k8=QKo7Wg6CK>(m+-S!mVNOS$@7qci* z>>!pF1|yJ?lI7Y|b@SfkH~YIb=UUszuL(e8oK)aR)pWqg!%n}>YMv1EYyl;i$N*~R zj47obJ~99Wx)cN{2D%guXT&%tSN3dSg+aql`)Q_q%(j30l$>5WUmz7AA-5T+>dvR{ z$xc~Zn0$Cp*~^e4$*2NFVm?%?J3_>qA>7+Ze>O;nl2HN14iF)i#A6cn1C1#VFie=^ zK!C`l;{~NHjB_q59sD7+@mmpsvN$lqD-(~?xoQy}!^nY|u$)qI&By#T!kq@HQR3$q z^8%*GF-;4}nGQKhC`FRwOzCSe9M;6EG%J#UBq>FRmm(QKkQ7=}_p~}vgRrLtTgHT$ zLd^O`O2Qh=wZprU){_446vMg$F@Elcqmr*ogIpsj36diH(+(Pdng4%21}by_N=3zy zQx*V;T`0WG%AObN(0>~0raRR~dgoX1K&Yt$r^UtqZ`{w#B8%l0pCSwth z?|H6M;e-vDhJ3DJ%JA_^X6-+A*zo&SKK0bvHP62N`noL}sZ+51(?K?Yval=o$cWyrK(rfqIcLo5|Y7UXFq|{QF2#`bI zdqh%dCAunSJ|oOVQ9z7k zEarG}{HVd_UwFyauX^R1U;oyY?YpN;9=~zZ=HLAC#yz{buD$N-^JY&c0AB_~s#dE8 z0VqWz!Se&R=6G(^^L+r2z6yN5RPO65mxc_^yS^OURy^py#Sj1U?yVcvOq??B=pzp! z07)#P^TrT~kTYTc8#iqEWc|B`AAQV(@uMnL9~lqJQR$fLdLB05VlkiML~e}M=Ko}X z>E}iAFSXdUgDWDqgrZ>>KuUz9L{Wdw|yT)3+;|&0_%EV&zix z#Dh;?GH+ScuPO={=Ls%rT5kT5u`Ln+kqo`YN=AkfU5el28HVkn*q9P^7KxG>H{si& zddT5RQki~6h}Dxo_?+0i7N;OaY~N(eBA7kXBexF%FeHV*^4X$50YD05IVgLcCxk6! zU|2ONB8&q74Y$ydSxA7ukO`gxqCj~JS=5vm<|c#OlJWQnsZs9+Hv%CkSWL?eQ`dtN zN~Y91F}6x3$6Gf7lhPxWyYaBa0E~>EG&F>n!NX`E0MG1xWR^vk1fx?wuJT19vcLK7XvbI4-+X>6D2p$Ta~ zE802&L)(Y-4%>nX_&H~uVp-x>fBfsWe)vO4 z!Dmif<|{>@GwG6+&V;EgHPGq9%v}VwA;eJ>t~WCWo>ZBl7&X3S{X2VBKKaqHXU}eE zwOuzL0N{|x3#PYx(Kj%X0XmMaLxMqX?189tus{YY44%E; z;Xwc*2X8&Q_p#-#EIMe)<=;9aY_I~SDitWbcd>4;ZP_TGQgRpvB2ocaHfwInB0_UR zkz1m-+ts#W*9o!~mx?M?hjXxOE~VrE6d)in9_}SefC$=RNC1Egj7c^m7R~{Hq*MTq zu>|K<)$z6cU;5Irx$?oOO1;4aggQim%9P;^nr$RNteK4HWhuOwoXF&|8xV947<7Ia&ll6t9N>U5IA(k+Z+aOjZ<#gGD!;qSx%7^zC7$^eSC zedhcbZG(!HYHfQ@_irD4B$pAb#g<~gzJAIv71 zx?@m7bII{I=ULxAW&eGr4sP4iR|a4i+wzsKBw3uZ#DHpJH4*jJs!FM-C5Xt8anwcS zkTc{)-3z@|@gN#Z5N?A^pg;lzB(yk##7FU=o0fce0Kt$ zM2Rrw4U!ZhGA=M6Pb$Hf=ldDXES3org0BFX0=WIDXMg&uUym3z^t|JbUpRGYQ%lpo zSH5`PBmdRZ(P-IUIP9SPCyjmN#aCZ=>+LnKues;$yEkmxe)o^Qm*X5102h{JF{7{u zhKW%okmO70cmYFn{Gec2T=4Ev1tl@WoNW`K>jpX()boQ(HiL|HRVxe`vvO;ic zH)I2O+ObE?9yh+drR}2~JFfrZUzG0$M9g?~8IjExXN&-3Ai)a)QW;BB9hW0!ve;X3 zltiTv0F(*~84)07Y|HMw<*qK#-16CFOG?#h#dW`X`tf_WYPQJa*}l z)@&wB+wZp|6J1T<9Stlfffr)i5X6us&9OsHj3J1`buo!bDb-|=KHUvs~V#q)V z1Ah_*Kp5ai;}`+}6d7*u&K3VEz4g3ZXeQ|a0b>jatB&8W_~a31-@vjhe$N(R*+3BP zvx3SfW(1%@15Vg|2B1s|4I&{hhJveVH`onrhkTw{nazLu9`^!~$%67w0k<3czMb12 z`t5`-?!&A+c{Su5Ls=i`3yBq_xnC;vlKSiJnZ;x2{n)3X`jvXDtw+_o~IKu|=C zWr{62JqE~^>zx0j22Ut0*Zc##z6Zm z5h&4!*ib`JWEDnuIh0hXd`1d4t-(xVGXRoTroh+Pa1l;2j42vFia=^)H^Jz)kW@7| zPN*Aof~)RG4hDcR>%^1+(Tk!1sQbapb1XYUVh1Tm(;KQPdhNV z;=>tDy^?h9rZG(Sx8Df}F>d(0xQ#R*7cwZJ-YpPQQ9Le5(G)Yngr(bP0{zoJDgBv} zKT-grKwQ87De2b`jBg14i5`(KshQ;pvER|K!-O?Hq2YyWDX~I~CqJUtC`BvDXAG;Y zA1MICpObciRPQLNS`?~!ai`L-3@|Ke1z-!3M5UVBp0zJJ>d51k9QOLUwJ)rDHY=E&6^`q13$mF^q1XUE z3?I}np?!p+Sj$Mwiy6#l-6ncr`j4Pu@n$%ezE^p6vGJ&5mfd#SZNIqjm*DMbA2Rsd z3%~r;FJGcxP{`&Ajm<(>i4o+2+r_5VLOxgXXzq-0*WY;K&wh5plgl4@{Go>cC|l(7 z79M{6^*@~0(WVF{j2-s^lYhPS7WF3r=>d47#*X{W_pTW^d~n&701CJ`hV=iF9(phLSe}fXI}UHZ_k+A;W)l6bSw}?avo6;DmPH)pL0TA)%n9OuK(88 zz5(0@ucv)z%jdsx-KCeD&rk-y8ww2~+lWdAG7OPY3Ye9%vPDD=04>c;BRa;s_rZoW zYu=eOZirF=5kGL@-0Ac7UHjVdefM9q?>^JKK-oedO1(}MktMhySoiMx0M5L97PK{3 zJGv{vY@ZYZ)M$q5#AK2V>iMo&h}!m3#|qQzA@!UTl8u)^^3GVcguG}Vo}c0c{ZEFm z>CwwV4TJy)q*O`;M8d!-Ex|(G!I1~bcU?Sn>F2m@J-zxdLZuLx%>@_tJ$a{;a>=|C znhS$^sylCa`1e~nH{}a?8AxIAzEbZ2a}Qg#=rm7yLEv%5`;7r5RuDvnIf#Wb5dd%k zPKb!eO!|(An2VQPB5Bi%h!Lq^WR;G4Gs2rpsjqNQ;vmUHJCotkiK_t;*uo4yfvyc; zh#qyMG$Lj*xxU`MchUN&Uh z;xOBB`VWG8OWlwNS2uz4tt2-8(Nu!A~0zZN1>e#A|&p=Q>z*L|p!wx-e`m>L{ z_s*M}@A>^JXI`|L2ZEb4FzVgzh?Hl?= zPjAT-EdVHY`GG|frw<<7o?G|&)*TzmpVvc|@HcTv7OkJD!8`6m;^yHo${oh-M)wLTr z3?oZ$ph#j;>e6I0LWp8k6Pid;2u#Er0!aNr#t5M1dOoS~t<9${n)mj$9q(=41{92J zDtz{k0~d^+c+0a-?ymWc@{}bSn;M-UP=aOhwx?**-o2f@58{s9;&fbzM1E%+UVESL+$e7M#M+gJx2%_FcIbNZOA0T5{S;iQm zB9J-@K}j8%87N}}G-DguC$&*HDFuKO08d9g#2&Gvm`o#kFr{mf;D`V`DRUXSt+k0< zcm2m(cGcV=O$`9}=9V3AeDD!+&N#0DyuD_vrTA&*o%@SZP5=NG;Q4pfqaSGFbj|l2 zqWK*i^H1+6pMKK4D^_3gi(h}R?!A}Zcx&7*p%oB=n6XyAx|3>nvy!8t2?{tNG| zKXUfemV6EoKiu8<;f9YJi*6pi4+;GaQsSTV1!1M2Z@bQ-IW7>zc zG&jEZ%9~DS_t6)g|Ie#Fub+R*^DkkoMgXK#sI_orS(b5~;HdV&0JLG#mYu!jkxfOP zV0+1V_T^VGlVgGdfeb+;DuO^M#?bW~)(e|=bxoK$UINV>-SNwBedVMpuIX|D64^r! zI-g*5f8AQBNl7~Z#r()RB}npWdCPq16KT=XeGtgwdCnEE=4e5==vMhg{;>@ z5dAr!M%TmKNPtL1qS)&1e5Ln=2f+1MV-5nJA#x72-k#iygNB{-4VGyRDmz&w7eXV( z4ErY_1*qf4DBM{9IfniaMi`}NAP{3VSIU)cwdH^dRHb+4KYo(686hViV1Rb6_Q9IY zReu|F_*Vk2LeY(82>WXflg+C z^za)Rq)59+&o6!&*o5?&i*q(9;ru2u28rH>-HQe0rwHqiLr0sd#YR$!lozVIW8g<6 zUR+PDk@q(0LLweM{4wD|GZ#d>r=NFBK+;?nlYRWecqM!~Oi95AsM8wIbU$h+LGp4+ zeM-J@z;}dmmU>Y5N=#lBGh0k_k<4xJ>NbNM(tcQ0&=^}2@pRE6;ujGiGeH%}`M~Ij z`fqYgX<&qjMH}~fp#D-6#*(B%NN1aAfoe zG<8IClj|wQLmm}3+!#l~zZeZaMngj8js(RL0!S6EW+B-1Kl|=GXPvs@x#a*bb;`7J z&pAOTRq;_U`0RP7j~g}Wzys$?03h@wG&W=|yYj2~e70>+i~nkf?8q023l|=E_>y^~R8PremUZ}H2RZJK_TP6t5h3GlAe&km z&%NM+Lk>G)_S`9ff_by2e)qfIdHuE5M|HFV07)dGapT8MnmT^{TloVPACME&S(5oI z2hF7biNF%rQ+3zA`;MJyojH9P0e}J_v~44S7g7r{wc07M@M8IyP+bPZH2wK>_!f+x zle)}&N;+o3-&jA+l#;@+0j1xs30x4WJ)sRz1wrU259K^zs21t1O330Oke=(nX$M`% zi7$WYLCgUv1{|%t{qN;}BjEc@TYAS6e_p@k?P8&zq_QkgE|q3Yn1A}x3oOAM#}!;q zXl2o1CJ2eKHY4cO}k zW}<-9l!%RiT4?-CJI*39j^q?3p=#>+X{HUN2ndOkl2W^qG2GTr*PX)9Fh@W{p5rw) zGz@BQBT@+1($czZ`;I^U^_H9edM79~a`Z^oRWb+|6M)*ziU6p5WeJwGEvdBKPsh;5 z^u|oQivmJKQYt(hi%>Kji;0*B6ong-5-1(0K?s2)MZ_8Eotr3%7)1a=MnFiM5D+;7 z#+j0VPOz1d#*H5Fh0mS)!s=IRuIqWO@&X1x1Ocg_OM;a7LVniFnHxX+=&9#c9(Cjr zAiX_n{T#-#pE8*k)R>sgkS^*$S@?kn5xMWEg@;c(cxoX?A% zJ(cGk+IatcuN`~#oa_E@ED`P*8BT>-bdVdLU(o5 ziQhWsR22b7VPW%{N_oQeq?*PJ0)jY6dMB4>FPR_#;}|iJ!ibD-9d#j+gaU>I8HAFX zP%0FP^dE+-fdgSa+?b+2At$lsyrfZ%$^P~Ij zb?B@^4_kEQWe@%KzaRO?=MU(eR^0T)=HLG0-ff!(&->yLeG}WaZ>kCj_GnPU;UEB% z5{1xP1qPuc074SdXi6Y}kw`Gb&^NVh!Qx3zJ-GVse|~eqaEbu(x8 zWFGQwd7SUe1M;82-$y!k1KKEb%T$2v3l!VMcjiEDkbw-P+`MCWMsG*dR(N^!#>!}8 z`SM-&o4=saY^>cfP$evdVMj6OEfqs46Hd!v5d@;ZC<^vpJnw)-3!i^|jf!c-{F%?J zTmSf)RSPCfJaO0EN9KpVTKfR*ZHcVC*5YF&DZ2jEi*QgW%AyMeUxGH5$S> zdB~6wBGwYs+g{#%@xrLP^MQN*`M>jKy#LUH-dexue{Qqj=N-~agIcb_&TjccbI zb=XzcU;p##Z|p36U}i`0nbqsR|NASbUSGM}vc-KJk4k2cYu9ajZtZ#jaK|&xe)p%p zb1Q& zVfWByHeW*@895LD*4elG0J)DizB*=eP>z(b?nBe`+@Ka=L4g z8v+2x2p}DK`i{ms&xPf7pp=182F+@nd#CiD_{qYAMM-6w42xz0sZZfFK^Ou;Mnn;z z2mk?CL7Fh7DD+}+WOH_>9;iSmIjvC;^c-?tyy^APd#^3^^dxD_#4-$%(a{|b-Q2hD zsiH86;|dDtfk;b{Y>lshXdc<11roVDb%vra1Dv@CT}B*3GxW$!AS}#JM4|ZlbI*O^ zKR*A!qfaP+UFOYs=)t?nZ5^Z%DbVM$r8T;Kdd$zDrLm`onYnjQN9_h&JkFlM#!|=T z7y#_fHoj-bsG|K%2KcOicr_Jyxi?6OSr7`QRE7mo@i#B|+LKQ|ef1x%+I{Z>((0f| zn*wSRkyQaZc;!#({MA0=VAibTS;E&!uPX?3gtNmj(}^4e$zSL{!BWM~hZ&+dqI>&M zSfGd=b+S(S%xQg;rXJ=VNGq zMN(``f%P@1T?dD4+9Pdaj?{xMDCn1fQlO7UL1&fja-`3z8v0g#o#Qc-^M z!jBNZK!p=Ug&^8G(CD8~KJV-k0Zz2-t9m^NBT2-KL>;ov;zRaX>>f@GTLzouf>4S{ z0Dy|)=COzDaoGM#b!K>|(ij+N22r6I)BgLcICB3LRRz_$LI5Gdks2L$^xh@0_h60d zO;soqw(Mwhc0}jB?*xDo^dpiq9<9YP2oOPm001Im20=BZVkAF&_6Z+8+dQ|utpEUT zuio^`(@)J`wEF@3?L}<;9|54*H6|3WZtaE#{`pYqf-#Cg z0FweC%tW393dI!2Af>q4q*D)hU!szGpS(RPnc6ihgtt6=-SexTd~?lfot^E>T#&)Y z=;(s!OFnqYXS&-a)M}$aVAkkZ>SC^coORv#YXBX*!$6`yA%#SQPy~Sp1lkHA^mD-e zB++lUrCQqy!Z~h?;c?5$E;R5>v7VJ=1tH$e?m1bSt&(|0f=?I9Fxd`*OwW@&Qly9gK}z}hs*O)P`%?F7mG|3Y+2jdbaYBmHp04%_KKPz<-hC43{R}9}Ol!qU)AYf||Mlgs zeyda}I!;^B@WsT56OZ@1`^aO2%qx>eWBQazqk{P4H;%41YtKHr`pVxw@aOBEXfK4L zgH?g0{+V4%cAt&{!$3CTbfn(=(YNkINSf8Sk+1;RGCcgDPabgL_fH54I5aw3Pa5Fm zJ^=t2K}kS?#DbXz}xgf!*OzQQ@5JZRhY=FNY3 z`k(i|+S4UAZ5-S%JaF)FOH{(|JO9898wPH@_3;;8d}r#kwzaQr+PuAb`Ueg;=CoZ! z08$9Tc%(L%QX-@wGa-*QMrzH9iFgN)sA{U3D8cR2G+M32X+kMSZQ_t47d?94s+(^3 z*9$Lf2#H>QW9{S#eQkx}z|cso7I#3AT``!+CVHj}tmW`*fW`5?yBp)MfU`7wuH3^R zMWMD&~Y5hz>KnJpW(UueNM>)8MSB!VJl zfOW(5N_9tAD5eUq5Iyzgnulk+x!?Q+bNVN|x^asD0gP#ylnS8~l2aB8X{rJl^mTOB z;^x{N1HI+WhDzVuvUO8jA6>idkcCUy+uD>ObEX^s153>(q1T8DMQrS~(xp7wVKTaq zyR%S?Adndtfmt!JjH0L*#m!U!#7WXrD$$1)+eNZqc1tj^H8cTE&-gMxw#h~2wIOHF zbCBMYX|TP_MI=lm2QqLoPLEo#%jqW^b=|c${OGbPuKnxnJGO2Gqm;d&USKoF2ycyGiV)*vD zwZmJs9)0*>D;F-@Hncge*Q%9KB85T_fIy+rm_`O5ZWaKDRBd#qT)-00mwx;|zg@C; zV8^yiZ@#wME=xc6p3{m*X}SD`vrd2Ot+$?i?6K2dczIH9_qvT6(pq(&J@@*|8K+C7 z_F1xU{_-VHJ@nx5Yu0v^qu1Vev%lO~iD>P{&CNKK0;%3is-qM)Ln#9(iD<#(i5Gt4 z1K<9^Pk#UVKi>7|Qvr&BEt_^(w&b~||J7(Tr7#Qg6d<5bL_Ougg&#iW;>}wgx%a-~ zUwLKPgx)w#H@*CFsk?jMz4myeUcKyBSCmC~$%o!8g&@kYz|2h$z~9^hoYLEAV~&&K z>XM1*8R^8_tk2zG89#RN*7~ye!-nMyEFRM&di}sLZrg_LluBiLU%LIJ>T~~uW{PD< z6#>dP70r|<9&l#Il4B{UN-69#*`AD~bqD}OAfgf=Q&Ity2qB@|2`N!hN3+xe5zTRB z2mnkdk($G@)Yo^+Co8W$5pQ1y#Uhack%pm2H@-3Q#Eo4?ele{LV`#{Yew4$9PdncS z496p>^;NbO&6+YxF82O!Z7%}>Ds3>3B|=L0)o*;`zDJ)}x?s_Si4%Hz+Lg{e0-G3_ zrnk^RNdR{q4mbp5O7{T)%(nG9DkltW?co#lT08$hvq^=;AzmGsH{)^t+Im~Fw$Ybc zUG|gZh0#ft2IztT8DvUIh@e)htlPNdmDk@H9vXCbky-C1XtuLA&qaqqv+u?MshRC_ z`FfvA=opB0@o%1w+;X)yEy}Ox%|F~IpJjU1)tr($3Yzerb)X)&_lE15rd&5Hz5QqF z{`o_-0XS%VSvZmDF}EOrz_0T%t0ru^KQ9|zZeiS)9(!wQ&XHlPRkGR-FwQLo)S^Fs z8H;f_cfG?=z45Ex=Wq=sr{9}NZs5Hbt{otz!X{wP_Aqp7?w#bs%m8SSqgj~gp>(Y3EIRu>wLuS3lj{;KFMzdLOgc6Bmp%?{H zA5Ra}S{$b&WFP{mADX7HaeGrSM1@cw0&uYy)ElZ&tx05kc3>C;VJJy405jomqme4T znGmLgECMM42GVC?3ry2g4c67*NL?>jj)EWvrDpEnNU|lNP|7eeyM6`;JBHFUr9vcS zAPBfr44X=A+EEXX5CKtyVGxFb0f3Qg_LNNdm5Bl=DWZQ7K2BNj3MTh1b^Xj#MNc}<&{8KV$6No{$x zno@U}Z|<$==GyU85Uo%l_)5?c=xb@+D}~P9WspFkC`Lsize2=m98;qJMP1jR^-Y%x z019G86pED;GNriQgm)kQ;WSC^|JUEcQYa(_g;1&FmA9X1?`%&~70RG8Qk~K_N%2D4rgVK0$6bxiZG_yy0vSAFgW$pcm3e| z-)%zU^_So5>FQd#bWwl*BqAOjsa*1{Z`^t7->$#*`eTneetUJKtGoNLCm%TO#8VDE z_>epPdTTSOtEd?jf;sbMFI>F1SSXT8fjLzvA^?*zYOi^!V_6J{`gA=#TyhJXfB}U> z>Bx{3Ti6kr?Lr`<6OJcpK0UxcLOc`J7B}J;uUXEJNp<#WA?z4On`xqBc`M|}wPvCz z;LAbAD|5RJTM#oTMXZPwFpwfv1bXjvGcjgn7E%;S^akZaoH8?)^DCV zZJJW5-e^c6-I_YR0g04BtyY`7bm=+od+*E{Q;A9Vdxqr#7=VB(O=TDk4GzBW>Z`B5 z_D)wUT{$5lhg;1$dsM<>fTf;YoF^Kc$%uG@xbxjws3x?((M4p%VSdHU@{_8Jg z%`?kl2N{T@NfW1+zWIwYZ~OBT&p)+(^TvTRNf&lZS+-){1rcz3iW_2BU!t5n0r+}3DR0u}UHH5%gg*X(fnlNQ%=MR7L z0YGz9Its|+e*^?6IZf2cgJ*p8yC?kZPtQI7!rE%1vD=IV7oWP` zUQs|&+|^$`>evM<_L`Am|Nv~b3pK9s0Z+WWAXpSr+IRT~3k_*g`j#mSsDA@HoIQ2BsP4>$^h>B{k4(F{>sZ;~4-W z2`v!R7#{W>)K-*;05VHC0fP{Tkr0P2UKq1Nkig`Me=5R2j}a`B+gZ-uvid>o#qvj10}0Fk#Ol zkNVI_$M&@cTZZKUyDuMFSnVmbrOb$^fT#3!EZuFF-4@JAnWIoHnK9+?J$5_cm?Qsu z>m5%&`@-bzjziCU&j*h^=IC9Q4A$Z>5R3aKTz<(#m;U*NXI_1MbYx`DCG+>*W%=31 z9<|G?>Dy}cg;OSd|H9Ay=$dN=-d;zel@Gk@l#`D+{Lg>8b70%nW;5=Hf_)awr&?vs z#7P7Y1yUlUiavDw5e1Zgx%=*I0|TX~^r_GO#~w@PeeJvdwRm#B0FXksH4O+*P0|zg z*{$tcU;f=+Zh8IXR~lQkmO9&4?ziVD#~=N^cb#z6jeouUmOEa3?UhQi*;y*sb*4^R ze8=e2Ems9IMw{489$Q#u)TkwE*W%#~j?DDPn+>)==zr(>bL%I^0laRrFD+dHMNoVF z(fXGW5rs|9TXsrDgSBJ3F zQ(SUz`z}Xdsf(LcLSR3I!s?Odw=Z8Q%WP{hfz? zl!K5d)rX|#O=IhfBJ+bS1Q~;pJSzuY5Wq}H#sQ{mjRPP70wILB93Lpk#6oME`B?cLX!lWbpSum8D zfynllh*@Y;OvKE>Td2wmz$ENpm0&lfL|r;=qIKr1D`U5e$wFqmUoZnJU_wTv5=4#y zDZ@}RfJpDns6&N>_5>BTy46N7&=+-|upR=o@4To$CZ!pqwnCt#8!a2hYu-I3@4Ef( z?LLvdPu6|NLRzgc#T=3ZHv=$V3k!|i-lRUDZ|Tt3kem%Uxdx46)&un&vTiwO9V-|k zGG5Q^volD+CX|J4s^`Fl>q0KbnLRmAG{_BeYX9MCTN*_005veVj_i&Vt zFaQ9AG}Ws#u#pgP1sF<2*=$A(8s=%F%!pVBgF<8or!5UL79$Cf)QYGxt6>mEVW3B= zVW`RWXZY7xH61iz1`G285lXYYo7F@HkO%@GD9A!2*>gIGTqs7m(L{j&jG`z>(^4sX z`Smql`sUB>x%;koV9n%ND^GscNvKq#o)jXflq3{DW+S0W4D;sAx&Hb;OzQ6q3nFd` z6oSk{e7iIT$*|jgBV#vvY(>oDpG+Xfexu`N#!`a~nv8)cnL$OcVgcYdotJvZgp5t% z$`gL~qnU*uioV{-_%;K8l(OEauivt2*V!u-F`H*uk7!0ofT%c?C=%7cCZ2iBM~LWw zf88CH1qLVr?C9!DRT>7e*=%;U_nvpg7v}aY8g33rArU0$?P{{+B$>H%Us#W(bshnz z6qVO)T01y8AVUcNL_DE;a;Z>ODq)v(&|S^M$k7GIOdML6`|nMtcNk6!h#K!M-&3MF z{GAzri7|jkl%x#OB<-Iv6(AfMSU+?2jBBpHx-v36acX}|%^(a%21n8wY}&jTF=#J$ z0~9KiYBJKKn1u*CJ3159m_K*kUvIyqTrSO+IcuehpSulMxy zPMS2aQLhUWLK>>tDXj@XN(>tHdc9f!fYG6$Fe)fww3rtxh6G@Nn50Q}--I-2s#NKt zs4c|Pd&Lpxo&qTbdw#J&NGK3dG!vRJW#U=yI!Xiq5Fvn&QhOWJhXJG1AEXSL^_oi3 zsr?fGAe6d*PXL2b9BvwoIowQ`1qici2%x&!w z3ec!f8pG(Y>YEXL>gz|GyZw-qRabW*YKOR{>eWO97)1E73y&25iXe_TDuij1ci(sJ z?{5AyBPdplDlJ?-^(R+dKnwkDQVzVCv|uU;S{P(%)h)1dT$7+P zkQs;kByfxAayE*szLTy9MLWq+EdyWxyNyCr2 zKl|%#i>6IJYUQqs+}mCZBy<-`?LjC*5ro)CnklFk)~reD$%Kxc`Q1Hf7%rdMKdo!O z_Cl$%P!bF%TtSj4C~FIX71O5*V@KF+Hu>+ZpaNFjM*>LFl;VT|LWBSiWI#wtDFR(6 zXDDTK9o;^zqGjX0ys`E~#PgFm{DjTd%FAE z+Ut$xdyY7?9EPK5+EFZCa_YOzJMQRey)mJ^ttX5C;MD#13WT6kbrhq|pK{zsPC0I< zR%L=h6m>))r0Ldbefp$Hzx>))6P2=}dYVcpW2H_x^x$_Lc4$!s1938G(xl73bxC_v zC`)nZ@?`_Vqs3BjLKKDoLycxJlEgUDjOX_E{q#RB*xIN!leAPUbcc~rYM@e&q!>-& zqgO0FaQS}@Rcal@Vpk!OsXAcSWlU)lMU<+qf8wJl5u#|Msvx8ZkHpFO#~pgsF$Y)U zW_zL7iKqZ>yXgpppM0n_(H`zJnH)xY79Ng^oWR?4EE5m+cV{r!Ys_Ka zar4i{lDJ$o0+1468>ibFuRo!Nhp?+JO%x(hoCu-1_c**beR*0NMF3W0@H3M=N(vZJ z6ieyW*EU}Ft)VCH5KIg~q5$u^aq>~;^q+De7CO1v6auXeBqklfAw;5h1i}gJyB<6| zZI0Tsj?3jVNf|=LSYPvM^XV;VzDr!6hi#FmQ;amNc|xaox^ zE&&K+4hyBITtX?8q8W2%0!E|5JBm>hc1_?$Q>97JRs@ugG}C4p6iX0>0K&v-R7}mL z4)KYoAY=h30cMbq6_rFa>atV>49s&?%*`ePFbYy6Wr*c60Ge84)ky0#1R>knK_Jwt zX_5$J29V_<2*K4F5F;?kP?QQFkQ+@(6-p_i0)!EO1VCU?jV1#FNMw+uvIGf~fDj=R z0R$*c(lkyLkpciB4vUctN&qo8tDK~*p3RY6XK2P1_&gh3B@!45i9YqchP6(PuZnCv zVHQs@VF>FiZ8XCD?jS9?*1b5+xG>9hPS2(6&HmN@m!a5cq1@PcLw+LVqMZO3_>ttD zQDp3s{V`-ObhE;i&UmYK{ypq*wf)|;<9S?k&DyPhT1-|8>S60f9U(HkbyvDPsF{-a z2hkZwVE^PhlZ`Z^@3`0G=DpUWVYWHGN1eR+9iK7QxVSeadSGtz7;8dl`S#E;+=~s1 z00NY33UIS$QN}@bjc1V;t7YT&6K!G8IO9NK2m-ms-YeTmrKk|53JImIT-SoClL%%_ z1-rn5=N@fI7g}xAvh0Se;Vv_f*?7p(iGhF8Fh9yOf>ak#_ZwoVX1(=Hwb^|0omGWWDQPxj5P;4m>+PnQ zw6f>{5x_{Txq9uI?SsQY1mx;@96n>)Gjq@?Dc1KJ?#0b`-t1|M=FiYR!MG&7VZ6yM z>XM%9rI>Z;rBXyj;+=U!A%GEp1PKOUfhYs1*o5u~bEP%Luh`Y!%#fLXFu(a1dyvA{ zvCKLfDH8|`G8Ab{Bh5G}iU~8yD3DUB48_18L#eBZSSSUM#H5!ZGXvNNgTR0iRZCKV z=$#nQDjhDgLk!XjKr(yz8PYrN0sx|bW?dmdp%a;)-bj)WKq&!G2G|&-rbxneC`#E( znzbz;LK%cYGdpF4x+FvBXf=okm=u!SbuALaG-)=>8>x-&$5T`USGAaYvTWTXFQYv8>B-I;6Qwl{zRB1K|F%p7_h&f4lq?rU# z^o9ijR>UKfDgzXPAWapesWAwkYsn!L5{XqB3kDFPBruKR9f}KqoYv8%n5)eu5k)dc z830%!j?|mXsx1sVf*?_}W3<93f6(}02 z76qXUF(uNT(3f>jRXsd7evN^-5Pj7edl6>e=S;Of;U4qKgIxPKH{q~9=NoI$VSO9g ze}HwA2!RxfQhU7dq3T=Dr6dqJO;|>fD#LA)XLK*wmq~D35kUw5fPz^URS_VPQdsQd z=H^W|e|P%>H+S_<1j)pr5Cn}{y787PMVj`X{T(F&qF88cBa;pTW1T{$J8?De?w~Ubt$8uQ$MGh`9|E%W#%DD z0wWX3aA0Kc&9~l6m0;$(@4B}jqiIw7PQgx-4NrM|ui9p$n>o#saX2#cj^t-fK?+rCeEIjUyb&>NXM<$x&Dqk@PEQ~k z9eR8Nzk(54cw+Bhx9JaL?Dpu3F0szz63Htcbho?4vg@6;GrE;Kx@1fWS2st*XpeWc z2g-O>H%C+$QzV&<&pz4Cz%udnspAu6oL4R$=9I-rnVkUGIiLOAzssUbhYQRnv?J1` zOIepOM>Zdi>{QZnoy@{C?t49QV(95C-g@&NSwS&^X3R$0*r`2|FJ+pdcA-83>V=oq z#_OK?d1p6c(?aSvg$y7CDi9*z%YXjElvw~(>g2MtrZUUb-|26B&X~pLzM7i2u9@EF ziKCb98}iy9qv@j;e?rh9K(hq~+MmqnGQgzg5o`*P2!OQmp&S}jQ>XR+_IE!Stw47N zgc1gan}nf6RBVl#_ta+0)w+@r18Fu(G5_vF0(}W(aHYuZH_S>3TkTmcGKXMG>g+#e z#fn83-V#8&6$pF3aL(}P{*H+YRh4YXkzn9RMk&Q2E}V1X#}pmBFDU zbedyG`UhGs(taLDFFNi5ocU#Y+4?lkF(I*0fka+3Oe|hQ8fBCWVKm7G?fBk*u zob%Q@Z(i}6-*)%(p7HK?Co#z|_|-2iyW?-SuUxrDPz>++#{(jao`3H7<-6>$aLN4Z zZ}?+dq5bfqj@)J0@*8iut{@86-gd(mKX>8#KXh(ad)t40^9KM>Y%8B|;&I>p?$>5a znbnA^<+k=W-(2;rZ-3`6H{8T2PnMXz0XjRAwBmq(Z1#2Xm<~i7#|Z%Fvr|n=V9Rmrh>|oem7=ZNwte{<-;2Tk zfrBvAMOaLzXVL@=$fUz-1Ol;M@Oj{H^FrctmiiJO3Ys0wXtL-0#b^SltJlw za7*8;1jbJP5E*13q?AGkVfHRS)BhY8LO{DkGXMjm%C4Zz25m02YG%~k`4z)4O6A+=v z%^)%Zk41lDFlBQzjQaK#nQNQkrM{m97mFJ(^ap+O=X3p$=>-8;v{nIn0a`DKM zmrtJ4*{mz+Av`;W0BFf1GFvDz&SJM5qrfBD*w@ZD43MENV}$M3Y#lM?g7p?!xCYtx z6B%T)xZ&UX@mw$LZzeU%&WN9)0&fIg4nO(gD z!_|Z5&ks+MzrOpfH`i|rgJ|u*$Ypo@ecFV+a;fy#+iR-z=5V9>(%KCH!^8N3YVKyL=4hw(#LvVzhWqed9=|)L@6+o($pja5O5%nK-QB~F(aT1q^^?CQS)LT z6md04m?4xh3Xw=PQV69)wuy0PbnQQp6p2!C3J5Hvl+3jxWow~ySA9!c3PYu6xY1x{ zfdU1FVW7_=P)el)QlLj*&`&ieHS=Xw9(Kyi%qe2-a@GYyXj{t?RbC5YoPF+N4$4AK z&Ws-Ful?D6cB3ar*^hS07l`Ki*Xx_!rZC_%PDyZzm?Wj?ON)~hQgawt>9dKD1V~|= z5g~(=G8ldNp^@kBY3uF*5mOu^BBan(h~g6Oc=V3;T@EPkai$vG!l*ON%Jh~AfsmQf znr!cFTe9EwyMN8iCS#zK5-2FC)Yra@R0An=shagJ8N4>i*g`O$J((>X6MAViv>qFM z$Yx_af*C+bWGJ-V^@khYcfl8A6cW+bzWVj=e&ZVtKmKrIWc27GjywB#sS7^$<%=iwc6{m+pSthiCvW@9^+%m}LX$ucf9A6nz4^xKYp%a) z#cnHDMvvZk%jZ9RVOv|r~)^g1FX0y2_gj zz>eqhu(bo8jCnB{+Yt`~85HKmKSnflTFAo?<2}}NKEJBnAGrPznK^&>!%n8PJWezJ z9%W>`vDOED=+MH&olNaqJLVd9%&!xJaV95O%XW#4S>MqnXDAf%Ka zQ16k*I)zLK#E_(%CQSb1!~<_*dcrV<4UWWFMV9W@cmY!Hn=z!;fXRVJ-;lAx7p4~( zlF#DX8QAuj>GhOtQ;y=?(hc(n%s@^4N6fz;V?k{fiJ&MH2~bM7dIc|a!p?Isw=@9= z`glDMW`5*7+Uu0HBH67rFoXa=DIg{xGI7ARm=?iCsQ?k#z6Z!h7`+|Uvlr%iZu@MP zY}zSfjtTl?Aib;@5hVhcVhFN5G0`s46BE5hs9+PELc0|JVzrh4s8RrxQAiX9K_Ebo zwQD|O^bDsE1{#8EKSmTc~$|E!D@nRx0382m7u&&BLQ z_p5W`rZB^qyxg_pS{2(|HYWx|(MX&96J|{6owk1aTOh+Qh_-Cov}tI~y#A$093!~U zAo%9ps4ofz4rCOoxR{haaKa~)QV+lQfC`$aO3pd<;|DG|wiZ`YV&QE#mBUp#vAn*? zRH-VJ+TPmq>ZToQkXay()@yU7&FJgsV@ipX6mt9kd1eeUNZIN<9bGar;#1s(mB9IC zvtTU)kDeFKzVL7=0|N-elq!W%u>To3TLA z+169xN)2msX3tr+%d&}+`ja%B+TXu@%Z{$@?pd>Dbai$0mU}9-`uevwbhq`U%_Im5 zqm|mo!02x;zp_3$y5~N7cXxF^^~B>h{pqH9z47N8t|@VO-P-jZ{pbZxKJw_&<;xZ? zTKM{#Z~gk0zXgDt4Tf~1)?a$=TeoL}DQGE?XHiyTo59b# zwq=jCJ!rMKo&#ukfVLKzT`t}_Hhnq%lUlztISmH0q8z>P=5)huk)SJ1^^zZE0bus9 z1R_Qh%sez&(Y9EbJ>#;9c+)7D!X+jMBnE**1h!jxdm%X!2s5kjPzW%mrkgwlibSbe zqag)Ii2_jw^j~(Hd6Sb-43sKF0`N*^w0#zV9)g7w?1)ChW{(z=Im~PKID2@wQhguT zu`fkn?X9~k<3lh=D*7mJtNTJ(!3Y8eh%q?dIol3?@QnB_;EnIe*dOQ@#I#g+m!+ zAiFbxK*>m163^|Zk1}!u@zI-0hJ&AE(>o)Y#1w-NNB~S$T2M-X44gE$Tnf)V=SYnE zUVCl*i!ZDL5>j&iq^?hV<>&y=Krg=&&RM32lmaOoEXf#UQI1!WZ>2HQV25YWQ+y`{ zWBpb}K--+V3EdwD)-p5eZn9+K42I;o=kvrf1(x|O7R$e-MUvP`jFw+hgJwG;oN_W3 zWcbeJbq~Mvda1o_eqaBY`|q}(ySvtCMp0p~TH9yNoSt`|@%uaf@$?&S0zf5BUR=G7 znSiLHy(kevjJi5IYNL(q6ui1_>(-&h+({Gq+S`IKcc2Vs(? z!fiwlV9NBw8*dIZ<0yy}F(Hs*#iWQ8fC5xbgafflxI1e_*8t&Yb(oPDz%W}>^?=K|*L?{6=&mIOsGlrN2017D) z5Kw7EBP4@4lZF`pgcQi`Tu0Y20p85R=yc%4u%y{Zh7mCc%*HGxoR&pGfkAKhf&{3i z*Pa~%DYD!yGe{vUUSn%VEp6=o2>?+D1O{{XuM~m-D2MwE?GTU|gb)QOTH-hep!Yh! zR#CTR20e!4uw`a!^M>2lPd2_YcZ<(iAGMA*Zyv|#BKY@@oz(iD{mm+^jmY|KA4jC^ zd$N7As#G~D5D|mmI28oppkuqZKH3q=~YJ zrU0dBScsC^j^P)cXxsf%kO3=&n)$@$4-*1|iXo-2Z+2nQ^xB%$(B8>JfXIsCEt_a$ zD~27M)`gUA++h8;9_U#7ei0O+ zZ+-8_^Ovo-@5yJMe)gsP4?V2h+5Pe}&%F5Ns<&6Idf>r_7A#s??&|o*eUClAYVC1{ z9X4gw{3joI@B<${Z_}1-E0*uF$I6v!*RK8j)z?1y*i+a1@i%+ydk{dnYQvVbTL-@V zz5niLZ<{}F&Y?#f)zjUTrYQiR2;;c#HXHGzSFPc3xL zT%i8ri+hVd&vC|mKrq!m;xh!+tAr*JqD4@{+NA{1?Mc^)C;Kb6S}< z?YZ{+`Eou>>*s;;5(yB1=Oi-h=L_?A0YD2u(Eq5HgLvhRJLx%ig#@jm&880i*kH_O zTeFt|6qj(|RwHgNL2vkZFv$QwED#HkM2581+_s~!eRF-s)@q|#M=3gc+b2zF@0k#F zbQao6VN6hO5}Oi=@!6cW&aD$~&lY<$9Iq*NnO*gg$vVaQg*if!0s#nNHxtiDlpXWPIq|jC zwFro;Q3aWhb}kReh9c%vQgn3DVKSSpBMKC-uvKGVVpgC7f0#`ZS~N1_A3J67B-^}r=l+9lg{)Eag;$?mJb496%4a5= z9P1X%qlqaHK|QTST>9Y2|Iyjj^Vsu`9e&VJNA7+?JsnAz5CyXn6VoL7LY0Aav~+PK zWdJ~dFTVNgj*+c02!Nr{OlC};*VW#WB*_@s<`Jcr&fpd|Vwi-Ei>>zF@22CTrDZD| zV(S)Iqk3Swp(Zm302XqvKCFZF6 zYH{=60}p%Rna3`^=*z$V-Bn-v+C}G_{UQB`$De#)zkLqfYwwk}+;p@4=B>A0?U>Nb zflO4|R)BK3z`*5l;VWPM+$9%(Goi-+{N$%!{mR#$d*+!n>(1j~;Zy z5m)`;H*==W*|crlCqDTfx8D4>WxFl;@W;*_ZH(AM%Es7h`_4?gbDZP+kJdctV6&}@ z8Vf#h@|oFDx4toFWSycJ;)07GL7vzD#vge#sn%p=cQ}Rc485~^_Sj#cm(H_|WHIZq z3mx#u`7!`&HCl>{jrL{P&~g-+9n*4@&mk`B^N5I)Qk?0eshHFM`L8owVek!cJIc^fxC$p0=|40*wFD$_J=Zj+Wf$nCj`V zjrSSeISA+dbsp7QOJ8#l+7S8?GTkkyl+8eKL*qEx#PrUhdGifpr zAq_T0H;)V^N{KKOe%BEMa$7Nq0iz%yW=2%R$}YMmKt^+7tPmnila4|pEJ+9%7%8K_ zZ@Y7>(jdbN0)wf}WwOCKaMW-0*_M&cYdVT!{@a|$cnHVlr>)X>aU!FnY_~OI&=D=O zbi-d9!j6aFLi3rvXWcT2>xTx-9L?4UJH^k+sJ+}y1`cw-(tm_SAI6`!&>Da(LwAcz z{AE{G;eA}T4V~ZK`Cm9=k8ON`C4TE!R zK1TK2c{bn3y6O!kODsV)g|&i^U2XBC4vm3`m}45)EMwrZR73)SoAt04~UQee`+ zFhJJ+%AR>809c_!PHV}?HcCiHK`EMinx>Bs%qfj-WmQ2DL0ZiVG#UuV0BJ1Rd!p$J zM&5i2Q6MWoL>AB(R+VjXVjm~99MM{`xE^BijF%Bn1b4`w{hF;s^j{wTof$>%5d_E} z2n08(haP+4p~oFRb;_I_gF|=R@|WrJ76b5xx8ITg#ZvjGBM$ofXFt3D0sF~97bLa* zzKJKDb!J;v9{}8a``^xd|GBr{ao0r`e>DsvDL53Ov%BX9Km73rKlHxJ@aQS0o%ZNs zPxN%OUw8dAM;v_|fcnS>K5+H*f4=J<_Z@!1DI=p>zWKfH1VQlCi!Z+9l1l*L!F%pL z=R+U<`K6bA_`LJaKmWX|uegzUchBkUdHvPb z5#Zd9e6VlQr1Q@E$fhmZPCNCKUtRjYlO|6G;Lm^hGynUmU;W?*KmNsK3;L%_RZIe) zzkkwaKl91=zwbR$W-hLcY){h!07~WZb=O_}lmGq2#NOUN{_(eaA8>eWV6zaC5eZo2 zDu;ak?0K92*OzyTn`?S+bMwXgeTX);kcS7`RiXq^#S@ZtK+fJ{*&Lx3F{s;@k=`GqImS^e6Ep>3l{BPK;Dg9t>a z98Ku&Ubu9|%0uQY*sZ_Z88s7*Q)4}y=Rwya@O#C6FA)IkUS&dKDkkF(GW6!7BLoD2 z!nlR8K|W~ZQ44>(w|S4_h?pZWwtQy40e3^rzx(dSXh)6)29IZ2;vq@^0AcqL%`zrt zg6g_xrvMhAFoP6G0AU~k2?S^s9Wo;;Frq6Ek%^;70ze~SAYg0KeJmyXKZ%WFq5_KAPxfvB$$O-F2K!tgCo`}a}AmjAW#xBfIvY~mq-#L012=m zH747!%srt9rQ?MikxN76m}4i_*^JB$$eXD+$#m+E?kd0*GnEh2WuTQa1eQCk(tBCt z=6{v_%bZmij;(h0EHRJy+D})sz7Qc*@$!W$AAaf%0s`b>q4?a(PaV0}Nj>e8;v}{Q z502Ae$ch1i_BgJ|Rhya@4-L zvhjs?o@&PRa(i2|85g3`{As(E3vIP}#oHLmbDk|MF$2y0+N$B+6|FazZ_)KE*I7pj zXJ-+tF-FslS$i&&g0$I)DFJ|y(a|_=)arF+PT~}Rfl?v@MWP@9FiFxRiFb@{>g$-e zZD0og)Eo6UPLjA;Zfj$pBu*$*%nFcGrI>mD1NXn=;;#%0ZjFj~=6m1sgCG7#rPOFP zEA{HV|9qg_-ge$cKR9Q~oT19Vljx(81(?Z8{* zw8fu;pC-%PRST)J8IfJl?&+ZEh<*G2fPco3QFl8!bEFw&`q)zAXS5|VgqT?gKemU$ zgF>Ed@jOFDB-Yl?J<$y|R>}W8AoG86CW-A~VRown&kLEAb^?Xn=8YK`gn&k)zGmI} zFf5?JI7yuHN+A&SF%<|>*uCM9m=S>ph&g3qrAVpa%7{cUp=aW>{vMSQ1j2c603ag8 z9@D&6E=XtXS5Af8m1C5bU4x#AwyG!ObDl=&yo=b*PHmAIf<-SGb6XMkIH7!F%FP7b z2NBr{X-yHcT+j+XGih{Sp0e zo8&<6$$5U8U&j<-f=+T}n$DVK8KgAd=AWFsH8r6kkWw>2gy)^D1{#CPnL*5ZCI5rX6XcMdH52{^dpY}((kkoO zJM*jXbk`S1m-_Xe0Vc`g9IbIrp3G)`N{`oO0j#6Me6w0~*$K1XXItFuhvf2=F2?iO z*qdFu=brCT7PGhGSZ_~(-JLm(+yU^>LPPpfO$2>dpeapTf3`12LNOo)lWpK9; zNX=%@KR4>1O=*)kHQO8jqT5280hmCg7=;*>2ow^TBmd0GCKJ$h@T@#f0lu|_TvXuucTX{gW zQr*6NyGoNi_uCs02L^{4alH)PEU}ryC!cug2R?9i+-!9A^qhXiDGxvL=$U7nvETj& z?bx!m+|hf=sV84|!(TRT*(Rm9|G|fchAJrF$fFNkyLQ#!;LyTdmd=?w?ZF2(u35YK zu)`0ZHf_e^Pdz>|GBOR|-uoX+n`vL~#0MUIblbMA{S$j%Tm4RFp>6Md_FJ{;^_O3N zvk*mJ`qJko_D>()zMuJU`j;(Lm z9}A49y!w^fV{Y7w7)&y8-0o&piEUA$#|qaYZ$%up-smh&{x;75n&yq+(zy*b(8ykD z*7!2`^ID^exfG)%F=f1^_EM14(+BQ+>z*5)-LQIFTSsxqlnJw@PiNw!ktC@~5>*?m z4Q(F1>!l~}{PW|x@4xKi5ACyLuSqPRX-|mDV3+egy4)xq!$+_&6tt#S=;)EfP3&sa zY%@Xj+S=iuyvvC(sSY0m1ym!PjH@m8Hu5lLf86o5diRGI=nTYGz|D5i#lauV0Odb%rv6$w(QWXJY_Qn@s1-ZTc5 zfdJqcQ)d+0iF}Y(>RM zg3FtXO_F6kLTBduh)wH@TmEKtg4~FV3|p3Ebt^)kjk9SJCjI_f}qrUd`851U!gh-Ii5XCs^D;7nkXcCkrTyJs zq2|DVOON{z4c{^535IUgWptRW{^lpVmIUljoM*nBA@o58Tad@bE@zIZ#ba3Oni(y< zDk7UPW#xKc&53twruA-+=!_a?bhF)S^=;$4*j+sS&*OgdU4|zc7IL`B2RpsBF@CQp z#-NZ6tZNKxB>+Gaz(Vg`HDPKnVLDLkP5DfFn#Kr%k~)-ngQ*LtSmGoW2t=eK#6n=w zsHs9nX~9Z_0?-f$2>?K*L=}L{P89+eNJPb`Zwdy0dV5D85F&0?n_D-QWvJ`^Tgc<) zWFCi%WjEw>vI#lX=`wt0>hc<`+cieiA2t9o3IasHpnxSIPzXekDvAn4Z3z*vqqB<` zNL2(2lm(S0_uqBrZMWaCdfmFX*?9AZLNwE1ZXCS5ctNMZ`W$IB&OqzJ)syDDzzG`wBC#XV0dtVSsZoPVL!k0SDQ9% zUbr}Zvljf<&wsLI%ht}0^1#sG0SE6pY0{L(pMGR;aB$J$g%c-D1E4~& z1QgGjJ#F%oiO)Ru!j>(Yolwo5J6kDLAKp>w=mG#CBs2ZtkJqU*{nBSHIP=}7lS(9# z6cU-N@Cg=P(A$$62S{9ziIt@cYxvnE8-2GTh-NvUTU&xH%8|>HdvlbGwV*ef0{4r5 zP1Ys!cPqD7WKA(Zrq?+i>2*HCKK?5U+xTtx?iyNtfxH{e{~Y|^=4I!|Id>HT2nM!0 z`DJk>Xtf&SM>u`*dG}dRBJ$c~CNH^gVU}1L-x3;kY<#)Y1^&ccZE|Q^^P2yCRU8Hj*8KBhNkl>MPH!e(wcG9{t`$ zBEm+Tia^KavWmBik(hmh0Qy)7;eJC9h-sW4V-QLmC)GBWl?ED=szgW;6bfXHthf8u zSbyUYF|+SuRLB{$7NlrCr_m? zXD?}IffFfJ4CP}_{Ohw9eBi_9eR0nfUk?hAA{0RY%!H6AKv074ix>Z(K0Nr%Z(clO z`V?v;+CnQpGN8a$AnW@48b6I#^=dBnjYo|X>z_aO zBNtqJ;Qrqx#R-v_@ghqEfhPJ)q$G&D?z-=rUq1h$ul?}Q{dP%Js&m!=LSKfAx?W!& zR_-0em@B@_MrUVXJ|3)v`M>}H002ouK~%ItU?tUHHMG)}-H^p}S`DB7#=!;eQwzaz zdB2^S7As#iPpT!xLoTiX&v3W4Yh7{PxVDHh0x4C-j=h#2^2VB1MTCmeQb*~ZPu;oa zE(cBNo)sqzllwN(>jL|1dFupJX(Ba}hLC!ZG26*d*1@saK+Z{!BLJv0X)APW99s9} z3lBA$wQ^gDC}n^>7wR*zF#1{vr!reGg*sl z4@ECtk_#~9ZndpvF&Jlq4Xb(LO>FTC$0<#N~zgML02b{FgBloY+%mrOUilGuswII@JQIAbrvd)g<$r= z9Pn#V>Fi4Mriae?qU{FeZ-6}6jj-kxH5hY@2!(#$+Biq{ z`;~i#PV?A(JH`+Czva2q^1-nn_sW{LA@rTSyc#%5Hy5CE)mJUg%MZD=UkCsKP$EjL z@lrB@&^piNz+Q7XqLe6w%xbk50Dz1}nu&4{$Rtg6q)owqh!QZ6B0!WvMu7mPk!G_y zDjqm{Ht0>N0FspINm5lxN>ldFPAwS#RFbB4wED5kU`~F}oiSk<2EY_S?@;2hDwur$ zlMB(63_7~y*PXF<+JJ#n=rPQz`fvt1^ARvsBs^7P`}py$$mPX6Kj19COZRFT2m}#G zM8N=wN)_2ihP^0zMot{EvLru%o0FzoPS1Rq(;U-=2Eooxvb)i9Ia#yj1NsDG%uz5K zEC4WbAY~v$Gf5SZPjk#im@EN7hj{$3l~c>SURh8xhLc`a!$tMnL)?G=*K3?9HbZ9N z+-2DfKG7Wywa_}~VYPv?-g?78A(3KGF(IH3AasZcMAU{s8xSG{fPsfG%!cY91d{@W z&LxMG7Vlqq=H9NJPL&`LppZ&IwUKo0cjSbF&LmYc=b1AgAhSSFi~>wpo&f+v7(-tQ+IrazdM@r;WfmInc<3v)fvXoC%@iF{}|61lFJ(gfv@R z03txD5-CC<3!oIRxbx=gPI}M#qe5XqUvCh|a(lZBkSI-5oOPB!22wzTLJE|cc~T0c zP)I>~8(c<2jGHkL6$;U=%a)^Hm8O7P2nr(LS+iyUz{w{af9d6y|Kr~KYxVlT;NZcB z9=zMK761FIU%vd(%Ud^X8XOqfXWzZrJKGC7vn?@{fT(~Ol!72A1_fqrHe;|hj1!Vl z7K%l*Tjv76tXZ?R4-DLN>z&6Od-P$)9t(*+W>*>`=8!)aYJ{UR~OHQjClYWP4qGn{%;mhdEUjlgj@OP#*YRubJmdkjs4t(4+Op8 zXYR9=S~{vniaXkZfi2BneEZIqpIUw3{wsD_F}vIqjf^(7ZQ3z1INGeIL?9$e6o4QC zF13X-+9pn!(D&+VYkv2`zl{!$zWWn<79)%k7Ix*J8&P)Z8-Uk$Tlj{ch>Hc$s5h^< z=CNlVdt?5B>CHw{F({=dp=O*kW2#n0w`|{hz@dA7_6sKiDJGkeG-94(r+JTVj6R7S z=dDS1>f`q?6G_kOIQ_HtWIn-J_Ax-jOQ-qH$7Hb>0GWwR#fugRCNRqgEci27!F=>O z(<)*`KtzR7Z%1c0F{cSdp}6M8yLN0JdEZ$l6ielTfOXrdcmCzZ4eMV$=Gc>_pE1P( zFa*#?CzyR4ys|z6F|>aahF>i7IyVFId~pI|3j_`AwSh6?LS_U)CP4}Sm?;RlqhdQT z2myjvAR(||6WZ4G9h#9r7zIIlR4Rj}kG=-Y&UYTfKt>h>j3@v}Cpv81qrJlBj2wr7 z&G9CTh$zf6P32#P{%lUuX9P0313LX+U*=uiSMHWfpvIbsyx~MAorZ#7%op0{Wlgl$ zqr4OMXLg<(ySy+O0-?Z0QeD1i--n*QYu%2wg%CkOjtmdp@$hvYKJJU53{y&N3f2Kj zHvG{4%aVT#2q=*ucSB3(T0D@047m#!07W4xJn-;68+NQN6bdqsmC?$yNpqLaUs(`Q zl`CfU;zg2d9MEN^45zb)W+io=e>9TOs>-fa@NFu9&2l)t=+^CJY>N@{IZ?f84Zu~! z+ojt=2q9hN5}?_OUMC}TV9rFhn+ZXx7gQ-qnK(_;BuPjqMJZT&uPeM#A|Zs{GOQ35 z`zG`ZY}>JU(^ddbiXeo+;o<5?HIN~iMXb*Fuobm&9jX(*O!i%#)|wEHioUQK^Xt_` z<{(1$^cH2xZZTydIg_1Lh})njXAS0t&>9pT`*8bg?Sh5CKu9U16cP}G479PZ5hIr` z)puE;0PqgAFeB1>%j0z+GZrVn(-dQ)5(HQ{|S)dR?YLJbnu4}Da$^;7ob^cBz9I^}zKt2Zz#QdKzlT3Ou;WY|12D z>{`p=ggl@FjjkMi)q>NC2CW8oHXd|TPNlGB?NEI*nKHAhP?kD22LK>++?9((Ss98q ztsRZyq`R*)Xm6F+>SUTkhWBR=_Pm_TSO<{ISB{x4{ zFK%Ik)lwjPmNNtP0qj4(UD*;%z+6W%COhtB7_}AJo1Tpk_OanPj}(~;%Yq_qP-8F8 zzRK`hE+~%r%oKrAN`WYZU?yY`3}~>A^(u~nx;}Ho zRUj};;{nBF3RD3AP)HC$xuLW1G5V<{l5S{firNrS??Eq|8D`xzYi2FXKtp}wr}TnU z-2~;%0JJ9$5*dCF@1;{wdUSuhTnGpt_^EjJ;7wpRXGpIzG?CP zY-nw<)&@i+R483RVj9yu& zFy{vB!i~%Yn4i#O+{flqU8xb6sJqGh_`b$;O79oVfFM8!5eSw6hybM2XFP-~Ll6?& z;v6l`LKnM*X=R`|VcxWpKf7kz`sS9^GLlTpfQ@>kW0yncyzgR;I-t5k$j}fM^`dJ5 zOqQ#H5kU$J3&NBV03r|~pg<91{WUc7t(X2Xrz1vqT<|xS$#%C`Sd~E^^a2FTkX09Z za~8~S0DzQ%J!oE=D5aeTA_6EDg~s+xpZ?-k3WdV2e)-e0&pNwME(3`9b7v0@R?@_s zL&QNCI3%dqq<6eEGQ$i2iWM{W^!6a)g8B1qyZx4~?ml0VlV-JE8Qp8|J!j6GarGbn z_{gJ=HJi;Pix;ijbN8v!rd)UZ^=-wrBuRE(xdH&DPM*}+(Xnprx{=BVK%giol-h>2 z@7T0;D*$wLb^@5)Z%zB8%)%}N0QlO)UvAWEpZfIYzI@RoS5Kd{aF<=1!#jkOU^alI z%(FUmawQR2tlhX)->Vu6VWtZH0wc==C+(PXUDm&tPv}AB?CZ?=Vs@M1y{8?SJI>Xb zp;@|OCC7ich`<;_>G^f9sa&AL+?b8ugxXwhE%Nf3cGflUg}{4i_Kp82&TKt+tkKVK z&Ms&8J-dNpYY<)kbkw}%u?TJ!mm`6(NFL`s4AW{ly^n0g0}(MvsI4Sw!|Jl{-TB(T zRv&lb0gIPTQ=m4i-?3@KV6z$nfj|tTAjTwBm{kHQ5y_>y%n#m>fBNnHL0O*u(UruB zN(IV1h5e!iz1G$fD;=tC#?)3SOzi2p;ZOJ0YH=uwiHd;*1CUUHvB^8SJH@dl98wT4 zoKP4@$mVQ0dO2X2<&ImzA7lJ2`hPO>W^#!3eU6C6Z@G&di#-SC=}AlKnSoiD^PPyn zY*?bmF~+n*%mmKqu;45Y3<$s!m_?$5z>Ru6i4&D32~k0+;Zgp|=RUh>e(N`*y>c5Q3xnKy5iVn_*zkr|22j=5&;M1ZKI-cNx+x(&|}%m#R9GW3XuAPqyA znMfb+#%6hx&`}2lmwu%Hln_cu1pxJCBTWgE&|9es-~dP>>scfbrKB^r3;;>9k)}AledW_m(4P@m82c*9Zx>@=#n}AJb0I5Rm!?JM#ta)?eY<4)fltGGCZ|o zmqmc=2$pdo6Snt|4FHu=-EDoZZF>2sR~}@MMx_E1Cn+7U;*c2=XEoy(42sKCGN;sr z3dT^kJ`!8s`WLi1hJ2vFmbGRc!J2HR{W;grGOZ0zgh2oZ!Y;{{h(QqQk_vM-vQny1 zZ2*9vkeQTH0FcCugkngA6ifufN~u(-RB@_E0f3O8Kq)4@sE`SSL`o@ⅈO5cW_CqdSZe`9d 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%0D2+-SUPviJkTvnUuo0a?AdUJ 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 Date: Thu, 18 Jun 2026 13:25:04 +0200 Subject: [PATCH 41/42] bump to v0.5.0 --- README.md | 2 +- config.toml | 2 +- pixi.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0805297..ca2f5cc 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ --- -> 💡 **PhosKinTime** is an ODE-based modeling package for analyzing phosphorylation dynamics over time. It integrates +> 💡 **PhosKinTime** is an ODE-based modeling framework for analyzing phosphorylation dynamics over time. It integrates > parameter estimation, sensitivity analysis, steady-state computation, and visualization tools to help researchers > explore kinase-substrate interactions in a temporal context. diff --git a/config.toml b/config.toml index 7b038c3..039db06 100644 --- a/config.toml +++ b/config.toml @@ -584,7 +584,7 @@ out_xlsx_name = "" app_name = "Phoskintime-Global" version = "0.4.0" parent_package = "phoskintime" -citation = "Abhinav Mishra. (2025). bibymaths/phoskintime: v0.4.0. Zenodo." +citation = "Abhinav Mishra. (2025). bibymaths/phoskintime: v0.5.0. Zenodo." doi = "https://10.5281/zenodo.15351017" github_url = "https://github.com/bibymaths/phoskintime" docs_url = "https://bibymaths.github.io/phoskintime/" diff --git a/pixi.toml b/pixi.toml index 8181d8e..a3ad050 100644 --- a/pixi.toml +++ b/pixi.toml @@ -1,6 +1,6 @@ [workspace] name = "phoskintime" -version = "0.4.0" +version = "0.5.0" description = "PhosKinTime: ODE-based modeling of phosphorylation kinetics and transcriptional time-series." authors = ["Abhinav Mishra "] channels = ["conda-forge", "bioconda"] From 490a29429989ce84959315f0cc11fd2d704658ab Mon Sep 17 00:00:00 2001 From: bibymaths Date: Thu, 18 Jun 2026 13:29:06 +0200 Subject: [PATCH 42/42] updated changelog before PR and release v0.5.0 --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a5f251..ae147cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -712,6 +712,20 @@ Make combinatorial model memory safe - Made a project presentation using the sample results. +- Changelog, organic testing, publishing workflow for github and zenodo + +- Defer ODE input validation until runtime + +- Make imports safe with empty output paths + +- Merge pull request #70 from bibymaths/codex/fix-import-time-issues-with-empty-config.toml + +Defer ODE input validation until ProtWise runtime + +- Coverage, update readme with workflow, extension planning for future + +- Bump to v0.5.0 + ### Tests

    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%0Ae<= zBVf)2Zn5Lo(5nFLI|Tz!(VPp-8=TpWdG?OQI}~bK4Quu}Id=#NFT}7|q3ZGgTP16w zPZcpOuBU>LLEw=^(MwUtDOJ8OF+7k&d_!g_5kqBd7ds|pJWv{>((l=Muk-%>r}^Wj z?mBMTP^Trz^2Vc!MPZmB;}K3iFk))B36Ep)%xxbWF&M8QOmp@%aZJ^cgC~f57x5^t z5CR0B3vUA>E(oqZ9~MP&S%Xm-ba|ekBZvet0u+{vjKchc1IDN0xQ4*17$63@{pA}i z(X8tfnOW#b$)Xya%-}v_)<8g7apyhq@kU57UP z5Tg4^j$;78tv><*qrfqJU0wCGt0qCpnd3$eb~?Et5JDS;?4x#k=$1KA05-E66A4mo zZnn0WH6<02C^urnq#{caO40aH{gcOyes=wEJ8O3`wQ%;7Lhaenw356sgA!J%h z^L9s|07;}!11e1bFsi?QPe|_2V<;!sn&i5KbS72oO zt02)iK)eeAAOfv?U`s>keOJ}J1-94%gW1g)Z`zoXaI7gR{IH*~;6#Y#h^nd=!;u_X z?}09;em^7jCzCT<@XZy3Qsm6Ay$7XGQdP{Z4wLRzDHcK@rOGKy(hq##%!NBFc=+K5 z1;NgXcHDi>J<}vnqy@mJ{!!of+Sk_(u6z8E$9CCmx5ExOsHeB5(^9>?Jzx3C7k1fo z=e29r?zQ(G{i8--^}DO4&X}Gny~}R9Tzl*!q3%$c*UzUmM2=5N<(DbP4& z^3=)#IU)9^!*KRkPt+q^(zMkG0)21%kasE}m zz4D%W?n{&U5l6kHR!jeL=e=oCZ#VUO-u>>;qsP4b(n|{$EReEs-nY+}iA0oHN1b^5 zadYO(zVH6~H*MHBZQAsM4>@?!gmFYLZQ8VJuKoRX3l@?FA%xQOz4Ol>Zf4zGJ-O1} zG36DYpC{&Nbtn&(N~La$wP$oy-1E_5w=u!2v&uwaC%dHQg4A`R@UE{68(T5-H z?dexqH@fQQef!&A`^Gol_x`hPxbcstoq5*Su@hc=;UzPFn>KCOG&D4Sn{B&l^}NwI z|NGxFcu=IJiSG&|4Sw-OCWeO56j?Rw=Lo}uX=5~ba&}~jh)O90?CMU|E*rZ3!n^CXL0U?BQr!o7`wu~6PQmSg)6(h1U6&RL^Vz4r|F5XHO zN}3MQ342o2^8uTkc$wdngxMb(q-{4pP=J!SZM@&R;|!;t7?qO zx^}7JZlECl8J=)i`Nd;nPJ^Feo{CdqFo7`9DyS&Vqh1#Wx6%K0z)tlk8LPK zzJsztrZ$)x(C2W)Yj-L_=o(}h>*PT8d29^7!4N5l0dyuo)sVa()jD9EQ$mSV6SEgB zSjKU~-1~b7I>H#(LyF3%fhWnVLD4B2N01l?N*I{^Uc z;Eo2@ybo*y(zN0>Vr6g2`FH$@zzP_-ifxJ_M6<}T2H>;RgT^W4uZ0O9;9JKFsf=MX zk%SBB;pj?`pVWvqjW`KWv;rqHNYJU9Ah85Mo@L#&uEDJH>j&@Zt9Ku{^#ZN6HgiQ} z0u4%&)^^O=cWW{^HG!FhieOr#Lm2-=FbX03vuICQRLJwLH!qy{4V4Q@#fd)zAfIjw zW(LeX2N)s{U+NK2v(ss|6_9GR^TBpL)ale@s=a@}voQv*I)VT}#^-g?zKiaC?v>|P zZ`^(B8SgoGF-om8kst&@LdqyXp-E5f@BP>@`~LLL{~c;~-go?d$Lz8V3ZPsE5^+rH z@07prQKPeH`HIIuhDqm!3VFu_PRq4Jn-Ui+58>UHGFPqk?0O zeybm4nn*x=?zv|sO`f>t9((0PkS01Yu1s^N7opuQW78+OkqzvG7|*|EO&-T%Y_vH- zHTT;VrhvShD_Bfc?Ap*OTE|?h{9=bI003yMiD|`(%el+_57MMHk=8bO5DNVBzg=-E zpkKuhY0}X=@NI5V=#me}Sv)=fVy}iZ^Q&UF>->i4(P;B%V*sYwNJTHAH?+WOQk!xg>v=c2vUd+l%Pzj!M*tw3*C~LqjzR(Z@4LtT`|e>1x0;;} z=`kNj5vgwnj&3^YuS&O8^x$m7>7zGgJ zxjOKG{SG`}KYK^R)^le!2X)p_-L+AtoqDply?JAP)G>zvK&zE&t@B(j+G)o{JMHLO z%Cbxd(cjm5?Awkp&>~>gru`4t8vxoZBIB3~CR0FPz%D~+(dBLKMLHJ%gx`8WAsqt& zboIn>AJmq(&J{I{74;Z7TTc`U1QN0qmN!a@N2CLzGG?CeY^>nqivgqZJ;6`MD#2?u zU!aTk#sv%`xK}iW_hk{8nPMB>ypoSapJ!17XRG?XE5Qfo(aD_}W=#=%C~hMf_y8T# z@ywVFdd(G~kmXKHYu#gSv8vy(U6ohsw zTeo)Iiq}_e8XT^rQfY18089gcB^dwZ4M1DTe@V^Vj%LSCKCzpKVEs5`mja$g$We-$YQKze zAwk!meQ9E>FQc=pVku;dvnn@)=aFblfDY=SJ;C)vlbQ_&h>V7{DmY^B(&h7-D?%4VG3)Oe4KLi7y%2XeG%0n=;wZL@ z9+Rd6;rbH*VA2ps6QBk|ZT19X^Aa)wAwVPu2->+z;)R(r8UR3R%FIcu01AjeB9YcA zWB9UvV&$i(?zr>a->xk_M51zY_G8wFIx7NqdahP-G*)V^6vaS)jp3~9Ko-ODr zf@|7utaDf*I~B<7y8xAo3HV_bub>2ZIWGtKL^$LGgz{FrPP7lS2JMg9X0nPI6y|FJ zBVXjj3mM!vC#nWSl0tN{?C5z5UfZw;h~ga z>R>M-iAAvD)q`m&l7B&HG6Tys9plZ{i@fy!MJtAZ!!nS9=DgjukLYHGtI9wo0T{H(kQ+(dlgg>^&9B&z=x55vq!1=E zOi5AEARZVs2kjk-vPQ!FBI;w;ciBetxQXyrK)R!usNuLo)Fc-P%rD5`)w->9f4!%r zJHNQ^KSO!`(Ovc)Rc~Z@1}HRX0x+peT9ek`PX_fwAxtl2ZCZ69J7AJxjC%!+aRona zArRsh%yIFob>P4P8~Bj8C%FP6gH7^A0oDdHLO@8FNHS-_rin;%8S1c|ER5aI3U7pt z&Uc?T<9lbk?Xjh+_TGBt{K@08JTow8(g}#}MqTAv6Dg%m+G~f|69?M4+HKy9hLlQc z7FclVI-Ym}$01%?j4%U5s^l&CXMv!I0JYXgq_X_xTmF3U#g}Zm&DP77Et|K^yyH)J zdrwdI7r*$Wb3S{{M?dlLA6)pO7oU6XzD_uAa5)*FX07GrQ(Qj+tNf#^ z6-EM%OQs@J%&G`BlcTEzX>*Z{ACs=OnqXeiii1eQGF zXn|8!TbN0^CnHiH%*-<`N)&>$QiGeC&W#Kx5}5!IX;yo~c$dmqJJ(08lBld94x>Qz5fX-f3%@ z2&GZCa|Cd2nLF|?@zKvJf{zcbON?H4E^%t?5PF-?~%yqSGaLG0D8 z^~g{nZC@=@tOl0k3J$moO|wh zM<0FkC71ph01iI%u%W@B-rl}n{_2urjy?MMmtQ>Veed6Mk39jPyQ}AIZ#_D@-?n57V|M&^x_uOlroBwj_HGjN$>aHS~xw2TlYL zj@Iha1S%sUk}~WVLSvnwebs|DQdMctl+ zhcxIMiUYw!MqRfdqsw zuCs{or?kZIgNw)b?XCs#E;PiZ+gn=&Zw>PidG;*3B0_`y^s~a26Ap(bu*h-kCMq&W zFjV!vapHU$2+P+A_9h=ok-kQ}g7%I8b2Pz+m5_Pehg%5QHLx2i*`t}lR&xOY1ffYa z5(2b7YnQ!$b^m{VddI&{+F{WiQ|AEbp-wZ?N}v!z*z5=gg72FGC_yWRZalo6*f<)1 zmn&oyTDbo=OaT>$#Wl|zqZAd;CgMWu6+k7j2=}?1vC^9x0Z!BLEplwc3hH%io5ec%sw{4o0D8^D0rT0g38K+Fk2fwt3wZ4?QrX)dzOl zcSir{EYA>y&w4Q~FB2mocbAB5E=6l(mNU|k*+E3MDIdQKiw$qu7emhu0Vvp3)*w^u zZ-*>mL;>+-gEW4dQY;aufMiGR2q=(*up|~84Hkt{g6Ob{Q4{HW|M|1`n?G9v47XYm zL4eRo)lkY>`oijUlLz{{lSC;kkrvOLVFsQng=pVh=zPcp=JRL>BE_#L%)i2VM?f%k zc(MY-b{X0%JuRgi?sT@_Vf!mCzwAHv{%7fuB?mMPKKAIN_S|F7ThUL>Fn-*a&wl1pbLVdL)RRx`xWi6|9d_uGPd_zg?6_R(_nvn8cJmi( zzrzl#PUoW^|9G=G-011<5wtr+Rz3 zpLpuY1=}rr&nfTu+Bd#>>n*o@>eHW0QMR;}QoQi|^G`kf?1?9yP^%@IHx1Vs4J+^r zrLfqc)9n?`ut10wnaso^@(2s0YW@X+#n2ALqNCiI#dT%QM)gH@;zae_TTRMxZ#0mg zuh_8%M8q`kP6nZH~EvYJ;j|W7UnpC01NeEgz*NMqQyvyacEpwN6SGtcyWxu zRP!}$0wr5wxcjD(vBj;mRLVR>Rvb%WDk{Urqdl=1F&FZp2!xO|Aqg}f2!Z7K9vD4l z+pQP&_V>v|qL8(Ef`CA%H6oxu2~vU$`a&X8A|MS2GL_QXfigiM(g-*y4U7_n-5-XS z$QoMA*(_0W0Jy|ND?)%YNl24cHUlF`gbCmyq7WoO8Y>Mnpb)8)28SpTM0>D{iERL( zbMQfuBoY5@nNmXnG2`ZlXbSjevb?Yx)&NK3WPqDgbV+u6&va}pX{|{`udQRc0^*&Z zk#>)?zdt^K!Q^vJpo)T^P?8nq&oKbxNsM&GF^HBig%quhUb((Gd3>KYHsTQ!Efmv_ zQ~0hJ@h1!b3ogn1H zrxOGbHvA6_06Lnwh!V(^_jqb}Oi|2g4R+A`1t_VRGd9WlGPSwbca|{3wx9DeCI!`S3?R3@DU_2@@uK z?Q35-`+aBUL^GyL27p$Uf8m_ZoPNe>E8cix!nkphCQjHqICT1%XCOecolTlN<$K>f zf7xrV4U8E}B+h={na7`W;$U-l+?a9Q^@ISDBy}buSVc`Bgv}W=|0_*8(`ij6sb~(f z6lJ@OiBN+kb3OyryOIP206cZ)@_YXH>_2|@=-{S&?|1BY{6`jTvv^{sm1zQ$Mn_u( zT1w`0^GlxGf;R{mi6H;yDc0G3ZnXh`6t+r|GeC%G*048*rQAB6_GX5oQSxUd8+0-6 zj92+ac#}^TisYLGn8<@s?B2eP*#jm}4z<-#E0@9{fLNLffKq@Uq?E1;2(>MWi_tOe z^^Q?$?`v%n6WuE(Dumw_+^5A;Z&`ko`-m$eFH1p{$JI1B*Z@E#qSlKd0i6M8$}%8@ zs-*|tz@$d?(V#Tj^=oIEK!k{a5P&FANC8p+nAgJ!06~I`Ur%5-?X$23GN5?6lxD&>pb_mRIrNEn4hOuTb;b~v5JnjWO&M?(a8}e^3`1Vm zIoN%-6&G2qFSLpb7hXUFyhS|+Bf``yWXu&IHMFdivTq~SMx&yUs|ct75{>U)yzh07 zKk}!?AA54es)M%KW_I6L08lFHs7#p?Bpn@<5{P|QhF~h(yN*^zGPg^&k#FkbYPk}r z$ZUkrK-l2G1anXp0cKtafcalMva3Z@$?7l>z|Ng6m6jk}TrSpK@uaT6khY<65f8Bux_lF|6AEc;V?gm%K8rr|-Sn?=-!) zKg)9z{t*3`l)X|X0wC>B>3oDnGGid7!nhD5qPE*YAYSP^SrNPTSm>^x1w5vV^dk)_ zGEPKAa^ncpTGC|z0+4`&-Nz$L#MivDp5^0OSz?a2(}1Audp^uSl-3)ETS8z?Boj$M zN`nNEi}Yu={`b!3UOIfI`DgCGI29sOx|8LIAcQa{qeGCe-s>0%-;jHQC0dCtE*=6q zL|X-mqem%_NGG*)_uY2ceYaiw1Fba><#|4H*31vT|3m(MC(CC{pYidJe%#-gH*X#Q zw6lD{{P_#!&j*0b&EdBmaTEY-YBvesgyY_x0}KvtP5@Pw9e&WE28`SP`=4vBx#olK zd*8PfehUCzc=woUSKb|e(?}GYT(k!U-pm*pW=8GFT8rudUDD3K1erDx*W+a?pYW^Jh$-lIK)Q>wZ^+F^&Ruwd(>4c(YAn!RBCA zpnJa_02tHK2hrV9(8+V-+YzFe$ztV=a1I#))S&ID3h3O#t`~N20KFOi#VBK-mqtk= znR@nS@$@JFM!n$%7aJpQA=kicTCiJKyj5-uIFyoa9tD7sy-7A_qa>}jNL(y79~o3` zITJr|&nZ4zU5B*V-mY3Bm5)5XcE@?+NfUc_P8mb?E`p$vlJO3-BF9Bj<+rhxAH{uE zDCF>zsXcp-srB-SJP}4maIA&0BmTB9kC68m6{`Ln*d4=S)9>GO=}SnY0mRsG1B!H( zX|s0`338?DjfN1YmCh6;X*#N_P8vw-b|o{h+XxXKm-DqntA+Z7Vdk(g2^*`hMPH{5E6(G_)DJ2u3X~j2vJJ55G#|Wv+jxihA?-=oORP$ zAe}-Ua4A`fQAns10~%!>1#Ry%SX7m{u~^;>FI7#a8WCPyHAD(Wch?G~%y=`UQHVtN zbPVoKv`Ta2iK?N62Q% zoGaNK=;4)^qgSTvEz%G`Xwq!w2lptUB! z_tGN(f&@@RLczOs*yZj~WA9$}@>LH#u+6}@g_9=F7(38c>l!I3{(rcbRaIb)|EWzX zeTklVPqvpb{#`G{DMK>8JI)~myE<$I2xX$s>;HC9>?ACj5T!?zc1*d$Er3u~3zbqF z8J$%^QfLt4?_1CeBkH9Qy4aGE`QPgPKNDo(8c8SpKbKdV^Ujj>n_gVI`l&T5*S1@` zOq+T1yluN=(#|t!eRuY31_E%$)k{u{E?);wgcJk!HW`ztOaNdGsxt(dD^LJ+iCU8; zdt8Elk%EK0Xjg;TMN3eXIqIPS=I;ZjT8w!Y6uA@%wp}KC3b0WVB0v&CC?TW}LfSO8 zuqT7u*=%UI)OqEME8AqFNC_G!k(92x*2crFpj+ zwVEwWS_q+(l2S@3o2@pHmMF43H)gac3b5tNs=^8Hw_OdB9REC_3F(VguqlJ z04RYrZQ9iCbjFVxw`R@SU;OOn_x<<3C!TP^aI5*dKm1?4yK&~(XXZ*1L0U@*XzOja z{mQq#bm{!g7r3Me1qxZT+PHLLG4BYLXuEV39*8~j!i|eDLtGR}x|=#ouQn(m zAkzKaa_ab=|30!*m@OQcDpeWU%77jW0dA>d8A_z3;EjzV_<+ncGZ$=NAvz>&R`k-F3@7G5j>BEXdlZ{iY1;Q5wg-YkPZe0C1#w3-h4u} zS3QKDEqrIroGpnX&iV#G?knUJ9aU2bD50lcUNg{Bn>DE)+$gQ~AOL_|Yd|phbQ(yK z?}7DPp!)**VmOG8Tw#Go8gs3U%Matx7A}*k=$asFb=!`aVs)h*pHhewqU+duNX;p7 zzLHj;GSHe-CID1tc*7mP8M^=PqETP1GC$odGt0a+3n*vOWZ$ut{?u z1WFJjWFiG5LKA6p^zROKF4`XeTqRp#Hp8Ov>dhr$9Mx|tEaKW}R>qcRrlNLuS0BmhYOiR?TW6re#9Y5)N!1pz3har{&mBT}H& zCfgsiHa^)%-_?XU!3A`TcVi{aisQz+1y2CJ>+0? z_d~{9(Hjl`0NU)s0L2(KbYs3tL`AxjWqZw>wQ$Om`cy0!5`OD%8f0HM+;+QY=mE7OP}G9AW7Y}bQ9JlGCT7DfV6fai|qPX`mjT| z$O&~Xsn9-;0u|tCwPH!>CZ8vtd3g_D7m{Ed;23PaP#%RfdReED_Hk1g;$g_Ddjxyf zLMl_(SL;Mhv?g@z8_)#vKe|y{R)LZm#_2CdYK|C@J27M9Hx9NsB>UHM_;&fP;^qi1 zO9HAmrXmv&;)3jMyd%chFfK$~7^&xNjy0yPO*7_2^Qb`&Wu4W-Lu=a2%~`HNPw4GG zcK%LtM-2c`C(ly%7IQ=(5P&2Av;Y7|gpke!Z|DIb3P}bi+(i2Q2nKqk^iB5-4d!_I zfxQ6G>gdG6WrxCT6OJuSn%q%11~_J4SR`m4w<2TPP>@^%@sX@m7h8H8!%-k2p%g+& znM#oW2n2~hV8c(gcd|QKtO=vNrGkV&nutiNTp$R7o_c!s^GkmH@B4cCd(+PFz6<6y z5^2g9Pr27&a5+qGT_P78`S|Y6p zB2uJlQlbz5kP2a57*ea(g>b?YF-b8=BmroGG)<(ntUx9S0T7}h5CSnx5`<=!?YZY( zU;pN}uD|~J%YXN~EYD}pp8w&Gd~okQ_84lnlUgc-R9YXr|AB`daG(ZKN}GLi;A4Wt z?PL*hDx^dKH54P6SBZ@5|EFsN`YY-}002^;wWgX`(8THxo%pg%3J@C1OKAlF3J`{^ zEO%}JU}h2o3WJI&=5@^4o52j^g0?`&GPB{xc3m}Sto(%(X~yupoqX;> zag+sI6hUDzg))&dM>10dnv^F0f-j!=uM{K+%oyKTwQlnp>sw>`>m8+~@Jm2P60t;J zUUcO50}-RAtP#?;D|Q-jsN)eA%6J$k5V;Y8&e8~+T+v1t24{1o%j3%!m&~Li`$kf_(}DfC3332KRS zn#1O5&(1?Hmz;0Ua@AyiyK~ibj5S`zxK*wueaMUW5J|%y?3|W4w^l8@x*!!hFUsn zkxV59zA4%@D12zZZWFaj5$Bq4lY#}x4eG~{II)v{5X?%(zAFu!;Acl+03eG$RdFxZ zqD+Kf{LqsXJFa1*J-V)Q;a=8IQU;-%CQ2nD;XqU5wg?TI(D^lX*KCP~P6$8ftcp8V|ZB5vWN>6xchuYxG3pgF~}Y0ss^U zf`kAPD5MJ=2mlfy6#}FHO@smo&87$y&n)|52}L`!k>xRqKNDf`S!n=Tp{#dx^=(|Y ze&xznQHY5XCyp8zfP6S_H;r*<+1?Bp&{2MIJq1D4Ti2&0Y7J7>lC%o|K<8R(MH&DS zApj9k)QmL_TIU`Ah6;xkAfmM1uvUm_t1Qb2r4T~skSbtDS4dh9Mhhb>mV6E14)D~T zg(IMsI`_dX?8l#K5~~pvBSEA8B*@Kf^g_ZR+0~(h>kFB?i%-%h5yak!7w8}`cT};S}D)*Zz%lM82zCtud;LoIbm$az z2%i6qs}oT2SGGi@?R+^5NBo}f9UU9;F-*^i=&7jc~2NG zo6z_Rh3&(l4xJg}%0$F#nTutv1niXpG3;|AM%voPYk$rgL2dmWWGP@I$Q#PKnNg26bOkBLWo+D zAV31fy+!~;2)WYc)tN#FDbS68d^?(Sf|y8=pb!AVolaef$6kHywKc2frsMaYKkN8C zc94iUS)U>~V~=w%n2w*Y#Pn(85&@CcCh<)ek?pAp01+jc<+G3i z(H(l{!vF#VlJGzvk@egnkxj8dZ_XOUB~dD^a!mpRp*?Vr5R`E$rAe#P89R316QBIp z$tS;K{l-lQG-vC%<9hoyHHT3O6O_<|NGjKw5JFCY@oI_^Z^uO9pp6uw!E9uB18_;m z7ga1R5sMXq$xwC`VDwRjtWXxMeIesWN%1oLfNpU2+PK%Ruwmu`gYTbg*Zff zRUdor+aUsg{(i)2bE2j~gxeCaSNfOi+v^YA9@94Yf-%Fv1Vl zaCBlzsX05)G7$vdWAHWxZfCJk03n5cQJt&qEx*DZg#zuy)|dsBPb|f*v_PC50<_AO z-208gkipPCvYB*wDUnyy&o##&e_S{XB66uy^_=>-Wkw!3(7E`EUGyWh=6^V?U=5ZE zsx!H#c{>A8W`H!#pRO(7A0_F zG;+c^>5%M72TgvDfOE?)(F6+2nlzE(rDYp$yldH^drVzCZwvtB zN(p-cB{(YrS++HSCeS$u3DJ8hsxG6_h{I`x8(K_j01WAJ?vQ1zG-?-zM5!D7Z7C!s zZPKU#NCPRzJ466U3Ix_QBLt8DA?3qs(WIkOMgf1h`q@~+XNM{AX9ZLD?yh>lQ@1fn(6 z-SJjLOc|0>)JQ4=S<5?}i+}nPfyukxd)lbc18HK@CA8K;%HLf2%b|^%PC50ofw5y$ zmQmOOgj(lmt?}fekKB0OHM{Mx_rZs~C2jO31_hnrSmRnj=w}J-UQ@?6>}^r5xJ!sY zwAgkG0Tyux09p$I)OnUP8gIPz`d7d7m2nd$U3TTA1VU?tLRyhU{+|F8gh(WafV56) z>5An`FZtEa=gyt?uJ@j)R7)U`K(dRs>Zov)DGHTmY!sP&Wa>7-l&bm;CCtUewG~%U zL@Z;@@kvPO#ggqN{3cvJI3Phth*CgKq_yr6a)+r?c9=Sa0EY8UmaC998EQMnOE4iy z`WHhVCDX;}p-_Sea4*Htt1H{3)k(ot`JaUM|9<@s#$B-_ZQ-ZepX1asdatCBp*|7V z7b_AD@y}o=T5(bVE}E5wMPsZo0>=SZaxblR-3`H{uWOo-AH}8pDWe4i=w{X%(V?0% zG8jpNOAV|THF4l8C*7MsF<#0^;gvPnhM%wyinV?4LlVZeq?Dq!R%^KUYNm1`k|w#v zj>+uKG};1iwHFY0tYA2qxGh z0dlPyiKr(vA{g#;6uIaEujz`;DFwq7VAMiU?sA1NBGPe3ZKrKuFD((Xt? zKW{dt1MKN3PL!Gq7i|)OwKDNkLa-@4c8TBvAtnf~K_dYPfm)LQnMzV*5B4ByTew+E zL_6z9k<6R5mDvt9tUGI3o28VAKusD6gg|o!y}-ohZxVn6;odGp6buU+s6c1x5Sw;x zL52+i{!UOBj_ZP}&NW})Q7n8Gz9ZvtcWIkj9o-|KAaSF$fHhMCkOt2{AW(oXj${*^ zG6SgQ8z#!f7l9%zg2g2%^Ud57H!1-gx_qz4c`Kt;T6{rYL#6goYA*mR=MuaAB9tUZq3XLci%%~l40i9`@W3P;0W zcAXIrk=DW{FS|2jG?8#`#dfpd+^x2DL7YaOR|Mzq(x7v#6e>kp0e}X|l+JaobWWhH zJ~8%{L=X~`ut}tv2n}Iq00ri}9$C{uBmf{1&+X(A`Lq$rq#;B-`Q&H-B(odH`_Y{q zBM>%~9Z9LI*42H{1s9z2m2bA&oqhM+v!}cJpSRy}{mr-Ru-&%%9d<;nH4&(cG%0~1 zO{9<#05yS9TA(D-xyl9UR0=7~VXByGR7w-6M3B%Kid0d4?s?x?wRYn^2OhHh=rLDc ze(C1HO(&f6t}){#YJHDL_30b!^K)TcJr1kEH9(nYu=Y8+c z0}k3}{{x4HhA+S57xTB>=HRy+kt?log#wdAngfHhQd;LIgb;#2n-|k*M6EH`8nhNj zQldmb=CC8J2?c>rd5)lJsT3wl4}{i~E0rtK8c_%$XrOGjvS(g+X=*zog?T5}O38W+ zv=*p=wAKox6jEwUS)MDU0f4kl>-A@!eeP@Let+To`R{t~*$RZpvX0VPDJd|KNs^c& z2>jL(XDbCGDLSXkF`>O-JgrW<+7>Fcd(n{@U*=GBPuwgy1Kjops|%A--I5tDyiN;I zjtCS$pRsO?nM`XSk|+d1kE~U7@}^g;gdgVF!snaAsi0d#<{W z>5Hn_DechCi zN-2|_E&!#qKL~^jJKrtt19u=$5?+jo+VQvb;o0~T0)p_X96~S)Zz3sCX=*Fo+n@9{ zYJdFCriWi_pL)pXllSePHd+p~l(jVl)0Y7&1ST^Gs7Uhw;FcSK#SnNdWmKF1A};WE zD=x#B0!3otLMAGvk%;PvY%6$f+3P}xttO5WN)s3})o>0;AzoRt=|4|CzjAPJ{pMjs zbl8sb58ZC|g305)a`Mr2ffAsd=ZO$RK%`S4gv55169^Cxo$wBb?9f+dXxLwDG=8So zVB=fpOm76}YBT^KS1OfK5or?@GQC;dfpN-CFm09AX_6p7Qz@;qMATlHXb?ys(47b` z%qg!#BoIX^0U%RK5oyvStWQ-tV-uxRncCRi3_w}{rHM>ZBXFJ3i}nmB1h-K`*u5nh z&31L7umParvi6y$q^jLjF8K!m!;*!G_kvXpfp3Tx3q6_?MHjoXM_T(mUl3q5pVsIs zOIsHKBImXRHd8`?wbmHWR((ZwJF2 zd>k4mKp1MGuWIk$2*GGC`JAQc7B>}Mlkl6bxUCHa01#L{zO)9B2-NWUs~ZL;^bSnw z)kfZFsJKwLx3@VM$-Ps2i(ccB)UcJoIqu4*84@zAThlmh)8$5)3I^@wtOgLEH6;=c z+IjL{?tJN&*FW{yckj4)ux;HpyipDz6>b1<`uFn%KKnZ?39OXyM1><$K!CnN{!t7X zm85r!Ni04qbQ+ri7}39%q+2j-k!@R~Li@oXMFo-KKxY8^3B)i4`_`12;dr>bccD1HBU_^|jkAg;^@ommXd6(4CtGri`63d(!0nN6(luVcLSR zlV^<@KYgHkv>j`wl_>=vu~swrEEa0Jz+ohUAui1nLuo2~b`5&K4Rc{+8<<&eDk`Gl z0t$olD?ecLRf%_3zbp?}HH`07Dpxyi&Ol*QWh)>cKqt$4>&YuC2OoN2-3bTG95=eF zohd1V6K+;w0GRYIYYYp40)?l#Xapwe%9#k=={SCyDv>68x>HwIGQJ<~dw9vmFU;-rBZ>GSkcZK`YoJb{egC`rPipmJA|x=obtuQscF^Pj0jpQrQKoo zR&<#yBPK5n!JNqHHYNxVH9!I(A*s6#H5gZ&!MU~31p#ORlRc!+x|4u3=scv(5rKe^ zwFKe7r!e~j1VRfm??wl$AxVZdZTQhezmiFE*)M;7R$%76#V*G?jisVXH1_}uh*Y^^2twr{!1VJz}atk>+zB(&y~`-)(V9n(jrM^(o3qX z^9&J;OEk|ig=xL3UkcDF@3aS%&djE!v|i6T9j&3Ke>4DeTANg!B{I=kYrtApPaTq6 z>sGs|+HC-+H5vos#@3Tm5!JhU^DI|dBMNhZT&>=vwaT&%h_t)AR};qPM#b0F+iL>kuhpd7~4Vc22EwsA6j;Z!Keclg80z;lk24R?5&M zy7xD7x}i{%LVj(6h|Cv66a#1uP87nOH;LW|bYjZ=F=~Jar0_eJP?ILo#R0Pp${b4U zUqykDOld3Zs`PYZgvT0egvLW`iK3Fun^!O|jB+d5OJR(~xO@Dx07>bb9Rpb8`_SAw z;Owt0glGK`lhHk^B1fzRY$Bp!-b++nqcEa)N3d(v-0<3%2TUj?0gRj+z^tWU2bpP# zvlW;bQy#*WuMus%ic&l!t~63-rWFTXY{KRS2t-UgPniu9rmBsEmdrJCpuDi_f2GM7 zEJFBK`)LoDa-b2QIjn$4BM7BIp=>Fk5hjmGR<0gC@AtzGy}ao|hmYHPn;ty+i41BFG#oU7XTVTBCa29f9K}g z9(wuJ6!fY4@A3BCcLsB$t4+?*i4=dh>)}7#`9Rv!0K#_Gd1>X^ZKq9`(9Rk_*Zj@-u_-P&#F8$U!qiAtGA`g&=J$O>evX zj%%;IX8H2vXTSdgM;&pvM9h^!Fp)q>L{i|o4I8e!^2)vT+;j16yD4oCb5&XkDc5h@ z@S7{HoIPu+Bab*j0Vu5zQP^X~5j26Yx#c#`PU|E|{`}X!zVO0}?>Oni@e?MrJIci7 z2tbAeeG*9`5`QGEJwinI*Ia>3x3?$ja#6|OIq#<$!M?fDFt;-d8Lv^WBY9k1d#p08 z$Mq!_Pk}kvMn?eW;Ik{G=miS?(iG`ya=9`Z&2C-4q^-Q%9(MsohuS7I1;?8O)!E3t zrh~gA(u)fR6Mq&JFc8=?AQ3?+E$d>!)ZQ1KUbE97Q)}Hx-d4UbqZ<5+j~I75Ifg)` zb+}PMmay#$UVIJ{kb_-Y@2>SRlAWpuUgVP-Mv8XQy~Rsmo`K`gO>eBC$aQLe5_tC) zc+Z1h256fhS!7H%8BFll#J6Jpj(I|kw+O;hJD*G_lORDg|H|i^8D(xDdS!M z0MeQo-D2>KeD!O?^R^!^8zSo{L~~?BNPRK15cYc`7H7_lNca<_EuPRj3ym7}3L6U8 zvsN@WTfkK}&nY6=__74-lhY8i*3%~Ro_h3l=UsB&A-m1kdFz2qLwPL~5EPLAU{UohDZ;w~t9ZHeu3~0vGGl@Z z1c!t@DBy8ST=m;pI%z|?1uh& zS7)fBvv%4@rAV?)K7H$nAO66xW2f{DOdQ=mzPr)u=SSro%5y-0LdrBnlRf2-9&Ot6 zu(`8Gf^RuCH7J?!SBOG zaYsd&3w~Hm3lKDO-4NITyzs{7W=$Er|Bll#RbEGj-~NCFVPAuW<_M7h3Hgo9Mv@f~ zQp6g7ChDMQjPGw|^wU2){@>@G)MO)0ElEm&c^qF5|Wxgfc6Gxt=6)E&Y6J;f);@RttrnHpGKZech_po5O<>CQdx< zw9^4_-MaM$9C+a2M;xj0T&WJA=;`m@v}xn>&oArk?wYyPYyd@hrt5M^mM+<_aoyNa1Jh%_!d6ws!)^8j=y1$ktPe1cig0S`0b3t@>hBnu_8-R_?gBv$)+}ucO z<0g!U-Ua}oNC>4SP^6oiH<6~k(W5)fW+G)yv~lA`A+e{YPbA5bSC=TAjTt*;^r!(% zG;P}SuYKcNhG>$s0V%w)Wa*~O8zxVjFk$?70Hxb)5W*ip7EGha1_NUOfw$rucQAeB zN^=8`8AMdb_X4IJIbD0bU3C?b*UKb1(ztO^{)H6lFO9t~Xpvdbd-jla(nQ#oT&BC_s5oa$Icdg_G$^0~{vvVcUMPbAsI^WL@!%`Ve|+;lYLlnX`Zb-w!6SCvsapyH`-&0- zp#WZ9wWh1Dr?0n9Yf2Javw85vH#Sb2*Vk&d6OH&h^fx;awmI)9=o@ezmefEXt&OYnRtewr-dhXER zFcBb7p68^sl(Hs-(pn1f`s*vd^0lv?`}J=u-fcIRWQna#r@y!7g%@7@!skAB=ILi2 zd(1I;r=yilgfJGmbCPK1j4(TA6(q?u*ZkqHxBl(m{STNpVS>u@RMZ3tvvQDN&MDU! zg!eQd5dc}WU>sP&9!zVNI$DF$IXVSFZux;kiiorZvjqbXOm1F?E(9sR1*a)VVB8&yXJ-UtA{7g?q}-8eK-~+Z$(sMt0;nEo5ZaFnF{jU z?Un*jbaKRbE@g$e?zl1J+b&gcL|QQMEeQS`LZae`SR+`f%13JYi1TgUL?cjuwy>X& z8H;ZAiB~FOBGN+6<%4YUIL#Nv!4!d8X|lOu!}OjcC*;7B9=b%ih}r|OQovIos1^e= z;^kT(0Q6gciOn4WA&}NWh^L-d*&fo9XAXezd&?l1Jr2l>vN%Bwe8YVOb0F5{2;jYI z++M0W8!XRH(iGq(YGi7IjL(ShJ!h{f-F<@1Z(x=dpEwceC_ZzPhB{=H)&@ok#@6f&>&8>2;pDC z2LzNWLqX(IgBalC`*xX!7JjWMS6Y!dRvt8vB9V7=?*Jxa8;?G|{6ouDKmXG9?|<74 zQwO>RhdUY|k?6fuE>a1A2tsH!VWlV*y8nff&Wvw4e-T-qmu3}FA^-|0l2k|`(MCQI z0W~UVUrQ^*|A)Q*j<=*J8i(r5!bS!DqkN)zu{=4h{`n__eRk z+j`CpJ8XaX6<3{j;tBQkw#zTOtkr5QU3$mz*Oo8ZcANF<)*i6;UMIfyeL@PE)NlUH zZ+`vT>(4*;>;n!ytl1m_t&>{&Ys+4_>86{PF8#~vuP>i7d&V)x9(VLHM~@#r>7S4M z{pzcKFk{B7Oz9hMzGY-*$MMG>fAT3OPna-y^QM8@Zu`wGx8AyX_3HLo?Vtk>eE+E* zm^^icQi=%LJ3D(fZoc%A%i8L-&wSzYQVLnGKk?Y3mtS`2JKuTOaVMU9>9;Sr;l|%J zn}aiF&e&^@y+8JePrkWo#UM$b8(OX;-wt%QX1twCj!GkO?CY!_L=zEY&H|Yns#|W84fgFz5(mK`psE%Z z7|1`cr;Kn5u>n4~HaVW$){^~9aliyV{esnryGjwwi3KiF!@e>Pfwx)apsCp4RJWy)9|0C+&6F zRu>(0(b<`_waK2&L?$BB+Jx=3GD-zZ9oxQYZT6L4z4^uK-+JPWMtfbh*M!L!kSllh zF(L_xP}(w!R~Y7n2-}dt8P^DaBCJR}I~p+*Ey9u6l+GT4C<{BGCafj3j_xi&fFP!g z8zsDu_E~;Q0}_i6n?3v=9j(*BSvHe(2#hUVr`aE3drg z?z>Mq@pu4eW?3R-yW>(VzkHT(ugF=Fm{q%$kixqtya{5#8Nm#*8KaMC@#DH^*G1IVX_i&}vB{iI{8M zBCXL}yG1!^mFGxW0+7l{X_FH$&+}H^5{N|9Y&7#$ZmxqPB9-Tm=QSZy6r_~a+ETo= z(=eoZaK^Mv6v8pMqss0&J12a6c93AazCwtimbKV$ zCPQE}=Y66Wt5|Bi&=gpd6f7Mw*#*sZI3OSrLXqL^sL-7*KpyDr1s8|Nq^s82MvnSv zh?ZPl_s0VifHqJX-P)TtWfcDfJ;cW^496jO>(eE}B45>H=P4{V9hMM~FqoAE^cs+h z>9gH$ho*`uaZ&fDFb1mKe*z*Y0TKUk-?CBT>a!P&AqRR~*`r)XcU?L5D`^^U4uS~#owbKigHsaN~EI}(XH zH)4~Vz+&VQ`ghiw9iH7IE8`ddfE)ejMPv|CPE^FA({Y+ZTad1RF*@0yZ*%|>Ad&sI zMN{1}8vhr*LJZ{NrY;Z`9~N&8Li`w5()V!36dBkBnN;I;jc+%o7T_3Q-&$6~0z7~K zCJ~kk3UX+7DuA(mKqvaVS;k`WjTKac>l)2J6gDTX5Cq_^ZW90kHDbqzWd3fW4m^F% z>EAr~%x@lc?8o-m@g4KW%^KU#;>l;;dh)T=S(XnBWLZXpBB>{}_B5>}LfSx1Vq+4~ zKNP}`9l)QbW~MVI89UPqKS9?MA6{J5Jrty!!@m1aA-4;HlKHp1K}udM25n4?+yM~1 zz$Et_aB4y;p$pV*ZUWI{j!#ma>sCwmbfh9pzI*#?e|}`eS%=MCIDJHxwGyF)AbyKf zXhf3$NQBvsr##oKJa4shE2CCMc@DXPT!XUzgwjF-YK}x;z=lPfX?ZM|(b#>IbI#Q)gYD5G>VnPA{qVO3#(NUYj zwoA|G&4r?r2b7_x9jL0`Gv23{R?0Cd}C;6#hWXC{kxma`^ZO^F8%YIt+sk|-TF^_{(pb; z!)rvXZRs6LKm75JFJG~8yKQ%P?e&!xUUbpxue~ay{N5GcyW-L-2L}dJD{Bl60?=T8 z|GM?-WK#e0AC_Kw^>w7_l~>>R`nN85;e{6f1z>W|U3Y!sqHk>6xOv^W4L`o_x_>&wu_4Z>?UtaPgw&Uw-XF=Y8ZizxgdD>C?|W|Fd7-@YM^y^~+!UYTDE(E7x!Q z%oo1&gYW$yt+&7M;>#C*=R1!+`skQ3V>fK-{lfo#_1oY4cB|P0fIMp@iIhqGk;fnZ z)^{)c$0Ls=wKk>Uu6yqJ`Smxv`R3ZCfBNGmKmBQ~Y5sz3pLp`c>wo)Ot@3s2)?R+u zl{emWBLLif>#gUUeRl8WO}p;0!dWtMX(_{52VBnL-I zZ~G8~0&C3YDTEc;JS4 zqVLNa`mDhsL~eI1-kuBAM+|ucqutP8nO4x50&J3oja&73zUR%jB{4q zPEKW(qT=XcsI2_ttsy@*Mf}f*>TK*m5%&S^obg_rl{UQ*B$Xm^}_O2;YCILW}D;X}w zb$3@605nxDgqS&dcD=15&lQ@Ev_^r>9}1*NBGx-ymUQ0Bvys?KHP3b>@Gb;iflMOZsJ3wK**6=;9~61L?W7l zD16)Ap2jvw-c_cwk}AiOFBYs6LtN@JLWHeaR))rgqqs-%lv4Rr?r*www?M9;gWxu&fHLp?A`qxry4Hc~ zR}8-R=(+=s-+J`q4yDY+tQb{ugQx=5vX~R%4oK_yV5&T(QE%!MhE}#Wc>i%(03aE( zBXaDT=|=>u^@z^em(SYs!XH2Q#UKCkj3ehAzGPw@pxMlGO>yO<74&1ZJrNZ< zwYS}1xKkl0cH{lRLR%E-$A)NVfEa)P)glf(azmclYNZBc?zPr5lP%>QDsT6pP|X=G zPV6B)9N5`5dMll*)r z0y60`k?N^T+ws-aLqGV-@_)a){?jMSJ9MXs%~ngelL}=J0YE7&fJ~883IIqGS=p%v z$u0VelFi%`tyLlgcD5xsU`CLWP)d`^>g{!rCcpp7OV7Q!`lBapf82iCOz5uXxiZN* z36V^goXN#zF0!-RM={8DKgpR|90Ye@2Ecnz%_$wblo0?zNCE(qGOc^RGa>=%;8yqi znbvBfM$7JzS}7ofq=cwpM-K`Cq<|D@rGbpslEURx!k(Np^G#Gzf{tSSC=3tz9L|RJ zFrhp@=lt`C^zU!I{d?d4@l{t{d)T3eo_6}_$DZ&m3Ha5oe)X}(|M90k+a?h)NR-Sg*eed*N0 z`o_E8{q9$mExYf&yT(r#1E9xE7+>$|7&UtIC6`|MuYdpRxu>7`(GP#P>uyV=Oww91 zYV>F&89?ku6MlSu)(4Jkt0U-5B48&=%FKey5Diw zVJDyP?k|1$OOV!jMs$Dtlb`+j-yht1;r5UIwCx;(-RCmv)*OxuNWUqbixa;nZe&SQLv|dZoMcXdC=)$k=chEt1-gW2cr=Rt= z`yUwW-8g>2g#Z2G7k1fg_Zib?0l<4sI_Z|%{_sDa{%oyQ%d>oFaA@?nac7)y+CBH) zd)uG>u*ZJ;t$ypxKQFy=!TkA09e2#vzWVi!j_zMwfBn{5Z~gMJS6*56Qmw5G2uJnw zOrJ3W0Pei&Zj|!d-~86$M;`Ikn{O>!_Wa~26G69xkN_k?Bq_81D4JQWldVkm{PK1I zXQ5W_XL17HLZ_^zx zV*M3t3pOq`?WX?_Ct|S;PSrGy;OQ5hY>xI)noRli07}5eO_MZ9A9?iA2Os)- zb7*k+MVb zvb4QkKk(oKTdn-9m2aJR!ts+QPFl5Q&9ATj^;1th)!os4@H^gl@WF>lDe_!N;ZhZa z&49w%hd&xhD<)t>Qx*zAuuX`Io?PJHlVbAawdGy=?y4Px@ElrYRH}WC>k8hlBqBxu)xLqPja#)RB>@t7;AeU zF>Fd_x$bIDE;@goD}VRI4{v_%iI>(Kx!cr*Ta7mP%t=#jZZhL+jL!67{Y5gQnq@uQ zp)rm{I~7bh7uqbPgmok0T}IE_5$P7H#DghI68@)m3=|O@4Vl2GiOJY0Qx@$x z>9rTv_l#`=fHXmf%){Nz2?*Nwggs0*4q;##>FZs z48sNG$E-etzA6ev(g0aBnD3>7*N(f+9SZ=NB7tb;RRaMb$`k;K7622y#fUja zgaNGtCT5N7UBy}uNOCu7AB_1c)Rqofo7 zy47lupbZ-~9CXN`vt~~J)vvBU{)CfiDL(S(qxa_sntL%r*z1c|w70j*1PYrWV?k6R!d^o{`;vXtMY0x#vC$=g+_IZ}*c@FE4xP{=eP#fe)NAXU^O) zV@D4T_FeshtB*eF=mpy@IOLE+0br;x)H~SU9BKf-%o)>^%CGzBPnub4#~pXvd!GXU za@`mdG6m}ihhT=fSv6D7x3GfwXGKt0VU#73mw;6#S*(Gs%hI7z17k7AT$P-0^yaMG zY9VPheLY)M20Z{bXb3_nSJ?OjEW*$Y6XHSz;7So{+?pHi@q3<;QgK3~9Q78B6ZsHg zCUvpzEY8c9BMwqH=fXFShKot#RapFY5yFBk#_RH|EneA$IpVdV{opE}oAEPSQYd^K zjR?d4R0*&_SnMkHHH+AZ;fq{p0o&ZI_bsz(0e&na3%nFR zPhJyYq2Ql(&ON@M0t8AEO6u+H9YSiYK!Gs(b=um>wh`?V9RUa=ML-&}T()wO0_sv5 z#p+LM3FCp%FnUD$P@Z1Bbp4B~S|2}R!gjN|P46n#!bA%hoba?F=-@9{ZKbL9sEmo1 z3TV;*g0wl}N(7pSKxmB`KxrTZjR1%(twp1?Xwn$1XrR%oOPi;#y_Wi>4&G+gqG=QQ z8;y=M9pBR}iCRjdO?+<78epb%S1tY62?q`I_H7z!oq5=& z9Iv2$BOB2)Wb?oPBBnyT@ycuKH*5ewZ@l(8H*eb5-qEf#wbkp` z-Y$f>xtX$7mL}=VH{bF<7kqM4-{vV(Caqby_Jil1`_(UhvAd_^>1Ut%);BL2GiFSt z^oKwE(HCA?_N{Mxy;iSXef70hTyf>XMcZ!PxapcJul=9Te(FnK_+0p~3!vfx+)z{o{+iap6Zle0J~V-tS(1)#aC7GGo^CTD|@DKm1|U>NVSJv(3AX zId=WJb?2UU-YqxYc<_M-u3EkNXTSK(x4!+I51n;tE6XGfb9Fa*j25inz);96zo1I1 zxeUUB20^=%6`ppz%_X?DW5n2%q;u4$<&UjvdvhSqln^qw;GMuE08)lXLFIW`m&>2) zmngMX0;JC`Qy!+fmodDFK2!~ed+Yh4$nEc%kU5Y7^GuJQ(Y5=5GjIRtGh1ytcHFFv z=72)WAWWKgj%0w8q<5sg{N{UAAYAJ;=5YrD!9OZr!-|=IDhJoRIy&iBk zO8$xi#6#~{A*V2lW{tx_sP9V?gWA2bLJlL(u>Vv5(vF1f{`kOLrkacGhiv!AS}O#S z*moRyjJV8ZY2%hy!F~Z(j#Uq^JDbRb1%aQos%3le!2l`+Y@v^`(x@`k-d%g~pKJel z|LgBNcggtaU0Q3A*yDLo{2Kw7qsZPoje4r)u1XWjW|$dfcg=1Xd6Tv{(8yi^vQZ;u zv{-`7=n5hb0<&C80UthLyCn-(U3TMBPrtNg@x1Zd&KNO!O3$P*9izJI)noYY^WW$H z`l(r0QLZ4*by62|7L7A+%ssOI$qBFjKL5$n-^iD*?O(NV;ElC|Prkh2rMLQbT`=Jz zN6l@o$^OACNt}uXfWq1gz=#b+)Y4)gqsL!b|BatL_RnQ&8;VFPPz1`Hk=9`HXy~Gt z0fF{LdPI9$rTIVrNg@&{YKc-lk(vOaEK}{Hx}d49|HF$BKMFgl75`xW$qLB#g zjg-o)A^;E(1qva|?g}A*5GisqKa63EvKFI{LLh+9nzCl2(Q1sFH0^{FXP@w{Z&q+@_{?DIZ|LZ^e;Sck+nseyk2cCcaN9N95K%`quWp3#k8f**=kx9fiXixn$ge|6cimtS7?@eiNd-qDd|Ehz;NNhviTO0luGS7$>) z)E6#Vyv@A14?p@?-{#HBUVLd}PtUHq>_R#RY9XY#f_i87L-*f(@?fF{iIT&t#5xd6&?)!Etk=8EMPUikGt{prt}`ZodL=8e4z=Fe}n8bn=M zsYE6^&!$bAdeqT}Uv1Td05ki~uQ-Fw?o8e&r zQR(}RFL$x_Ok}Y|pE>20)`r@3=nD`FOAppfR{|n@UdWn z#6$BZ5LolX!nmrD5x0kYmGz%40^AC~+kRBA(c^I-hPy*;b!MTmC3(?h745jjI|-(| zYpmLWEbr4s&Bq^#EmQ^id2^mswV-kT7Z#SMrG$xPcx-!Np;#R-=$#c6KvgyrDsnk* zySIhiI?{s_PEVB@DPWOk7-QWL6LAlxUnV+&;HxO^nvEk2hi%@E(}5e-WfT`9O-fS& z&{CiY0I``9AVB~K8nKxRiJjeD zZFl^$ciHk~A3J8kK|75bQBN`jnL>0+67S?jcP#@V_^<#hb1$%gL1B>_D9uYbe?El3 zs?=O-4PfrzGpRky@HaJD5}__7AZnm`l57}iJo(1T{$^{hd9!+I>BNq9=o1p8uXku6CO@UA3|dNua@@iA5ra=c_!Y_BS#e01%QgAt0a$ zW@}~Hsi&OW$_793(NA3U{U7YMWY_f@H=g;yGslk~fAh^Z&)a(IH&(2A$07TF>|-BU zwD_Km_V%pR(nZFc}hTyD+YJ2dh}IEHtVM znO|-mF?QNm-GcxovrA_pCk?gTaK%GiO(B5naWpN->=P5%=u{g>%(T0Lv3w(fM(x}ooX?cT*Z&0KQu zR!V8hx^_4M$ep}Io3KLj)vSlXD<>#gbRHCM*<#tk8U7i@dJJO@y+foTq6tAj0x3{y zo#)xE3nu>Ji{r0f`og{cUj47&GH}DVTsgCi4wiY)XR;4_1>^>cHUWeS)p42Sh;{9a1@xv9SPmuQSavIa zDqzVohnprpt&TGSgAo9lC`l(@(8nA&7Iu?v;X(&j5FG>nVKWb`FTvtn6Y~rs00;~m zPaereKo}2~J8{WYAdXf%A3IPDeWNiWLVTF{9}zU!EEiTF@JqYVFO3ZEyX=vK!lwo| z`9f`via=??T!B_7$RFu3#=y8Tthn=ZWO>X0Z0~QeUwTR;A{V`7a=($qvXeQU zBf~y}7rOqh@Wvgc2on;alF`*CvvuGTW^tI5$*~N!{7}j^8AJ_Pi3!G1O#~9q z8|#KvtZ%41Ym;i~nC`PawA1VfUCm7OH?mqypp)7HxD^@T0RTlvLTu=5ZXSdT+CbyT zdO{*0WrZM-2GR(MANaQ1>RH|MB9cbbS}KjXwj0Ml04NEBCPV>{>!hCabc}iawZ8K% z``hC$tvT)RZMT~_GLaGhkdz5?i||-h1rC?UNP>=xg+@Y6 znv@2uK>`3#o&h-rB@tN1oNW;Z0HnzrDoNW}6ey$wlhQ9x0XohPlt@Nxa5YMxopcn4 zKw2be(pA$+_x1HDm5m%d_PwW`_VsUHymsB1Mx)tkG^S0T{=;joCV^V#Bf3X48jWqX zS@6c2uaVYLBuOf>9FioJLZ(R#5j)yCF1_-5M;&+k&9~hAzyp83;)-h~PMrMN&we3I z(^i%%tr1ZQnIttKQ@|8JYpn&KL?WVNjz0Q^n{U4D*4v(W=DArjr|-JkZbT#yr4aTA zhyYDcPirFWXf^w~MvPjxaND2#>Q~?Y!8H#){Ez+j+-<@9d6W+dK&2F>odbh|7hUwt zKPhE55S^vP`)^q0^eDJ}DxZ_Ss zmj3Ba-@o>n2OoOip}#+J_r3Sbo;_#Ml!-*pY&8L3{({9n{rNACzx~!b?!4m|uJI?Iw$kvbzn4IhffLj3oha=nTxQNPPDNz8Y_^;lFR zDFp3D(#!oKKuyt`3Ny`9t@9*A8H1hS7OXMhhUpa*fIDCswa$#8*hUKvvTs8S))pQr z4VRl`XK$YGUFI{?|>RcCm5OoT$g_N;o0=^>oDU1#Ll960=0U#rJf8f-Z5XMWZlp>`^_jJC#ap>G1FF)eBO`kk^PE%tm zQ-r#Fk$dRS$roUg$0eL+-4GBF4c=jnAJNjJ2}miWa^h2HY*rx>8zTl9poZeL4ZT<0 z`^YmZR&MU=`}#>o9WZCwP_t#7Ap!-WO<#dFi@ydSL=e>57}{aZ6babdXgFic2{|`Q zMZ1sNVth0{lEVB${{aC}05lOqo+l_(rZ)HWwpy*FfBxgDw^si0=f9k{_13+cd#6vG zc*dD$eDZ=%J@ec%i?&^;@;t580N{a#9@uul;-ii@D$nzJnx1~@`+xGIYg>6sApGXH zH~j8*H+Oclx3{;A9yjL8U;gr4cis8ciZ`#h`p1j5-L^3}bie`o8GzSs+_=+@JDqsq zi3uj7d%E}7W4HV6|NH9Is~0U=aN>z4Jonslzx~~B1qzu^u5r!!^;2g~*|2f_4m<7o zh5!AG02)1FT6xK(m!}D8%3puu&4(ZT*FgvD)yx{wsmef21p&*Y9Q&3?2V92oj4s$zcvV-q z4z~##s^q$PClG5o&H7Mbsx*KGi5dYl3Dm~6MHB!MP)bCC6cpuJE3I`U0&|37)b}jB8-Xz~02O*Y2yFxaPdHF27T&}bL~-p_JltI1s0RHKVM`rfe3Pb`VU}21RVJv!$#cVR*=EYOQ@OzA=dc zP`UD3ZqL#(2q92Fvz19HPI<@tQ{FNEx#hi&JiGFR*EguW1g#gkb=&4H))&Ytp-999znx)P7MWZ!3EWSw>(JitLr#rA zg)7kuRWf%V7*r$JGb<>ikU}7!NW{EpJv(kSYUjD5+7qdj?jLF;Qq)rs@f|vn^O$gA zN@>;7)XYhu5=q{q9F#_FJyw;`l}TZ##O*_%5C6JV&zkdO?7gp;I|puXy<6c=b$%M}x#9 zv$;T8Yo)bziJO&HO6wf7vNWYKL%OaJ*CGK(0VIS3DKHga0uc~F3zSLXZ<+A@*|{~# zBI{@^Drj=tk4OSF0uJ`~{rXqG8Z&0}0f)SE^vJQTto6s+Z(Fr$)s!idCr_Q;Got79 zE98dh-pGNs`u+B$Y``2mz=-$h4l;(ptUV_WJ9u3=9nIzyAUI?|;Ap z_uYHQJC1nnndgC2Qm^^p;2eA zJ~(@;*@#%L*ODYnWC8#>&w+F!YXN~oO{9)I`p7@uamU4%UAAuZ%2VHWV)y9reVaEV zSXZjq)z$XuvoF20?3MlY+4tAK{yB*Bm6u)`J#w^^5_%wab^kK4IMCPkj7>Pkj7>Yku(kv(G*6-h1yn>+Exc5Hd*s=<$C(+R@c> z?Ef=xaQ$%JCz z>o5t!A;0jgHBV>@Q()f&3#iByR4VIL5cs^Vo`0xVs{m>6pE{y;TDzDrwg~YsspTsk zJMW&x8}O$d-`^_r9j0JU0e?3j_=-Q8K94fglw3a%%I>w9{BWh`jR9}DJh>;^D;LzX@D&1DEZ``=y!i&Cn>+fzA zZDQPnF|WS#N_)K%OpX{S0il0jAWZ~dGSEMu^1RU)G#h=o=*t0D*>K_mnb<){cXB)P8XRwrd66EQ;RcIO)} z17F}Ga$D??@`{I0;(*}Jwq6Z0K$KGCOQ+P9HCeR4 z;J^@+Knp!aN+8kzWxfc_g(@Y980o8!3J;*f>QU>l>o&40uuMSAvI<+6f!6H)L|F^^ zB9Ttz9r$G-|IY7@ac7|efXaVj8I4XZB3rc@uYxCchcMf@qcZ0+sG2|Cak0nZ6R;o5 zg-Y*|*Jtb$0P7{tH1F7Zu^gnX6#)pO6=|(IdeY{g{_!^+fA$~iKlSZ>r_AojGX(^s z2+*WJ2j?P+uo@T+k*5w7Ypwh+yC)cOiIh3% zRx?WzF@IXm{AoSIRsZkv-{-&2|F@o2t_GW#6rx^Bke&AQQp<@CFW#LO1|U;9*D%z~ z8%?b>W=bQPt2wNkMvzXUg`Fyw>d*ZxO!$|zDZrXWX1~P&A_0g*&}ix;ks~II zefq_9r+(qqkG*TrH$Jf+5$4(-Ce?iD6{H_K8c`J06}lS0Wdk=BA^{MYn_x&Qr4`w< z!^)LP|4B2udH&Em!Pp zkn!=7FrlnUWujK!uzJNuKK8Lp!3WPgbLOlWYuBy2?z*3B+_>R_kAI|V#OSlmIQ5*5 zeC*_tPx;UXKhWLPeb1eD5B6>N{*QlN6G_%;4mBHy5-|rM8_nkW4eL8QIxfBRJAeAi z-G?4@(EM%YFTLZ>Lqmf*@4Pc$+TTCWKiIFe27pNu$N%ezC$7HwnmKc49&^MIt*kjP zI7lJ^XpI;>{@{ZSy8kO*5hC4p--Eh)x&c5F_V)L;@(chbPnx!$cTC{lnkAL`+JMX%C z?3i&Y*RB~eepF*0PKdp!G7GGIPJ~3-?O0SkA>K9tZ$&sEP%>b{KGks6i0Pbc z2v1nn3uM7(k(G{&vZKyQg^AUIs?X&=f!oa?9|BurRN3{Fjg-5fDk*{$aAGComG6qS zesOX3e*hbn%51?HFCZVc@YnE76&7C+e&X>|VQJXru~fFIIu&{t9zsLjzNsyn#9ML$ z6zI@FRqT2To_-2@>o%(lV;p zKD$SQoej5&bgpVvn<4@#atc}R2NIG5L=@p77dCka02(kSdSl&sA;j9%>yFxS-VW0z zHuK!cDWl$j+}T*Nafk?L)^?(v*kv3#)S(M*42)hTC-Pr~H^~3SVp+4nD3e4aQYI1r zwwk?lp0yr(_>sd7IcUPzF#zz)Q%`HHM~xVn=Q$#og9+VTUCUlura|>|wgbSL)oZgX z@95|PfHO}&{mj!(=WxCF!V98?Z@sx9P1C8uwi;6UqF z-+O#$AV2t|t=c+8tD#5{S#c5KcL|1ZYDNh3QmKI43Nea2uBxp3k#R3GhnNhHYfLgapnv>s_y2j*tkW zio7>2-x`5&?m3xdTC;d_d=p_PLIqC(5tlK6M-;MW^N|O3085ZYCb}Y2aIo^Jv<1rc zM)Zo|zWZfxdtk+fzp%%`J;y1fQJ{+t7bq+cD*<>80%iE8R-xN6Bk7bK6Rku5A z8JAVX5^qU%7D+z(#-X-kNyT`G7;QL6D5fdPi7r^mPIPr3D6;?A$Q(~o!IbemMUmzh z>Xl#{R@;`|V!Y48iIe~Kn=mENt8pFneakfVwv!CbSrro=20-{rasUR(@Y2zKCZlhK zz_wZf*4hmG!^fgEQMhgw?fGy70>~6(B;0{<1)vcGfgqcQ%2W|ym?+SkFlU>Dh{k)R zg8(lL(e7TFjBbdEpgGV$(o41;H*b2k01$#CGfzr~S{-6o2#IA!7up#z`x^J8KoAmy zL@Dh-1h5vrCeTF6LLeeYi829!fC7X>A*IAbf;OHt zBqcy5HdxjtGvPR3aHAgxxfjBzU<3ly96MpcH!k|xEjQnON$-u#_=Y(U9JN{Szm^x`vcU!%)qYVH)c;@M=SH1O}i!UDC z-MQ}`dn}$mzavRI+S))VMXmRobll$``0MxyQx|W)9jOeZ9MRdeaNeAW?gmtA1<+BYt|P$|9hE<5hG=bi%ty>Gm+eEQUBb7xK;Gh!qdMJvSgDN~0U%@L!-u~{MkpwVz>v>YjxpU|4 zvBw@ndfL=!2kg7wC6|5o8{hnDfB(>=i4)E{@4TaqIqn~i{e8}?8Pg|EAi_o4E`Ivy zXFv1VPY*VRM)!<5=R;?n^xhNl=0Gh$1O)&RJ=sNurL(y>rLs*>C*b`iefdGgwp&uc z!>SYeHVK9WFUndqemUiRbEPJHF#s@*aw&rW*J$aM0&ASQisZ~BXXOD!6c6B%SD2sV zRcu@$&g=%@B@9b)iE$xfw@12K1Yv5p$-xsoctsu?wGq@&JKX3k=zpul3PuBXJFB2i z0g998;bY&qEII6?jx7{GLS{Ea4OS{pJGhdrDLl+KRxprQg%DKcVJOpOjM^~w0Hq7R z>~whFlDD#o24R7uJuu;Ti*3)RFoQx13|cF3?Js}H7c)YFHi<@r{FBe?;ew@1oLZ6y zX;mKTaB%|>0%$-Y?FiDe74S|(8cBl&dtZ?tM1dw9suv_Kq}2f7MvF+=C!Db@YIiil z93uh5!A$iHHD`^7j~qVreFsixWw|1dNHx^uiS%5Ej1P!U4L`QZj>S+QXlHRnEN}db z2;fddAWD-W0<0b+$HHV1&k+&9ZgZ!#n=*fCCPhzs)wUzqLG9dj0CPTI(Z^I`)4)`H3s9y6QbAoY3FjciCl^ z4fYSVb#wy2hK(B=jfO;#rYT6#-PN`4zWeXC+mauA|EgKDXUv{G>($p@dE$v@KXA$^ zNVIX|rd%nlwGgt^YWDVS&hsp5^)^==r0jfz z19`Tpr|+B(9yp_?le9`iiUfvB?EPQ~2x;P02_$Ktv`sv_VdG8DJvETFasVKm0h1DL zI}JH`6ae9NIv)kO-Ll}Lk9@>Fj|`_!DMd5O-}TWQYCW~z|MJ;2%Lfj5-&PZ6bpk-% zQn}JbdkEj>mP`!x9RiSMcn>l;(%My+w#6aVOjWGpim)K%NOnd|Qf0sxtcBoRRH?1SrW{QmRn zHxGQ~vV9lqGA3&&d*IGbh|Tqi$V@YEW7CppjT4luu^gnyN1;a&2WfA*XRFsGw8m_>w zq9j-i{t*Qt94_>EI5=b51cxoQWw3Y|EYxK-4Fs+-HcGL7*F>?6$S^4UVV)Sn&R^*^RS1G%8h&t} zoWY_-&@SE)LFH}joge+!|Gf9z?|$xumpAnHCMai3pRsV!c0dHGl_|X7Q=dEhuy;K3 z;>!Z$j@xfPWA;`6v|zjKfBnl}Oqe{;M1cdTFMs9Bn>KE2Z?C=Q{ip7}Wan4kd~@A~ zjXmw1haP+Yq;(?oh0lGqUaL)+GC^mJV~#(5+T`&sy!6Jb*)!&Bv-KxF_K~cWjUPW! zE3LEsIor&;>hjCmJ3GdY>Cst^*jTvjylbzyddh_HkoRj*|I{ZxdBi&o+puBtoULXE zDG(uTYtvfqu;ccl#*E&)X}uIF0wH38koET;arAN9E#Cg2$NtsU)_%}I2jxS}XP$au z%H&Birce3VkFK6Jb2jN*qN=smKl0I!N<@_nE?&IjjW_)Ep1TQ=@cKO*{O__O*3%oc-YsA9mOw&%U&5XmD`) z)Tuk|vXfHH*|VnqFd**4UJpbzQ&Aq)-Cr{aB=k4;WMXjckiE+#o zMWdV7SY3E?fuE=#R-;0aVQc{xzKiqZRO(pk{Y#9MP?q(! zN?2IiPfqHYx7s#H90|_OL@vpzP-|NvheOu21=`PlX~6=NHql+j?oMfTq_nmR6@?o40x`6wwI)G|TFw4Jl0qVYL=r*+3Y#YhjiN(x(Hq7! zP5@evAe~BtBt@k)_$yY4NEt%x8^{UuL5tcic-Q15b2>H;wxlG92_Z^Q#6xCEcBu2s zS-pjhv%q7y$|cP9?g;`m!~U5@0MLm90g#{&Xu&png%U^zp@}q+QtFtUx7};r>~SNy zpw(<;nGiytNTei!rdBSO9w4A1$n#wKXhkO^?7s?;iu{j=po>J|Yd9)(_Ks!@pVVq& z#*H)S6_P}J`Ac8^)Mq~R@e3{(Gk(mv4eNK=VaazdzjWOAv9B(FW5%pmufMr+^X9&D z&pr3WmtXkdkFNdwEjJG}8{5p^X5PGQI@>z{ptGZ+y{*lJEeau;&1P3u$Nzrmi|3zz z{;|iuYudD_uf6`tKKmbZ+G!scF>=)CF=O&P(;7fPduQjUF{3wbTz|wnkG%1Q8$a=h zkItI8RioLjTG@n2lU{#o#ol7K$rC59->@-P=DY-s9y@0Am{IH2t=ntwy*~Td&tH7; zw~s#N7$kW0wO5l`x^~05p+@tRQ%-sM+2_7}$#;J9yWiCl`O?cTec+6<4?E=GRwGAa z?;?>9F(UmE*f>tnhh}rZ6%bw}kW18MInoLzmlZgaFy^5lzj$){bhe^rV8MaYc9_!b zUK@?ErF-gHZ`Ibm^oT;C$>b{ra51I?Ht5E>U|1HekoczL7$9Z=FcQQ93lhX35d>NT zASEbT&FrYt7EYfv_E(qx>*eRxA8_2vg?o%2H@VZ?29+zNmD`SEc&mC?pBzl%U@h}@ z6}LyP3$meSn*Qt!+(79u3KN7y?D&mzk5*kc-d+xX@;hq7n$)%@%ll|D;(Jr zILxWYSeKa+ez$-H%K0X$+;CNYGCYtu%f+0x1sZUc2AM4Cq)mC_1{7$QwS|->)jJGZ zd_o21`*3bdW;&NzrLxDV_>??@6u%B5f173?kZIr}ONyTLOB#6i28RRu?ZlidMa8b; z3JkpBS8hd%MCOB+GXZdsYoBHd`FYv#Hr4WWxhmD)N6!kd;q$fc0?C+ZUr@ zKF6I_dT)ZobRQ}>xP!C?Qy_PdjJ5m1~<>& zZaWZCHF`;9G7Wfk-unPzaUfot<5~?YS>dOErgdYp~YVv-4gD2mr0Jq2|Dv z)hqA1`;PHr#w^)&377++NrFTOgqR@YjsCs~Q@1*C_5uLtA83e&1PfVlo=GoigKqS@Qru z6Akunl8~oq0`4et>0zNv-k1&F0arK#QL(6zVZL!@hs%KEUQtD1%i)PPHoU%w6@rxs zCPyd##w4BdOB+NG68oF9apPux^wTdiCa*Gq|ILNU#@~ zX&8_dmbK^&XMdNRUEg>^zHCJK=phWFH~zN}gh8C1Q@KU55#xTd7c* zBnGx7fdI-ikX9;J<2vfu(2&+D5kd$7LT(%!tR-oCTfN!J3|NF>#m3&Z)^D0MVa)jM z4nYKnHnkkfkykWt-OPHr@Vvx^87RuUL{~>UPoM$t71_vDG&7GED6oyyxEgUU}`cS+i#ycib`UGU*!{+IrzOU-`y`64MN*r=DJM#TD;5;l#)P`L9`9 z%{k_nBVK&w`L?z?5lNW{VP+H*k&v=)U}(R6_PKrO9lyKr#^;`SW}5{IKk$L~O&mG$ z#P^+S|YQ^=}-0_&c@D-XxrG3V}eCfhs)HQzSzC zLI^!CdWjOIhLc^Pa-kzW&*W^gkblu^$sc5yAH3F2GE#Fz|?LK5+G5gy8S~xxcP-O#HUO@Jz{oB$p*fk<1zI{tn1$Pn!BLeJM4Zmsv6GcV< zQb4X@`P$agD`-Qn8rLJYot8`;FS={PZczRA`TxBq_Lcm<*5LoUZT|o9Q_l$2ZC0U~-m>9uFRY!`o~m34 z6WfS#pb0w9cA4Gwk>e*Gy12V{C>v-%TM~{{h(zQ`f&fCG(viBdK|t({1`yu0>NLH1 zm}?k{q+%TwA#BYQLBO7RSEm#JAk4+&NQlW`mapE}`}(H7Ctg{x`@GpZOdH=MM1)43 zBZ5d00vOEo9Zx=Y-!spT>S%xOetXOsJF1l{MA4sRPrb2v_2$j>T5Upimqac&eWZ*Z zQPH;(!Ob_Vc|bBhR}NP46WSt!c{X?U>;<#88q|6)Yl&LAeqg9))YwzreS#^zx!KyB zHIgK$A-?z6;{hNe8p^U7;-Lo|aOeRC0D#KX;zbJqpp`3=VApP|0%}C8rRxR;$Bi5F zKOZ^YwAt5et{-abvdc~qV5pTVt%kDJyshWX-+C?pwDNrH*l}l`d4`Ao#N&@KgF5(t z1I!0=LHlky?XufWy8yr=k3M?cbw4@%)YF&#`Og5be%;z%{OqSaBSwuKGitCgBv77n z)>-GAb(U!_*Se{-NK>~_BAN_1~ zV@9L})jR5GDnyciam)b<6Y$5p^ZY1LTCX91(n<@^{*FQL@C6TD#gMBJQSod+*SgR- zGIySk2GS&@Xg2ctD0$}RcRp&_HaGq9shh8Vvi{3t*4CqDZZmq)tdZTLYe_0C0#JwT z7LItb2`pShfb(CtACbd4ShB(Tse~GV$psAWe9Rn#K4OE#8&1G$xxS54*Jj;uQQl!1 ze55u18SN&JyDCB$vs9oxH6{fTX+=6CZH#;Zo9dUCIp+iS&0HV|M}or2IN{7iW)YJA zWN=3SU{f2A6(it2oAw0)3VTk91e!=W(nOlHB2wnK4-Zr@aM(jl7VTE**&&CSVsl1r zr^sV4f3^29uOZ2oQ);Sjt8WIpa+$Cbx_u4e(?f$rK9XqJT zi;#ga7CG(;a?Ex^yqD0rix-HbhhIE7W{d~nJ{cKqYm!Ha<6|$~O~H5!KF*hAz2Wmq z6rkcga{$8Xod-&}*dq^=FW^Rq91-y;83dqsQ3w8X9Xn3~2u{8c-_~?|MqsY1M28JR zh=yQpT`kVBj|=d}o@~laHUc(iXF64riz`uRog>0eaRdZnRJEYsW0a%+zR30r3LWqU zU}Hxhs!|MF@lzDYJEp)8xflaz8n>r0Sbz=yNPz&5NHKYAM_VevPN)y>ur4R9$#bur zej)(Kb5$2KV@zGm>^^+AX|K)fB;6!U!rUq>q+teu0)#(XY;U6`0MgprjsRL~(3*f+ z)Skk|M&t1pH}>{rG7&^tm>EZj8nT9JPv{-{O#kxP2QHq`Gt_9+(zLCHKqLTUl46oV z<>N-+*#e734@N)PsUm;`MS>`e(~STLg|^zt`~!Q852d>S4>brPjYw#tz?IetoWWwY zQ1e{nij-1>0#Im0Dp#NgNCmHDk=kMdgU`Q**P9yx5-DpWSp{vqK8Pa0B&qpx`&M{K zB$-%3AdLVubDt<^07&W*YLXFUj({?)+1(=qA%$#jtC{|^mPrkWh_oXdsMYHZVgjN> z0JNo6IS`2igiJ`*6G;y~@bI(GzPR5$d%ov=@9pgAX$@{p6KUWF0CN;gAlBI)VgI)}>Dm!;S(V6-mp@RG3$Ofx1x}EWXF5`JhM+ zMIx+38Q$_kmhpXfN-(@e0Ed3I$552m(MUq| z@>g!k3Q8diJs7>Qyk?EiFmFmHFE|1!f#vTakrFEsrveT9UWPG@I?YiScd5;&*Mi~f zpf{8hY)Xs^g%87!Xo1Wr>YJg9JeD1T*fN3}TUO=(fWNTbSwRI5$hD6}Got!2M~Q4o zEt@>V-j{-q2pHcZCXK9bH>3XV*Rw}oZoITg?KQ79Wt1Qd+IXoWA`5U(WA#tAB~&(vot{=09bk% zDL|$G020wAwIe5*E&cFws}#sJwpYpz<6HZGv`8mP6M4$Pdl2QOcO!FO->~_IcRupK zbFaR#X2YAy-#Y)OgSJ2YNDTmpiA=O6rSrBl{l{y|FS+TCmA$>HF|>AL--RDIv6cuT zY_#%vl1>=e)7f5kYjz5bn*goj18$L_lO=)v9do-tFo-#sSV8ap=^tuld7h?;5JCgh zQkki2b)yMDLST|4NsSewPD#C+*3V~l3V@i|4ZCfJA3yhT!n>0lxO zl$z~lr?mpfq7T-NC|hZ*0TqfINgCV7!4#>eD&db#OcloB;j_DNTYMaJPAUjq`wd%1)R%CyDU65J$BY-0GDQCPiC35@TnkabZLOvPI zM#S<0aOQEhLm@K$3Flux0H96PTM}u;G$7ltGYY+}06}aJ0HCwgjZucypKmQRG`5x| zB5iJBAwbaD-OlMVZ6IMnAT&s`Q7Hr^f>4{&^BPg1b`gDJP#}~t2Prfuf*iC`pa9KU zj{r#k2|xm&i3mbCG5~5Pf*o6sGel#HChR{jc(s3lh=9VF@vg2}b@;h7{z(APIibK2 zquVFV8nx@;+wOkI6i7j7O&LkVum@xlXHcN+Dw`*`<${K`;}F3m$IWlnp0}@9fwCKJ zxHvt4NYWIbDhi6g;Z~WDS+t{g?u|_kJ-6Yx<^3wxiOEE($r$=lfE1pD1lkl#pvkIu z?e=Hf=DME_LgtCK9sqldGdM;@@&-7Oi@gV%*u^Vn1TgL(bg2d1z<5k!(JUj!P>%D1 zD2)Ubmy_m8B*FGf0#1Wp-g{@t>cP2|EE%($$5sV_Qvp2LAG!8R)~*g$a)IYp&kM+# zXG+L^FGBh)=41;1dR2s$!x%1teeTH63XX6{$e|vb%a$j~@;I}X1!{N07(v9`$l2ZA z4ut*-JAqY4S|gV9R9>R@58-7j~ znTZtsYzGA>m=Dp+piN^y1Rxw8`czKnwqCSRU7BQynm_<@i`=;lxFXZv%UABS7 z0UePuzdxvWDr&5NDN)${s z5$Zx{%h_!Hpb*;Q!UV=^jII^}lG`9d1f7Av^FI2qQ$P5j?hzvZlDyHI2%~~XSbaqR ze7z9&8AJs7|HztoOaVYiE%_z_&e_zF-}<6RGTSX%v*ayIwIf%T6~m$116m|~08DuO z$oIk_jO`HXltn;5fs`qD@a4uUEAxF8ch4O!w1&ZkRW72C9v=z@l>ZS?G%LXA-Zd1< zc|X1gVAE4P2!}pM&sA@Dl!zzm1xqXdEStRaSN7aXPyx ze1W`rycrcC!WUwyI#i8jf!z5?FQFocg7D(%km4y|^K9Fucq;jBU|i7rDB1nQeg{xvD2r$x^~?lU`>czljl?f zSl>IS1x}nYIqMsEe#N>Ct$cFY-qLDBXU8sEPuEIywbvwCJ>tD`!L8s-Z*oR%g#qHA z_o6o(RE%bX6AdClDrF+2@dQW$K$1e%>Jk`25I`cN?RB)L^g&9Ih??;s0D(vZ5o&T? z(XjDv`>dt1mO6`(2msoWgv)_MCbA|GiBKd$rfJ}Qbd%ZE)&}+xTMz*Cv{p+}MBHt+ z-G2C^A766Wcfa|aZ#IS+W5-SW!S}8`?UeU4^DM2UBv8~68)k+8gl1XeS0_OPQc)v< zDD^wZ<+5KHU z`w=|VfP4@(u5UI5aJFB=uSv$2ptZK79{l0pb-7zJ1XQuL zmR)FB>}w6Awbo{sq?B2+qKgY7L;y)G+60K<`S`5Ec@o z2}h3Z7&S39uar`%K|%|LM*ioH_>@;!i^zQDqG&S3Aj;IBabulw@6oAZ? zg`iDf5V@oiW_jSO{UCMRbO3@$(ihyw%zW@1?-t3Cc6SJ2)4+|QLPu_K1txYRRPlUn zmyXsSWy2&R><8?!?bbkz{IX%eoa{orPaQ3fXxPa-AN1>j*~rbKxZ z462gB>tv<`%OYaH+aJP`VF3`E< zto(O;pXGYprp90X@zxc$EZcMO_@j3n-_tHyxkf~rHyk{LvN>_nnWi#LMW$3MQ^G|e z8+IvN(^3#eepZM`YfxG%O}QqK%1ymP8VDrTv8l18MSU>Sc~dW(Gx19w+UtaUW(*9r z1{9`=u%%#l z1Sf7$8B!RL<3s|#s}Z5gnV_*y1=lrL%oo-ck=}J!v@0%jo{-{J@_RftPd+e(9II#?`YUnt?~DS;4*!AlCd=+sS7}fkIWCi zbN&Kw;qg{=n%xw8OhW((eE6lI*Vn-jyY-CkfWem58l|wg#tdbn9}NSOC(n$Bz_-RJ znrw{5U(&#!;(#4$V1u5awmYZB{;yN1f;g+$wR*eCOJSsb84 zZOH_RHB%%z83{9E+m}IvT&bTdeQ@3S-mji|IJw;U8wRt{6Q^{I9^D)q>fgLMZ)RR# zkiCJO6w#c?6MEV^-rCq-BfZ16Tldsb0&T|9R!=3S=Kfpc(twjpY}t4|^}3Z0o_Q+K zD^@n;URohC%5`oD@KwCqBCrK{f&}uhNtRgAX}_`nbq1|}9r>pMD-#hR2-4=NUk!k4 z3JMz8en!w*BjO3i9dr2M?^v^TohFz%d1_5Uv(?ln1fsTgC7`8!3S%g7yv4UGTCMKN zbno#KoI6li$k>z7v7JH!5l5p;yb%a2Zq66zo4+$|X6I}+cYP5c0JlI$zp!N}(-oXm z-M8@=(Z2);Bo!^4N<8S`u{aFLTmXF3zDy($sZ47P0)PaFHXJvt22kg1#Bv!+Vy)11 zcftktCT_%M4BAk zR)S<^(=vVB-v1q(K6248lt&^W0+K+{0(!Hre_BsZijgY~!m@#aSVv$6D|iu9^;B`> ze=^S;dM4nJz0stz%v>x3h$vIE4C#-ETd7OvC9pGP{bvqVlig`ihxLf;=U(V{c7pUCmcNI$lWG`o9j3PqH?z&g(Ya&xxAfmgs&tlH8pP^MLQKCo@q!5rG04Qx$ z7RM*!d$e6g^i3Mg0t7KvX(G}j5gIZs0|Mu5kL+)2bF_TmT)y8B!UEJ0F*+YkU{_@b!Z$mcUQm(VXTyfZO|*K;C^T`>fPSwl4jgpfi? zpPeWMBp&xLGQfESEgJz^M|NOi@H~k2=Bhj=r6r<}34(Us9#eqal5-d%(2L+Qkiqh) zu-hT3=kVk(y9EK~O^7P1h=DcCHejJ<0+A3ePbv54ns2@ex`>&))0TKX}Pxnh$l3^r}H3~!u;CC3ynDF%}fQlC$=@uPatqGz^6H9X9K`D z!Dg1D&<`ja6R@xa*!hNzAHAPB zZK;rMXU_!ca8IyA^jBz_J(qw!0PvTzM-m1YF;JKaWZdJ$vj^8t45B8I0&}e&cbOzI z?zw$WP2|dMo~T@F1StYVnpuu_!8v#kksPy6_yij=^a3=D)kz*p9%x?_NYMcTK0M0X zc@ZiB!23oW@guqQo-H6;U;c!W4T51b<4Dv-e0!60D|E zzwL;KAW#~Yt|C&9W!goGRn`4Je>_;#z`XraE?#ZryltV9t{iS@>sweJK2hZVCQs}@j2*1-5>B|}H34g#IH-=bRfY>|)< zz{h&>Tnm0v4;@u`g-Ags+4ec&gJ6k-7Vy_*3JSF3te+~7DIPwStXS1EpGh@?K&#KyD(Gf)_kAl}{0N*SEzIg92r~dAiBQVQ1rrmKNOE0Q>NacOX=R2i2+L0knZVfJNfvXzjn&5J#Db5zu8uoW`S!vAdMO{xbSvOEIV6_4gf@fG65j~ z1V{-kn?)$+Z~{Ok>KAlQIs=^%DNTSX2cpiccAb9A1way{5J?@|>Ov+$BOC3K9SkqJ1RP>Yy_q-9C4ZDJLK#bs&I*G=ORj)+WpVBx|psa~+1X zio+5Dy46bvs|h?2b6YIBBb~zi8$Qn27DM}eR5|{Q7@MhlWfmra%dW!FG20UX07;25 zF=;zOUJ54sD7-_o$A}owd3|Zi1tCW5pfttpK~w?wx}>MXMC84C?01*{*?kGwRr z|8_lN+Mt;c+pA_%2}ez6XSnrpYz_p}xp8j6nzw0+DyJObfQ9v2 z9&J4QQg-eEs}m#vZ#<=RiZXa_Fcd z5D4Uv14UJ!%?++4Cgymvdc~2F``(|4Gq6Y2az~d54e5- z0ITF~*>w&vMOobOg<<&0Ni2xCoHJgKg={*x%<)LD`L>u~4Tq(8w>G32g_W>un>dsu zv&o2nE^91W_az_z7_X=zU2qm6VwxmM>1N&nBt%)S*R;)p?;!FpBgUP^0>n={*RL^e zQj9P^MNSPtXsYDVD@zFP`eb$h6d!VUj%@@kwa9_0!)n_GU)+;5?OR)9;Y~W6UNG5$_LH9vB2b4Qz-G zMdls}S1f497&MCDWSd0*Q2?rMr~p8Do19pK7$*xd+jjz*IX&|H`stH8j8{&W`@|#T zq5}EeOe(U7nQ?Y06UI&Pg5>QJD9lwMih$P{t!rQ=}HYMMMsVSraeGa<_o{`bV`QV5o2_L) zE3Evcsf#}og5MbA$%d)g2v}mk1Z>&+5q!}^iWGq|tunp!?9rb-bHCH}->QG8*=ULO zRGRGpe!-hjkRT-KT<1Bdf@6+Bf&xT>=E6~wfYMG3nHeVc2Z4JFM4&ZNu0c@RgD4?s ztIgbF%*;J1XURSyku&%1nz?uR8_JqQ8Zd2Jd{p~($5j*nB254q@+@##V2ps`$WZaR zJ$R7$7v@LMsBYTqo51n$I@}aOSC`uc{MLLK6r8{t^UFC1g3& zI|MKmFBHo1oyVeA+B1v~4v1keuL8o@7g4hS@r1CwppxWcHM}$^y#bdEFEkRbxR~YP z85pc!qLP-6AGftz8dVwTL07MsO=1)Ljm|2cxbi&s`;U&Jasa!xr*jWN#!3IT2iuXEf zYZ0!(AGTRH#YjPX1*K@_nW-r&QVVky1=<9*wTNcBz-|bUV0kr!roM|T~JsYK3=3Kmz~J!A?uiE$;Oc zvd$eK%)d*HBaOlf+Y)@yz@J#tMKj>wCx`jUwY_U6NLB8(3)(ToTti0+dv25d?fK@* ztFvt;rP`g_HZ5t5C9@bx$+hQ9nl(P@YpA*eAy5JU+XB$0 z1?HpGW@F5$86RgHKwy>}7I0=}#j(D}xhZRx!XZ`++%OP`P-3nrBW&i_1gHV5>FxW| zlP~VE?N-0}^eKIV&CZUFsckjVS^)_ugw3-{3QeofYBd3{K^g%~_+g-r0FvRxARaJ` z(xE;A-f3w77dPqUpmR-go5=q5J$rTv3d!;iL4khJgGa8a4>|-O&9b0)%)973=T1Vj z_hy8?z0%VTPIHXUr{}k+vyh~a{rv-)bXRw0urs|~hma%^Q39X_YqB{#>~dv0AACWt z1E&+NEtoQ+yJXa;I#on+SWrFm@}5@7>&k`E$qnIJ>XaYARx$^?A5?BQLRlbiL#a&Do^b61xQt=MqHsxo z09Z9R^v{(myQYo%*PE;No-`3L1i1zjT6nGGiEKFtbH{3VqN|!4HwwUj5T%H6k+}X@06gm{I@PNIQKOqdtqA~8V6=`P|2q<^ z2oQx_mro61@dKM=NAt*r>(v}@qY_DF>>x9$JktZ4Y)h5STy>}a%w+LSZ39Lxl3!X= z=*x+Um@W(s{17-_So-i(SGg#3+z!#I#oIYt(0hQ%<1&UROhs5&A%oK!)1g1GFh-N* zOhV3`0RH$&gy}E{0|&)iW~Y)l9>U1c4=G^Ff$0znq2(|X!$!7^61lNbg%`w-&H9Tb z4)_mmCR6A=;*bJ{qs0UVAwmiN#%-fobHKHt9h3l2tBHX|zT1Ma4?e&0jWvUdW{fl$ zLxmOGrWw@MCy4+crGSuMG@3?=MM}IJaHa#1y_tz@OqeMx0dtM@nmF>nZNGfVl7%z6 zHV-sYDWnhrKspYxQBS5(a|4vlNN1$-2t63#CG3ErKy+y!nVT;rH|xR?NSYMoO*Ob4 zbq2;0AW{(0p6jvr79gY*23l#AfmUFW(~%2Luu1L+C9=iNg%t^>N*AXB= zphmCtTw6BVZs1VfcU7bhFp_FCQDl93%mop*yQG$m&#^M~;gtTbLLW{0V4uy(bk*1Ygt~Wg-AT7kF)s zzK|67)@JH$WP8l-A+wMxXrp)o$jhOym_hcfeZe${ClYRPL_1u@@8S>8k+(cdj2Q?J zwlWcrnMUrCMh=EWJ3@4`N(?1>;OsD<_+a?XIi8qIawEWK%naWUR`YzE;o2zg=pcV- zZ{QrKh!_Ih*T}Vlhrl-x7D&J?Nrz=eN)E$8$q}dM&<4k0!60C)%VYv01F|2&lzRyL z^1$jO2&)=krm6cs*5c8AoT+9>$E)C?dXMoCEVT;p<6n~NIyPkrpMxm^7AW61Gf3>P zKp-haGsnv3dgO~Mv$+!zez5~-t#!tmCmY%k=G%SnYY96+CRtrh`j|bsPd;$e^pVL> zQ+L!b5?_1~8|xSipxxc$+OZg~gXH`gr4U~apWlEfVAbKTFc7jM)|#}|N=tw@H*Wai zum3o@Yt;Mp+7XnRG^!1VhFTdSCgyeuK+Aj_$}MwNTa`l7n49E*sN9F%BDb#26zG&AmDTy2{IHdjEDr% zHcZ#t+8D$QfxE)nMp9_wdm|0@CUgSIO*(l+1VCAH60y?^P8H$3^|#)fXIwcYp3@(*mg&6xIj zaFV+lVV2Vp)SNr8Uruacx4Nlrj|YcW!t( zB_B5FG`xAO2oa=!B$3i{FhQoY-^_{H2~aSslY=*sv4tV=Ze7_>iZO8DCXS3@pNJ9d z=p$KCZomt{AV0h^b~@CrDw(p5U=Kh1^>AUC5{Wzn2C8nm5a!tBCSzyctu+X<^_Rw#Q}hcBj(DD zC>Gh^NE(3y6&TRxb>mkpUffbJXxiWnaNihx5w97;P=lG|trt!VUadx2m>eAF4TPwIfz1dL+dxF6 zesSpX&4D5i1oI}P|9CZfV|{DZxVjGfK>!L-0Yny+-wEKaF?31*hysY9tuE$Isw)k- zqPEm|UyV#>6p7&wy8CHXJC@dn{ETAYM@RPFQ-}sA?ph2ZanutdjN+oC(Wwt93FwK} zUSB(qf9bSCa+N8inku(@UUm}Ij z0)hZ*VvwJGzw~g7jttM_CYbM{#8T619oLjmG$={gt9IR0kq+C&zCeM1N^46t=17Ct z7&N(c2?#)-kTwIjS@j~32DC?60SKi)KyvFflif*ar5(2tfB-^GxmEzUdezE@|9;i-fXq#iA;v^$O&X*?6!r>DMp^*}On?HLfOg#`eOtSt@2V z@FRe?0iddAIS7l7!r3gIko=%Xred(Sb^jk;?(fZ}jg^fo&s+6}?tbp15AE1KS^$OQ z0tJs};WN1_{+O#Bij%@)9!sV=MlJKrV-P~D9Oz%YVe@w5$NgjZ@-A$?v1#L|`gn=L zitk|j0;iK3R)gbE3m9qQ(0WFRm`1uF!aP%4~4k19N1`ATbw_4En!1*j9A!e=z zpJUu&5JOJNM9QO}Rar&;rm!&-)VFY?W z*C8Ll_HMI_N)fnjNyC&kCt7rJk$8EJ2EGztbH$dNo?^mbF^foV`ov!Os7ZG*rt=`0 zC_&zjgCOSauosM!|qFJ-dmIw zdE`?=QZx@HZb55kuS*2b1X_c0t`h&BBTc)G37l6f8ZC<-wu0%V$;GFm*f99C|~XN{}-wn$;Fgsz-w=ZuZpM`F^$l*knTQXwHy zLAH8$oj7pLA-@W*e4;Oy1GU^PQ~O~cOqh}tLhjykBBit@+IHsj%g&fFz9s~qls4nK zm-NOeFfj%QD2)trcrnUWqs`4m##*x%VpzOMO!@`}a}6Wf>ja>+wiX%Vq%8%)MN+SD zD#W4MASae00s%=tDz#FrMkA@!P|8-85nx?PGedcvBM@nwq-la8%QDa^t=9-ZD{btQ zTAB)gJj+mEnxq7fD_u)c0BB_`Buvv30JQN>Nzhtnc`HrRnyd|FEmD-EiPoBOEfUdL z@6uY$U$EeoTW?S5X-{{T(i#zKNeuuRjYg6riA*#QDMEo#B+X_s%UZR1y_U8&n=P%f zBu#Tm+?Es35!JASerC{UZ zDQPCI2di97m2JA>!d=o_Apqhw!-Au_3v`<|oJPs(+wiK?TY;dNwyqR#wp`F$tV8Fw zDI5a-RN~>I;Oj5CW zdH=n)ymaJQ+o)WdmVFRbLB$sIE5if3Tb?+Xa#N@%R0|_QGkSp%#q-NooVv&2$KG1? zhJGe_R5=^AQ3&C^&J;XKI6y*i)W5Z6KrKX1&uTC zOy|glmMOvAfi!AA^uByjPRG_75c@Ys^S!uJiM(o(|^hFRXU@D@qGzQNC7(2u4 z=W6YSZU_M+tZdzo3nDM=m_Z1%+pMDUg458m)>><4l54`UdBJ5`FF{}|d5Q86>jgLSpGM7JSO+tHK@(wGzYy&VS?Jb_Y&L&1@<}x-S z(bm?z^MQKycD1e%B#kl_=0qxjw0nPS5I{saN6^OXHf||r`#Vtr2q-`bk)$Y7kP>7K zWrB!OB%qo?c0f`y{ziLjkjO5uIc7_;3L$jknZzj;HUVA^6)Tqo78{!V%mpVwScRZP zAqH6;i6V-Axek#@7v`}ew`vJMqtiBANkK8Nka2!$Zy zyu9WZDlRI+z7msQG2Xp9z*8GvcgHyLv&jRSfTF*Q$zU}~Aso@o6p<5L9*6vRAR9pv zH(dPMssBJtL?94XZiH0A$W9S>$<0^Hta14kvBG%j5wbqSBvtF-*i5)WYu7Sv_GUnGf;b?`)K3zDy3^rY*bLZ5yV(K69^FbRPW@rkEi?CbB}YSxVLHJxuKFh3F6t?y8{BLM5{u#bstf)pESP*6S&&fDLo}$7dKZ~EFnjMiwn&Z)Dsvt zBH7%p6oC|ALd7!zrAvB&O*a!;u^qy|vIk`XfaKN97UEn&`}{W_A16A_EN&v%fHA5T z6}7V2!32OH1SYj410YS~x_V5Kb>TM51cJ+lOnmUe!B1oyeLyw=n%Uyh2#{$?Q2gw+ zrGI~I!^cl}=T0*wq!L?-(2pnxz-Sl+T*oXO7M8#Sg#RvAs=Zdb@4*LOdFA!J_T2sP zC!SdP=f5o8cERz-9y@02IGHB*-+$lGKx6LKbMCt99x23$CmtsO|8&>gk3atSP=D{v zyX zZt)@%$urMApC;*y$&+7r>4iJ*zH65qckb^Wy6L7Hr%juD+%fN3uwa{p%IazDrI%m1 z{3i5V!G6|=lbf+q3BF-Y2;QfIcA92!DF!8u;HLs#RNF3BFBo03U4+zmo`F45LQdP z(4dp&0R>Q`6;sTeCr1H^lvzXH_s3V>T(NoP*olM90TKuTTSMY6w?A?4$y=pu(k?n; zE0+EcIJ`_!`C z=gsV{*PJOCM(x0fTJ*P!6Bkp#g!K+GD3kPXx+6pjP^4r%dV-5SjI-EyA-K}heuWhU z0D#(DkWpwvBTvF#G4JK+D~u&5vVet1tX1eAhhvOh0n?Zf8-&r@Fdv7aK)_^WOsHE+ z#6O;2|Fvr$yzlYXI@;PsjqE^>udVEV;-#nm@W8T9pS;rt4x87O%9hg7_$`qI$os?5 z5mKYnTmeh*ILer!5EX{3tc&I+EY$QTe!#@3xef}lA||=uUGiQ449#L}@w!F`0J$s8 zX_gWpM}u})V4feZePX=0l?T{8#%$UvK z+Ar!5wzfuydXJhW{?Qr>tYhXracxDO!cfpQ<|CERsR%+23+s#s0F*-IPS9xXD;U;D zi5><3hF3)9T!0Y3Gv@@+jkXK)0rhAXg=muSnoHq`*zrjM(1e13NavKd0049zi4ck> z#a-A+O3AiSQ&0LPK)S`z5P-7&5w~=7ts@sP05(;N59t}cNkuvX7lL3(oyWns4;arf zK)hk^55`%>^Kdx1Q+!ykiSLSyAV{>5ZUjK|>8==kbKoMcHWxBPoEEsEiade5Cfgjs zsGX7t$4YZ0>9ERMj<)2u-U!0J_+a680j!QYos;L2qb9v2Hn$vHDM3bGVNNBQ(=?^O;Q?ON&kSG zEsWbX+SiE)w2VdG5s##W6jy%l>W3cu`-q+%lYSe8kV584%S80`_Dvi&{&S!I>?8kp z?03KW-8pBUv*+$hTCL2?kp|Etv^lI^ngx$IA6*ou5B3g4UejwYLN5j|CVe-`3i)e_ zSfPMKlqC4ps?`^M`#Y-9yxND#MWxPdB2x?7IiU%Kg?5kh-%68jr|JAR4ReRta#}czk+_}UG=@Jiv1d;$k zAg%KDj*gFf_=ETV?Y@gIzUpHiI|qf(nuO;xMC0@$0!@@ANQ4AB(?HAhmjy@cxx@S^;}Dg<8$Rgc*gfy{OpHal28sp*LEi&W)@-)dYS;hr z`fIMeX6~H1Lqp9>wSIE#4{rMH&ENa}m5UcI{QB3v{*Ol=o;G#rOE0~=-@f}FbJUR+ zee2>&zI9R0$Px9n_De3g>%HRAtA6o| zpYOHLULX79r+)sU>n2T}I5^a}{IV;*dFgl0IpegYfBMV$AO7&FHLJ#q8MX4QRXgvr z>kYsC_3HJjPkQ%zUR}0q(xgdi)~uZ}b;fUg{hJ9>#-Dk{sXH#-?yy4+_}gFa|JZpS znK5%Z0k#^gHEY(~e%sRD{Py};Gp0ZKkAIzY<_Dj8^6^n)#@%%D%>x62pz}|E{_}9+ zi8{+_h)6DI&Px*)*@}UP3Iq_eeu>;X;Q&)MPLun>Ub2|5CKEUrnF;a3x>6=yj;KJs zVKSo#c>plyBuJoFRbERM^a@*MN29|^xfD3eiPZ||D?M$|=5{4IS>GkMLin2sWxz4E z+nOnEZC1dKPJ|SayOzNzL`YS^>bfeq+lpON(e?JW1+@L&(#abyuDy5Z6XPayHDFM7 zCaMLb8U)#MPriQRHIKjV6HBsIjzZXLSW2C3!8oe`20R8UxS{Z%lP@dQtpD^6Z`gj} z!d<6NUf-W>+_d@CH`nbxWy;^4el3Iautl@{dFlwIr8p&TEDVRQw?$^vh>VvxxN~`T z9uj253m_FfdzwV2A2fxlZovvxENj7N!@BeYk}HkT3Vw{237(hyA|GPb3Y<3_#{#RX ziIf#K+D)zNDae-qj`xq~dYatx@0I6&`>vI%`xk68?cIlNv&Xg*>ZyGC<@L8e^2S5| ze)ID`xc`OMH+~mZ^u+1u&MtE!cpSCof}jfa160Iix^G7;RuNOTb3M z`!*QlPHmtIp$Y$a)FXOKYC8hQ1kuK5t`AQC21Hh~ut0f)mOyMU?a z>w?bOB8m+Hias^}slrV1qIek4Vsj69f&Yw{t4bMATwabXHsm)Z943onsFET61M}M! zjG^JgQ-m=)_^>nsZ{e`11uy#SPEv@ah z|2`dE9h586t`8$eM0=#ANOgfS-6!kuv!8*ly;U;Y2UO;AmO0MbEXGoe$)h5FmO~#o05GsNSI}|ez#P5+!DOT& z6tU?UZq5aPluEJH)bam(KhnDB!MW6 z7&d{Y7D=SZ{!?0Oty_vfqf)A+WDQBxNQ~@wZPmsrZ@Bl(HG^OO;NhdYQj=aSo-k*0 zu?1&A2RLMULj=6JRG^8;lO{^ivuDis&LtNw+IHbJ*ZuU|51w(&55E7sAAE26j9K^p z_1?wv7hd(fs}DS2ziWT=lS{sJ(W$4N`mKwxv+IBH@=Gs$``h3C)TchR?B&;AeCfq`+st0K zVdJO~J>5Mc0HC|GQ%X5+>-m>n_T2^Z7kvNw*PeIYhiVsq0%VfQo=109=X;5_tH#cb+zR zOx_d^-Sx^7PrrK32j7{tWy@D==pL7XBf(g@`)q?1yDv=bm*rn2#Alt`r zd+suK`qYta9kV8mnK5b1+{t4A;QjmW*l4POzOA>E4y5S<`DA0qSFK`M!XxXTY@x_!J0lxa%Vw%XFn%6{{2PSe-XM1|& za+|l;lP6!<`0>mBwtDTrZo5po@Pm6UnKvp|S|IGW)yQM_o^kQ7|MjD#&;R`PfAw_N z|M%2gRh~~!C?G`MGQO19ks&xMSrjX?0E;~Les9Q$(HLg z`1o@e5l=t}3be^otsX|Reaq~!(77LS(flEsBA%Bg0G^50-wy1{SnI&MUJ(F5lLjGz zEx-_20;cG)^Xm`(z7Q`LDM3FZPp;A96(b`AkHQcu#Ybe}D$_{`oe&Sv6e2cS|8*=O zT*b(QL^o2;O2|y9VZY72&e`7L;B zMeJe_KGreEdX71l1vN)1#_o30LXweXxog`m<7&3EL zva;76`Ce~%gDjF|)`noS9Mh(sE^op42y9M!!3rtB$A|CUQ~Z+6GP#AT=aT>~8x5b_ zn2`#;T`m(NMdw9yN#`;o#83vZ^51YabUVJ~CsxVDFF8V7*AD3=Wn%$$QW{+5e4jzz zn@vT1KmdqIjhcOGU_))rcGd_pyMb(w+J$ir3$X*cB4Td1qI^C{K_aUgj+6~EN0Q|A!m@h4-5+IN(cKYm@yY9N=>8GEWx6L+W4#g8`P$q|)Kw)xE5dn}*JxM@XYZMX?5wvyB z3r91ANGMR6`>nMOP`iPUR@x1OT(U(nzCLr`pOX>hZ{w^d0w7IFYXmFrrc9oA@IeQo zNO#_O2V+$zr33Z()NlA1cgKrOfGn{7S>K46+|x~kk%T2jMI&@1~N%l&^QXU z)>>(k{(uOSQeHI&HYFe__uhM-1NJ*$?lyC4^_tnrFbfp{fD*I@(&mnD0bn9ZNC;z$ z5}8X9(b*VIC6Kab9IO)!DbMqIk_bTWQZaV}CLbO`>=utg4-F)L`KJ`D_E#7{o zoo?;v>1t(zh$v79DTNRsG5*pVoTtXCwjw!_m!hTP<={mJG1cuUloR-HW&^R7xw1yG zSFVAS06bJtz>3=K6^-m0bT|MU4T?6lJkN~v3Ky0N{jbmB^={rIL7sZ*X$$5r$n$*B;sv9}j9s^8&F0?T`~LRV zJ@(l1-6x(nI5>FJ5$}BF>2tn&@ug{!7z80Aqo`rjR9Rgh7D{6wvrkM~ZUyG`Ym{xl z*_PzIdvWEGQa1srAsB26k0mbQ{BohQxXD<*g#ytChryI5?lGpfUTbTcmO_cD(f& zMLmIMP-YAptyNEPU2o&7*FE;?%WL=CbJmp~-*4XJuHL~+AQFLAt+sml+4t{|)Wvsy z`RFyjeQ>*Z6OP$^TBD_<^blh)`&NuE_gz6Uvl4#dVh*h$2yoVLH68h?ZkEkkZ8w{p z56;p)NdmXMN}7Z@%Y#6WB+~bl(U z)!O?p+_&Ci3jjdI^OB~*ThM7rgh@GQ{1vZDf_uiT5t~%d8DxK=?xr@*Hyq{nAe4FLYOm}tFsZ%G{sVay=Q;8#gou-vP=Hcd z+E9wBl}emcq%zs()k=&2X``V?MMA`t3K1wpI@c=_$^=c!i~vLkaV1ttrfEtOh!>uNh*LM&7=?lWCo;?I0C>lP3v`-w(+#v?z}@v6(QE@^(2W! z6h)vKX(}ZN5ml3FMxdk=D3TbEWUZbOKoZAEB>^F1W;B4)-ik;7R%21G*E1;*MUq4! zP8y9&N8-}79tlycCiS$DHZmbZwWUQW5qiTo`B~>2p`x+FIXO^;-Wxe(`B+Jhii{M=EGEvXLW( z59{e!x^(G#@4a6esI^ZXl2ltnB>MX5Nm5y{dgVa9wqp6JADn)AJ#AF02@y`8Ia8*M zFMavMXPHoZBf!GY(7Cc3Jr zz0Matl2Ii#$2?!!4+s@W-?552T^M-Hmfjrq5-3y@71NDFIME6N-!ZM8K>_je;KJ_u zPxN^=z_F7v*^m(8BodLx!_NAid*o8vT!lq&%yc>ypQ5Xk-KOwop;O$%bRdQ0^T|pq z6{R#+&X+H9Kpo;ezRKV$%knGjg3aazAgweMDMgiv$WmGFuV)R}zrNlQi7d@3Rbg`^ z`Sdw)fK63C|Ha9M{Q0CVkdHZ0pD)Hbs)0guU1n83PFe{O5#dGsx%`(KnO`32?0_nr6@__TD`t( z*>WH;a@4SvYPC_XukGzs3c9*FA&PYfO_;u;v(V66WTubgeKKIC3KMJkuQKwU0Q}x) z)+PWG!Jv#(-v{n*bl;WkX?c%?1lg znhQeIPC^CDQpN&Ye|SGT&=LjGVg7SbkaG>q@QBXZDgeRyl~-oGS~mliV|ZH$7wP#o zZAo5p4s}J|37TmlL_8On5CKASKD7Of2>xf$hBZEDW7LII98 za(n?grbco1#I$>4{iO%1+Z;n#KM=Vs09iq%zKyJ=alB`;N&I{|u!?zFx|Zc;!Z##B z%x7Z~qkOO&=Q`#DujO9$+lT?rHAwk7^4Jc4dlSkk3Pe8CEOO@FXCf$98}VWg1lgTt z0?u%}zHl8>jy3((59Wb4MxB|>4hhgDL(8&E)(6Ux-*R6INo7`y6|42O6QCcY!W9s( zpX4Fm87v~lylP4Z&S(&TMFIhFE2aIlMR&DK+6?11QW8`%ib#FZOwyZOF*??33k1NYo>*Vo^8Sarp?6|`Y#~*j>#EIhu8nT*1 zX`0^qz`t(0<(B2k-`{A;w8IZOeBS(7I`|f+Rw#2Je_ug{LZLhxa z^6tCu+*fa0dF9o6?y}qd2Yvb{XPw>J+WzG)96xE=6jHEmZSSqO-*wMD_bgxj(bP#( zK6k|7JMOeYLs7MwtX;MC@++>n{kGc_rBgSay35YH?fa>{+uGYnNGzPJc5oiTHh-FMkzk3IK}BcYTu z#;AxuL8TJC{my&8{mp+p{`jL4CXD~aH^0`XX81Xb~_r68XFRaz-!-ow! z_|QXk-F4@r((?O1{^`<-FU{(5@uGz%eB)N;}5kWh(q(N5h8?Z|`VdxpH~hsJFGZw6wJV;)r1*NU3eM+2+O@Z|ol0 zy?pt~_V(7U&MpKbrT+4lOMdywU*3EF!{?v>)04jSjgiBK@3-Hl&N%bT6HYww>T9n1 z??3(F_+yUhU9;wMM;-=>vNQ#NC{Bnd%^HZPbWDx_Kva`zM{9edR?ljUq>>=w`o4ii zL+Ukw`g9#aMo;$A%D^%frvz7$754*Zs0d0g3@u7G!w3in62Q#_fE%X#Weqh&u@HVD z*n)>zO5~c=Z<6)V*wP!_PAMY>22K%%ToX3a!kQd`n4+Mo9$MZ;Alw);I2W6jgd!6c z>>1`#1kBs)%0=q}8z2OakpX${r%a^sK5E`C#VO{FfAvj-L32AxucXyDmir(DYG4Ei zLPW7)bOI1fLVj)_jHzUna1APYd0?yXj05RVfCxH~oQN7(wsP%2U&HPvVacM1)m(@9 z7i>b5B^@lrNek@kzH{UU6_qtgZnL65c9z)F4x0o(pomCtKhz4@Tx6CHf+O4zA|o=$ z9cW+$H!!ksB;=%14ktPi6j?2Vq4INI6d`d92*!p8d|sU;P6Py%B!1()b-%vi>7MrL z=k}hl+uRYoef1=chzN-yL_$nrp_FQ`#^3(jmUle!{wptic-b8myIFHnIpiK6R_kG=C2h8i(Qr#0Ek?Z#y8fiDiu{L(e*do{p1tR)N1_$1GQ>P zGG*e#U3T7K&g>bLC`wb=)>^sq-iOw&>)m6wow~cbmM&ZMm9Kr{<{NGjSb6xLcQ4p{ z(=VOyjlW;>k6Nwqm&-3b=IGDVYjp&Q1QH-&WE>GBbUVUuSraCSIG0~{R`|6thP<6d zM?a2~WpYSI_0fMldBTa`Ip)a2zjyLC(=?0X*kIQlNutTerOsI`;t=YTqYK+=)po zJ}#hqQd1a>4bIZCa?`480Wyo)hgT+U)A#t_DifclQL~`dYm-$85D*oC@XKHf#`1^? zY&f*Z!(51a<0`Lf0C*`I+Vsv9ffH5U#PpB&K|4m>HnTi)0Gp_x)gSylXFLWs12huv zlkHA$r_d-^q!>}oyf#nCIfS6wt%=tZpe`?3O6G4%AqvxT(HG|cyZWpN5|&~v#1pd28h7zGkdLf7~#baU-4muE6E~ zl;KBz#1wR;ydVMzMDTlS8TF7e=JgX6hOnTsLDQ?Pn@u$YmZFBt#koVd=9nFI60hDv z%`P7%!Z?bs3INJEu-h>AcV04YxJhQI&q$}9dlY-rD(d+xe;@k_t?%|)wMuWsvT z?OnGv5^V5azzW9Yj|MmOd4W1e69R1`%*L|K+z@|TO>c;k&UP51uPo-3CxZEI~qfP3${=hqkh`i(c=-Dv8> z+CVCm1OOqRwYB=f%P;S@&%W=z`%Y&^=i)`r-F(wc)wUJ@Xk>Ljc=hF%KYQ?JmVB_J zr+cVUvVUOUl1u-5`4v}v_TYnm`>S8R@#gCoCm+1~?ng`BYe_nO`jfM-zUtbqe(fu@ z+Q7&WBl`yiZolp3n{T@DlFKjOX3GVcl9ri#U@RcL65-CZwBdZG(}{iIZ(*o%y@%jj zCa+<=RYWY%@7i}9SIX_dCX-g}dz%h`OI1^SsUsa~d?a&Rx$9H$RCh(n_O4KwZO*c7 zsN1+<#rKP``V0|;h^%JO2r=4KSQ9oBs#b(CvxxVTpE7Unn*8|)sGdm#01gl<2W^c9mW*1y=;X{u+vfsY@4(}PdV$F)xy{jjUne@SuC2M+n$Bi9((Ej@_ zUHbMnPCRM(%B3HE{PDtti?&#>;Oi%zu*t?#KfV8cOP78mFai-}nKXD6!fGi}N)e(Y zIc)gQt+(6eo;&Y;;J*9!-goa;Uw!TV`|j=P>8!R?q*-i0cK$IpV+bttY4so*XsaR% z>2D=^%;fn%o&ufGtreNFCpKb8HGvgj|6-&M{>`=SLJ6jpP`hh26h_2y@0NvKfCmmr zE>Be@vdZ*~sh7Y6n+O0vfdZ0lmklrQ%Y|t8%Pp(VDUq@+=LgtFsT}QS z8ni~Iwy-l$s)A7@pvmPL_UPjME%?=(BKfaR9!_pnoJZkwcN`VCtV8DS2dfTCF9bjk z2#7-HNmBw4K0@NQ3iBGaSzkG9Ts!Hvf}}`p0=r_?I7bA~Tb#P%+X_yNyB|_-V9mRr zgdijZBF09luDSP>S6};R*WIQczweA%L!yY3aaGa!0w|C&rDjbWa_nAnetpR!m)`L7 zv3t$vY!Q+WQLmh}%;nT*(S-176oLqW+rx+3J9fp5bDb!U9SAV&Ri-9nW!(Uwlmv)w zx%IZc{`rqH=Wf>3-MxDC>ZKpPcglB`o%pSj&;HR5dWLiY!0D%aXW_yZpLyoV%{H5N z!9^F|e8bhB+GqdmcHC~(teNNh?3^nv{mU1=__Z+;#%{dHB(k%eQj&;-&<6sU6G92h znmkZ4SY$?ebsd_}iWcq)6e#11=+TM5By=lxI;GL}3IJBGTJ_TN&#c~ScL2zw#7GFO z4uPZs?Y#>WsJ%HoG(yoh$-8r%oMP% zI;pM^6OOc}B32utFiv%0E>URSc}NOcupo#710G8>QK2gZWEI*7I2g%`t-OoC3;G0< zJjDJ~H*FC%mE8brnjiB8GPtjeQ1E=pEZksykZ&d2eT%gRW`7N{ExR)XH0vv+ zC>b-ib@s}24_(>0%TYLD1}I4~^CY9~CB5aGnej&6IYtByiEOeo)TOM)GJ8A0zU*3TIGg$#NVm+kGXMR zu?+Tzh3d;jJSW(_TJ)}nJHM9f=|`qw5JJQNf+z!<4WSfBBBdlL(#K18b#)^mMiBs@ zfVTG5<;#~&o;3SMXZ>hhZ{L|eIOEk9Uwrk&7xz72zwe!X+QSb#cEP#l+^U%&suZ-4cR`J2u^{RgMbo-^n2ORxIXFE0A!Md!|(vGJB$ZkEYR2thTKzS$Okzy8{@fAX_m|K~3bJ?x+-pM2`-Yp>X3#>_L%`2Ln# zZFB3*w=P_~Xu%enISkwQp}OJkH=lR*4~GmH`jxMraOfe2zWMr_r<{7)Bab}z^Pil3 z!G-5jmLVdbn7YxlAN}M+bU{U85$#Z^~d zaoHtXELd>%Pk%OP%9KeHCp|&kt-DT%p-g)b-Z~ezfPe1j{``bio~W+}hpK z_4wmY?03LHM;vuD5uEg$(_VV{wL=a$c$b}b`{0B3SFT)n%{5n_eCiqheDdkT4?lF* zop&8RwEOnE?$~ALy|2Ianyaq9^0e=rK5x$4P3Ld=@S_iIx7{uW?sw1)H(veaFMn;$ zoVnX=z0E_9J~(ddg#Gv3zrVLPt2bg10f3}5m6^$dQ%XujO4e%w0Puw`eDQ(%?mywg z6ZY7B_r)(Qe)gH?rq7(&R~rCuiFIJpvN+~EmOQ!)$8bBcY=VmqIGUBfengm?VKt@k zdIkv+Fgp|o2!sjC*}yt`k;ixV%;aF91F%$yx#-4V2~GYsk!XSd+d*Dc?t4BVksN&+ z{P~+;qBh=0$J; zRJ6&r8m~GkJ~K41?C5htE>{MEH`8()@=u%c}T99-WZ^P*Y8X`05(2358A6;D$rhu>R}zz(z%37 z1O#N`sfz7p0bXoaN-I#k&F%8PwPKAa$p|;xZOj^1{clN88K4V zu<^Iu^7ko|#sk2I%T}Cs{;&S?!gH(D=&T=}(b?I4=8t~b+0`*+$|L|-wscun_xPXx z{G3ha&jEl%i(eiyX39z5K5@>RS+#mY$utrO0C6l3F_RES5Jy7yj)0U@h?pb@08)}t z1c*t3sLujo1B(Drj0pN<fAz-GY(O@>2nlf>h}ila}@&dP|lh7O_C33@V}swQ(es zii8j`5ilaz9!@%X!gW%b$v!kToEO`S6o`$Oz7^DJ z#Q`JFV0_&VQ%-+pAeEdTQM&7j|KW{7(;?78gluI@iG(k5)2&Q9HxYgM3+tHq7MOxL zvE|qo*lXc>V`qFamzvxbNZep?H$ql3W)#OCy8mt9q&PzcR^sI?E^mT_!x<=Iw9IKh zVbf}0^`A*S1w@@eV=N{FBEqCPV^@shb@yG_K6O^S$&T1Q0^%xQY`4f3COqfnfWWKX zCKuD1C0Hw7I_yb?V#v*lQ&0xj=m+(2c~ykU&mQ{G@KFpXGc~{sYN11U@eh6zK8GLv z8#$&NDS1tT{0^@+1Uu-DF2P5d_@k1Jl+~cWQn4VXAg2$^|A7!Gv{|&-nhZGj*sJ|Q z*pa5fJhL5*@VF!F<=ev zTwh|yTY*7`tg=O9;uDyJ4;VV6C=0!|5E;rj#O7<5YMY0ZoH#Q`BDSoaVNkd4EF`oc zIWkH>>8)YNa3j<7PLq2mT5qne&mE5MATBL zo_o&u2OoM+e_!8oPd|6jMHft-IPG`8{r!|F6E~l~>5YH;`_oVTYvqd70Fb7Vh|)$q zj+5t~dH%5{9&hUya^Zy+?XuJMjWpeS-u(Vry}hk9lO#~YQB-Yhn>KCgDJOqdk0U9H z;}{X8RMkr5`NfN0edU$3kzVkNU+%WsE<|+6C4b&(>uq0K_fis9h-m(%o8NW!odA$! z86qBi>=Ad~dh2`df4Fwt`rUWkdD*g$uf6K>5kp7Mn>%;ps1dbV{m7$^IO^!5q?Gk~ zeXFgu+IH)$pML6z4?kYfKhWr`wq{bHKt4%?cAXd_`rxuED_HI6%pdsZo znThzchGRW{vXEe}c!QZY5@?q)sg?Wbtq#lE?i><#j}Xx4P9v-pdqKZd2v1p^V7tuJ zAai)#`}xCR&CLLC@|D;Wm{6p#mz>?C?IB_zJ#Ify*re|@m5e?WUa|(Fe~B0IZL)j} zv^HXdC?W&^rId)GKm6%WufO)zt#{t?#S^}I+R3Mk9yJO8_TB%WaTBHt8`c8=kr0(A zKJUD9w%vY*Yp=V$uYcY77ybH}BR<#D)7{(OKWEk^S6_McZ+`##fBx&yDH~5e`{!TS za+_`2s@1EmzUIIG@|VBeaD88W;P@|o?WkjpthQE;Ip(+tlczoU_#=y6cyX7#4>;wd z{}?)K$f1WH4N==Q*If0;)BoCd_Pp!hu>-D=tL6<__viNm^k0ASPk3r_m>cQ@X6 zBT0}-IdRgYGtWMI(>Zei;M4o=^T7QN{KrWr-E!9*#~yXetU0s)apO%ZSFF@$0NTL{ z_DAD?4c1HIGJ&FQ!jwLqq`zzQhHPL~PJlbnFSO}d^Z|_K0X^-52*of0xKO&O1?^Uo zWKCSQ6;DV!T2tryF=#T7t_M|947h4b>f~l&KD1)lsWe@f{cxqN>BP$AUelliW`a@X ztXdvDw9xaOu$sA)E!Z6)dDvUltmkc6Il)%!<%zwW>DvDc5^cZQV=NKP9vpmcN<4Wm#L3xO!5-U&ssh9>*M zN;-z55;r6#LD>hgjX}V9p9lbuNksrzmJ*RtG@@t7uYd8=_dj^|m%sV*5uZDH%gtx+ zzQ<1M25Jz+eYN!64?apzE_wg`me%U<5hKz}E?cqe`GwC%aXfO===a`zf7tM$edyQj}Gb=&kpb^sXP6 zI%!->wUTC;o}#Q&lI5$`y!!fE1O0ttMvj^?c|vPzE0KyKv8K2G<=5X{y<+8rabq{y zXp&j9O3+9%jp^6k{9yFx5j|ZUStgSt`grMzx8M6{qbcJ@4)5vfuf6c$ zI9)d3O=5fJdhN?;ga+XNpCX^XFnrg-74$dMP(igDl1H|crq-UfF+FXvo4|?%-SQ?$ z2~&sd6l9oFL8d}|z>t(GiG*-lWpc^o`k+_g_(*xag9wH8802mMwM|sWAa(_8@6e(| z2(2%H6OE^~YIT!6;!&H_p1-sH(4|plj~F_Rl6Ht=rY3c1MM@d5L|no1^`8hJ0%hf* zr~oDvmv3y4v_3z*o}wS8#B8-o1~zAZkO-c8~bkr_J9dtna>qA{dWmn7%# z%&Z^xBw*@t8h1(!gF-=REO~)}-2CFXC)}PhU?X^-nW$m;5?0Dvxxpi4$N)zGa{t-R z=M;1?PmjV+_kIy~uB07qbj^caK}z+tYW3^sx>d=ft%mHrKel!Q=rni=8uC>Uf>Ex` zq>qyyF@z&hz&l!B1|2m3I1i;PxzX3=j48f_hF!&82o|&VxKZqJ#wJ;Uf;u%Km)t`^ zGy?#Dl#7m&FxowJ4J(9!dTqjl31h~LRs;fJ({S;_x&YDA92KsFD+{C=paS?{e3g1&${%I zOZWfuzWeQW;4QcO<4a%s!dX8$>!1SvpvH|FyV+J-WQuCF29c~pLT1?!M;&qP zRo6W8+*3R6xZ@_%ryp_X=Z^d8mwGxo01;6{0u%v?Xvv35(ne#@7{<&e&< znVZab?d6w}B-Y&X!iz6md(Ab^Jp26m^}Qc{xODyc{}q0YCv{M3NvQM5P1ThJ=alU|@;cDLV9IiQr>%jvhIe z2KRC~Kg6jT5imcA$g{_-)bZxbC$cqi(~Q8_&6?C!dItJiSyzw(DS>*Qu)L*XehYJc zuKDRe4FiqllbEh38faD;pj|4$L-XEbu~_i{S)b0Sb3O!IMtH>V1LmEM_lA)#ZzY`d zkC?0qP;9Gr+QecNtZYS>%mSd1rcWlGGI7%3haB>Q(@)WYI8zD$zI5DipeN6js#Ysf z5-2?Qzyl6G=l}u`1Pz%Dq-l~=*4GG)&y9YxgNNIQlMIsMe{rAnQb&7r~$y}vE#n}m9G*}BgZVMo*rO zEVcQXv*k=jpKNn^TAvE z&P;8J>On5giZs5n?AwQA|~Hq-X2>llZQcnVbVJAX_1jvo|C++*B`}Hcd`a{(5{Et zwO<6vC<2ZR;3&)|m4hEk27d0!q-vx}csH5r6|XFtMmromTCXA&V%h5c8}EIwHG&-% zOqejTWqofZBB4xjj?U#bIMB4Ah+2~9g#Bl}zjXC(3&unMv4G4N$f0xs=U?dm6$$*? zqwhPiIS8<;Lr-I_oFrb{>EHu}2^M$b*jz=^nCn&5B)j+vj(`y=dmljemCj zIk(<;>kWUqZkJtmxc9zC4?Fbm&wl1JzxnM&`V28i(9zy@|3idzj0^sj&Yi}B+|-Eh<0-~Yi6-gxz;NMM#VjymSJAOHBwj>+RCD4C{}Bwn+2?LPZ_ zYKI+myz=rt>j=w_&-&SAmtKDN-M2=wW*l+k7w@_2wzjs8{{B@v?zI1(FaEK^Bs0nfVf?tNQ`OQYsHT zboN#el;UJh7;a-Su1PTp>4*Rz$Ca)vTd;(&it|vpD@b9>s#vMmXXVZDCOYf~PPGcPD>B$5fn7{5gmF!AhW zqqm*Fu`*BBqZK?8&qW1q`bxPwg@Ru3yLN+u$nCOF)3TbG)kdx+vvF-$m{;ypPk~m6 zl`4f;6P*XdE(He0>ZKDfz5<63B2bF>bKy#18G=Jf@(P2w3Emv?2DLXpO6Ha+;C(~q zWNI}=h(;*^3axL10Ej!{X?s@3%n_~KV36;o2icgAuNH08mViVVlARKbi_ds5&0>J8 z5-l1?07x$-9D2a%a3@$e8I>(|V-;iJPP5{9(P&m}7MlqK((V@mfOS@ltRVss zM^PME6ITI%h$6E!3Hn7WjkM878vrnNMS$6YVJ@WN@&fA8vRue$m6J4TNf zrlgcgW~qc$)nBVAqSm(dDAwtI008Y>odA$#jVOxly7Ts9k3D|b^5w(2hfkY2ZTz^g zE0!+H8kycYDo(11f)MpYaa&v4$>06nZ+`o$Mx!x$^!Tyk#t9Grki-!XW*JBYLI8r7 z62elaORf(rlY#}E|7kUvpNTKo!@&3ej$(l;N5y`!zXBoRPD{yUnZRj)!iB6{?#=QS zYy=AJ1}(s1bIK@8hy(%(2_O(8H}$>g5ol`rgNnvpZnwRBe;Gp1iCHf`LRqZ!vfHvbnKpv7qt^)!c;#1#zMfPWzm1mQ7*b5psJ{f0Se;}zcrF1=YnMJ72Mn+O9%Q6De z>52*vBP60)n(7_>6aWf=hzbBAtSdE8%K*((r-S0Wfkp#_(7Y*$YV}5I5|dQ_`Mcj;^2a~@^@=Nx zIP$Q29(v$6zx?&=S###jnVTsol7!+oH$Fuhr(n`hFw3?y3>s!^@~n)QN_rZ;kAAk-L<7A);eY{{H)iCfV@Dbrt`t|y zi{~1~#)~OeHW#ZMBz;fUg^qTZ+$&%T^Ed4YIz>|&fU~y;mOl$IiY`{+;^!JeW#ROq zHs|qt@1HLbm}0vi6w3Ah)ukCdC z>8;eYtpR9u+VkOQM98F?w^7$GPTb*&+n&4YnI(HJ7@O5(WTw)P%+V7FHnN5QKq`*J zk`)8r`_(fo7218XF~d3pDMIhrHnS!?`rL#|Gn!#5fy*z_9Qne)Y9Eb7z0!YbWgWson3s>%rqb|M_dLx#q`b{qUzh`NCw=!@t*w#tsQ%{AL?yY)j4K2~k1 zj2k=h>1P&x_uF3|K4SRocilc~#>~quz2uA^oYB$I_50ucB8no2XywWk-9v`#w#$xx z|JzLuKKR95cG>o^$NzQx_1AsoGY4+F{kF#(an!=+p1kGO+qT+z^S}S??_dAM$v->y z{LB9QYbEO+y!XNrPex~)b=GmgH%Usa9F-KKa=;2;$rG>Z-L#8vTik>a!OBeJ2C~jy6YXQFGsjjb13z(my6+S<|H z1^_3V`1KP{{A!w}Ns`z~5CD!l`pBGluJ4Z?Gy2Rk&p7pzlOKEhpBMh>qC0QB{i!dfnQr)~L3(f=XH{2_nWx0stFLn|#hWKRxruKf2@2yT5bNcb|Rk z*~|ZO*~zDTTPh{9OerNZ+0ou9gjl|EdGFfw-9v^5Bmj8top%91L@@xI^1UA{TfXe% z?|tv{$9!StjA@TQ{=^{%A6y%#sZ5iZBv4V5D54~e-+TA{8~^e5MkBl8%By$ZefNiWW^wO}ya;$j0$B-tP)v42a4w=~~U=$UAMT9X9hXhnbD$d=YL%Ob67 zw7S1aE~5MJ;* zV>TF$vK>WAfEaAKgAcQMNgD8UF3{&&aY^TXD09dv&=<1_$&Vlups4&e8ftvTv!knP z*t|_=&6+ta5@Pt!o}SJT+ibnnrkl>GH`Mz6fi1S$`M3Z1tI1O)Wofqc7MpLo)fNNw zIw5Yc#pdJ3kNxPQWqp0MiDO3n@QgE0KjVz8x7%4L^_%~^aQ3WC8jUngA_6lxk|dSB z^=m&~^6{vVBaS}m;6|g4h&SDK>+)5-fB3^6_u6geEK9$C`l+wK{>Cl0+C^=DxA+n%QNjR9Lx|AzOBosEQp_y-@DUb4+ z2jfu83oqq>Oe&2NUS#*+&#ALwwqZEDX8nt`Eg5&@Kr{xkHQ?NBa8%4wGs^5muZg{$ z*uV&p&+fJ|H8gv4e_74CAAAi}XyAnT0EMrgz(Op$a6^xaMp~0<+@5vi=3P-h1w;refP$rKu^rk}-hoJ%Oaf!iPTwotL7zVcuw4C>ITlNc@ z4X!qDvE|!Ed%u`DQ05Y#WlM57pFBI*d9!F@KtgXv?>46(1OR;=8Ah={VZw9h`r^+s zQlwo}%k^OHYoujTNvQy!ku};|+a^t#0sz-vfA!+U3#-*?qu#jpzWZ;u;U8;OtpR{~ zz0p5V>+c(=)#{B#s*f*RwtV^Z*Z=LQr=D+ZYu#h_-M{js6A*F5isjv1!*<+$7XY~V z)|(eCT+}_JD~h5QUVQnwzu&OrgAe1Rl9}8zX6Bf~Zh({=+B0y2A)x%Im1t^#kk$(Z`h}*?Fg(_Stt|09f|%asVJw^+sB6)cgAe zIy&0-Kj45yqkipme}DG*#VxI^ufF!yDW{!=2y^Fe+B2k0uL;FSNV93X$(Ykyjj)6Z zP)2BwehLKhH{Eo|&=ISafApK*{b!ab!06@I-@4?|D_5`Uz4^A=&%f|jD^~TjR;!;q zaR05g+)N0uYQi2%IXwgCdh$_(s zAAGcW)hYnoVY{8?%--acH(tBo!t+_mciwxiULRrMOcACc%K4VJEBGIufVlxk2ZjKMi3n~RbybpKovqKm|3OsaD;YUaSj~fYMQ`?rqK$mFfzlWc)4zIBDn0CeKoLTn&~Kyn?hKXeRHy{ zQmp{M$)}w1>~qi0oi`5v^lDQZmqkL52vP^&2$V9BI5L4VV#B%m@IZ-7E1L=wW>M3e{=2_=LQLJA>~9bbwNAw+s#Jb*~A14Td~L>$$#Y`?wt zeCqK>?zs1^KV1Bm+aGxF*+tKN;n<_}8e8F(=sVmoY&so{W|E15?6aK1tPgkRhN1aq z7jKc{C0*QH5sEkx{b~B{sx`AljpXCuofr4NVMEW2gC<6SSDiriMN^q@tQ(Xr3%>cu zxxyp+sgzsFN`=rE<)|%hixk5ZpG1~~XkxAkHZST6*jaBXd&QR|E(h~47H+wCOwrJ2 z(hD{vu)&L2Q3O(vlB6U7fXd+Jt6o3to42c)-r0<#BE3U=Q}V#l9|5k)<+c4ZD#eMm z=JH>^bkCdbpK;s$>r<6~HhAw#NTcc7h4EpmYLx?qPx2*$c8eP$>JNS^zg%sw%LoUR z1J*60(fM>iSiEWHn?y`=RojaE;Do9NZAuK0Wn67rtfrffx&n1Vo_I=ZJ{n zSS(vzyYlWglGfef-ff zRB20V3jjnhn$$4>P=p|fsL_xB(2_(%jWkOYK`PUZO z>lRyWz2(*mUV7pAm23MRfAX=7H=erFjyt~o)|&w7?YG}HWBROV8*Q@nwmaT)&s|Yc zZAgfdib#e{nluR!YpD)+qXJYQ$PkS~JqFIK)@96NESM#^@pBQi(x+ zOx_>>C^w@4(0mvRpzwR{^-xDQts#WL+u7y@p+LJntqdR{GAD;vOUQWbfSyA21F{?R zYV--z`zP7}hjXONKlH2Sy%A`9I%m@vTNs5vj08pkBNV|uVE<6KpaO4BOC}T;JQdzW z(;#{uB!kL zNCGS&X>dwe&oY&!Uc$%?BWj<=${c1z1F(!aUMu&6jW2CfspDZR)vLB9V&D0v4l0vj zIW9?@&~~-v1cPxVLu1fE<>}FxHv&kS+Usdu2%)UAP6YY@=d@85LS#|`04aq4QlBbF z1c(Cz1BjSqS(>T1BGNQXvlJ1REnf)$haYm-BM&|D@WYQBdBo9MY`Nt}OFw+@!3XBd z+;qaY@mp=PB@qb(GCSjg&UL)w&bz*F{Bgs3hR&WhZ}^B2&p-P#5lxyrrM)%YZ{K}y zyx|}JdiQ9on38>ff^!`K1?9oRiOqlTTvX2%%w`kJ^3l2H_@W&o~x{_L}U{Oxal^B3ox zd-FeTYHM$O_0?AgYPH?=*zJy+@3{1@f4=y4f0(uT{CchTu}2@TR9ZiE;C?#kPehT3 zu#wTEiDSR=)o-19&JQpC%b%Zne&PE5-nZX*d&rQU-gRr1zWd?Oks~&pyV(aHym#97 zPW{s#|M>Wm|6H?rjR0Eq@v`O1R>3S7J$zIpsXo8xnFBv_kWk{Mzc_#9CiCuHa_2X{ z_03VE#ypTx2g+$DW-z_2J zbx~Lk0*G8_2T=euw}!$g{b2Vr4sxy&C5PyR1zg=^%WH*dk%Rz5L)+VCjT&|DORw%f zeR^ayux{ULPbV74+m2=;ih>dlL{~y%!dd_=&|T)%1If%MS(T3+}+|(I(o3b zta$~65i>mlV4}@Rg-`~1+CoG{FlxkzQ6oSRDDqH}HQrb-CbW}?N2qw8Z9^KlKG>`m zxtfF%sb8=X(jg`Y7F!BOUw<&yCCrZMl#&`TblBcI?4_JreqfbE2#EOdx>WJU_LdJ64+2*r}Nzu_hrM22NbvkU-G5vf4}D9EvC(NW0p$*=LW-(3XFKg{(J!y5Bf z!2!@m9=kI!@(uc8Vd|E-YidMvYBg7T(}rCWc}NYfU5>8^0f6*mpG?(9Z}%;E zrzMKOB=7O`Z!ZE+`7cNf5GpN z5FjT~A^!-1cXG7A=f@P@a0-nyFFU)g9-Ky5hzU zuDIpJPi;F{2%)DRgg|RiqdvGAkPyYicfa-8Ys=@(9KPF@V;dPMu(Kx?IH$C|*dflc zB^1K-DQAU1mxYc=qmd~kl~P2Yt+l)FxRa=Dqm8BlfXtN2NcrR=fnd~<5JCtYs02VH zqzHkOisCpH__^c0{NR1}pM2`cd+oD#MZ||3a`2kfYm`(1ammt;-+lXS0J`hWI}ZNL zr{~U|qZH}mQ=>>IDL0!xa@(T|^e{Fws}+`p}@+PA(B08aSo@y8!~ z-0SbW+c~7It7FK}p*@ud>WxNAduz2N0RWvH2>{3qw{V9cW}yUj6tLx!MT-kq+And7 zzz%p|zX77tmVVG!4muxUrscef_l6p$a5B(a_=-v%3q+F>7zRD;B`9vet__fKRSOi9 z$Dl)A5_siWYC==4yfJ#MuFx*Nm1FrdfL!P86RAva9L*^UTofX>ZLO>X<1PT%Srgu2 zrz?v$tx0U>xXWcJf_6#( z1!ICu9{E8oHeI-KZ&_w*8f76%Gy%-HNM0ce%wTb@rY4lD%A=BMX}KP#tj`YT9N1) zIvfCob`KjiYV6SQ6WcqxfD{0X95uFU=*ZFI#_QE&ZLJ++#!ehPcGA!hqXA&gz4o~5 z%D;Z@=p$FJ>%Hch>;C!hKeyRthwuOBta+Plu886|Ns>yEByk)?5$YOt-g(#W|KQ9C z8%=qB;o|GB{oB&ztH1xFv(7vB{CcA?XVZCqz523)k3Q<-m8it{mdVB^$dOL$!8vW;87teU;p+=XP$Xxrequ^ zNfK8pNm8k#nVd3V?3LI2_4pIMNuu@fr=IUyU*G4z&s=})jazRvQz{zL)6>y2yrXAi zoFo8; zMR8QERI1gaT1o0@cE;%^eg8*49X@{Q)6XqhvSis$&%f}vqrcSBHl)(g4Klm%H@`mQ z$j`m{`Wv_3e)H%t6My%Ii%uI{<4m%(Dh2z>fyPtnG_&1c~nnO9j_6^Ja9ADJMh(Cr_AcVclYZ z5duH1xz6WKdNKxAC~}Ns^tqJIwGW4=#93x0ogHdJZ6@)J6p)gc%(6^p=8(&1vtM+3 z%9y=;0txi|qp-;qW`YRKDt(hf2M}50xp_7&&GpGuihy+Jha=vCZoO19K_&nrzyw7k zK(u{n&V#m8(P+RxKU`a>`yLd2hX8Bj1fa-YF7dzy-rjW`h`c{Ucuo%dzR@K2!w6t;xk@^S%9J2rZ@ z)#BQ&sVTh#G-|S5%hF~A2=WG)S89kkbOC?FjKi|#18GYI;bI|VAqW8xLL8w$O5*6b zH&kJ!;?ST`iC)MSu!W0_qcB9e5DJW+^B~;To}MbGo?&L@u>}5tzYo6ek#o zOpy>`eSiP5RcpU-(rLHda@~pF{KoW6HUR&h&J#EF4ak`PfG zR|p^$xMuCTS6+H)*WGsc`q#cPZ`O>*o_OND_dn?D?2O|W5Wn)}uf6r=o7eyC=B!@3 z@E5;MrK(h7MT7z)Ar#=7Z+x(9#o8^lT=0u?&pP#cr>|VK?7jEjnKyUd#~&=Y^RD}Z z5bf>lFTC>F_19g$>73a!XUwcO>aA^UdPf%k*k|v(dwPcb>36@HG-=Y2M;!?OTWr4h zrYsNQT`?BzBo*NF1Mtq zpixVRd65~`?yR(2J|VK!3t$yQCpY(bYkYVKh|I#*P@QouuqU*7%-eZH-;_6Q0&CLO zm8UtUDmZ#Pp1^mL>;#7^5Xpo%*1Z0Xxm)#0g`5eCFw=pLX(^wd>aPuJ7vX z964fmgrb&al*#GSHooNdzd!qjKk8k#uB)qS#PH!A?QM-z4jnrDSHHgK{PWMNRFW*q z+FDwqlCx$`f9$b`5k+fjidP-*zG79QUhD4e8Pe4e#R(CN88zzcAO7&v z?|ygrij}p2`j8>rV@3^+<2cO-krW96Bm@O8(2$eHkNwpJKmWn$r}nN{+tJxEYWUD< zwVGuTfo5&I(MvDAP;aQ=Lx(mbAV$X?d(0t+el`-Z$|RtOlj=nmov)-!l0;_dr}y7y zx7}YBB5tiFibzD!@y8r}_#p?cS=&nhogM9+?QH}&d-_KI{hzO;YH5VC|>5U;@k_Nz5oF7N4aSUABJ)~FXXB+ z@f%L)p+NKYm{o3MR7ha>hwO-6ATaxjH(SS8Ai7L-(3B>yHmS`rn^B zJP|^YjKYocomc0SanUYACRVKFZ`C^b6287rCXpLTCrB9Bh}hU zX)JJs9L=JgNVe2x7T}x7JqIoYo5COkGyP`7fKv$(8{`1hd^*R}pR)!jKliZl{RiC~_0X1}dAPqU$v=N*|`&z=ak{bTyz2saU{Kj}Z@U1ztqY#?>f!RO6fR4IBqgO1rGyIly{f?zuNf4c|K$t#dx0?E zjoK_uAfkXa*!Lp-0#Fsz>(G!Yf8RFlzUP6+6?O^N{&wC_4qtJx0OUE{1x&d6MLNMy zA?Sfa{wr7B1ri~AO({|~*`G--0u)T_8bgvw@SjsEjxZc}`7%Xx@SdWlNXq9rIwRYA zsw@$SoKUgm1H*;Og!UpqH>ew82DJMpmD+0F$lZ6Cde7Z2pL@wacbNUzwhAaB?eU`k z9UqKivA$paEUmNJ{9jKjr+S#X`{H?auDgdlmxw5afSKB9jy}iqp zF3Yk^*VL%h*7mMZBz3Lzfj*gKaTG~KL%KS5-F>&qFTd)5gAQBz@e)!36+QXPv&)t( z|NU9NzvI?BFTUi@2Y+_|wQE;@^{Zd)=^l38c|WUG<65m=iAAR9?4O@=^`(-{{e!9(wq}j`r@8Pdzn>vC&A=+JN5u zW}r5(&DL9OztxtnEq;3Y9d_Pvhi&`%`?uV3i?e_Fvu}UryW4KRb#Y+~H$fvH5@==4$YQtIT5bEb1wexC?8GyD!az zRG_m8i6`9jK;#AUFe9HjL|-m%(Ah}2u@|hIHcjy2&Q5Vwj%$F~q`7|b%i4zMtt6|< z97E?{)z+W&x0xNntOR!11K5mJ(L~!86;SSe3G4-dJg9(k(E-7yG@2AO@H$f?KTlR5 zmE0-|H=#p?l+WO+mzA6n!qP;qa*&Ee9YWBR@*2@Qx%vE3ufPolT0v9_Z2%1hPdPy3iXh|&B0vrX zcLR3GH5YtAlS}J2iPZQr)jE(`>r@2ro1 zb14}X49S#|`Km7q5(Y;SGT z``#&~1Y%cbr|vf*NJ&ysk|d)>3`2pWD9bVcl7IkMtyEj86#&c>)Ei2nAV9Jki6Mdj z%48-0M~~_mKe|T|q>U_z;xQvfG%`x1YGi5uQe`>eh8YGhfKNfaVbgse%lJ<2H^7m6?UkzMIh!RLfjskHY7i!;336AuInn7K|i zM^0$)ag7#;HdmYTwXCzI(05C#17e!T!0E-H{@>I=R?#8oSPD00JsuD_<^rRK_qhDB zkh>LDXsj!HWT`gyt>CDq@(h)SNRxT(5OB*RWa~ z$FHwl`-dkN{&1J=+eAe6ZDq9`a<=w*o(OWQg$KJVJ)3-2BBi)-==2`CP^A|j-n4BV zbWudouXPTvVqbMqV#Bos#&ph5&cEnKgBy@g{2qewZ-L~b7yC}W3M?MmNuD1VoMv{G z%|P(xb@iboXUv-t2FE~X3KU6eMYP0mjK+|1QxgT#8C#G1>MnOxWz!&FGfMd)wtwD z2!GkvRVZKVpf2X-_9?eC+ZwCn;53H46B|uQH`jV$q>yzsgbe|O*IEQ6!xxkWuLQxY z&G9x8oao7<@Z!~RMTU)D!@P}u7f7qxoPe1+4UR!SQ zxx)@#^xWcQ%U8B^v`m;Z`9FXAha(O@jF67~{80pA#p<$J8lC2`|P`a$B;4O#tsL7IF9-Bgd2`PMl;SS3j>F=$78>_=^0-SlM*%>9PIDl z-)Le_n8H?`l$OXXIOY1^+m6K4XMRhVl6i+P^DBo8#;NQrw9r8Q4Q?kg+nmXQoLNJT zGY!uaHllI7;<#I{u?;;C-@N&$!g>fotF_6M3)t~Du+Y^F89nwr6qGmZnH04}5$slT zo+dYJRx#0Fj5-In!$6Jvo#(+QVxbxC>|{ov5^Ggh z)#nATF|Qbv5i=n9!un8Dg3g$uFc!doMntw%d!Y+95s=dn@W8tBH~cXp7W6Vga^fBe z(hIb2!3ZE070Z6Q)bsa(uMVIsgRLGK)_fVoeF_4B7=R*l+;H`=uVL$ z0Bwt)0Eh$tfRun{eG=;B0i*zc6rkPV!s3Jkf|5#-IbBMk0D#COtAGGfS>0+VK_G_`FuQ0O40B9Bph9-SoW zuMwDO8bm-P^<Lk^^bI!Om(QlJ`A<3Ru_ zqIyQctec1;1f`TzCRbU{mrAAFE~J_X$r-tvs>?XV(O&+_D{*aMas_Tef9Ue`iED}y zyQE+jxV)%l8kpyt1wc8DwY>=09Ff~Kg`N@V9cIG*fn`^LNB~1xTE4OEcIQ6u&<}3A z^9P^)R9g(0l9@ZojfCM?!^EME%nQ^YcxK2p>?!aPOyUKSyxar?&#VC9G>?6%eOqNU zeJ(MaC>R0DLi~n<$y0zb^ItBP3M?7$gnKLd43yrov*Y7dsJIDM1b`?o`_Q6PnYxVC zPKsPxHm`Q zH-NpqH@8uDQcKHfk^sOH%a{K0(I-#ba=~W9hf5_9^eNM3gps$%R59~2o7p_Pbnqag z6g#APNLV^d6J=buh=@=r$lQ7Xa#Rtt!o*f7A2*3IY@m6rk3*gVLg9(xG zB5SemBM2~Sa6%>|K6quYG3nC$^1iANpv?yWE&Qa+)<@OI?k#628uRZ481{r@JK-N} zfB;Og6(8pi!yIe?6a;d04a;n5F0K)PjE8GvF4t;C#8}w4*^Idgc|6A6^x_wTvZWWx zM=J-oG$J-wjs~I%HYo6KYU_nU4lm<~(k8I^BV(sq*dRz2Gv~5;o-EO!rV>O{EI4W( zVeU06=gA5$S2&300)XEo6U;^un5A-?8N*Ng%8sXBaMv}rEKDVxas1Y!x?0jy5>X`< zZ+y7^oXeiL=gE(10|P%gVdrhwn(ln0aN>bf??kp*#h{OqB`9c&& zh*8>*NhSKi=Z{RYOkvbtmw+(=$%dRWYoj?cr_|F!WR|s5TjHdWW|9boc6WW_gk!&S z?4eSsmey*LR8pywqLIUgegC^(*Oq4-C+q9kw%cv9!?s&SQPfCfYfC~z62+FA&z?VL zTBFfO;-uPA1;8wm3pSs-*=DnWL@iY!D#=A-b`!cK8m<)P3wm-QU~vrpgxGMomjW$m z?BxO%mPWJ6pkXv@8$~OAT(H}O&AIGB?`3+0$IKV|n@0~y#88>q&hvX9rwf-8!Hx?Z zcF`Jj!0k%5QUHA=wx7<^w{~$bh%Cv>oyV02o%18|c_4q4X6rWZqIrjREq5Vba!4gw z7g-cJ7%Ng>A{W@GB7q1NJeYnHL1eILT@Qc9X$&35wbcp#6%ZhfgiG-uu+)ek2&A3RCNm|E zRPgplA6O$y6&h}IOhTYAc2vN|(;%1t2?gm5985|jL~ODs^6JL>6?!=vfDSR|n5jf8 zH(QhC^83wzGoD8~fz3wVNg-m^hxtha#I`fC{59Cc@}ihJbW9uSNN}U+Uk~1O_cSz! zen1_MVHnIG+0k*v?z{cv>8HMV)wM@&yUCUM zm^_mWG_8A}lu{AvDLd!O3Uh84uwL727OR~w5Va+jd%%--C`6c3RmjHLjW9PLydLv< z-QDo&$W$#bM#L0o@!Hk5y!^_dRcpSw)q-8dja5n#pwhChOxbaTZ9=VlB|*Mq@wT6q zqTFN5qqImZRt6WV)xup#K)c0EzD#Kxq1YzbGa1Ye_Q2Fa9-CngeKq7gra-#6CQ1Nv zZVV5sSh-|J-dPaj+G82>JjP4BS`7||#b@_Av@oU5dJ`;b$u;5hrI~w3#O%2v>WxNJ zb$edw@O{4H<`@HwzPlJ4|Le7)sI`Su4CX(oga> zKqz=UNFfs=gmldB>o4Z8J#gEHF|ikH1ptm(!WlX@rQkwdnlV7%GA6Dzq9BUk#DiwN zzkJ;vF8k;8w=RC^t)=^IKW*NW9zgon3m^RBkvCs|dyS|hr+;zBFYhyrq@LeZ#ze9z zA1&K~AwrIo5MnotLWFs8b}YjXh<-JpKJbB1*j!IkiW>D)Vq}jUA|Nz#@nn>yQXqr? z0!e!Ql_DXCKU(ZLA?@sxU1YPEgobm$&&HkSqwv_{Sv}fPc5-{}|x^ zt)3#MVU>YWfDuc(C?|I!GE0UCfY>aA&l+{|596Yd%4^lECV*^^EnrA%=&}G{uvw6k z+@YPzEex<*3!<&js|ha2gIq_({XD>AdI?}7;ciPo@LMZszlzMZbXpyIAU$ZomKj!2 zIg>^hbdcFhOTR=W=B13_Mr9U8<)oA8n0d)ss6NOA&O7v!Waj75_Q;xkO3L$`~ zTB%f{3P!M|UazNF1VBVeDKqz{je3)p;d^16Abo0tC3W2arT^GuI^RhPz3@<5)H#tQ zbXZV03F%P}U^_*c2ZVhYQP|Cn96pga^^<=WAZJh;;PQbqw6a3CYwA=$Vttmruwuo+ zWgpi-%^xxL=kw-GZf!#VWSbtAa17;s5da|&Pvj%6Wt%b-=>^L9R>HlR{B3U8hrEFP z7An9bvWtfm*b&&kl`F$hNTL00`iDg*N@^Hv$}+r|#bBk1S#;f`9%2i_!OWNNfUYwG znuP*$-3%*t%;t*bYhYC9k)RYH;`aMY+;X>ZAbeyp=MFW$Y*50-dtCE&9|wn?9K?mu zaN>x`F$5r`Pe6O5v#GHP&S>Bx|Ktfk;uVc=r5?vWi+kkjZuHYIVvM z%$;(|vD@vv`KTBvRYZDH+U5*cqBn!+WqO&=&h?>L_w`5+H^P|NV$!v3(?r%cA^>5x zM?i-!5W<0`r&ffyNu(!cNFgFbkx)tzqA*KA41%T6o+t^(s7uoOz-X3HAe7dU1dxFc zC@_-NIx(3f1VT@pnf1JA=i2-*DguFm%+|61AP~(7P$&Q)A^@eWdPRiJ0t^_+LhTi~ zZ6Pei=K-1tF3)+vI?r4ZP_yCm;}y1*Z^0}Yaazx#v2X>vtFR z9rBgs*dMI->;bd>0GBo;+aLH{FT&2TOe_Og9_uc7!icdVBavOBAd`Z^@*stEe{vlS zIUN&P1x2~%p>&|zS`fl<2_o*AIU~yY8XvrvtzQNiq23JMySo?)7NhLJ0ZREx_Q@Z5Y{G%iYV|95WR0#^cJ4(|BjSdNQSi?_L=z z*~lwAa(|IyEI%RV`Ve%; zx>^{*6ZX-i2$M~&u^lsC8Bgf)Zko7c=$!{5LMOWHC;GSm@KJF> zz}pG7InU4F{Kr5A@Lk5xkR=6`XdSC%f^yXmu&_<4E%jvI6?q`zN|q~#zKI#G$|-+$Cn5Z z1yO4p?>KSdoRK5mSiSnWB_H1N)|;7Bf`AkVA&BfgV+4pUA=;pTES;g9n@41^T1G0N zTrxLp?g<}i^O_@T^OmiGET6kTRdE+Erf6)=C!-v+Ejnt}UW_oEFwtrauWm(|=oKm? zAdCn=NkoVg2!$XBNkOV&fp0Hg{%Y@lqti9bflS-3hGi466&LrP{#@ob#kq3 z-U%_+J4^XWDbk0r>TsC};MpG{wyt zLpY!eZrx$21~d(c$tgh#1sKVRn*4O+4-rL_M3EFwNus?s*?4Bp&{5TvmN<4(C}?vr zm{AmvpCdLR(z>}M^?(XSk=HmD7oO}epwPhB^--Ym%c226D58#zwm6EK0&m~o03h4_ z)zPhg7RI(*x0ojODgz3cX+gWTWSExa9su}#|H|L>4e?83D}b8yuesO_stU3sn!I2k zVcLP&ZwMG+T#2#)AVnC3O2o)?uD~%@Ew>(+{-EHORn5$1@cnfLm%*r4{N%Q(uBYj$ zTK~9?D2dpf!pJo!vT6s_S{8C+9AM5}WeCFDZI6Kx&0-#h4ut6j* zYmE2O4njU$LA0e4|{LXZlymIFDm)UY*L%w!7++fB8Qs51XWDOEbo+Z zj~0ey@&v5H%0ukrqZxD-OaLY?yttu8RE z;iYT|IsqV9BUN@GKm?c))Ecs*Rqshvn%C?lmxOnTYPDzomM(c+v<-!*=xB@E4o)oln!K!$ zEG|~yZ)Stq3jMKeR8k7;LQ}Hf8b(sq@sh z;_cWi7>saZS_VVZ`HFH3;m>aHgN z6P{%h9adoI&QcUNYQf>u8Zh=2`Kf4sH?Semrg{PAFD|BS>l{M6|2CSKv*$Dibr7rp zF0w3;XmgF2jQ5ALun!8Wa@=IGLF{g*l5+gvhoMl!NFaLzgBt>#wZ{*V_8@wSa?S#R zwV3Uwu{{VvpbSS?RbQYi+b!j)f`SmW?7=$1>$jtCs?xc6`USLt*HIK1wE*b#YB(6~ ztM$T)MXH7dcsh-~!o41|pGL9bhhdf{;ZQZ{Z0@%)JRLRr zNza^&@$d7g0c5kL$V*xO-`VHN_D8FZV(p<_C`^+qktIxCgmKk?Mn*FOma z-`Z)19i~o7l@eZZ1*y@ThYB>wd|0wv#U&jVF}emT3d2N|5QXT{zyjCEMagre!Qqa< zMtTzf>kbuxq7c;#&nDPoVz~Yr} zo9%39i#sd627hORL3S=0Btc6x*0XQ~Byt8vSSi_2b26tStt@QEzFja97|J#{2~T#Z ztQXZz8L(P8Y`J78-4e?(81%xXMZ%C`?wzKu7}`U({tuKQkQ60YU!UG|#VZRJee|RA z_l(=5Y!C{)$pxAT3t*~*+Y<%{uHE9ac7a<1wP4FQ<%fvMB*G$*LdYa#QYK0A{Ci8T zeC)-a9kS=pb|IyTqR4K6!CG&QfgCn$!vXvA-8@{CWzp*mQw!@GKu)@py=u8Q2%b6; z(61}w!j-&C*5@gKs}M-tz%({CtB98{!cIx$!dh-BGZ=AFQc7e6Lh>h06TyulX@|0v z8*ThM0#ZtmfO%7UrccuVa+MbB2_V=>9{Zm z3*^7K@$|iM1)NEZXqQH_#|S}UlII;qxy++6)|Bp%ZBBR##Cosf^|G?c-v*Ao4P*_u zpwGoKgWSk?$JJ%lIU|JZFNUQ65ddU&4Gd}~X2n=6a0)4SH=p!!mHQqVh(h@s5=XNp z0w{b0yilmPdeXv8Kxk*=iI)q(yxnl zc3?C?FrWb`InfoAw-m_m!r0Z1r>}>Wh^50Hpu$^wC9v@;XE}r+8z&`7 z!ya)_3)LnCo zuAIfHHH}h~^~sN(t-bO9y#8dz9$$la2vKIkf}v^!05E|&qew!?>?v1<>*72oh8QE} z90KugJ`%~rs3Mac<d_?SLi>4Li~8qDB^3I%uo4 zwt?B?py>+jbUbQc^G*;S5?jhrr3-l>V_&pRrTOQ#l47FJjt*JYG#JxozACf$z>z|3 zm~B##(am128Wf@4Tg1q0mtN(A_2lytFi1P|oMAy^OzWDq;JU%`F|(Z92Iq88aF=(e zbXldtkZS`hrUW1;@N>|b5Zru#V1sA*-qfOZTw!1FXg9}z<)R-3n6Oonm_GhZNYubZ1q zgkezFMUYDZlpFxtb!Q(%Lc~=80R5{QPu}y!KNr9Mos~Ne@2p0x003#Kz-kajD<$oF zx#;b_pjAtr;E1YVtNR|4-=0Gopw%Q!Dv1DG(YNmYH(p9A`v?>w7Em(C##}6m8aEvm z@P-$=;i}0QJUk-I>4Dc-GRMZBHgP(vLy6wtvE`WNF6)_2`YJ&P+KTyIHWk5*W{-*B z<*=RNs44FbA+zy(?gv2WjzROQr6c1EdlZz zZmgW(1=uW;ecL9U7rY=Yhe~O^M0Ikp!0-;hR_^FtYj1^-POfEMJK8GHb(vfA?B$&0 zz!I4;FpN!k29rjPL0FltanpMouE4an_d=>|qWJadWFo1Q9#*|Cm7{#{e-RK+Kor@{ zEIzR@v4IJOLK!UyH~f~9RHf2Z-#4q6PynXOp6h$~lFls;!SP#&BvP3KQbZB~fP^0= z3}r6#g8I7D~uy>`kGn^%o1IKV8jufC?IprCLll(VHC52 z?J$SHA|gv^uNe`Q426jtx-2ycs?@B9K%tu6U_(XN@?;92T|CG#$RrsROYVFe&!u); z9pRcZCjd$k5ho~w-rtvRh`zzA1ahsTY{p)wTX>J0x?%CtoZZHoK%=~L3cx3Vq_m8Z zq=+&}X-3Ly_+r=qy-bebisZ<%tB$yt%A2UbcJqPiHpeL|Ack^f5&Cw%|yZIARPa+#-vq^k`Y z(^_O2uL!syz>8=htGz{k+iJKVj*k#Zj}Uxqd6YaYNs(he%V!d}J`WA5((?KA%AyTc zfJeiiy%MsMU2zgEd1LtlH@`7={`j^^lJ!$3wk>|*!$~XJ9=Z4B$ur09bigJulVrAp z@C(TY>x*M7Z>WG3l0h^M0SBQPeZY|pVm|ot8}F=KJ*ubczL#EG-Pd>1q8Db5?0Nm2 zrMu0aJG`sSA>8qW%fr_octbmwrYW}0EJklc2Hglt8}2QQeGkqLmU6;I!E>v%WlcpG z9I{*njypcU_SeEO7y$VW`LB*<2J3|`i9~$zkjYi^SxF)w@#aVCXN>PqO2q;dIqeBV z9NTst%>y z97f1SyumDKb%5J<1H!X-BOvl?d(0T29SMW6W}@BY>9YPAL1HB!arhkxSoM^{Ko~o8 zO1PZLkx2pWG@*6>bL~Pn!uq#El-m{^AU{;#&VFYHM+#=^$DbHrnAO{+W+ z@m9+y!qG387?Fu}BZ5A_S#J`9%v7?Ovvw#7kTaYjk z0mC|D?vpPaz!us{fxv8{dV~9}@*Hh*%JpTf;R+!sxL`JC7uQf=$dr8tqoKX4Zh`Ri zxmEp61QrE%4*r}-aigSv<^r(w{Uut&m6F}^&l%CjIm>M>sH6spT1)KLzi^! z{aqd0;rW|7)Pev)AfRXhyd6Ix&`VjHc8dxtV%c62n(_o;Mg#z@6-)_M^wPS%Oep{$ z5$Q9L%+aBUY}Z1L1lz9b2nBf1CP?m~`G)qyC9v)qpQg4GvfAD-5p9>hZhzVg2$7>U zhkd|c(+87cs}xEFEeQ_m6df&?WmIbbphAJ>Jl62wL5o~c5`a`|RYY;ryDt0qqeiW! zq*RC?g#M?up)!BV#t(^%WkWhJYBrAtAiZdVx5+1J^msb#Xk^$#JhvFc&v{xq4FOFy z9|*H$hI{HUsv9-qLPUx*B`5+VK`Cf$6+^nKon29ysajnsKp}+AW<&yE=$Cv{4nZlE z#1R1YN%i5{{<_REsicmHvS}%_qS!OH-6zCpRhIy0#gS(nM=t0ngIxhj1mA@i7*3SBT3q6wtdi|O}D4~(?Dt&I5qly2_ zA#QSM-vABZ3>DUVCM!l=TM$_D;kON5Sk(4hYyWRvrBHpsCIVw6cc(yc005*X2f@TW z9I>EfQ9wWtLbW7uC8kCul+BW?lhmA&L=gaFN@-rT_5qWw+^qU!9r+~6{okz zbUIq>Am529ug*)rC;^N)NT!-#T*%AFBJkw@hWCkOj5_nt+ihq}CpMLgPFx0-MDy$_ zTdTQ2L};dXa(&HzYM{!hWlGhA*nBg@I$}Vx1kLuSV*)mJ>9mf#4P{@#^eT-84ldukLyAaxuYS^@Hjql(ebZaFUi;3N?rK)6j_VnD#qXc3_pe*q zyY`r`_GsZJ+}4GKXk$qfl3078n9$*tf=0@JBSa#%RV5&b=a;Si(|wOss!4w=TSpK5 z`TdV1l0>aOZ~0-D zvi+`SKAJUg6Qz^_0hV&KXy?%gXR#3r1qHaWo#Yc6#0rvmJ;?DSyT}2;Z4v|q?}ozD z5k$DZ5C5)>B2Pg;VCO8XrD~eO0KJG7Kx^&|wsP2K%y>C$VF?L|k*cSI5Ot;t1Z>4D z*?y6oaM9)t2uDjUVri)tZO_Y~H_f;Zd4S>23=OmmS-!F;)PR*#V;^y`?mOvmM2>#* z#lr1tO0E)iBz8Zn(Df_OSuSUQ8%w2dT5S@7#G;x2CE6)RixB+ea1J7uco2*ctsz?% zi@^Xk7Ll{#uVt>Stx=clZPB8)*REaP7(c8HoM~a%f%U=J5}|$xet6N01@$+$dewTN zAmPhwi%^$Yd%)un0j#HPgbSzv`TpY~8ktPnQPul^BnVwlxLuwtF7x(U*_H$j9|js9 zI#d#cu&DFLeEHp=+#u%Eki(5%nCNCc3CQ|A_L;tozQ@9E}9*Lnv@A_!j}s#gB>o{D7wEP5Te*OUI4)>VROfS zWq}kgH}jR`$dSLm_vZt~;EXRV>dG)@Z(=w?h7<^8ohZdhM|IOf8V~#~d*`3gq-}vD zfFl61yVhYO1fs|%9Qyc)$E)9CPP3Da#o00*&DMC!SEz`p2{r(qdAsr6(t0XU2$4kE zlLSPJB1BMVrz|l*tKl8wEoyj^?cl{EtcvQkNs7!h?a72*gZeawi^Gc0IP0RW_7&^DP;pcIjI%#=Bd zl}LgyuH0xdgAdJGDk47!=t-5QP>~&U7Slq#c@6@A5H`2i1`s@9S*wwVlrr0KDuptG zOj4Sy>FSQAP3xRGwKYv;BO?*n$e>&P=<9+cj+PG87rwuAZKDxIm?RO}2qgGH2L!Yk zc5JfBC`avSTk5mi;&|JLTyS&5=n6Q7aaNY;pDu4>PYTFxalnTwq$DSHJb2`vBA`2H z6@U~qvTUHy=t+{zCry|(Y^ZSLt2Z$9@ott4P_D78N-=0~-OfuP=Q&u-8u-a&75f^9 z4O#eNSOyD~^JswgVVq)S@-%NjF&|#j=pcs1zj>AQ86gh=d&aO@e3v02ties`nkObC zhXj!j%h#-3S*yjBctXpt<*7#z|Vf8 z!Jf--pt`cORG6Mz(oW6HL%f*s7Z3IJ; zgV@@gW$s;Ztn?QJWHeNOHb?V$GIVnr3>5*9gi^;Gg2IaAqjD?@TbZqo3|AH7H!gdo z*lfu-u#5>8RtK*knM8Dmlyzb%`Mz#%?X``A%S%d2R(Tuqp?{oAFC8ZFo<)Y!_1fWww z)`%%#$iP_Qzc7H5%>0}_-x)z1v|!GyufF=`n%=h7ssNcO=q{$Rx z?w$z%`h{COSufy3$L`!8%jsQq1)NgQ3pva%;h(F7%DxxHEidNGN+6N*)&YPW83SI2 zdF$Ajngsyd9n8~UD4;@(R_HSmUl`0;k)oE0*lK#uZ*F|)xwqGCHl?e#uPy)qg^2-~ zybr_JVEcx8k(i#bvlBkL0NJyyoHgQtYdUa>3P2!{4%Zg2X-UJ~E%9TVM;Z!dk1_qf z9tvfpC|H9ZY{1dcdJxbxtCLJmoss30Pl#H}VBYW;X zaOp0_Zzr;emWl{aMCqCj>L0(>x!K{06v#S6u^Dn?As#A`!p=e=tEcQkXJZ*5X*M;F z5+VRpjMqZD!b=!NP;AI7GZ``922S5+rjP*}4UoAd7hFG<(4`YHW>(!5XDW#o%NdfW zCo0M$p_RlK=0p&%%oK-btA*^KYulBqofi_jd)2OiG6d@Biwz|k!m!uoojfua^z3PX zR5mcKw86jYO(bQuvLkVF27tQaIjPz0?Nd~c0>ba8JI#gj%?NA*P2 z2xDQxT?UU{dj`P-yJ#CAK%iAgOzzo`2{|fds}bv=6UH=yVk*aS*}PMXtuQWJrcw03p&!3P76J-lk+!j@fj8`{yTQblI#60(Rw zAO&%RO5pu(eeiMb`ia9jr;i=g9w)+*E_v=V$6uR015ETVP_BWXAlpR@*-z6N57ZXp z@@#n6fPg}G{D=M)tODT`gpxBiw*DOgkVNa###U83wj@$1LP9nS zdL49ePB^U506MsJ%DT?_JLrX0QWY79>-8qhIk8yIeol0FRg^O#Y#_#m6bA_-{x4kr zXO)+A69aNUtf-zf)|kSp&`Cb4V-Jhs9z} zyOcGAW%QkU3g9{u+WMZ-wD6#iGOhVjMy^Km8USxVkiW^qM3J)qESI>~jU;E$B_5aL zP`gPGuu2n)eGVD_6Nax5OZ;vsvZC9d1jDpU4ovR0i$p-NgPi(v7IfK_Lq{34m!=8i zeU-wSq4A6$2o(YV3Is_l?a^L`ZuHU<%Lmp$TTA=;f%P3NE!eYu@6XQZ98t|usneM` z#kpRGhAHcH{*hG@927S@W91&_MFd29UMc`h>TEw?^I3m<{F%0vYQ2%hEtO7?hb`Ew zJ*i|_hJ2F7MRs*X*8IW%1tE4UIHeP|K_tJVKf&l1337wsRL3xRG!@ks*Ztn)=e(!KL8n9i@Zv2ugtfa#=2w=oxUYk@nDs^l+8+Euc5o9R1w6GQ>xckUyNo1We^2=u82*d~@1P}mqqJ)&* zE>anEptG3VFy^D#oKtdfcmlgloQY7+Obp1Je)RR^ghV(#IRI?1l4)dgnk*2@wFn^3l8s^{y)y^?_yw4qjem zm>Yh?@Bch^b`ADA;CC*okR?+$iS3eCbyFiBg(+QqnT zF=b@*^@!3V5ALHK9%!VL@Sw`*nM}MIZ?>fL|@aAyqj<5M7>f2sQ0TGf;-F4lR7)64;}vGyC2;8+)Mk++qkt-L6U*LgvjeM9~7>n<_&tFnqHyUDi{>3 z9N9Ap3ZgKu1AJYDI7?|Bgnh>Q=@lWM3uP4D?B>vx$wC+u8H4+WK`6%&T%lhM!VSz@ zmc_gYKoaN`;k8C%%7~uH;80FKVsoxZAQueaXikR6&PZW1_NDaYq#PX*dP{QVFLlcHp^vwF~umTskxN1 zQvu|m%OO?kQ5Q%t64d_7@kqd8zM{f7={6lo>=#oR0T3uV8JeG@wYBNKH+8^*AW80i zGX`-~MVt=`C36~8qryd1SfPB5XecO}a$kP%{JXgqgRIZe_+8l@Z!REU1kURRQe&rf z?RU)V%P(9MMIBjfVAa6D)GbEuc+mJpEps{GP8AUqd(9d`3OkaM6t+i&Cjs#qbI6li zrquqkX5R4J%PR*4qNK8XW$&T$XH4(zmP&a;(=>o?_L8d;A47v+^P-{{58!2(wsh(o z8S;22yvlP<2cKdILYZYWQ1U|Q7QQY^qA1vc9|0{H&z79}59E&(5`_ve$H#86IVfyL z8nU${1dm273Z3qU zY!(^qf^ud7nXa3E${Tb9*2Q3UocUIW0Wvj&fNois-$mCo&5P?rKV~qP-Zz_82_izf zLxDYLLK07!GizULFwSkH$cDp4FHKj_QVT~(fLkwI{P;rt8yP$s;Bq-ecbY<4s&czFw99o3k=iC%!w^Tcf&`@r@C?BEy84Bmp{Df>HE=S^&(o2!pp-8O{fW2#za zl94c$Ff3}dUPa#$fmJ$;y-c`Dik8l#b6EEN3sKKx7F;Qs5+z!b!At-qW6oKS`AKs0 z$@0MynNde;^xm56h4&g;Zqhz=R1yKDk}|D57~{LhvKwgtbB+pHZxqpSo>#yQb3mkQ zC5Fr>-&HNFr9rVBI+M@A`w)z(+xbMN{j;+Tc>OM_42n=Ee@OsPV0M8-5(s05h`r`j z9$egb=#_NO`AKUG85y06KqR4~HCno?{?EtOOq$TKVq!VVP#6b)IGKb!VwCj`rQAZ}jl1?>zC|in(LPcC`q*&!MT$vCSYFJitT%<|oj& zO)dg(6T2$cx-+(NW<`GDLu&wQS~Doin=FbmL}T(d6L`(v{a?FmUvq$!=H{5IgkX4W zydFJ40g9+Cj=!|a4*z=hoflWFt|Db=rU+Wv+tO95KfBrH`)xKqiG-9=AR6Wk-0!B4 zev%#{qxzDLnCN)kh6}7G0ALAlrIopwyj`sodYGKTT6cXw%hq|KV`hIqdoEBlc>fVx z)k*;>tJaBYY_N8dhQweTaHrRpp!`43h~CYgT^QWBU=19+!hOkS`nC*07jWX zC+#<0!=S0GYygV`lhX+$F9(h0fi4Tym)22GVN7jW?hC^GSl;ReXuw;|Mw3WMQ6lDU zH)761V_$!^zpJyoo@Af-(&m+_Xw(!5Amyiwz`gA755&=;BOWXYmTR7=-+V8^kt0BM zh7=J^XlvVN_Vm9mezkkVkkKt2M{c#C8b?a$)G9)4Q-;wgqZ9Ly(onkRwxI!M$cImz zvFYk4BdDgbz}8%(0XBI&*w8sBofQr_79%XoVC64uf)=5&kG&WmCJfz6EZPwaxi68c znMo<7s1l3)cbGVNY{wI?uDJ8rC3igYL4p{^Bqe~!JwtYigbBGBQztMz^d2<`+DTOi zfvE(jvvz<$A6KIFhp;IqLZ7~l$c`}3{-4Q(AtG|;z-cz|2ESfIKma;f#d|e2TFV5T zKHf^}4n#wVWONGvAP6#>&ctao9vZ;x6JsXF5Ftmr248H-)<$;Fs4NRA z_p>z_=^PxhZIH`yBX2!(VHi%HlO92j342--+H z5xMPdfQY2Fq`ANZ?@Kz4HJ+NMFNQVN6~F$F>nm>rI!R!pSAa%lOalOmiXji#xfD@7 z9%d(PPvYb;jSe>)-N>RQday1j1MvRk>IyQ9> ziWQ&}c77I`%7mOsYc$Xs4I7UjkpokrZ~P~>2*Yw{0@ZNIeMdRrFCqWaL-Uq_%k+&{V)E z{~H4CWN5)K3hfoA552y(Xtn)CUzCwjLC+VLWRy(>2SZXYC4!~=wo6vqScse*!Z_TL zfUlkj8;gjbNo0NHYfsI*7?MPYMN1p?tp?L8#72OBs35yiw*$XA%!Z-Ri zo7OgML@Xtx1mw~_TuU|%q7?($?txbq3{y5J43;L{7AIzV5VDK-yoW=+LBnog)Ea$< zY(8y){~7TSVq~Q}+E|P(uH2q12$9~7!*-Df8V%K1#a-rB?pc&R`$o3gyqM~s_t;Sq zDlyh-u=u&&u6D7__T6y|X(};_1X^XqREr-+Vt52Jfk4FuSI^P~Q8Pz{8gUjg=#Z=p zo}y?bzMLBPmX{tPN7wuzt4CoDZa_p~R2q^1(EH+nRI0Tl+HuDrH{Ud{aN*kRw(gcz zY?2~O#G`L6jU&0;_z7)sRLe3BbY6^GhBF+=xXB6?5n{;kVt z8wV;d&FLO-ivKs;LOx!+UAy&z&v*dTSpzPjfCvyp(LkEcA2DLvjV8bJ;fE?sF^V7( zjkT-WljN{1HyzPZm5PMWi9HM_d`g7<|9^NoJ8lYp96q+ zT7y?|T0ThSdYX^wSj)piznc;4;FKJuFIgv#YpM{%j+{Me$ak#BQ-ieYz6SsR3@$_T zz~seGAy~^itqoqp!6!*d0g&t(nk?9P_zO=y-O|!Fe}2!rt$S+ysfdtt8i?>H@QMZ< z2J-T@{6fsh3&O!rCjiJ#=aN$Lu=%szTDPh{%8uP``{_fwq*7j{y8wx{q}*Kjzb{A` zt%e$dXF5YL3Z4?6>?uG~55y6qXI1}pvtTj+i!ZplB3FpDR)&I{)r2|45ke4_rSL_) zyHp972zrw^)Vm31QpFK&y3x>0#t&JsuGU-6q$EUAl8pahv~ZA=L{fP(K{UrQbe)7?V<=kIIPF|3UqFCn!%)B{JfLPBg!YfCw8W>!D z=EDJlc4tH@9`ii`Qxo#s6acU*h{=wfAx~Bafi-AqSA6^d02C=!rzHcPGakgkY-XGz zA!Bm+C_%UIz6_l=0lut0P>=R?~rE-e%iU0LZcok(>D}`tLm%quvET6#3=Rxn2~nyb$xF zYQc5-f#U-6<#TQDk@Glmnwn7?f&xVZ5rAG!Mq#iP0;|YK77RGn#vu7VO|E6K3-$rp zBT+S!g@DS`%(Axqd>9$A;E=!;dNSKQ_+~kVO8^W$JSsS`8NtWd)CywXXF$ugd>jlO zZ7L6e$CP=~X+r|*ECphWYb*3$Lo(xJPQKr4C<~p?ENEe(fZ;=3Y6&PW0?<_hRu+W8 zF{fJH3xT=8_)-JPg7NMrvOy2w;npJ4lLkXxbQ`haqtI6O5)z>(njnsvt-@p7M&A)I z&k%IRoNd|E&12I}p*r=UNm0c3{G01~x~fw~#7gff>y#*i%3w!B=KL8S3(T{&JLugZ z!`WcgigU=~!jV%A1e8p!zZAaYy9_Re5dg?rOSvGisRu!jPR=rCWE#C7a3Fgw@#$#-5JF2a%u;G; z729qz;*JO2pEJ8_NQcmC8bpLE8rkd1m+m)vN=q#2GP40&Mw)JFCSW-|l)R6`2h#S6 zw3PRr8(P99yIZj5e>?YIqKpVx696u%$C*1PdAz6##=+nXZ7vSD$u|NNh_x(jjgwiU zy6;-Jd=G)*Wm7?6XDGx-X+!zTW3BmxHjSQK}tr%6; ztX_ZouDk5C@l+{gswgs<4LRHB|H75)MgA$4+zj5$e=Dn`yk;iT3sRk!g${sxNf-Z; zvz7927?kB=SuRlyOx8zkR!c({tlKq0-np!$z_9O4F-Fb`F^vjg&bx8Z>ms)fo=;TL z1pn&nk|3UuXWd*2RC?ErqecD(2(nlS8?M3L;GpjsU#8# zzezcPS%t{dmwN&_5fYh(`yZ+{o6grn@HvBO5QBnP9;VP zvra?g5&O=o1^j)CGW`F5A?Z)4?19e3G~(IosZM)XLlih441JX_iuIT2l|6k z8L}w+f(Ul26P^dm4+RfxD%YTChkI!bw>HRNix$>Hv!9f=o^oZpTtJ@o#3KInR81Ql zz5a3f>XK~gusA{hqDq2|1}t6L7&WFcbVMa>NF#R1iXhXv1%Q04P6OkjqCR+6LY<8N z(ZiNQux3UAOCN|}SE2ZY?>+?&d<@4Dg9FQB%L!rsgB%zxZG0n*vS#FoCv;C&W3hm zY#Q)gE?z|7uxJCA=(6p21zf#`WL1zwdP)SX`;tmIZbKlA@)zeI2Y{$aPcURj*%zZWnPh$QV=bi#M)v zdKJu2=#&sF_l`v0IjlRFsRr5tH-i-Wu#a&8bP zMZ-q6j@dX``0hJ%cKlqemJwJvk4tM$^Vif&OgEP@mZoEE6S*@PgP|>CZ((la z2}mhLDB3W2mxpV8-H_@K=n`+76=6vCy~*=Z?~Nu^YCRm-4o z!qr&;6m+a<@AWNbd%7-I8_x9C7+66vf~&6#GH#7fS)0KykzWW_SJ%`F4~ zpcF}WHb@yXxw!|vL`L(u7OT$K;0sU!e)9=C%^8na=@PMT;zWejaDgz}#(X-L*dAxY z$-t@2K3@mA_P)#QUL(D_JwTq@=8xDMo}EKks?*^(;}4&`t&Yq7Pzb!MY@7p%3gmE+L5k!{whg8eT^&rc8+>DdEZuMy2rzFx_?pWDA^s+>oo~rz z%b|mWJZJ?~X#w+utx1m+_CS|#8*30OB3!W6s@rhUu`?-h-D0^Yx-j}`!4o8->TnJd zjnD-EZ-P@EMBTzCa5~6m%=yZ4Gm@yx>Uv!zDk1@}t}h$eoeXP1v+tJ&&{HiVZ?}mF z6h_g6wDeMYk)sCvzR&pJ&zYl7-0z&+>ww%mx>B{6ldcSkF8( zY+gp!1q2eH2wD>uKMdbrN&P9bCQxrc5{nN$%m(VwyqOgXyRVxiXEw5ofvIH&#aX7z$CB{b#$zJmCCMKy;}u16a}RQf-BAQessy9S!`qgw%xX0WkVpjppok=q8l2k! z3vIaW<ze_+$0SKb9`g2Br`Kw3>j79m@J|-ju5ac8jYI zl7IWMbfLJsMcy_e5dGkPspSF;PL-L=R08lGHwlW9Mk>F)%Wf}zu;k{&uU4wbclO$K zhw&4DRC}co>3uTu3jhD|rJ>s}LIMlr|5KOLhZ+Ku5>MWi;<}KC^maZjX$`p4um(V| zBDq+*v;P9)ucWZm(A)yZl`(bQ*Fl+}jlw`_6pi-X|wVe|H^ zvM&>J2;k|&6kCiR{pnd#N4K;l zLMUm-4~3n_HBue{4Mxx!5@E2f0H3?4{JU3(P(mb>|LP~ph#&(Zr2r5G3ag@=xfRf( z*F6qJM#GbzQFC^V=^#U14k|5iF;Caz^6~OL391OK39mD~8DUDH-W8=#LFt8hR}!IB zb6I&tQ(k}BU2=uqN0%=-0FT6wnyeMc_dj51nh4qv_S^4zbd&<7FTZbCNpCHxJ+b&6 zF+ak?ZMO6(Z)$Mq7nEc5a`Q3(gSEmGf3cD9K7Y=8#BWmB)10JqKSkMnULAXpAH|;M zQ}1Fm9jrjBg;zmkV(~kp2X@=tbsfPC=#G+hoZJ<;2L%n9!)+eg=7gG8vFtPVsJw~N zitO8rU03ArobzPJ}{eG0H=7PRixr&Qa=N`KzLJqLn4PAaiGvlEt=Cq~6bZnj=29Xvl z$AhO6OVjZ(WP82oqFw{qVhBW}GD&D6kq8J;6rroq z<~opb+d*4p2;O8xcb|8fh#~+YQZhp!;z$JJ&9{~y_l=nf-u&>ifi{ALU}mRKpM0ta zfQEI5k5*-C`eoaYNSiln)=4R8*BfG1CK(1aAyEP%C8bhI5ePkEk-$g@ z0+3Q>QdW{!K;*~Jpc*WDm~n9gVK-y*AvYg;1JiD!k)jZB68lw6Onhu4qL8FD_tg}!^`yc%jg(;Mq*TFe5V+s4qL ziWE`WXpl{pLxDm>kq|_rNXkscQ7l9ZcGr|NONl6nV~mhUA&N{&C1sq%La-xny^+sS zCA{d$TU*378n7DE>{rp#mbABsT0^==N`WMhMM-8G3F78u!XUq#$8lN?ufZnVdLYeG z90@LDp0670{5ke zp)+)XUXp9hla>v6+W9>@o(?M?Vh+sGA&Z{2m#$|X_&3ebR!I8dvP>*@Z? zc3a=}^rB5BPMkA!!jj&#wN$lMV*%!DDm{r3te-STQU&SAA$WFF-48YsVexEbETaYT zbjmeHv3|Ds8laO20k(5ug}u*jx&13VhXuw2ksDwD1Qdt@1t7E~NmsQ+7i-8&lpckf zM+(1VqE?Lb+=c9~o1SEp%8N4Dg%G?K5G4ApH-l5F#L~#@NPzUS}WSy5KVJ z+kd}mJ?GtXX~CQDA8oeQ7=OG|+lQ;&4QCjv$xys|MxT5_aRCS51f!>n7&f7^uN>#2 zkRu7X{}7Rr)?l(OfvPBq?0<|e*^y9OMWBsB()(@{l!hcVX9xlTkP@YWQeGL}-g4wt zGg1;UN5()Xhok@?rWHRZ(P7Txl5F+k)}vd#)rydeOf|ZjK!?2ya-ENvjsgG(0su(4 zNI7T7f`A$Ba;G2A7O<{SkL4xd327rL-&`%a@O7^Xjr*?=cvcT( zYwg)6ub~{=ee|I-VzM^=&B0XRQN$^fb&HmzZ*tOkELUPE>m=y&Hng3e=5 z3!S8y-3Lcut48rc+fI$`cK`#aiY(aKAJI;Z*2UIZ$aC#+vY&%)ADfB?8U z#{;tiG7wg|YL&^_zn=FJc4*!Bn>mx%9Yn(RwlZzWl%>JPg(pp1gu!bQ%cVB8nVpoY9Jj1*#sP)@5y_I z+}j5A&d4%@w3`PrKH+LEHBHu{R70g|o~wKH)QASzZ!Y_ql}w~vYFOhrMV0m!Bii(R zgB2^U93^Td%1#EkbL@cZs$EOo-arY^X3SaNTz3DJ09nO~h)8I+MlQnkhCt@Bxu7|c zSgC*v>d4NcBoUG)7>7aVMq>m~nj|a;q{S%>HzLUFQDg&&JdLb(a6Ajh=@?B7`y@(ga}bUKnzSG znlNKQ%N=GTf%3|MSwIyEK@dbj005*yByn6xL_Uh@8}cjwo{Bi;$e2N|izefU(B4vi zOjV0@M8JR*iUl=gb~CwdNRpla6Jk{)rJYce-N3E@0Z@qpa^MUp$|;Z-lPHHMzyb>m zO?mWdj&~T~LIaT9m#DiV+_~5L87lzia9XG!XPXZbCo1XL@L8H zT!>;mA2L=>62S!`a>1h@$mjEwG!;SwEU-oY6yg=jt2wo@*UT6i)**cZ0J)G3aS8(r z8K#Z^7o-pCl`~@J6l$nfMfG>3SlgHp>s>1EOfkl7JA(pM{NG%-Y$0S^s#5r9m| zAaEH)j~*O{HQ1jOAz71C8zBggi6>hTmr;ZOI!Gs!16(l%8Ky8RBqUG^Z$Lm10AoxD zEaLZ^;{CSWwxzlK-LDtV;v_H(00JQZL6EAbBz<2(bEJt?ljIR0GKK(nn#0-KZVW0r zICZQH(@n}XpQEg7)1(!h(FPeRuTuS_=MwDGN`|3XA9|=(NF*Sg!%eDwf*utL5NVp` zLmb!EJbmQw;f+m6%7uR_BZ2iJpz6~DjcXXJg7!yQZH}PEoHAYv4l(Gq(*Pt#JG#zF`ZlJb>1RXQ`k zq5zE{<2cH_zYY_j#uPG*Mk@o&ikyTAW)LukDy?<_%Qc(<%G0^QCJp#_Q=3-gTjnS$ zuBld7RSTqD#sLCT9E<@nCjSDU+;Kz!Fd#t`rzp~d2m^`DKrl?~A&-O%8IT;VJgSK) zq{%*+w7TSowNMsh3JZ}shFyZCnzd>k7$E`$fCz+YUk?EQG8RD?FyKUy4s!w$aY00h zAdbYPtdNduO?Yk<24ldXqaqZ;DKkI`2OZcq0$Wj_;Z@Yg1kgG3dY+g<05O2F;4z88 zb%lv7&67LZrwkp|5Jdoxa?Sx5W29{hjYC7#;K$otszbYyBRAhm7p#zmi-~XjxI@xh zju`VL5>`D|r6IL|L!JGgq?N~~>IN4g3|J6gkZt9EU;q31-`D@YE`pQ`y|(m3OSXI| z02d&*b3bG7Ycn3eM%FX#IY(dGwLuj~)K)CS-x;5kGqGU`Fc) zy9QTQvWI8$fPziuyJ&I%GTtYp20`EVQDN2t8U(ekC+m_^&FdYI%Cd1m&~3Ty74+Kh zyS3jW2*!)yP>~bPaR8Afid!eyN4lgmJ4qHKGI-ANL&i(y_NG>JWFGT@A@%>7=7oE+ zIy~<64{Bcq>GBrV>QM%u<0x|(%Zyl#PZ7153$=M%fgK{oas0!Q;TDg|6`fh`Gu7S{V`wnRENbN(Ap(inAAgdjNwJU@ zf;Ts}jv6_#!g-n`eZ9TQmM-rcIy9HhrD@6pWr4zW(OrujaQD>c$RfU%ybF55ka1w>yGTxY`S^ zpw%lWZ>?w9#`~nX4>SV7yJtt{x)@3O$SlvvaTzK`XWCqqXY$MiASee_Ev4 zEg+I9MySmg$tyz58!41fiQ43&aJWGKTsf`~`}rX(b;1pp^$0619z2%yf} zR9_W>6cA<<($o<|XdL%y0YO$+k;R-+jxu=3H0vS&V=M#~1`HA9s8Y!vf`CX!556x{ zb&iToB}HdKWwayX#@0590fx*k8OsTj%Ugmgz!e81nO)9&BB(csd&{M-S9ia+cxh?Y z$KxC8cbz(M{h=cOAW2ik5LJCV8_+Z~UQ-!LG#LzMcq_Y7t#wHr{gEf!#B(dVoi02p zKsKr5n$k0N3x(zYl=>bh3>X1?^!4gxYbt4)0wR(iFQ}k5CR^ky>qeLEoo#2R3 zb!03T&&ds7Yu#uJ5rEp>lbvO`l>!NYNfx(1>BgKpR`QrnYMwO>sAq*0(&{&To~z4$ zP#Z%IU3s1R8iG9ExQ-zz54J5+sWm;gSoW<%7a{s=QBqO`wXvp?CqW7y`H)b;P#f1K zYGfYG*zE>QNM6r``i~Y9KAu4BYq7{M7_#>?LN%G&w`(zS#uGudT|cg6L?ZbwXD?qX zD@6<@Sqw_z~F5CuUl#6iuuDdXD1kO>l;bB4^G%BFj@q^N|F@w8;^22UtCi#O0h z&x2Rn{MluL^Q-JtZttvtLPz{tj!@J_22Co+XCBLXXRPjVl)e#SDhpllxQt@62pRNz z^!WGpT*kY)TDIO}#36r-80&uTC1_|Lyx$+{H~h)U$FJ`C;N2CEUKbS#gJzx}N~;M# zEmCy09B4@lT7GDklO|KYbhsU62AMWG8I7lh$Z9zA zoF_+K1zmaPO@ z;spXsxjdW9?U!u3nEk=7wKRJnfb?{yT!dlp+2?c5Klj2P7B8v9{Yjd%wYKiP=e{SL zbbO(ZPg2eRgh+`@HC$Cy3lTXNxqLML`-O`Z{V;LD#KzWEo}>X1ks!edQ3z_NuYdKm zH-7W$-~43PpZwg%L7D2pE$zLquHKFPxYr6kUt}wg1oXrq-g`DW~ec z1hOa=5@X1;dgq)h|5^{0MwQC@v#pU@XGzf{b0>sW>P9?}`M`x-L6IQAQ;rN7vV5Vi zY}u;c{qA>PefdSD99PPfw)U3k8*Y5ouYWyl-F04j{k8MYJ%7gZ>F506_l=FsmAJnt ztozG_fBycv1vlStQ~1ceN+%IO&{93uf@DJQal1N z;)ImIb;4i-#(v_Qgxtigv0*|WhO3>+&jgU}S6{9e>F-EZvUG1=v>&ZbLRXBtZOcB!m0wAqfBNxslvCRk| zV=n*zYie+q!;pY)oetc^|JsWN{>uK>K(*oUAwTr=&sni@)_31u@Zy`NZMAU|hAHs? zkr9Bb6u=Mw)k@x7=AZRPaD=@l={YOnwJ*sV97+&YMa5Jaj9f?7X0Ym3^w`HF_zPt0&eZBUI-i2j;i z^RUPCo?E6Wi%u^Ow8H{H+wW#x%$TI990Uk}FMqJ;gD+Nvg?wFI7y<-Az<^i)464hm zk(Dp1vJ4T~`6Z>&Q10ZiIJ8!V!iILln4%|S;5T?B75E@@jC|#|b})k~mSQmHA(gFIRKfeJOC=D zDB*Ek8IDWFIFzjT)o_sdo3*s;GRsOZUzZTb%!8`gu)DQ9YsHeg-Wab_g{w&47@-<> zc1dE|V<>>BNC0Td(~N@T1Zq3d7*Yxy8IO+Y&z}4#C`-mb!T@$BzeA3{Dj4<+AAol@ss!p39C_l zx`Qh@6r1|*T2R)#sv6SHA~#optPN+F!uXvG@#{C-jToLM0?7QTrH1KGEf>j!+)6g< zakK6{((`Hdk{BVZrxf-0z4_AMplwr69RYxQh@nQ3tHza1v^!r^BWOBMLekD0=??Wg z8ApK$^GG?a`~@!V%{=Mhm?oXNa}Gf`tfm!{ixFSJ$WNY9{Lw3vZ)&Hz|BgfeBI*|P z`~wkiwZB3M7l&xHD%Hc(3fK5#oT@4EFnEA9t5?19(u-rqjNNYgZHUDE4?X<5bACHw z`0)Mq-@9yDG&ugkn)rSa4rh@=*~Otyyxz_ufO4@EjHhzU!*CC04WLs zK_X5P79b@FPZAaAkqKfXq9|kx(==r)BpX#Tm?ukpdP>2cv;jQY#=&NOAd*_dr5Ps( zWPAWt3jzTGLlQ{H06@%}H|OJzKHP7=gGP+n`ipsAJpRNZ3l}b0d!5ORO?AtcFIls? zD~XdrF)v625J-Pa94Cmx7>kpbVaQlO1Zf(x5JDCtX##@h!W>W2lyf4=<-%0(R8S!o zAyOKref@oL92W|C&V?XV{vb)Ypg0VXry}JTuso?`9%~m=$729&eH|%7h}0fNKx7P1 z`uQaO$lH`O;HAC6(h;b4I{V62%PHW3bB>5n7zx1z2@(_rAuteJ08tRI&pw^ArfcQF z2Orwj*8bAVuiSOV?F`s8*Icz~#mWyqc<+OE-`RYNE%)AQ&wvG$IR5B^_gAf0mGD%g zyqGU8UApwi#~%CmquGx?^2ASe-DTLYVR5Ar1cB>A1eaAjEvkj3qzy+rIV2>DP^1~# z22q#${cq?pn}C3Sz~42!wkcrD#@6i^9qFm1E15e6m8NSY`O&hNhXajUBci|%5LSig2h>m47> z{maX5{Aq`6qEznC)D{ToBH84&jVQNp5-@GWxzA+5@#kBIDK(y`_KRMm+S)#zBGPzL zJY$Yu^5{h4-MZ|x*)6|S(zHIG|LBLM7r*%qGTe9FiCc~uF{Zge3e%KRCDF%Z0D#Kx zaJf>m3b?RkX4}Occ&{2dhYXVSzkb%U>c@LW>&VO{wGVi+Z*@d9W%`%@mc54t-zrT+ zB1R?38p$X0qE0Vd$ZjMdM6~N!Ko^-ldTc6-&a^bSa^#}83eDEGkZFBc>2qIw zb@s#0{AB9n<2Twc07y8OHFm)r<^aGFkRw)H(n1fGOd%ekjPCaEY1C3iHz+Mx(|EBk z=)KMWj;s@q(`MCO5CV}ckYdUxV+LMl zKahsNnRyM0+URZ6k)zX8HmgbImH-)=@WhsF*w-39%{fG9x~e@}S(M5tbAFMp2_0YY zrH%UtR83>1Ux&AxPElDI#to=vUQMeB+Y^{vRInS?NWGz-_C{!>TShl)z+A{PaAien zhTcJ~(ftv6tyw&iCuuDC`kW5hXU0&c)}Vdd_4az=*9D!lcA=_yaMtqO&{AzmXqCId!Ddzj)Up+U*S+{P)YRgBK8wkt6`4DUfr=mQn_l<#4Nhz7bsoeHZDYVa?nj%Fh? zn|!Lt%!*E2lW=NaRiS|90AB%OxFc<8(=bpd*?OC~8wEfH-4nE+ZXPP;XfQ2A0OdFp9IVS(DHfRpA-9LvC>}W*afmWv%??=J(k78Cv}|T4Gp7PT zCdN2^W^kSs6ox^em}_tAIP>%~H`#o{Wy_Xbaru=OU3B4#FTL2=(H=#)sne!Jxd@O& zQ9ydPN?o0*be_-W32sI=;{X8w07*naRG?grgMbz5JOrj(og;{wTA#qD0it&`?(_th4qO=bv|OXXoIrzWL_B0}p!Wp$C5d z$8%a+TL!fcTDWlG#eY42y{S_sPhO{|)SE9B+6T2qVVH7JS66uC;Riqe?6bk0gWrDt zt@l6raQLucf(V3ARKl3t6-8t@+-N|HBd|YcWkg0N36SXm_E!KPquZR(ct@F9RiN3B zF`KRKG^aSylXS}UR?X?E+>+5`Rb-8boM_f}-+lP~!qa!yZg^uuDM?ZlkqcDeNNdKH}9I|TA>=LR%LUy638z!@+)(A8(o3{f8#m1WnPIG3I>NO?2Gy2dGeWvrQ zX=Vor05bBAYBN4SmcC8rsPM1Fl5Naetl2hDzhqx9de8)f&v92@g(XWGHe40JO(B1AvZZ5l~9Jl%zl~qQ3sv8SDN1^|x;O;KNfk z+^9cJ8Dj#$(O@3rh`>N@yH`l8Vu;G=uze7WxMp+~I0&Xl%RBI=JTDItN{T@K(bBcu%Qx>v~%)!akok4N8C zydhowMh>~-v#w?WP4Ylz+lF#VPE-sivletCSLTNq6Yjny zO{(aUhmosP)tdIl2?DM)u53l?AVsPY^-LQAHBZ%X#hT|Ow>r}N$rwfkzUr%rjZ7D{ z`ZZlw16D1sTmU4BvIR+Nf>6ao9t^fDiPvup_iAx_n6%j**X;NBKn7Cc@wtKI9^k1vq zdA@V+c~RR)N@HMvAQdJ9?MyeAaRFz(=n%$0F%LPmzM^eY;K9-`g358wo&=eWr{t*7 zTVDQ#MomT#p!Kj=w~Na=CLF8&Zxxf7DMtuvys9{&rd0d54n-NMZ>Nb|P5}2n2)~n2 zF!VOtdVuRsR>Yd9t2X#tWo+JXRgY;69Z)p|WyB*IN<}ayuA6BSDuEpV$UhJ$qhMXZ zoi)TI9ZPL5!}tE8M*XYEeE?x)uMnJ(%K6K@BPmF8g_50U_z8_y(~;TAq3RtA=#0@7 z`%0WM43ju+Yi%hO3IMSEHruwgwh9Jw=YDqWwb!pZb;?H{ecZLG`^KBDdwb41H(Yna z;zi$gb`Cz|(8KoIXU}V{z2W)ipNpcx>8GEv&6e9~@+i!Pc!|LeB4wj+P~ zvjY#@yHf7I_PQH3m@#ALnLAv1>EF{dZES9M`l+Y$xx%kbK6RU|w@6Yhh%-b1b^(Ek zwv9lvD$n}1O%lR@1Sl_UD%*#gG(*il(zmX;PIDF_!vF+EQP|$riU5N2lz+;PwC%a<(QVvEg=`}qmO zh7C!Q^vNfmz3%#}dwcswj~ci4zI*OCbLK5K+$Iph96kE*W8=q-J@luCZnM?aTnJ=r z>C)xr{ptKCo_u_>Ew?%4SHB!PZZsjAH*fxR*IxO_C!cl>9e%`N$LzTC*1bImQ(14M z<-C+}9uZ~?KecLcj5ztUt?*CIU38kLGJuTx-n>LwwFtpOWI@2rzwpnwFt=#&qOZRA zV(oRN9I)TMZ@v4@>#x3wfJgoGh@E%cC7;VBY0}!%G^ni|049tZH+t;24?p}cP2##j zzEr6U=^Xa)hoAoAAOHC4#g{ZTH3-3za)nZrdimIsPt?^H4nFv>n{K`7tykXIZO2`r zTolKNTd>&(L0{{TMTe)wEWhYl_DH~7mN%KYHEFKqRUIO8fAaw_#)#{)w`#`q2)Yew zpB=8~?R{p>=Lc-G;qb6uH~e`uALi&!uR*;-8ctE`&C^oL*p)*&DjwWkc#5Pr1bGF>&IUhDIUC9!Nlb(|UaBI1c0NccjgKxeWbPQCoFp zur_pR(1v9RA|O=uoyqR>o6$sJ%KZWoaUqIPbj9m$JUVy&p&M>+L zZI=Wlg6L1Up)f?diO2XOl>Jss(28`Oood!NtAgIv{cub}(^G~TEulCNW*8?E3#_`V zj?q$3EEHvp#PU;W&U0z&R(=ojx6%aPewg+!mjiCkXuMx6xq(rHca>=Insnp0ZpHZXdOt z@_GRR6xkOB9Ef4_s*YT3=OPyM^dY!1ueO}EfC+^wFGx*QCV+k}S>m&7vuBY=R(GD`q;^qSwePX%rwZ z0wj@iefnJa%P(3+jvO@e7$Ja2FiJsi3YfqUNFWLTE;zRBbo}bqAIBBTm%nuPh=a}( zaal_lbXg0tde$GX`)_6w0cf$Til8D%$B!DOWD#Ok+-cK|z>|QM+YBjbe~Z=LfXL*k zhX4d8Avj~mg22)L?nY1(9|YsECCy(vO+gR~BO7#7>kGB#*ntgY0GtaUk`w?~5HhBF zv_(r%KIqbvClxF-&X~0xmx9_DF;+FWbKx3isO<)Kk^sre)CY||1VDAdn0`Z+8ncqd z`o++Syc&Gw%)i7KRz0GhVgS}&u6-#Ch2AI}92zFeu!@a2n?$>TdeD2BGxr91I$-Sk zMT=Ig?h2#e+H0>{v}n<^^{0RO+2^<4etV@-YHn)XW}B^Fdg+xvo`3G#IdgX2b(hB< zf9$o_UK=)a$dJyCFbI;Q+)&rF!TK|1e?0rNQ_uM9(@$saJag9DZ=ZbfiQ^`W9W!Fs z1%Ep4_!CdqVcYE=e&pe|-h6%7h!Gt_hJ5_N2XjCF;-0(jnl^1psZQ(Z^2u`3bFUt;5HSJn#Gq=6&(? zO*h{(Z{EC4*Kk?L)i0Ka7Z+G1d*L*Yon+X%gbqpDN^KG}ydUw|S_utpp z(3HgDm6u=Xuar8654q}!%NBh1{i6^4`Z@Xo| z*WZpFHzwuu%(MS__SvTvEnGBw+nc3u{f95QWjV-+%w~v;Qg9<-eRe z?}g|7v%&fs3~C>=a>a`7uI>|0IAPxBU*7)De{Q?Yc84E+XcR@gDHlQn43{ij_Q3}q zt~+JjU;gT(mtT4D>8GAO>7-wd7&)vWD!`brH_#USb*ldkq!bPNDY0mbc8`p*8FLbK zKT<2mT?~S9pnK^6_LD@q$G2#d5d%P7_gC1(aiG(<5~7cmEGvY$O@|NdPm)MxH#lJr zZ^7vZZR7uv2a{MM#$hT1NB+1*l8OlmIkc=LtN+Qk1Kc!BZyTK^GRuk9l0xH@H_v*y z*+sdx0C%=V8G6?6yT+H+t)_8nFIW{snmlS|ba(+E^@A1i1`^AlmV@PojO!A8TJ_%s zyK&FrP|dH_?E1b{*?yXk0o#HD?n%t#&SaKjujQXGG@fHpUpdY zvrYPW5*SA;f)vXpMG3)3W>>m95Y*Oe7G0!ck>s(uJU}=5@&Ia5_AIRgG*yafX?kTB zN=_glPBdour6C}qriNc(K)V<+u3)OgrH()_y=jpJ1`g1R z11G`Vg-LU)wS(;<&y&5zpwPewtI1Hw1*de0Cl9Je>PsRuY5-*_Yje@o3d(|Qj2hFd z`zvXHYxM7I@h~s=E$cY|gI@cnfdtKZNP&RT6@?5LL5T|<$7>JnJa^|E&wci}^Phj= zPdm;WQD0x-X~+W5IcRzrp=+YLqf^2p%Uv~G<5iazuok*KFWIwp#7n=&to5Ve@;1y` zRj*LIvMc`Zi>{d)j~G6v(A~$wh{-zV26(2KL6ftCTjmm(ivm#38~304n**>`6Z#oc zRaRYRpQdfQWOOK98wR%Qw%v7Oh}-SjgT{&cJO8hBWob+|B?sY7h7>Q>pioy}rcd8t z=(M5UCCe|iF+Ei8u1j|sF|}4n)dQ*`LU%3b4KRC|noo+aOdv*!Fb9L4?s0Bs?p67c zJP@%a{LT>UDkc+x*5p9UvOfX2G0>Xu>CqW+?<2oT)OhWX*OWCmyPnH7^kr(H3AwZi~d~z0p@sl&8oMa z4mmWgJtIG6L!R`b;2;nLF~(4E1dfy41j7*oz}Gg7BOn2aLFRgWM9g}EZIP$Xrw7&Ptw{&maEw{&)NJpaOr zX_EZmx4#PuxrZKp@VmGXG!3Y0+_xx`@|J!AM&*ekCt4F&k&=QwtB0FN;$f0VAK;;0p64Swn zW=_u#Bf~ueq$;=wDGWgfLcn}3-_|zh>Z`7L>ZvDZ%$V`noVn+n|L2Dudg%A({C>gr z-+jMuApqp_xmoYNd+4Eu9eT(iXZ`lR)3ci8^Zxu4Abh&v>qP|72|| z-FvMUP|LYms|L{HByfW(RTjZ~=WyJjQRsAB{`Doz?8ZZdlGcdJ+R@g!hogNYG3m}!eh zWse)tET8&u))VGo8j$Ion?|>w+Sg5F|MT^atDR~&7i9GmB}=)WTom2?;he|keD#~{ zx88Nq*uFUFPemAn0Yhh^T_7kEHu1%o2Q*aANzFM@2DhW++y^tS_@O_UzV1EZBVUuO zHyGFW`?1TLMQd8Rir$4qcn&G|MHt`}aBdTTbRYS>7z?SZ1D( zp(;+`H%L%hJY{#mWzvhj% zx|1|Q#)Xq12HwI@cBQ>^nf4WK(XEmr-_h0OYFq=0(3)?VS_4j>QWQAZjZ!yR<|Y8> z>Wh2Ie6#gB(p1RWzF>_<8O>F*AxyoxS~FtinN{6%M?;Rzw^c6uR~V@BnoOnXk=DO< zSVp-yRt}g(sV0_C8#WdQV?=ncS&{3IpOvc_O4qVVw}&2r2BLQbk$w`%X6Bn;5loQO z_0GF6>-M!IH~MR!E`e&L)`AQ3fLg{RJR0~iqDsw(CKLyCq&1nrx}4T(|2w)Pa>c!t zx!}x?nlWQyk-24O*sh_`-}+4Mi<&6WnrEoHk~CO*8ZFUO-L16(HTuYXasY`@B~vBH zXb|B9VZm#|*zi@HO8R&c1Y}Vd#4%rcOv9k2+=3;&@=f6|l+||x01!Av+Q2mOqt^iL zwjVcaNLtYv&z_8`Awt{^ocoqDT$$vXBS1s~)PEd+BXA-N2AJ0Rl0(bU{R9tXSXJ)Y8(@+S1zE($dn>+}zU8+y)GV;8K1gaR9CtC<4`g zhO$u?6%+Z!)?#yeRBS+ozybk*fPg^xmU>n!uk`gXwHQJ`CKwVjGW;b7ga9FgIvkS( zQOX6fV9lyk%a{HTrztQLL_#kzkYoUg5d;L0+*ScZxng}?U44Y2n2+k~8=`z3fPgVz z3|IijfJu#^6CqI}$&=s%k(G8MXjCAO!4D7ta9z>YG$JK30}KFIlJbOeU;(fIFi;;@ zKr93n0t)~z%IE7ETk`eIfB?vxGu;G|K%pp&I8RC?o>l-g1u959I@RAOV*vtc4=V%I zrwRQCQ%Nlq*1D$Dyi|fHJ0gRm)`bEU9@B1c;c;-teb_3o&Hq&{3mChG95! z=1zO;zT1QeeZ`1pZ8fQF4fi7rEwYr*w@#){Usial(Z9`r;op;`8<_-%NElfl* zbl9lfciR;R_TO*c3op9pg%@8w`IM6Y#O7OUF=_mSN~OHnW*h(K>1S3hU-8g`4~-c+ z@#jB3RwR7aop;%KtL@%@Z&s3U#y|*QIxwtglYwLASp5HKRj<#S6GFWqpX>Bk=P^NTLJ@cw)6LBL$0z$rzjCXfLW?6?xOPhIn zE^1y`QX|lU^1mo+bUdEbXjSe)lp7^T4Tz+wK?cxMsdQIL>x>wZ2*DWB=^$X~gG?mH z3RrUT7i=b<7I@zB6J^zD>AO&RQ4n##IS~*EeLApS90Cvo01PqE^>DNtRaC2kpXA9g z#hwU0BRkr4g!j1f081I~C?->z;< zp+I%3@ycv=hNHj{0%WP+VGzt&w)~bi-aU1j&32qLray@}VaS+y)NRqmD;0;?$@43* zfH6c|n@h71`k(@VI&00;Rq+RAdR6Xf$%rod7~ejc^7p)?T==NXesBkgjT=|=*z2lnV^oF zBk26j34mckf$>E688})sfgwK^Z<>bmp5iPH^!eiUU2Pt?71@WTOoFB^lUV@E*{zA=$modokHIPT)$@u+gms5TEJM+;=eNPQ8*#W(Kq- zCnN3L27Qt-b8fmIa1@i0h7M9{F^*3Lk+LCVz-rcX zv{Pvn%8y*WpaV00r!gGp`Kn&c;SWy1;A-6hpo-Yr0hxXb8>8;Zb?C}O#emXs-@Mo3 zB`exC+^jfxb6)NSA)O{jB8~gXxrP!U6T|}`MkEB!4WCvVKdI-_d0n5rQMbX~l#~Gj znS-N!?Gi4pM2E7%(J_5&+`v@35^BY(wX7h)qQdO=-+u0e=lgm~l_X(A_4RdYO`5dd z0sE0)JV_9oGj)+10V%h^DzkwL5$1|tef`CkbLMTb*@kU{1{3F800D|LDb&?{GW)$h zpL_mMNBnfxef9_9M5!Z=1OO6oOU0lz8w){#AS&iAz4Y&&efsf5mtHz~%DUyg9u}gq zuT&6E)lCCnJWYaJe%aFHH{X2oo3FiGEEe|Kd%yh;IxwG$h{qTNf)l8c`T`gMF^3*p z0+57)j(z9Ql#%nsj3SWMBPsdkZ1vKs2)X@>1yL?6004;ufeGbJlXN3{5}CpdbiyEkgjxqQ3`Np!iy#W4G&Jse)5(@hbOX$ZD5g zt-h5lfnRlz9kn7!*$C73tWy^pF=*CfGCv0$^QGohjG{`Z|ESZ>{MD~cVgZZ7D2@}( zc^aoc7$CIW0b`Xk?(gp>A`G!utSbaTrBWfm ze|hq+_TBFQ&Xd00KD~WV>)}&;u ze#u-qvjPS_sYB6}qDw{^kqneVCdPmm!+^24TyAe4^pAgBF@D@=VpzyU06;`?hhR@n zH|M;!ueY4Uh|t^DiwxU3TH-h+qBxF+4jtazwR-%RF?amyUk^R_z#Vtqea+R^{N}fR zI{D<|0#X~pySlmovAv_Sx4TOovrR&9Au8occTXn77K6&>V2G&^_D zjLg5}V_Jl29@1cFETBGbK@+{uZbo+)RmEAn&qi}pYilp!=n;V>Z}gv15W70Z*K4l- zQ-IJR5w$2PM$xMN(!|b=pKZ3ut?z!Y-q2wi4;zwlVcg}uK=6c^`$5&ZQ2+jq-D;L7 z9L1@oP~{Z+%G_^OA%cJe1WdPu%p_bW%?Df%2?UwtfWQC*0Rwa3uP~EnAaeDTJix{2 z(!wv_m*t6!#8*OBJwp~u03cm4DT^U5o}j=$z3<&GBP$1IsMTXZjYXqbEbN+YT@gf8 zXSjHzL~>8FVI&KtaG%#7w3o|ZM-ve^jXFQrDHNdgH`z%bI}c7Ul+3w2-jjChRagN4 zP&!Dv?;O2QHFg5hNKutZ0D;(IOfHIbI4SD?EE<+ibZ-_`ABxWl& zkw&8$TSh~f#@tL5XTycmAkt?dWBKYu+|1x-w8b{ z8KTVRAkO<&uVD=_5Cblh+)HDYt8baM&B~8I>-zfB;Sf`hBc}F9SXZ#LyYva__VT

  • lPZd_MxoY{ZrTAc|R>FR6n2`}(CI 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