diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..cf4c8a8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,141 @@ +# 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.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### 1. High-level +- No unreleased feature changes yet. + +### 2. Low-level +- N/A. + +## [0.2.0] - 2026-02-12 + +Comparison scope for this release note (relative to `v0.1.0`): +- Baseline reference: `dd681a8` (`2025-12-17`, `pyproject.toml` version `0.1.0`) +- Base comparison: `dd681a8...release/v2-stable` +- Branch snapshot used for this summary: `2c92b43` (`2026-02-13`) +- Delta size at that snapshot: `33` commits, `76` files changed, `18,232` insertions, `321` deletions. + +### 0. Technical Summary (concise) + +#### New CLI workflows +- `segger predict`: + - Checkpoint-only inference with strict checkpoint/data compatibility checks (`segger_vocab`, `segger_me_gene_pairs`, `n_genes`). + - Supports inference-time graph overrides, assignment threshold controls, fragment controls, and `--use-3d`. +- `segger export`: + - Unified format conversion (`xenium_explorer|merged|spatialdata|anndata`) from parquet/csv/SpatialData segmentation inputs. + - Adds explicit input resolution (`--input-format`) and boundary policy controls (`--boundary-method`). +- `segger plot`: + - Resolves Lightning metrics automatically (or via `--log-version`), groups train/val curves by metric key, and renders terminal or PNG outputs. + +#### New capabilities +- End-to-end SpatialData support (ingest + export), including optional AnnData table embedding. +- Alignment-loss pipeline with ME-gene constraints, scheduled weighting, and checkpoint metadata persistence. +- Fragment-mode assignment for unassigned transcripts via tx-tx connected components with GPU-first/CPU-fallback execution. + +#### Stability/performance changes +- Strong checkpoint-first safety checks to prevent silent inference mismatches. +- Improved thresholding and memory behavior in segmentation writing. +- Hardened boundary generation and parallel Xenium export fallback (process -> thread retry). +- Expanded lazy optional-dependency handling with clearer failure modes. +- Broader tests/CI coverage across CLI, export, alignment, fragment, and SpatialData paths. + +### 1. High-level (major changes) + +#### 1.1 CLI and workflow expansion +- Added a checkpoint-first inference command: `segger predict -c `. +- Added checkpoint metadata validation for saved vocabulary and ME-gene pairs before inference starts. +- Added training early-stopping controls and best-checkpoint prediction handoff in `segger segment`. +- Added `segger plot` for loss curves with both terminal output (`--quick`, `uniplot`) and image output (`matplotlib`). +- Expanded CLI output controls to multi-format segmentation exports (`segger_raw`, `merged`, `spatialdata`, `anndata`, `all`). +- Expanded export controls to include `--input-format`, `--boundary-method`, and related boundary-generation knobs. + +#### 1.2 New export architecture and format support +- Added a format registry (`OutputFormat`, writer protocol/registration) for consistent export extension. +- Added dedicated writers for merged transcript output, AnnData output, and SpatialData output. +- Added a richer Xenium Explorer export path with improved polygon handling and metadata consistency. +- Added support for choosing boundary-generation strategy (`input`, `convex_hull`, `delaunay`, `skip` where supported). +- Added SOPA compatibility helpers and conversion utilities for SpatialData-centric downstream workflows. + +#### 1.3 SpatialData support from input to output +- Added SpatialData loader support and `.zarr` path detection in the data module and CLI. +- Added SpatialData export writer support, including transcript points and optional shapes. +- Added optional embedding of an AnnData table in SpatialData output. +- Added lightweight SpatialData Zarr read/write utilities for environments that avoid full `spatialdata` dependency trees. + +#### 1.4 Data loading and graph construction upgrades +- Added configurable transcript quality filtering (`min_qv`) with platform-aware logic. +- Added explicit quality-filter classes for Xenium, CosMx, MERSCOPE, and SpatialData-based inputs. +- Added 3D-aware graph construction controls (`use_3d` with `auto/true/false` semantics). +- Added prediction graph scale-factor plumbing and alignment so CLI and data-module behavior stay consistent. +- Added optional transcript-edge similarity capture in graph construction for downstream fragment operations. + +#### 1.5 Model/loss evolution (alignment + metadata-aware inference) +- Added `AlignmentLoss` integration with scheduled weighting and combination modes (`interpolate` and `additive`). +- Added ME-gene edge generation and labeling in heterodata construction. +- Added contrastive same-gene positive edges and ME-pair negative edges for alignment training. +- Added positive subsampling logic to control alignment class imbalance. +- Added checkpoint persistence and restore of `segger_vocab` and `segger_me_gene_pairs`. +- Added stricter runtime compatibility checks between checkpoint metadata and prediction input data. + +#### 1.6 Fragment-mode segmentation for unassigned transcripts +- Added fragment-mode assignment pipeline for previously unassigned transcripts. +- Added connected-component grouping using transcript-transcript edges with similarity thresholding. +- Added GPU-first execution path (when RAPIDS is available) with CPU fallback behavior. +- Added minimum-fragment-size controls and auto-threshold options for fragment similarity. + +#### 1.7 Optional dependency model and package surface cleanup +- Added centralized optional dependency utilities (`segger.utils.optional_deps`) with clear install guidance. +- Added lazy module loading in `segger.io`, `segger.export`, `segger.datasets`, and other package entry points. +- Added explicit RAPIDS requirement checks where GPU-only operations are required. +- Added optional dependency groups in `pyproject.toml` (`spatialdata`, `spatialdata-io`, `sopa`, `plot`, `spatialdata-all`, `dev`). + +#### 1.8 New datasets/helpers for reproducible testing and demos +- Added `segger.datasets` with toy Xenium loaders and synthetic data generation. +- Added sample-output generation helpers for merged/parquet and SpatialData conversion workflows. +- Added plotting and SpatialData demo notebooks to document end-to-end usage. + +#### 1.9 Testing and CI expansion +- Added a full test suite scaffold (`tests/`, fixtures, and targeted modules by subsystem). +- Added tests for alignment loss, fragment mode, prediction graph behavior, exporters, optional deps, and SpatialData I/O. +- Added CI workflow (`.github/workflows/test.yml`) and Dependabot config for dependency hygiene. +- Added pytest and coverage configuration directly in `pyproject.toml`. + +#### 1.10 Documentation expansion +- Added dedicated docs for installation troubleshooting, release process, versioning policy, loss functions, and math foundations. +- Added structured release note document for `v0.2.0`. + +### 2. Low-level (minor changes and refinements) + +#### 2.1 Accuracy, performance, and stability refinements +- Improved thresholding logic in segmentation writing with robust Li/Yen handling and safe fallbacks. +- Reduced peak memory in per-gene threshold calculations through iterative sampling-based processing. +- Improved boundary generation throughput with parallel Delaunay options. +- Added fallback from process workers to thread workers in parallel Xenium export when process pools fail. +- Added safer empty/degenerate polygon handling in boundary extraction and export code paths. +- Added additional positional-embedding guards for empty batches and zero-variance coordinates. + +#### 2.2 ME-gene discovery and alignment tuning refinements +- Added ME-gene discovery caching keyed by scRNA input metadata and discovery parameters. +- Added scRNA preprocessing normalization and optional per-cell-type subsampling for faster ME discovery. +- Added progress/debug messages for ME discovery and alignment-edge creation (`SEGGER_ME_VERBOSE` / debug flags). +- Tightened default ME exclusivity criteria and increased pair coverage tuning in discovery defaults. + +#### 2.3 CLI polish and compatibility refinements +- Unified worker-count semantics across related CLI steps. +- Improved CLI help text for format/export settings and deprecation messaging. +- Added robust cell-id column alias resolution for export inputs. +- Added typed handling for unassigned IDs in AnnData export paths. + +#### 2.4 Internal API and import refinements +- Switched multiple package-level imports to lazy-loading patterns to reduce import side effects and startup overhead. +- Updated data utility import strategy to stay consistent with existing project patterns. +- Added compatibility comments and deprecation guidance around legacy `cli/config.yaml` defaults. + +#### 2.5 Housekeeping +- No additional housekeeping notes in this release summary. diff --git a/README.md b/README.md index 050674a..58fd7e9 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Before installing **segger**, please install GPU-accelerated versions of PyTorch, RAPIDS, and related packages compatible with your system. *Please ensure all CUDA-enabled packages are compiled for the same CUDA version.* +- Segger is GPU-only and requires the RAPIDS stack (no CPU-only mode). + - **PyTorch & torchvision:** [Installation guide](https://pytorch.org/get-started/locally/) - **torch_scatter:** [Installation guide](https://github.com/rusty1s/pytorch_scatter#installation) - **RAPIDS (cuDF, cuML, cuGraph):** [Installation guide](https://docs.rapids.ai/install) @@ -32,6 +34,87 @@ git clone https://github.com/dpeerlab/segger.git segger && cd segger pip install -e . ``` +## Tips & Troubleshooting (v0.2.0) + +- Avoid user-site bleed: set `PYTHONNOUSERSITE=1` so `~/.local` packages do not shadow the env. +- Torch Geometric wheels must match your `torch` + CUDA version (`data.pyg.org` URL must match). +- Keep RAPIDS packages from a single channel/version set; avoid pip/conda mixing for RAPIDS. +- NFS cleanup noise (`.nfs*`): set `TMPDIR` to local scratch to avoid exit-time errors. +- UCX/CUDA segfaults: try `UCX_MEMTYPE_CACHE=n` and `UCX_TLS=sm,self`. + +## Optional Dependencies & Lazy Imports + +Segger defers imports for several heavy/optional features to keep `import segger` fast and to allow partial installs. If an optional dependency is missing, some top-level re-exports (notably in `segger.io` and `segger.export`) will be `None` rather than raising at import time. + +```python +from segger.io import get_preprocessor +if get_preprocessor is None: + raise ImportError("Install opencv-python for preprocessors.") +``` + +For strict import errors, import from submodules directly: + +```python +from segger.io.preprocessor import get_preprocessor +``` + +Common optional dependencies: +- `opencv-python` (preprocessors) +- `spatialdata` + `dask` (SpatialData loader/writer) +- `spatialdata-io` (platform-specific SpatialData readers) +- `uniplot` + `matplotlib` (loss curve plotting; install with `segger[plot]`) +- `sopa` (SOPA export helpers) +- `geopandas`/`shapely` (geometry utilities) + +## v0.2.0 Detailed Delta vs `v0.1.0` + +This summary is intentionally based on the release baseline comparison (`dd681a8...release/v2-stable`), not only on the latest commit. + +- Comparison snapshot: + - `v0.1.0` baseline reference: `dd681a8` (`2025-12-17`, `pyproject.toml` version `0.1.0`) + - Release snapshot: `2c92b43` (`2026-02-13`) + - Delta size: `33` commits, `76` files changed, `18,232` insertions, `321` deletions + +### New CLI workflows + +- `segger predict`: + - Checkpoint-only inference (`-c`) with strict checkpoint/data compatibility checks for `segger_vocab`, `segger_me_gene_pairs`, and `n_genes`. + - Supports inference-time graph overrides (`--transcripts-max-k`, `--transcripts-max-dist`, `--prediction-max-k`), assignment controls (`--min-similarity`, `--min-similarity-shift`), fragment controls, and `--use-3d`. + - Supports post-predict multi-format output (`--output-format`) with optional overwrite semantics. +- `segger export`: + - Unified export entry point for `xenium_explorer|merged|spatialdata|anndata`. + - Handles segmentation inputs from parquet/csv/SpatialData with `--input-format auto|raw|spatialdata`. + - Adds explicit boundary policy (`--boundary-method input|convex_hull|delaunay|skip`), worker controls, polygon vertex limits, and cell-id alias resolution. +- `segger plot`: + - Resolves latest or specific Lightning run metrics (`--log-version`) from `lightning_logs/version_*`. + - Groups train/val series by metric key, applies rolling smoothing, and renders either terminal pages (`--quick`) or paginated PNG outputs. + +### New capabilities + +- End-to-end SpatialData support: + - `.zarr` ingest path in data loading and export path to SpatialData output. + - Optional AnnData table embedding in SpatialData output. + - Lightweight direct SpatialData Zarr I/O utilities for reduced dependency footprints. +- Alignment-loss pipeline: + - ME-gene constraints integrated into graph/loss flow with scheduled weighting and combination modes. + - Checkpoint persistence + restore of `segger_vocab` and `segger_me_gene_pairs`. +- Fragment-mode segmentation: + - Unassigned transcript recovery via tx-tx connected components with similarity thresholding. + - GPU-first path with CPU fallback. + +### Stability/performance changes + +- Checkpoint-first inference hardening: + - Explicit mismatch failures for vocabulary order and gene-count incompatibility to prevent silent misalignment. +- Segmentation writer improvements: + - More robust auto-thresholding path with safer memory behavior and sign-stable threshold shifting. +- Boundary/export resilience: + - Safer polygon handling and process-to-thread fallback for parallel Xenium export when process pools fail. +- Optional dependency behavior: + - Expanded lazy-loading and explicit install guidance for partial environments. +- Validation surface: + - Significant test/CI expansion across CLI, export, alignment, fragment, and SpatialData paths. + # Usage You can run **segger** from the command line with: @@ -42,4 +125,60 @@ segger segment -i /path/to/your/ist/data/ -o /path/to/save/outputs/ To see all available parameter options: ```bash segger segment --help -``` \ No newline at end of file +``` + +Run prediction only from a saved checkpoint (no retraining): +```bash +segger predict -c /path/to/checkpoints/segger-best-epoch.ckpt \ + -i /path/to/your/ist/data/ \ + -o /path/to/save/outputs/ +``` + +Plot loss curves from the latest training run: +```bash +segger plot -o /path/to/save/outputs/ +``` + +Quick terminal plot (no image saved): +```bash +segger plot -o /path/to/save/outputs/ --quick +``` + +Plot a specific Lightning run version: +```bash +segger plot -o /path/to/save/outputs/ --log-version 0 +``` + +## CLI Parameters (New/Updated) + +- `--input-format` (`auto` | `raw` | `spatialdata`) and `--output-format` (`segger_raw` | `merged` | `spatialdata` | `anndata` | `all`). +- `--boundary-method` (`input` | `convex_hull` | `delaunay` | `skip`) and `--boundary-n-jobs` (0 uses `--num-workers`). +- `--sopa-compatible` for SOPA-ready SpatialData output. +- `--num-workers` for data loading (and as the default for boundary generation). +- `--prediction-scale-factor`: polygon scaling for tx→bd candidate edges (default 1.2). +- `--min-similarity`: fixed similarity threshold; if unset, per-gene auto-thresholding. +- `--fragment-mode`, `--fragment-min-transcripts`, `--fragment-similarity-threshold`. +- `--alignment-loss`, `--scrna-reference-path`, `--scrna-celltype-column`. +- `--alignment-loss-weight-start`, `--alignment-loss-weight-end`, `--loss-combination-mode`. +- `--early-stopping-patience` (default `10`) and `--early-stopping-min-delta` (default `1e-4`) for validation-based stopping on `val:loss`. +- `--use-3d` (`auto` | `true` | `false`) and `--min-qv` for quality filtering. +- `--tiling-margin-training`, `--tiling-margin-prediction`, `--max-nodes-per-tile`, `--max-edges-per-batch`. + +## Alignment Loss Example + +```bash +segger segment -i /path/to/your/ist/data/ -o /path/to/save/outputs/ \ + --alignment-loss \ + --scrna-reference-path segger_experiments/data_raw/scrnaseq/human_crc.h5ad \ + --scrna-celltype-column celltype +``` + +# Project Docs + +- Versioning: `docs/VERSIONING.md` +- Release process: `docs/RELEASE.md` +- Release notes: `docs/releases/v0.2.0.md` +- Installation notes: `docs/INSTALLATION.md` +- Loss functions: `docs/LOSS_FUNCTIONS.md` +- Math foundations: `docs/MATH.md` +- Changelog: `CHANGELOG.md` diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md new file mode 100644 index 0000000..a0ccdb3 --- /dev/null +++ b/docs/INSTALLATION.md @@ -0,0 +1,48 @@ +# Installation Notes (v0.2.0) + +This project relies on GPU-accelerated packages (PyTorch, RAPIDS, cuSpatial). A clean, consistent environment avoids most runtime errors. + +- Segger is GPU-only and requires the RAPIDS stack (no CPU-only mode). + +## Clean Install Checklist + +- Use a fresh env; avoid mixing pip/conda for RAPIDS packages. +- Keep CUDA versions consistent across PyTorch, RAPIDS, and cuSpatial. +- Install `torch-geometric` from a wheel that matches your `torch` + CUDA version. +- Pin `sympy` to `1.13.1` (matches PyTorch 2.5.x) and ensure `mpmath` is installed. +- Install Lightning from the same env (avoid `~/.local` bleed): + - `PYTHONNOUSERSITE=1` before running jobs. + +## Cluster Tips + +- NFS cleanup errors (`.nfs*`) are harmless but noisy. Set `TMPDIR` to local scratch: + - `export TMPDIR=/ssd/$USER/segger_tmp` (or cluster-specific scratch). +- UCX/CUDA segfaults: try + - `export UCX_MEMTYPE_CACHE=n` + - `export UCX_TLS=sm,self` + +## Alignment Loss + +Alignment loss requires an scRNA-seq reference: + +```bash +segger segment -i /path/to/data -o /path/to/output \ + --alignment-loss \ + --scrna-reference-path segger_experiments/data_raw/scrnaseq/human_crc.h5ad \ + --scrna-celltype-column celltype +``` + +## Optional Dependencies (Lazy-Loaded) + +Segger defers imports for several heavy or optional features, so `import segger` works without them. These features become available only when the corresponding dependency is installed. + +- Preprocessors: `opencv-python` +- SpatialData loader/writer: `spatialdata`, `dask`, `zarr` (and `geopandas` for shapes) +- SpatialData platform readers: `spatialdata-io` (install with `segger[spatialdata-io]`) +- Loss curve plotting: `uniplot` + `matplotlib` (install with `segger[plot]`) +- SOPA helpers: `sopa` +- Geometry utilities: `geopandas`, `shapely` +- scRNA utilities: `scanpy`, `scikit-learn` +- RAPIDS/GPU helpers: `cudf`, `cuml`, `cugraph`, `cupy`, `cupyx` + +When importing from top-level modules like `segger.io` or `segger.export`, optional re-exports may be `None` if dependencies are missing. Import from the submodule directly to get a strict `ImportError`. diff --git a/docs/LOSS_FUNCTIONS.md b/docs/LOSS_FUNCTIONS.md new file mode 100644 index 0000000..d24b89e --- /dev/null +++ b/docs/LOSS_FUNCTIONS.md @@ -0,0 +1,314 @@ +# Loss Functions in Segger v0.2.0 + +This document describes the loss functions available in Segger and provides guidance on when and how to use them. + +## Paper Foundation + +The original Segger paper ("segger: scalable graph neural network cell segmentation", 2025) introduced a **Binary Cross-Entropy (BCE)** loss for link prediction: + +**v1 BCE Loss:** +$$\mathcal{L}_{BCE} = -\sum_{(t_i, c_j) \in \mathcal{E}} \left[y_{ij} \log \sigma(s_{ij}) + (1-y_{ij}) \log(1-\sigma(s_{ij}))\right]$$ + +where: +- $s_{ij} = \mathbf{h}_{t_i}^\top \mathbf{h}_{c_j}$ (dot product of embeddings) +- $y_{ij} = 1$ if transcript $t_i$ belongs to cell $c_j$ +- Negative sampling from **nearby cells** (hard negatives, 1:5 ratio) + +**Relationship to v2:** The v0.2.0 multi-task loss extends this foundation with: +1. Triplet loss for explicit cluster-aware embedding learning +2. Metric loss for phenograph-based cell similarity +3. Alignment loss for mutually exclusive (ME) gene constraints + +You can still use BCE-only mode for simplicity: `--segmentation-loss bce` + +--- + +## Overview + +Segger uses a multi-task loss combining several components: + +1. **Transcript Loss (tx)**: Triplet loss for transcript embedding similarity +2. **Boundary Loss (bd)**: Metric loss for cell boundary embeddings +3. **Segmentation Loss (sg)**: Main task loss (triplet or BCE) +4. **Alignment Loss (optional)**: Mutually exclusive gene constraints + +## Loss Components + +### Transcript Loss (`loss_tx`) + +**Type**: Triplet loss with cluster-aware sampling + +**Purpose**: Ensures transcripts from the same gene cluster have similar embeddings. + +**Parameters**: +- `--transcripts-margin`: Margin for triplet loss (default: 0.3) +- `--transcripts-loss-weight-start`: Initial weight (default: 1.0) +- `--transcripts-loss-weight-end`: Final weight (default: 1.0) + +### Boundary Loss (`loss_bd`) + +**Type**: Metric loss with phenograph cluster similarity + +**Purpose**: Ensures cell boundaries with similar expression profiles have similar embeddings. + +**Parameters**: +- `--cells-loss-weight-start`: Initial weight (default: 1.0) +- `--cells-loss-weight-end`: Final weight (default: 1.0) + +### Segmentation Loss (`loss_sg`) + +**Type**: Triplet loss or BCE (Binary Cross-Entropy) + +**Purpose**: Main segmentation task - learns transcript-to-boundary assignments. + +**Parameters**: +- `--segmentation-loss`: Loss type (`triplet` or `bce`, default: `triplet`) +- `--segmentation-margin`: Margin for triplet loss (default: 0.4) +- `--segmentation-loss-weight-start`: Initial weight (default: 0.0) +- `--segmentation-loss-weight-end`: Final weight (default: 0.5) + +**Recommendation**: Use `triplet` (default) for most cases. BCE may be useful for debugging or when triplet loss doesn't converge. + +### Alignment Loss (`loss_align`) + +**Type**: Contrastive margin loss on cosine similarity + +**Purpose**: Enforces biological constraints where mutually exclusive (ME) gene pairs should not co-localize in the same cell. + +**Edge selection**: +- Positives: tx-tx neighbor edges where both transcripts are from the **same gene** +- Negatives: tx-tx neighbor edges whose genes are **mutually exclusive** +- All other tx-tx edges are ignored for alignment loss +- Positives are subsampled to at most **3×** the number of negatives + +**Parameters**: +- `--alignment-loss`: Enable alignment loss (default: False) +- `--alignment-loss-weight-start`: Initial weight (default: 0.0) +- `--alignment-loss-weight-end`: Final weight (default: 0.1) +- `--scrna-reference-path`: Path to scRNA-seq h5ad for ME gene discovery +- `--scrna-celltype-column`: Cell type column in reference (default: "celltype") +- `--loss-combination-mode`: How to combine with main loss (default: "interpolate") + +**Fixed margin**: $m = 0.2$ (not user-configurable) + +## Weight Scheduling + +All loss weights use cosine scheduling that transitions from `weight_start` to `weight_end` over training: + +``` +alpha = 0.5 * (1 + cos(π * epoch / max_epochs)) +weight = weight_end + (weight_start - weight_end) * alpha +``` + +This provides a smooth transition, typically used to: +- Start with embedding losses (tx, bd) at full weight +- Gradually increase segmentation loss (sg) +- Ramp up alignment loss as embeddings stabilize + +## Loss Combination Modes + +When alignment loss is enabled, it can be combined with the main loss in two ways: + +### Interpolate Mode (Default) + +```python +loss = (1 - align_weight) * main_loss + align_weight * align_loss +``` + +- Main loss decreases as alignment weight increases +- Total loss scale remains approximately constant +- Good for fine-tuning the balance between tasks + +### Additive Mode + +```python +loss = main_loss + align_weight * align_loss +``` + +- Alignment loss is added on top of main loss +- Simpler but total loss scale increases over training +- May require adjusting learning rate + +## Recommended Configurations + +### Default (No Alignment Loss) + +Best for most cases without scRNA-seq reference: + +```bash +segger segment -i data/ -o output/ +``` + +Uses: +- Triplet loss for segmentation +- Cosine-scheduled weight ramp-up +- No ME gene constraints + +### With Alignment Loss + +When you have an scRNA-seq reference with cell type annotations: + +```bash +segger segment -i data/ -o output/ \ + --alignment-loss \ + --alignment-loss-weight-end 0.1 \ + --scrna-reference-path reference.h5ad \ + --scrna-celltype-column celltype +``` + +Uses: +- ME genes discovered from reference +- Alignment loss ramped up over training +- Interpolate mode (default) + +### High-Precision (Aggressive Alignment) + +For datasets where false cell merges are a major concern: + +```bash +segger segment -i data/ -o output/ \ + --alignment-loss \ + --alignment-loss-weight-end 0.2 \ + --loss-combination-mode additive \ + --scrna-reference-path reference.h5ad +``` + +### Debugging / BCE Mode + +If triplet loss doesn't converge: + +```bash +segger segment -i data/ -o output/ \ + --segmentation-loss bce \ + --segmentation-loss-weight-start 0.1 \ + --segmentation-loss-weight-end 0.5 +``` + +## Troubleshooting + +### Loss not decreasing + +1. Check that loss weights sum to > 0 +2. Try lower learning rate (`--learning-rate 1e-4`) +3. Increase `--segmentation-loss-weight-end` + +### Training unstable + +1. Use `--loss-combination-mode interpolate` (default) +2. Reduce `--alignment-loss-weight-end` to 0.05 +3. Check data quality and batch sizes +4. Increase `--early-stopping-patience` if validation loss is noisy + +### Alignment loss too high + +1. Verify scRNA-seq reference has correct cell type labels +2. Check that gene names match between reference and spatial data +3. Try reducing `--alignment-loss-weight-end` + +### No ME genes found + +1. Ensure reference has diverse cell types +2. Check `--scrna-celltype-column` matches reference +3. Verify gene name format (symbols vs Ensembl IDs) + +## Monitoring + +During training, monitor these logged metrics: + +- `val:loss` - Total validation loss (used by early stopping/checkpointing) +- `train:loss_tx` - Transcript embedding loss +- `train:loss_bd` - Boundary embedding loss +- `train:loss_sg` - Segmentation loss +- `train:loss_align` - Alignment loss (if enabled) + +All should decrease over training. If alignment loss stays high, ME gene constraints may be too strict. + +Early stopping defaults: +- `--early-stopping-patience 10` +- `--early-stopping-min-delta 1e-4` + +Set `--early-stopping-patience 0` to disable early stopping. + +## Mathematical Details + +### Triplet Loss + +For anchor (a), positive (p), and negative (n): + +``` +L = max(0, ||a - p||² - ||a - n||² + margin) +``` + +### Alignment Loss + +For selected tx-tx neighbor pairs: + +``` +sim = dot(emb_src, emb_dst) +L_pos = (1 - sim)^2 # same-gene positives +L_neg = max(sim - m, 0)^2 # ME negatives +L = mean(L_pos) + mean(L_neg) +``` + +Where positives are same-gene neighbors, negatives are ME gene pairs, and $m=0.2$. + +### Combined Loss + +``` +L_main = w_tx * L_tx + w_bd * L_bd + w_sg * L_sg + +# Interpolate mode: +L_total = (1 - w_align) * L_main + w_align * L_align + +# Additive mode: +L_total = L_main + w_align * L_align +``` + +--- + +## MECR Metric and Alignment Loss + +### Mutually Exclusive Co-expression Rate (MECR) + +The MECR metric from the paper measures over-segmentation artifacts: + +$$\text{MECR}(g_1, g_2) = \frac{P(g_1 \land g_2)}{P(g_1 \lor g_2)}$$ + +where $g_1, g_2$ are mutually exclusive (ME) genes that should not co-occur in the same cell. + +**Interpretation:** +- Lower MECR is better (ME genes shouldn't be in the same cell) +- High MECR indicates cell merging artifacts +- Typical good values: < 0.15 + +### How Alignment Loss Reduces MECR + +The alignment loss directly targets MECR by: +1. Identifying ME gene pairs from scRNA-seq reference +2. Selecting tx-tx neighbor edges that are ME pairs (negatives) or same-gene (positives) +3. Training embeddings to push ME transcripts apart and pull same-gene neighbors together + +**Connection:** +``` +Alignment Loss (ME negatives + same-gene positives) + → ME transcripts become dissimilar + → Same-gene neighbors become more similar + → Segmentation less likely to assign ME transcripts to same cell + → Lower MECR in final segmentation +``` + +### ME Gene Discovery + +ME genes are discovered from scRNA-seq reference using: +1. Identify cell-type-specific marker genes +2. Find gene pairs where each gene marks a different cell type +3. These become ME pairs (shouldn't co-occur) + +**Defaults** (can be adjusted in code): +- `pos_percentile=10` +- `percentage=30` +- `expr_threshold_in=0.25` +- `expr_threshold_out=0.03` +- Cells are subsampled to at most **1000 per cell type** for performance + +See `validation/me_genes.py` for implementation details. diff --git a/docs/MATH.md b/docs/MATH.md new file mode 100644 index 0000000..6543462 --- /dev/null +++ b/docs/MATH.md @@ -0,0 +1,424 @@ +# Mathematical Foundations of Segger v0.2.0 + +This document provides a comprehensive mathematical description of Segger's cell segmentation approach, covering problem formulation, graph construction, neural network architecture, loss functions, and inference. + +--- + +## Paper Foundation Reference + +The mathematical foundations derive from the Segger v1 paper: "segger: scalable graph neural network cell segmentation" (2025). + +**Original v1 Formulation:** + +Graph definition: +$$\mathcal{G} = (\mathcal{V}, \mathcal{E}) \text{ where } \mathcal{V} = \mathcal{T} \cup \mathcal{C}$$ + +v1 Loss (Binary Cross-Entropy): +$$\mathcal{L}_{BCE} = -\sum_{(t_i, c_j) \in \mathcal{E}} \left[y_{ij} \log \sigma(s_{ij}) + (1-y_{ij}) \log(1-\sigma(s_{ij}))\right]$$ + +where: +- $s_{ij} = \mathbf{h}_{t_i}^\top \mathbf{h}_{c_j}$ (dot product similarity) +- $y_{ij} = 1$ if transcript $t_i$ belongs to cell $c_j$, else $0$ +- $\sigma(\cdot)$ is the sigmoid function + +**Negative Sampling:** The paper uses hard negative sampling from nearby cells (not random), with a 1:5 positive:negative ratio. + +**v2 Evolution:** This document describes the v0.2.0 multi-task loss approach (Triplet + Metric + Alignment) that builds upon and extends the v1 BCE baseline. + +## 1. Problem Formulation + +### 1.1 Input + +Given spatial transcriptomics data: +- **Transcripts**: $\mathcal{T} = \{t_1, t_2, \ldots, t_N\}$ where each $t_i = (x_i, y_i, g_i)$ consists of: + - Spatial coordinates $(x_i, y_i) \in \mathbb{R}^2$ + - Gene label $g_i \in \{1, \ldots, G\}$ for $G$ unique genes +- **Boundaries**: $\mathcal{B} = \{b_1, b_2, \ldots, b_M\}$ where each $b_j$ is a polygon (cell/nucleus) + +### 1.2 Output + +Cell assignment function $f: \mathcal{T} \to \mathcal{B} \cup \{\varnothing\}$ mapping each transcript to a cell or unassigned. + +### 1.3 Key Insight + +We frame cell segmentation as **link prediction** on a heterogeneous graph, where we learn to predict which transcript-boundary pairs should be connected. + +--- + +## 2. Graph Construction + +### 2.1 Node Types + +The heterogeneous graph $\mathcal{G} = (\mathcal{V}, \mathcal{E})$ has two node types: + +- **Transcript nodes** (`tx`): $\mathcal{V}_{tx} = \{v_1^{tx}, \ldots, v_N^{tx}\}$ +- **Boundary nodes** (`bd`): $\mathcal{V}_{bd} = \{v_1^{bd}, \ldots, v_M^{bd}\}$ + +### 2.2 Edge Types + +Three edge types capture different relationships: + +1. **Transcript-Transcript Neighbors** (`tx → neighbors → tx`): + + Using a KD-tree with parameters $(k_{max}, d_{max})$: + $$\mathcal{E}_{tx \to tx} = \{(v_i^{tx}, v_j^{tx}) : \|p_i - p_j\|_2 \leq d_{max}, j \in \text{kNN}_k(i)\}$$ + + where $\text{kNN}_k(i)$ returns the $k$-nearest neighbors of transcript $i$. + +2. **Transcript-Boundary Belonging** (`tx → belongs → bd`): + + Ground truth segmentation edges for training: + $$\mathcal{E}_{tx \to bd} = \{(v_i^{tx}, v_j^{bd}) : t_i \in \text{interior}(b_j)\}$$ + +3. **Transcript-Boundary Prediction** (`tx → neighbors → bd`): + + Candidate edges for inference, using scaled polygons: + $$\mathcal{E}_{pred} = \{(v_i^{tx}, v_j^{bd}) : t_i \in \text{interior}(\text{scale}(b_j, s))\}$$ + + where `scale(b, s)` scales polygon $b$ by factor $s$ around its centroid: + - $s > 1$: Expand polygon (capture transcripts near boundaries) + - $s < 1$: Shrink polygon (be more conservative) + +### 2.3 Node Features + +**Transcript features** (`tx`): +$$\mathbf{x}_i^{tx} = \mathbf{e}_{g_i} \in \mathbb{R}^{d_g}$$ +where $\mathbf{e}_g$ is the embedding for gene $g$ (learned or pre-computed from scRNA-seq PCA). + +**Boundary features** (`bd`): +$$\mathbf{x}_j^{bd} = \text{PCA}(\mathbf{h}_j) \in \mathbb{R}^{d_c}$$ +where $\mathbf{h}_j$ is the aggregated expression profile from scRNA-seq reference. + +### 2.4 Boundary Feature Computation (from Paper) + +The paper defines four geometric features for each boundary polygon $B_i$: + +**Area:** +$$A(B_i) = \text{polygon area in } \mu m^2$$ + +**Convexity:** +$$C(B_i) = \frac{A(\text{ConvexHull}(B_i))}{A(B_i)}$$ + +Measures how convex the cell shape is (1.0 = perfectly convex). + +**Elongation:** +$$E(B_i) = \frac{A(\text{MBR}(B_i))}{A(\text{Envelope}(B_i))}$$ + +where MBR is the minimum bounding rectangle (oriented) and Envelope is the axis-aligned bounding box. + +**Circularity:** +$$\Gamma(B_i) = \frac{A(B_i)}{r_{min}(B_i)^2}$$ + +where $r_{min}$ is the radius of the minimum enclosing circle. + +**Feature Vector Construction:** +$$\mathbf{x}^{bd} = \text{Linear}([A, C, E, \Gamma]^\top) \in \mathbb{R}^{d}$$ + +The four features are concatenated and projected via a linear layer to match the model's embedding dimension $d$. + +--- + +## 3. GNN Architecture + +### 3.1 Overview + +The ISTEncoder architecture processes the heterogeneous graph through: +1. Initial linear projection +2. Positional embedding addition +3. Multiple SkipGAT convolution layers +4. Final linear projection with L2 normalization + +### 3.2 Positional Embeddings + +We use 2D sinusoidal embeddings to encode spatial positions. For position $(x, y)$: + +**Sinusoidal embedding** for scalar $z$ with dimension $d$: +$$\text{sin\_emb}(z, d)_k = \begin{cases} +\cos(z \cdot \omega_k) & \text{if } k < d/2 \\ +\sin(z \cdot \omega_{k-d/2}) & \text{if } k \geq d/2 +\end{cases}$$ + +where $\omega_k = \exp\left(-\frac{k \cdot \log(T)}{d/2}\right)$ with period $T = 10000$. + +**Per-batch normalization**: Positions are normalized to $[0, 1]$ within each batch: +$$\tilde{p}_i = \frac{p_i - \min_{j \in B}(p_j)}{\max_{j \in B}(p_j) - \min_{j \in B}(p_j) + \epsilon}$$ + +**MLP projection**: +$$\mathbf{pos}_i = \text{MLP}(\text{sin\_emb}(\tilde{x}_i) \| \text{sin\_emb}(\tilde{y}_i))$$ + +### 3.3 SkipGAT Layer + +Each SkipGAT layer applies GATv2 attention to different edge types: + +**GATv2 Convolution**: +$$\mathbf{h}'_i = \sum_{j \in \mathcal{N}(i)} \alpha_{ij} \mathbf{W} \mathbf{h}_j$$ + +**Attention weights**: +$$\alpha_{ij} = \frac{\exp(\mathbf{a}^\top \text{LeakyReLU}(\mathbf{W}[\mathbf{h}_i \| \mathbf{h}_j]))}{\sum_{k \in \mathcal{N}(i)} \exp(\mathbf{a}^\top \text{LeakyReLU}(\mathbf{W}[\mathbf{h}_i \| \mathbf{h}_k]))}$$ + +**Multi-head attention** with $H$ heads: +$$\mathbf{h}'_i = \|_{h=1}^H \sum_{j \in \mathcal{N}(i)} \alpha_{ij}^{(h)} \mathbf{W}^{(h)} \mathbf{h}_j$$ + +### 3.4 Full Forward Pass + +``` +Input: x_dict (node features), edge_index_dict, pos_dict, batch_dict + +1. Linear projection: x' = Linear(x) +2. Position embedding: x'' = x' || PosEmbed(pos, batch) +3. Activation: x''' = GELU(x'') + +4. For each SkipGAT layer: + x = GELU(SkipGAT(x, edge_index)) + +5. Final projection: x = Linear(x) +6. L2 normalization: x = x / ||x||_2 + +Output: Normalized embeddings for tx and bd nodes +``` + +### 3.5 L2 Normalization + +Final embeddings are L2-normalized: +$$\hat{\mathbf{h}}_i = \frac{\mathbf{h}_i}{\|\mathbf{h}_i\|_2}$$ + +This ensures that dot products equal cosine similarities: +$$\hat{\mathbf{h}}_i^\top \hat{\mathbf{h}}_j = \cos(\theta_{ij})$$ + +--- + +## 4. Loss Functions + +### 4.1 Combined Loss + +The total loss combines multiple components with scheduled weights: +$$\mathcal{L} = w_{tx} \mathcal{L}_{tx} + w_{bd} \mathcal{L}_{bd} + w_{sg} \mathcal{L}_{sg}$$ + +With optional alignment loss: +- **Interpolate mode**: $\mathcal{L}_{total} = (1 - w_{align}) \mathcal{L} + w_{align} \mathcal{L}_{align}$ +- **Additive mode**: $\mathcal{L}_{total} = \mathcal{L} + w_{align} \mathcal{L}_{align}$ + +### 4.2 Triplet Loss + +For anchor $a$, positive $p$, and negative $n$ with margin $m$: +$$\mathcal{L}_{triplet} = \max(0, \|a - p\|_2^2 - \|a - n\|_2^2 + m)$$ + +**Cluster-aware sampling** (FastTripletSelector): +- Positives sampled from similar clusters (high similarity weight) +- Negatives sampled from dissimilar clusters (low similarity weight) + +Sampling probability for cluster $c'$ given anchor cluster $c$: +- Positive: $P(c' | c) \propto S_{c,c'}$ (similarity matrix) +- Negative: $P(c' | c) \propto 1 - S_{c,c'}$ (dissimilarity) + +### 4.3 Metric Loss + +For boundary embeddings, we use MSE on cosine similarities: +$$\mathcal{L}_{metric} = \text{MSE}(\cos(\mathbf{h}_a, \mathbf{h}_p), 1 - d_{ap}) + \text{MSE}(\cos(\mathbf{h}_a, \mathbf{h}_n), 1 - d_{an})$$ + +where $d_{ap}, d_{an}$ are the cluster distances (from similarity matrix). + +### 4.4 Segmentation Loss (Triplet) + +For transcript $t$ assigned to boundary $b$: +$$\mathcal{L}_{sg} = \max(0, \|\mathbf{h}_t - \mathbf{h}_b\|_2^2 - \|\mathbf{h}_t - \mathbf{h}_{b'}\|_2^2 + m)$$ + +where $b'$ is a randomly sampled negative boundary. + +### 4.5 Alignment Loss + +Alignment loss is applied on a **subset of tx-tx neighbor edges**: +- **Positives**: neighboring transcript pairs from the **same gene** ($y=1$) +- **Negatives**: neighboring transcript pairs whose genes are **mutually exclusive** ($y=0$) +- All other tx-tx neighbor edges are ignored for alignment loss. + +To reduce class imbalance, positives are subsampled to at most **3×** the number +of negatives before computing $\mathcal{L}_{align}$. + +We use a **margin-based contrastive loss** on cosine similarity: +$$s_{ij} = \hat{\mathbf{h}}_{t_i}^\top \hat{\mathbf{h}}_{t_j}$$ + +$$\mathcal{L}_{align} = +\mathbb{E}_{(i,j)\in\mathcal{P}}\left[(1 - s_{ij})^2\right] +\mathbb{E}_{(i,j)\in\mathcal{N}}\left[\max(0, s_{ij} - m)^2\right]$$ + +with margin $m = 0.2$. + +**ME gene pair matching** uses vectorized hash-based lookup on neighbor edges: +$$\text{key}(g_1, g_2) = \min(g_1, g_2) \cdot G_{max} + \max(g_1, g_2)$$ + +--- + +## 5. Weight Scheduling + +### 5.1 Cosine Schedule + +All loss weights use cosine scheduling from start to end values: +$$\alpha(t) = \frac{1}{2}\left(1 + \cos\left(\pi \cdot \frac{t}{T}\right)\right)$$ + +$$w(t) = w_{end} + (w_{start} - w_{end}) \cdot \alpha(t)$$ + +where $t$ is the current epoch and $T$ is total epochs. + +**Properties**: +- At $t = 0$: $\alpha = 1$, $w = w_{start}$ +- At $t = T$: $\alpha = 0$, $w = w_{end}$ +- Smooth transition with zero derivative at endpoints + +### 5.2 Typical Schedule + +| Epoch | $w_{tx}$ | $w_{bd}$ | $w_{sg}$ | $w_{align}$ | +|-------|----------|----------|----------|-------------| +| 0 | 0.33 | 0.33 | 0.00 | 0.00 | +| T/2 | 0.28 | 0.28 | 0.18 | 0.05 | +| T | 0.20 | 0.20 | 0.30 | 0.10 | + +Weights are normalized to sum to 1 (for non-alignment losses). + +--- + +## 6. Inference + +### 6.1 Similarity Scoring + +For each transcript-boundary candidate edge: +$$s_{ij} = \cos(\mathbf{h}_i^{tx}, \mathbf{h}_j^{bd}) = (\hat{\mathbf{h}}_i^{tx})^\top \hat{\mathbf{h}}_j^{bd}$$ + +### 6.2 Assignment + +Each transcript is assigned to its highest-scoring boundary: +$$b^* = \arg\max_{j : (i, j) \in \mathcal{E}_{pred}} s_{ij}$$ + +### 6.3 Thresholding + +**Fixed threshold**: Accept if $s_{ij} \geq \tau$ + +**Per-gene auto-threshold**: For each gene $g$: +$$\tau_g = \min(\text{Li}(\{s : g_i = g\}), \text{Yen}(\{s : g_i = g\}))$$ + +Li and Yen are automatic histogram-based thresholding methods. + +### 6.4 Fragment Mode + +For unassigned transcripts, group using connected components: + +1. Build graph of unassigned transcripts using tx-tx edges +2. Filter edges by similarity: $s_{ij} \geq \tau_{frag}$ +3. Compute connected components (RAPIDS GPU or SciPy CPU) +4. Create "fragment cells" for components with $\geq k_{min}$ transcripts + +**Connected components** via sparse adjacency matrix: +$$A_{ij} = \begin{cases} 1 & \text{if } s_{ij} \geq \tau_{frag} \\ 0 & \text{otherwise} \end{cases}$$ + +--- + +## 7. Computational Complexity + +| Operation | Complexity | +|-----------|------------| +| KD-tree construction | $O(N \log N)$ | +| KNN query | $O(N k \log N)$ | +| GATv2 convolution | $O(|\mathcal{E}| \cdot d \cdot H)$ | +| Similarity computation | $O(|\mathcal{E}_{pred}| \cdot d)$ | +| Connected components | $O(|\mathcal{V}| + |\mathcal{E}|)$ | + +where: +- $N$: number of transcripts +- $k$: max neighbors +- $d$: embedding dimension +- $H$: attention heads +- $|\mathcal{E}|$: total edges + +--- + +## 8. Summary of Hyperparameters + +### Graph Construction +| Parameter | Symbol | Typical Value | +|-----------|--------|---------------| +| Max transcript neighbors | $k_{max}$ | 10-50 | +| Max transcript distance | $d_{max}$ | 20-100 μm | +| Polygon scale factor | $s$ | 1.0-1.5 | + +### Model Architecture +| Parameter | Symbol | Typical Value | +|-----------|--------|---------------| +| Gene embedding dim | $d_g$ | 16-64 | +| Hidden channels | $d_h$ | 32-128 | +| Output channels | $d_{out}$ | 32-128 | +| Attention heads | $H$ | 2-4 | +| SkipGAT layers | $L$ | 3-5 | + +### Loss Functions +| Parameter | Symbol | Typical Value | +|-----------|--------|---------------| +| Transcript margin | $m_{tx}$ | 0.3 | +| Segmentation margin | $m_{sg}$ | 0.4 | +| Alignment weight end | $w_{align,end}$ | 0.1 | + +### Inference +| Parameter | Symbol | Typical Value | +|-----------|--------|---------------| +| Min similarity | $\tau$ | 0.3-0.7 | +| Fragment min transcripts | $k_{min}$ | 5-20 | +| Fragment similarity | $\tau_{frag}$ | 0.5 | + +--- + +## 9. v1 vs v2 Loss Comparison + +### When to Use BCE (v1 Approach) + +The original paper's BCE loss is suitable when: +- Simple binary link prediction is sufficient +- Computational resources are limited +- No scRNA-seq reference is available +- Debugging training issues + +**v1 BCE Loss:** +$$\mathcal{L}_{BCE} = -\sum_{(t_i, c_j)} \left[y_{ij} \log \sigma(s_{ij}) + (1-y_{ij}) \log(1-\sigma(s_{ij}))\right]$$ + +### When to Use Multi-Task (v2 Approach) + +The v2 multi-task loss is recommended when: +- Higher embedding quality is needed +- scRNA-seq reference is available for ME gene discovery +- Dataset has clear cell type structure +- Reducing over-segmentation artifacts is important + +**v2 Multi-Task Loss:** +$$\mathcal{L}_{v2} = w_{tx} \mathcal{L}_{triplet}^{tx} + w_{bd} \mathcal{L}_{metric}^{bd} + w_{sg} \mathcal{L}_{triplet}^{sg} + w_{align} \mathcal{L}_{align}$$ + +### Comparison Table + +| Aspect | v1 BCE | v2 Multi-Task | +|--------|--------|---------------| +| Loss function | Single BCE | Triplet + Metric + Alignment | +| Embedding learning | Implicit | Explicit cluster-aware | +| ME gene constraints | None | Optional alignment loss | +| scRNA-seq required | No | Optional (for alignment) | +| Training complexity | Simple | Moderate (weight scheduling) | +| Typical use case | Baseline, debugging | Production, high quality | + +### Migration Path + +To use v1-style BCE in v0.2.0: +```bash +segger segment -i data/ -o output/ --segmentation-loss bce +``` + +To use full v2 multi-task: +```bash +segger segment -i data/ -o output/ \ + --alignment-loss \ + --scrna-reference-path reference.h5ad +``` + +--- + +## References + +1. Brody, S., Alon, U., & Yahav, E. (2022). How Attentive are Graph Attention Networks? ICLR. +2. Hamilton, W. L. (2020). Graph Representation Learning. Morgan & Claypool. +3. Li, C. H., & Tam, P. K. S. (1998). An iterative algorithm for minimum cross entropy thresholding. Pattern Recognition Letters. +4. Yen, J. C., Chang, F. J., & Chang, S. (1995). A new criterion for automatic multilevel thresholding. IEEE TIP. diff --git a/docs/RELEASE.md b/docs/RELEASE.md new file mode 100644 index 0000000..190e232 --- /dev/null +++ b/docs/RELEASE.md @@ -0,0 +1,58 @@ +# Release Process + +This checklist standardizes releases and keeps code, docs, and tags in sync. + +## 1. Prepare the Release + +- Ensure `main` is green and has the intended changes. +- Update `pyproject.toml` version. +- Update `CHANGELOG.md` with release notes and date. +- Add/update `docs/releases/vX.Y.Z.md` using: + 1. High-level summary + 2. Low-level technical details +- Review docs that mention the version (README, docs, slides if needed). + +## 2. Run Tests + +CPU-only (local or CI): + +```bash +PYTHONPATH=src pytest tests/ -v -m "not gpu and not spatialdata and not sopa" \ + --ignore=tests/test_spatialdata_io.py +``` + +SpatialData (optional dependency): + +```bash +PYTHONPATH=src pytest tests/test_spatialdata_io.py -v +``` + +GPU tests (when CUDA + RAPIDS are available): + +```bash +PYTHONPATH=src pytest tests/test_prediction_graph.py -v +PYTHONPATH=src pytest tests/test_alignment_loss.py -v +PYTHONPATH=src pytest tests/test_alignment_loss_integration.py -v +``` + +## 3. Build and Verify + +```bash +python -m build +python -m pip install dist/segger-*.whl +python -c "import segger; print('segger import ok')" +``` + +## 4. Tag and Publish + +```bash +git tag -a vX.Y.Z -m "Segger vX.Y.Z" +git push origin vX.Y.Z +``` + +Then create a GitHub Release using the changelog entry. + +## 5. Post-Release + +- Bump to the next development version if desired (e.g., `0.2.1-dev`). +- Open a tracking issue for the next milestone. diff --git a/docs/VERSIONING.md b/docs/VERSIONING.md new file mode 100644 index 0000000..3252c9a --- /dev/null +++ b/docs/VERSIONING.md @@ -0,0 +1,115 @@ +# Versioning + +Segger follows Semantic Versioning (SemVer 2.0.0): + +``` +MAJOR.MINOR.PATCH +``` + +- **MAJOR**: Backward-incompatible changes to the public API, CLI, or file formats. +- **MINOR**: Backward-compatible features and improvements. +- **PATCH**: Backward-compatible bug fixes and small maintenance changes. + +## Pre-1.0 Policy + +Until `1.0.0`, Segger uses a stricter interpretation: + +- **MINOR** may include breaking changes. +- **PATCH** remains backward-compatible for the supported surface area. + +## Source of Truth + +The package version is defined in: + +- `pyproject.toml` (`[project].version`) + +Any release must update this value, the changelog, and the release notes. + +## Release Comparison Baseline (Required) + +For release branches, changelog and release-note scope must be computed against the previous released baseline (for `v0.2.0`, this is `v0.1.0`), not just against the most recent commit batch. + +Use: + +```bash +git rev-parse +git log --oneline .. +git diff --stat ... +``` + +Required metadata in release docs: +- Previous-release baseline hash/date. +- Release-branch snapshot hash/date used for summary. +- Commit count and file/line delta from the previous release baseline. +- Major vs minor classification by subsystem. + +## Pre-releases + +Use pre-release suffixes for release candidates or previews: + +``` +0.3.0-rc.1 +0.3.0-beta.2 +``` + +## Versioning Scope + +When deciding version bumps, consider: + +- Python API: public functions, classes, and module behaviors +- CLI: flags, defaults, config file formats +- Output schemas: parquet or Zarr output formats +- Model checkpoints and training configs + +If a change requires user code or data migration, treat it as breaking. + +## Major vs Minor Classification + +When writing release notes against the previous release baseline, classify each subsystem explicitly: + +- **Major changes**: + - New commands or workflows. + - New output formats or schema families. + - New model/loss behavior that materially changes training or inference semantics. + - New dependency families that affect install/runtime behavior. + - New I/O pathways (for example, new platform/store support). +- **Minor changes**: + - Bug fixes that keep the same user contract. + - Performance/stability improvements without new conceptual workflows. + - Default tuning, logging/diagnostics, docs, and test hardening. + - Internal refactors that do not materially change user-facing behavior. + +## Release Note Structure (Required) + +Each shipped version should include a release note file under `docs/releases/` +named `vX.Y.Z.md` and use this structure: + +1. **High-level** + - Must be derived from `...` comparison. + - Focus on major features, behavior changes, and migration impact. +2. **Low-level** + - Technical details grouped by subsystem (CLI, data/model, export, I/O, tests/docs). + - Include concrete option names/defaults/API notes when they affect behavior or compatibility. + +## Worked Example: v0.2.0 (`v0.1.0` baseline -> `release/v2-stable`) + +Comparison snapshot used: +- `v0.1.0` baseline reference: `dd681a8` (`2025-12-17`, `pyproject.toml` version `0.1.0`) +- Release snapshot: `2c92b43` (`2026-02-13`) +- Delta: `33` commits, `76` files, `18,232` insertions, `321` deletions. + +Major classifications for `v0.2.0`: +- CLI lifecycle expansion (`segment` early stopping/best-ckpt prediction, new `predict`, new `plot`, richer `export`). +- New export architecture and formats (`merged`, `spatialdata`, `anndata`, Xenium improvements, boundary strategy controls). +- New SpatialData input/output pathways and lightweight `.zarr` interoperability utilities. +- New alignment-loss training path and checkpoint metadata contract (`segger_vocab`, `segger_me_gene_pairs`). +- New quality-filter layer, 3D-aware graph construction controls, and fragment-mode post-processing. +- New optional dependency model, dataset helpers, CI pipeline, and comprehensive test suite. + +Minor classifications for `v0.2.0`: +- Prediction graph scale-factor alignment fix and boundary robustness improvements. +- ME-gene caching, progress messaging, and sampling/default tuning. +- Parallel export fallback hardening and import/lazy-loading cleanup. +- CLI help polishing and repository housekeeping changes. + +This policy keeps release communication complete, comparable across branches, and easier for users to trust. diff --git a/docs/releases/v0.2.0.md b/docs/releases/v0.2.0.md new file mode 100644 index 0000000..bd1b864 --- /dev/null +++ b/docs/releases/v0.2.0.md @@ -0,0 +1,49 @@ +# Segger v0.2.0 Release Notes + +Release date: 2026-02-12 + +## 1. Technical Summary + +### New CLI workflows + +- `segger predict`: + - Checkpoint-only inference (`-c`) with explicit compatibility checks for checkpoint metadata (`segger_vocab`, `segger_me_gene_pairs`) and runtime `n_genes`. + - Supports inference-time graph overrides (`--transcripts-max-k`, `--transcripts-max-dist`, `--prediction-max-k`) and assignment controls (`--min-similarity`, `--min-similarity-shift`). + - Adds fragment controls (`--fragment-mode`, `--fragment-min-transcripts`, `--fragment-similarity-threshold`) and 3D policy control (`--use-3d`). +- `segger export`: + - Unified format conversion (`xenium_explorer|merged|spatialdata|anndata`) from parquet/csv/SpatialData segmentation inputs. + - Adds explicit input resolution (`--input-format auto|raw|spatialdata`) and boundary strategy controls (`--boundary-method input|convex_hull|delaunay|skip`). + - Supports overwrite behavior for compatible outputs and stronger cell-id alias handling. +- `segger plot`: + - Resolves latest or selected Lightning run metrics (`--log-version`) and groups train/val curves by metric key. + - Provides terminal plotting (`--quick`) and PNG export with pagination when metric count exceeds one page. + +### New capabilities + +- SpatialData interoperability: + - Added `.zarr` ingest, SpatialData writer output, and optional AnnData table embedding. + - Added lightweight direct SpatialData Zarr utilities for environments without full spatialdata stack. +- Alignment-loss workflow: + - Added ME-gene constraint integration with scheduled weighting and combination modes. + - Added checkpoint persistence/restoration for `segger_vocab` and `segger_me_gene_pairs`. +- Fragment-mode workflow: + - Added unassigned-transcript recovery via tx-tx connected-component assignment with similarity thresholding. + - Added GPU-first execution path with CPU fallback. + +### Stability/performance changes + +- Inference safety: + - Added strict checkpoint-first mismatch detection to prevent silent gene-mapping and metadata drift. +- Segmentation/output robustness: + - Improved auto-thresholding behavior and memory profile in segmentation writing. + - Hardened boundary generation and Xenium parallel execution with process-to-thread retry fallback. +- Dependency/runtime behavior: + - Expanded lazy optional-dependency handling with clearer import-time and runtime failure messages. +- Validation/QA: + - Expanded tests and CI coverage across CLI, export, alignment, fragment, and SpatialData code paths. + +## 2. Implementation Notes + +- `segment` now supports early stopping on `val:loss` and runs prediction from best checkpoint when available. +- AnnData export path supports split outputs when fragment-labeled predictions are present (`segger_segmentation.h5ad`, `segger_fragments.h5ad`). +- SpatialData export preserves `cell_id` across points/shapes for downstream interoperability. diff --git a/examples/plotting_guide.ipynb b/examples/plotting_guide.ipynb new file mode 100644 index 0000000..47fd37a --- /dev/null +++ b/examples/plotting_guide.ipynb @@ -0,0 +1,397 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-11T09:05:45.389608Z", + "iopub.status.busy": "2026-02-11T09:05:45.389153Z", + "iopub.status.idle": "2026-02-11T09:05:46.044058Z", + "shell.execute_reply": "2026-02-11T09:05:46.043322Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loaded 24835 steps, 4 metric groups\n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib as mpl\n", + "\n", + "# Set color palette (matches segger plot)\n", + "colors = plt.cm.tab10.colors\n", + "mpl.rcParams['axes.prop_cycle'] = mpl.cycler(color=colors)\n", + "\n", + "# Load and prepare metrics\n", + "df = pd.read_csv(\"../../metrics.csv\")\n", + "\n", + "def smooth(values):\n", + " \"\"\"Adaptive smoothing: window = max(5, min(25, count // 20))\"\"\"\n", + " window = max(5, min(25, len(values) // 20))\n", + " return pd.Series(values).rolling(window, min_periods=1).mean().to_numpy()\n", + "\n", + "# Group metrics\n", + "metrics = {}\n", + "for col in df.columns:\n", + " if col in ['epoch', 'step']:\n", + " continue\n", + " base = col.split(':')[1] if ':' in col else col\n", + " metrics.setdefault(base, []).append(col)\n", + "\n", + "# Extract data\n", + "metrics_data = []\n", + "for base, cols in sorted(metrics.items()):\n", + " entries = []\n", + " for col in cols:\n", + " data = df[col].dropna()\n", + " if len(data) > 0:\n", + " x = df['step'][:len(data)].values\n", + " y = smooth(data.values)\n", + " label = 'val' if col.startswith('val:') else 'train'\n", + " entries.append((label, col, x, y))\n", + " if entries:\n", + " metrics_data.append((base, entries))\n", + "\n", + "print(f\"Loaded {len(df)} steps, {len(metrics_data)} metric groups\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example Output\n", + "\n", + "From Xenium breast cancer training with v2 multi-task loss:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example Output\n", + "\n", + "From Xenium breast cancer training with v2 multi-task loss:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Matplotlib Plot" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-11T09:05:46.074338Z", + "iopub.status.busy": "2026-02-11T09:05:46.074151Z", + "iopub.status.idle": "2026-02-11T09:05:46.518302Z", + "shell.execute_reply": "2026-02-11T09:05:46.517663Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "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J8W0k2LmAO106mIqy82bN8vp1Lt37y4vpaetHDRokJz6UkxFGRISYnTaysmTJ8tZsBYtWlRm2kpHkZ6eLqf3FBfxlbFgwQJ5+/Lly/LxefPmyeP4119/1Rw5ckTO4hYVFaXJzs7WbWPIkCGa9u3ba/bs2aPZvn27pnHjxprRo0frHhezj4WFhWkef/xxOSWp+FsR7f/ZZ5/p1hGftYuLi2b+/PnyMxEzBIkZy44ePapxxLYXj7366qtydjbxt7Bx40ZNhw4dZNvm5OTotsG2r74JEyZo/P395feN/jS4WVlZunUs9X3jaP9/3K7tz507p3nrrbdkm4vjX3z/NGzYUHPHHXfotsG2tw2OdmybC/tGlsN+kbLYN1IO+0XKmmBnfSMGoizs448/lj9a3Nzc5LSHu3fvtvQu2DwxfWTt2rVlG9atW1feF394WiIA8txzz2kCAgLkH9F9990n/0j1Xbp0STN06FCNp6enDGKJDlx+fr7BOlu2bNG0a9dOvo74I/7iiy80jki0gwiClL6MHTtWPq5WqzXTp0+XgSTxhTRgwADN6dOnDbZx8+ZNGXjy8fGR04OOGzdOdiT0HT58WNOrVy+5DfG5igBXad9//72mSZMm8jMR04quWbNG46htL/7TEf+JiP88RECuQYMGmvHjx5f5D4BtX33G2l5c9L8LLPl940j/f9yu7WNjY2XHKjAwUH5nREdHyw5TamqqwXbY9rbBkY5tc2HfyHLYL1IW+0bKYb9IWbCzvpGq+E0RERERERERERGZFWtEERERERERERGRRTAQRUREREREREREFsFAFBERERERERERWQQDUUREREREREREZBEMRBERERERERERkUUwEEVERERERERERBbBQBQREREREREREVkEA1FERERERERERGQRDEQREREREREREZFFMBBFRA7viSeewIgRIxy+HYiIiIgE9o2IyJwYiCIiIiIiIiIiIotgIIqIHMaPP/6I1q1bw9PTE0FBQRg4cCAmT56MFStW4Ndff4VKpZKXmJgYuf6VK1fw8MMPo1atWggMDMTw4cNx6dKlMmcLZ8+ejZCQEPj5+eHZZ59FXl6egu+SiIiIqHLYNyIiJbgo8qpERBZ248YNjB49Gu+//z7uu+8+pKen4++//8aYMWMQGxuLtLQ0fPHFF3JdEXTKz8/H4MGD0b17d7mei4sL3n77bQwZMgRHjhyBm5ubXHfTpk3w8PCQwSsRpBo3bpwMcr3zzjv8jImIiMhqsW9EREphIIqIHKazVVBQgPvvvx8NGjSQy0R2lCAypHJzcxEeHq5b/+uvv4Zarcbnn38us6QEEagS2VEi6DRo0CC5TASkli1bBi8vL7Rs2RJvvfWWzLKaM2cOnJyYdEpERETWiX0jIlIKfyURkUNo27YtBgwYIINPDz30EJYuXYrk5ORy1z98+DDOnTsHX19f+Pj4yIvIlMrJycH58+cNtiuCUFoigyojI0MO6yMiIiKyVuwbEZFSmBFFRA7B2dkZGzZswM6dO7F+/Xp8/PHHePPNN7Fnzx6j64tgUseOHfHNN9+UeUzUgyIiIiKyZewbEZFSGIgiIochhtj17NlTXmbMmCGH6P3yyy9yeF1hYaHBuh06dMCqVasQGhoqi5BXlDmVnZ0th/cJu3fvltlTERERZn8/RERERDXBvhERKYFD84jIIYjMp3fffRf79u2Txcl//vlnJCYmonnz5oiMjJQFyE+fPo2kpCRZqPzRRx9FcHCwnClPFCu/ePGirA31r3/9C1evXtVtV8yQ9+STT+LEiRNYu3YtZs6ciYkTJ7I+FBEREVk19o2ISCnMiCIihyCymrZt24aFCxfKGfJENtSHH36IoUOHolOnTjLIJK7FkLwtW7agb9++cv3XXntNFjgXs+zVrVtX1pnSz5AS9xs3bow77rhDFjwXM/PNmjVL0fdKREREdDvsGxGRUlQajUaj2KsTEdmwJ554AikpKVi9erXSu0JERESkOPaNiKgyODSPiIiIiIiIiIgsgoEoIiIiIiIiIiKyCA7NIyIiIiIiIiIii2BGFBERERERERERWQQDUUREREREREREZBEMRBERERERERERkUUwEEVERERERERERBbBQBQREREREREREVkEA1FERERERERERGQRDEQREREREREREZFFMBBFRERERERERESwhP8H+aeRhXtZpLoAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axes = plt.subplots(2, 2, figsize=(12, 8), sharex=True)\n", + "axes = axes.flatten()\n", + "\n", + "for idx, (base, entries) in enumerate(metrics_data):\n", + " if idx >= 4:\n", + " break\n", + " ax = axes[idx]\n", + " for label, col, x, y in entries:\n", + " style = '--' if label == 'val' else '-'\n", + " ax.plot(x, y, label=label, linestyle=style, linewidth=1.6)\n", + " ax.set_title(base)\n", + " ax.legend(loc='best', fontsize=8)\n", + " ax.grid(True, alpha=0.3)\n", + "\n", + "for ax in axes[-2:]:\n", + " ax.set_xlabel('step')\n", + "axes[0].set_ylabel('loss')\n", + "axes[2].set_ylabel('loss')\n", + "fig.suptitle('Loss Curves')\n", + "fig.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Features:**\n", + "- 4 loss components: `loss_align`, `loss_bd`, `loss_sg`, `loss_tx`\n", + "- Solid = train, Dashed = validation\n", + "- Auto-smoothed (adaptive window)\n", + "- Tab10 color palette" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Terminal Plot (Quick Mode)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-11T09:05:46.520583Z", + "iopub.status.busy": "2026-02-11T09:05:46.520440Z", + "iopub.status.idle": "2026-02-11T09:05:46.567442Z", + "shell.execute_reply": "2026-02-11T09:05:46.566882Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " loss_align\n", + "┌────────────────────────────────────────────────────────────┐\n", + "│\u001b[35m▌\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▙\u001b[0m\u001b[34m▄\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▀\u001b[0m\u001b[34m▌\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▜\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▐\u001b[0m │ 0.5\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▐\u001b[0m\u001b[34m▖\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▝\u001b[0m\u001b[34m█\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m█\u001b[0m\u001b[34m▖\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▐\u001b[0m\u001b[34m▌\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m█\u001b[0m\u001b[34m▖\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▐\u001b[0m\u001b[34m▌\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m█\u001b[0m │ 0.2\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▜\u001b[0m\u001b[34m▌\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▜\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▐\u001b[0m\u001b[34m▙\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▜\u001b[0m\u001b[34m▙\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▝\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▙\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▖\u001b[0m │\n", + "│\u001b[35m▙\u001b[0m \u001b[34m▝\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▜\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▙\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m│\n", + "└────────────────────────────────────────────────────────────┘\n", + " 0 10,000 20,000\n", + " \u001b[34m██\u001b[0m train \u001b[35m██\u001b[0m val\n", + "\n", + " loss_bd\n", + "┌────────────────────────────────────────────────────────────┐\n", + "│\u001b[34m▌\u001b[0m │\n", + "│\u001b[34m▌\u001b[0m │\n", + "│\u001b[34m▌\u001b[0m │ 1.2\n", + "│\u001b[34m▌\u001b[0m │\n", + "│\u001b[34m▌\u001b[0m │\n", + "│\u001b[34m▌\u001b[0m │\n", + "│\u001b[34m▌\u001b[0m │\n", + "│\u001b[34m▌\u001b[0m │ 0.8\n", + "│\u001b[34m▌\u001b[0m │\n", + "│\u001b[34m▌\u001b[0m │\n", + "│\u001b[34m▌\u001b[0m │\n", + "│\u001b[34m▌\u001b[0m │\n", + "│\u001b[34m▌\u001b[0m │ 0.4\n", + "│\u001b[34m▙\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m\u001b[34m▄\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▜\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▖\u001b[0m │\n", + "│\u001b[35m▀\u001b[0m \u001b[34m▝\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▛\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▛\u001b[0m\u001b[34m▜\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▙\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▙\u001b[0m\u001b[34m▟\u001b[0m\u001b[34m▟\u001b[0m\u001b[34m▟\u001b[0m\u001b[34m▙\u001b[0m\u001b[34m▟\u001b[0m\u001b[34m▟\u001b[0m\u001b[34m█\u001b[0m│\n", + "└────────────────────────────────────────────────────────────┘\n", + " 0 10,000 20,000\n", + " \u001b[34m██\u001b[0m train \u001b[35m██\u001b[0m val\n", + "\n", + " loss_sg\n", + "┌────────────────────────────────────────────────────────────┐\n", + "│\u001b[35m▖\u001b[0m\u001b[34m▌\u001b[0m │ 0.4\n", + "│\u001b[35m▌\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▐\u001b[0m\u001b[34m▙\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▜\u001b[0m\u001b[34m▖\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▐\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▖\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m█\u001b[0m\u001b[34m▙\u001b[0m │ 0.3\n", + "│\u001b[35m▌\u001b[0m \u001b[34m█\u001b[0m\u001b[34m▌\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▐\u001b[0m\u001b[34m█\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▐\u001b[0m\u001b[34m▄\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▝\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▖\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▜\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▖\u001b[0m\u001b[34m▖\u001b[0m │ 0.2\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▝\u001b[0m\u001b[34m▜\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▟\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▗\u001b[0m\u001b[34m▗\u001b[0m\u001b[34m▌\u001b[0m\u001b[34m▖\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▛\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▟\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▖\u001b[0m \u001b[34m▖\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▘\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▛\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▜\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▟\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▙\u001b[0m\u001b[34m▖\u001b[0m\u001b[34m▖\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▀\u001b[0m\u001b[34m▘\u001b[0m\u001b[34m▝\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▜\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▙\u001b[0m\u001b[34m▟\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▖\u001b[0m\u001b[34m▖\u001b[0m \u001b[34m▗\u001b[0m │\n", + "│\u001b[35m▜\u001b[0m \u001b[34m▘\u001b[0m\u001b[34m▝\u001b[0m\u001b[34m▝\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▜\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▙\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▙\u001b[0m\u001b[34m▙\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m\u001b[34m▄\u001b[0m \u001b[34m▗\u001b[0m\u001b[34m▄\u001b[0m│ 0.1\n", + "│\u001b[35m▝\u001b[0m \u001b[34m▝\u001b[0m \u001b[34m▝\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▀\u001b[0m\u001b[34m▜\u001b[0m\u001b[34m▜\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m│\n", + "└────────────────────────────────────────────────────────────┘\n", + " 0 10,000 20,000\n", + " \u001b[34m██\u001b[0m train \u001b[35m██\u001b[0m val\n", + "\n", + " loss_tx\n", + "┌────────────────────────────────────────────────────────────┐\n", + "│\u001b[34m▌\u001b[0m │\n", + "│\u001b[34m▌\u001b[0m │\n", + "│\u001b[34m▌\u001b[0m │ 0.25\n", + "│\u001b[34m█\u001b[0m\u001b[34m▄\u001b[0m │\n", + "│\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m │\n", + "│\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▌\u001b[0m │ 0.20\n", + "│\u001b[35m▖\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▙\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▌\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m\u001b[34m▐\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m▙\u001b[0m │ 0.15\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▜\u001b[0m\u001b[34m█\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m█\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▜\u001b[0m │ 0.10\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▐\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▐\u001b[0m │\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▐\u001b[0m │ 0.05\n", + "│\u001b[35m▌\u001b[0m \u001b[34m▐\u001b[0m\u001b[34m▖\u001b[0m │\n", + "│\u001b[35m▙\u001b[0m \u001b[34m▀\u001b[0m\u001b[34m▜\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m\u001b[34m█\u001b[0m│\n", + "└────────────────────────────────────────────────────────────┘\n", + " 0 10,000 20,000\n", + " \u001b[34m██\u001b[0m train \u001b[35m██\u001b[0m val\n", + "\n" + ] + } + ], + "source": [ + "try:\n", + " from uniplot import plot as uniplot_plot\n", + " \n", + " for base, entries in metrics_data:\n", + " xs = [e[2] for e in entries]\n", + " ys = [e[3] for e in entries]\n", + " labels = [e[0] for e in entries]\n", + " uniplot_plot(xs=xs, ys=ys, legend_labels=labels,\n", + " color=True, lines=True, title=base)\n", + " print()\n", + " \n", + "except ImportError:\n", + " print(\"Install: pip install segger[plot]\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Advanced: Smoothing Comparison" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-11T09:05:46.569531Z", + "iopub.status.busy": "2026-02-11T09:05:46.569360Z", + "iopub.status.idle": "2026-02-11T09:05:46.940583Z", + "shell.execute_reply": "2026-02-11T09:05:46.939965Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABc8AAAGMCAYAAAAMbVprAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAsIxJREFUeJzs3Qd8G+X5wPFHtuOVxHb23pPskJAQVhiBhFH2poy0hTILhTILCRTKhoYChRbKKH/KhrRlBEhIgEAGZO+9E8eJHe9t3//zvI5kSZZtydbW75uPPo5Op9Pp1UnP3XPvPa/NsixLAAAAAAAAAACAQ1ztfwEAAAAAAAAAAMlzAAAAAAAAAAA8oOc5AAAAAAAAAABuSJ4DAAAAAAAAAOCG5DkAAAAAAAAAAG5IngMAAAAAAAAA4IbkOQAAAAAAAAAAbkieAwAAAAAAAADghuQ5AAAAAAAAAABuSJ4DAAAg4tlsNrn55psbne+NN94w827fvl0iTSDWPRLb46effpJjjjlGWrZsadZ9+fLlZvqsWbNk1KhRkpycbKbn5uaGelUBAAAQ4UieAwAAxJhVq1bJhRdeKL169TKJxm7dusmpp54qzz//vISzH3/8UR588MGITIo++eSTJqG7bNkyl+mWZUmbNm3MY9u2bXN5rLS0VJKSkuTyyy+XaHfiiSeaNvB0Gzx4sGO+iooKueiiiyQnJ0f+8pe/yFtvvWW24+zsbLn44oslJSVFXnzxRTNdk+v+tHbtWrP9RdKJBgAAADRPQjOfDwAAgAiiCeiTTjpJevbsKddee6107txZdu3aJQsXLpTnnntObrnlFgnndX/ooYfkmmuukYyMjCYt48orr5RLL73UJKWD6bjjjjN/58+fL6NHj3ZMX7NmjTkZkJCQID/88IP06dPHpYd1eXm547mhWvdg6d69uzz22GN1pqenpzv+v2XLFtmxY4e88sor8pvf/MYxXXudFxQUyMMPPyyTJk0KyPpp8ly3P0309+7dOyCvAQAAgPBC8hwAACCG/PnPfzbJSE3Muiegs7KyJNrFx8ebW7CNHTvW9PLX5LnzCQpNmLdr1848ro/98pe/dDym95U9eR6qdQ8W3S6d378n9m20vm23qSdVAAAAAE8o2wIAABBDtOfu0KFDPSYZO3bs6LGO+AcffCBDhgwxJTEmTJhgyr6ov//979K/f3+TFNbeuJ7KWehzx4wZY57bvn17kxzds2dPnfm++eYbOf74402pDV23c845R9atW+d4XMtl3Hnnneb/2jvbXtLD/TVnzpwpw4YNM72z9X1qj+TGanxrL+KzzjrLJKvHjRtn3k/fvn3lX//6V531XLlypUycONG8H+0p/cgjj8jrr7/eaN3wxMREOeqoo0yy3Jne1zY99thjPT6mbaHvxx/rrr3cTz75ZJd1r66u9ri+f/vb30z7aTt27dpVbrrpJpdyOX/9619NIt952jPPPGPW7/bbb3dMq6qqktatW8vdd98tzaVXHGjbKy3doq+l253err76ajNd21in67x2ixYtkilTppjkfGpqqlmGe1sr3S5//etfm/er71u3sxtuuMH0/te219dUeuWGffubN29es98XAAAAwhc9zwEAAGKI1odesGCBrF692pGUbcj3338v//3vf03yVGlZDU3W3nXXXSbBeuONN8qhQ4dMTe9f/epXJglupwnHqVOnmoSmPm///v2mNIwmLrX2tz2BP3v2bDn99NNN0leT5CUlJab+uiaUly5dahLE559/vmzcuFHeeecdU+taE/GqQ4cOjtfTBPLHH39s1kkTtprgveCCC2Tnzp2md3dDNm/ebOrAa/JUE7GvvfaaScBq4l+TyPbkqj1xeu+995pE/6uvvup1GRXtQa7tqclve9kPbQstP6KJ7+nTp5tktLaL1kLXMjWaWI+Li2v2umdmZpp1r6yslHvuuces+z/+8Q+TSHenn4GWJ9HyJ5o83rBhg7z00kvmagVd3xYtWpgTHZp41zbX7cG+rei66l87/ZwLCwvlhBNOaLR9NNF+8ODBOtN1HXV9f/vb35r6/I8++qj87ne/M9tVp06dzDyDBg0y7+dPf/qTSXr369fPTNftUbctbQttX10/PdmhJxF0PbXd1d69e83/tf2vu+46U2ddP+8PP/xQiouLzfrra+o2dd9998kRRxxhnmf/CwAAgChlAQAAIGZ89dVXVnx8vLlNmDDBuuuuu6wvv/zSKi8vrzOv7iomJSVZ27Ztc0z7+9//bqZ37tzZys/Pd0y/9957zXT7vLq8jh07WsOGDbNKSkoc83366admvmnTpjmmjRo1ysybnZ3tmLZixQorLi7OuuqqqxzTnnrqKZfXcF/XxMREa/PmzS7L0OnPP/+8Y9rrr79eZxm9evUy07777jvHtKysLPPe77jjDse0W265xbLZbNayZcsc03Sd27ZtW+96Ofvss8/MfG+99Za5v2/fPnP/22+/tQoKCsxnovOo1atXm8f+/Oc/+2Xdb7vtNjPfokWLXOZLT093WaZO03Y87bTTrKqqKse8L7zwgpnvtddeM/f1sbS0NLP9qOrqaqtdu3bWRRddZN6Hvh/17LPPms/x0KFDDbbNxIkTzfI93X7729865ps7d66Z9sEHH7g83942P/30k2OartOAAQOsyZMnm//bFRcXW3369LFOPfVUxzTdznQ9nZ/vvBylr6mvoesAAACA2EDZFgAAgBhy6qmnmp7nZ599tqxYscL0GJ88ebLp0as9zN2dcsopLoMjjh8/3vzVHt3au9t9+tatW83fn3/+2dSh1l7gWkrE7swzzzS9ej/77DNzf9++fbJ8+XLTU7pt27aO+UaMGGHW9fPPP/f6vWlPaXuPY/sy0tLSHOvUEC1Lo72p7bRHu/Zmdn6uloDRnuCjRo1yTNN1vuKKK7xav2OOOcb0fLbXMrf34tYe1K1atTLray8nYv9rr3fe3HXXdjz66KMdPa3t87mvu14FoGVKbrvtNpce7zq4rLal/XPTx/T9fPfdd+a+ltjJzs42vdr1XIZuY0p7d+sVDt7UItft7Ouvv65z03VpCt2uNm3aJJdffrlZN+3VrreioiKzXeu6a+95vWm5n1/84hem9rw7vdIAAAAAsYmyLQAAADFGk7Va3kSTpJpA/+STT0wpFC39oQlHTcba9ezZ0+W5Wjda9ejRw+N0LeGiduzYYf5qEtedJs/tCeSG5tOSGF9++aVJdmrZjsa4r6tq06aNY52a+1xdV02eu9O6797QBLKWUXFOkI8ePdpROkWT0c6PaZ1052R3c9fdfoLDmXu71/d56LpoWR3740oT9vYyO5ok79Klixx55JEycuRIc19PfujnfPHFF4s39DPWEyD+oolzZa+H7kleXp75HuTn53tVxggAAACxheQ5AABAjLIPYqm3gQMHmvrkOsCn1oa200EhPalvek0FldBozjoF6/1oT/KXX37Z1NbWBLkmzO30/1qvvKKiwiSdtU63c6/9UK+7p/ei66q9zDVZbu/9rn/1/vr16+XAgQMuveKDyT4Y6lNPPeVytYAz7fGfk5MT5DUDAABApKBsCwAAABzlKrSMir8GJlU62KQ7nWZ/vKH5NPmqA4Pae52HunyGrqsOzunO07SGEs6a1NbyKDqYpg6K6pw8117cWhpFS654U7LFl3W398R25t7u9X0e2jt727ZtjseV9orXEzCaKHdOnuvgmosWLZI5c+Y47oeCvYSPlpvRHu2eblo2R8vX6Dw6iG5DQr39AQAAIPhIngMAAMSQuXPneuyRbK8t7ql8SlOT8R07djS9rMvKyhzTv/jiC1MfW2ufKy31ob2C33zzTdMb204TmV999ZWcccYZjmn2JLrzfMGkteG1l7WWtrHTXstvv/2218uwJ8SfffZZ02vbuee51vzW9tA69M7z+oO248KFC2Xx4sWOador3H3dNaGsCfG//vWvLtvJP//5T1PixP65Ke0Vr1ctvPPOO7Jz506Xnud6EkCXoQlsfU+hoD339fWffvppKSwsrPO4vn97/fZzzz1X/ve//5la/e7s7RDq7Q8AAADBR9kWAACAGHLLLbdIcXGxnHfeeab2uPYo/vHHH+W9994zyVst3eIP2qP3iSeeMMubOHGiXHbZZbJ//3557rnnzOv8/ve/d8yrZTVOP/10U0/817/+tUm8Pv/886aOutbUdk6Gqj/+8Y9y6aWXmtfQQR69qYfuD3fddZf83//9n6nlre2or/vqq6+amuOaRPemZ7LOq/XiNQmv7dC1a1eXxzWZ/tFHH5llOfdK98e6v/XWWzJlyhS59dZbzbr/4x//MD3JV65c6ZhPe2Hfe++98tBDD5l5dWBZ7YX+t7/9zSTKf/nLX7osVxPljz/+uPmshg8fbqbpSRM9CaPP04FgvaXJeW1fT9xf1xuaFNfPR7ctrTWv26IOjLtnzx5zEkl7m2vCXD366KPmZI1uq9ddd52pt69XYWgZIy2ho/Xq9SSPlsjR7VrXNSkpSU4++WTzfgEAABCdSJ4DAADEEO2FqwlB7WmuyVNNnmtC98Ybb5T777/fJAn9RROnqampJrl69913m4StJu01+ej8OtrbedasWabW+rRp00xSXJOYOl+fPn0c82ny9uGHHza92XV+rWmtpUSClTzXpLcmXX/3u9+ZZKsmmm+66Sbz+jrNm/rk9h7l2lvbude5nSbMNXmuJzbatWvnt3XX3t+67pr0189Dl3399deb5L2esHCmJyz0vb3wwgvmJEfbtm1NQlnfs342npLn+l40We08XZPnvtQ73717t1x55ZV+S56rE0880Zyo0O1G34/2QO/cubMZPPW3v/2tYz5NqmupmQceeMD0xtcBRHWaJt51G1b6PN32HnvsMdNmVVVVpk1JngMAAEQvmxXKUZ0AAACACHfbbbfJ3//+d5OYrW/wTgAAAACRh5rnAAAAgJe0pIyz7OxsUw5Fe5OTOAcAAACiC2VbAAAAAC9pXXYtBaI1sbWGuw6kqSU+tNwHAAAAgOhC8hwAAADw0hlnnCEffvihqRevg3oeeeSRJoF+wgkn0IYAAABAlKHmOQAAAAAAAAAAbqh5DgAAAAAAAACAG5LnAAAAAAAAAAC4IXkOAAAAAAAAAIAbkucAAAAAAAAAALgheQ4AAAAAAAAAgBuS5wAAAAAAAAAAuCF5DgAAAAAAAACAG5LnAAAAAAAAAAC4IXkOAAAAAAAAAIAbkucAAAAAAAAAALgheQ4AAAAAAAAAgBuS5wAAAAAAAAAAuCF5DgAAAAAAAACAG5LnAAAAAAAAAAC4IXkOAAAAAAAAAIAbkucAAAAAAAAAALgheQ4AAAAAAAAAgBuS5wAAAAAAAAAAuCF5DgAAAAAAAACAG5LnAAAAAAAAAAC4IXkOAAAAAAAAAIAbkudAhJs3b57YbDbzN5yXCQBALCJOAwAQWYjdAJyRPAdC6P333zdJ6k8++aTOYyNHjjSPzZ07t85jPXv2lGOOOSZIaxkd3njjDdOenm6ZmZmhXj0AQBgiTgfPvn375J577pGTTjpJWrdu3eBJ/BNPPNFjPJ8yZUoQ1xgAEI6I3cEzZ84c+dWvfiUDBw6U1NRU6du3r/zmN78xMd0dsRuRLCHUKwDEsuOOO878nT9/vpx33nmO6fn5+bJ69WpJSEiQH374wRxI2u3atcvcLr30UnP/hBNOkJKSEklMTAzBO4g8f/rTn6RPnz4u0zIyMkK2PgCA8EWcDp4NGzbIE088IQMGDJDhw4fLggULGpy/e/fu8thjj7lM69q1a4DXEgAQ7ojdwXP33XdLTk6OXHTRRSZ+b926VV544QX59NNPZfny5dK5c2eX+YndiFQkz4EQ0oM8TeRq8tyZHjBalmWCkPtj9vv2nYK4uDhJTk4O4lpHttNPP13Gjh0b6tUAAEQA4nTwjBkzRrKzs6Vt27by4Ycfmn2ghqSnp8svf/nLoK0fACAyELuD59lnnzV5Cc1J2OlVYBMnTjRJ9EceecRlfmI3IhVlW4AQ02CzbNky03vcTnubDx061CR6Fy5cKNXV1S6P6aXJxx57bL312PSSqGHDhsnatWtNr3W9hKpbt27y5JNP1nn93bt3y7nnnistW7aUjh07yu9//3spKyvzuK4ffPCBObhNSUmR9u3bm4PWPXv2OB7/73//a9Zl5cqVjmkfffSRmXb++ee7LOuII46QSy65REKhoKBAqqqqQvLaAIDIQpwODi3VoolzX1RWVkphYWHA1gkAEJmI3cGhV8E7J87t0zSer1u3zuNziN2IRCTPgTAI7BUVFbJo0SKXBLnWNNdbXl6eKeHi/NjgwYOlXbt2DS730KFD5qyv1k5/5plnzHP0sqovvvjCMY8m7E855RT58ssv5eabb5Y//vGP8v3338tdd93lsWb4xRdfLPHx8eYy6WuvvVY+/vhjs/65ubmO96KJ8u+++87xPF2eBlTnHvQHDhyQ9evXm8DakOLiYjl48GCjN32v3tKTCWlpaeaEwtlnny2bNm3y+rkAgNhDnA5unPbWxo0bzYl/TbrrZeEPPPCA2Z8CAIDYHbrYrSe19aad7YjdiBoWgJBas2aNpV/Fhx9+2NyvqKiwWrZsab355pvmfqdOnawXX3zR/D8/P9+Kj4+3rr32Wsfz586da56vf+0mTpxopv3rX/9yTCsrK7M6d+5sXXDBBY5pM2bMMPO9//77jmlFRUVW//79XZZZXl5udezY0Ro2bJhVUlLimPfTTz81802bNs0xbejQodbFF1/suH/kkUdaF110kZlv3bp1ZtrHH39s7q9YsaLBtpk+fbqZr7Fbr169Gm3n9957z7rmmmtMu37yySfW/fffb6Wmplrt27e3du7c2ejzAQCxiTgdnDjt7IMPPqizb+PsV7/6lfXggw9aH330kdnXOfvss838zvsfAIDYRewOfuy207yGPn/OnDku04ndiGTUPAdCTMuXaC9ye8/sFStWSFFRkel1rvSv9ja/8cYbTS10LTdir3fekFatWrnUAtUBRceNG2cG8bD7/PPPpUuXLnLhhRc6pmmP7Ouuu86l9/nPP/8sWVlZ8uCDD7rUVz/zzDNNj/bPPvtMHnroITPt+OOPl//85z+O8ij6fnQAsLlz55pe6Dq//tVBOrW0TEOuuuoqr96rlpFpjPaa15udlqqZPHmy6f3+5z//WV5++eVGlwEAiD3E6eDEaV/885//dLl/5ZVXmn2XV155xZSfO/roo/36egCAyELsDk3s1ivQNS+gx90nn3yyy2PEbkQykudAiGmZE02Qa6DR2uaaKNfa4/379zeP62M62IbSx5Q3wU5HstZlO2vTpo1LPfIdO3aY13Gfb9CgQS73dT5P05Umw51LsmjyXBPRmzdvli1btphlT5gwwUzXpLmWe9G/WrPdvT6au759+5pboGg7jh8/XmbPnh2w1wAARDbidOjitC/uuOMOkzzXmE7yHABiG7E7+LFby7Ked955poPcq6++6tVziN2IFNQ8B8KAJnG1tvmqVasc9c7t9P+avNaBOTVJraOHexPstDa5J5alV1EFjj2xrycDNEl+5JFHmpqk9uS51j/TAVL1fmN03szMzEZvWkO9qXr06CE5OTlNfj4AIPoRp0MXp32J54qYDgAgdgc3du/atUtOO+00SU9PN1e363gkxG5EE5LnQBiwJ5w1Oa7Jc+2VbTdmzBhJSkqSefPmmUFFnR9rrl69epne4e4J9Q0bNtSZz9N0+zT746pnz57mpolyvdmT5FoeZfv27fLBBx+Y0jONDRaqnn76aVNWprHbUUcd1eQ20DI2HTp0aPLzAQDRjzgdujjtLXtZOmI6AIDYHbzYnZ2dbRLnZWVl8uWXX5rnErsRbSjbAoSBsWPHmlrib7/9tulh7tzzXBPn2nv7xRdfNLXQvSnZ4q0zzjhDvvrqK/nwww/loosucoy+/Y9//KPO+mkpGS3H8qtf/cqsk/riiy9k3bp1Mm3aNJf5NWH+zTffmDrpt99+u5k2atQocwb68ccfN/XT9KRAY/xZj03PnLsfUOtZ8SVLlsjvfve7Rp8PAIhdxOnwqXmen59v9kPs+yJKOwE88sgj5v86ngkAAMTuwMduzU9oTkFzGDrG2YABA4jdiEokz4EwoIN56pld7amtB4PuiWVNpj/zzDPm//5Mnmv9ca2nrgFUk8h6lvitt94yg4Y6a9GihRn0c+rUqTJx4kS57LLLZP/+/fLcc89J7969zeBc7slzPRGgtebs66tlZPR96NnoE0880bznxvizHpu+9ujRo81OlF5OtnTpUnnttdfMZd733XefX14DABCdiNPBqZtqT4CvWbPG/NV9Evu4Kvfff7/5q/Fb90P0puO2lJSUyCeffGKu3NNBQ7XDAQAAxO7Ax+4rrrhCFi9ebDrYaac6vdm1atVKzj33XGI3ogLJcyBMaJJZk+f2Mi3OtFSLJs+15/bIkSP99pqaJJ8zZ47ccsst8vzzz5v7GgBPP/10mTJlisu811xzjXlce47ffffdpo65DgiiSfWMjAyXee2lWnQw0Xbt2rlM1+S5N/XO/e2SSy6Rzz77zPS01971eqJATx5Mnz5dOnXqFPT1AQBEFuJ04D3wwAMu9/Ukt509ea6l4nQ/QhPmWpNVBx8/4ogjzNVxmjwHAMCO2B1Yy5cvd8Rr55htj9f25DmxG5HOZgV69EAAAAAAAAAAACIMA4YCAAAAAAAAAOCG5DkAAAAAAAAAAG5IngMAAAAAAAAA4IbkOQAAAAAAAAAAbkieAwAAAAAAAADgJsF9AkSqq6tl79690rp1a7HZbDQJAMBvLMuSgoIC6dq1q8TFcQ7bX4jdAIBAIXYHBrEbABAJsZvkuQeaOO/Ro0ezGhYAgIbs2rVLunfvTiP5CbEbABBoxG7/InYDACIhdpM890B7nNsbOC0trdln0w8cOCAdOnSghyFt5VdsW7RVoLBtBbat8vPzzQlae6yBfxC7Q4PfC9qLbSs88F0MbFsRuwOD2B0a/F7QXmxb4YHvYuTEbpLnHthLtWji3B/J89LSUrMcLs+nrfyJbYu2ChS2reC0FWXB/IvYHRr8XtBebFvhge9icNqK2O1fxO7Q4PeC9mLbCg98FyMndlNsFQAAAAAAAAAANyTPAQAAAAAAAABwQ/IcAAAAAAAAAAA31DwHgCCqqqqSioqKsK8npuuoNcUYq8H3tmrRooXEx8cH5bMCAER/XPYGsbt5bUXsBoDIQeyOPdUhjt0kzwEgCCzLkszMTMnNzY2IddXgVFBQwMBYTWyrjIwM6dy5M+0HAGEqkuKyN4jdzW8rYjcAhDdid+yyQhy7SZ4DQBDYD9A7duwoqampYZ1U1cBUWVkpCQkJYb2e4dhWer+4uFiysrLM4126dAn1KgIAIjwue4PY3fS2InYDQGQgdscuK8Sxm+Q5AAThsjL7AXq7du3Cvr05AG9eW6WkpJi/Gsj1M6eECwCEl0iLy94gdjevrYjdABDeiN2xzQpx7A6LAUNffPFF6d27tyQnJ8v48eNl8eLF9c778ccfy9ixY03X/JYtW8qoUaPkrbfeqtOo06ZNM2cetDEnTZokmzZtCsI7AYC67LVUtWcbYoP9s46GOrr1IXYDiFTEZXhC7HbFcTeAcELsRihjd8iT5++9957cfvvtMn36dFm6dKmMHDlSJk+e7Oh6765t27byxz/+URYsWCArV66UqVOnmtuXX37pmOfJJ5+Uv/71r/Lyyy/LokWLTJJdl6mF5QEgVCL9knB4L9o/a2I3gGgQ7b/V8E20bw/EbgDRINp/qxGe20PIk+fPPvusXHvttSYBPmTIEJPw1jMHr732msf5TzzxRDnvvPPkiCOOkH79+smtt94qI0aMkPnz5zt6nc+YMUPuv/9+Oeecc8xj//rXv2Tv3r0yc+bMIL87kbkbsqSwrCrorwsAQKAQuwEAiCzEbgAAIrDmeXl5uSxZskTuvfdex7S4uDhTZkV7ljdGE+XffPONbNiwQZ544gkzbdu2bWYQAV2GXXp6uikHo8u89NJL6yynrKzM3Ozy8/PNXx3JVW/NUVlVLUt358uWApucOqRzs5YV7bSt7SPogvaKpm3L/vr2WySwr2ekrG+4tZX9s/YURyL9N47YjXD6fY00tFd4tFUkxmVvELub11bE7obbi+Pu6EEsor0icdsidsMKYewOafL84MGDpuh/p06dXKbr/fXr19f7vLy8POnWrZtJeGtB+L/97W9y6qmnmsc0cW5fhvsy7Y+5e+yxx+Shhx6qM/3AgQPNLvWSl5snRcVFIpYWsQ95R/+wphu2fra64etJFNBe0bJtaf0tXQcd4EJv4U7bSX+bFZfFNa2t9HPWzzw7O1tatGjh8pyCggKJZMRuhNPva6ShvcKjrSItLnuD2N38tiJ218Vxd3QiFtFekbhtEbtjmxXi2B3S5HlTtW7dWpYvXy6FhYUyZ84cUzO9b9++pqRLU2jPd12Gc8/zHj16SIcOHSQtLa1Z65p+sFrEVtP7XUd/Rf10g9cvgbY7B+CNo70ip630JJz+cOvI0HqLFBp8tKTWm2++ae7runfv3l0uvPBC+dOf/mQGeUZtWznTttJtrV27dnXaKVbbjdgdnUL9+xppaK/waKtIjcuqobisnYrc4xHqR+xuHLE7OhGLaK9I3LaI3Qhl7A7p3mL79u3NTt7+/ftdpuv9zp3rL3GiDdO/f3/z/1GjRsm6detM73FNntufp8vo0qWLyzJ1Xk+SkpLMzdPrNPcLH2ezmR8P/ctBZeNMW/mh3WMF7RUZbaWvqa9vv0XCWV3n9ZwyZYq8/vrr5my/ltq6+uqrzXuyl8uKZc5t5dxm9s/a0zYX6b9vxG64Ixb5hvYKfVtFWlx25yku6/v485//bB6PxPcUTMTuWhx3xy5iEe0VadsWsTu2WSE+7g7pEXxiYqKMGTPG9B53PlOl9ydMmOD1cvQ59prlffr0MQl052VqT/JFixb5tEwAQA09uai/q3pFzrnnnmvGlPj666/NY3p51GWXXWZKaelgz8OHD5d33nnH0XSffvqpZGRkOC6x0quGNLjdc889jnl+85vfyC9/+UuaO0IQuwEg/OLy7NmzzWPEZXhC7AaA0CJ2R7aQX6eo5VK0t8TYsWNl3LhxMmPGDCkqKjKXJKqrrrrKJGW0Z7nSvzpvv379TML8888/l7feekteeukl87gmZW677TZ55JFHZMCAASaZ/sADD0jXrl3NziUAhAsdUDjYEuKbd8509erV8uOPP0qvXr0cl8/pSdC7777blLn67LPP5MorrzS/0fqbfvzxx5tL45ctW2Z+u7/99lvTc3nevHmOZeo0fT4iB7EbQLQKdmwmLiNYiN0AohWxm2PqqE+eX3LJJWZgzmnTppkBPbW0yqxZsxwDfu7cudOlq70m1m+88UbZvXu3pKSkyODBg+X//u//zHLs7rrrLjPfddddJ7m5uXLccceZZcZqnVkA4Rng5204EPTXPXFQB58P1LX3eKtWrcxgHHrSUn+TX3jhBfOYntz8wx/+4Jj3lltukS+//FLef/99kzzX8R70d12T5Zo817+///3vzSDNOm6FDiizefNmmThxot/fKwKH2A0gGoUiNvsrLj///PPmMeIy6kPsBhCNiN0cUweDzdLCMXChZV404aNJneYOGDpnxVbJKSqXjPR0mdC/g7RMjKcOYQPld7KysszAqpFeEzgYaK/IaSvtnb1t2zZzJYzzSbxw7XmuYUEPyHXwDb0KaM+ePebqHj0p+Ze//MVMf/XVV828Wo7l0UcfNclyna+8vNwcyJ933nlmmr2n08aNG+V///ufGTxm/vz5cumll8rjjz8uOTk5cuedd5rnRiLntnKuvVbfZ+7vGIPAtCuxO3J+XyMN7RUebdXQb3S491675pprPMblV155xcQjjUV6pW6sxmVvELvDB7E7NIhFtFckblvEbmJ3ZQiPuznKCaSt8+SkmWNl6KaXzd2FW7Jlf35NbXYA0APmYN+aomXLlmaQ5pEjR8prr71mxpD45z//aR576qmn5LnnnjNlV+bOnWtqmk+ePNkcrNvpYM56YL5ixQozOrZeMaTTtBe6lmyh1znCL3YfRewGYhRxmbiMCETsBmIasZvYHWgkzwPpncslzqqSIdted0yqCEFPUwDwF+1BcN9998n9998vJSUl8sMPP8g555xjBvzU5Hrfvn1NbzZn9rrn2jvOnii3J8/1pv8Hwsa7V0icVUnsBhBRcVnHeNK4rOOSEJcRc4jdACIIsTvykDwPaOvG15m0IbNAth0skqU7DwX0pQEgUC666CKJj4+XF1980QzM/PXXX5uD9XXr1slvf/tb2b9/v8v8bdq0kREjRsjbb7/tSJSfcMIJsnTpUpNop+c5woqN2A0gMuOylnLRK8WIy4g5xG4AEYbYHVlCPmBoVHOqw+NsS1Zh0FcFAPxF64zdfPPN8uSTT8qyZctk69atplRLamqqGaj53HPPNXXFnGmCXEu62JPnbdu2lSFDhphE+6BBg/hwENYnvhWxG0A4x+WbbrpJnnnmGXNiWmt/EpcRU4jdACIMsTuyMGCoB34rKv9EH5GSHPPfry9aLzaba0f/SUM6NX3ZUYiBS2ivaN22GhrEIpIG0oL3bcWAoREcu58aIFKUZf5L7A7/39dIQ3uFR1tFWlz2BrG7+W1F7A4+YndoEItor0jctojdsc0KcezmKCeQ3JLlAAAgzMVxUR4AABGF2A0ACCCyuyG49BsAAIQprrYAACCyELsBAAFE8jyEPc+rq62AvjwAAPAvYjcAAJGF2A0AaA6S54E08S7zJ69lX48Pf7M+SyqqqgO6CgAAwPfYnd+yt8eHid0AAIQZYjcAIIBIngdUTRF7q4Ee6N9uOCCr9+QFdjUAAIBvsfvwX0+I3QAAhBNiNwAgcEieh4HMvNJQrwIAAHCqm2qThkurEbsBAAgTxG4AQACRPA+Srts+ko67Pg/WywEAgCapv8c5AAAIR8RuAEDgkDwPgozCzTL05z/KiAW3SYuyQx7nycqn9zkAAOHSe02sxgf1JnYDABAGiN0AgAAieR6MIO4koTzf46wrd1P3HACA0POubIsidgMAEA6I3QCAwCF5HnSNH4wDQKSaN2+e2Gw2yc3NbdZyrrnmGjn33HP9tl6A7ye+idcAIh9xGTGB2A0gihC7ww/J8yDzpicbAISDl19+WVq3bi2VlZWOaYWFhdKiRQs58cQTPQb4Ll26yL59+yQ9PV2iib4399u7774b6tUCAMSQhuLySSedFFNx+Xe/+52MGTNGkpKSZNSoUXUe3759u8fYvXDhwpCsLwAgNhG7a6xYsUIuu+wy6dGjh6SkpMgRRxwhzz33nHjad3G/ZWZmSqglhHoFYk3nHf+T8qS2snvALz0+XlhWKa2S+FgAhJ4eiOtB+c8//yxHH320mfb9999L586dZdGiRVJaWirJyclm+ty5c6Vnz54yaNAgiVavv/66TJkyxXE/IyMjpOuDQPG95zmxG0C4xOVWrVrFTFz+1a9+Zd73ypUr651n9uzZMnToUMf9du3aBWntEFzEbgDhidhdY8mSJdKxY0f5v//7P5NA//HHH+W6666T+Ph4ufnmm8XZhg0bJC0tzXFfnxdq9DwPsr5rX5DBy/4kaTl1d/LKKqtk4ZZs8xdAFKuqFMnbE5qbvraX9IBbe6zpGWA7/f8555wjffr0cem9pdN1x8D9ErM33njDJJm//PJLc3ZZD+o1Aa294BzNUVUlt99+u5lPD2rvuususdwGaywrKzO9zDRwasL+uOOOk59++snx+NixY+Xpp5923NeSL9oTT5MMavfu3Wa9Nm/eLE2l66cJCvvNfuIA0Xnpt83L3DmxG4gSoYrNfozLmkiOlbj817/+VW666Sbp27dvg/Pp+jvHbl0HRCFiNxCbiN0RE7t/9atfmZ7mEydONLH7l7/8pUydOlU+/vjjOvPq+jnH7ri40Keu6eIcIm0zfxBL4qSg7TDHNPt2vXxnrozvS68IIGoV7hf5y5DQvPbv14qkd/N6dj3w1t5r99xzj7mv/9dArMFZ/6/lW0pKSswBuwZET4qLi00Qfuutt0zg00D5hz/8Qd5++23z+DPPPGMO5l977TVzIK/3P/nkEzn55JMdy9DX/Oijj+TNN9+UXr16yZNPPimTJ082gbtt27YmCGuCQJerOwnaE093HObPn2+SAt9++61069ZN+vfvb5Z3/fXXm7PeDbHvJNjpQfpvfvMbE+z1+RrsEY18671G7AaiRKhis5/ispZy0Th4yimnxExc9sbZZ59teuQPHDjQrLPeRzQidgMxidgd0bE7Ly/PvK47Lcemif5hw4bJgw8+KMcee6yEWujT9zERxOvqv/ovMn72+ZJasK3OYwWl3vdAAYBA0oP0H374wRyUFxQUyLJly0xQPeGEExw93xYsWGCCm3u9VbuKigpT603PZB955JHmsqw5c+Y4Hp8xY4bce++9cv7555tAr/M612YtKiqSl156SZ566ik5/fTTZciQIfLKK6+YWmn//Oc/zTyaxNegrkl9vXw7MTFRrrjiCsc66l9db7s//elPsnz58gZvznT+999/X77++mu54IIL5MYbb5Tnn3/ez62NSB50jNgNINRx+bvvvouZuNwY7VGviYMPPvhAPvvsM9O7TnvQ/fe///WxxRERiN0Awhixuy4t2/Lee++Z0i12enWd7nNogl9vWt5F9yeWLl0qoUbP8xDLOLBEilv3Mf+fv+lgqFcHQDC06lTT0yxUr+0DDVZ6kKyXcx06dMj03OrQoYM54NWe19qbSw+AtTe21lbdunVrnWWkpqZKv379XIJiVlaW42yzXio+fvx4x+MJCQnmgN5+mdmWLVvMgb7zGWe9fGzcuHGybt06c//44493JBE0EOv66bo//vjj5nE9S37nnXe6XArmS+20Bx54wPH/0aNHmzbRpMEtt9zi9TIQWWxulznWh9gNRIlQxWY/xmXtaR4rcbkx7du3N5ev2x111FGyd+9eE7t/8Ytf+O11EF6I3UCMIXZHZOxevXq1KTk3ffp0Oe2001zK0zmP1XLMMceY9f7LX/4i//rXvySUSJ6HmkV9cyDmxCf4dIl2KOklWd27dzeXhetBur2XWNeuXR0DfehjzpeDuXOvL6p10tzrrzWXXk42cuRIkzDQHnennnqq6YV3ySWXyMaNG2XTpk0uPdyae4mZ7pg8/PDDpmefDnKC2LhqDEAUi5DYTFxuOo3degUZohGxG4hJxO6IO6Zeu3atKTGnPc7vv//+RtdJk/t6JVuoUbYlkKobL79i8/GycAAINvuAY3rTM892Gki/+OILWbx4cb2XhjdGLwPXHm/Og5zppeg6Gred9o7Ty731MnU7PWuuve70UnE7DeSayNfL1nU9tX6aXm7+5z//2byG9s7z1+Xh+nibNm0kKSmpSe8bkXDpNwBEVlzW0iSxGpe9ocvQ10UUInYDCHPEbpE1a9aYdrj66qvNvkAkxW56ngdS3u7G57GqPU7ecqBQerdrKfFxHMQDCC0NcDpYph4YO59p1v9rndTy8vImH6SrW2+91VwKNmDAABk8eLA8++yzkpub63i8ZcuWcsMNN5hLxPTAWy9D18FNdMCzX//614759MBc65Dr5eu6HPu0F154QS666CKX1/TlErP//e9/sn//fjn66KPNqOTaa+3RRx81A6kgmvl+cpvYDSCUcVkvt77tttuiPi4rHdxMe7NlZmaaAVLtyXVN3mtiXwdD079aak19/PHHZhC1V199tcntgkhA7AYQnmI9dq9evdpcra4DlGpZNY3fSq/i1teyj7nSp08fGTp0qClDpzH7m2++ka+++kpCjeR5IMU13ry2epLn2w4USUZKC2nXil6NAEJLg7gemGrw7NSptjarBn2tiaZ1yZpzNviOO+4wNdr0DHRcXJyp2XreeeeZ2m12uiNQXV0tV155pXlNrd/25Zdfmt7fzjseOo/zzogG+ueee86lZ56vtOzMiy++KL///e9NuRm9ZF53Rq699tomLxPh33utKVeGEbsBhDIu6xVhsRCX1W9+8xtTe9XOniTftm2b9O7d2/xfy6vt2LHD1H3VttKByS688EK/l45DGCB2AwhzsR67P/zwQzlw4IAp8+Jc6qVXr16yfft28389gaDvY8+ePWZ8lhEjRsjs2bNN24U6dtusUK9BGMrPzzeXLOpGlpaW1vQFzXtcZN5jDc6yYfT9smvAVR4f65KRLEO7psvstftldM+MqE+k6xdUByvSM1f6ZQftFS3blp411YM5PYuqPZfDnYYFvURbDza1Pjl8b6uGPnO/xRgEpl1Xfyzy4VQpTuooP5z9ndhsvv1mELsRzvEokgSyrSItLnuD2N38tiJ2Bx+xOzSIRbRXJG5bxO7YZoU4drPXHkg2LwaRa+DcRU5RueP/RWUMLAoAQPA0rW8BsRsAgFAhdgMA/I/keSB50WOzvrItqqyi/scAAEAgL/1uGmI3AABBRuwGAAQQyfOAtm7jPc8Hrmi4rEtpBT3OAQAIHnvavOlV7YjdAAAEE7EbABA4JM8Dqvm1gssq6X0OAEDQ+KHOP7EbAIAgInYDAKI9ef7iiy+aUdG1uPv48eNl8eLF9c77yiuvmNFfdTRYvU2aNKnO/Ndcc40pIO98mzJlShDeCQA0PIAKYkMsfNbRG7sPJ88ZTx2IerHwWw3vxcL2QOwGEOli4bca4bc9JEiIvffee3L77bfLyy+/bA6+Z8yYIZMnT5YNGzaYEXrdzZs3Ty677DI55phjzAH7E088IaeddpqsWbNGunXr5phPD7hff/11x/2kpCQJV0nFmVKW2jnUqwEgQBITE81o43v37pUOHTqY+84jREfKSNZovK30fnl5uRw4cMB85vpZR6Oojt2Ht/mU8mxJLtotZa16Bn8dAARUpMVlbxC7m95WxO7oid22ZpRcAxDeiN2xzQpx7A558vzZZ5+Va6+9VqZOnWru64H4Z599Jq+99prcc889deZ/++23Xe6/+uqr8tFHH8mcOXPkqquucgnanTtHRkJ6wqwpsnnEnZLd+XgpcTtIP1RUHrL1AuAf+mPep08f2bdvnzlQD3caiPQMrq53pCcTQtVWqamp0rNnTzM9GsVK7B76032y9KT/8/l5xG4gvEVaXPYGsbv5bUXsjobY3fTkObEbCG/E7thmhTh2hzR5rmcJlixZIvfee69jmr5hvZx7wYIFXi2juLhYKioqpG3btnXOlOsZdL08/OSTT5ZHHnlE2rVr53EZZWVl5maXn59v/uoH06xLACzLq7o4CZXFMnjpQ+b/X1+03uWxTfsPr4vVzHWJAPr+7F8I0F7Rtm3pGdLu3bubs6VVVeE9ELC2U05OjvldjdbkbyDbKj4+3nFG3NM2F+m/cdEfu2tr2iWVZIll+b4sYjfCOR5FikC3VSTFZW8Qu5vXVsTu6IjdyeWHRCpLxUpI9nkRxG7Uh9jtPWK3b4jdkRO7Q5o8P3jwoNlZ7dSpk8t0vb9+vWsSuT533323dO3a1Ry0O186dv7555seJVu2bJH77rtPTj/9dHNQr43r7rHHHpOHHqpJXjvT7v+lpaXSVC0LC6S1j8/JzcvzOH23VSrJlSkSzXTDzsvLMwdKJOxoL7at0H4Xi4qKTCDiu+j/tiooKJBIFu2xOykvT9oc/n9VdXW9cdkbxG64Y1/He7SVb4jdgW0rYnfkxO7uy56V1QNvavKyiN1wRzzyHm3lG2J35MTukJdtaY7HH39c3n33XXO2W+uw2V166aWO/w8fPlxGjBgh/fr1M/OdcsopdZajvee0dqvzGfAePXqYGohpaWlNX8FWrXx+SkZ6usfpJXqmPqGV9GibKtH8ZdAzRtruJOxoL7YtvovR+rvlHK9iUdjH7kMZjv/GxcfXjcs6kKiX5YyI3XDHvo73aCvf0F6BbStid+TE7t5ZX8vuo+5r8qKI3XDH76v3aCvf0F6RE7tDmjxv3769OSO9f/9+l+l6v7G6aU8//bQ5AJ89e7YJ0g3p27evea3Nmzd7DOJap83TwCb6gTQriWvz/bm2Bp6TW1IpvaK8hIJ+GZrd7jGE9qKt2LYi73sY6b9vUR+742p7ytnc4nL/FU9Ip12z5OeT3/F6oG9iN9wRu71HW/mG9gpcWxG7Iyd2a/Ru6JjaG8RuuOP31Xu0lW9or8iI3SE9gtfRUMeMGWMGHXE+m6D3J0yYUO/znnzySXn44Ydl1qxZMnbs2EZfZ/fu3ZKdnS1dunTx27oDABCLoj9219+rvPeGf0pK8R4ZsPLJoK4RAADNEcuxGwCA5gp59ze9bOuVV16RN998U9atWyc33HCDqWMzdepU87iO5O08KNkTTzwhDzzwgLz22mvSu3dvyczMNLfCwkLzuP698847ZeHChbJ9+3azQ3DOOedI//79ZfLkyREz2jcAAOEqumN34+Iq9aJuAAAiR1TH7tydwX09AEBMCXnN80suucQMEDJt2jQTjEeNGmXObNsHItu5c6dLV/uXXnpJysvL5cILL3RZzvTp0+XBBx80l5KvXLnS7BTk5uaaQU1OO+00c8bc0yVikai4vFLibDZJblF3EBYAAAItqmO3Uz3z1ILtflsssRsAEEpRHbt/fi0giyV2AwDCInmubr75ZnPzRAcbcaZntRuSkpIiX375pUQj63AA/3Fztuh+zcmDa3Z0AAAItqiN3SW5jv/axJJWueukMOOIJi+O2A0ACBdRG7v9jNgNAAi75Hn0sjXpUvDqhBSPjx0sKDM3VV3d7JUDAADu1nzscrfL9pmyadQRTY7uxG4AAAKsdWeRA+v8Vv+c2A0ACKua59HN95rnJ388Unps+ldA1gYAADRizDVuEw4fhFuMYwIAQFg6+oZQrwEAIIqRPA9Dg5Y9EupVAAAgNiUku9y1bDYZuugPcuxnJ4VslQAAgPexGwAAf6JsCwAAgIcBQ+267Pgv7QMAQATE7rjq8pCuCgAg+tDzPIL9tD0n1KsAAEBU67nxDQ9Tm17ChdgNAEDgJJUe8Psyid0AENtInkewvOKKUK8CAABRxrXneZxVVXeWZtQ/J3YDABDY2J1ctNuvSyd2A0BsI3keppILd4V6FQAAgAcd9s2VLts/ZhBRAADCsORaz41vhmxVAADRh+R5mDru81NEqj30dgMAAEGtee7J0MX3yKQPBkn/FU/waQAAEEZ0sG8AAPyF5HkYO/K7qY3Oc6CgLCjrAgAA6uq94Z8+NwuxGwAAf3JNlvfa+IakH1xaZ642+xfIhC8mS7u9c31+BWI3AMQukueB1IyaqKpt1sJG56msrm7WawAAAGeB761G7AYAILCO+ubSOtPGfHu1tCzYJqPn/9bn5RG7ASB2kTwHAAAAAACRiTItAIAAInkOAAAAAAAik420BgAgcIgygVReFNDFAwAAP6P3GgAAkcUW73Hy2DkXS3LhrqCvDgAgupA8D6QFL0gwyqov3XlI8ksrAv5aAACgrqGL/iDtfRh8jNgNAEDge55nZC+XoT/d65eXIHYDQOwieR5IlaXNXkSrQ2ulRWlOg/PkFJZLZl7zXwsAAPg+YGiXHf+VUT4OPkbsBgDAT+LqT2u0ObBYbNX+6WhG7AaA2ETyPMwd/fW5MvG/R4d6NQAAAAAAiLia58MX/F6SijODtjoAgOiSEOoVAAAACBvUPAcAIKqS5x33fGVuAAA0BT3PI5wV6hUAAAA+IXYDABD4AUP9idgNALGL5HmE6Lfy6VCvAgAAMcD3mucAACB8e54DANAcRJkI0Wf9PyS+oijUqwEAAAAAQPiIC3zPcwBA7CJ5HkFsVlWoVwEAgOhGzXMAAKK+5zkDiAIAvEXyPKLUrbS2OaswJGsCAEBUsgJf1ZTYDQBAaJPnlo8ny4ndABC7SJ5HkJTCndJ39XOSWJLlmFZRWR3SdQIAILoEPnlO7AYAINTJ8wSf5id2A0Ds8i1iIKTGz77A/G2/71tZfOrHfBoAAISRtpk/SEmrHlLSqmeoVwUAgNjRhOS5LQgnywEA0YHkeQRKO7Q61KsAAADcHPndVPN3y9BbpCh9oGR1O40a6gAAhOOAoYwnBgDwEslzAAAAB99qoHrSb83z5m9u+yPl55PeIYEOAEC49TwPwhgnAIDoQM1zAACAAMg4uFRalB2ibQEACCRbU3qeM3YYAMA7JM8BAADCtyM7AABoMNb6ntZoUZ5LmwIAvELyPJBOuj+giwcAAH5WkuPnBZI9BwAgoOJ8T2sc/fW5AVkVAED0IXkeSBk9ArZoW1W5y/28kgopKqsM2OsBABATSvP9ujirgeQ5sRsAgND0PG8qYjcAxJ6wSJ6/+OKL0rt3b0lOTpbx48fL4sWL6533lVdekeOPP17atGljbpMmTaozv2VZMm3aNOnSpYukpKSYeTZt2iRBF8BBSAYt/7NIdZW0KK3pIZdXXCGLt/m7txwAADEWuyV4A4gRuwEAwRS9sbtpV3m1PrRWkot2H/7/Gkkp2NHoc4jdABB7Qp48f++99+T222+X6dOny9KlS2XkyJEyefJkycrK8jj/vHnz5LLLLpO5c+fKggULpEePHnLaaafJnj17HPM8+eST8te//lVefvllWbRokbRs2dIss7S0VKJF9y3vyJhvr5aJ/z1a0rJXmGlWEA/4AQCxi9jtPZs0PCAZsRsAEAzE7rrGf32uHPfZyZJasE3Gf32eHPvFqSah3hhiNwDElpAnz5999lm59tprZerUqTJkyBCT8E5NTZXXXnvN4/xvv/223HjjjTJq1CgZPHiwvPrqq1JdXS1z5sxxnP2eMWOG3H///XLOOefIiBEj5F//+pfs3btXZs6cKdGkzYGaM/991zwf6lUBAMQQYnd4XIUGAIC3ojp2N7NsS0bWYpeEunuJVABAbEsI5YuXl5fLkiVL5N5773VMi4uLM5d7aa9ybxQXF0tFRYW0bdvW3N+2bZtkZmaaZdilp6eby9J0mZdeemmdZZSVlZmbXX5+Tb1T3TnQW9NZQTo7YYll6bramrm+oaXrrjthkfwegon2oq3YtiLzexjpv3FRH7stP8duq9LE6PoQu2MLsZu2YtsKPWJ3FMbuFqnNit2WzbXsS3xFgVTEtal3fmJ3bCF201ZsW6EX6tgd0uT5wYMHpaqqSjp16uQyXe+vX7/eq2Xcfffd0rVrV0fQ1gBuX4b7Mu2PuXvsscfkoYceqjP9wIEDzSr1kpyXLxkSeJUV5ZKblydxNpvUU+0mIuiGnZeXZ74QujMH2otti+9iNP5uFRQUSCSL+tid79/YrYmB0rLEeh8ndscW9nVoK7at0CN2R1/sVsmt+ktG4eYmPbe4uMTlfl5+gZQn1r9fR+yOLcRu2optK/RCHbtDmjxvrscff1zeffddUwddBz1pKu09p3XXnQ90tZZ6hw4dJC0trekruK8Zz/VBi4R4yUhPF5vNJh07dpRI/jLoe9B2J3lOe7Ft8V2M1t+t5sSraBBrsbtzXK602fOl7Ol7kZQnd6jzOLE7trCvQ1uxbYUesTsKY7eIFMXHN/m5Wr7GWVfJktz0nvXOT+yOLcRu2optK/RCHbtDmjxv3769xMfHy/79+12m6/3OnTs3+Nynn37aBPHZs2eb+mp29ufpMnTUb+dlar02T5KSkszNnX4gzUriul3+FUi2w3XeIj3prF+GZrd7DKG9aCu2rcj7Hkb671v0x27/fj5Hzb3C/G23/wdZcvI7UblNEItoL7at8MB3MXBtFem/01Efu5vLLfan5a6V9JxVsq/PeVKRVFOmJtq2CX4vaC+2rfDAdzEyYndIf/ETExNlzJgxjkFHlH0QkgkTJtT7vCeffFIefvhhmTVrlowdO9blsT59+phA7rxMPaO9aNGiBpcZEMFKnjMYGQAgSKI+dgdIm4NLQr0KAIAYFQuxu2X+1iY/1+Z2PD1o+aMycOUTMuLH3/lhzQAAkS7kZVv0sq2rr77aBONx48aZEbuLiorMKODqqquukm7dupn6aOqJJ56QadOmyb///W/p3bu3o55aq1atzE3PRNx2223yyCOPyIABA0xQf+CBB0x9tnPPPTe4by5ISW2bBOd1AACI+tgdF/JdIwAA/C6qY7eGb6uiyc8d8vN9Hqe3ObC4GWsEAIgWIT9CvOSSS8wAIRqYNSDrJV56Zts+8MjOnTtdutq/9NJLUl5eLhdeeKHLcqZPny4PPvig+f9dd91ldgSuu+46yc3NleOOO84sM1rrzKblrAr1KgAAYkhUx+6EupeTAwAQ6aI6dgMAEEA2S4cqhQu93Cw9Pd2M5NqsgUuWvyMy8/qgtO7sizeav5OGuI52Hkn00sGsrCwz6Gmk15ALBtqLtmLbiszvod9iDALTrmv/I/L+VQGN1e6I3bGD2E1bsW2FHrE7fPh1n+jBdAkEYjeI3d6jrXxDe0VO7CZDGUhBHDAUAAD4AX0KAAAAAACHkTwPJA7AAQCIMFyQBwBApClJ7RbqVQAARCmS5wAAAEE48d0yb6MMXPaoJBXXDLoGAAD8oyKRUngAgCgdMBQAACAWTPjyLPM34+DPsvjUj0O9OgAAAACARtDzPJCoeQ4AQIQJfNmWtEOrA/4aAADEFsYbAwAEBsnzQKLmOQAAkYXYDQBA5KHjGgAgQEieAwAAAACAiGXR8xwAECAkzwEAAAAAQASjbAsAIDBInkfJpWMt8zYG7bUAAIhalG0BACDiFLfuHepVAABEKZLnUXIAPuHLs4L2WgAARK3k9FCvAQAA8NGGUfcFpM26bf63THp/oPTY+CafCQDEKJLnAAAAdv0n0RYAAESYiqQ2AVnuEUsfNH8HLf9zQJYPAAh/JM8BAAAce0bsGgEAEIlyW/UP9SoAAKIQR4hRUvMcAAAAAIBYNf/IZ0O9CgCAKETyHAAAAAAARLSS5E6yfvT9oV4NAECUIXkeJQOGAgAAAAAQyyzh6m8AgH+RPAcAAAAAAJHPRooDAOBfRJZAouY5AAAAAABBQs9zAIB/kTwHAAAAAAARryBjcKhXAQAQZUieR5EWpTmhXgUAAAAAAEIiv80wWh4A4Fckz6PIUd9cHOpVAAAAAAAgJCxbPC0PAPArkudRJLVwZ6hXAQAAeMOqpp0AAPA3xh0DAPgZyXMAAIAg67Xhn7Q5AAAAAIQ5kucAAABBNmDlU7Q5AAABtn70A7QxAKBZSJ4DAAAAAICoc6DbqY7/V8e1kLVjH23SckpTu/hxrQAAUZ88f/PNN+Wzzz5z3L/rrrskIyNDjjnmGNmxY4c/1w8AAPgBsRsAgMhC7G4+y6kGen7b4XKow1FNXJDlh7UBAMRM8vzRRx+VlJQU8/8FCxbIiy++KE8++aS0b99efv/73/t7HQEAQDMRuwEAiCzEbj+wxdf+v1n5bwb6BoBYldCUJ+3atUv69+9v/j9z5ky54IIL5LrrrpNjjz1WTjzxRH+vI3xRmi+SnEabAQBcELsBAIgsxO7wYaPjOQDErCb1PG/VqpVkZ2eb/3/11Vdy6qk1dcSSk5OlpKTEv2sI3yz+Oy0GAKiD2B1+WuWuC/UqAADCGLG7+arikpzuNT0DnlSaJan5m/2wRgCAmOh5rsny3/zmNzJ69GjZuHGjnHHGGWb6mjVrpHfv3v5exwhWW18taCrLgv+aAICwR+wOP0d/dY7MvnhjqFcDABCmiN3NV5XY2umeJeJUA91Xx8w6g7gNADGoST3Ptcb5hAkT5MCBA/LRRx9Ju3btzPQlS5bIZZdd5u91jGBc2wUACA/EbgAAIguxGwCACE2eZ2RkyAsvvCD/+c9/ZMqUKY7pDz30kPzxj3/0eYdAe6tryZfx48fL4sWL651Xe7ZrfXWd32azyYwZM+rM8+CDD5rHnG+DBw+WWGExCjgAwANit/f29TzL/C1PahuUbYnYDQDwhNjtXzbLEstPV4cTuwEgdjQpeT5r1iyZP3++SwJ81KhRcvnll8uhQ4e8Xs57770nt99+u0yfPl2WLl0qI0eOlMmTJ0tWVpbH+YuLi6Vv377y+OOPS+fOnetd7tChQ2Xfvn2Om/O6RrvyKkYBBwDURez23roxD8miYQ/KTyf9X8A3pf4rnpLCssqAvw4AIPIQu/0rqWRfs8q2OCN2A0DsaFLy/M4775T8/Hzz/1WrVskdd9xh6p5v27bNJMO99eyzz8q1114rU6dOlSFDhsjLL78sqamp8tprr3mc/6ijjpKnnnpKLr30UklKch74w1VCQoJJrttv7du3l5ipeU7PcwCAB8Ru71UltJSdXU+XisQ2Ad+Wem94JeCvAQCITMRu/0ouyQrNMToAIPYGDNUkuSa7ldY8P+uss+TRRx81vcftg4c2pry83NRIv/feex3T4uLiZNKkSbJgwQJpjk2bNknXrl1NKRitzf7YY49Jz549652/rKzM3OzsJwaqq6vNrcmsqqadnWgGy2rmOoeQrrde/hap6x9stBdtxbYVmd/DUP3GEbu9V62Xdevn6nZCevmxf5NRP9zo98+m2fsbIUQsor3YtsID38XAthWxO7Jid2670ZKRvUxWH/WoOT52poVbmsO+PGJ37OD3lbZi2wq9UMfuJiXPExMTTQkVNXv2bLnqqqvM/9u2besIgI05ePCgVFVVSadOnVym6/3169dLU2nd9DfeeEMGDRpkSrZoHfbjjz9eVq9eLa1bO4+0XUuDvM7nTgdELS0tbfK6JOfnS4YEV0lxseTWU/Ym3OmGnZeXZ74QeiIFtBfbFt/FaPzdKigokFAgdnsvLzdPioqLJNGtnMo+aS+j/P7JiBw8cFBKkuIlEhG7aS+2rfDAdzGwbUXsDu/jbufYrbnxr4/8m6SUHZCS5E4ieXmu8xUUNut1cg8v7+CBamJ3jOD3lbZi2wq9UMfuJiXPjzvuOFOe5dhjjzUDfGrtcrVx40bp3r27hNLpp5/u+P+IESNMUO/Vq5e8//778utf/9rjc7T3u3O5GT0B0KNHD+nQoYOkpaU1fWUym/HcJkpJSZH0jh0lUr8MOsCrtjvJc9qLbYvvYrT+bmnvrFAgdnsv/WC1uao7xW0fIK2eZEBzte/QXlont5BIROymvdi2wgPfxcC2FbE7cmJ3enq6xJm65m3EU6HXtNbNe53Re9+RbUdcL+07tCV2xwh+X2krtq3QC3XsblLy/IUXXpAbb7xRPvzwQ3nppZekW7duZvoXX3whU6ZM8WoZWoc8Pj5e9u/f7zJd7zc0GGhTRigfOHCgbN68ud55tH66pxrq+oE0K4lrC34vMt1PiOTEs34Zmt3uMYT2oq3YtiLvexiq3zdit/f0oNv+uQYjrkd63CMW0V5sW+GB72Lg2orYHUGx2/z1vKyC9EFSntJJypPaSouyQ2JrQgmX/qtnyPYhNxK7Ywy/r7QV21Zsx+4mJc+1jtmnn35aZ/pf/vIXny4fHzNmjMyZM0fOPfdcx5kEvX/zzTeLvxQWFsqWLVvkyiuvlJjAgKEAAA+I3QAARBZit59pUj0uXuaf9a3YqivkpE+ObNJi4iqbV2IGABBZmpQ8V1qvfObMmbJu3Tpzf+jQoXL22Web3uTe0ku2rr76ahk7dqyMGzdOZsyYIUVFRTJ16lTzuNZS117tWhvNPsjo2rVrHf/fs2ePLF++XFq1aiX9+/c30//whz/IL37xC3PJ2N69e2X69OlmnS677DIJvuYNRgIAgD8Ru8NURYlIhJZtAQAEFrHbf8qSO5i/1fFJInpron6rnxUZ+LQf1wwAEHXJc70U64wzzjDJax0gRGmCW+uVffbZZ9KvXz+vlnPJJZeYwUGmTZsmmZmZMmrUKJk1a5ZjENGdO3e6dLPXZPjo0aMd959++mlzmzhxosybN89M2717t0mUZ2dnm1o4WuN14cKF5v+xoCmXngEAoh+x2x+0hqr/JS6YIXLatIAsGwAQuYjd/rH+yOnSZfvHsm7Mn/yyvF4b35ACIXkOALGiScnz3/3udyZBrknptm3bmmmarP7lL39pHtMEure0REt9ZVrsCXG73r17m5FVG/Luu+9KtB9kN4iyLQAAD4jdfmAGIPO/+H1LA7JcAEBkI3b7x+7+V5gbAABBS55/++23Lolz1a5dO3n88cfl2GOPbdKKwD8sep4DADwgdocxqzrUawAACEPE7vDF9d4AEDuaNPSojpBdUFDgcXBOHQgUAACEF2J381mBuqKMq8YAAB4Qu4Nrzbgn2A4BAP5Jnp911lly3XXXyaJFi0wZFb1pT/Trr7/eDBqKEOIAHADgAbG7+UpTuwZo26L/GgCgLmJ38GT2OF2q4xi8GwDgp+T5X//6V1PzfMKECZKcnGxuxxxzjPTv319mzJjRlEXCX7j0GwDgAbG7eSoTUgNW85zYDQDwhNgdWItP+UB2971Ylh3/D1kz/hmfnkufNQCIHU2qeZ6RkSH/+c9/zOjf69atM9OOOOIIkzxHaNkObuQjAADUQexudoT1OBD42rF/lqr4ZBm+6I4mL9mqpuY5AKAuYndg5bcbaW5NUVFF7AaAWOF18vz2229v8PG5c+c6/v/ss882b63QDFz6DQCoQexuvvyMIZKWu1a2HXG9x57nmT3PFLHFiyxqxotw1RgA4DBid2Rose0bkeGnh3o1AADhlDxftmyZV/PZAnVJcyQKQVvEFWcH/TUBAOGJ2N18S056W1rnrpXcdkd6fNxmVUu1rUkX8tUieQ4AOIzYHTq26kqv503/6FKR4XkBXR8AQHjw+mjPuWc5wrcQWkLWqqC/JgAgPBG7m6+qRUvJ7XBUvY9bmji3NWkIGeelNPP5AIBoQewOHZtQigUAUFczu0oBAADEnorEdNkw+n6pTkgWqa5q3sIYdQwAgNAjHgMAPGhuVykAAICYs2PQryWz1zn1lmnb1+ts7xdG2RYAAEJOS7HZVbRIC+m6AADCB8nzQKL+OwAAMdA7zTV5vmnEnVLUup/3y/KhxioAAAiMwvSBjv8vOu0/NDMAwCB5DgAA4MeT5TsG/UZsPtQx92WAMgAAEBj57UbKqqOflSUT35TSlt1oZgCAQc3zQKJmGgAAUX9pt7O8tsN9v/KsuTXTAQCAX+zveRYtCQBwQc9zAAAAn3nuWX6g66TDD3vf81wsep4DAAAAQDgieR5I1DwHACCmep7ndhh7+H8+lG2pqvDTWgEAAAAA/InkOQAAgM9ck+OLTp0py499SXI7HOXx8YYX5cO8AAAgKJae8E+pTEiV9aOn0eIAEMNIngcSB8MAAMSEgjZD5GC3Uxrtme6RL/MCAICgyOl8vHx77s+ye8AvaXEAiGEkzwEAAHzUWHJ8f4/TfVgayXMAAMKRFZcQ6lUAAIQYyfNAouY5AABRqbJFqwYfL0of6P3C6HkOAAAAAGGJ06gAAABe2j74Wkk/uEx29b/Cb23mU4kXAAAAAEDQkDwHAADw0uYRd/q9razqKtofAAAAAMIQZVsCKaVNQBcPAAAin1VVGepVAAAAAAB4QPI8kPpPCujiAQBAFLCsUK8BAADwQWmrHrQXAMQIkueBxIChAADASVV8St3dBaHmOQAAkaQoY3CoVwEAECQkzwEAAELJouY5AACRhavGACBWkDwHAAAIEsvDVWk2BgwFACCiELsBIHaQPAcAAAiwktSu5u+uAVfVecxGz3MAACILsRsAYkZCqFcAriyxiY1LwAAAiCqLT/1EWh9aLfltR0qfdS+7PEbcBwAgshC7ASB20PMcAAAgwCqS2khO5+PFsrHrBQBApOOqMQCIHRzBhRsPtVABAEB0sFnVoV4FAADQTNXVxHMAiBUhT56/+OKL0rt3b0lOTpbx48fL4sWL6513zZo1csEFF5j5bTabzJgxo9nLDDsWo3YDAMIbsbsZSJ4DAEKA2O1f9DwHgNgR0uT5e++9J7fffrtMnz5dli5dKiNHjpTJkydLVlaWx/mLi4ulb9++8vjjj0vnzp39ssxwd6jDuFCvAgAADsTuZqJsCwAgyIjdAcDJcACIGSFNnj/77LNy7bXXytSpU2XIkCHy8ssvS2pqqrz22mse5z/qqKPkqaeekksvvVSSkpL8ssywQ9kWAEAYI3Y3T2ViWp1p1XEtmrlUAADqR+z2P8qwAUDsSAjVC5eXl8uSJUvk3nvvdUyLi4uTSZMmyYIFC4K6zLKyMnOzy8/Pd9Qxa24tM5/PTrhVbbHcJ0Rx/TVdb8uyInb9g432oq3YtiLzexjJv3GxErurLavmc7UsiRP/fF5WAz3UDnQ5STpE6HZBLKK92LbCA9/FwLYVsTs2Y3eDrOavc6jwe0F7sW2FB76LkRO7Q5Y8P3jwoFRVVUmnTp1cpuv99evXB3WZjz32mDz00EN1ph84cEBKS0ulOTwXl6mfZbOJzSlfXllZ5fNrRmqJGt2w8/LyzBdCd75Ae7Ft8V2Mxt+tgoICiVSxErvzcvOkqLjInNC2xflnIO/cvLx6H6uoqCB2xwj2dWgrtq3QI3bXIHY3czuqLCd2xwhiN23FthV6oY7dIUuehxM9Y6510p3PgPfo0UM6dOggaWl1L68OpoQE3z+ijh07SqR+GXQgWG13kue0F9sW38Vo/d3SwawR3rE7/WC1iE0kPT1d4vxUTi0jPb3ex1q0SJAOxO6YwL4ObcW2FXrE7tCJtNjdkIQ4m2QQu2MCsZu2YtsKvVDH7pAlz9u3by/x8fGyf/9+l+l6v77BQAO1TK2f7qmGun4goU/i+h74Q7/OTadfhvBo98hAe9FWbFuR9z2M5N+3WIndetBtPlfz1z+fl/Nyvj/rO2m/9xtpnbdBum95x9RNjeTtglhEe7FthQe+i4Frq0j+jSZ2B4ZNiN2xhN9X2optK7Zjd8j2AhITE2XMmDEyZ84clzMJen/ChAlhs0wAABC4OBsLsbs8qa3L/bLUzrKn/+VS0aK1uc+gYwCAQCF2BwaxGwBiR0jLtuglW1dffbWMHTtWxo0bJzNmzJCioiKZOnWqefyqq66Sbt26mbqm9oFJ1q5d6/j/nj17ZPny5dKqVSvp37+/V8uMOEG45AwAAG8Ru723dOLr0mv9q7Jx5D2eZ7DF1/wJxsBmAICYRexuvl39LpceW/4tue2OlIzspWbAUABAbAhp8vySSy4xA3tNmzZNMjMzZdSoUTJr1izHoGE7d+506Wa/d+9eGT16tOP+008/bW4TJ06UefPmebXM8EeyHAAQvojd3svpdKy51ceyl3LhABwAEEDE7ubbcOR02TbkBmmXOd8kz21WlR+WCgCIBCEfMPTmm282N0/sCXG73r17m5FVm7PMcKeXcqcU7Q71agAAUC9it39PmNu82LcBAKA5iN3NZLNJeUqn2ivDid0AEDMid+STKLLq6Gdl5YQZktd2uCw/7uVQrw4AAAgCR89zyrYAABARLHvJNXqeA0DMCHnPc4hUx7WQA90nS1aPM2gOAABixeHkOYOOAQAQGazD/Q9twlVjABAr6HkOAAAQApZ9nBMu/QYAIMJOfFPzHABiBclzAACAEIivKjF/2x5YRPsDABAB4iuLzd/k4n2hXhUAQJCQPAcAAAiBPusY5wQAgEjSc+MboV4FAECQkTwPUY1zAAAAAAAQOeKqSkO9CgCAICN5DgAAEAKcTAcAILJYcQmhXgUAQJCRPI9GDDwGAEDY2zTirlCvAgAA8MGePhfTXgAQY0ieRyOrOtRrAAAAGlHZorX5W9SqN20FAEAEyG87PNSrAAAIMpLnAVaQPtj8rWiR5pflWTYvPrLqSr+8FgAACCBbzZ+WhdtpZgAAIoHtcPBWXPENADGB5HmALTv+77K2z1RZNOnDBuZyCsCN8SZAV1d5vzwAABASGQd+rr3DATgAAJGlqiLUawAACAKS5wFWltJJ1gy4Xkpa9WxgLi8S4r6wSJ4DABDu0nNW1t7hABwAgLBXkZhee6eqLJSrAgAIEpLnIVCa0qnBx5ee8Jp3l4nVp6ygCWsFAACCybLF196pKqfxAQAIc9VxSbV3KkmeA0AsIHkeRKuOflby2wyTFce9LEtPeL3e+XI6H9e8F1r4t+Y9HwAABFy1c/K8mku/AQAId9Xxzsnz0lCuCgAgSBKC9UIQ2d/zLHNTVfEpTWoSS2yNV0gvyaW5AQAIc1UtWjndYbBvAADCXXV8Yu0dep4DQEyg53lY8GHAUG9UcwAOAEC42zz8jto79DwHACDsVdta1N5hvBIAiAkkz6Mx0U7dVAAAwl5papfaOxyAAwAQ9qw4p4v3OfENADGB5HmE2TbkpsZn4gAcAIDIOgAndgMAEGGxm8G+ASAWkDyPMNuOuF7y2wxteCYOwAEAiKxLv+m9BgBA2LNszslzyqUCQCwgeR5p4uJlxbF/k139LpfMw4OP1sEZcAAAwp4VR91UAAAiis0m1fb4zYlvAIgJTqdNEe729LnQ/C1L7SIbxjwoLcpypPPOT+vOSPIcAICwR91UAAAitfd5BcfdABAj6HkeAZZMfEN29f+lbBp5j8v0yhZpnp9QzeVjQLQ5WFgmpRVVoV4NAH5k2eJr71ByDYg6xG4gOtnsPc4p2wJEHWI3PCF5HgEOdTpGNhw5TSoT60mWi0hpapfaOxyAA1Fn+c5cWbcvP9SrASBQl34Tu4GoQ+wGolOcdbiz2noPV4EDiGjEbnhC8jxKVMcl1t6pKpc1e/NkyY6cUK4SgAi0cneu7MktkUiycGu2FJdzxQ0iU5yj91oZsRtAkxC7gRBZ+iaxG0CTELsjC8nzELGJFbhLv6srZV9uqRwqOnxADiAq+PdXw7Os/DLZkV0skaSwtFKyC8tDvRpA8yx+ldgNRCFit2fEbkSFpHRiNxCFiN2eFcbwcTfJ83BgszXpaZbYPA86xoChAABElo1fhHoNAACALybeRXsBQAwgeR4OrOaf13LUTFWVsXkmCAAAAACAQCpMH1jzn8SWNDQAxACS5yHi3GvcL8uzOfU8t9dPBQAAEcK/+wUAACDAx/JWNU0MADGA5HmUqKZsCwAAkevEe0O9BgAAwJfxxqqraC8AiAEkzyN5wFCnWunOPc+tKtee55ZlSWkFgR0AgHCT13a4+WsltXaZTuwGACA8pRZuN3+tnK0u04ndABCdwiJ5/uKLL0rv3r0lOTlZxo8fL4sXL25w/g8++EAGDx5s5h8+fLh8/vnnLo9fc801YrPZXG5TpkyRaBsw1JkVF1+7uLJ8l8d25hTL/E0Hm/0aAOAvecUVsjO7mAaNYDEfu/3EcfK7utJlOrEbQLghdkc+Yrd/JFTW7MPaFr3kMp3YDSDcELujJHn+3nvvye233y7Tp0+XpUuXysiRI2Xy5MmSlZXlcf4ff/xRLrvsMvn1r38ty5Ytk3PPPdfcVq9e7TKfJsv37dvnuL3zzjsSzVxqnrspq2y4Ftu6fflSUk7PdADBsy4zXzbuL6DJIxSxO/CXfhO7AYQbYndkI3YHHrEbQLghdvtH/RnXIHn22Wfl2muvlalTp5r7L7/8snz22Wfy2muvyT333FNn/ueee84kxu+8805z/+GHH5avv/5aXnjhBfNcu6SkJOncubNX61BWVmZudvn5NT23q6urza05qi3LXL6lf+Okdlk6zfn/Vn2DjTT4WHXdg2/H06pd3oPer++97M4pkhbxNunbPrSjhdesp9XsNo8V/m6v6uqa7TQhPuTn1PwuGrYt+3c40O9BX0d/PgLdXlYjv0s+r7OflhWMbSuSt8NYj92BYI/fWnKN2B39iN2ha6tQIHY33DbE7uAidgcGsTv6EbtD11ahQOxuuG2sGD3uDmnyvLy8XJYsWSL33ls7SFZcXJxMmjRJFixY4PE5Ol17qjvTnuozZ850mTZv3jzp2LGjtGnTRk4++WR55JFHpF27dh6X+dhjj8lDDz1UZ/qBAwektLRUmiMvN0+Kiot0SG6xxdWWZ6koru1xWVRcLLl5eR6fX1lZWe9jzsnzsirXGur252Rl2SQnp0Ry88rM/z3ReXPiyqRVdZGEkm7YeXl55guh2wGC216r9xXKoZJKOb5vRtQ1fTRsW+Y7XZYgWcmuYxp4Unn49yAh3tak10mKt0nu4eAUqPY6lFsgReVV9f4u+brOBxPKJbGisFnLKamokuLyamnXskVAt62CgsjucR/LsTsQyqtrvq8F+XmSm0jsjnbE7tC1VSgQuxtuG2J38BC7A4fj7uhH7A5dW4UCsbvhtjkYo8fdIU2eHzx4UKqqqqRTp04u0/X++vXrPT4nMzPT4/w63U57t51//vnSp08f2bJli9x3331y+umnm4P3+HjXHtpKEwDOB/Xae61Hjx7SoUMHSUtLa9Z7TD9YraODSnp6usQ51TZPia+tS94yNVUy0tM9Pj++RYt6H9Ne6XYJiSkuD9mfo0mIXKtAiqTY/N+TjGxL2rZrJR3DoOe51qfXdo/UH9pIbq/4XJtkJFbXu51EsmjYtvR72qZlonTs2KbReedtOCB6AcHxAzo06XWSE+IkI606oO3VpjBeWpRV+mV703Vu3761dGyT2qzlLNqaLYVllXJEn44B3bZ0vI5IFsuxOxDiWxyO3/EJxO4YQOwOXVuFArG74bYhdgcPsdu/9vS5ULpt+1CKjriY2B0DiN2ha6tQIHY33DbtY/S4O+RlWwLh0ksvdfxfBxQdMWKE9OvXz/RoO+WUU+rMr5eJ682dfiDN/cLrQbd+wDV/a5el05z/7/yYM52rvsdMlzjHC7kmFuzPsb8HvV/fezGP6TqGwY+baSs/tHus8Gd72bfDaG37QG1bBaUVkpgQJ0kJdZN7/qSfjbefj3Zk1fLJTXmv5nXMb0bNGd1AbQ81r9H85ZdWVPnUNoFYJ1+3rWj9jsVC7A6IuJpdsUMFRcTuGEHsDk1bOSN2Nw2xG+5iNXZXxyWav/lFJcTuGEHsDk1bOSN2Nw2x2z9CegTfvn1705ts//79LtP1fn01T3W6L/Orvn37mtfavHmzRKvqBgYMBRA4i7bmyLKduTRxiOSXNl7GBv5F7Pav5OI95m/LvOjdRwHCDbE7tIjdwUfs9i8rrqbUQFx1pZ+XDKA+xO7Qyo/x4+6QJs8TExNlzJgxMmfOHJeu+Hp/woQJHp+j053nVzroWH3zq927d0t2drZ06dJFolVVQvMumwDQdPYa4wgBmj7oiN3+1Tq3ptRNh31z/bxkAA0hdocQsTvoiN3+VX34qjGbFdvJJCDYiN0hZElMC/m141qv9JVXXpE333xT1q1bJzfccIMUFRXJ1KlTzeNXXXWVy6Bkt956q8yaNUueeeYZU1v1wQcflJ9//lluvvlm83hhYaHceeedsnDhQtm+fbtJtJ9zzjnSv39/MzhZpLFsDZSCcCr9Uh1fc+kYgOArq6yi2UMswGWp4YbYDSDSEbtDj9gdXMRu/7EOX/Vto+c5EFTE7tCzxehxd8hrfVxyySVy4MABmTZtmhk4bNSoUSY5bh9YbOfOnS61ko455hj597//Lffff78ZTGzAgAEyc+ZMGTZsmHlcy8CsXLnSJONzc3Ola9euctppp8nDDz/ssb5aeKi79e0ccLV02f6JbBj9QPOT7AACymns3qigI1hHq9lr98uI7unSMS2yB+0MNWI3gEgXbaGO2I3GELv9+H073POcsi1AcBG7I8fsKDvuDnnyXGmvcXvPcXc62Ii7iy66yNw8SUlJkS+//FIi3cbRf5RNI+92BObmlG2J0RNDACLwwL+0olpSEgN7MjC/tFI6pgX0JWICsds/dvW7XHps+bfkthvtMp3YDSASELsjC7HbvzXPbZZrzXNiN4BIQOyOwLItUJ67vnibOFfV8Sk0JSJeeWW1fLvxgFfzVldbsmJXrvkbjnS9th8s8vns7JYDhQ3MYQVthPRQ2J5dLD9sPtjgPHM3ZMnO7GKprKqW4vLKRj8DnQ8IZxVJbc3fqoSWoV4VoEmI3cRuYjdiTbVjwNDyUK8K0CTEbmI3sds3JM8BhI2iskqpqPQu2VleVS0HCsrM33CiCfC8kgopKKuUzVmFPl9GfaioPGYv/dadOE+0Pe2J8qoqSw4Wlcmavfny4+bsBpe3dOchmbfBu5MxQKg4yq5ZjJ2AyETsJnZ7QuxGNKPmOSIdsZvY7Qmxu34kz2PQvrwSk9RztvWAbz1kvbFpf4HM25Dl9+Wibk9cDX4ILm1zTZR7kldcEUGXa1UF7ASCv/y0LcclUa65/TIvTrLklzZtHeyfq7ZNRZidnEH0sWw1u2I2q+FtjdgdXYjdoUHsrh+xG/Betb3meVVZg/MRu6MLsTs0iN31I3YHD8nzsBDcEgnrMwt8LifRFAcKy6SyKjxLakQTLU3hj0RlqEp1NNfuQ8XNTgDvyilupFxKXQWlkX/CYtvBIpm/qeEyKQ3Rkij19RZvrKRKoAO/P7YrbZtlO3NDvSqIkZ7ntkZ6nhO7owuxm9jdVMTu+hG7ESytc9fV/M3b0OB8xO7oQuwmdjcVsTvyYzfJ8yiS226UdzNa4VWqAXBsg25NsWRHjmQXNtyjY/vBYtmZU9ysRtyQWSDbnK6+yCkqD0iP41DVZ9deEvbe8HtySxwnG3RwzqbQ34ofNx+Uxdty5LuNB8yVLFqH3BeFHk4+FDSxp3hTNVQPff2+AvO3JAA98wHPyfNGvo/EboQpYndgELs9I3YjHHg9TgmxG2GK2B0YxO7ojd0kz6NEWUpHyche7rifWJIlKQXbQ7pOsUYTo4EogRHptHRGQz2KtcZ3fb2XDxVVyL68Ur+sR25JpXzfSC/rrIJSkxheuuOQzz3RG6PJ5W/W1y1jdLCwrN7yL/6idcJzimtqqa/bmy/bs2tOFFheDkC6P7/UJeDpebbi8ipzU3oly8b9NUHPTuvR+6o5Fz/Yr5zwpVSL1kMvbKTkEScVEXCOsi3Ej1AgdntG7K5B7G4csRux6FDHceZveWJGqFclJhG7PSN21yB2N47Y7TuS5xFuw+j7ZXffSyWzx5ku00/433Fy7BenieTubPD5VQHsCWsLcjmaUNuW3bwSGNFq8dYcU7O6Pkt2HKqTeA2E7KIKKa9sODm1cleeZB1O+lY75fNzi8tNr+imJFLtT6kvqavLdplfws+q3Xmy61CJT8E2K9/35Lk7PelSX5vbpzs/WlJeZbY3X64aqO/EDRDsnufpOSu8fg6x23+I3Z4Ru2vagdjtO2I3YkFVfLL5G1dd7v1zOO72G2K3Z8TumnYgdvuO2N24mpEuEHSVTpd6lSV3aPJydg24quEZts8X6fKLeh92HzgUTaeJOzRNdRiVDPK0Kj9vP+T4/6QhnRpfhh9S4NrTO85mk7i4pp+E0oR/y8QEv2/nC7fVDt7ZFNrD3xt60mVQ59YRuR0B3mq7/wfH/+MrCqWqRatGn0Ps9h9id9OF028usbthxG7Av6oPJ88TKotrfoC86FlC7PYfYnfTEbvr4rib425v0PM8RCqS28m6Ix+UzcN+L/ntRgb8cvD6EnuBqOuMGlqKw9syLtr71dcBFqNJQ1cp+OvY3NNitGSKe53t5iS+G6pp7rxPrb2mddTwmv/XX1Jk9d4813XzcdUWbc1xlGjR7atOL3fL+x1Re09vPZOvZWCaQ3v4B7qXjn6nnK8eaKowyg0hSnXYN9fx/4SK+k9oE7uDg9jtPWJ3XcTuGsRuRLvquBaO/8dX1o6b5I7YHRzEbu8Ru+sidtcgdjeM5HkI7el/uWwfckNAX6PSqpuUrC+hRJLI/7xNnmvpkh83N683byTJzCsNeJ1vb3o/L9+ZaxLMzan55WzZLu9GiNYBThdsafzzLvAwqKavKg8nn/fllrr0oPfkh831lx3ypoa5JtibMiiqDqzijdoSLlbQevfoTgQnGREsiaU130FP2xyxO3iI3Z4Ru4ndzojdiGXJxXsd/2+X+b35S+wOLWK3Z8RuYrczYnfTkTyPcmVVIjuyi0O9GmhEWSO1uKOJ9rhevcf7nsfNufxqb25tnW53/uiV7GnwU7uGEvLhlozV9XbeBnXn0/2SPm8S+av25HkcFLUx9p7s3o6ToAPJ+lIapqHBX+1XfOh7rqynR30ga1QCu/pd7mgE6/DVYvo7SewOf8Ru/yN2e4/YTexG6GR3PsHx/4qkNuYvsTsyELv9j9jtPWK3ROxxN8nzKGc/EPdk96HGk+rai3RfXon525QepcE+kxzrCssqZUOmd4Nvas/cQH+mu3LqbmP7872rd+0LT1dN6ACXa/fmO83j3XsN5hUY+hnYX27bwSKf1kV7gm91SgprQl7L0DRlUFO98mHdPtftJjO/7gBIjW0vucWuSe2conLJLnTtsb5kR45fB+zML/GcSHcOyNrrvj7r9xWYcjY62G99vzP+ujIB8GTj6Psd/++883/mb0NfY2J39CF21yJ2e4/YTexG6DiPTxJXVbOvS+yOLcTuWsRu7xG7yyP2uJvkeZQrKrcaTBp5CgLfrK8tp7G/oFTW7MmXn7bnyPwGSjo0Z8PX5PzK3Q2Xu9AvWJYXSVddjp759IXWvPYmGREqmrD09j3tzC72mLB2p8vbfrBIigJcZ93bRL5dfYnfpiSEG32tRkp/6FlPX1/Xvs1v2l8oOw42/jnoZ2C3pZ4yI/r98BRctG23HihybCPfbjhgytDoSNmN2Z1TYmqXO789957m9jy589nf3Yfq78nvydIdh2TZzlyXBL97r/HvNh6ovdPIb4bzKtr/a++dq21QdjgR31Cy3JPGytkAgWTF1Q7q23vDP83f3Aa+x8TuGsTuwCF2N4zYTewGVFlyB/M3rqpmv5PY3Thid+AQuxtG7CZ2NxfJ8yhS1LpPnWmZBeUuCWhNjjdEe2A6l7PILix3lGxobg/R+mw/WCxZ+Y3XU7Ynxhqiy2nsPXoKNJ6SEY3R9shz62nbGO0JrUlLX6zZm28GsfBGQ2VKGuvBH64n+cqrqmXOuizZnFXgMrCl8+CWmgj3thSK9s52n9fTiR7tIb/lcHLaG+4nd3JLar977oOS+kJPXtmT5PVxTny75/v1hIoni7fmuFwFUN95goVba2uz60mmVbubXnJH294b2qveU0183RYa+h5rsl5t3O/6febKFUQa55NpxG7PiN01iN2uiN01iN1A4FXFJ5m/8YeT58TuxhG7axC7XRG7axC7wxvJ86hS92e4085PXRJIDQ36p4kp9wSaDjARaN72UPeU3NNetppkc65vvHTnoaDU1F63r6ZHvi80ud1Qz3C9jMe9zEVzEq/uNAnjz+UFYxuw1xF37lGtA1tqWzn3pNae197Q3tmajPamvrYmexu8pMiqlkFLHpSeG16TlfUklXWz1UFJC+upGe7e41tPyOzILvLYLu5lUepdr+aornJ82bQeuPNJimKn/wfSoeK6JWOUv2pAu7c5EFbctk9it38Ru/0nYmO3k6iJ3U6I3UBwpBbtNn+7bXmvzmPEbv8idvsPsbsWsZvjbl+QPI8ilodfws67vhBbdYWkFmzzKmFV0khtcR14b08jvZuDSUtaqPyS2oMb7TkfjKR/lQ8JON2B8qb3qx5s7vNy3XfmFNdbVsR54Ep3FfUMzhDu7G9Vr47whad2157q9ZVtcZ6qB816sF+fDnvnSI8t/5aBKx4XW1W5y86IfX3tV2zYtxe98kCvtnBOHrjTsi/KOXHt6T3Y2fx01B1fUSTHfn6KHPn9ryWnuEIWbKntde4P2ove3zrt+J8c9+lEyTjwU4Pz6ZULPx7+LOvrjV8f/U0JROkgwJP+q572qWGI3b4hdgdXOMZud5Eeu51FSuz2FrEbkaDNwZ99fg6x2zfE7uAidru1B7HbJ9Eau0meRxErroXH6aO+v1aO+WKydN4+s05PmaLSCmmds1riKwrNzrF949YN1tMAhtsOFMn6fU3bidYe4usz870+aPJUtsFer9ubshuBZvOxx7fefKX1pj319tX6zpv2F0hhWc1j7u3qXBpGP0t/jCquJyp8Pfh1fy/ellZpyN5G6lm797jy1O5ahsiZc6midU6DjCpPv926bWpvusTS2gPUuGrPPcvcD+Bz3Wp++1qOx708jJYp0vdch49BR0+4dN7xH0kp3ivt9v8oVeXelVjxVkNln/T3p++qGZKWvdLr5dl7Aw5fdIckF++TsXOvaHD+/fllTe45r5/hwq2+XWUCNFXv9a/UmVYndjuVJyN2+4bY7ZtojN3eCFns9pF7Zwl/d5DwpmSjL9+p+nry14fYjUgxet7VdaYRu/2H2O0bYncNYrd/vlPE7hokz6PI2rF/9jhdE2FqwMqnTPLbWcqWz2X87PNlwqzT6+x81zeAoacDEi2b4s0ZohwPPaI9fXEb6qW9eFuO6yCDTRjI0B/82WOovpbzts688wGkcr46YOvBIvl+o++Je3eaoFnVjHI4+pl5e3l2c/y4ObvRHme+1qr3RBOxlq12oD+9wiOQ2uxfICkF2+uc1Fq4JdtcWu5YD0vkyHlXydhvLq0pweIDm+VUR74J23dD5VAaGhR4wIonpO+6v8mYry6o85hzXfZQ0mRlOJY8QnRqv/cbl/vusds9iWhH7G4csds30Ri7Q6HR2B3CCrhNjd0NIXYj1rTLWlBnGrHbf4jdviF2+wexOzSKwvS4m+R5FCloO7zBx1uU1daZtOux6V/mb3KJ517e9dGa4vYBHLW3+spdeR4T42rFrtzaHx4vO8TYDyKcE/L2y2VM0tJtORWV1R4HI/x24wHZesDzSYCGDs6aPDhqEy8xqfJzT6Hiwz3StWeT+45bY4dn2rM/EPQMeGOW7aw5SGuoh7vjsinLktT8rfW2eaAOQ+3rpttmdXzt1R5x1a7r7M9PVEuSjPn2ajn2i9ManTcue720zVooGdnLJCN7acMzW5YklHu+GqS0Cd+Bynq2Yz2Z417z1VZdKQllNZ93W7cDDudBfzVJ2HPDP6X7pv+TQOu2+R0ZsvhuU4LHEy82YcAvRs2/PiAtSez2L2J3E2J3I4IRuxsSsp95P73xQMfuhrjH7nBB7EawJPp4PO0tYrd/EbtrELv9gNgdU7Gb5HkMibMqJaVwp1++8VpT3F77MfNwz1DdwJ0PnOxL1kFK7YMo+cr5GEdrSTrvmLs/roNJudOkun39vKWDgK49XJpGE/86Krgm1O29uTUJ7D6op+q88GE5/n/HiRza4dXraOmVhhLV2pt/RT09frz9LXG/TNgbG/bXnBTx+LqWyKrdeY6SOtoWukOnB6Nr9+ab9moqbQ+7dfvqXwe7/iuflmNmTTF/7RoaKNb9eNn5cmpf/Ly99iSU5fQTarOq62x7/tJu37fez+zU21wT1A0ZuvhOOXHmWEk/ULdWo+X2fprD/XJ6dcznk+TE/4yT1PwtZuBVZzmFtb8jLXM3yMAVT8jgZX+SnMztPr1uQnmeJBVnej1I6BFLp0vX7Z9I9y3venzc0wk6IJIQu5v/HSZ2120PX2K3J8GO3brQET/cKGPnXFonTvozdvvETweJ/hwQ21Psbohz7Hbm6364v98PsRuBsrf3+S73T/jf8QF5HWI3sTvUx91hEbsbQOyuRewOHJLnMabf6hkmUdZu3zxz33JOnjsl3Zbu9O6Hyll2UZn5gdPEsiZXU7NXSecd/3X59fS0C+zeO0WT1AfqCZLFbslzb3th13epryb7PfWqsdd10sT/rpxiWb03z/wQaQ/67dlF5kyt+2mH9qtekaTSAyJf3ucyvb5eTiv35Mm8Bi6F1tf1tb6U++t6e4mbXhqTkr9N2mQtkn25pXXqzdvrnWqPfOdLcXX9dIduzrosExS1vZQ+37nuurOtbj3hlS7jm/VZLusj9ZTz0fVTvTe84vLXvhy7nEbqsx9qQv1SZ9l6kOgyyli1S/kcreOtpRfiKl0PGsur6r9kPKl4nxm0U7XN/EFa5a6rM491eIenrMLzAb7rd8cyr99j45vSMm9znXm76PdTxCSm675Q4E73pmWvMLXV7fWdbQ28VmJZbV15W7EPg6BVV8mJM4+S4z89wSTQTXtVV0mXbR9Jy7yN9Y6poJIPr5u2nZ64iKus2eFzv4oD8JctQ2/xy3L8Ebs9iebYXZ9Iid12kRK7PQl27NZY23HPbHN1VrvM7+uUvvOkodjtjcZi99684Jcf9Jf6eq77I6nh3l4Nxe76ELsRKFuH3OSX5RC7id3OiN31HHe7IXY3D7HbdyTPY0znnZ/KUXMvl9HfXyfpB5e5PDZq/m8d//f2wM95sCN7WQ77JUDDPztHhi36g0vtVh0MyvlMpzMdAFPpgKTbD5d50XrdzgdjTU3nldYzYGZ9ZzP1QM95UCn7e9M68I3mFMtr1j2+vOb9bKqndnx9dZz0IFJf3/11tNe9HjRoD5qSwzXh9fC69aE1Jsmng4YmFe2VDru/9KnWtZbbWbAlW4769FQZM+9KUyLEPliX/WDb03vWdfTUI8iecPBHbVJ3vgy66t4DqqGPrW3mfOm69f0607Ut+qx5XuKq6uvxYPNYL1yN/OFGU3ph8NLpLtPtV2y03ztXxn19vqRlLzf3U/M3y/GfTpTjPjvRDOJ75HdT5eivzjFJeZvT2ut30zlZYafPH/n9b6X15v86rZ0lfdf8VQYt/7NM+PKMBlqgbqKmZckex/9TCnbUOQlQH52vy7aPTXLCEy3VMm7ORY77li1ObOLhwNrDthVfWSLdNv/b1H9vTHxV7fq2P3yysNvW92XoT/fKhC/PavT5WsP+5I9HyOjvr5Whi+9qdH6gOUpbdqszbdL7A6XPmhd9Wo4/YrcnMRG73QQ0djslx70dSL2+2O1eZi6WYndzrsS0szn9vyH22N1U9cXuQPQYBxAclS1a+2U5xG5iN7E7MIjd8CeS5zHsqG8ukbYHFjnut8/8zlzGqgfs2jNUJRftNsmquErPBw1aSsWuvl5FXXbMdDlQ3JHjeVk7c4rlkP2g7XA96+0HCuu93FMPRu0Hor7Q53kzAMFP22oHcmqoBrpzEkLp4Y+1/nM5aeYYSZr7UJ3ecXpg7z4gaqtDa6XjrlmOI11PPbx0cCl7eRrzf8uS9PXvyNGzL5Ajv71GdueUyPGfnSgjf7xFemx5W+ZvPujoTabsr+neZnrZl7PhC25zzG8v0eKpE5wetC/Zccinsi+q4+4vZcT8GySx5IBUV1VJpx3/k5Z5m8xjelXEiB9uqinl4aa8gRI39Se3az+j3JJ6DpAtS4787lcy5Of7pY0OrmtZprdxctEeGTv3Cum35nkZtPRPdZLBWhc7/fD3xNzXJHd1pbnaQssjad1xpWVA9H6FUxKo/4onzcmqtEOrZdycix3zqRbleZJx8Od6k/L1OWbWGdJh31zpsLw22dZv1QzpveFVx30dSLTDntnmO37KB4Md01vnrqtTp3HKj5eZv20zv5djvzhVxs0+fGlqdZW0yVoog5Y+ZK5g0aS9ngjQExDmva16Rob+dI85EaBtZK8frn97rv+nKdXiylYnw9N77Uty/P+Od2wXdkd9c6kcsfRBU/9dfx90W6rDQwLiiCXTTO9x/Y1zeeV6apsnVOTLET/90XG/k6fXAfzKc0/jfmuek8FLpptY7DJ3dYWMnH+9+U77OjBwY7HbuUe5z7H7ME2iR1rs1pMD9gSyJt29id3uvIrdbjR2O2tq7HaePxCx21l9J1I8aSh2N6bB2N0cLqXCGu7lr4PwBkNDPfO9oXG44+5ZflsfAI2rTMqQg51dS7XoPrbeEkvqP1nWVMRuYndMx24R04Gqm5bXbOSEc6TEbkQWkudwoZexKnvP0KO//IVJVg1c/pjLj5QmPNvvmWMO8PKdenl54p540oNZ7cWmva3mbnDdsVidWXPg2X+VvZ71U7J9f5503PV5neSBcw8lk9h0+xF1vrTT/fd1n9MlwrXzWLJ+T7ZJCnbe8Z9634/9kubKw9cK/bjZ9WA4Ry8pfu+X5v8pP71Qp330UnQ9u2wfFFV7iB399bkyYsHvpO3++V7VBdPk7on/OVo6LHzE3HcfGHLQskfMpa7Or23v+aUH3PaEiF4CZQ7MnQ4kW5TX7X24UmuvuzVifQOA2hMBzpeIOxvx4y3Sce8cOWLJA7Lmq9dl+KI7ZMKXZ5rH9KqIjnu+NicDDmRny+hvp0qvdX93tJtRXWUS787GfnOpNESTBf02/kOO/XySo+6/9tgf/PMDLtvVqPk3yIAVT5jexsd9dpJjerdtH5hk8MClDzt6YA9fcKv03PSGY572md+agS31agt9HWd6//h3h5hEl667c0LbnghLy1lVe9+prd1rqduT3P1WPi2jvvtNvQlglZ5Tm9xXmtDXHvGelqt1GjWx7u7I735t/rbK32zaatii22XMvKukx+a3zRUsmrTXEwF6AkLLw/Tc9Kbjuad8NMyMA5CWs1LGzblQBq58os7y46rLJLmkpi65GrrwD9J/9V8kqTRLhi66s973pr8Pui0567TzU5k48yjpuOsLcym+s5ra+LXtqlfEnPTJaLPO7rpt+1C67phZ72sD/lae1Kbex7pveUeO++xkGfPNZWZQW/297rr1A+mw9xvzndYrJDRxpgfrnXZ+5tXreRO766yjF7Hb21IJ9dVGbnLs9qL3dmOxW3sF2w8WtRe+N7HbXVNrejrzKXY3wsRuN02N3c4a6kGt47U4c8TuJjA96wMwiHmcU51zyxYf0DqqenLfXvqrMT02/UuGLbi10Q4B7lqUZps4PHLBbdKyuPaqsUDT8nSj510tvdb9w+Pj+r51Hk90f2LI4nvM/kFz6VWXGv91X8qgFz+CaPkJ/5Rd/a+oM/2E/x1n4rIeU+oxh3271OTfhC8m1+kg4g1iN7E7pmN3ZYm5Mls7RbVz6xAVNjXQo1xK4U6Z8MUU6bnhNYlFCaFeAYQvDfh23be+Z277ep0tqQXbJf3wzu73Z30nZamd6z7ZrSdchw3vSFWLVlKRlCG75FhTE9RO6w+3ytsomd1Pd0zTOsjm74ZXpTy5gwxc8Zi5P7vlRpfl6k754KUPSZcd/5GsbqdJScvusqfvhVKc1r/OgBZ6yfTATjWX1+3MLpb0lBZmR0ZrKusO95x1Ij02/sskBfWW2eucBg/6k1e/J8P2z5e1Yx8xB6P2wy/LHNy6HZwe3mFKLD1o2sCKa+E48NUeYp0Oz9bmwM+Sc7gHg73Xmx5EJZTnS3lKB8fiNLnbKO29X7BV2u/7Vvb0vUSqWrR0eqhmfTYfvizduXdzdVyLOouK2/y1TPr+OvP/2RdtcK31bT7Dzaa39N4+F5j3Zl9//XxO+uRIc/+b81dKQkXtwCKpBdvqJDjtkkv2y945z0jf/T9Iu/0/mPIjBRmDJbvLieYA0b0HcdqhNabEypCf7pWs7pMlt92R0mvja1KZ0FLWHvW4lCdlyLAtNduU/uB/d85CGf/1eea+btd28VUl5nn16bn5LXOJ5tbht5kTAO4nLBq7TFwTXUf8fH+dx075cKjLffv2btZv89smeeac5Na27LO+5mC167aPpCzVvgU1T7ss13Iofde84HJfE3gN0fIw7hLLc2Xc7AvrfY697rrj/s7a+2m5a6X34ffpjeELbzd/Ryy4tc5juo1UJKY77mtJHfs6662odd8Glz1oyYNyqNMEkcG/FInjvDP8K7vzCbK/+xTp1EDP0TYHl5ibDmzrLK66wlF2bfjC38v+njUnI/XEmhWf6PvKWJbEVZVKdUKKy8GHxm3n2O0LjXNNUW/sdqJ1u71hj93ONbM1drdd/bp02/RfWTVhhqzaXTf+uXOO3Z54qsXubtmeAslIr/098pZ77G5MU+qDe7P+DVm5q+HPOv3gEjnqm8tk5YTnJKtH7X5fMOlJW3HZZ2uempPaNilP6egyXb+DJ380XCpapMn3Z/8g1fFJHp+v+1DFrXo69iPy2o2WXQOulk67Ppfi1n2koM2QOgevGQeXSGbPX4gVlyApTgnztKJtUiKu8/vKjL1iVUtVYmuPCf4em96SRZM+lj7rXzb7DXrbccR1HkqfjTT/n3veMpd9UHXU7IskqSxbum7/WGZf7Lpvr7Sjgv4Oac/exmhZuoTKYtkw6j7Z0/diOfnjUfXurwKBsHHkvebY0ZNhhzuCFKQPktwOR0mPzf93eLs90/wO6j7rygkzJKtHQ+UVfRMLsdv5HJk360nsbl7sDgc6tpy981fL/C2S3WWihAWz31wi1QmpjvsmF2Rr/HhRO3HpFc9Lu9V0vAwU3fdqmb/N5GqaExcH//yAtCzYKgNXPC47B/1KYg3Jc/jEPdGlg/FpslUHHj3Q/TST5M3qPkW6b3HdgRiy5AHH/3cOuEo2jr7f9JTRRKS9/vBwqUl8/XTS2/UmEvXHaNT3v5GylE6y/sgH5ZgvJtcM0ml6zX9l/mry89tzFkpFUltTXsKSOMltP8bUI3UelEoDrekFffh5C0+dKamF2x2P6yXx2pOgpGUPqUpIlXb755sf6h0Df2UOgLQ0hSpu2VPmJtwmLn2NnSN6dZXpGagJDpWfMUSWH/+KxFcWSUrRbsnpdKxj1pTCHSbhrCcalF7ypz0X1PLj/i4Hu55Ub48a9x7Ivde9bHrw1rTh4+bgpf2+uXKo49Gye/kKmTDvLtl+xPWyr9c5ptyInR6A6GtoUrYwfYDktx1uehjXruNOKWndy5TrSC3cZZK79mR2QkWB7Bh8bU3SJi7BkThX2gbOWhZsk7Jk1wNNZ62cemT0X/Ws+Zvb/kjJOOjay95OS6w4n3ixm/jfo6WodR+XJPaJM8dKU/Vd9zdplV/3QM9bWlrFF/rZuXNuS/dEmj/1W+uaPA+FdlpKxw/cr85wpzsCDemx5d/mJh3iREYHdgcHMcgWJ6uO+avs3fedjP7+N81a1HGfTpTkw2WmKhNSZd75y03Pt8TSbNnf4wyT1Cpt1aPe50/6YJD5u3LCXyWrxxRpUZojVly8VDqdfPJKdZUMWvawFKYPkj39a8pANYWn2O0vc9dnyaQFNb+heiJ+9finpdfmtyW78/FSmFFb2qqpGjyBoSetDx9YaRsPWPmUZPY6y2WfwN1Gp3I7zolb/bzz29UkDANFE7w6fsTufpeZRKiuc2Via8cJc29p4lxpwmh2E5Pnus+iHQu0g0CbA4tld7/LpTo+2esDwgSn3tD2K720bFt5ckcpSnftfOEupWC7uRpzT79LpDouyZzY15PaSvezUop2mX3GklY9HaXFWlTkS+tDqyWv/Rizn6xX+Onjqt+qv0ifdS+5vIbua3bYO9ucDFOaXNZkcvt930he21Hmaruk0oMydPHdMvfcJdIqt3afpCquJkGvPV21k0BOx6Nl6Yn/MuXwOu36woyvoMl8/dy6b/4/qUpoKdldTjBtqiWitDOFfZyVpRNfl17rXzWdGJQmpwctf9T8f+SPN3m+Ykbb02aT1IIdjkn9Vv/F7PfbH9PEvCbOPX42ZbmmvexX8H13tn4u7c3+sGVLkIrktnWfc7i0pHY0qIpPcUzvsv0T2dfncMk5IIC8OVHdOm+DuTmzd/YYseA2md1tsvn+dd75P/P7oIl2X2i5Sd3mdw642uOJr2ALdOzW4+VuO/4re/teJLnNG5Ii4DzF7kijV073Wfc32dfrXMlvV3NitDl0X9TX/QfXq7JsTeq57u2+gl5RpeVV14x7UqoTkj3PdHj/wb7fvPSE1yWn0wQZ+83lklyyT344Y3btezwc/zTGJRfvlcKMI6RFWY6j49mWtHEi6TXf+aGL/iBFrfvJ9iE3iL/Y973KktuZ/XIt9VvfSWYdj00rAWwdckud9556+Ap+5/fkfoJdq1OsmvBcoye/db9L96c2jbzHtNvx/zvBHLcsOKMmNxeObJa9Gwsc8vPzJT09XfLy8iQtLa1ZLfP1mn2Sm5dnehjZvDj75M/e4rEur80wST+02nFfDz5a5a6rGYRR68aNuEsGrHzSL6/17dkLZOJ/J3h8bMvQ30m/NX+t97lLT3jNlLxwVprS2fSItyfc7dYc9bgjad8cVfFJEn84AGV1PUW2DblRxs++wPH4xpF3y8AVdUtseMP+fqvik10GbWzM+tEPyOBlDzfpNYGgGTBZ5IrawWWrq6slKytLOnbsKHFe9kj3Z4xBdMTuUMRx7QWnJ4zz246QNgd+koWn/cfsFDuXQ1p2/CvmSic9Qf7d2QukIqmNKbOgCThN0umBhSmvVF1petYe8+WZ5kRURYvWsnHUHx3xSnfOO+7+QlqU58uefpeasRTsJaH0hLomCnI6TjAnq/XkdM+Nb0hJy65yoNtpHg9y9ICj/d55kt35WClPqbnyRq8+0ucWpvWv7f3jwbCFt5vB05ec+C9zMtne3gUZR0hmjzNkwKpnatbZuTes/Wq6ONcSH+32fWeuuto65OY6yZNT3h9kkpB6ddrevhc7DjT0n+xaLKcuvMrxOnqyXsvw1HldL5z00QgTa1cc87wc6D65TjJFS5BtGHW/7BpY83rOBi57RHpu+pcsPuWDOgfDpiTHd7+RLcNvc2mn3X0vlh2Dr3MkN2dfuE467PtGRv5wkyw/9iU52O2UmrFyqitl14Arzeeny0osy5FuW96R3hv+6XiN+Wd+I6Utu0uLskM1VwbZ4sxg61omLK/tCEkoz5UDpXHSs2qntM+cb/ZVWuVtkKO/OrvOe9H59cSDntDX5KvK6TDejO3j/P5Mx4LDJ+TtnPcH14+eJoOX/cnsw+S1GyW7+v/SnFixd9Twlh4A2pO6drntRknG4UHCted22/0/yoBVWlLMvzYNv8OxHQfLvp5nS3FaX+m3eoYUt+ole/pc5PV729v7PMe4L56sG/Mnc5m+fZ+54+6vzNUD68Y+Yk4KakceO/d9+4NdJsqKY/8mpwzr7rJMYnf4iJbYrSVEtcRjIOwccI0pFbl63JNmbKR9vc8zHdD0WLE8qZ35nXXed9A40n3T/5kYvXZc3U44qvXBZZK6c65kjvqdJFYUSLet78mOQb82J6mG/HSflKV0lC3DbjucsLTM1WhGdZWJ83rFZmrhNilp1cvnJKg/HPe/482VyvobveHIaebq8dwOY6SgjevVvE1JsGrntqL0AS7TLavabFuD874TKy7JdC7QttETFnr1u6cTe42dXNcxp/LbDKuzb9FcrXNWmauW7J3xnJOcuq+kJ3E1Vvti6MI7pMvO/7nsp9R0lmtRZz/N3lYev4eWVbPvsfktOdR+rCw98U2z/6NjWe0acJUklWRKcVo/j50PWueslvGHx+DaNPwP5oonHSdLaaLZPSGv5bz0quS55y01+2rOnQEze5wunXd9Yf4/54LVklK0U5KL95urwIb+dK85Ma82jL5fdvW/0lwJVpraRfLaH2k6ErqXaPUkq9skWTf2zzLxP+M9Pq4VE3Rbs5t7ziI5yWnen05+TyoSW8uAlU+b75vu67XM32yS31pyTjuM6vajvwPaiUI7tGruaNGpn5iT933WvWyWU5jWT1odHk+uskUr0+4d9s0z9xdM/tx0GtB9L3PSrbpKJn14hHlMl7dh9AMm/q4a/4ykHVolvTbWlqxddfSzsr/nWeazOuG/E8zVcKajmdnfGW1irz0/9s0Fq8x82rlAr/TX9bS3S7UtXpad8JoZ08wet9cc9YT5Tk0a0imsYjfJ8ygL4iN+uNnRkxoA4GdxCSLTssMmiCP6DsB151LHC0CNJRPflNLUrmbgYj1I+Onkd71uHz3A04GodTwNTxo6Ia2J3fTs5Y5yUJYtzhyk68FOTc/iXjJm3pWO+ff0udCMl6AJ0qUT33CUjtATD9+es8gxWHJJShdJKdnX4DrroO3a63jTiD+YHon2Xr+7Bl5jThyYJEHHo8wJh0lOgz9rW/Xa8E8zZoSWL7MfxLhbPf4pRymB2rZ4zBwwKk0EeLsvqVeQ6evZ7ex/pTko9lZWt1NNDycgoK6bJ9J1tOMusTt8REvsVjpOU7BPXHnD+TffOWmoCtMGSKt8z/XX9Qrs+srReKJXfmhizH7Fi+qz5kUTI9aPeUiGLbhNOu/63ExfMFnHaLGZskvONEE5/6xvTSI0vrLYJJg15qZlrzQnNrcNvk62jPiDy8mCLUNvNQOsq9kXrZcWZbmm7KMmFQ91OEr29zjTpXSUjq+kZSL1ypbKhFamU4CexNdStPblaixfctLbpoyVlofd2/tckd1L5KSfa8o+6onxIU6lOO0JZU0Ca+Jajf7uV6bTweqja07Y6rL0JL9enW1/nZLUrvLDWfPMvp9eeaBJ0TYHFjk6GOiJSXtJyx9O/8p8jvYxrQ50OVFWHPeyOdGtV8h/94vvzT6LdohQeuJcy1/ZT2QunvSho5SmJjb1CqW+a180978/61vHyR89aVKW1M5cfa77NfZSQ3Z6JbheqaflPPVkqZ7gtCc+q+ISa8rFFudIn72feezQ6Au94r+hkqqIDiWp3VxK0KlqW4LETXe9Si3UsZvkeZQFce0Bpj/wAIAAeTAvbII4ovMAXAfl7rzrM1Nmpcv2maakV2rRrqCvBwBEDWJ3WIqm2K30BKeWDrWXJRjz7TUhWQ8AiHRWajux3bU1bI67GfUMAAAgjOzv9QvTmyiz19mybOJr8tMptaWCAABAeLInztWhTseYclYN0fFFAAB12Yo9j48SKmGRPH/xxReld+/ekpycLOPHj5fFi2tqDNXngw8+kMGDB5v5hw8fLp9/XnP5j52WcZ82bZp06dJFUlJSZNKkSbJpk+fLkaKNXh5s5zxIop3WxAQANPE3NsW3mobRjNgdPBXJ7UxNcmd6ibDWBVT5bYaa+0tPqK0nrbYecWMQ1xJAMC5t9lZ5YsODdcUSq6fncYliEbE7uLS2tNZntpf/0lit9X+1lMXKCc+Z2tlzLlxraiurA11PNqW+DrUfI1uG1o5BorTuMICm2999iuRnDPE5v7Zg8qcNzqPjpTRk4Wk1pXecSyJpuSF3WhJnycTauuLFLbs7xuXZ2/sCn9fbvSRSpLFuXCjhJORlW9577z256qqr5OWXXzaJ8xkzZpjk+IYNG0x3fHc//vijnHDCCfLYY4/JWWedJf/+97/liSeekKVLl8qwYTU1MPW+Pv7mm29Knz595IEHHpBVq1bJ2rVrTcI9mi8f09FtR/1QMzLvnAvXyCkfug6aoQG7scHIdGCl4QtulZTivS4DMbXK22TqmAFAzDrhLpGT/xg2l4+FCrE7NJKKM6Xb1vdld79LpTylZh/JMcjPYTqA1fAFt0leu5Gy/Yia2pyetNs7V6rjkyW3w1gz0JAOfqm72tmdjzcDibbLnG8Gk1RaF1SXqQMo6QBBhzqMk14bXpVdA66WkpRO0nXpM5LQuqPpKa/1Se2DYP9wxmwzqFmL8lzpuvUD2d/zTDNQVHlyB1l71KPSMn+LqUk6av71dWpb6mClFYkZMm7OReb+tiOudwx+5InWHNeTCSN/vEX29TpH2mQtkOSS2lrc7nRg7uSSzHofX3X0X0zdcecDmoyDS8UXa8f+WYb8XPt70RzZnY4zNU2bQj+/E/57jPm/DopqrznrzcDelQktJaGyyKvX2d/9dOm0u7aWrtbW1UFg+6z/h7lf3LKHV+WHnOvX+iq74wRpl7Wg5vVa9TL7tPZ68+70QFRLLHTYN9fc3z7oWkksPSDpOStl46h7pfuWd6XD3jkuz1l+3MuSmr/NDIaaUFkoR/z0RzPAqbblkhPfkjir0gwgN2DlU46ByHQwNedBzHRgwV7rX3XUhtdkmQ6YpvVpszsfI+33fisDV9YdtF237+XHvyJdtn0s6dlLZevQW6U8pYN02PO1ef3kor2yPuMEyWjdUqoT0xy/GWU6qK7bgG5tshZJav4W8z1OLdpdO7CtZUlazgozqFhx636O57XM2yTdtn4gB7ucIDmdjxNbdaWc8mFNAuLHKbMkqWS/o+btvHN/MgN5jp17maw6eoYZuEzr728ffK1sHn6HJFQUysT/jDO1fVce87zj+3+w8wmyacSd5rPvuGe2bBj1RznQ7RQz9kDvdX83A4R23D3LMeis1taNry73+NmuGfe47Ot1nnTe+V9Jy1klPS/9i0h8guNxYjfH3UFlWWawYx30z30QxOYvu9oMtmz/vrfKXSclrXqYAcAPdj3ZDByt35udA39lvs/2gRh1UEfZtVBSMzpJSeu+5vlddnwi+W2G1w6WaVmSUrTL/I63KD8krQ+tNQMz238Xhv94q/nNX3Hsi+Z5mifQAUy1RvnQRXdI60PrZOWxL5hBnm36eocHDuy++d9SlNZHCjKGSMuCbZLbfox03vk/U59cB2N0LnWjAyB33/KOyUto/No84k4zELY9oaiDn3fdMdPcr/mN+YOMm32+5HQ6xoyTor+b+hvTNqs2Cae1w3WZvTa+7hiwMLfDUWaen0/8PzNY9JhvrzIxXwcp7rBndu1AiG1HSuu8DY7YqWON2H/77J0XD3Y5SXI6jje1zfX3q9+ams6LpSkdJbvzROm27QOXj1DHU9G2rUpIMe2nNc51wMWfT3nPfKbVcYmmdvqgZQ+bE6h57UeZ9hw79wrHMrTzhL1OuiaHfz7532YA+PaZ35t9EU0aj599ntkunG0cebepUX7SJ0ea+3PPXWLWW7eplILtZh+uPLm9jPzhBjO45YIpX5g42Xnn55Ld6RhTYz25eK/ZT9Dck8aC9nu/kcHLHpE9vc+TPf0uk1Z5myW3/WgTFyoTW5vPv/vW98zr6XqlFmyTNeOfNLGqz9qX5UDXk8znobXf+62aIRtG/1HaZf4ghekDzLrpmC7a/rpd6+Dk+3ucbp6rNdx1XRMqCkxM1ZrwOmZOpQ5Ibuc+CL0OCO82YKunwUqd6XdM45iuY2JJltmntS9Xa/XrZ5NYetDUm2+7f4HZ99XPzwzcqoPGu+UEE4v2yP6KVK/zhVo7v23Wj+a7rYN0agebht6PO90H0fFq7POl5m82fap10G/9PdF11s+rOiG1zvJSCneaMQKyuk82+zW6L2C2FzPYbqkZeFg/Dz1G0eMRnb8orb/EVxZJauEOs9+v66yxuW3mD+ZzK8wYJCmFu8w4BUtO+j+XQX8ZMNSNJsyPOuooeeGFF2o+7+pq6dGjh9xyyy1yzz11B3G65JJLpKioSD79tPbsz9FHHy2jRo0yCXg9F9C1a1e544475A9/qDnLqwmKTp06yRtvvCGXXnppnWWWlZWZm3NiQ9fh0KFDzU+er800r6+Jkjj3L2sgWJb5MhW36i2lLbvJiTOPkhYVBeahlUf/xWzMOtJw+8zvzBnt1eOekJ6b3pJem950DFqhg2TpSNOnfFIzsM7aMQ+ZH1U7DW7lSW1NINUfh2NnTTHTs7qeYkbl7bx7lpSmdJJlx71sRgTvvPMzye58nPni6E7DyZ+MdjlY0wOz5ce9JCn522To0ulm2jfn/mwGKBmw+i/m/g9TvqgZ8GLlM5LZ8ywZ5jTA176eZ8nqcU/J8EV3OA4I9UybTX+cnJtG4sQm1bKn9/nSbfvH9fbS0R+B+WfOlq7bZ5qD65ELawbragpdt/b7vpMWFfmOaZuG3SYZB5dJh8xvHUFWzzCe4DRCu7b5kCU1bbFu9APmR3nkgt8dbq9USagsFn/w1E52GnjTctc67m894nozqMyIRXeYnQw9e6kHXCqnw3hpe2CRBIruqGgw7Hj4IFbvbx5+uxnkpHXuBmlRkedYx74NJFd8sa/HmdJlV81AJ55kdzxG2mX9aP6//Ni/SbvM76XHlnfqJAh29btc9vY6R/qvnuE4oHd2sNNxsmXYrSYI91n3N7ODkVh+yDymO4S6g2b/bu7pe7EZubvDnjmyr/e5LtuMM91Z2DrkJjliyXSXz9DZ7AtWyejvf2vew+KT/m0O+MfOu8o8ltl9iuxP6S/9Mr+Qg11PNKOy7+8xRarjksz77Lv+77Jh5D1SlNbP7HzqOqcWue6MOdsy5EbZNvh6aVm4TSZ8dY6ZVp6YLjsG/VoGrKoZREfldBgnbQ+Pbq62Dv6tCeSaZNCdDufH3FXbWkhFYprs7X2+VMcnSpsDP5ttUttw8SnvS68Nr0n/JiZjth5xg/RdV3PZbfXF/ycy+Mza162ulgMHDkiHDh18Sp63adMmopPnxG7YVVtWnf0crdGeUFEkBW2GNCkBUB89oNGEfnbnY6Uw44hGF6kHeB13f232QfQ3JKE8zxxIORINJfulVd5Gk5jWA58em94yB+ErJjwnpYd7+3hd4zaxTd2DssPrrPsAGsNUQkmWHChLNO2VlrfRJBv0oEITEnrQpQcXRU5JS3c6b1VC7cBnqlXuerN8+2s0yqo6fPFp7UGcHuBre2iMSc+uSZ7qb7zYDh80eTjoa1F2yJz80P07X+l+pi7PHJx5u23pOthsEl9ReLgNdJ1q2kkT2VVxSeaAVw9m9XPUkygmcdxoe1jmvXtKMoeCrbpceq9/1ZzY0hNVNdNqD1B9+S5693qNLzuc6OevB+WaMEgu2i2tc9eb7SGn0wTTdpatJvHj7JQjXLcDYjfH3bGuqb8XTXb49zsQ4iqLTXK9KbEobNsrgtFWtJe/hFvsDmnP8/LycklNTZUPP/xQzj33XMf0q6++WnJzc+U//6k78GXPnj3l9ttvl9tuq01oTp8+XWbOnCkrVqyQrVu3Sr9+/WTZsmUmoW43ceJEc/+55+omTx588EF56KGH6kzfuHGjtG5d25urKb7bfEiKioukZWpLscUF/4dWzwIml2VLYWoPR8CKryyRDoeWSVbbMWbEZ9Xu0Arpv+tDWd3/eik6fEmoHuzZLMskufwdDFsXbpPB2/4lG3tfLnmtD5/drqyQI1dOk6KMwbKhb80Z3A45SySuulz2t5/g02trov3olfdLammWbOv2C9nS8yLHgbkeJHTf/4303T3TPLaz6+mNvg9z5qwsS4pSujqqHSWV55iRqFVK6X5pXbRDstoeJcllByWxskDa5q2R7d1+YR5vVbRTKhJaiWWzSbkeYHvQNneVHLH1DVk94LeS13qgWR8z6vbhA5oRG56TxIo8+XnoA5Jauk9Si/bKjqQBkp4UZ87i2ukBZI/MOXKgzWgpTuks7Q8tl0Npg+SIrW9KUUqXw21RJa2K9zi2Cx3NvGVpphy77E5pVbJbZh37nhS07G3WYdT6Z8wJjtUDaq5ocKYnZipaOH1HrCoZs/YJSSnNkh9GPy0tKgslrXCrDNn6TylJ6ig/DZsmU37QXoSWzBv7sjnZ0rJkj0xaVNNLcf6op0wbts1fI3mt+km3rHmyt8MJjna2v4bjYN7tM7Jvz312fyLtclfJ8sG3m1HUrWqr5nuYkiq2+JrPT9/z+d+cJJntxsvCEY9IRUJrk8Q4Y/75kp0xQn4c9aR0zP5JRq1/VlYMulUOZoyQjIKNklhZKNnpw6UioaWMWfuY5LXuL5t6XXZ43aqlddF2KWjZx/O25OV3Jamspr5XWWJb8xpV8UmyfPAdHpZXLUnlh+Tsb2tGqv/s+JlSnFJ7SZa2w9i1j5v/f3DaItN2iRWFjX6nHe3l4++WOQA3B6y2+t+nVW1+f/Jb9pGypLaSUpIpozb8RbZ2P7fme25ZMmLjX6U4ubNs7nVJnedqLzPtYdcud6X5feh6YL5s6HW57Ol8incraVVJ/50fSvesufLjyMfM91FPXIxd+5gUpnY327n+5nTN+tZ83lu7nyfFKV3NtqCfbdeJv3F5bxrEHTvTXgbxgoICGThwYMQmz4nd8MfvRayivWgrtq3gO76vawkbYjfH3bGOWER7sW2FB76LkRO7Q9rN4ODBg1JVVWV6hTvT++vXr/f4nMzMTI/z63T74/Zp9c3j7t577zUJefee53pGo7kNfH779j6fHQmOkW73tZTLReJ9P6vm0tebLD3dzyQN+Jv06tBBhjnaquESMw06tqa2lJ5CqT2NYqe94W4W7aN1lPiDrufxh/8/6PDfKTLG5XFvlnGBdK7v4aNfNH96HX4Nba/B9W5bNZde1agpZyTH17zT2rbw0Gtv0hTRi+pOc5424R8u76pRE2rqdJ3vmKC9pmqu+DCf99ErTPL8TKdeQdWTzzN/ay4qd94+x7u8E+/d7dRW9Z+lrD7ukGjhg7Odn3rsFulis0lNVbGBImdeIcc5HnTbko6pueR6hMvEweJXh9uzXwOzVPeYKVJdIaf3d+uJXv0HqR7YS6TzSLmgo/ffpaac1fWNcxsNFDnpBNHTUg4TXvT4K+VK38+F5n9H+/ryEx4QkQek5tTWYcd/4LadD3O7P7DetrLZbD61lTflw8IZsRvB/b2ILrQXbcW2FXrE7locd8cmYhHtxbYVHvguRk7sjpxr9AIoKSnJ3NzpB+KPA0H9gP21rGhHW9FebFtN0L+m9l8d+psz6nK+i2H2u0Us8A9id/ggdtNebFvhge9i4NqK2O0fxO7wwe8F7cW2FR74LkZG7A5pNrd9+/YSHx8v+/fvd5mu9zt39tz/Vqc3NL/9ry/LBAAAxG4AAKIRx90AAERo8jwxMVHGjBkjc+bMcemKr/cnTPBc41qnO8+vvv76a8f8ffr0MUly53m0DMuiRYvqXSYAACB2AwAQjTjuBgAggsu2aK1xHSB07NixMm7cOJkxY4YUFRXJ1KlTzeNXXXWVdOvWTR577DFz/9ZbbzWDfz7zzDNy5plnyrvvvis///yz/OMf/3B049fBRB955BEZMGCASaY/8MAD0rVrV5dBSQEAALEbAIBYwHE3AAARmjy/5JJLzEBT06ZNMwN6jho1SmbNmuUY8HPnzp0udWqOOeYY+fe//y3333+/3HfffSZBPnPmTBk27PCgiCJy1113mQT8ddddJ7m5uXLccceZZUb6IG0AAIQDYjcAAJGF2A0AQNPYLMuymvjcqKVlXtLT0yUvL0/S0tKatSwtQ5OVlSUdO3ZkoBnayq/YtmirQGHbCmxb+TPGIDDtyneAtgoUti3aim0r9Ijd4YPYHRrEItqLbSs88F2MnNgd0prnAAAAAAAAAACEI5LnAAAAAAAAAAC4IXkOAAAAAAAAAIAbkucAAAAAAAAAALhJcJ8AEfsYqlpc3h9F7QsKCiQ5OZkBQ2krv2Lboq0ChW0rsG1ljy2M1+1fxO7Q4PeC9mLbCg98FwPbVsTuwCB2hwa/F7QX21Z44LsYObGb5LkH+oGoHj16NLuBAQCoL9bo6N/wD2I3ACDQiN3+b0/FcTcAIJxjt82i65vHMxp79+6V1q1bi81ma1YD65kO3RnYtWuXpKWlNWtZ0Y62or3YtsID38XAtpWGXQ3gXbt25YokPyJ2hwa/F7QX21Z44LsY2LYidgcGsTs0+L2gvdi2wgPfxciJ3fQ890AbtXv37uJP+uGSPKetAoFti7YKFLatwLUVPc79j9gdWvxe0F5sW+GB72Lg2orY7X/E7tDi94L2YtsKD3wXwz92M2AoAAAAAAAAAAAkzwEAAAAAAAAAaBg9zwMsKSlJpk+fbv6CtmLbCg2+h7QX2xb4zeD3NRwQj2grtq3Q43sYnfhcaSu2rdDje0h7Reu2xYChAAAAAAAAAAC4oec5AAAAAAAAAABuSJ4DAAAAAAAAAOCG5DkAAAAAAAAAAG5IngMAAAAAAAAA4IbkeQC9+OKL0rt3b0lOTpbx48fL4sWLJdo9+OCDYrPZXG6DBw92PF5aWio33XSTtGvXTlq1aiUXXHCB7N+/32UZO3fulDPPPFNSU1OlY8eOcuedd0plZaXLPPPmzZMjjzzSjLTbv39/eeONNyTcfffdd/KLX/xCunbtatpl5syZLo9bliXTpk2TLl26SEpKikyaNEk2bdrkMk9OTo5cccUVkpaWJhkZGfLrX/9aCgsLXeZZuXKlHH/88Wa769Gjhzz55JN11uWDDz4wn4vOM3z4cPn8888l0trrmmuuqbOtTZkyJSbb67HHHpOjjjpKWrdubb4z5557rmzYsMFlnmB+98L5t8+btjrxxBPrbFvXX399zLVVrIrFz4TYXT9it2+I3d4jdvu3rYjdsY3YzXG3M2K3b4jd3iN2x3DsthAQ7777rpWYmGi99tpr1po1a6xrr73WysjIsPbv3x/VLT59+nRr6NCh1r59+xy3AwcOOB6//vrrrR49elhz5syxfv75Z+voo4+2jjnmGMfjlZWV1rBhw6xJkyZZy5Ytsz7//HOrffv21r333uuYZ+vWrVZqaqp1++23W2vXrrWef/55Kz4+3po1a5YVzvS9/PGPf7Q+/vhjS796n3zyicvjjz/+uJWenm7NnDnTWrFihXX22Wdbffr0sUpKShzzTJkyxRo5cqS1cOFC6/vvv7f69+9vXXbZZY7H8/LyrE6dOllXXHGFtXr1auudd96xUlJSrL///e+OeX744QfTXk8++aRpv/vvv99q0aKFtWrVKiuS2uvqq6827eG8reXk5LjMEyvtNXnyZOv1118372H58uXWGWecYfXs2dMqLCwM+ncv3H/7vGmriRMnmvV23rZ0W4m1topFsfqZELvrR+z2DbHbe8Ru/7YVsTt2Ebs57nZH7PYNsdt7xO7Yjd0kzwNk3Lhx1k033eS4X1VVZXXt2tV67LHHrGg/ANdkpSe5ubkm6fjBBx84pq1bt84kRhcsWGDu65chLi7OyszMdMzz0ksvWWlpaVZZWZm5f9ddd5kEvbNLLrnEfDkjhXsyuLq62urcubP11FNPubRXUlKSSegq/SHQ5/3000+Oeb744gvLZrNZe/bsMff/9re/WW3atHG0lbr77rutQYMGOe5ffPHF1plnnumyPuPHj7d++9vfWuGqvuT5OeecU+9zYrm9srKyzHv/9ttvg/7di7TfPve2sgfxW2+9td7nxGpbxYJY/UyI3d4hdvuG2O0bYnfT20oRu2MXsbsujrtrEbt9Q+z2DbE7dmI3ZVsCoLy8XJYsWWLKbtjFxcWZ+wsWLJBop6VGtNRG3759TckMvcxCaZtUVFS4tIuWwujZs6ejXfSvlsXo1KmTY57JkydLfn6+rFmzxjGP8zLs80Ry227btk0yMzNd3ld6erq5nMS5bbT0yNixYx3z6Py6bS1atMgxzwknnCCJiYkubaOXxxw6dCjq2k8vz9FLdwYNGiQ33HCDZGdnOx6L5fbKy8szf9u2bRvU714k/va5t5Xd22+/Le3bt5dhw4bJvffeK8XFxY7HYrWtol2sfybEbt8Ru5uG2O0Zsdt7xG7YEbs57vYVsbtpiN3exSOOu6M3did4PSe8dvDgQamqqnL5gJXeX79+fVS3pCZ7tb6QJjP37dsnDz30kKknvXr1apMc1iSlJjTd20UfU/rXU7vZH2toHv0ClZSUmHrhkcb+3jy9L+f3rYliZwkJCebHx3mePn361FmG/bE2bdrU2372ZUQKrW9+/vnnm/e7ZcsWue++++T00083P4Dx8fEx217V1dVy2223ybHHHmsCkArWd09POETSb5+ntlKXX3659OrVy5wE1Jr4d999tzmh8vHHH8dsW8UCYjex21fEbt8Ruz0jdnuP2A1nxG5it6+I3b4jdnsfjzjujt7YTfIcfqXJS7sRI0aYZLp+Gd5///2ITGojfF166aWO/+vZSN3e+vXrZ86Kn3LKKRKrdFBQPVk1f/78UK9KxLbVdddd57Jt6SC+uk3pSRrdxoBoQ+xGsBC7PSN2e4/YDdQgdiNYiN2eEbtjK3ZTtiUA9JID7fm6f/9+l+l6v3PnzhJLtKfrwIEDZfPmzea96yUTubm59baL/vXUbvbHGponLS0tYhP09vfW0Dajf7Oyslwe11GGc3Jy/NJ+kb5tapkg/e7pthar7XXzzTfLp59+KnPnzpXu3bs7pgfruxdJv331tZUnehJQOW9bsdRWsYLPpBax2zvE7uYjdhO7fUHshjtidy1it3eI3c1H7CZ2x2LsJnkeAFoeYcyYMTJnzhyXyxT0/oQJEySWFBYWmrNGegZJ26RFixYu7aKXZGhNdHu76N9Vq1a5JD2//vprs+EPGTLEMY/zMuzzRHLbaukQ/eI6vy+9zERrczu3jSY/tV6T3TfffGO2LfuPjM7z3XffmfrWzm2jZXS0BEm0tp/avXu3qXmu21qstZeO7aJB6ZNPPjHv0b0UTbC+e5Hw29dYW3myfPly89d524qFtoo1fCa1iN3eIXY3H7Gb2O0NYjfqQ+yuRez2DrG7+YjdxO6YjN1eDy0Kn7z77rtWUlKS9cYbb1hr1661rrvuOisjI8NllNhodMcdd1jz5s2ztm3bZv3www/WpEmTrPbt25uRddX1119v9ezZ0/rmm2+sn3/+2ZowYYK52VVWVlrDhg2zTjvtNGv58uXWrFmzrA4dOlj33nuvY56tW7daqamp1p133mmtW7fOevHFF634+HgzbzgrKCiwli1bZm761Xv22WfN/3fs2GEef/zxx8028p///MdauXKldc4551h9+vSxSkpKHMuYMmWKNXr0aGvRokXW/PnzrQEDBliXXXaZy8jqnTp1sq688kpr9erVZjvUtvr73//umEc/l4SEBOvpp5827Td9+nSrRYsW1qpVq6xIaS997A9/+IO1YMECs63Nnj3bOvLII017lJaWxlx73XDDDVZ6err57u3bt89xKy4udswTrO9euP/2NdZWmzdvtv70pz+ZNtJtS7+Pffv2tU444YSYa6tYFKufCbG7fsRu3xC7vUfs9l9bEbtjG7Gb4253xG7fELu9R+yO3dhN8jyAnn/+eZOsSkxMtMaNG2ctXLjQinaXXHKJ1aVLF/Oeu3XrZu7rl8JOE8E33nij1aZNG7OBn3feeeYL5Gz79u3W6aefbqWkpJjEux7UV1RUuMwzd+5ca9SoUeZ19Av2+uuvW+FO11mTwO63q6++2jxeXV1tPfDAAyaZq1/sU045xdqwYYPLMrKzs03yt1WrVlZaWpo1depUE+ycrVixwjruuOPMMvQz0KS8u/fff98aOHCgab+hQ4dan332mRVJ7aU/uPoDqj+cmsju1auXde2119b58fv/9u4lpKo1DAPwZ0lkVIRZBBE1qEGEBOUkggiSLiMrSBAhDCcNopk0CLqqA0EIGhZJUIMgukwaFFEURIGTGgRCYpjQoKDSoDLNWD8dyVWd4+lydB2fBxbidrHZ+9fty379/NdUWa/vrVN2fP26+C9fe5P5d98/rVVvb28K7PLy8vQzsXz58hTEb968mXJrNVVNxe+J7P4x2f3vyO7xk92/b61kN7Lb++7xZlHG+27Z/bNk99TN7pIvTwoAAAAAAPjCnucAAAAAAJCjPAcAAAAAgBzlOQAAAAAA5CjPAQAAAAAgR3kOAAAAAAA5ynMAAAAAAMhRngMAAAAAQI7yHAAAAAAAcpTnAAAAAACQozwHxqWhoSG2b99utQCgIGQ3ABSL7IbJR3kOAAAAAAA5ynNgjIsXL0ZlZWWUlZXF/Pnzo7q6OpqamuLs2bNx9erVKCkpScft27fT+c+ePYva2tqYN29elJeXR01NTTx9+vSbv5wfPXo0FixYEHPnzo29e/fG4OCglQeA30B2A0CxyG4ojtKJfgDA5PH8+fOoq6uLtra22LFjRwwMDMTdu3dj9+7d0dvbG/39/dHR0ZHOzYryjx8/xpYtW2LdunXpvNLS0mhubo6tW7fGo0ePYsaMGencmzdvxsyZM1PhnhXre/bsScV8S0vLBD9jACg22Q0AxSK7oViU58CYEB8aGoqdO3fG0qVL023ZFHomm0T/8OFDLFq0aPT8c+fOxadPn+L06dNpGj2TlevZFHpWlG/evDndlpXoZ86ciVmzZsWqVavi2LFjaZr9+PHjMW2af4ABgJ8luwGgWGQ3FIvWChi1evXq2LRpUyrMd+3aFadOnYpXr179cIUePnwYT548iTlz5sTs2bPTkU2kv3//Prq7u8fcb1ac/yWbVH/79m3a8gUA+HmyGwCKRXZDsZg8B0ZNnz49bty4Effu3Yvr16/HyZMn4+DBg/HgwYPvrlJWgK9duzbOnz//zdey/c0BgD9LdgNAschuKBblOTBGtv3K+vXr03Ho0KG0fcvly5fT1ivDw8Njzl2zZk1cuHAhFi5cmC4E+ncT6u/evUtbv2Tu37+fptSXLFli9QHgF8luACgW2Q3FYdsWYFQ2Yd7a2hqdnZ3pAqGXLl2KFy9exMqVK2PZsmXpIqBdXV3x8uXLdLHQ+vr6qKioiJqamnTB0J6enrTX+f79+6Ovr2/0fgcHB6OxsTEeP34c165di8OHD8e+ffvsdw4Av0h2A0CxyG4oFpPnwKhsevzOnTtx4sSJ6O/vT1Pn7e3tsW3btqiqqkrFePYx267l1q1bsXHjxnT+gQMH0kVGBwYGYvHixWnf9K8n0bPPV6xYERs2bEgXHa2rq4sjR45YeQD4RbIbAIpFdkOxlIyMjIxM9IMA/r8aGhri9evXceXKlYl+KADAOMhuACgW2Q1/jm1bAAAAAAAgR3kOAAAAAAA5tm0BAAAAAIAck+cAAAAAAJCjPAcAAAAAgBzlOQAAAAAA5CjPAQAAAAAgR3kOAAAAAAA5ynMAAAAAAMhRngMAAAAAQI7yHAAAAAAAYqzPMf1mcorLvBUAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axes = plt.subplots(1, 3, figsize=(15, 4))\n", + "\n", + "# Get raw data\n", + "col = 'train:loss_tx'\n", + "data = df[col].dropna()\n", + "x = df['step'][:len(data)].values\n", + "y = data.values\n", + "\n", + "# Compare windows\n", + "for ax, w in zip(axes, [5, 15, 25]):\n", + " y_smooth = pd.Series(y).rolling(w, min_periods=1).mean()\n", + " ax.plot(x, y, alpha=0.3, label='Raw', linewidth=0.8)\n", + " ax.plot(x, y_smooth, label=f'Window={w}', linewidth=1.6)\n", + " ax.set_title(f'Window = {w}')\n", + " ax.set_xlabel('step')\n", + " ax.set_ylabel('loss')\n", + " ax.legend()\n", + " ax.grid(True, alpha=0.3)\n", + "\n", + "fig.suptitle('Smoothing Window Effect')\n", + "fig.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Design Notes\n", + "\n", + "**Auto-smoothing:** Window adapts to data length: `max(5, min(25, count // 20))`\n", + "\n", + "**Grouping:** Metrics like `train:loss_tx` and `val:loss_tx` plotted together for easy comparison.\n", + "\n", + "**Step-based:** Uses batch steps (not epochs) for finer granularity.\n", + "\n", + "**Two modes:** \n", + "- matplotlib = High-quality PNG files\n", + "- uniplot = Quick terminal checks (SSH-friendly)\n", + "\n", + "**Color palette:** Tab10 for distinct, colorblind-friendly colors." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Quick Reference\n", + "\n", + "**Healthy training:**\n", + "- All losses decreasing ✓\n", + "- Train/val tracking closely ✓\n", + "- No sharp spikes ✓\n", + "\n", + "**Troubleshooting:**\n", + "- Train↓ Val↑ → Overfitting (reduce model size)\n", + "- Both flat → Underfitting (increase capacity)\n", + "- Spikes → Instability (lower learning rate)\n", + "\n", + "**More info:** `segger plot --help` | `docs/LOSS_FUNCTIONS.md`" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.0" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/spatialdata_io_demo.ipynb b/examples/spatialdata_io_demo.ipynb new file mode 100644 index 0000000..a3321be --- /dev/null +++ b/examples/spatialdata_io_demo.ipynb @@ -0,0 +1,566 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# SpatialData I/O with Segger\n", + "\n", + "This notebook demonstrates how to:\n", + "1. Read spatial transcriptomics data from SpatialData Zarr stores\n", + "2. Run Segger segmentation (simulated)\n", + "3. Export results to SpatialData-compatible Zarr format\n", + "4. Validate compatibility with SOPA workflows\n", + "\n", + "## Setup" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Input/Output Formats (CLI + API)\n", + "\n", + "Segger accepts input in raw platform formats or SpatialData Zarr, and can write multiple output formats:\n", + "\n", + "- **input_format**: `auto` (default), `raw`, `spatialdata`\n", + "- **output_format**: `segger_raw`, `merged`, `spatialdata`, `anndata`, `all`\n", + "\n", + "CLI examples:\n", + "```bash\n", + "segger segment -i /path/to/data -o /path/to/out --input-format raw --output-format segger_raw\n", + "segger segment -i /path/to/experiment.zarr -o /path/to/out --input-format spatialdata --output-format spatialdata\n", + "segger segment -i /path/to/data -o /path/to/out --output-format all\n", + "```\n", + "\n", + "Notes:\n", + "- SpatialData input/output requires `segger[spatialdata]`\n", + "- SpatialData output includes an AnnData table in `sdata.tables[\"cell_table\"]`\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "sys.path.insert(0, '../src')\n", + "\n", + "import polars as pl\n", + "import geopandas as gpd\n", + "import matplotlib.pyplot as plt\n", + "import tempfile\n", + "from pathlib import Path" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Create Sample Data\n", + "\n", + "First, let's create some synthetic Xenium-like data to work with." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from segger.datasets import create_synthetic_xenium\n", + "\n", + "# Create synthetic Xenium data\n", + "transcripts, cells, boundaries = create_synthetic_xenium(\n", + " n_cells=100,\n", + " transcripts_per_cell=30,\n", + " seed=42,\n", + ")\n", + "\n", + "print(f\"Generated {len(transcripts):,} transcripts\")\n", + "print(f\"Generated {len(cells):,} cells\")\n", + "print(f\"Generated {len(boundaries):,} cell boundaries\")\n", + "print(f\"\\nTranscript columns: {transcripts.columns}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Visualize the data\n", + "fig, axes = plt.subplots(1, 2, figsize=(14, 6))\n", + "\n", + "# Plot transcripts\n", + "ax1 = axes[0]\n", + "tx_pd = transcripts.to_pandas()\n", + "ax1.scatter(tx_pd['x_location'], tx_pd['y_location'], s=1, alpha=0.5)\n", + "ax1.set_xlabel('X (microns)')\n", + "ax1.set_ylabel('Y (microns)')\n", + "ax1.set_title('Transcript Positions')\n", + "ax1.set_aspect('equal')\n", + "\n", + "# Plot boundaries\n", + "ax2 = axes[1]\n", + "boundaries.plot(ax=ax2, facecolor='lightblue', edgecolor='navy', alpha=0.5)\n", + "ax2.set_xlabel('X (microns)')\n", + "ax2.set_ylabel('Y (microns)')\n", + "ax2.set_title('Cell Boundaries')\n", + "ax2.set_aspect('equal')\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Write to SpatialData Zarr Format (Lightweight)\n", + "\n", + "Segger includes a lightweight SpatialData writer (`segger.io.spatialdata_zarr`) that creates Zarr stores compatible with the scverse ecosystem and SOPA, without requiring the full `spatialdata` package.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from segger.io.spatialdata_zarr import (\n", + " SpatialDataZarrWriter,\n", + " SpatialDataZarrReader,\n", + " write_spatialdata_zarr,\n", + " read_spatialdata_zarr,\n", + " get_spatialdata_info,\n", + ")\n", + "\n", + "# Create a temporary directory for output\n", + "output_dir = Path(tempfile.mkdtemp())\n", + "zarr_path = output_dir / \"experiment.zarr\"\n", + "\n", + "# Standardize column names\n", + "tx_standard = transcripts.rename({\n", + " 'x_location': 'x',\n", + " 'y_location': 'y',\n", + " 'z_location': 'z',\n", + "})\n", + "\n", + "# Write to SpatialData format\n", + "write_spatialdata_zarr(\n", + " tx_standard,\n", + " zarr_path,\n", + " shapes=boundaries,\n", + " points_key=\"transcripts\",\n", + " shapes_key=\"cells\",\n", + ")\n", + "\n", + "print(f\"Wrote SpatialData to: {zarr_path}\")\n", + "print(f\"\\nStore info: {get_spatialdata_info(zarr_path)}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. Read from SpatialData Zarr Format\n", + "\n", + "The reader can load data from any SpatialData-compatible Zarr store." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Using the class-based reader\n", + "reader = SpatialDataZarrReader(zarr_path)\n", + "\n", + "print(\"Available elements:\")\n", + "print(f\" Points: {reader.points_keys}\")\n", + "print(f\" Shapes: {reader.shapes_keys}\")\n", + "\n", + "# Read data\n", + "tx_loaded = reader.read_points(\"transcripts\")\n", + "shapes_loaded = reader.read_shapes(\"cells\")\n", + "\n", + "print(f\"\\nLoaded {len(tx_loaded):,} transcripts\")\n", + "print(f\"Loaded {len(shapes_loaded):,} cell boundaries\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Or use the convenience function\n", + "tx_loaded, shapes_loaded = read_spatialdata_zarr(zarr_path)\n", + "\n", + "print(f\"Loaded transcripts shape: {tx_loaded.shape}\")\n", + "print(f\"Loaded shapes shape: {shapes_loaded.shape}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4. Simulate Segger Segmentation\n", + "\n", + "Now let's simulate a Segger segmentation run. In practice, you would run:\n", + "```bash\n", + "segger segment -i data/ -o output/\n", + "```\n", + "\n", + "Here we'll use the sample output generator." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from segger.datasets import create_sample_segger_output, create_merged_output\n", + "\n", + "# Generate sample Segger outputs\n", + "tx_data, predictions, cell_boundaries = create_sample_segger_output(\n", + " n_cells=100,\n", + " transcripts_per_cell=30,\n", + " unassigned_rate=0.1, # 10% unassigned\n", + " seed=42,\n", + ")\n", + "\n", + "print(\"Segger Predictions Format:\")\n", + "print(predictions.head())\n", + "\n", + "# Statistics\n", + "n_assigned = (predictions['segger_cell_id'] >= 0).sum()\n", + "n_unassigned = (predictions['segger_cell_id'] < 0).sum()\n", + "print(f\"\\nAssigned: {n_assigned:,} ({100*n_assigned/len(predictions):.1f}%)\")\n", + "print(f\"Unassigned: {n_unassigned:,} ({100*n_unassigned/len(predictions):.1f}%)\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create merged output (transcripts + predictions)\n", + "merged = create_merged_output(tx_data, predictions)\n", + "\n", + "print(\"Merged Output Format:\")\n", + "print(merged.head())\n", + "print(f\"\\nColumns: {merged.columns}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5. Export Segger Results to All Formats\n", + "\n", + "Segger can write multiple outputs from the same predictions:\n", + "- `segger_raw`: predictions parquet\n", + "- `merged`: transcripts + assignments\n", + "- `spatialdata`: SpatialData Zarr (with optional tables)\n", + "- `anndata`: `.h5ad` cell x gene matrix\n", + "\n", + "### 5a. Full export writers (SpatialData + AnnData)\n", + "\n", + "This uses `segger.export` writers. SpatialData output requires `segger[spatialdata]`.\n" + ] + }, + { + "cell_type": "code", + "metadata": {}, + "execution_count": null, + "outputs": [], + "source": [ + "from segger.export import SeggerRawWriter, MergedTranscriptsWriter, AnnDataWriter, SpatialDataWriter\n", + "\n", + "pred_path = SeggerRawWriter().write(\n", + " predictions=predictions,\n", + " output_dir=output_dir,\n", + " output_name=\"predictions.parquet\",\n", + ")\n", + "\n", + "merged_path = MergedTranscriptsWriter().write(\n", + " predictions=predictions,\n", + " output_dir=output_dir,\n", + " transcripts=tx_data,\n", + " output_name=\"transcripts_segmented.parquet\",\n", + ")\n", + "\n", + "ad_path = AnnDataWriter().write(\n", + " predictions=predictions,\n", + " output_dir=output_dir,\n", + " transcripts=tx_data,\n", + " output_name=\"segger_segmentation.h5ad\",\n", + ")\n", + "\n", + "sdata_path = SpatialDataWriter().write(\n", + " predictions=predictions,\n", + " output_dir=output_dir,\n", + " transcripts=tx_data,\n", + " boundaries=cell_boundaries,\n", + " output_name=\"segmentation_full.zarr\",\n", + ")\n", + "\n", + "print(\"Wrote:\")\n", + "print(f\" segger_raw: {pred_path}\")\n", + "print(f\" merged: {merged_path}\")\n", + "print(f\" anndata: {ad_path}\")\n", + "print(f\" spatialdata: {sdata_path}\")\n" + ] + }, + { + "cell_type": "code", + "metadata": {}, + "execution_count": null, + "outputs": [], + "source": [ + "import spatialdata\n", + "\n", + "sdata = spatialdata.read_zarr(sdata_path)\n", + "print(\"SpatialData tables:\", list(sdata.tables.keys()))\n", + "\n", + "# AnnData table with cell x gene counts\n", + "cell_table = sdata.tables[\"cell_table\"]\n", + "cell_table\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5b. Lightweight SpatialData Zarr writer (parquet only)\n", + "\n", + "If you only need a lightweight Zarr store from parquet data, use `segger.io.spatialdata_zarr`.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Export to SpatialData\n", + "segmentation_zarr_light = output_dir / \"segmentation_light.zarr\"\n", + "\n", + "write_spatialdata_zarr(\n", + " merged,\n", + " segmentation_zarr_light,\n", + " shapes=cell_boundaries,\n", + " points_key=\"transcripts\",\n", + " shapes_key=\"cells\",\n", + ")\n", + "\n", + "print(f\"Exported segmentation to: {segmentation_zarr_light}\")\n", + "print(f\"\\nStore info: {get_spatialdata_info(segmentation_zarr_light)}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Verify the export\n", + "reader = SpatialDataZarrReader(segmentation_zarr_light)\n", + "tx_exported = reader.read_points()\n", + "\n", + "print(\"Exported transcripts columns:\")\n", + "print(tx_exported.columns)\n", + "\n", + "# Check segmentation columns are present\n", + "assert 'segger_cell_id' in tx_exported.columns\n", + "assert 'segger_similarity' in tx_exported.columns\n", + "print(\"\\n\u2713 Segmentation columns present in exported SpatialData\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6. Visualize Segmentation Results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Visualize assigned vs unassigned transcripts\n", + "fig, axes = plt.subplots(1, 2, figsize=(14, 6))\n", + "\n", + "merged_pd = merged.to_pandas()\n", + "assigned = merged_pd[merged_pd['segger_cell_id'] >= 0]\n", + "unassigned = merged_pd[merged_pd['segger_cell_id'] < 0]\n", + "\n", + "# Left: All transcripts colored by assignment\n", + "ax1 = axes[0]\n", + "ax1.scatter(assigned['x'], assigned['y'], s=2, c='blue', alpha=0.5, label='Assigned')\n", + "ax1.scatter(unassigned['x'], unassigned['y'], s=5, c='red', alpha=0.8, label='Unassigned')\n", + "ax1.set_xlabel('X (microns)')\n", + "ax1.set_ylabel('Y (microns)')\n", + "ax1.set_title('Transcript Assignment Status')\n", + "ax1.legend()\n", + "ax1.set_aspect('equal')\n", + "\n", + "# Right: Transcripts colored by cell ID\n", + "ax2 = axes[1]\n", + "scatter = ax2.scatter(\n", + " assigned['x'], assigned['y'], \n", + " s=2, \n", + " c=assigned['segger_cell_id'], \n", + " cmap='tab20',\n", + " alpha=0.7\n", + ")\n", + "ax2.set_xlabel('X (microns)')\n", + "ax2.set_ylabel('Y (microns)')\n", + "ax2.set_title('Transcripts by Cell ID')\n", + "ax2.set_aspect('equal')\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Visualize similarity scores\n", + "fig, ax = plt.subplots(figsize=(10, 4))\n", + "\n", + "similarities = merged_pd[merged_pd['segger_similarity'] > 0]['segger_similarity']\n", + "ax.hist(similarities, bins=50, edgecolor='white', alpha=0.7)\n", + "ax.axvline(similarities.median(), color='red', linestyle='--', label=f'Median: {similarities.median():.3f}')\n", + "ax.set_xlabel('Similarity Score')\n", + "ax.set_ylabel('Count')\n", + "ax.set_title('Distribution of Assignment Similarity Scores')\n", + "ax.legend()\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7. Save All Outputs\n", + "\n", + "Use the `save_sample_outputs` function to generate a complete set of sample files." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from segger.datasets import save_sample_outputs\n", + "\n", + "sample_output_dir = output_dir / \"sample_outputs\"\n", + "paths = save_sample_outputs(\n", + " sample_output_dir,\n", + " n_cells=50,\n", + " transcripts_per_cell=20,\n", + " include_spatialdata=True,\n", + ")\n", + "\n", + "print(\"Generated sample outputs:\")\n", + "for name, path in paths.items():\n", + " print(f\" {name}: {path}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8. SOPA Compatibility\n", + "\n", + "The exported SpatialData Zarr stores are compatible with SOPA workflows. Key conventions:\n", + "\n", + "- **shapes[\"cells\"]**: Cell polygons with `cell_id` column\n", + "- **points[\"transcripts\"]**: Transcripts with `segger_cell_id` assignment column\n", + "- Coordinate systems use identity transforms\n", + "\n", + "To use with SOPA:\n", + "```python\n", + "import sopa\n", + "import spatialdata\n", + "\n", + "# Load Segger output\n", + "sdata = spatialdata.read_zarr(\"segmentation.zarr\")\n", + "\n", + "# Continue with SOPA analysis\n", + "sopa.aggregate(sdata, ...)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Cleanup\n", + "import shutil\n", + "shutil.rmtree(output_dir)\n", + "print(\"Cleaned up temporary files\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Summary\n", + "\n", + "This notebook demonstrated:\n", + "\n", + "1. **Creating synthetic data** with `create_synthetic_xenium()`\n", + "2. **Writing to SpatialData (lightweight)** with `write_spatialdata_zarr()`\n", + "3. **Reading from SpatialData** with `read_spatialdata_zarr()` or `SpatialDataZarrReader`\n", + "4. **Simulating Segger output** with `create_sample_segger_output()`\n", + "5. **Exporting segmentation results** to all formats (`segger_raw`, `merged`, `spatialdata`, `anndata`)\n", + "6. **AnnData tables inside SpatialData** via `sdata.tables[\"cell_table\"]`\n", + "7. **SOPA compatibility** for downstream analysis\n", + "\n", + "### Key Functions\n", + "\n", + "| Function | Purpose |\n", + "|----------|------|\n", + "| `write_spatialdata_zarr()` | Lightweight Zarr writer (parquet input) |\n", + "| `read_spatialdata_zarr()` | Read transcripts + shapes from Zarr |\n", + "| `SpatialDataZarrReader` | Class-based reader with metadata |\n", + "| `SpatialDataZarrWriter` | Class-based writer with incremental writes |\n", + "| `SeggerRawWriter` | Write raw predictions parquet |\n", + "| `MergedTranscriptsWriter` | Write transcripts + assignments |\n", + "| `AnnDataWriter` | Write `.h5ad` cell x gene matrix |\n", + "| `SpatialDataWriter` | Full SpatialData export (includes tables) |\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.11.0" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} \ No newline at end of file