From a30d5c65382c266074e4c2d77278ae2264c78bfd Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 09:22:51 +0200 Subject: [PATCH 01/22] Define audited long-recording curation contract and integration plan --- design/README.md | 16 + design/large-recording-curation.md | 345 ++++++++++++++++++ design/large-recording-integration-plan.md | 244 +++++++++++++ phy/apps/tests/large_recording_fixtures.py | 153 ++++++++ .../tests/test_large_recording_contract.py | 151 ++++++++ 5 files changed, 909 insertions(+) create mode 100644 design/large-recording-curation.md create mode 100644 design/large-recording-integration-plan.md create mode 100644 phy/apps/tests/large_recording_fixtures.py create mode 100644 phy/apps/tests/test_large_recording_contract.py diff --git a/design/README.md b/design/README.md index 90565b927..995206b0c 100644 --- a/design/README.md +++ b/design/README.md @@ -57,3 +57,19 @@ and section 11 for integration and manual acceptance. The implementation and user documentation are complete on the unreleased phy 2.2 branch. Final large-dataset smoke testing and save/reopen validation remain. + +## Long-recording curation (proposed) + +The [long-recording curation Phy-side design contract](large-recording-curation.md) +describes bounded local datasets for ~1000-hour sortings, the three spike-index +spaces, optional upstream waveform evidence, full-duration metrics, replay safety, +and the sequence of implementation PRs. The accompanying synthetic 1000-hour +fixture and reference tests are in `phy/apps/tests/large_recording_fixtures.py` +and `phy/apps/tests/test_large_recording_contract.py`. + +This is a proposal and a reference test contract, **not yet** a `prepare-large` +implementation or an upstream export-format agreement. + +The [integration audit and plan](large-recording-integration-plan.md) refines +the contract with correctness findings, module boundaries, ordered PRs and +acceptance gates. Follow its gates before enabling editable bounded sessions. diff --git a/design/large-recording-curation.md b/design/large-recording-curation.md new file mode 100644 index 000000000..0d3dfbaab --- /dev/null +++ b/design/large-recording-curation.md @@ -0,0 +1,345 @@ +# Long-recording curation in Phy 2.x: Phy-side design contract + +**Status:** proposed; implementation sequence and file contracts for review. This +specification is for Phy-side development; it does not authorize changes to the +AIND/Code Ocean export pipeline. Current Phy behavior remains unchanged until +subsequent implementation PRs land. + +The [integration audit and plan](large-recording-integration-plan.md) refines +this proposal with assignment revisions, transactional persistence, capability +gates and ordered PR acceptance criteria. Its enablement gates take precedence +over the original implementation sequence in Section 9. + +## 1. Objective and boundaries + +Curate chronic Neuropixels sortings of roughly 1000 hours without opening hundreds +of millions or billions of spikes in the existing in-memory Phy clustering model. +The workstation downloads the **complete sorter output once**; downloading the +complete raw voltage recording is **not required**. All preparation, interactive +curation, full-data replay, and regeneration run locally: + +```text +complete, immutable sorting (local disk) + | prepare-large: streamed/batch + v +bounded, temporally distributed Phy dataset + full-duration summaries + | existing Template GUI + Unit Stability + v +semantic curation actions (not only sampled row assignments) + | apply-curation: streamed/batch against complete sorting + v +new complete curated sorting (original untouched) + | prepare-large again, potentially different evidence windows + +-----------------------> new bounded GUI dataset +``` + +The **complete spike-level sorting stays outside the interactive GUI**. +The bounded dataset must reproduce useful current Phy workflows rather than +pretend to be a statistically representative replacement for every spike. +Full-duration plots and rates come from separate complete-sorting summaries. + +Out of scope: cloud services, rewriting phylib for out-of-core clustering, +longitudinal unit-identity graphs (phy3), automatic change-point detection, and +implementing upstream waveform extraction in this repository. + +## 2. The three index spaces (essential contract) + +All index values below are **zero-based row positions**, not timestamps, sample +numbers, SpikeInterface unit IDs, or stable IDs assigned by a sorter. + +| Symbol | Meaning | Where it lives | +| --- | --- | --- | +| `g` | Full-sorting spike row index, in immutable source order | Original `spike_times.npy` / `spike_clusters.npy` | +| `b` | Bounded spike row index used by the GUI | Bounded `spike_times.npy` / `spike_clusters.npy` | +| `w` | Row in the stored waveform/channel tensors | `_phy_spikes_subset.waveforms.npy` / `.channels.npy` | + +**Canonical mapping:** the bounded package writes +`_phy_spike_global_ids.npy`, a one-dimensional strictly increasing `int64` +array of length `N_bounded`. It is `G[b] = g`. The underscore prefix is +intentional: phylib treats ordinary `spike_*.npy` files as per-spike +attributes, so `spike_global_ids.npy` would be needlessly interpreted as one. + +**Dataset-local waveform IDs:** `_phy_spikes_subset.spikes.npy[w] = b` in the +bounded package. In the *upstream full export*, the same filename instead +contains `g` because that file accompanies the full sorting. The file **never** +means an intrinsic immutable/global ID; it indexes whichever Phy dataset is in +its directory. + +Example: + +```text +full indices selected by prepare-large, G: + [14, 19, 27, 117, 203, 839] +bounded rows b: + [ 0, 1, 2, 3, 4, 5] +upstream waveform full indices: + [14, 117, 839, 1902] +intersection with G: + [14, 117, 839] +bounded _phy_spikes_subset.spikes.npy: + [ 0, 3, 5] +``` + +Recover full source row numbers for waveforms by composition: + +```python +G = np.load('_phy_spike_global_ids.npy', mmap_mode='r') +B = np.load('_phy_spikes_subset.spikes.npy', mmap_mode='r') +full_waveform_rows = G[B] # [14, 117, 839] +``` + +`prepare-large` must preserve source row order, subset all per-spike arrays +consistently, retain absolute spike sample times, and remap matching waveform +rows **along with the corresponding channel/waveform data**. A sorted +intersection / `np.searchsorted` implementation needs no billion-element +inverse lookup array. Sorting by sample time is not a substitute for preserving +row identity; use the source export's exact row order (including ties). + +## 3. Source and optional upstream waveform inputs + +The source is a locally accessible standard Phy/SpikeInterface export (or an +adapter yielding equivalent arrays). The original spike index `g` refers to +**the exact exported row ordering**, not an assumed row in an unrelated +SpikeInterface spike vector. Source arrays and their provenance must be +validated before processing; never infer a row mapping from spike timestamps. + +The existing, unmodified Phy waveform files are: + +| Filename | Meaning | +| --- | --- | +| `_phy_spikes_subset.spikes.npy` | `int64[N_waveforms]`: source full spike row indices, sorted/unique | +| `_phy_spikes_subset.channels.npy` | `int32[N_waveforms, C_sparse]`: model channel indices, with `-1` padding; `channel_map.npy` maps these to raw-file columns | +| `_phy_spikes_subset.waveforms.npy` | numeric `[N_waveforms, N_samples, C_sparse]`: aligned waveform data, zero on padded channels | + +The upstream AIND pipeline **may later** supply the following proposed files; +these names/schema are *not yet finalized with its developers*: + +| Optional file | Initial proposal | +| --- | --- | +| `_phy_spikes_subset.window_bounds.npy` | `int64[W, 2]` recording sample intervals, `[start, end)` | +| `_phy_spikes_subset.window_types.npy` | `uint8[W]`: `0` survey, `1` rescue | +| `_phy_spikes_subset.window_strata.npy` | `int32[W]`: survey stratum index, `-1` for rescue | +| `_phy_spikes_subset.manifest.json` | Small versioned scalar metadata: source identity, time base, extractor geometry, parameters, seed, array semantics | + +There are deliberately **no structured NumPy dtypes**, mixed-purpose `N x 5` +matrices, or massive JSON window arrays. The upstream manifest is useful for +planning downstream windows but is not required for fixture-based development. +The presence of a window denotes *potential* waveform coverage, not one stored +waveform for every spike within that interval: per-unit waveform caps still +apply. The three established waveform files remain authoritative for which +individual spikes actually have stored waveforms. + +In the absence of the proposed window sidecars, `prepare-large` may use the +existing three files and their spike-index/time distribution as available +evidence, with reduced guarantees about raw-I/O locality and survey windows. +A dataset with neither raw traces nor pre-extracted waveforms must not claim +that Waveform/Feature View evidence is available. + +The full export's identifier/fingerprint should combine an immutable sorting +asset ID when available, full spike count, and a digest of a canonical +row-ordered immutable spike array (`spike_times.npy` is one candidate). The +upstream reservoir must be verified against that *exact* source. A mutable +`spike_clusters.npy` hash must not be the sole identity used across curation +iterations. Byte-level hashes in examples are illustrative; the definitive +AIND provenance method is a pending joint decision. + +Coordinate identity and assignment revision are separate: the latter binds the +initial full cluster assignments and metadata for replay. Each curated output +records its parent revision and journal digest. Validate relevant immutable +feature, acquisition and time-base provenance as well as spike rows; equal +timestamp arrays alone do not establish source identity. Production hashing +must stream file contents rather than read a complete array into memory. + +## 4. Bounded-package Phy-side output + +`prepare-large` creates a **new directory**, not an in-place rewrite of the +original. At minimum it contains ordinary, internally consistent Phy files +(`params.py`, `spike_times.npy`, `spike_templates.npy`, `spike_clusters.npy`, +channel/template arrays, and present per-spike attributes), plus: + +| File | Role | +| --- | --- | +| `_phy_spike_global_ids.npy` | Required `int64[N_bounded]` sorted mapping `b -> g`, no duplicates | +| `_phy_curation_manifest.json` | Versioned local contract; immutable source ID/fingerprint, complete/bounded counts, durations, preparation algorithm/parameters/seed, evidence limitations and file names | +| `_phy_spikes_subset.{spikes,channels,waveforms}.npy` | Existing Phy-format stored waveforms, *remapped to bounded row indices* (if available) | +| Full-duration metrics | Separate time-binned evidence, described in Section 6; do not pretend proxy metrics are full metrics | + +Unselected spike rows are absent from the GUI arrays, **not deleted from the +complete sorting**. Absolute `spike_times.npy` values remain in acquisition +sample coordinates and require a dtype capable of representing 1000 h at the +source sample rate (typically `int64`, not `int32`). For 30 kHz, 1000 h is +108 billion samples. Keep recording start/end, session/block boundaries, valid +acquisition exposure, and gaps distinct from periods of zero firing. + +Do not rely on phylib's fallback of estimating `model.duration` from the last +spike when raw traces are absent. The future GUI metrics/time-axis integration +must take the authoritative duration/coverage metadata instead. Standard +`params.py` still identifies the bounded Phy dataset; the manifest augments it. + +## 5. Preparation algorithm: scientific and memory constraints + +A first version should: + +1. Scan the **full** local sorting in a bounded-memory batch pass; calculate + full-duration per-unit time bins and coverage/exposure. +2. Partition *valid acquisition time* into coarse strata. Select short shared + contiguous survey windows at deterministic seeded offsets across sessions/ + blocks (illustrative defaults: one 30 s window per 1 h stratum). +3. Include **all units and all spikes within each chosen window** as initial + bounded candidates; preserve source indices and absolute times. +4. Enforce configurable **total spike / RAM budgets**. Add shared rescue windows + for underrepresented units, prioritizing benefit to several units and + temporally separated evidence; retain bounded deterministic selection. +5. Where a waveform reservoir exists, favor windows with usable waveform + coverage and report per-unit counts and uncovered regions. Selecting a + window does not guarantee all its spikes have stored waveforms. +6. Write an atomic, versioned bounded package. Verify array-length alignment, + sorted global IDs, waveform/feature alignment, provenance, coverage and + source immutability before marking it usable. + +These choices are **heuristics**, not a claim of unbiased sampling, complete +physiological representativeness, or equivalent CCG/ISI statistics. Never label +metrics from the bounded subset as full-data measurements. Windows identified +manually in a future Unit Stability View may motivate a regenerated package; +automated anomaly detection is out of scope. + +The upstream `20_000` waveform cap per unit is **not** a mandatory local budget: +for 1000 units x 20k waveforms x 90 samples x 32 channels x 4 bytes it would +approach **230 GB** uncompressed. Extraction, transfer, storage and bounded +GUI consumption require independently configurable *total* byte/spike budgets. + +## 6. Unit Stability evidence from the full recording + +A Unit Stability View should work on ordinary 1-10 h recordings too. For a +selected cluster it plots time-binned **full-sorting** spike count / firing rate, +amplitude median/quantiles, depth/position and presence/coverage when those +quantities exist in the source. Use an explicit time axis, valid acquisition +exposure per bin, data-availability flags, and recording gaps. Counts divided +by wall-clock bin width are wrong for acquisition gaps. No missing metric should +be silently synthesized. + +Initial storage may use regular homogeneous `.npy` arrays plus a small manifest, +with explicit row-to-cluster-ID mapping and bin edges; exact metric schema and +plot integration belong to the Unit Stability PR. At each full-data curation +iteration, merged/split clusters must receive **correctly recomputed or +incrementally updated** summaries, not merely the stale parent-unit curves. + +Current `BaseController.get_mean_firing_rate()` divides the loaded cluster's +`n_spikes` by `model.duration`; this would severely undercount a bounded unit. +When a bounded package is detected, its full-count/exposure-aware value must +replace that calculation wherever presented. The same provenance distinction +applies to the Cluster View, correlograms, ISI and other proxy-based statistics. + +Window statistics need explicit observation intervals. Do not connect ISIs or +CCG pairs across independent segments or unsupported gaps. CCG normalization +must use a declared lag-exposure estimator for those intervals; initially hide +unsupported normalized diagnostics. Whole-window sampling, rescue selection +and incomplete waveform coverage do not establish unbiased full-data quality +metrics or chronic biological unit identity. + +## 7. Semantic curation and full-data replay + +The current `Clustering` operates on arrays of loaded spike rows, creates new +cluster IDs during `assign/split`, and saves those local assignments. They +cannot by themselves define the fate of billions of unobserved spikes. + +Before mutations in a bounded GUI session, record **versioned semantic events** +with preconditions, affected source clusters, deterministic operation parameters, +resolved cluster IDs and provenance. Track edits through existing undo/redo and +save. Apply them in order against the *complete* local sorting to write a new +curated output (never overwrite the original). + +| Operation | Initial replay policy | +| --- | --- | +| Merge complete units | Reapply to every source spike in the units; replayable | +| Cluster quality/metadata labels | Replay per resulting cluster identity; replayable | +| Threshold split | Replay only if the predicate/feature definition is serialized and an equivalent full-data per-spike attribute exists; otherwise disallow | +| Lasso or arbitrary selected spike-ID split | Not replayable for unseen spikes by default; **block in bounded mode** unless a valid full-data rule is supplied | +| Undo/redo | Journal must represent the committed final event sequence and allow exact save/reopen, not duplicate reverted edits | + +Unbounded/ordinary Phy behavior must remain unchanged. It is not acceptable to +silently treat a selection of bounded spike IDs as a valid full-unit split. +Existing `curation.json` merge proposals and `curation_review.json` are separate +producer/review artifacts; the new semantic event journal must not overwrite +either file. Re-running `prepare-large` after `apply-curation` may reuse the same +source spike/waveform bytes because curation changes assignments, not spike +identity. + +For the first editable release, support merges and labels only. Keep all splits +blocked until their specific replay rules pass end-to-end tests. Allocate IDs +from the complete unit catalog, including units absent from the subset. Record +resolved inherited metadata, rather than recomputing it from full parent counts. +Commit journal, assignments and metadata as one validated save generation; +reopen must recover a coherent generation and allocator state. Validate operation +intent before mutation, including plugin and console entry points. + +## 8. Test/reference fixture and future acceptance + +`phy/apps/tests/large_recording_fixtures.py` deterministically writes a minimal +32-spike, **1000 h** full Phy-format sorting and a bounded eight-spike package, +including upstream waveforms for eight different source rows and remapped +bounded waveforms for five. The fixture intentionally omits the raw binary. +`phy/apps/tests/test_large_recording_contract.py` asserts: + +- exact `int64` sample indexing well past the 32-bit limit, source-order and + time preservation; +- full -> bounded -> waveform mapping, including copied waveform/channel rows; +- existing Phy waveform filenames, row/dtype/shape and `-1` padding invariants; +- simple window array dtypes, sample-coordinate bounds and shared row alignment; +- source fingerprint agreement, separate source-vs-bounded identity; +- empty/disjoint intersections and existing phylib load compatibility. + +**These are reference contract tests only:** they do not claim that +`prepare-large`, Unit Stability or semantic replay already exists. Subsequent +PRs should reuse the fixture but replace the reference remapping with tests of +the production command. Add mismatched-source, reordered-row, excessive-memory, +partially covered units, gap, sparse feature and replay/undo corruption tests +before enabling bounded curation on real datasets. + +## 9. Ownership and implementation order + +1. **This PR:** Phy-side design, source-coordinate/format reference fixture and + tests only. No GUI changes, no new CLI, no upstream exporter changes. +2. **Unit Stability:** full-data summaries and selected-unit GUI view, initially + usable on normal recordings. Keep user-visible full/partial provenance clear. +3. **Semantic curation journal:** integration with `Supervisor`, event semantics, + undo/save/reopen and blocking unsafe splits in bounded mode. +4. **`prepare-large`:** separate streaming batch CLI, input validation, window + selection, output/remapped waveform files and bounded-manifest generation. +5. **`apply-curation`:** validate/replay semantic actions against full local + sorting, write a new curated full sorting, verify, then regenerate a bounded + package. Test deterministic repeatability and failures atomically. + +A future release may choose a different PR order for journal/prepare integration, +but **do not ship an editable bounded GUI without replay safety**. + +Agent starting points: `AGENTS.md`, `design/README.md`, +`phy/apps/__init__.py` (Click CLI), `phy/apps/template/gui.py` (controller), +`phy/apps/base.py` (views/rates/save), `phy/cluster/{clustering,supervisor}.py` +(actions/history), `phy/apps/template/tests/test_gui.py`, and +`phy/apps/tests/test_large_recording_contract.py`. The existing waveform +reader is in the separate `phylib/io/model.py` dependency. + +## 10. Decisions not frozen by this Phy-side PR + +The upstream team should review the exact optional window-sidecar names, AIND +sorting asset identity/fingerprinting, segment/time/recording-block semantics, +waveform extraction alignment, total storage budget, and whether windows or a +more general sampling-plan format fits its pipeline best. Phy should accept the +existing three-file waveform format regardless. Values such as `1 h`, `30 s`, +`2,000` and `20,000` are preliminary, not schema requirements. + +Code Ocean handles **creation of a reusable evidence reservoir**; Phy handles +**bounded selection, GUI coordinate remapping, full-duration summaries, +semantic curation and replay**. Neither side should infer an absent waveform +or silently redefine source spike IDs. + +## Implementation references + +- [Phy `Clustering.assign`](../phy/cluster/clustering.py) and + [Supervisor](../phy/cluster/supervisor.py) for current row-based edits. +- [Template GUI](../phy/apps/template/gui.py) and + [Waveform/Feature mixins](../phy/apps/base.py) for standard stored-waveform + support and full/proxy metric safeguards. +- [Existing stored-waveform GUI test](../phy/apps/template/tests/test_gui.py). +- [SpikeInterface `export_to_phy` source (AIND inspected commit)](https://github.com/SpikeInterface/spikeinterface/blob/896ea840da72b4a5f06dcf8870ad820d20fe7031/src/spikeinterface/exporters/to_phy.py). diff --git a/design/large-recording-integration-plan.md b/design/large-recording-integration-plan.md new file mode 100644 index 000000000..004eb8c41 --- /dev/null +++ b/design/large-recording-integration-plan.md @@ -0,0 +1,244 @@ +# Long recording audit and integration plan + +## Assessment + +The downloaded contract bundle is a useful foundation. Keep the bounded GUI, +immutable full sorting, explicit source-row mapping, and full-data replay model. +Do not enable editing until replay and persistence agree with the GUI. A 1000-hour +timestamp fixture validates coordinate range; it does not validate capacity or +scientific representativeness. + +This review targets phy `7e439491` and the downloaded +`phy_large_recording_contract_bundle.zip`. The accompanying contract remains a +proposal. This plan refines its implementation order and supplies additional +requirements; the phases below govern enablement. + +## Findings that affect correctness + +1. **Identity needs two layers.** A spike-coordinate fingerprint identifies + immutable rows and their time/channel/feature provenance. An assignment + revision identifies the starting full cluster assignments and metadata. + Replay must validate both. A times-only hash cannot distinguish recordings + with identical timestamps or changes to feature values. Include the acquisition + identity, time base, relevant immutable array digests and schema in coordinate + identity; hash assignments and metadata separately for each revision. Record + parent revision, journal digest, output revision and preparation identity. + Compute hashes incrementally, without `read_bytes()` on production arrays. + +2. **Cluster IDs must come from the full namespace.** + [Clustering](../phy/cluster/clustering.py) initializes its allocator from the + maximum loaded cluster ID. A subset can omit the highest full ID. Seed the + allocator from a full unit catalog and persist its high-water mark. Record + explicit output IDs in events and reject collisions during replay. Units with + no bounded evidence remain in the catalog and output, with missing evidence + visible to the user. + +3. **Save is a transaction.** + [BaseController](../phy/apps/base.py) currently saves assignments and metadata + separately; [Supervisor.save](../phy/cluster/supervisor.py) emits further save + events and clears dirty state. Adding another journal file to that chain does + not make it crash consistent. Bounded mode needs immutable save generations + containing assignments, metadata, journal and identity, published by a single + commit pointer. Reopen only complete validated generations. Preserve the last + valid generation after interruption; keep dirty state after a failed commit. + Define whether undo survives reopen. Recommended v1: reopen establishes a new + undo baseline while retaining the committed semantic history for replay. + +4. **Record resolved metadata.** `Clustering._do_merge` selects the largest + parent using loaded counts, and Supervisor inherits its metadata. Full and + sampled counts can choose different parents. Serialize the resolved group and + custom labels in merge events, including an explicit policy for conflicting + labels. Replay must not infer this choice from full counts. + +5. **Capture intent before mutation.** + [AmplitudeView.on_request_split](../phy/cluster/views/amplitude.py) returns + selected row IDs and clears the threshold. A listener after clustering cannot + recover the predicate. Route bounded edits through a command service before + any mutation. Gate direct assign/split, plugins, console operations, shortcuts, + merge proposals and threshold providers at the mutation boundary. V1 supports + whole-unit merges and labels; block every split until its full-data semantics + are implemented and tested. + +6. **Statistics require observation intervals.** Preserve shared contiguous + windows and segment boundaries. ISIs must not connect windows or acquisition + gaps. CCGs must exclude pairs crossing unsupported boundaries, and their + normalization must match observed lag exposure; the existing full-duration + baseline in `BaseController._get_correlograms_rate` is not valid for a window + subset. Initially suppress unsupported normalization and diagnostic claims. + Label window statistics as sampled evidence. Rescue selection and waveform + availability introduce bias; they do not justify extrapolating quality, + contamination, refractory violations or chronic unit identity to the full run. + +7. **Define time and channel coordinates.** V1 accepts one validated monotonic + sample axis with a fixed sampling rate and explicit valid acquisition + intervals. Reject unsupported segment layouts rather than concatenate silently. + Preserve tied timestamps and source row order. Sparse waveform channel IDs + index model channels; `channel_map.npy` maps these to raw-file columns. They + are not interchangeable with hardware or SpikeInterface channel IDs. Test a + nonidentity map, sparse padding, whitening/scaling and waveform alignment. + Keep sample coordinates as integers and CPU times as float64; subtract the + viewport origin before converting fine-scale plotting positions to float32. + +8. **All preparation products need budgets.** A dense units-by-time-bin summary, + exact quantile calculation, waveform gather, or full index inversion can + exceed RAM despite streamed input. Specify batch, output, summary, cache and + GUI memory limits, plus temporary disk estimates. Distinguish peak working + memory from file-backed pages. Whole shared windows exceeding the spike budget + must be shortened, rejected or replaced with documented deterministic rules; + do not silently thin spikes within a window and retain its statistical claims. + +9. **Persist the final window plan.** Store retained intervals, segment/block + identity, survey/rescue classification and valid exposure in the bounded + package. A seed and parameters do not identify trimmed or replaced windows. + Count acquisition exposure once when composing merged-unit summaries. + +## Module boundaries + +Use a small `phy/apps/large_recording/` package, with pure services callable +without Qt and thin Click/controller adapters. Refine filenames while coding; +keep these responsibilities separate: + +| Responsibility | Contract | +| --- | --- | +| Source adapter and validation | Stream canonical arrays; classify per-spike, template, channel and cluster data explicitly; reject ambiguous unsupported arrays | +| Manifest and identity | Validate versions, paths, coordinate identity, assignment revisions, exposure and capabilities | +| Preparation | Deterministic window plan, bounded output, streamed waveform remapping, budget report | +| Summaries | Full counts/exposure, availability, declared exact or approximate estimators and multiresolution queries | +| Semantic commands and journal | Operation validation, explicit IDs/metadata, history cursor and transactional commit | +| Replay | Pure event interpretation, chunked output assignments, invariants and lineage | +| GUI adapter | Capability gating, evidence labels, bounded model/controller integration | + +Do not load the complete source through TemplateModel or Clustering in batch +commands. Do not hide full-data scans in a selected-unit GUI callback. Limit +changes to phylib to demonstrated loader/coordinate fixes, with separate tests +and dependency requirements. Preserve existing ordinary-dataset behavior. + +## Ordered PRs and acceptance gates + +### 1. Contract and reference fixtures + +Land the revised contract, this plan and format fixtures on a design branch. +Fix the bundle's missing `dtype` in `params.py`, allow equal sample times, and +reject malformed reference row IDs. Run the real released-phylib loader test +without accepting a skip. Its success proves this small file layout loads, +not that all GUI workflows or long-recording statistics are supported. + +### 2. Source validation and summary engine + +Implement identities, assignment revisions, array inventory, exposure and +capability validation independently of Qt. Start with full counts and rates; +add amplitude/depth only with defined units and available source attributes. +Do not add per-bin quantiles until their exact/approximate algorithm, merge +behavior and memory costs are specified. Medians cannot be merged by averaging +parent medians; invalidate or recompute unavailable derived summaries. + +Gate: exact tiny-oracle counts; missing exposure; gaps; source/feature mismatch; +reordered rows; column-vector input arrays; unknown versions; unsupported +segments; bounded peak memory as source size grows; actionable disk estimates. + +### 3. Read-only preparation and inspection + +Implement `prepare-large` with deterministic shared windows, rescue policies, +per-unit evidence reports and explicit budgets. Write into a temporary sibling +directory and publish only after complete validation. Rebuild paths in params, +subset every registered per-spike array, retain template-indexed structures, and +avoid copying stale `.phy` caches and derived cluster metrics. Unknown attributes +must be explicitly included, excluded with a report, or rejected. + +Add a bounded-manifest GUI adapter with authoritative duration, full/proxy +counts and unsupported-view safeguards. Until phase 6, require read-only bounded +sessions, including save and plugin mutation entry points. + +Gate: production command vs independently specified expected arrays; shuffled +channel mapping; actual `get_waveforms()` values; sparse PC feature alignment; +missing/partial waveform coverage; tied samples; zero evidence units; empty +selection policy; deterministic budgets; interrupted publication; no source +writes; GUI open/close and time-axis precision tests. + +### 4. Semantic commands and durable saves + +Implement merge/label command validation, full-catalog ID allocation, resolved +metadata, undo/redo active history and transactional generations. Keep the +feature disabled for editable bounded sessions while replay is incomplete. +Existing `curation.json` and `curation_review.json` retain their separate roles. + +Gate: merge chains; conflicting labels; undo then branch; redo; reopen baseline; +omitted high-ID units; proposal-driven merges; rejected direct split/assign; +failed-save dirty state; fault injection at every commit boundary; assignments +equal the journal's projection onto bounded rows. + +### 5. Full-data replay + +Implement `apply-curation` against an exact source assignment revision. For v1 +merges, resolve the final source-unit mapping once, then stream assignments into +a new full dataset. Preserve row count/order, times and immutable arrays; write +metadata and lineage coherently. Reject repeated application to the wrong parent +revision. Publish only a verified complete output. Reprepare from that revision +with the same coordinate identity and fresh revision-dependent summaries. + +Gate: compare every assignment with an independent tiny oracle; preserve all +unseen spikes; replay chains and labels exactly; reject mismatched parent or +corrupted journal; interruption never exposes a complete-looking partial output; +same source/events produce the same semantic result; source bytes unchanged. + +### 6. Enable bounded merges and labels with Unit Stability + +Expose editable bounded mode only when phases 3–5 pass together. Integrate a +Unit Stability view that distinguishes acquisition exposure, evidence windows, +available measurements and unresolved identity. Add bounded status and operation +capabilities to the existing workflow. Count/exposure summaries can update for +merges; quantiles and other nonadditive metrics require recomputation or explicit +unavailability. Keep all splits blocked. + +Gate: prepare → inspect → merge/label → undo/redo → save/reopen → replay → +reprepare → verify. Include ordinary 1–10 h datasets to prevent regressions. +Run `make test-full`, `make doc-check`, and `uv build` when CLI/package changes +are included. Complete manual smoke testing with an actual chronic dataset. + +### 7. Optional predicate splits + +Add one operation at a time after the initial workflow is accepted. Store feature +identity/units, predicate operator, threshold, missing-value policy, parent +revision and explicit child IDs. The same predicate must evaluate identically +on GUI evidence and all source spikes. Stored waveform-derived or local PCA +amplitudes do not automatically define a full-data predicate. Lasso splits +remain unavailable without a separately validated full-data rule. + +## Capacity and scientific acceptance + +Use three kinds of evidence: tiny exact-oracle datasets for correctness; +generated high-density on-disk datasets for resource behavior; real chronic +recordings for usability and scientific acceptance. Duration, spike count, +number of units, array widths and available waveform coverage are separate axes. +Measure preparation/replay throughput, peak process memory, temporary disk, +GUI startup and selected-unit update latency on documented hardware. Establish +acceptance budgets from those measurements before advertising capacity. + +Have a domain curator review known drift, rare/bursting units, transient +artifacts, gaps and intentionally incorrect merges. Compare selected evidence +with withheld contiguous windows and full-data diagnostics where available. +Record what the curator can and cannot infer; finite selected evidence cannot +guarantee biological identity throughout 1000 hours. Software integrity and +scientific evidence sufficiency are separate release criteria. + +## Producer decisions + +Agree with the producer team on source asset identity, full unit IDs, authoritative +duration/exposure, segment mapping, waveform time/channel/amplitude semantics, +reservoir coverage and total storage costs. Existing three-file waveforms remain +supported; proposed window sidecars must remain optional until jointly agreed. +The inspected [SpikeInterface exporter revision](https://github.com/SpikeInterface/spikeinterface/blob/896ea840da72b4a5f06dcf8870ad820d20fe7031/src/spikeinterface/exporters/to_phy.py) +supports one segment and distinguishes Phy channel indices from exported original +channel IDs. Do not assume that arbitrary multi-session inputs already satisfy +this contract or that a deployed exporter matches this inspected revision. + +## Validation of this design branch + +On 2026-10-13, the locked development environment with phylib 2.7.1 passed +all ten reference tests, including the loader and returned waveform values. +`make test-apps format-check` passed all 165 application tests, lint and +formatting checks. Patch whitespace validation also passed. The test process +reported pending ipykernel tasks during shutdown after successful completion. +This branch changes design documents and reference tests only; it does not +implement preparation, replay, transactional saves or a stability view, and +does not establish realistic long-recording capacity. diff --git a/phy/apps/tests/large_recording_fixtures.py b/phy/apps/tests/large_recording_fixtures.py new file mode 100644 index 000000000..7041213bd --- /dev/null +++ b/phy/apps/tests/large_recording_fixtures.py @@ -0,0 +1,153 @@ +"""Small, deterministic on-disk example of a 1000-hour two-stage Phy dataset. + +This is reference test data, not a prepare-large implementation. The fake +recording has 32 spikes spread across 1000 hours, not 1000 hours of raw traces. +The full and bounded folders use ordinary Phy filenames. +""" + +import hashlib +import json +import shutil +from dataclasses import dataclass +from pathlib import Path + +import numpy as np + + +@dataclass(frozen=True) +class LongRecordingFixture: + full: Path + bounded: Path + global_ids: np.ndarray + upstream_waveform_ids: np.ndarray + bounded_waveform_ids: np.ndarray + + +def _sha256(path): + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def _reference_remap(global_ids, upstream_ids): + """Reference intersection for sorted, unique, nonnegative int64 row IDs.""" + global_ids = np.asarray(global_ids) + upstream_ids = np.asarray(upstream_ids) + for ids in (global_ids, upstream_ids): + if ids.ndim != 1 or ids.dtype != np.dtype('int64'): + raise ValueError('Row IDs must be one-dimensional int64 arrays.') + if np.any(ids < 0) or np.any(ids[1:] <= ids[:-1]): + raise ValueError('Row IDs must be nonnegative, sorted, and unique.') + if not len(global_ids) or not len(upstream_ids): + empty = np.array([], dtype=np.int64) + return empty, empty.copy() + positions = np.searchsorted(global_ids, upstream_ids) + keep = positions < len(global_ids) + keep[keep] &= global_ids[positions[keep]] == upstream_ids[keep] + return positions[keep].astype(np.int64), np.flatnonzero(keep).astype(np.int64) + + +def make_long_recording_fixture(root): + """Write one full Phy dataset and its expected bounded counterpart.""" + root = Path(root) + full, bounded = root / 'full', root / 'bounded' + full.mkdir(parents=True) + bounded.mkdir(parents=True) + + fs = 30_000 + num_samples = 1000 * 3600 * fs # Far beyond signed int32 sample indices. + samples = np.linspace(100, num_samples - 100, 32, dtype=np.int64) + samples[8] = samples[5] # Simultaneous spikes retain distinct source row identities. + samples[6:8] = samples[5] + units = (np.arange(32) % 3).astype(np.int32) + amplitudes = np.arange(1, 33, dtype=np.float32) + templates = np.zeros((3, 12, 4), dtype=np.float32) + for unit in range(3): + templates[unit, :, unit] = -np.arange(12, dtype=np.float32) + + for name, array in ( + ('spike_times.npy', samples), + ('spike_clusters.npy', units), + ('spike_templates.npy', units), + ('amplitudes.npy', amplitudes), + ('templates.npy', templates), + ('channel_map.npy', np.arange(4, dtype=np.int32)), + ('channel_positions.npy', np.array([[0, 0], [20, 0], [0, 20], [20, 20]])), + ): + np.save(full / name, array) + (full / 'params.py').write_text( + "sample_rate = 30000.0\ndat_path = None\nn_channels_dat = 4\ndtype = 'int16'\n", + encoding='utf-8', + ) + + upstream_ids = np.array([1, 2, 8, 13, 18, 21, 28, 31], dtype=np.int64) + channels = np.array( + [[0, 1, -1] if i % 2 == 0 else [2, 3, -1] for i in range(len(upstream_ids))], + dtype=np.int32, + ) + waveforms = np.zeros((len(upstream_ids), 12, 3), dtype=np.float32) + for row, spike_id in enumerate(upstream_ids): + waveforms[row, :, 0] = spike_id + np.arange(12) / 12 + waveforms[row, :, 1] = -(spike_id + np.arange(12) / 12) + stem = '_phy_spikes_subset' + np.save(full / f'{stem}.spikes.npy', upstream_ids) + np.save(full / f'{stem}.channels.npy', channels) + np.save(full / f'{stem}.waveforms.npy', waveforms) + + # Proposed, optional upstream window metadata: simple homogeneous arrays. + starts = np.minimum(samples[upstream_ids] - 10, num_samples - 30 * fs) + bounds = np.column_stack((starts, starts + 30 * fs)).astype(np.int64) + types = np.zeros(len(upstream_ids), dtype=np.uint8) + types[-1] = 1 # rescue + strata = (samples[upstream_ids] // (3600 * fs)).astype(np.int32) + strata[-1] = -1 # rescue has no survey stratum + np.save(full / f'{stem}.window_bounds.npy', bounds) + np.save(full / f'{stem}.window_types.npy', types) + np.save(full / f'{stem}.window_strata.npy', strata) + source_hash = _sha256(full / 'spike_times.npy') + (full / f'{stem}.manifest.json').write_text( + json.dumps( + { + 'format': 'phy_spikes_subset', + 'format_version': 1, + 'source_sorting': {'num_spikes': len(samples), 'spike_times_sha256': source_hash}, + 'recording': { + 'sampling_frequency_hz': fs, + 'num_samples': num_samples, + 'num_channels': 4, + 'num_segments': 1, + }, + 'selection': {'algorithm': 'synthetic_windows_v1', 'seed': 42}, + 'waveform_extraction': {'nbefore_samples': 4, 'nafter_samples': 8}, + 'window_types': {'0': 'survey', '1': 'rescue'}, + }, + indent=2, + ) + + '\n', + encoding='utf-8', + ) + + global_ids = np.array([0, 2, 5, 8, 13, 21, 25, 31], dtype=np.int64) + for name in ('spike_times.npy', 'spike_clusters.npy', 'spike_templates.npy', 'amplitudes.npy'): + np.save(bounded / name, np.load(full / name)[global_ids]) + for name in ('templates.npy', 'channel_map.npy', 'channel_positions.npy', 'params.py'): + shutil.copyfile(full / name, bounded / name) + np.save(bounded / '_phy_spike_global_ids.npy', global_ids) + + bounded_rows, waveform_rows = _reference_remap(global_ids, upstream_ids) + np.save(bounded / f'{stem}.spikes.npy', bounded_rows) + np.save(bounded / f'{stem}.channels.npy', channels[waveform_rows]) + np.save(bounded / f'{stem}.waveforms.npy', waveforms[waveform_rows]) + (bounded / '_phy_curation_manifest.json').write_text( + json.dumps( + { + 'format': 'phy_bounded_curation', + 'format_version': 1, + 'source': {'num_spikes': len(samples), 'spike_times_sha256': source_hash}, + 'global_spike_ids_file': '_phy_spike_global_ids.npy', + 'duration_seconds': 1000 * 3600, + }, + indent=2, + ) + + '\n', + encoding='utf-8', + ) + return LongRecordingFixture(full, bounded, global_ids, upstream_ids, bounded_rows) diff --git a/phy/apps/tests/test_large_recording_contract.py b/phy/apps/tests/test_large_recording_contract.py new file mode 100644 index 000000000..8e882afc1 --- /dev/null +++ b/phy/apps/tests/test_large_recording_contract.py @@ -0,0 +1,151 @@ +"""Reference contract tests for future prepare-large and waveform remapping. + +These tests deliberately do not exercise a production prepare-large command: +that command does not exist yet. Later implementations should reuse this +fixture and replace reference-only checks with command-level assertions. +""" + +import hashlib +import json + +import numpy as np +import pytest +from phylib.io.model import load_model + +from .large_recording_fixtures import _reference_remap, make_long_recording_fixture + + +@pytest.fixture +def long_recording(tmp_path): + return make_long_recording_fixture(tmp_path) + + +def test_long_recording_uses_exact_64_bit_sample_times(long_recording): + full = np.load(long_recording.full / 'spike_times.npy') + bounded = np.load(long_recording.bounded / 'spike_times.npy') + assert full.dtype == bounded.dtype == np.dtype('int64') + assert full[-1] > np.iinfo(np.int32).max + assert full[-1] / 30_000 > 999 * 3600 + np.testing.assert_array_equal(bounded, full[long_recording.global_ids]) + assert np.all(np.diff(long_recording.global_ids) > 0) + assert np.all(np.diff(bounded) >= 0) + assert bounded[2] == bounded[3] # equal times do not collapse distinct spikes + + +def test_two_stage_row_indices_and_waveform_data(long_recording): + full = long_recording.full + bounded = long_recording.bounded + global_ids = np.load(bounded / '_phy_spike_global_ids.npy') + full_waveform_ids = np.load(full / '_phy_spikes_subset.spikes.npy') + bounded_waveform_ids = np.load(bounded / '_phy_spikes_subset.spikes.npy') + assert global_ids.dtype == bounded_waveform_ids.dtype == np.dtype('int64') + np.testing.assert_array_equal( + global_ids[bounded_waveform_ids], np.intersect1d(full_waveform_ids, global_ids) + ) + upstream_rows = np.searchsorted(full_waveform_ids, global_ids[bounded_waveform_ids]) + for suffix in ('channels', 'waveforms'): + np.testing.assert_array_equal( + np.load(bounded / f'_phy_spikes_subset.{suffix}.npy'), + np.load(full / f'_phy_spikes_subset.{suffix}.npy')[upstream_rows], + ) + # A bounded row identifies one source row, and never a waveform tensor row. + assert bounded_waveform_ids.tolist() == [1, 3, 4, 5, 7] + assert global_ids[bounded_waveform_ids].tolist() == [2, 8, 13, 21, 31] + + +def test_ordinary_phy_waveform_files_are_aligned(long_recording): + bounded = long_recording.bounded + spike_ids = np.load(bounded / '_phy_spikes_subset.spikes.npy') + channels = np.load(bounded / '_phy_spikes_subset.channels.npy') + waveforms = np.load(bounded / '_phy_spikes_subset.waveforms.npy', mmap_mode='r') + assert spike_ids.ndim == 1 and np.all(np.diff(spike_ids) > 0) + assert channels.dtype == np.dtype('int32') + assert channels.shape == (len(spike_ids), waveforms.shape[2]) + assert waveforms.shape == (len(spike_ids), 12, 3) + assert np.all((channels == -1) | ((channels >= 0) & (channels < 4))) + assert np.all(waveforms[:, :, -1] == 0) # -1 means a zero-padded channel + assert spike_ids[-1] < len(np.load(bounded / 'spike_times.npy')) + + +def test_window_arrays_use_samples_and_simple_dtypes(long_recording): + full = long_recording.full + bounds = np.load(full / '_phy_spikes_subset.window_bounds.npy') + types = np.load(full / '_phy_spikes_subset.window_types.npy') + strata = np.load(full / '_phy_spikes_subset.window_strata.npy') + spike_samples = np.load(full / 'spike_times.npy') + assert bounds.shape == (len(types), 2) + assert len(types) == len(strata) + assert bounds.dtype == np.dtype('int64') + assert types.dtype == np.dtype('uint8') + assert strata.dtype == np.dtype('int32') + assert np.all(bounds[:, 1] > bounds[:, 0]) + assert np.all(bounds[:, 1] <= 1000 * 3600 * 30_000) + assert np.all((types == 0) | (types == 1)) + assert strata[-1] == -1 and types[-1] == 1 + source_waveform_times = spike_samples[long_recording.upstream_waveform_ids] + assert np.all((bounds[:, 0] <= source_waveform_times) & (source_waveform_times < bounds[:, 1])) + + +def test_reference_remap_handles_empty_and_disjoint_inputs(): + a = np.array([14, 19, 117], dtype=np.int64) + b = np.array([2, 4, 119], dtype=np.int64) + for left, right in ((a, b), (a, b[:0]), (a[:0], b), (a[:0], b[:0])): + bounded_rows, source_rows = _reference_remap(left, right) + assert bounded_rows.dtype == source_rows.dtype == np.dtype('int64') + assert bounded_rows.shape == source_rows.shape == (0,) + rows, upstream_rows = _reference_remap(a, np.array([14, 15, 117, 118])) + assert rows.tolist() == [0, 2] + assert upstream_rows.tolist() == [0, 2] + + +@pytest.mark.parametrize('ids', [[2, 1], [1, 1], [-1, 1]]) +def test_reference_remap_rejects_invalid_row_order(ids): + valid = np.array([1, 2], dtype=np.int64) + invalid = np.array(ids, dtype=np.int64) + for left, right in ((valid, invalid), (invalid, valid)): + with pytest.raises(ValueError, match='nonnegative, sorted, and unique'): + _reference_remap(left, right) + + +def test_manifests_bind_source_index_space_not_mutable_clusters(long_recording): + full = long_recording.full + bounded = long_recording.bounded + source_hash = hashlib.sha256((full / 'spike_times.npy').read_bytes()).hexdigest() + upstream = json.loads((full / '_phy_spikes_subset.manifest.json').read_text()) + downstream = json.loads((bounded / '_phy_curation_manifest.json').read_text()) + assert upstream['source_sorting']['spike_times_sha256'] == source_hash + assert downstream['source']['spike_times_sha256'] == source_hash + assert upstream['source_sorting']['num_spikes'] == len(np.load(full / 'spike_times.npy')) + assert downstream['global_spike_ids_file'] == '_phy_spike_global_ids.npy' + assert downstream['duration_seconds'] == 1000 * 3600 + assert hashlib.sha256((bounded / 'spike_times.npy').read_bytes()).hexdigest() != source_hash + + +def test_bounded_dataset_loads_with_existing_phylib(long_recording): + """The old Phy loader consumes bounded rows, not original global indices.""" + model = load_model(long_recording.bounded / 'params.py') + try: + np.testing.assert_array_equal( + model.spike_waveforms.spike_ids, long_recording.bounded_waveform_ids + ) + assert model.n_spikes == len(long_recording.global_ids) + assert model.n_samples_waveforms == 12 + assert model.spike_times[-1] > 999 * 3600 + np.testing.assert_array_equal( + model.get_waveforms(long_recording.bounded_waveform_ids, channel_ids=[0, 1, 2, 3]), + _expected_dense_waveforms(long_recording.bounded), + ) + finally: + model.close() + + +def _expected_dense_waveforms(path): + """Independent dense expansion of the fixture's sparse channel slots.""" + channels = np.load(path / '_phy_spikes_subset.channels.npy') + waveforms = np.load(path / '_phy_spikes_subset.waveforms.npy') + expected = np.zeros((len(channels), 12, 4), dtype=waveforms.dtype) + for row, channel_row in enumerate(channels): + for slot, channel in enumerate(channel_row): + if channel >= 0: + expected[row, :, channel] = waveforms[row, :, slot] + return expected From 38f3e7e56505712caf024c4c1b05f907a11465ef Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 10:07:40 +0200 Subject: [PATCH 02/22] Plan one implementation PR with explicit standard-recording compatibility gates --- design/README.md | 4 +-- design/large-recording-curation.md | 8 ++--- design/large-recording-integration-plan.md | 37 ++++++++++++++++++++-- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/design/README.md b/design/README.md index 995206b0c..27af3605f 100644 --- a/design/README.md +++ b/design/README.md @@ -63,7 +63,7 @@ The implementation and user documentation are complete on the unreleased phy The [long-recording curation Phy-side design contract](large-recording-curation.md) describes bounded local datasets for ~1000-hour sortings, the three spike-index spaces, optional upstream waveform evidence, full-duration metrics, replay safety, -and the sequence of implementation PRs. The accompanying synthetic 1000-hour +and the implementation stages. The accompanying synthetic 1000-hour fixture and reference tests are in `phy/apps/tests/large_recording_fixtures.py` and `phy/apps/tests/test_large_recording_contract.py`. @@ -71,5 +71,5 @@ This is a proposal and a reference test contract, **not yet** a `prepare-large` implementation or an upstream export-format agreement. The [integration audit and plan](large-recording-integration-plan.md) refines -the contract with correctness findings, module boundaries, ordered PRs and +the contract with correctness findings, module boundaries, ordered commits in one PR and acceptance gates. Follow its gates before enabling editable bounded sessions. diff --git a/design/large-recording-curation.md b/design/large-recording-curation.md index 0d3dfbaab..7e9b11388 100644 --- a/design/large-recording-curation.md +++ b/design/large-recording-curation.md @@ -3,11 +3,11 @@ **Status:** proposed; implementation sequence and file contracts for review. This specification is for Phy-side development; it does not authorize changes to the AIND/Code Ocean export pipeline. Current Phy behavior remains unchanged until -subsequent implementation PRs land. +the implementation is complete and validated. The [integration audit and plan](large-recording-integration-plan.md) refines this proposal with assignment revisions, transactional persistence, capability -gates and ordered PR acceptance criteria. Its enablement gates take precedence +gates and ordered commit acceptance criteria for one implementation PR. Its enablement gates take precedence over the original implementation sequence in Section 9. ## 1. Objective and boundaries @@ -310,8 +310,8 @@ before enabling bounded curation on real datasets. sorting, write a new curated full sorting, verify, then regenerate a bounded package. Test deterministic repeatability and failures atomically. -A future release may choose a different PR order for journal/prepare integration, -but **do not ship an editable bounded GUI without replay safety**. +The integration plan now organizes these stages as commits within a single PR, +rather than separate PRs. **Do not ship an editable bounded GUI without replay safety**. Agent starting points: `AGENTS.md`, `design/README.md`, `phy/apps/__init__.py` (Click CLI), `phy/apps/template/gui.py` (controller), diff --git a/design/large-recording-integration-plan.md b/design/large-recording-integration-plan.md index 004eb8c41..ee6270afa 100644 --- a/design/large-recording-integration-plan.md +++ b/design/large-recording-integration-plan.md @@ -113,11 +113,18 @@ commands. Do not hide full-data scans in a selected-unit GUI callback. Limit changes to phylib to demonstrated loader/coordinate fixes, with separate tests and dependency requirements. Preserve existing ordinary-dataset behavior. -## Ordered PRs and acceptance gates +## One implementation PR with ordered commits and acceptance gates + +Implement the complete workflow on `feature/long-recording-curation` in the +main phy checkout. Use the stages below as reviewable commit groups within one +PR. Intermediate capability gates support development; merge the PR only after +the complete prepare, curate, save, replay and regenerate workflow passes its +acceptance checks. Predicate splits require their own full-data equivalence +checks within the same PR if included in its supported functionality. ### 1. Contract and reference fixtures -Land the revised contract, this plan and format fixtures on a design branch. +Start with the revised contract, this plan and format fixtures. Fix the bundle's missing `dtype` in `params.py`, allow equal sample times, and reject malformed reference row IDs. Run the real released-phylib loader test without accepting a skip. Its success proves this small file layout loads, @@ -204,6 +211,32 @@ on GUI evidence and all source spikes. Stored waveform-derived or local PCA amplitudes do not automatically define a full-data predicate. Lasso splits remain unavailable without a separately validated full-data rule. +## Standard recording compatibility gate + +Recording length must never select a new behavior implicitly. Activate bounded +curation only through an explicit validated bounded manifest. Without that +manifest, retain the standard loader, selector, metrics, mutation capabilities, +save format and history behavior. A malformed bounded manifest must produce an +actionable error rather than silently enter standard editable mode. Optional +Unit Stability on ordinary recordings must not replace their existing views, +change their default layout or introduce full-source scans at GUI startup. + +Keep the semantic command, replay and transactional save implementation behind +the bounded adapter wherever possible. Any necessary shared-code change requires +focused standard-mode regression coverage in addition to bounded-mode tests. +Do not impose bounded split restrictions or journal files on ordinary datasets. + +Before merging the single PR, run `make test-full` and verify ordinary datasets +with raw traces, stored waveforms only, and sparse features. Cover standard +merge and label inheritance, lasso/threshold/template splits, undo/redo and +branching, save/reopen assignments and metadata, merge proposals, plugin-driven +edits, channel mapping, sampled views and existing rate/ISI/CCG behavior. Assert +that ordinary saves do not create bounded journals or manifests. Compare startup +memory and selection latency on the same ordinary datasets before and after the +change; any meaningful regression must be explained and resolved before merge. +Existing tests and these checks establish compatibility evidence; the plan +itself does not guarantee compatibility before implementation. + ## Capacity and scientific acceptance Use three kinds of evidence: tiny exact-oracle datasets for correctness; From 5582419649922ee04230a073be04c32e056136b6 Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 10:37:42 +0200 Subject: [PATCH 03/22] Validate streamed sorting sources, acquisition exposure and revision identity --- phy/apps/large_recording/__init__.py | 1 + phy/apps/large_recording/source.py | 532 ++++++++++++++++++ phy/apps/large_recording/tests/__init__.py | 1 + phy/apps/large_recording/tests/test_source.py | 240 ++++++++ 4 files changed, 774 insertions(+) create mode 100644 phy/apps/large_recording/__init__.py create mode 100644 phy/apps/large_recording/source.py create mode 100644 phy/apps/large_recording/tests/__init__.py create mode 100644 phy/apps/large_recording/tests/test_source.py diff --git a/phy/apps/large_recording/__init__.py b/phy/apps/large_recording/__init__.py new file mode 100644 index 000000000..373145000 --- /dev/null +++ b/phy/apps/large_recording/__init__.py @@ -0,0 +1 @@ +"""Bounded evidence preparation and full-sorting curation replay.""" diff --git a/phy/apps/large_recording/source.py b/phy/apps/large_recording/source.py new file mode 100644 index 000000000..89fd2c48c --- /dev/null +++ b/phy/apps/large_recording/source.py @@ -0,0 +1,532 @@ +"""Validated, file-backed source sorting on one monotonic sample clock.""" + +import csv +import ctypes +import errno +import hashlib +import json +import os +import runpy +import sys +from pathlib import Path + +import numpy as np + +PER_SPIKE = frozenset( + ( + 'spike_times.npy', + 'spike_clusters.npy', + 'spike_templates.npy', + 'amplitudes.npy', + 'pc_features.npy', + 'template_features.npy', + 'spike_positions.npy', + 'spike_depths.npy', + ) +) +STATIC = frozenset( + ( + 'templates.npy', + 'templates_ind.npy', + 'channel_map.npy', + 'channel_positions.npy', + 'channel_shanks.npy', + 'channel_map_si.npy', + 'channel_groups.npy', + 'whitening_mat.npy', + 'whitening_mat_inv.npy', + 'similar_templates.npy', + 'pc_feature_ind.npy', + 'template_feature_ind.npy', + ) +) +WAVEFORMS = frozenset( + ( + '_phy_spikes_subset.spikes.npy', + '_phy_spikes_subset.channels.npy', + '_phy_spikes_subset.waveforms.npy', + ) +) +WINDOW_SIDECARS = frozenset( + ( + '_phy_spikes_subset.window_bounds.npy', + '_phy_spikes_subset.window_types.npy', + '_phy_spikes_subset.window_strata.npy', + ) +) + + +def hash_file(path, batch_bytes=1024 * 1024): + """Hash bytes incrementally, including the array header.""" + digest = hashlib.sha256() + with Path(path).open('rb') as stream: + for block in iter(lambda: stream.read(batch_bytes), b''): + digest.update(block) + return digest.hexdigest() + + +def hash_json(value): + """Hash canonical JSON, normalizing integer metadata dictionary keys.""" + + def normalize(item): + if isinstance(item, dict): + return {str(key): normalize(val) for key, val in item.items()} + if isinstance(item, (list, tuple)): + return [normalize(val) for val in item] + if isinstance(item, np.generic): + return item.item() + return item + + payload = json.dumps(normalize(value), sort_keys=True, separators=(',', ':'), allow_nan=False) + return hashlib.sha256(payload.encode('utf-8')).hexdigest() + + +def assignment_revision(path, metadata): + """Identify mutable assignments and resolved cluster metadata.""" + path = Path(path) + if path.is_dir(): + path = path / 'spike_clusters.npy' + return hash_json({'assignments': hash_file(path), 'metadata': metadata}) + + +def close_array(array): + """Release a file-backed array handle, including on Windows.""" + mapping = getattr(array, '_mmap', None) + if mapping is not None and not mapping.closed: + mapping.close() + + +def publish_directory(staged, destination): + """Atomically publish a complete directory without replacing any target. + + Ordinary POSIX rename can replace an empty destination directory. Native + exclusive rename prevents a racing publication from silently replacing it. + """ + if os.name == 'nt': + os.rename(staged, destination) + return + library = ctypes.CDLL(None, use_errno=True) + if sys.platform.startswith('linux'): + rename = getattr(library, 'renameat2', None) + if rename is None: + raise OSError(errno.ENOSYS, 'Atomic exclusive directory publication is unavailable.') + rename.argtypes = [ + ctypes.c_int, + ctypes.c_char_p, + ctypes.c_int, + ctypes.c_char_p, + ctypes.c_uint, + ] + rename.restype = ctypes.c_int + result = rename(-100, os.fsencode(staged), -100, os.fsencode(destination), 1) + elif sys.platform == 'darwin': + rename = getattr(library, 'renamex_np', None) + if rename is None: + raise OSError(errno.ENOSYS, 'Atomic exclusive directory publication is unavailable.') + rename.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_uint] + rename.restype = ctypes.c_int + result = rename(os.fsencode(staged), os.fsencode(destination), 4) + else: + raise OSError(errno.ENOSYS, 'Atomic exclusive directory publication is unavailable.') + if result: + code = ctypes.get_errno() + raise OSError(code, os.strerror(code), str(destination)) + + +def _vector(array, name): + if array.ndim == 1 or (array.ndim == 2 and array.shape[1] == 1): + return array.reshape(-1) + raise ValueError(f'{name} must be a vector or column vector.') + + +def _metadata(path): + sidecar = path / '_phy_cluster_metadata.json' + if sidecar.exists(): + metadata = json.loads(sidecar.read_text(encoding='utf-8')) + if not isinstance(metadata, dict): + raise ValueError('Cluster metadata JSON must be a field mapping.') + result = {} + for field, values in metadata.items(): + if not isinstance(values, dict): + raise ValueError('Cluster metadata fields must map integer cluster IDs to values.') + result[field] = {int(key): value for key, value in values.items()} + if any(key < 0 for key in result[field]): + raise ValueError('Cluster metadata IDs must be nonnegative.') + return result + result = {} + for filename in sorted([*path.glob('cluster_*.tsv'), *path.glob('cluster_*.csv')]): + # cluster_info is generated GUI metrics, not a source label table. + if filename.stem == 'cluster_info': + continue + with filename.open(encoding='utf-8', newline='') as stream: + reader = csv.DictReader(stream, delimiter='\t' if filename.suffix == '.tsv' else ',') + if not reader.fieldnames or 'cluster_id' not in reader.fieldnames: + raise ValueError(f'{filename.name} requires a cluster_id column.') + for row in reader: + cluster_id = int(row['cluster_id']) + if cluster_id < 0: + raise ValueError('Cluster metadata IDs must be nonnegative.') + for field, value in row.items(): + if field != 'cluster_id': + result.setdefault(field, {})[cluster_id] = value + return result + + +class Source: + """Read source arrays in batches without constructing a GUI model. + + Duration must come from producer metadata or an explicit argument: the last + spike is never used as acquisition exposure. Intervals are half-open samples. + """ + + def __init__( + self, params_path, duration_seconds=None, valid_intervals=None, batch_size=100000 + ): + self.params_path = Path(params_path).resolve() + self.path = self.params_path.parent + self.params = { + key: value + for key, value in runpy.run_path(str(self.params_path)).items() + if not key.startswith('__') + } + self.batch_size = int(batch_size) + if self.batch_size <= 0: + raise ValueError('batch_size must be positive.') + if 'dtype' in self.params: + try: + raw_dtype = np.dtype(self.params['dtype']) + except (TypeError, ValueError) as error: + raise ValueError('params.py dtype must be a valid raw numeric dtype.') from error + if not np.issubdtype(raw_dtype, np.number): + raise ValueError('params.py dtype must be a valid raw numeric dtype.') + self.sample_rate = float(self.params.get('sample_rate', 0)) + if not np.isfinite(self.sample_rate) or self.sample_rate <= 0: + raise ValueError('A positive finite sample_rate is required.') + upstream = self.path / '_phy_spikes_subset.manifest.json' + recording = {} + if upstream.exists(): + info = json.loads(upstream.read_text(encoding='utf-8')) + if info.get('format') != 'phy_spikes_subset' or info.get('format_version') != 1: + raise ValueError('Unsupported waveform manifest format or version.') + recording = info.get('recording', {}) + upstream_rate = recording.get('sampling_frequency_hz', self.sample_rate) + if upstream_rate != self.sample_rate: + raise ValueError('Waveform manifest sampling rate disagrees with params.py.') + if self.params.get('num_segments', recording.get('num_segments', 1)) != 1: + raise ValueError('Only a single monotonic acquisition segment is supported.') + duration_samples = None + if duration_seconds is not None: + duration_samples = float(duration_seconds) * self.sample_rate + if ( + not np.isfinite(duration_samples) + or duration_samples <= 0 + or duration_samples > np.iinfo(np.int64).max + or not np.isclose(duration_samples, round(duration_samples), rtol=0, atol=1e-6) + ): + raise ValueError('duration_seconds must specify a positive integer sample count.') + duration_samples = int(round(duration_samples)) + if ( + 'num_samples' in self.params + and 'num_samples' in recording + and self.params['num_samples'] != recording['num_samples'] + ): + raise ValueError( + 'Producer sample counts disagree between params and waveform manifest.' + ) + declared_samples = self.params.get('num_samples', recording.get('num_samples')) + if declared_samples is None: + declared_samples = duration_samples + elif duration_samples is not None and int(declared_samples) != duration_samples: + raise ValueError('Explicit duration disagrees with acquisition metadata.') + if declared_samples is None: + raise ValueError( + 'Acquisition exposure is missing; provide duration_seconds or num_samples.' + ) + self.num_samples = int(declared_samples) + if ( + self.num_samples <= 0 + or self.num_samples > np.iinfo(np.int64).max + or self.num_samples != declared_samples + ): + raise ValueError('num_samples must be a positive int64 sample count.') + if ( + 'valid_intervals' in self.params + and 'valid_intervals' in recording + and not np.array_equal( + np.asarray(self.params['valid_intervals']), + np.asarray(recording['valid_intervals']), + ) + ): + raise ValueError( + 'Producer valid_intervals disagree between params and waveform manifest.' + ) + declared_intervals = self.params.get('valid_intervals', recording.get('valid_intervals')) + if valid_intervals is not None and declared_intervals is not None: + if not np.array_equal(np.asarray(valid_intervals), np.asarray(declared_intervals)): + raise ValueError('Explicit valid_intervals disagree with acquisition metadata.') + if valid_intervals is None: + valid_intervals = declared_intervals + intervals = [[0, self.num_samples]] if valid_intervals is None else valid_intervals + raw_intervals = np.asarray(intervals) + if raw_intervals.ndim != 2 or raw_intervals.shape[1] != 2 or not len(raw_intervals): + raise ValueError('valid_intervals must be nonempty sample [start, end) pairs.') + self.valid_intervals = raw_intervals.astype(np.int64) + if ( + not np.array_equal(raw_intervals, self.valid_intervals) + or np.any(self.valid_intervals[:, 0] < 0) + or np.any(self.valid_intervals[:, 1] > self.num_samples) + or np.any(self.valid_intervals[:, 1] <= self.valid_intervals[:, 0]) + or np.any(self.valid_intervals[1:, 0] < self.valid_intervals[:-1, 1]) + ): + raise ValueError( + 'valid_intervals must be ordered, disjoint integer acquisition samples.' + ) + names = {p.name for p in self.path.glob('*.npy')} + unknown = names - PER_SPIKE - STATIC - WAVEFORMS - WINDOW_SIDECARS + # Replay lineage and original optional sidecars are retained; bounded + # outputs deliberately cannot be used as full-source sorting inputs. + if unknown: + raise ValueError(f'Unregistered source arrays: {", ".join(sorted(unknown))}.') + self.arrays = { + name: np.load(self.path / name, mmap_mode='r', allow_pickle=False) + for name in sorted(names) + } + for required in ('spike_times.npy', 'spike_clusters.npy', 'spike_templates.npy'): + if required not in self.arrays: + raise ValueError(f'Missing required source array {required}.') + self.n_spikes = len(_vector(self.arrays['spike_times.npy'], 'spike_times.npy')) + self.metadata = _metadata(self.path) + self.validate() + counts = {} + for batch in self.iter_batches(): + ids, values = np.unique(batch['spike_clusters.npy'], return_counts=True) + for cluster_id, count in zip(ids.tolist(), values.tolist(), strict=True): + counts[cluster_id] = counts.get(cluster_id, 0) + count + for values in self.metadata.values(): + for cluster_id in values: + counts.setdefault(cluster_id, 0) + lineage_path = self.path / '_phy_curation_lineage.json' + lineage = {} + if lineage_path.exists(): + lineage = json.loads(lineage_path.read_text(encoding='utf-8')) + if ( + lineage.get('format') != 'phy_curation_lineage' + or lineage.get('format_version') != 1 + ): + raise ValueError('Unsupported curation lineage format or version.') + for unit in lineage.get('unit_ids', []): + if not isinstance(unit, int) or unit < 0: + raise ValueError('Lineage unit IDs must be nonnegative integers.') + counts.setdefault(unit, 0) + self.unit_ids = np.array(sorted(counts), dtype=np.int64) + minimum_next = int(self.unit_ids[-1]) + 1 if len(self.unit_ids) else 0 + self.next_cluster_id = lineage.get('next_cluster_id', minimum_next) + if not isinstance(self.next_cluster_id, int) or self.next_cluster_id < minimum_next: + raise ValueError('Lineage next_cluster_id collides with the source unit catalog.') + self.counts = np.array( + [counts[cluster_id] for cluster_id in self.unit_ids], dtype=np.int64 + ) + immutable = sorted(names - {'spike_clusters.npy'} - WINDOW_SIDECARS) + # Optional subset planning metadata describes a sampling policy, not a + # new immutable spike-coordinate identity. + acquisition = { + key: self.params[key] + for key in ( + 'acquisition_id', + 'n_channels_dat', + 'dtype', + 'offset', + 'depth_axis', + 'amplitude_units', + 'depth_units', + 'position_units', + 'waveform_units', + ) + if key in self.params + } + self.identity = { + 'format_version': 1, + 'acquisition': acquisition, + 'time_base': { + 'sample_rate': self.sample_rate, + 'num_samples': self.num_samples, + 'valid_intervals': self.valid_intervals.tolist(), + }, + 'arrays': {name: hash_file(self.path / name) for name in immutable}, + } + self.identity['sha256'] = hash_json(self.identity) + self.revision = assignment_revision(self.path, self.metadata) + if lineage: + if ( + lineage.get('coordinate_identity') != self.identity + or lineage.get('revision') != self.revision + ): + raise ValueError( + 'Curation lineage does not match immutable identity or assignments.' + ) + + def close(self): + """Release canonical array mappings after a batch command.""" + for array in self.arrays.values(): + close_array(array) + self.arrays.clear() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + def iter_batches(self): + """Yield bounded row slices; vector fields use one-dimensional views.""" + for start in range(0, self.n_spikes, self.batch_size): + stop = min(start + self.batch_size, self.n_spikes) + batch = {'start': start, 'stop': stop} + for name in self.arrays.keys() & PER_SPIKE: + array = self.arrays[name] + if name in ('spike_times.npy', 'spike_clusters.npy', 'spike_templates.npy'): + array = _vector(array, name) + batch[name] = array[start:stop] + yield batch + + def validate(self): + """Check source row, clock, sparse channel, and feature alignment.""" + for name in self.arrays.keys() & PER_SPIKE: + if self.arrays[name].shape[0] != self.n_spikes: + raise ValueError(f'{name} is not aligned with source spikes.') + for name in ('spike_times.npy', 'spike_clusters.npy', 'spike_templates.npy'): + array = _vector(self.arrays[name], name) + if not np.issubdtype(array.dtype, np.integer): + raise ValueError(f'{name} must contain integer coordinates.') + previous = -1 + for batch in self.iter_batches(): + times = batch['spike_times.npy'] + if ( + np.any(times < previous) + or np.any(times[1:] < times[:-1]) + or np.any(times < 0) + or np.any(times >= self.num_samples) + ): + raise ValueError( + 'Spike sample times must be monotonic and within acquisition bounds.' + ) + if len(times): + previous = int(times[-1]) + interval_ids = np.searchsorted(self.valid_intervals[:, 0], times, side='right') - 1 + if np.any(interval_ids < 0) or np.any(times >= self.valid_intervals[interval_ids, 1]): + raise ValueError('Spike times fall outside valid acquisition intervals.') + for name in ('spike_clusters.npy', 'spike_templates.npy'): + if np.any(batch[name] < 0): + raise ValueError(f'{name} must contain nonnegative IDs.') + templates = self.arrays.get('templates.npy') + if templates is not None and np.any(batch['spike_templates.npy'] >= len(templates)): + raise ValueError('spike_templates.npy references an unavailable template.') + waveforms = self.arrays.keys() & WAVEFORMS + if waveforms and waveforms != WAVEFORMS: + raise ValueError('Stored waveforms require spikes, channels, and waveforms together.') + if waveforms: + ids = self.arrays['_phy_spikes_subset.spikes.npy'] + if ids.ndim != 1 or ids.dtype != np.dtype('int64'): + raise ValueError('Stored waveform row IDs must be a one-dimensional int64 array.') + channels = self.arrays['_phy_spikes_subset.channels.npy'] + values = self.arrays['_phy_spikes_subset.waveforms.npy'] + n_channels = len(self.arrays.get('channel_map.npy', [])) + if ( + values.ndim != 3 + or channels.shape != (len(ids), values.shape[2]) + or len(values) != len(ids) + or not np.issubdtype(channels.dtype, np.integer) + ): + raise ValueError('Stored waveform tensors and channels are not aligned.') + last = -1 + # Sparse-padding checks create temporary boolean arrays and gathers; + # cap their tensor bytes independently of the source row batch size. + row_bytes = max(1, values.dtype.itemsize * int(np.prod(values.shape[1:]))) + waveform_batch = min(self.batch_size, max(1, 8 * 1024 * 1024 // row_bytes)) + for start in range(0, len(ids), waveform_batch): + rows = ids[start : start + waveform_batch] + slots = channels[start : start + waveform_batch] + if ( + np.any(rows <= last) + or np.any(rows[1:] <= rows[:-1]) + or np.any(rows < 0) + or np.any(rows >= self.n_spikes) + ): + raise ValueError('Stored waveform row IDs must be sorted, unique source rows.') + if len(rows): + last = int(rows[-1]) + if np.any((slots < -1) | (slots >= n_channels)): + raise ValueError( + 'Sparse waveform channels must index model channels or use -1.' + ) + block = values[start : start + waveform_batch] + if np.any(np.moveaxis(block, 1, 2)[slots == -1] != 0): + raise ValueError('Sparse waveform padding channels must contain zeros.') + channel_map = self.arrays.get('channel_map.npy') + if channel_map is not None: + channels = _vector(channel_map, 'channel_map.npy') + if ( + not np.issubdtype(channels.dtype, np.integer) + or np.any(channels < 0) + or len(np.unique(channels)) != len(channels) + ): + raise ValueError('channel_map.npy must contain unique nonnegative raw column IDs.') + raw_channels = self.params.get('n_channels_dat') + if raw_channels is not None and ( + int(raw_channels) != raw_channels + or raw_channels <= 0 + or np.any(channels >= raw_channels) + ): + raise ValueError('channel_map.npy contains columns outside n_channels_dat.') + for name in ('channel_groups.npy', 'channel_shanks.npy', 'channel_map_si.npy'): + if name in self.arrays and len(_vector(self.arrays[name], name)) != len(channels): + raise ValueError(f'{name} must align with model channels.') + for name in ('whitening_mat.npy', 'whitening_mat_inv.npy'): + if name in self.arrays and self.arrays[name].shape != ( + len(channels), + len(channels), + ): + raise ValueError(f'{name} must contain a model-channel square matrix.') + templates = self.arrays.get('templates.npy') + if templates is not None: + sparse = self.arrays.get('templates_ind.npy') + if templates.ndim != 3: + raise ValueError('templates.npy must be a template/sample/channel tensor.') + if sparse is None and templates.shape[2] != len(channels): + raise ValueError('Dense templates must align with model channels.') + if sparse is not None: + if sparse.shape != (len(templates), templates.shape[2]): + raise ValueError('templates_ind.npy must align with sparse templates.') + if not np.issubdtype(sparse.dtype, np.integer): + raise ValueError('templates_ind.npy must contain integer channel indices.') + if np.any((sparse < -1) | (sparse >= len(channels))): + raise ValueError('templates_ind.npy contains invalid model channel IDs.') + positions = self.arrays.get('channel_positions.npy') + if positions is not None and (positions.ndim != 2 or len(positions) != len(channels)): + raise ValueError('channel_positions.npy must align with model channels.') + for feature, indices in ( + ('pc_features.npy', 'pc_feature_ind.npy'), + ('template_features.npy', 'template_feature_ind.npy'), + ): + if feature in self.arrays and indices not in self.arrays: + raise ValueError(f'{feature} requires {indices}.') + if feature in self.arrays: + values = self.arrays[feature] + lookup = self.arrays[indices] + if lookup.ndim != 2 or values.ndim < 2 or values.shape[-1] != lookup.shape[1]: + raise ValueError(f'{feature} and {indices} sparse axes do not agree.') + templates = self.arrays.get('templates.npy') + if templates is not None and len(lookup) != len(templates): + raise ValueError(f'{indices} must align with templates.') + if not np.issubdtype(lookup.dtype, np.integer): + raise ValueError(f'{indices} must contain integer indices.') + limit = ( + len(self.arrays.get('channel_map.npy', [])) + if feature == 'pc_features.npy' + else len(lookup) + ) + for start in range(0, len(lookup), self.batch_size): + rows = lookup[start : start + self.batch_size] + if np.any((rows < -1) | (rows >= limit)): + raise ValueError(f'{indices} contains invalid sparse indices.') + return self diff --git a/phy/apps/large_recording/tests/__init__.py b/phy/apps/large_recording/tests/__init__.py new file mode 100644 index 000000000..ba239ecd8 --- /dev/null +++ b/phy/apps/large_recording/tests/__init__.py @@ -0,0 +1 @@ +"""Long-recording workflow regression tests.""" diff --git a/phy/apps/large_recording/tests/test_source.py b/phy/apps/large_recording/tests/test_source.py new file mode 100644 index 000000000..0781ca843 --- /dev/null +++ b/phy/apps/large_recording/tests/test_source.py @@ -0,0 +1,240 @@ +"""Exact source clock, alignment, and identity regressions.""" + +import json + +import numpy as np +import pytest + +from phy.apps.large_recording.source import Source, hash_file + + +def make_sorting(path, columns=False): + path.mkdir() + samples = np.array([0, 1, 1, 2, 5, 6, 10, 11, 14, 18, 19, 19], dtype=np.int64) + clusters = np.array([0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 99, 99], dtype=np.int32) + templates = np.arange(len(samples), dtype=np.int32) % 3 + arrays = { + 'spike_times.npy': samples, + 'spike_clusters.npy': clusters, + 'spike_templates.npy': templates, + 'amplitudes.npy': np.arange(len(samples), dtype=np.float32), + 'spike_positions.npy': np.column_stack((np.zeros(len(samples)), samples * 2)), + 'spike_depths.npy': samples.astype(np.float64) * 2, + 'templates.npy': np.arange(3 * 8 * 3, dtype=np.float32).reshape(3, 8, 3), + 'channel_map.npy': np.array([2, 0, 1], dtype=np.int32), + 'channel_positions.npy': np.array([[0, 0], [0, 10], [0, 20]]), + 'pc_features.npy': np.arange(len(samples) * 4, dtype=np.float32).reshape(-1, 2, 2), + 'pc_feature_ind.npy': np.array([[0, 2], [2, 1], [1, 0]], dtype=np.int32), + } + for name, array in arrays.items(): + if columns and name in ('spike_times.npy', 'spike_clusters.npy', 'spike_templates.npy'): + array = array[:, None] + np.save(path / name, array) + ids = np.array([0, 2, 3, 8, 11], dtype=np.int64) + channels = np.array([[0, -1], [2, 1], [1, -1], [2, -1], [0, 1]], dtype=np.int32) + waveforms = np.zeros((len(ids), 8, 2), dtype=np.float32) + for row, spike in enumerate(ids): + for slot, channel in enumerate(channels[row]): + if channel != -1: + waveforms[row, :, slot] = spike + channel + np.arange(8) / 10 + for suffix, array in (('spikes', ids), ('channels', channels), ('waveforms', waveforms)): + np.save(path / f'_phy_spikes_subset.{suffix}.npy', array) + (path / 'params.py').write_text( + "sample_rate = 1.0\nnum_samples = 20\ndat_path = None\nn_channels_dat = 3\ndtype = 'int16'\n" + ) + (path / 'cluster_group.tsv').write_text( + 'cluster_id\tgroup\n0\tgood\n1\tmua\n2\tgood\n99\tnoise\n' + ) + return path / 'params.py' + + +@pytest.mark.parametrize('columns', [False, True]) +def test_source_batches_ties_counts_columns(tmp_path, columns): + source = Source(make_sorting(tmp_path / 'full', columns), batch_size=2) + assert source.n_spikes == 12 + assert source.unit_ids.tolist() == [0, 1, 2, 99] + assert source.counts.tolist() == [4, 3, 3, 2] + assert all(batch['spike_times.npy'].ndim == 1 for batch in source.iter_batches()) + assert all(isinstance(array, np.memmap) for array in source.arrays.values()) + assert source.metadata['group'][99] == 'noise' + + +def test_identity_assignment_and_feature_layers(tmp_path): + params = make_sorting(tmp_path / 'full') + source = Source(params) + clusters = np.load(params.parent / 'spike_clusters.npy') + clusters[clusters == 1] = 0 + np.save(params.parent / 'spike_clusters.npy', clusters) + merged = Source(params) + assert merged.identity == source.identity + assert merged.revision != source.revision + values = np.load(params.parent / 'amplitudes.npy') + values[0] = 99 + np.save(params.parent / 'amplitudes.npy', values) + altered = Source(params) + assert altered.identity != merged.identity + assert altered.revision == merged.revision + assert ( + hash_file(params.parent / 'amplitudes.npy') == altered.identity['arrays']['amplitudes.npy'] + ) + + +def test_exposure_gaps_and_missing_duration(tmp_path): + params = make_sorting(tmp_path / 'full') + source = Source(params, valid_intervals=[[0, 7], [10, 20]]) + assert source.valid_intervals.tolist() == [[0, 7], [10, 20]] + with pytest.raises(ValueError, match='outside valid'): + Source(params, valid_intervals=[[0, 5], [10, 20]]) + params.write_text(params.read_text().replace('num_samples = 20\n', '')) + with pytest.raises(ValueError, match='exposure is missing'): + Source(params) + assert Source(params, duration_seconds=20).num_samples == 20 + with pytest.raises(ValueError, match='integer sample count'): + Source(params, duration_seconds=20.5) + + +@pytest.mark.parametrize( + 'failure', ['order', 'alignment', 'unknown', 'segment', 'waveforms', 'ids'] +) +def test_reject_ambiguous_or_misaligned_sources(tmp_path, failure): + params = make_sorting(tmp_path / 'full') + path = params.parent + if failure == 'order': + np.save(path / 'spike_times.npy', np.arange(12)[::-1]) + elif failure == 'alignment': + np.save(path / 'pc_features.npy', np.zeros((11, 2, 2))) + elif failure == 'unknown': + np.save(path / 'mysterious.npy', np.ones(12)) + elif failure == 'segment': + params.write_text(params.read_text() + 'num_segments = 2\n') + elif failure == 'waveforms': + (path / '_phy_spikes_subset.channels.npy').unlink() + else: + np.save(path / '_phy_spikes_subset.spikes.npy', np.array([0, 2, 2, 8, 11], dtype=np.int64)) + with pytest.raises(ValueError): + Source(params, batch_size=2) + + +def test_metadata_json_preserves_typed_values(tmp_path): + params = make_sorting(tmp_path / 'full') + metadata = {'group': {'0': 'good'}, 'custom': {'99': None, '2': 4}} + (params.parent / '_phy_cluster_metadata.json').write_text(json.dumps(metadata)) + assert Source(params).metadata == {'group': {0: 'good'}, 'custom': {99: None, 2: 4}} + + +def test_replay_lineage_retains_zero_count_catalog_and_allocator(tmp_path): + params = make_sorting(tmp_path / 'full') + source = Source(params) + lineage = { + 'format': 'phy_curation_lineage', + 'format_version': 1, + 'coordinate_identity': source.identity, + 'revision': source.revision, + 'unit_ids': [0, 1, 2, 99, 103], + 'next_cluster_id': 105, + } + (params.parent / '_phy_curation_lineage.json').write_text(json.dumps(lineage)) + reopened = Source(params) + assert reopened.next_cluster_id == 105 + assert reopened.unit_ids[-1] == 103 + assert reopened.counts[-1] == 0 + assert reopened.identity == source.identity + lineage['next_cluster_id'] = 103 + (params.parent / '_phy_curation_lineage.json').write_text(json.dumps(lineage)) + with pytest.raises(ValueError, match='collides'): + Source(params) + + +def test_unknown_upstream_manifest_version_is_rejected(tmp_path): + params = make_sorting(tmp_path / 'full') + (params.parent / '_phy_spikes_subset.manifest.json').write_text( + json.dumps({'format': 'phy_spikes_subset', 'format_version': 2}) + ) + with pytest.raises(ValueError, match='Unsupported waveform manifest'): + Source(params) + + +def test_integer_clock_beyond_32_bits(tmp_path): + from phy.apps.tests.large_recording_fixtures import make_long_recording_fixture + + fixture = make_long_recording_fixture(tmp_path) + source = Source(fixture.full / 'params.py', batch_size=3) + assert source.num_samples == 1000 * 3600 * 30000 + assert source.arrays['spike_times.npy'][-1] > np.iinfo(np.int32).max + assert source.n_spikes == 32 + + +def test_source_heap_does_not_scale_with_spike_arrays(tmp_path): + import tracemalloc + + peaks = [] + for spikes in (1000, 250000): + path = tmp_path / str(spikes) + path.mkdir() + for name, dtype in ( + ('spike_times.npy', np.int64), + ('spike_clusters.npy', np.int32), + ('spike_templates.npy', np.int32), + ): + values = np.lib.format.open_memmap( + path / name, mode='w+', dtype=dtype, shape=(spikes,) + ) + for start in range(0, spikes, 1024): + stop = min(start + 1024, spikes) + values[start:stop] = np.arange(start, stop) if name == 'spike_times.npy' else 0 + values.flush() + del values + (path / 'params.py').write_text(f'sample_rate = 1\nnum_samples = {spikes}\n') + tracemalloc.start() + source = Source(path / 'params.py', batch_size=1024) + _, peak = tracemalloc.get_traced_memory() + tracemalloc.stop() + assert source.n_spikes == spikes + assert sum(source.counts) == spikes + peaks.append(peak) + # This checks allocated heap; file-backed OS pages are intentionally separate. + assert peaks[-1] < 4 * 1024 * 1024 + assert peaks[-1] - peaks[0] < 3 * 1024 * 1024 + + +def test_explicit_intervals_cannot_override_changed_producer_exposure(tmp_path): + params = make_sorting(tmp_path / 'full') + params.write_text(params.read_text() + 'valid_intervals = [[0, 7], [10, 20]]\n') + with pytest.raises(ValueError, match='disagree with acquisition metadata'): + Source(params, valid_intervals=[[0, 20]]) + with Source(params) as source: + arrays = list(source.arrays.values()) + assert source.valid_intervals.tolist() == [[0, 7], [10, 20]] + assert not source.arrays + assert all(array._mmap.closed for array in arrays) + + +def test_exporter_channel_sidecars_and_raw_map_validation(tmp_path): + params = make_sorting(tmp_path / 'full') + np.save( + params.parent / 'channel_map_si.npy', np.array(['hardware2', 'hardware0', 'hardware1']) + ) + np.save(params.parent / 'channel_groups.npy', np.array([1, 1, 0])) + with Source(params) as source: + assert 'channel_map_si.npy' in source.arrays + params.write_text(params.read_text().replace('n_channels_dat = 3', 'n_channels_dat = 2')) + with pytest.raises(ValueError, match='outside n_channels_dat'): + Source(params) + + +def test_exclusive_publish_preserves_racing_empty_destination(tmp_path): + from phy.apps.large_recording.source import publish_directory + + staged = tmp_path / 'stage' + staged.mkdir() + (staged / 'payload').write_text('complete') + destination = tmp_path / 'destination' + destination.mkdir() + with pytest.raises(FileExistsError): + publish_directory(staged, destination) + assert destination.is_dir() and not list(destination.iterdir()) + assert (staged / 'payload').read_text() == 'complete' + destination.rmdir() + publish_directory(staged, destination) + assert not staged.exists() + assert (destination / 'payload').read_text() == 'complete' From f6915444686858ea7507717e990b01151f18f9c5 Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 10:37:42 +0200 Subject: [PATCH 04/22] Build bounded-memory full-duration counts and additive source trends --- phy/apps/large_recording/summaries.py | 122 ++++++++++++++++++ .../large_recording/tests/test_summaries.py | 67 ++++++++++ 2 files changed, 189 insertions(+) create mode 100644 phy/apps/large_recording/summaries.py create mode 100644 phy/apps/large_recording/tests/test_summaries.py diff --git a/phy/apps/large_recording/summaries.py b/phy/apps/large_recording/summaries.py new file mode 100644 index 000000000..2f498fab5 --- /dev/null +++ b/phy/apps/large_recording/summaries.py @@ -0,0 +1,122 @@ +"""Exact file-backed counts and additive source-measurement summaries.""" + +from contextlib import ExitStack +from pathlib import Path + +import numpy as np + +from .source import close_array + + +def scalar_attributes(source): + """Return available scalar measurements without inventing physical units.""" + attributes = {} + amplitude = source.arrays.get('amplitudes.npy') + if amplitude is not None and (amplitude.ndim == 1 or amplitude.shape[1:] == (1,)): + attributes['amplitude'] = amplitude.reshape(-1) + depth = source.arrays.get('spike_depths.npy') + if depth is not None and (depth.ndim == 1 or depth.shape[1:] == (1,)): + attributes['depth'] = depth.reshape(-1) + elif (positions := source.arrays.get('spike_positions.npy')) is not None: + axis = source.params.get('depth_axis') + if axis is not None: + if ( + not isinstance(axis, int) + or positions.ndim != 2 + or not 0 <= axis < positions.shape[1] + ): + raise ValueError('depth_axis must declare a valid spike_positions.npy coordinate.') + attributes['depth'] = positions[:, axis] + return attributes + + +def summary_size(source, bin_seconds=3600): + """Estimate exact array bytes before allocating the dense output grid.""" + step = float(bin_seconds) * source.sample_rate + if not np.isfinite(step) or step < 1 or not np.isclose(step, round(step), rtol=0, atol=1e-6): + raise ValueError('bin_seconds must specify a positive integer sample width.') + step = int(round(step)) + bins = (source.num_samples + step - 1) // step + size = len(source.unit_ids) * bins * 8 * (1 + 2 * len(scalar_attributes(source))) + size += (bins * 2 + 1) * 8 + return size, step, bins + + +def build_summaries(source, output_dir, bin_seconds=3600, max_bytes=536870912): + """Stream exact full counts, exposure, and finite-value sums/counts. + + Exposure is one shared vector. Summing parent-unit counts on merge must + divide by this vector once. Scalar means are sums/counts, never medians. + """ + size, step, bins = summary_size(source, bin_seconds) + if size + 1024 * (1 + 2 * len(scalar_attributes(source))) > max_bytes: + raise ValueError( + f'Summary budget exceeded: need at least {size} array bytes; ' + 'increase bin_seconds or max_bytes.' + ) + with ExitStack() as stack: + output_dir = Path(output_dir) + output_dir.mkdir(parents=True, exist_ok=True) + result = { + 'counts_file': '_phy_summary_counts.npy', + 'edges_file': '_phy_summary_edges.npy', + 'exposure_file': '_phy_summary_exposure.npy', + } + shape = (len(source.unit_ids), bins) + counts = np.lib.format.open_memmap( + output_dir / result['counts_file'], mode='w+', dtype=np.int64, shape=shape + ) + stack.callback(close_array, counts) + counts[:] = 0 + attributes = scalar_attributes(source) + grids = {} + for field in attributes: + for kind, dtype in (('sum', np.float64), ('count', np.int64)): + key = f'{field}_{kind}_file' + result[key] = f'_phy_summary_{field}_{kind}.npy' + array = np.lib.format.open_memmap( + output_dir / result[key], mode='w+', dtype=dtype, shape=shape + ) + stack.callback(close_array, array) + array[:] = 0 + grids[field, kind] = array + edges = np.lib.format.open_memmap( + output_dir / result['edges_file'], mode='w+', dtype=np.int64, shape=(bins + 1,) + ) + stack.callback(close_array, edges) + # Bounded chunks also avoid a recording-duration-sized temporary arange. + for start in range(0, bins + 1, source.batch_size): + stop = min(start + source.batch_size, bins + 1) + edges[start:stop] = np.arange(start, stop, dtype=np.int64) * step + edges[-1] = source.num_samples + exposure = np.lib.format.open_memmap( + output_dir / result['exposure_file'], mode='w+', dtype=np.float64, shape=(bins,) + ) + stack.callback(close_array, exposure) + exposure[:] = 0 + for start, end in source.valid_intervals: + first, last = int(start // step), int((end - 1) // step) + for offset in range(first, last + 1, source.batch_size): + stop = min(offset + source.batch_size, last + 1) + exposure[offset:stop] += ( + np.minimum(edges[offset + 1 : stop + 1], end) + - np.maximum(edges[offset:stop], start) + ) / source.sample_rate + for batch in source.iter_batches(): + rows = np.searchsorted(source.unit_ids, batch['spike_clusters.npy']) + columns = batch['spike_times.npy'] // step + np.add.at(counts, (rows, columns), 1) + for field, values in attributes.items(): + values = values[batch['start'] : batch['stop']] + finite = np.isfinite(values) + np.add.at(grids[field, 'sum'], (rows[finite], columns[finite]), values[finite]) + np.add.at(grids[field, 'count'], (rows[finite], columns[finite]), 1) + for array in (counts, edges, exposure, *grids.values()): + array.flush() + result['estimators'] = { + 'counts': 'exact', + 'exposure': 'acquisition_seconds', + **dict.fromkeys(attributes, 'finite_sum_and_count'), + } + result['measurement_units'] = {field: f'source {field} units' for field in attributes} + return result diff --git a/phy/apps/large_recording/tests/test_summaries.py b/phy/apps/large_recording/tests/test_summaries.py new file mode 100644 index 000000000..5eb4d03e2 --- /dev/null +++ b/phy/apps/large_recording/tests/test_summaries.py @@ -0,0 +1,67 @@ +"""Full counts and acquisition exposure compared with an independent tiny oracle.""" + +import numpy as np +import pytest + +from phy.apps.large_recording.source import Source +from phy.apps.large_recording.summaries import build_summaries +from phy.apps.large_recording.tests.test_source import make_sorting + + +def test_exact_counts_exposure_and_additive_measurements(tmp_path): + params = make_sorting(tmp_path / 'full', columns=True) + amplitude = np.load(params.parent / 'amplitudes.npy') + amplitude[1] = np.nan + np.save(params.parent / 'amplitudes.npy', amplitude[:, None]) + source = Source(params, valid_intervals=[[0, 7], [10, 20]], batch_size=2) + files = build_summaries(source, tmp_path / 'summary', bin_seconds=5) + counts = np.load(tmp_path / 'summary' / files['counts_file']) + expected = np.zeros((4, 4), dtype=np.int64) + expected_sum = np.zeros((4, 4)) + expected_n = np.zeros((4, 4), dtype=np.int64) + units = np.load(params.parent / 'spike_clusters.npy').reshape(-1) + times = np.load(params.parent / 'spike_times.npy').reshape(-1) + for unit, time, value in zip(units, times, amplitude, strict=True): + row = list(source.unit_ids).index(unit) + column = int(time // 5) + expected[row, column] += 1 + if np.isfinite(value): + expected_sum[row, column] += value + expected_n[row, column] += 1 + np.testing.assert_array_equal(counts, expected) + np.testing.assert_array_equal(counts.sum(axis=1), source.counts) + np.testing.assert_array_equal( + np.load(tmp_path / 'summary' / files['edges_file']), [0, 5, 10, 15, 20] + ) + np.testing.assert_array_equal( + np.load(tmp_path / 'summary' / files['exposure_file']), [5, 2, 5, 5] + ) + np.testing.assert_array_equal( + np.load(tmp_path / 'summary' / files['amplitude_sum_file']), expected_sum + ) + np.testing.assert_array_equal( + np.load(tmp_path / 'summary' / files['amplitude_count_file']), expected_n + ) + assert files['measurement_units']['amplitude'] == 'source amplitude units' + assert 'depth_sum_file' in files + + +def test_summary_budget_checked_before_output_allocation(tmp_path): + source = Source(make_sorting(tmp_path / 'full')) + with pytest.raises(ValueError, match='Summary budget'): + build_summaries(source, tmp_path / 'summary', bin_seconds=1, max_bytes=50) + assert not (tmp_path / 'summary').exists() + + +def test_position_coordinates_require_declared_depth_axis(tmp_path): + from phy.apps.large_recording.summaries import scalar_attributes + + params = make_sorting(tmp_path / 'full') + (params.parent / 'spike_depths.npy').unlink() + with Source(params) as source: + assert 'depth' not in scalar_attributes(source) + params.write_text(params.read_text() + 'depth_axis = 1\n') + with Source(params) as source: + np.testing.assert_array_equal( + scalar_attributes(source)['depth'], source.arrays['spike_positions.npy'][:, 1] + ) From 489750220f03689529c2fcfc05486ce6ecb3165b Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 10:37:42 +0200 Subject: [PATCH 05/22] Add semantic curation journal and recoverable atomic checkpoint generations --- phy/apps/large_recording/curation.py | 638 ++++++++++++++++++ .../large_recording/tests/test_curation.py | 255 +++++++ 2 files changed, 893 insertions(+) create mode 100644 phy/apps/large_recording/curation.py create mode 100644 phy/apps/large_recording/tests/test_curation.py diff --git a/phy/apps/large_recording/curation.py b/phy/apps/large_recording/curation.py new file mode 100644 index 000000000..a37e01456 --- /dev/null +++ b/phy/apps/large_recording/curation.py @@ -0,0 +1,638 @@ +"""Semantic bounded curation and crash-consistent, immutable save generations.""" + +import copy +import hashlib +import json +import os +import shutil +import uuid +from pathlib import Path + +import numpy as np + +from .source import hash_json + +MANIFEST = '_phy_curation_manifest.json' +BASE_ASSIGNMENTS = '_phy_spike_clusters_base.npy' + + +def _json_bytes(value): + return ( + json.dumps(value, sort_keys=True, separators=(',', ':'), allow_nan=False) + '\n' + ).encode() + + +def _digest(value): + return hashlib.sha256(_json_bytes(value)).hexdigest() + + +def _hash_file(path): + digest = hashlib.sha256() + with Path(path).open('rb') as stream: + while chunk := stream.read(1024 * 1024): + digest.update(chunk) + return digest.hexdigest() + + +def _read_json(path): + with Path(path).open(encoding='utf8') as stream: + return json.load(stream) + + +def _write_json(path, value): + with Path(path).open('wb') as stream: + stream.write(_json_bytes(value)) + stream.flush() + os.fsync(stream.fileno()) + + +def _fsync_directory(path): + if os.name != 'nt': + descriptor = os.open(path, os.O_RDONLY) + try: + os.fsync(descriptor) + finally: + os.close(descriptor) + + +def _safe_file(root, name): + if not isinstance(name, str) or Path(name).name != name or name in ('', '.', '..'): + raise ValueError('Manifest/checkpoint filename must be a plain local filename.') + path = Path(root) / name + if path.is_symlink(): + raise ValueError('Manifest/checkpoint files must not be symbolic links.') + return path + + +def _integer(value, name): + if isinstance(value, bool) or not isinstance(value, (int, np.integer)) or value < 0: + raise ValueError(f'{name} must be a nonnegative integer.') + return int(value) + + +def _field_name(field): + if ( + not isinstance(field, str) + or not field + or field in ('.', '..') + or any(char in field for char in ('/', '\\', '\0', '\n', '\r', '\t')) + ): + raise ValueError('Metadata fields must be nonempty safe local field names.') + return field + + +def normalize_metadata(metadata): + """Return JSON-compatible metadata with integer cluster keys.""" + if not isinstance(metadata, dict): + raise ValueError('Cluster metadata must be a field-to-cluster mapping.') + result = {} + for field, values in metadata.items(): + _field_name(field) + if not isinstance(values, dict): + raise ValueError('Invalid cluster metadata field.') + result[field] = {} + for key, value in values.items(): + try: + cluster = int(key) + except (ValueError, TypeError) as error: + raise ValueError('Invalid metadata cluster ID.') from error + if str(cluster) != str(key) or cluster < 0: + raise ValueError('Invalid metadata cluster ID.') + _json_bytes(value) + result[field][cluster] = copy.deepcopy(value) + return result + + +def validate_predicate(predicate): + """Validate a threshold on a canonical full-source scalar attribute.""" + if not isinstance(predicate, dict) or set(predicate) != { + 'attribute', + 'operator', + 'threshold', + 'nonfinite', + }: + raise ValueError('Threshold requires attribute/operator/threshold/nonfinite.') + if predicate['attribute'] not in ('amplitudes.npy', 'spike_templates.npy'): + raise ValueError('Unsupported full-source threshold attribute.') + if predicate['operator'] not in ('<', '<=', '>', '>='): + raise ValueError('Unsupported threshold comparator.') + threshold = predicate['threshold'] + if isinstance(threshold, bool) or not isinstance(threshold, (int, float)): + raise ValueError('Threshold must be a finite number.') + if not np.isfinite(threshold) or predicate['nonfinite'] not in ('keep', 'reject'): + raise ValueError('Threshold needs a finite threshold and explicit nonfinite policy.') + return copy.deepcopy(predicate) + + +def evaluate_predicate(values, predicate): + values = np.asarray(values).reshape(-1) + finite = np.isfinite(values) + if predicate['nonfinite'] == 'reject' and not finite.all(): + raise ValueError('Nonfinite source values violate threshold policy.') + operators = {'<': np.less, '<=': np.less_equal, '>': np.greater, '>=': np.greater_equal} + return finite & operators[predicate['operator']](values, predicate['threshold']) + + +def interpret_events(unit_ids, metadata, events): + """Validate event intent and resolve the final catalog and metadata.""" + active = set(map(int, unit_ids)) + if not active or any(i < 0 for i in active): + raise ValueError('Full source unit catalog must contain nonnegative IDs.') + allocated = set(active) + metadata = normalize_metadata(metadata) + if not isinstance(events, list): + raise ValueError('Semantic journal must be an ordered event list.') + next_id = max(active) + 1 + for event in events: + if not isinstance(event, dict) or event.get('version') != 1: + raise ValueError('Unsupported semantic journal event version.') + operation = event.get('operation') + if operation == 'merge': + if set(event) != {'version', 'operation', 'parents', 'target', 'metadata'}: + raise ValueError('Malformed merge event.') + parents = [_integer(i, 'Parent ID') for i in event['parents']] + target = _integer(event['target'], 'Target ID') + if len(parents) < 2 or len(set(parents)) != len(parents): + raise ValueError('Merge requires at least two distinct complete units.') + if not set(parents) <= active or target in allocated or target < next_id: + raise ValueError('Merge references inactive units or colliding target ID.') + resolved = event['metadata'] + if not isinstance(resolved, dict) or any(not isinstance(f, str) for f in resolved): + raise ValueError('Merge metadata must contain resolved field values.') + _json_bytes(resolved) + for field in resolved: + _field_name(field) + active.difference_update(parents) + active.add(target) + allocated.add(target) + next_id = target + 1 + for values in metadata.values(): + for parent in parents: + values.pop(parent, None) + for field, value in resolved.items(): + metadata.setdefault(field, {})[target] = copy.deepcopy(value) + elif operation == 'label': + if set(event) != {'version', 'operation', 'field', 'ids', 'value'}: + raise ValueError('Malformed label event.') + ids = [_integer(i, 'Label ID') for i in event['ids']] + field = event['field'] + _field_name(field) + if not ids or len(set(ids)) != len(ids) or not set(ids) <= active: + raise ValueError('Label references inactive units or invalid metadata field.') + _json_bytes(event['value']) + values = metadata.setdefault(field, {}) + for cluster in ids: + values[cluster] = copy.deepcopy(event['value']) + elif operation == 'threshold_split': + if set(event) != { + 'version', + 'operation', + 'parent', + 'children', + 'predicate', + 'metadata', + }: + raise ValueError('Malformed threshold split event.') + parent = _integer(event['parent'], 'Parent ID') + children = [_integer(i, 'Child ID') for i in event['children']] + validate_predicate(event['predicate']) + if parent not in active or len(children) != 2 or len(set(children)) != 2: + raise ValueError('Threshold split requires an active parent and two children.') + if any(i in allocated or i < next_id for i in children): + raise ValueError('Threshold split child ID collision.') + resolved = normalize_metadata(event['metadata']) + if any(not set(v) <= set(children) for v in resolved.values()): + raise ValueError('Split metadata must refer only to explicit children.') + active.remove(parent) + active.update(children) + allocated.update(children) + next_id = max(children) + 1 + for values in metadata.values(): + values.pop(parent, None) + for field, values in resolved.items(): + metadata.setdefault(field, {}).update(values) + else: + raise ValueError(f'Unsupported semantic operation: {operation!r}.') + return active, metadata, next_id + + +def project_assignments(assignments, events, attributes=None): + """Interpret a validated journal against a bounded array or full-source batch.""" + output = np.asarray(assignments, dtype=np.int64).reshape(-1).copy() + attributes = attributes or {} + for event in events: + if event['operation'] == 'merge': + output[np.isin(output, event['parents'])] = event['target'] + elif event['operation'] == 'threshold_split': + predicate = event['predicate'] + attribute = predicate['attribute'] + if attribute not in attributes: + raise ValueError(f'Full-source threshold attribute is unavailable: {attribute}.') + mask = output == event['parent'] + values = np.asarray(attributes[attribute]).reshape(-1) + if len(values) != len(output): + raise ValueError('Threshold attribute is not a scalar per-spike array.') + selected = np.zeros(len(output), dtype=bool) + selected[mask] = evaluate_predicate(values[mask], predicate) + output[mask & ~selected] = event['children'][0] + output[mask & selected] = event['children'][1] + return output + + +class BoundedSession: + """Bounded semantic state; reopen establishes a new undo baseline. + + Snapshot/restore integrate with the controller's undo stack. Saving publishes + one pointer after every generation file has been flushed and verified. + """ + + def __init__(self, dataset_path): + self.path = Path(dataset_path) + if self.path.is_file(): + self.path = self.path.parent + self.manifest = _read_json(self.path / MANIFEST) + manifest = self.manifest + required = { + 'source', + 'sample_rate', + 'num_samples', + 'valid_intervals', + 'num_spikes', + 'bounded_num_spikes', + 'unit_ids', + 'counts', + 'next_cluster_id', + 'global_spike_ids_file', + 'windows_file', + } + if manifest.get('format') != 'phy_bounded_curation' or manifest.get('format_version') != 1: + raise ValueError('Unsupported bounded curation manifest version.') + if not required <= set(manifest): + raise ValueError( + 'Incomplete bounded curation manifest; regenerate with prepare-large.' + ) + source = manifest['source'] + if not isinstance(source, dict) or not {'identity', 'revision', 'path'} <= set(source): + raise ValueError('Bounded manifest needs source identity and assignment revision.') + if not isinstance(source['identity'], dict) or not isinstance(source['revision'], str): + raise ValueError('Invalid source identity or revision.') + identity = source['identity'] + identity_fields = {'format_version', 'acquisition', 'time_base', 'arrays', 'sha256'} + if ( + not identity_fields <= set(identity) + or identity.get('format_version') != 1 + or identity['sha256'] + != hash_json({k: v for k, v in identity.items() if k != 'sha256'}) + or len(source['revision']) != 64 + or any(c not in '0123456789abcdef' for c in source['revision']) + ): + raise ValueError('Invalid source coordinate identity or assignment revision digest.') + n = _integer(manifest['bounded_num_spikes'], 'Bounded spike count') + full_n = _integer(manifest['num_spikes'], 'Full spike count') + samples = _integer(manifest['num_samples'], 'Recording sample count') + if not n or n > full_n or not samples or not np.isfinite(manifest['sample_rate']): + raise ValueError('Invalid bounded counts or recording duration.') + if manifest['sample_rate'] <= 0: + raise ValueError('Sampling rate must be positive.') + if identity['time_base'] != { + 'sample_rate': manifest['sample_rate'], + 'num_samples': samples, + 'valid_intervals': manifest['valid_intervals'], + }: + raise ValueError('Bounded time base disagrees with immutable source identity.') + self.unit_ids = [_integer(i, 'Unit ID') for i in manifest['unit_ids']] + if not self.unit_ids or len(set(self.unit_ids)) != len(self.unit_ids): + raise ValueError('Full unit catalog must contain distinct unit IDs.') + counts = np.asarray(manifest['counts']) + if ( + counts.shape != (len(self.unit_ids),) + or counts.dtype.kind not in 'iu' + or np.any(counts < 0) + or sum(map(int, counts)) != full_n + ): + raise ValueError('Full unit counts do not match the source spike count/catalog.') + self.base_next_cluster_id = _integer(manifest['next_cluster_id'], 'Next cluster ID') + if self.base_next_cluster_id <= max(self.unit_ids): + raise ValueError('Cluster allocator collides with the complete source catalog.') + intervals = np.asarray(manifest['valid_intervals']) + if ( + intervals.ndim != 2 + or intervals.shape[1] != 2 + or not len(intervals) + or intervals.dtype.kind not in 'iu' + ): + raise ValueError('Valid acquisition intervals must be integer [start, end) pairs.') + if ( + np.any(intervals[:, 0] < 0) + or np.any(intervals[:, 1] > samples) + or np.any(intervals[:, 1] <= intervals[:, 0]) + or np.any(intervals[1:, 0] < intervals[:-1, 1]) + ): + raise ValueError('Invalid or overlapping acquisition intervals.') + self.global_ids = np.load( + _safe_file(self.path, manifest['global_spike_ids_file']), mmap_mode='r' + ) + if self.global_ids.dtype != np.int64 or self.global_ids.shape != (n,): + raise ValueError('Global spike IDs must be a one-dimensional int64 mapping.') + if ( + np.any(self.global_ids < 0) + or np.any(self.global_ids >= full_n) + or np.any(self.global_ids[1:] <= self.global_ids[:-1]) + ): + raise ValueError('Global spike IDs must be sorted, unique source row indices.') + windows = np.load(_safe_file(self.path, manifest['windows_file']), mmap_mode='r') + if ( + windows.ndim != 2 + or windows.shape[1] != 2 + or not len(windows) + or windows.dtype != np.int64 + ): + raise ValueError('Evidence windows must be int64 sample intervals.') + if ( + np.any(windows[:, 0] < 0) + or np.any(windows[:, 1] > samples) + or np.any(windows[:, 1] <= windows[:, 0]) + or np.any(windows[1:, 0] < windows[:-1, 1]) + ): + raise ValueError('Invalid or overlapping evidence windows.') + for start, stop in windows: + if not any(left <= start and stop <= right for left, right in intervals): + raise ValueError('Evidence windows cross unsupported acquisition gaps.') + for name, digest in manifest.get('bounded_files', {}).items(): + if _hash_file(_safe_file(self.path, name)) != digest: + raise ValueError(f'Bounded package integrity check failed: {name}.') + hashed_files = manifest.get('bounded_files', {}) + if not { + BASE_ASSIGNMENTS, + manifest['global_spike_ids_file'], + manifest['windows_file'], + 'spike_times.npy', + } <= set(hashed_files): + raise ValueError('Bounded manifest lacks required immutable array digests.') + self.base_assignments = np.load(self.path / BASE_ASSIGNMENTS, mmap_mode='r') + if ( + self.base_assignments.shape != (n,) + or self.base_assignments.dtype.kind not in 'iu' + or not set(np.unique(self.base_assignments)) <= set(self.unit_ids) + ): + raise ValueError('Immutable bounded assignments do not match the full catalog.') + self.base_metadata = normalize_metadata( + manifest.get('base_metadata', manifest.get('metadata', {})) + ) + if any(not set(values) <= set(self.unit_ids) for values in self.base_metadata.values()): + raise ValueError('Base metadata refers to units outside the full source catalog.') + bounded_times = np.load(self.path / 'spike_times.npy', mmap_mode='r').reshape(-1) + if ( + bounded_times.shape != (n,) + or bounded_times.dtype.kind not in 'iu' + or np.any(bounded_times[1:] < bounded_times[:-1]) + ): + raise ValueError('Bounded spike sample coordinates have invalid alignment/order.') + window_ids = np.searchsorted(windows[:, 0], bounded_times, side='right') - 1 + if np.any(window_ids < 0) or np.any(bounded_times >= windows[window_ids, 1]): + raise ValueError('Bounded spikes lie outside the recorded evidence windows.') + self.attributes = {} + for name in ('amplitudes.npy', 'spike_templates.npy'): + if (self.path / name).exists(): + self.attributes[name] = np.load(self.path / name, mmap_mode='r') + self.assignments = np.asarray(self.base_assignments, dtype=np.int64).copy() + self.metadata = copy.deepcopy(self.base_metadata) + self.events = [] + self.extra_documents = {} + self.next_cluster_id = self.base_next_cluster_id + self.checkpoint_path = None + pointer_path = self.path / '.phy-curation' / 'current.json' + if pointer_path.exists(): + self._load_checkpoint(pointer_path) + + def _validated_state(self, assignments, metadata, events, next_cluster_id): + _, projected_metadata, minimum = interpret_events( + self.unit_ids, self.base_metadata, events + ) + projected = project_assignments(self.base_assignments, events, self.attributes) + values = np.asarray(assignments) + if values.dtype.kind not in 'iu' or values.shape != projected.shape: + raise ValueError('Checkpoint assignments have invalid shape or dtype.') + if not np.array_equal(values, projected): + raise ValueError('Checkpoint assignments disagree with semantic journal projection.') + if normalize_metadata(metadata) != projected_metadata: + raise ValueError('Checkpoint metadata disagrees with semantic journal projection.') + minimum = max(minimum, self.base_next_cluster_id) + next_cluster_id = _integer(next_cluster_id, 'Next cluster ID') + if next_cluster_id < minimum: + raise ValueError('Checkpoint allocator collides with journal IDs.') + return projected, projected_metadata, next_cluster_id + + def _load_checkpoint(self, pointer_path): + pointer = _read_json(pointer_path) + generation = _safe_file(pointer_path.parent / 'generations', pointer['generation']) + descriptor = _read_json(generation / 'checkpoint.json') + if _digest(descriptor) != pointer['sha256']: + raise ValueError('Checkpoint commit pointer digest is invalid.') + if descriptor.get('version') != 1 or descriptor.get('manifest_sha256') != _digest( + self.manifest + ): + raise ValueError('Checkpoint belongs to a different bounded manifest.') + for name, digest in descriptor['files'].items(): + if _hash_file(_safe_file(generation, name)) != digest: + raise ValueError(f'Checkpoint corruption: {name}.') + if not {'spike_clusters.npy', 'journal.json', 'metadata.json'} <= set(descriptor['files']): + raise ValueError('Incomplete checkpoint file inventory.') + events = _read_json(generation / 'journal.json') + for event in events: + if event.get('operation') == 'threshold_split': + event['metadata'] = normalize_metadata(event['metadata']) + metadata = _read_json(generation / 'metadata.json') + assignments = np.load(generation / 'spike_clusters.npy', mmap_mode='r') + values, metadata, next_id = self._validated_state( + assignments, metadata, events, descriptor['next_cluster_id'] + ) + self.assignments, self.metadata = values, metadata + self.events = events + self.next_cluster_id = next_id + self.checkpoint_path = generation + self.extra_documents = { + name: _read_json(generation / name) for name in descriptor.get('extra_documents', []) + } + + def snapshot(self): + return { + 'assignments': self.assignments.copy(), + 'metadata': copy.deepcopy(self.metadata), + 'events': copy.deepcopy(self.events), + 'next_cluster_id': self.next_cluster_id, + } + + def journal_state(self): + """Return a compact history prefix without copying bounded spike arrays. + + Commands append event dictionaries and never modify earlier events. The + tuple shares those immutable event records between history entries. + """ + return {'events': tuple(self.events), 'next_cluster_id': self.next_cluster_id} + + def restore_journal(self, state): + """Restore an active history prefix while preserving allocator high-water.""" + events = list(state['events']) + _, metadata, minimum = interpret_events(self.unit_ids, self.base_metadata, events) + next_id = _integer(state['next_cluster_id'], 'Next cluster ID') + if next_id < max(minimum, self.base_next_cluster_id): + raise ValueError('History allocator collides with semantic journal IDs.') + assignments = project_assignments(self.base_assignments, events, self.attributes) + self.assignments, self.metadata, self.events = assignments, metadata, events + self.next_cluster_id = max(self.next_cluster_id, next_id) + + def close(self): + """Release file-backed bounded readers independently of the GUI model.""" + for array in (self.global_ids, self.base_assignments, *self.attributes.values()): + mapping = getattr(array, '_mmap', None) + if mapping is not None and not mapping.closed: + mapping.close() + + def restore(self, snapshot): + assignments, metadata, next_id = self._validated_state(**snapshot) + self.assignments, self.metadata = assignments, metadata + self.events = copy.deepcopy(snapshot['events']) + self.next_cluster_id = next_id + + def _append(self, event): + events = self.events + [event] + _, metadata, next_id = interpret_events(self.unit_ids, self.base_metadata, events) + assignments = project_assignments(self.base_assignments, events, self.attributes) + self.assignments, self.metadata, self.events = assignments, metadata, events + self.next_cluster_id = max(self.next_cluster_id, next_id) + return copy.deepcopy(event) + + def preflight_merge(self, parents, target, metadata=None): + event = { + 'version': 1, + 'operation': 'merge', + 'parents': [int(i) for i in parents], + 'target': _integer(target, 'Target ID'), + 'metadata': copy.deepcopy(metadata or {}), + } + if event['target'] < self.next_cluster_id: + raise ValueError('Merge target is below the complete catalog allocator.') + interpret_events(self.unit_ids, self.base_metadata, self.events + [event]) + return event + + def record_merge(self, parents, target, metadata=None): + return self._append(self.preflight_merge(parents, target, metadata)) + + def record_label(self, field, ids, value): + return self._append( + { + 'version': 1, + 'operation': 'label', + 'field': field, + 'ids': [int(i) for i in ids], + 'value': copy.deepcopy(value), + } + ) + + def record_threshold_split(self, parent, children, predicate, metadata=None): + """Pure replay service; the bounded GUI currently keeps splits disabled.""" + children = [int(i) for i in children] + if any(i < self.next_cluster_id for i in children): + raise ValueError('Threshold children collide with the complete catalog allocator.') + return self._append( + { + 'version': 1, + 'operation': 'threshold_split', + 'parent': int(parent), + 'children': children, + 'predicate': validate_predicate(predicate), + 'metadata': copy.deepcopy(metadata or {}), + } + ) + + def preflight_split(self, parent, selected_id, remainder_id, predicate, metadata=None): + children = [int(remainder_id), int(selected_id)] + if any(i < self.next_cluster_id for i in children): + raise ValueError('Threshold children collide with the complete catalog allocator.') + event = { + 'version': 1, + 'operation': 'threshold_split', + 'parent': int(parent), + 'children': children, + 'predicate': validate_predicate(predicate), + 'metadata': copy.deepcopy(metadata or {}), + } + interpret_events(self.unit_ids, self.base_metadata, self.events + [event]) + project_assignments(self.base_assignments, self.events + [event], self.attributes) + return event + + def record_split(self, parent, selected_id, remainder_id, predicate, metadata=None): + return self._append( + self.preflight_split(parent, selected_id, remainder_id, predicate, metadata) + ) + + def save( + self, + assignments=None, + metadata=None, + events=None, + next_cluster_id=None, + extra_documents=None, + ): + """Validate, flush a generation, then atomically replace its commit pointer.""" + assignments = self.assignments if assignments is None else assignments + metadata = self.metadata if metadata is None else metadata + events = self.events if events is None else events + next_cluster_id = self.next_cluster_id if next_cluster_id is None else next_cluster_id + values, metadata, next_id = self._validated_state( + assignments, metadata, events, next_cluster_id + ) + documents = copy.deepcopy( + self.extra_documents if extra_documents is None else extra_documents + ) + if not isinstance(documents, dict): + raise ValueError('Extra checkpoint documents must be a filename-to-JSON mapping.') + for name, value in documents.items(): + _safe_file(self.path, name) + if name in ('checkpoint.json', 'spike_clusters.npy', 'journal.json', 'metadata.json'): + raise ValueError('Extra document collides with a checkpoint state file.') + _json_bytes(value) + root = self.path / '.phy-curation' + generations = root / 'generations' + generations.mkdir(parents=True, exist_ok=True) + _fsync_directory(root) + _fsync_directory(self.path) + identifier = uuid.uuid4().hex + stage = generations / f'.{identifier}.tmp' + final = generations / identifier + stage.mkdir() + pointer_tmp = root / f'.current-{identifier}.tmp' + try: + np.save(stage / 'spike_clusters.npy', values) + with (stage / 'spike_clusters.npy').open('rb') as stream: + os.fsync(stream.fileno()) + _write_json(stage / 'journal.json', events) + _write_json(stage / 'metadata.json', metadata) + for name, value in documents.items(): + _write_json(stage / name, value) + descriptor = { + 'version': 1, + 'manifest_sha256': _digest(self.manifest), + 'next_cluster_id': next_id, + 'files': { + name: _hash_file(stage / name) + for name in ('spike_clusters.npy', 'journal.json', 'metadata.json', *documents) + }, + 'extra_documents': sorted(documents), + } + _write_json(stage / 'checkpoint.json', descriptor) + _fsync_directory(stage) + os.replace(stage, final) + _fsync_directory(generations) + _write_json(pointer_tmp, {'generation': identifier, 'sha256': _digest(descriptor)}) + os.replace(pointer_tmp, root / 'current.json') + _fsync_directory(root) + except BaseException: + shutil.rmtree(stage, ignore_errors=True) + pointer_tmp.unlink(missing_ok=True) + raise + self.assignments, self.metadata, self.events = values, metadata, copy.deepcopy(events) + self.next_cluster_id, self.checkpoint_path = next_id, final + self.extra_documents = documents + return final diff --git a/phy/apps/large_recording/tests/test_curation.py b/phy/apps/large_recording/tests/test_curation.py new file mode 100644 index 000000000..5de69f1f7 --- /dev/null +++ b/phy/apps/large_recording/tests/test_curation.py @@ -0,0 +1,255 @@ +"""Exact bounded journal projection and transactional persistence regressions.""" + +import json +import shutil + +import numpy as np +import pytest + +from phy.apps.large_recording.curation import BASE_ASSIGNMENTS, BoundedSession +from phy.apps.large_recording.source import Source, hash_file +from phy.apps.tests.large_recording_fixtures import make_long_recording_fixture + + +def make_session(tmp_path): + fixture = make_long_recording_fixture(tmp_path) + # The highest complete-source unit is intentionally absent from evidence. + clusters = np.load(fixture.full / 'spike_clusters.npy') + clusters[-1] = 99 + np.save(fixture.full / 'spike_clusters.npy', clusters) + (fixture.full / 'cluster_group.tsv').write_text('cluster_id\tgroup\n0\tgood\n1\tnoise\n') + source = Source(fixture.full / 'params.py', batch_size=5) + rows = np.array([0, 2, 5, 8, 13, 21, 25], dtype=np.int64) + for name in ('spike_times.npy', 'spike_clusters.npy', 'spike_templates.npy', 'amplitudes.npy'): + np.save(fixture.bounded / name, source.arrays[name][rows]) + np.save(fixture.bounded / BASE_ASSIGNMENTS, clusters[rows]) + np.save(fixture.bounded / '_phy_spike_global_ids.npy', rows) + np.save(fixture.bounded / 'windows.npy', np.array([[0, source.num_samples]], dtype=np.int64)) + manifest = { + 'format': 'phy_bounded_curation', + 'format_version': 1, + 'source': { + 'identity': source.identity, + 'revision': source.revision, + 'path': str(source.params_path), + }, + 'sample_rate': source.sample_rate, + 'num_samples': source.num_samples, + 'valid_intervals': source.valid_intervals.tolist(), + 'num_spikes': source.n_spikes, + 'bounded_num_spikes': len(rows), + 'unit_ids': source.unit_ids.tolist(), + 'counts': source.counts.tolist(), + 'next_cluster_id': 100, + 'global_spike_ids_file': '_phy_spike_global_ids.npy', + 'windows_file': 'windows.npy', + 'base_metadata': source.metadata, + 'bounded_files': { + name: hash_file(fixture.bounded / name) + for name in ( + BASE_ASSIGNMENTS, + '_phy_spike_global_ids.npy', + 'windows.npy', + 'spike_times.npy', + ) + }, + } + (fixture.bounded / '_phy_curation_manifest.json').write_text(json.dumps(manifest)) + return source, BoundedSession(fixture.bounded) + + +def test_merge_label_snapshot_branch_reopen(tmp_path): + source, session = make_session(tmp_path) + baseline = session.snapshot() + session.record_merge([0, 1], 100, {'group': 'good'}) + first = session.snapshot() + session.record_label('group', [100], 'mua') + second = session.snapshot() + session.restore(first) + assert session.metadata['group'][100] == 'good' + session.restore(second) + assert session.metadata['group'][100] == 'mua' + session.restore(baseline) + session.record_merge([1, 2], 100, {'group': 'noise'}) + session.record_label('custom', [99, 100], 'reviewed') + session.save(extra_documents={'curation_review.json': {'accepted': [100]}}) + reopened = BoundedSession(session.path) + assert reopened.next_cluster_id == 101 + assert reopened.events == session.events + assert reopened.metadata == session.metadata + assert np.array_equal(reopened.assignments, session.assignments) + assert reopened.extra_documents == {'curation_review.json': {'accepted': [100]}} + assert source.unit_ids.tolist() == [0, 1, 2, 99] + assert 99 not in session.base_assignments + + +@pytest.mark.parametrize('parents,target', [([0, 1], 99), ([0, 0], 100), ([0, 3], 100)]) +def test_merge_collision_and_invalid_parents_do_not_mutate(tmp_path, parents, target): + _, session = make_session(tmp_path) + before = session.snapshot() + with pytest.raises(ValueError): + session.record_merge(parents, target) + assert session.events == before['events'] + assert np.array_equal(session.assignments, before['assignments']) + + +def test_save_requires_exact_semantic_projection(tmp_path): + _, session = make_session(tmp_path) + session.record_merge([0, 1], 100, {'group': 'good'}) + with pytest.raises(ValueError, match='projection'): + session.save(assignments=session.base_assignments) + with pytest.raises(ValueError, match='metadata'): + session.save(metadata={}) + assert not (session.path / '.phy-curation' / 'current.json').exists() + + +@pytest.mark.parametrize('fail_at', ['journal.json', 'checkpoint.json', 'pointer']) +def test_interrupted_save_recovers_previous_generation(tmp_path, monkeypatch, fail_at): + from phy.apps.large_recording import curation + + _, session = make_session(tmp_path) + session.record_merge([0, 1], 100, {'group': 'good'}) + session.save() + previous = session.snapshot() + session.record_label('group', [100], 'mua') + original = curation._write_json + + def fail(path, value): + if path.name == fail_at or (fail_at == 'pointer' and path.name.startswith('.current-')): + raise OSError('injected interrupted write') + return original(path, value) + + monkeypatch.setattr(curation, '_write_json', fail) + with pytest.raises(OSError, match='interrupted'): + session.save() + reopened = BoundedSession(session.path) + assert reopened.events == previous['events'] + assert reopened.metadata == previous['metadata'] + assert session.metadata['group'][100] == 'mua' + + +def test_checkpoint_corruption_is_rejected(tmp_path): + _, session = make_session(tmp_path) + session.save() + (session.checkpoint_path / 'journal.json').write_text('[]\nchanged') + with pytest.raises(ValueError, match='corruption'): + BoundedSession(session.path) + + +def test_bound_base_corruption_is_rejected(tmp_path): + _, session = make_session(tmp_path) + shutil.copyfile(session.path / 'spike_times.npy', session.path / BASE_ASSIGNMENTS) + with pytest.raises(ValueError, match='integrity'): + BoundedSession(session.path) + + +def test_threshold_projection_is_serialized_and_nonfinite_policy_explicit(tmp_path): + _, session = make_session(tmp_path) + predicate = { + 'attribute': 'amplitudes.npy', + 'operator': '<', + 'threshold': 15.0, + 'nonfinite': 'keep', + } + session.record_split(2, 100, 101, predicate, {'group': {100: 'noise', 101: 'good'}}) + expected = session.base_assignments.astype(np.int64).copy() + mask = expected == 2 + selected = np.load(session.path / 'amplitudes.npy') < 15 + expected[mask & selected] = 100 + expected[mask & ~selected] = 101 + assert np.array_equal(session.assignments, expected) + session.save() + assert BoundedSession(session.path).events == session.events + with pytest.raises(ValueError, match='Unsupported'): + session.record_split(0, 102, 103, dict(predicate, attribute='waveform_peak')) + + +@pytest.mark.parametrize('boundary', ['generation', 'pointer']) +def test_atomic_publication_failure_preserves_previous_commit(tmp_path, monkeypatch, boundary): + from phy.apps.large_recording import curation + + _, session = make_session(tmp_path) + session.save() + session.record_merge([0, 1], 100, {'group': 'good'}) + original = curation.os.replace + + def fail(source, destination): + if (boundary == 'generation' and destination.parent.name == 'generations') or ( + boundary == 'pointer' and destination.name == 'current.json' + ): + raise OSError('injected atomic publication failure') + return original(source, destination) + + monkeypatch.setattr(curation.os, 'replace', fail) + with pytest.raises(OSError, match='publication'): + session.save() + assert BoundedSession(session.path).events == [] + assert len(session.events) == 1 + + +def test_nonfinite_predicate_keep_and_reject_are_explicit(): + from phy.apps.large_recording.curation import evaluate_predicate + + values = np.array([1.0, np.nan, np.inf, -np.inf, 3.0]) + predicate = { + 'attribute': 'amplitudes.npy', + 'operator': '<', + 'threshold': 2.0, + 'nonfinite': 'keep', + } + assert evaluate_predicate(values, predicate).tolist() == [True, False, False, False, False] + with pytest.raises(ValueError, match='Nonfinite'): + evaluate_predicate(values, dict(predicate, nonfinite='reject')) + + +def test_semantically_corrupt_checkpoint_rejected_even_with_valid_file_hashes(tmp_path): + from phy.apps.large_recording.curation import _digest + + _, session = make_session(tmp_path) + session.record_merge([0, 1], 100, {'group': 'good'}) + session.save() + generation = session.checkpoint_path + journal = json.loads((generation / 'journal.json').read_text()) + journal[0]['target'] = 99 + (generation / 'journal.json').write_text(json.dumps(journal)) + descriptor = json.loads((generation / 'checkpoint.json').read_text()) + descriptor['files']['journal.json'] = hash_file(generation / 'journal.json') + (generation / 'checkpoint.json').write_text(json.dumps(descriptor)) + pointer = {'generation': generation.name, 'sha256': _digest(descriptor)} + (session.path / '.phy-curation' / 'current.json').write_text(json.dumps(pointer)) + with pytest.raises(ValueError, match='colliding'): + BoundedSession(session.path) + + +def test_compact_history_preserves_allocator_and_reconstructs_assignments(tmp_path): + _, session = make_session(tmp_path) + before = session.journal_state() + session.record_merge([0, 1], 100, {'group': 'good'}) + after = session.journal_state() + merged = session.assignments.copy() + assert set(after) == {'events', 'next_cluster_id'} + assert after['events'][0] is session.events[0] + session.restore_journal(before) + assert session.events == [] + assert session.next_cluster_id == 101 + assert np.array_equal(session.assignments, session.base_assignments) + session.restore_journal(after) + assert np.array_equal(session.assignments, merged) + session.restore_journal(before) + session.record_merge([1, 2], 101, {'group': 'noise'}) + assert session.next_cluster_id == 102 + + +def test_session_close_releases_own_file_mappings(tmp_path): + _, session = make_session(tmp_path) + mappings = [ + array._mmap + for array in ( + session.global_ids, + session.base_assignments, + *session.attributes.values(), + ) + ] + session.close() + assert all(mapping.closed for mapping in mappings) + session.close() From 1237823b640d02f1d0aa26ae0dff9e33041bb037 Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 10:37:42 +0200 Subject: [PATCH 06/22] Prepare budgeted shared-window evidence with exact waveform and feature mappings --- phy/apps/large_recording/prepare.py | 500 ++++++++++++++++++ .../large_recording/tests/test_prepare.py | 174 ++++++ 2 files changed, 674 insertions(+) create mode 100644 phy/apps/large_recording/prepare.py create mode 100644 phy/apps/large_recording/tests/test_prepare.py diff --git a/phy/apps/large_recording/prepare.py b/phy/apps/large_recording/prepare.py new file mode 100644 index 000000000..15920b1ef --- /dev/null +++ b/phy/apps/large_recording/prepare.py @@ -0,0 +1,500 @@ +"""Publish a self-contained bounded evidence package from a full sorting.""" + +import csv +import json +import os +import shutil +import tempfile +from pathlib import Path + +import numpy as np + +from .source import ( + PER_SPIKE, + STATIC, + WAVEFORMS, + Source, + close_array, + hash_file, + hash_json, + publish_directory, +) +from .summaries import build_summaries, scalar_attributes, summary_size + + +def _row_bounds(times, windows): + return [ + ( + int(np.searchsorted(times, start, side='left')), + int(np.searchsorted(times, end, side='left')), + ) + for start, end in windows + ] + + +def _union(windows): + result = [] + for start, end in sorted(windows): + if result and start <= result[-1][1]: + result[-1][1] = max(result[-1][1], int(end)) + else: + result.append([int(start), int(end)]) + return result + + +def _write_metadata(path, metadata): + for field, values in metadata.items(): + if ( + not isinstance(field, str) + or not field + or '/' in field + or '\\' in field + or field in ('.', '..') + ): + raise ValueError('Metadata field names must be safe filenames.') + with (path / f'cluster_{field}.tsv').open('w', encoding='utf-8', newline='') as stream: + writer = csv.writer(stream, delimiter='\t') + writer.writerow(['cluster_id', field]) + writer.writerows(sorted(values.items())) + + +def _selected_waveform_count(source, windows): + ids = source.arrays.get('_phy_spikes_subset.spikes.npy') + if ids is None: + return 0 + return sum( + int(np.searchsorted(ids, stop) - np.searchsorted(ids, start)) + for start, stop in _row_bounds(source.arrays['spike_times.npy'].reshape(-1), windows) + ) + + +def prepare_large( + params_path, + output_dir, + duration_seconds=None, + valid_intervals=None, + max_spikes=2000000, + max_bytes=536870912, + window_seconds=30, + stratum_seconds=3600, + seed=0, + batch_size=100000, + bin_seconds=3600, +): + """Choose complete shared windows, write bounded arrays, and publish atomically. + + Survey windows use a seeded offset within each acquisition stratum. A second + pass tries one first-spike rescue window for every unit without evidence. + Candidate windows that exceed either budget are explicitly omitted; spikes + within accepted windows are never independently thinned. + """ + with Source(params_path, duration_seconds, valid_intervals, batch_size) as source: + return _prepare_source( + source, + output_dir, + max_spikes, + max_bytes, + window_seconds, + stratum_seconds, + seed, + batch_size, + bin_seconds, + ) + + +def _prepare_source( + source, + output_dir, + max_spikes, + max_bytes, + window_seconds, + stratum_seconds, + seed, + batch_size, + bin_seconds, +): + output_dir = Path(output_dir).resolve() + missing_static = { + 'templates.npy', + 'channel_map.npy', + 'channel_positions.npy', + } - source.arrays.keys() + if missing_static: + raise ValueError(f'Bounded GUI preparation requires: {", ".join(sorted(missing_static))}.') + if output_dir.exists(): + raise ValueError(f'Output already exists: {output_dir}.') + if output_dir == source.path or source.path in output_dir.parents: + raise ValueError('Bounded output must be outside the source dataset directory.') + if int(max_spikes) != max_spikes or max_spikes <= 0 or max_bytes <= 0: + raise ValueError('max_spikes and max_bytes must be positive budgets.') + widths = [] + for label, seconds in ( + ('window_seconds', window_seconds), + ('stratum_seconds', stratum_seconds), + ): + width = float(seconds) * source.sample_rate + if ( + not np.isfinite(width) + or width < 1 + or not np.isclose(width, round(width), rtol=0, atol=1e-6) + ): + raise ValueError(f'{label} must specify a positive integer sample width.') + widths.append(int(round(width))) + width, stratum = widths + times = source.arrays['spike_times.npy'].reshape(-1) + assignments = source.arrays['spike_clusters.npy'].reshape(-1) + summary_bytes = summary_size(source, bin_seconds)[0] + producer_documents = [ + source.path / name + for name in ('curation.json', 'curation_review.json') + if (source.path / name).is_file() + ] + fixed_bytes = ( + sum(path.stat().st_size for path in producer_documents) + + summary_bytes + + sum((source.path / name).stat().st_size for name in source.arrays.keys() & STATIC) + ) + # Reserve headers, manifest, params, metadata, and window records explicitly. + metadata_bytes = sum( + len(str(value).encode('utf-8')) + 64 + for values in source.metadata.values() + for value in values.values() + ) + overhead = 32768 + metadata_bytes + 1024 * len(source.arrays) + fixed_bytes += overhead + row_bytes = 16 # int64 global row mapping and baseline assignment + for name in source.arrays.keys() & PER_SPIKE: + array = source.arrays[name] + row_bytes += array.dtype.itemsize * int(np.prod(array.shape[1:], dtype=np.int64)) + waveform_bytes = 0 + if source.arrays.keys() >= WAVEFORMS: + for name in WAVEFORMS: + array = source.arrays[name] + waveform_bytes += array.dtype.itemsize * int(np.prod(array.shape[1:], dtype=np.int64)) + if fixed_bytes > max_bytes: + raise ValueError( + f'Output budget exceeded before selecting evidence: estimated ' + f'{fixed_bytes} bytes; increase max_bytes or bin_seconds.' + ) + windows, plan, omitted = [], [], [] + rng = np.random.default_rng(seed) + + def accept(start, end, kind, segment, stratum_id): + candidate = _union([*windows, [start, end]]) + n = sum(stop - first for first, stop in _row_bounds(times, candidate)) + n_waveforms = _selected_waveform_count(source, candidate) + size = fixed_bytes + n * row_bytes + n_waveforms * waveform_bytes + len(candidate) * 256 + record = { + 'start': int(start), + 'end': int(end), + 'kind': kind, + 'segment': 0, + 'block': int(segment), + 'stratum': int(stratum_id), + } + if n > max_spikes or size > max_bytes: + omitted.append( + {**record, 'reason': 'spike_budget' if n > max_spikes else 'byte_budget'} + ) + return False + windows[:] = candidate + plan.append(record) + return True + + # Candidate enumeration is scalar and bounded by output-window metadata, + # rather than constructing recording-length arrays. + for segment, (first, last) in enumerate(source.valid_intervals): + for start in range(int(first), int(last), stratum): + end = min(start + stratum, int(last)) + length = min(width, end - start) + offset = int(rng.integers(0, end - start - length + 1)) + accept(start + offset, start + offset + length, 'survey', segment, start // stratum) + if (len(plan) + len(omitted)) * 256 + fixed_bytes > max_bytes: + raise ValueError( + 'Window plan metadata exceeds max_bytes; increase stratum_seconds.' + ) + evidence = set() + for first, stop in _row_bounds(times, windows): + for start in range(first, stop, batch_size): + evidence.update(np.unique(assignments[start : min(start + batch_size, stop)]).tolist()) + missing = set(source.unit_ids.tolist()) - evidence + for batch in source.iter_batches(): + if not missing: + break + units, positions = np.unique(batch['spike_clusters.npy'], return_index=True) + for unit, position in zip(units.tolist(), positions.tolist(), strict=True): + if unit not in missing: + continue + sample = int(batch['spike_times.npy'][position]) + segment = int(np.searchsorted(source.valid_intervals[:, 0], sample, side='right') - 1) + first, last = source.valid_intervals[segment] + start = max(int(first), min(sample - width // 2, int(last) - width)) + end = min(start + width, int(last)) + accept(start, end, 'rescue', segment, -1) + # One deterministic rescue attempt per unit, including rejected attempts. + missing.remove(unit) + row_bounds = _row_bounds(times, windows) + n_bounded = sum(stop - first for first, stop in row_bounds) + if not n_bounded: + raise ValueError( + 'No bounded evidence fits the budgets; increase max_spikes/max_bytes ' + 'or shorten window_seconds (tied spikes remain together).' + ) + output_dir.parent.mkdir(parents=True, exist_ok=True) + temporary = Path( + tempfile.mkdtemp(prefix=f'.{output_dir.name}.prepare-', dir=output_dir.parent) + ) + global_ids, base, destinations = None, None, {} + try: + global_ids = np.lib.format.open_memmap( + temporary / '_phy_spike_global_ids.npy', mode='w+', dtype=np.int64, shape=(n_bounded,) + ) + for name in source.arrays.keys() & PER_SPIKE: + array = source.arrays[name] + destinations[name] = np.lib.format.open_memmap( + temporary / name, mode='w+', dtype=array.dtype, shape=(n_bounded, *array.shape[1:]) + ) + base = np.lib.format.open_memmap( + temporary / '_phy_spike_clusters_base.npy', + mode='w+', + dtype=np.int64, + shape=(n_bounded,), + ) + cursor = 0 + bounded_counts = {int(unit): 0 for unit in source.unit_ids} + for first, stop in row_bounds: + for start in range(first, stop, batch_size): + end = min(start + batch_size, stop) + length = end - start + global_ids[cursor : cursor + length] = np.arange(start, end, dtype=np.int64) + base[cursor : cursor + length] = assignments[start:end] + for name, target in destinations.items(): + target[cursor : cursor + length] = source.arrays[name][start:end] + ids, counts = np.unique(assignments[start:end], return_counts=True) + for unit, count in zip(ids.tolist(), counts.tolist(), strict=True): + bounded_counts[unit] += count + cursor += length + for array in (global_ids, base, *destinations.values()): + array.flush() + for name in source.arrays.keys() & STATIC: + shutil.copyfile(source.path / name, temporary / name) + if source.arrays.keys() >= WAVEFORMS: + _copy_waveforms(source, temporary, global_ids, row_bounds) + np.save(temporary / '_phy_curation_windows.npy', np.asarray(windows, dtype=np.int64)) + _write_metadata(temporary, source.metadata) + (temporary / '_phy_cluster_metadata.json').write_text( + json.dumps(source.metadata, sort_keys=True) + '\n', encoding='utf-8' + ) + # Standard loader stays self-contained; no original raw path is referenced. + params = { + key: source.params[key] + for key in ( + 'sample_rate', + 'n_channels_dat', + 'dtype', + 'offset', + 'hp_filtered', + 'acquisition_id', + 'depth_axis', + 'amplitude_units', + 'depth_units', + 'position_units', + 'waveform_units', + ) + if key in source.params + } + params.update( + dat_path=None, + sample_rate=source.sample_rate, + num_samples=source.num_samples, + valid_intervals=source.valid_intervals.tolist(), + ) + params.setdefault('dtype', 'int16') + params.setdefault('n_channels_dat', len(source.arrays.get('channel_map.npy', []))) + (temporary / 'params.py').write_text( + ''.join(f'{key} = {value!r}\n' for key, value in params.items()), encoding='utf-8' + ) + summaries = build_summaries(source, temporary, bin_seconds, max_bytes=max_bytes) + final_windows = [] + for start, end in windows: + contributors = [ + record for record in plan if record['start'] < end and record['end'] > start + ] + kinds = sorted({record['kind'] for record in contributors}) + final_windows.append( + { + 'start': start, + 'end': end, + 'segment': 0, + 'block': contributors[0]['block'], + 'kind': kinds[0] if len(kinds) == 1 else 'mixed', + 'kinds': kinds, + 'strata': sorted({record['stratum'] for record in contributors}), + 'exposure_seconds': (end - start) / source.sample_rate, + } + ) + manifest = { + 'format': 'phy_bounded_curation', + 'format_version': 1, + 'source': { + 'identity': source.identity, + 'revision': source.revision, + 'path': str(source.path), + }, + 'sample_rate': source.sample_rate, + 'num_samples': source.num_samples, + 'duration_seconds': source.num_samples / source.sample_rate, + 'valid_intervals': source.valid_intervals.tolist(), + 'num_spikes': source.n_spikes, + 'bounded_num_spikes': n_bounded, + 'unit_ids': source.unit_ids.tolist(), + 'counts': source.counts.tolist(), + 'bounded_counts': [bounded_counts[int(unit)] for unit in source.unit_ids], + 'next_cluster_id': source.next_cluster_id, + 'global_spike_ids_file': '_phy_spike_global_ids.npy', + 'base_assignments_file': '_phy_spike_clusters_base.npy', + 'windows_file': '_phy_curation_windows.npy', + 'windows': final_windows, + 'accepted_window_candidates': plan, + 'omitted_windows': omitted, + 'metadata': source.metadata, + 'base_metadata': source.metadata, + 'summaries': summaries, + **{key: value for key, value in summaries.items() if key.endswith('_file')}, + 'selection': { + 'algorithm': 'shared_windows_v1', + 'seed': int(seed), + 'window_seconds': window_seconds, + 'stratum_seconds': stratum_seconds, + }, + 'budgets': { + 'max_spikes': int(max_spikes), + 'max_bytes': int(max_bytes), + 'batch_size': int(batch_size), + 'summary_bytes': int(summary_bytes), + 'estimated_bytes': int( + fixed_bytes + + n_bounded * row_bytes + + _selected_waveform_count(source, windows) * waveform_bytes + + len(windows) * 256 + ), + }, + 'capabilities': { + 'merge': True, + 'label': True, + 'split': False, + 'full_attributes': sorted(scalar_attributes(source)), + 'predicate_split_attributes': ( + ['amplitudes.npy'] if 'amplitude' in scalar_attributes(source) else [] + ), + 'stored_waveforms': source.arrays.keys() >= WAVEFORMS, + 'raw_traces': False, + 'normalized_correlograms': False, + }, + 'source_array_inventory': { + name: { + 'role': 'per_spike' + if name in PER_SPIKE + else 'stored_waveform' + if name in WAVEFORMS + else 'static' + if name in STATIC + else 'excluded_window_sidecar', + 'shape': list(array.shape), + 'dtype': str(array.dtype), + 'bytes': int(array.nbytes), + } + for name, array in source.arrays.items() + }, + 'excluded_files': sorted( + p.name + for p in source.path.iterdir() + if p.name not in (PER_SPIKE | STATIC | WAVEFORMS) + and p.name + not in ( + 'params.py', + '_phy_cluster_metadata.json', + 'curation.json', + 'curation_review.json', + ) + and (not p.name.startswith('cluster_') or p.stem == 'cluster_info') + ), + } + for document in producer_documents: + shutil.copyfile(document, temporary / document.name) + bound_paths = [ + *temporary.glob('*.npy'), + temporary / 'params.py', + temporary / '_phy_cluster_metadata.json', + ] + manifest['bounded_files'] = {p.name: hash_file(p) for p in sorted(bound_paths)} + manifest['preparation_identity'] = hash_json(manifest) + (temporary / '_phy_curation_manifest.json').write_text( + json.dumps(manifest, indent=2, sort_keys=True) + '\n', encoding='utf-8' + ) + actual_bytes = sum(p.stat().st_size for p in temporary.iterdir()) + if actual_bytes > max_bytes: + raise ValueError(f'Final output exceeds max_bytes: {actual_bytes} bytes.') + for array in (global_ids, base, *destinations.values()): + close_array(array) + for path in temporary.iterdir(): + if path.is_file(): + with path.open('rb') as stream: + os.fsync(stream.fileno()) + _fsync_directory(temporary) + if output_dir.exists(): + raise ValueError(f'Output already exists: {output_dir}.') + from .curation import BoundedSession + + checked = BoundedSession(temporary) + checked.close() + publish_directory(temporary, output_dir) + _fsync_directory(output_dir.parent) + except BaseException: + for array in (global_ids, base, *destinations.values()): + close_array(array) + shutil.rmtree(temporary, ignore_errors=True) + raise + return output_dir + + +def _fsync_directory(path): + if os.name != 'nt': + descriptor = os.open(path, os.O_RDONLY) + try: + os.fsync(descriptor) + finally: + os.close(descriptor) + + +def _copy_waveforms(source, output, global_ids, row_bounds): + """Intersect sparse row IDs with selected spans in bounded working memory.""" + upstream_ids = source.arrays['_phy_spikes_subset.spikes.npy'] + spans = [ + (int(np.searchsorted(upstream_ids, first)), int(np.searchsorted(upstream_ids, stop))) + for first, stop in row_bounds + ] + n = sum(stop - first for first, stop in spans) + targets = {} + try: + for name in WAVEFORMS: + original = source.arrays[name] + targets[name] = np.lib.format.open_memmap( + output / name, mode='w+', dtype=original.dtype, shape=(n, *original.shape[1:]) + ) + cursor = 0 + for first, stop in spans: + for start in range(first, stop, source.batch_size): + end = min(start + source.batch_size, stop) + length = end - start + targets['_phy_spikes_subset.spikes.npy'][cursor : cursor + length] = ( + np.searchsorted(global_ids, upstream_ids[start:end]) + ) + for name in WAVEFORMS - {'_phy_spikes_subset.spikes.npy'}: + targets[name][cursor : cursor + length] = source.arrays[name][start:end] + cursor += length + for array in targets.values(): + array.flush() + finally: + for array in targets.values(): + close_array(array) diff --git a/phy/apps/large_recording/tests/test_prepare.py b/phy/apps/large_recording/tests/test_prepare.py new file mode 100644 index 000000000..7b5b0bcb9 --- /dev/null +++ b/phy/apps/large_recording/tests/test_prepare.py @@ -0,0 +1,174 @@ +"""Production bounded preparation: budgets, rows, waveforms, and publication.""" + +import json + +import numpy as np +import pytest +from phylib.io.model import load_model + +from phy.apps.large_recording.prepare import prepare_large +from phy.apps.large_recording.source import PER_SPIKE, hash_file +from phy.apps.large_recording.tests.test_source import make_sorting + + +def test_prepare_exact_arrays_waveforms_and_source_unchanged(tmp_path): + params = make_sorting(tmp_path / 'full', columns=True) + before = {p.name: hash_file(p) for p in params.parent.iterdir()} + output = prepare_large( + params, + tmp_path / 'bounded', + max_spikes=8, + window_seconds=3, + stratum_seconds=20, + seed=0, + bin_seconds=5, + batch_size=2, + ) + manifest = json.loads((output / '_phy_curation_manifest.json').read_text()) + windows = np.load(output / manifest['windows_file']) + samples = np.load(params.parent / 'spike_times.npy').reshape(-1) + expected_ids = np.array( + [ + index + for index, sample in enumerate(samples) + if any(start <= sample < end for start, end in windows) + ], + dtype=np.int64, + ) + global_ids = np.load(output / manifest['global_spike_ids_file']) + np.testing.assert_array_equal(global_ids, expected_ids) + assert len(global_ids) <= 8 + for name in PER_SPIKE: + if (params.parent / name).exists(): + np.testing.assert_array_equal( + np.load(output / name), np.load(params.parent / name)[expected_ids] + ) + source_waveform_ids = np.load(params.parent / '_phy_spikes_subset.spikes.npy') + expected_waveform_rows = [ + row for row, spike in enumerate(source_waveform_ids) if spike in expected_ids + ] + np.testing.assert_array_equal( + global_ids[np.load(output / '_phy_spikes_subset.spikes.npy')], + source_waveform_ids[expected_waveform_rows], + ) + for suffix in ('channels', 'waveforms'): + np.testing.assert_array_equal( + np.load(output / f'_phy_spikes_subset.{suffix}.npy'), + np.load(params.parent / f'_phy_spikes_subset.{suffix}.npy')[expected_waveform_rows], + ) + assert before == {p.name: hash_file(p) for p in params.parent.iterdir()} + assert 'dat_path = None' in (output / 'params.py').read_text() + assert manifest['next_cluster_id'] == 100 + assert sum(manifest['counts']) == len(samples) + assert sum(manifest['bounded_counts']) == len(global_ids) + model = load_model(output / 'params.py') + try: + ids = np.load(output / '_phy_spikes_subset.spikes.npy') + channels = np.load(output / '_phy_spikes_subset.channels.npy') + sparse = np.load(output / '_phy_spikes_subset.waveforms.npy') + expected = np.zeros((len(ids), 8, 3), dtype=np.float32) + for row, slots in enumerate(channels): + for slot, channel in enumerate(slots): + if channel >= 0: + expected[row, :, channel] = sparse[row, :, slot] + np.testing.assert_array_equal(model.get_waveforms(ids, channel_ids=[0, 1, 2]), expected) + finally: + model.close() + + +def test_deterministic_budgets_and_zero_evidence_catalog(tmp_path): + params = make_sorting(tmp_path / 'full') + outputs = [ + prepare_large( + params, + tmp_path / name, + max_spikes=5, + window_seconds=3, + stratum_seconds=20, + seed=0, + bin_seconds=5, + batch_size=2, + ) + for name in ('one', 'two') + ] + manifests = [ + json.loads((path / '_phy_curation_manifest.json').read_text()) for path in outputs + ] + assert manifests[0] == manifests[1] + assert manifests[0]['unit_ids'][-1] == 99 + assert manifests[0]['bounded_counts'][-1] == 0 + assert manifests[0]['omitted_windows'] + for path in outputs: + ids = np.load(path / '_phy_spike_global_ids.npy') + times = np.load(path / 'spike_times.npy') + assert len(ids) <= 5 + # All three tied samples at 1 retain their separate source identities. + assert np.count_nonzero(times == 1) == 2 + + +def test_rejected_budget_or_interrupted_publication_leaves_no_output(tmp_path, monkeypatch): + params = make_sorting(tmp_path / 'full') + with pytest.raises(ValueError, match='No bounded evidence'): + prepare_large( + params, tmp_path / 'empty', max_spikes=1, window_seconds=3, stratum_seconds=20, seed=0 + ) + with pytest.raises(ValueError, match='Output budget'): + prepare_large(params, tmp_path / 'too-big', max_bytes=10) + import phy.apps.large_recording.prepare as module + + def fail(*args, **kwargs): + raise OSError('simulated interruption') + + monkeypatch.setattr(module, 'build_summaries', fail) + with pytest.raises(OSError, match='interruption'): + prepare_large(params, tmp_path / 'interrupted', window_seconds=20, stratum_seconds=20) + assert not (tmp_path / 'interrupted').exists() + assert not list(tmp_path.glob('.interrupted.prepare-*')) + + +def test_prepare_missing_waveforms_is_explicit(tmp_path): + params = make_sorting(tmp_path / 'full') + for path in params.parent.glob('_phy_spikes_subset.*.npy'): + path.unlink() + output = prepare_large(params, tmp_path / 'bounded', window_seconds=20, stratum_seconds=20) + manifest = json.loads((output / '_phy_curation_manifest.json').read_text()) + assert not manifest['capabilities']['stored_waveforms'] + assert not (output / '_phy_spikes_subset.waveforms.npy').exists() + + +def test_final_windows_records_match_retained_samples_and_gaps(tmp_path): + params = make_sorting(tmp_path / 'full') + output = prepare_large( + params, + tmp_path / 'bounded', + valid_intervals=[[0, 7], [10, 20]], + window_seconds=5, + stratum_seconds=20, + bin_seconds=5, + ) + manifest = json.loads((output / '_phy_curation_manifest.json').read_text()) + intervals = np.load(output / manifest['windows_file']) + assert [[row['start'], row['end']] for row in manifest['windows']] == intervals.tolist() + for row in manifest['windows']: + start, end = row['start'], row['end'] + assert any(first <= start and end <= last for first, last in [[0, 7], [10, 20]]) + assert row['exposure_seconds'] == end - start + assert manifest['capabilities']['predicate_split_attributes'] == ['amplitudes.npy'] + + +def test_prepare_protects_loader_and_preserves_producer_documents(tmp_path): + params = make_sorting(tmp_path / 'full') + for name, value in ( + ('curation.json', {'merge': [[0, 1]]}), + ('curation_review.json', {'accepted': []}), + ): + (params.parent / name).write_text(json.dumps(value)) + output = prepare_large(params, tmp_path / 'bounded', window_seconds=20, stratum_seconds=20) + manifest = json.loads((output / '_phy_curation_manifest.json').read_text()) + assert manifest['bounded_files']['params.py'] == hash_file(output / 'params.py') + assert manifest['bounded_files']['_phy_cluster_metadata.json'] == hash_file( + output / '_phy_cluster_metadata.json' + ) + for name in ('curation.json', 'curation_review.json'): + assert (output / name).read_bytes() == (params.parent / name).read_bytes() + assert name not in manifest['excluded_files'] From 1ba129c2908d07dbed46fc52f79081016e75e272 Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 10:37:42 +0200 Subject: [PATCH 07/22] Replay committed curation into validated immutable-source descendants --- phy/apps/large_recording/replay.py | 218 ++++++++++++++++++ phy/apps/large_recording/tests/test_replay.py | 142 ++++++++++++ 2 files changed, 360 insertions(+) create mode 100644 phy/apps/large_recording/replay.py create mode 100644 phy/apps/large_recording/tests/test_replay.py diff --git a/phy/apps/large_recording/replay.py b/phy/apps/large_recording/replay.py new file mode 100644 index 000000000..0fa3355ec --- /dev/null +++ b/phy/apps/large_recording/replay.py @@ -0,0 +1,218 @@ +"""Stream semantic curation into a new complete sorting, never the source.""" + +import csv +import os +import shutil +import tempfile +from pathlib import Path + +import numpy as np + +from .curation import ( + BoundedSession, + _digest, + _fsync_directory, + _write_json, + interpret_events, + project_assignments, +) +from .source import PER_SPIKE, Source, close_array, publish_directory + + +def _merge_mapping(unit_ids, events): + """Resolve a whole-unit merge journal once, independently of spike count.""" + lineage = {int(unit): [int(unit)] for unit in unit_ids} + for event in events: + if event['operation'] == 'merge': + members = [] + for parent in event['parents']: + members.extend(lineage.pop(parent)) + lineage[event['target']] = members + mapping = {old: new for new, members in lineage.items() for old in members} + keys = np.array(sorted(mapping), dtype=np.int64) + targets = np.array([mapping[int(key)] for key in keys], dtype=np.int64) + return keys, targets + + +def _write_metadata(path, metadata): + for field, values in sorted(metadata.items()): + if not field or any(char in field for char in ('/', '\\', '\0')): + raise ValueError('Metadata fields must be safe local filenames.') + with (path / f'cluster_{field}.tsv').open('w', encoding='utf8', newline='') as stream: + writer = csv.writer(stream, delimiter='\t') + writer.writerow(['cluster_id', field]) + for cluster, value in sorted(values.items()): + if value is not None: + writer.writerow([cluster, value]) + stream.flush() + os.fsync(stream.fileno()) + _write_json(path / '_phy_cluster_metadata.json', metadata) + + +def apply_curation(source_params, bounded_dir, output_dir, batch_size=100000): + """Validate identity/revision and replay only the last committed generation. + + The output is published as one new directory after validation. Full source + arrays remain file-backed; only one assignment batch and the unit map reside + in memory. Arbitrary selected-row splits have no journal interpretation. + """ + session = BoundedSession(bounded_dir) + source = None + try: + if session.checkpoint_path is None: + raise ValueError('Save a bounded semantic checkpoint before applying curation.') + manifest = session.manifest + source = Source( + source_params, + duration_seconds=manifest['num_samples'] / manifest['sample_rate'], + valid_intervals=manifest['valid_intervals'], + batch_size=batch_size, + ) + return _apply_curation(source, session, output_dir, batch_size) + finally: + if source is not None: + source.close() + session.close() + + +def _apply_curation(source, session, output_dir, batch_size): + manifest = session.manifest + expected = manifest['source'] + if source.identity != expected['identity']: + raise ValueError('Source coordinate/feature identity does not match bounded preparation.') + if source.revision != expected['revision']: + raise ValueError('Source assignment revision does not match journal parent revision.') + if ( + source.unit_ids.tolist() != manifest['unit_ids'] + or source.n_spikes != manifest['num_spikes'] + ): + raise ValueError('Source catalog or spike count does not match bounded preparation.') + # Identity/revision bind the complete source. Validate the actual projection + # too, so a tampered bounded base cannot silently replay unrelated evidence. + source_assignments = source.arrays['spike_clusters.npy'].reshape(-1) + for start in range(0, len(session.global_ids), batch_size): + rows = session.global_ids[start : start + batch_size] + if not np.array_equal( + source_assignments[rows], + session.base_assignments[start : start + batch_size], + ): + raise ValueError('Immutable bounded assignments do not match source rows.') + for name in sorted(source.arrays.keys() & (PER_SPIKE - {'spike_clusters.npy'})): + bounded = np.load(session.path / name, mmap_mode='r', allow_pickle=False) + try: + if bounded.shape != (len(session.global_ids), *source.arrays[name].shape[1:]): + raise ValueError(f'Bounded attribute has invalid source alignment: {name}.') + for start in range(0, len(session.global_ids), batch_size): + rows = session.global_ids[start : start + batch_size] + if not np.array_equal( + source.arrays[name][rows], + bounded[start : start + batch_size], + equal_nan=True, + ): + raise ValueError(f'Bounded attribute does not match source rows: {name}.') + finally: + close_array(bounded) + active_units, metadata, _ = interpret_events(source.unit_ids, source.metadata, session.events) + output = Path(output_dir).resolve() + if output.exists(): + raise FileExistsError(f'Curated output already exists: {output}.') + if output == source.path or source.path in output.parents: + raise ValueError('Curated output must be outside the immutable source directory.') + output.parent.mkdir(parents=True, exist_ok=True) + stage = Path(tempfile.mkdtemp(prefix=f'.{output.name}-', dir=output.parent)) + curated = None + assignments = None + try: + # Copy only validated canonical assets, not GUI caches or producer reviews. + for name in source.arrays: + if name != 'spike_clusters.npy': + shutil.copyfile(source.path / name, stage / name) + shutil.copyfile(source.params_path, stage / 'params.py') + upstream_manifest = source.path / '_phy_spikes_subset.manifest.json' + if upstream_manifest.exists(): + shutil.copyfile(upstream_manifest, stage / upstream_manifest.name) + # Preserve source params semantics and make external raw paths absolute. + # The full export can contain no raw traces; immutable array rows suffice. + dat_path = source.params.get('dat_path') + if dat_path: + raw_paths = dat_path if isinstance(dat_path, (list, tuple)) else [dat_path] + resolved = [str((source.path / raw).resolve()) for raw in raw_paths] + dat_path = resolved if isinstance(dat_path, (list, tuple)) else resolved[0] + with (stage / 'params.py').open('a', encoding='utf8') as stream: + stream.write(f'\nnum_samples = {source.num_samples!r}\n') + stream.write(f'valid_intervals = {source.valid_intervals.tolist()!r}\n') + stream.write(f'dat_path = {dat_path!r}\n') + assignments = np.lib.format.open_memmap( + stage / 'spike_clusters.npy', + mode='w+', + dtype=np.int64, + shape=source.arrays['spike_clusters.npy'].shape, + ) + flat = assignments.reshape(-1) + has_split = any(event['operation'] == 'threshold_split' for event in session.events) + keys, targets = ( + (None, None) if has_split else _merge_mapping(source.unit_ids, session.events) + ) + for batch in source.iter_batches(): + values = batch['spike_clusters.npy'] + if has_split: + projected = project_assignments(values, session.events, batch) + else: + positions = np.searchsorted(keys, values) + projected = targets[positions] + flat[batch['start'] : batch['stop']] = projected + assignments.flush() + assignments._mmap.close() + del flat, assignments + assignments = None + _write_metadata(stage, metadata) + _write_json(stage / '_phy_curation_journal.json', session.events) + # Re-reading verifies alignment, full catalog and immutable byte digests. + curated = Source(stage / 'params.py', batch_size=batch_size) + if curated.identity != source.identity or curated.n_spikes != source.n_spikes: + raise ValueError('Curated output changed immutable source coordinates.') + if curated.metadata != metadata: + raise ValueError('Curated output metadata failed exact round-trip validation.') + actual = curated.arrays['spike_clusters.npy'].reshape(-1) + for batch in source.iter_batches(): + if has_split: + expected_batch = project_assignments( + batch['spike_clusters.npy'], session.events, batch + ) + else: + expected_batch = targets[np.searchsorted(keys, batch['spike_clusters.npy'])] + if not np.array_equal(actual[batch['start'] : batch['stop']], expected_batch): + raise ValueError('Curated output assignments failed semantic replay verification.') + _write_json( + stage / '_phy_curation_lineage.json', + { + 'format': 'phy_curation_lineage', + 'format_version': 1, + 'coordinate_identity': source.identity, + 'parent_revision': source.revision, + 'journal_sha256': _digest(session.events), + 'revision': curated.revision, + 'preparation_sha256': _digest(manifest), + 'next_cluster_id': session.next_cluster_id, + 'unit_ids': sorted(active_units), + }, + ) + curated.close() + for path in stage.iterdir(): + if path.is_file(): + with path.open('rb') as stream: + os.fsync(stream.fileno()) + _fsync_directory(stage) + # Refuse replacement even when a racing caller creates the target. + if output.exists(): + raise FileExistsError(f'Curated output already exists: {output}.') + publish_directory(stage, output) + _fsync_directory(output.parent) + except BaseException: + if curated is not None: + curated.close() + if assignments is not None: + assignments._mmap.close() + shutil.rmtree(stage, ignore_errors=True) + raise + return output diff --git a/phy/apps/large_recording/tests/test_replay.py b/phy/apps/large_recording/tests/test_replay.py new file mode 100644 index 000000000..fefeb52ab --- /dev/null +++ b/phy/apps/large_recording/tests/test_replay.py @@ -0,0 +1,142 @@ +"""Full assignment oracle, revision binding and atomic publication regressions.""" + +import json + +import numpy as np +import pytest + +from phy.apps.large_recording.replay import apply_curation +from phy.apps.large_recording.source import Source, hash_file +from phy.apps.large_recording.tests.test_curation import make_session + + +def test_full_replay_chains_preserve_unseen_units_and_immutable_bytes(tmp_path): + source, session = make_session(tmp_path) + original_hashes = {name: hash_file(source.path / name) for name in source.arrays} + original = source.arrays['spike_clusters.npy'].copy() + session.record_merge([0, 1], 100, {'group': 'good', 'confidence': 0.8}) + session.record_label('group', [100], 'mua') + session.record_merge([100, 2], 101, {'group': 'good', 'confidence': None}) + session.record_label('custom', [99, 101], 'verified') + session.save() + output = apply_curation(source.params_path, session.path, tmp_path / 'curated', batch_size=3) + expected = np.where(np.isin(original, [0, 1, 2]), 101, original) + assert np.array_equal(np.load(output / 'spike_clusters.npy'), expected) + assert expected[-1] == 99 + curated = Source(output / 'params.py') + assert curated.metadata == session.metadata + assert curated.identity == source.identity + assert curated.revision != source.revision + lineage = json.loads((output / '_phy_curation_lineage.json').read_text()) + assert lineage['parent_revision'] == source.revision + assert lineage['revision'] == curated.revision + for name, digest in original_hashes.items(): + assert hash_file(source.path / name) == digest + if name != 'spike_clusters.npy': + assert hash_file(output / name) == digest + with pytest.raises(ValueError, match='revision'): + apply_curation(output / 'params.py', session.path, tmp_path / 'twice') + assert not (tmp_path / 'twice').exists() + second = apply_curation(source.params_path, session.path, tmp_path / 'second', batch_size=7) + assert hash_file(second / 'spike_clusters.npy') == hash_file(output / 'spike_clusters.npy') + + +def test_source_revision_and_feature_identity_are_independently_bound(tmp_path): + source, session = make_session(tmp_path) + session.save() + clusters = source.arrays['spike_clusters.npy'].copy() + clusters[0] = 2 + np.save(source.path / 'spike_clusters.npy', clusters) + with pytest.raises(ValueError, match='revision'): + apply_curation(source.params_path, session.path, tmp_path / 'wrong_revision') + amplitudes = source.arrays['amplitudes.npy'].copy() + amplitudes[0] += 1 + np.save(source.path / 'amplitudes.npy', amplitudes) + with pytest.raises(ValueError, match='identity'): + apply_curation(source.params_path, session.path, tmp_path / 'wrong_feature') + assert not (tmp_path / 'wrong_revision').exists() + assert not (tmp_path / 'wrong_feature').exists() + + +def test_full_threshold_split_matches_scalar_oracle(tmp_path): + source, session = make_session(tmp_path) + original = source.arrays['spike_clusters.npy'].copy() + amplitudes = source.arrays['amplitudes.npy'].copy() + predicate = { + 'attribute': 'amplitudes.npy', + 'operator': '<', + 'threshold': 15.0, + 'nonfinite': 'keep', + } + session.record_split(2, 100, 101, predicate, {'group': {100: 'noise', 101: 'good'}}) + session.record_merge([0, 100], 102, {'group': 'mua'}) + session.save() + expected = original.astype(np.int64) + expected[(original == 2) & (amplitudes < 15)] = 100 + expected[(original == 2) & ~(amplitudes < 15)] = 101 + expected[np.isin(expected, [0, 100])] = 102 + output = apply_curation(source.params_path, session.path, tmp_path / 'split', batch_size=4) + assert np.array_equal(np.load(output / 'spike_clusters.npy'), expected) + assert Source(output / 'params.py').metadata == session.metadata + + +def test_failed_replay_does_not_publish_output(tmp_path, monkeypatch): + from phy.apps.large_recording import replay + + source, session = make_session(tmp_path) + session.save() + original = replay._write_json + + def fail(path, value): + if path.name == '_phy_curation_lineage.json': + raise OSError('injected replay interruption') + return original(path, value) + + monkeypatch.setattr(replay, '_write_json', fail) + with pytest.raises(OSError, match='interruption'): + apply_curation(source.params_path, session.path, tmp_path / 'interrupted') + assert not (tmp_path / 'interrupted').exists() + assert not list(tmp_path.glob('.interrupted-*')) + + +def test_replay_requires_committed_checkpoint_and_new_output(tmp_path): + source, session = make_session(tmp_path) + with pytest.raises(ValueError, match='Save'): + apply_curation(source.params_path, session.path, tmp_path / 'unsaved') + session.save() + with pytest.raises(FileExistsError): + apply_curation(source.params_path, session.path, source.path) + + +def test_replay_preserves_empty_split_children_and_allocator_lineage(tmp_path): + source, session = make_session(tmp_path) + session.record_split( + 2, + 100, + 101, + { + 'attribute': 'amplitudes.npy', + 'operator': '<', + 'threshold': 100.0, + 'nonfinite': 'keep', + }, + ) + session.save() + output = apply_curation(source.params_path, session.path, tmp_path / 'empty_child') + curated = Source(output / 'params.py') + assert 101 in curated.unit_ids + assert curated.counts[curated.unit_ids.tolist().index(101)] == 0 + assert curated.next_cluster_id == 102 + + +def test_bounded_threshold_attribute_must_match_exact_source_rows(tmp_path): + source, session = make_session(tmp_path) + session.save() + # Even a manifest that does not hash this optional attribute must not allow + # evidence values different from those used by the full-data predicate. + values = np.load(session.path / 'amplitudes.npy') + values[0] += 1 + np.save(session.path / 'amplitudes.npy', values) + with pytest.raises(ValueError, match='does not match source rows'): + apply_curation(source.params_path, session.path, tmp_path / 'bad_evidence') + assert not (tmp_path / 'bad_evidence').exists() From b8b017f2df42504135a81e534f511f6e0d57f7e2 Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 11:39:55 +0200 Subject: [PATCH 08/22] Avoid dense allocations for sparse cluster identifiers --- phy/cluster/clustering.py | 26 +++++++++++++++++++++++--- phy/cluster/tests/test_clustering.py | 22 ++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/phy/cluster/clustering.py b/phy/cluster/clustering.py index 662ca7439..32fa7480e 100644 --- a/phy/cluster/clustering.py +++ b/phy/cluster/clustering.py @@ -7,7 +7,8 @@ import logging import numpy as np -from phylib.io.array import _spikes_in_clusters, _spikes_per_cluster, _unique +from phylib.io.array import _spikes_in_clusters, _spikes_per_cluster +from phylib.io.array import _unique as _unique_dense from phylib.utils._types import _as_array, _is_array_like from phylib.utils.event import emit @@ -22,6 +23,23 @@ # ------------------------------------------------------------------------------ +def _unique(values): + """Preserve dense-ID performance without allocating by sparse absolute IDs.""" + if values is None or len(values) == 0: + return np.array([], dtype=np.int64) + values = np.asarray(values) + if int(values.max()) > max(1024, 4 * len(values)): + return np.unique(values[values >= 0]).astype(np.int64) + return _unique_dense(values) + + +def _largest_cluster(values): + if int(values.max()) > max(1024, 4 * len(values)): + ids, counts = np.unique(values, return_counts=True) + return int(ids[counts.argmax()]) + return int(np.bincount(values).argmax()) + + def _extend_spikes(spike_ids, spike_clusters): """Return all spikes belonging to the clusters containing the specified spikes.""" @@ -81,7 +99,7 @@ def _extend_assignment(spike_ids, old_spike_clusters, spike_clusters_rel, new_cl def _assign_update_info(spike_ids, old_spike_clusters, new_spike_clusters): old_clusters = _unique(old_spike_clusters) new_clusters = _unique(new_spike_clusters) - largest_old_cluster = np.bincount(old_spike_clusters).argmax() + largest_old_cluster = _largest_cluster(old_spike_clusters) descendants = list(set(zip(old_spike_clusters, new_spike_clusters))) update_info = UpdateInfo( description='assign', @@ -293,7 +311,9 @@ def _do_assign(self, spike_ids, new_spike_clusters): def _do_merge(self, spike_ids, cluster_ids, to): # Create the UpdateInfo instance here. descendants = [(cluster, to) for cluster in cluster_ids] - largest_old_cluster = np.bincount(self.spike_clusters[spike_ids]).argmax() + largest_old_cluster = max( + cluster_ids, key=lambda cluster: (len(self._spikes_per_cluster[cluster]), -cluster) + ) up = UpdateInfo( description='merge', spike_ids=list(spike_ids), diff --git a/phy/cluster/tests/test_clustering.py b/phy/cluster/tests/test_clustering.py index 9557221d7..ef8d03beb 100644 --- a/phy/cluster/tests/test_clustering.py +++ b/phy/cluster/tests/test_clustering.py @@ -26,6 +26,28 @@ # ------------------------------------------------------------------------------ +def test_sparse_absolute_cluster_ids_do_not_allocate_dense_histograms(monkeypatch): + original = np.bincount + + def bounded_bincount(values, *args, **kwargs): + assert not len(values) or np.max(values) < 1024 + return original(values, *args, **kwargs) + + monkeypatch.setattr(np, 'bincount', bounded_bincount) + high = 2_000_000_000 + clustering = Clustering(np.array([0, 1, 1, high], dtype=np.int64)) + first = clustering.merge([0, 1]) + assert first.largest_old_cluster == 1 + assert first.added == [high + 1] + second = clustering.merge([high, high + 1]) + assert second.largest_old_cluster == high + 1 + clustering.undo() + ae(clustering.spike_clusters, [high + 1, high + 1, high + 1, high]) + clustering.split([0]) + clustering.undo() + ae(clustering.spike_clusters, [high + 1, high + 1, high + 1, high]) + + def test_extend_spikes_simple(): spike_clusters = np.array([3, 5, 2, 9, 5, 5, 2]) spike_ids = np.array([2, 4, 0]) From 3e01be4c838cc522c6c1f477faaf7db1b26786ef Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 11:39:55 +0200 Subject: [PATCH 09/22] Add default-preserving supervisor and GUI state hooks --- phy/apps/base.py | 6 +++++- phy/cluster/supervisor.py | 13 +++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/phy/apps/base.py b/phy/apps/base.py index 593ddfcff..63c8a7fc2 100644 --- a/phy/apps/base.py +++ b/phy/apps/base.py @@ -2449,7 +2449,11 @@ def create_gui(self, default_views=None, **kwargs): subtitle=str(self.dir_path), config_dir=self.config_dir, local_path=self.cache_dir / 'state.json', - default_state_path=Path(inspect.getfile(self.__class__)).parent / 'static/state.json', + default_state_path=getattr( + self, + 'default_state_path', + Path(inspect.getfile(self.__class__)).parent / 'static/state.json', + ), view_creator=self.view_creator, default_views=default_views, enable_threading=self._enable_threading, diff --git a/phy/cluster/supervisor.py b/phy/cluster/supervisor.py index 54c5988d1..5b0b4a3f9 100644 --- a/phy/cluster/supervisor.py +++ b/phy/cluster/supervisor.py @@ -755,6 +755,11 @@ class Supervisor: skip_masked_clusters : bool Whether automatic navigation and similar-cluster selection skip noise and MUA clusters. The default is True. + clustering_factory : callable, optional + Construct the clustering model. Defaults to Clustering; bounded curation + supplies a guarded implementation with the same constructor interface. + cluster_meta_factory : callable, optional + Construct metadata from groups and labels. Defaults to create_cluster_meta. Events ------ @@ -790,6 +795,8 @@ def __init__( n_similar_clusters_to_select=None, skip_masked_clusters=True, merge_propositions=None, + clustering_factory=None, + cluster_meta_factory=None, ): super().__init__() self.context = context @@ -833,7 +840,7 @@ def __init__( # Create Clustering and ClusterMeta. # Load the cached spikes_per_cluster array. spc = context.load('spikes_per_cluster') if context else None - self.clustering = Clustering( + self.clustering = (clustering_factory or Clustering)( spike_clusters, spikes_per_cluster=spc, new_cluster_id=new_cluster_id ) @@ -841,7 +848,9 @@ def __init__( self._save_spikes_per_cluster() # Create the ClusterMeta instance. - self.cluster_meta = create_cluster_meta(cluster_groups or {}, self.cluster_labels) + self.cluster_meta = (cluster_meta_factory or create_cluster_meta)( + cluster_groups or {}, self.cluster_labels + ) # Create the GlobalHistory instance. self._global_history = GlobalHistory( From cc91f6558c8f5b94a7f311e12c74d95cb45ac650 Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 11:39:56 +0200 Subject: [PATCH 10/22] Guard semantic capabilities and serialize concurrent checkpoint saves --- phy/apps/large_recording/curation.py | 176 ++++++++++++++++-- .../large_recording/tests/test_curation.py | 171 +++++++++++++++++ 2 files changed, 336 insertions(+), 11 deletions(-) diff --git a/phy/apps/large_recording/curation.py b/phy/apps/large_recording/curation.py index a37e01456..52babbad6 100644 --- a/phy/apps/large_recording/curation.py +++ b/phy/apps/large_recording/curation.py @@ -6,6 +6,7 @@ import os import shutil import uuid +from contextlib import contextmanager from pathlib import Path import numpy as np @@ -14,6 +15,14 @@ MANIFEST = '_phy_curation_manifest.json' BASE_ASSIGNMENTS = '_phy_spike_clusters_base.npy' +BOOLEAN_CAPABILITIES = ( + 'merge', + 'label', + 'split', + 'stored_waveforms', + 'raw_traces', + 'normalized_correlograms', +) def _json_bytes(value): @@ -64,12 +73,85 @@ def _safe_file(root, name): return path +@contextmanager +def _commit_lock(root): + """Hold a process-safe OS lock; process exit releases it automatically.""" + with _safe_file(root, 'commit.lock').open('a+b') as stream: + if os.name == 'nt': + import msvcrt + + # Windows byte-range locking requires at least one byte in the file. + stream.seek(0, os.SEEK_END) + if stream.tell() == 0: + stream.write(b'\0') + stream.flush() + stream.seek(0) + msvcrt.locking(stream.fileno(), msvcrt.LK_LOCK, 1) + try: + yield + finally: + stream.seek(0) + msvcrt.locking(stream.fileno(), msvcrt.LK_UNLCK, 1) + else: + import fcntl + + fcntl.flock(stream.fileno(), fcntl.LOCK_EX) + try: + yield + finally: + fcntl.flock(stream.fileno(), fcntl.LOCK_UN) + + +def _current_pointer(root): + try: + return _read_json(root / 'current.json') + except FileNotFoundError: + return None + + def _integer(value, name): if isinstance(value, bool) or not isinstance(value, (int, np.integer)) or value < 0: raise ValueError(f'{name} must be a nonnegative integer.') return int(value) +def _validate_capabilities(manifest): + capabilities = manifest.get('capabilities', {}) + if not isinstance(capabilities, dict): + raise ValueError('Bounded capabilities must be a mapping.') + if ( + set(capabilities) + - set(BOOLEAN_CAPABILITIES) + - { + 'full_attributes', + 'predicate_split_attributes', + } + ): + raise ValueError('Unsupported bounded capability declaration.') + result = {} + for name in BOOLEAN_CAPABILITIES: + value = capabilities.get(name, False) + if type(value) is not bool: + raise ValueError(f'Bounded capability {name!r} must be a boolean.') + result[name] = value + if result['split']: + raise ValueError('General selected-row splits are unsupported in bounded mode.') + for name in ('full_attributes', 'predicate_split_attributes'): + values = capabilities.get(name, []) + if ( + not isinstance(values, list) + or any(not isinstance(value, str) for value in values) + or len(set(values)) != len(values) + ): + raise ValueError(f'Bounded capability {name!r} must be a unique string list.') + result[name] = list(values) + if set(result['predicate_split_attributes']) - {'amplitudes.npy'}: + raise ValueError( + 'Unsupported bounded predicate attribute; only raw amplitudes are supported.' + ) + return result + + def _field_name(field): if ( not isinstance(field, str) @@ -152,6 +234,8 @@ def interpret_events(unit_ids, metadata, events): raise ValueError('Malformed merge event.') parents = [_integer(i, 'Parent ID') for i in event['parents']] target = _integer(event['target'], 'Target ID') + if target > np.iinfo(np.int32).max: + raise ValueError('Target cluster ID exceeds the current Phy loader namespace.') if len(parents) < 2 or len(set(parents)) != len(parents): raise ValueError('Merge requires at least two distinct complete units.') if not set(parents) <= active or target in allocated or target < next_id: @@ -195,6 +279,8 @@ def interpret_events(unit_ids, metadata, events): raise ValueError('Malformed threshold split event.') parent = _integer(event['parent'], 'Parent ID') children = [_integer(i, 'Child ID') for i in event['children']] + if any(child > np.iinfo(np.int32).max for child in children): + raise ValueError('Child cluster ID exceeds the current Phy loader namespace.') validate_predicate(event['predicate']) if parent not in active or len(children) != 2 or len(set(children)) != 2: raise ValueError('Threshold split requires an active parent and two children.') @@ -247,6 +333,16 @@ class BoundedSession: """ def __init__(self, dataset_path): + self.global_ids = None + self.base_assignments = None + self.attributes = {} + try: + self._initialize(dataset_path) + except BaseException: + self.close() + raise + + def _initialize(self, dataset_path): self.path = Path(dataset_path) if self.path.is_file(): self.path = self.path.parent @@ -300,7 +396,10 @@ def __init__(self, dataset_path): 'valid_intervals': manifest['valid_intervals'], }: raise ValueError('Bounded time base disagrees with immutable source identity.') + self.capabilities = _validate_capabilities(manifest) self.unit_ids = [_integer(i, 'Unit ID') for i in manifest['unit_ids']] + if any(unit > np.iinfo(np.int32).max for unit in self.unit_ids): + raise ValueError('Unit IDs exceed the current Phy loader namespace.') if not self.unit_ids or len(set(self.unit_ids)) != len(self.unit_ids): raise ValueError('Full unit catalog must contain distinct unit IDs.') counts = np.asarray(manifest['counts']) @@ -395,17 +494,31 @@ def __init__(self, dataset_path): for name in ('amplitudes.npy', 'spike_templates.npy'): if (self.path / name).exists(): self.attributes[name] = np.load(self.path / name, mmap_mode='r') + for name in self.capabilities['predicate_split_attributes']: + array = self.attributes.get(name) + if ( + array is None + or name not in identity['arrays'] + or not (array.ndim == 1 or array.shape[1:] == (1,)) + or len(array) != n + or array.dtype.kind not in 'iuf' + ): + raise ValueError( + f'Bounded predicate attribute is not available as a source scalar: {name}.' + ) self.assignments = np.asarray(self.base_assignments, dtype=np.int64).copy() self.metadata = copy.deepcopy(self.base_metadata) self.events = [] self.extra_documents = {} self.next_cluster_id = self.base_next_cluster_id self.checkpoint_path = None + self._expected_pointer = None pointer_path = self.path / '.phy-curation' / 'current.json' if pointer_path.exists(): self._load_checkpoint(pointer_path) def _validated_state(self, assignments, metadata, events, next_cluster_id): + self._validate_event_capabilities(events) _, projected_metadata, minimum = interpret_events( self.unit_ids, self.base_metadata, events ) @@ -451,6 +564,7 @@ def _load_checkpoint(self, pointer_path): self.events = events self.next_cluster_id = next_id self.checkpoint_path = generation + self._expected_pointer = copy.deepcopy(pointer) self.extra_documents = { name: _read_json(generation / name) for name in descriptor.get('extra_documents', []) } @@ -474,6 +588,7 @@ def journal_state(self): def restore_journal(self, state): """Restore an active history prefix while preserving allocator high-water.""" events = list(state['events']) + self._validate_event_capabilities(events) _, metadata, minimum = interpret_events(self.unit_ids, self.base_metadata, events) next_id = _integer(state['next_cluster_id'], 'Next cluster ID') if next_id < max(minimum, self.base_next_cluster_id): @@ -496,6 +611,7 @@ def restore(self, snapshot): self.next_cluster_id = next_id def _append(self, event): + self._validate_event_capabilities([event]) events = self.events + [event] _, metadata, next_id = interpret_events(self.unit_ids, self.base_metadata, events) assignments = project_assignments(self.base_assignments, events, self.attributes) @@ -503,7 +619,27 @@ def _append(self, event): self.next_cluster_id = max(self.next_cluster_id, next_id) return copy.deepcopy(event) + def _require_capability(self, operation, predicate=None): + if operation == 'threshold_split': + predicate = validate_predicate(predicate) + if predicate['attribute'] not in self.capabilities['predicate_split_attributes']: + raise ValueError( + 'Predicate split capability is unavailable in this bounded package.' + ) + elif not self.capabilities.get(operation, False): + raise ValueError( + f'{operation.capitalize()} capability is disabled in this bounded package.' + ) + + def _validate_event_capabilities(self, events): + for event in events: + if isinstance(event, dict): + operation = event.get('operation') + if operation in ('merge', 'label', 'threshold_split'): + self._require_capability(operation, event.get('predicate')) + def preflight_merge(self, parents, target, metadata=None): + self._require_capability('merge') event = { 'version': 1, 'operation': 'merge', @@ -519,19 +655,24 @@ def preflight_merge(self, parents, target, metadata=None): def record_merge(self, parents, target, metadata=None): return self._append(self.preflight_merge(parents, target, metadata)) + def preflight_label(self, field, ids, value): + self._require_capability('label') + event = { + 'version': 1, + 'operation': 'label', + 'field': field, + 'ids': [int(i) for i in ids], + 'value': copy.deepcopy(value), + } + interpret_events(self.unit_ids, self.base_metadata, self.events + [event]) + return event + def record_label(self, field, ids, value): - return self._append( - { - 'version': 1, - 'operation': 'label', - 'field': field, - 'ids': [int(i) for i in ids], - 'value': copy.deepcopy(value), - } - ) + return self._append(self.preflight_label(field, ids, value)) def record_threshold_split(self, parent, children, predicate, metadata=None): - """Pure replay service; the bounded GUI currently keeps splits disabled.""" + """Apply an explicitly enabled full-source scalar predicate.""" + self._require_capability('threshold_split', predicate) children = [int(i) for i in children] if any(i < self.next_cluster_id for i in children): raise ValueError('Threshold children collide with the complete catalog allocator.') @@ -547,6 +688,7 @@ def record_threshold_split(self, parent, children, predicate, metadata=None): ) def preflight_split(self, parent, selected_id, remainder_id, predicate, metadata=None): + self._require_capability('threshold_split', predicate) children = [int(remainder_id), int(selected_id)] if any(i < self.next_cluster_id for i in children): raise ValueError('Threshold children collide with the complete catalog allocator.') @@ -598,6 +740,16 @@ def save( generations.mkdir(parents=True, exist_ok=True) _fsync_directory(root) _fsync_directory(self.path) + with _commit_lock(root): + if _current_pointer(root) != self._expected_pointer: + raise ValueError( + 'Bounded curation checkpoint changed in another session; ' + 'reopen the dataset before saving to avoid losing its changes.' + ) + return self._save_generation(generations, values, metadata, events, next_id, documents) + + def _save_generation(self, generations, values, metadata, events, next_id, documents): + root = generations.parent identifier = uuid.uuid4().hex stage = generations / f'.{identifier}.tmp' final = generations / identifier @@ -625,7 +777,8 @@ def save( _fsync_directory(stage) os.replace(stage, final) _fsync_directory(generations) - _write_json(pointer_tmp, {'generation': identifier, 'sha256': _digest(descriptor)}) + pointer = {'generation': identifier, 'sha256': _digest(descriptor)} + _write_json(pointer_tmp, pointer) os.replace(pointer_tmp, root / 'current.json') _fsync_directory(root) except BaseException: @@ -635,4 +788,5 @@ def save( self.assignments, self.metadata, self.events = values, metadata, copy.deepcopy(events) self.next_cluster_id, self.checkpoint_path = next_id, final self.extra_documents = documents + self._expected_pointer = pointer return final diff --git a/phy/apps/large_recording/tests/test_curation.py b/phy/apps/large_recording/tests/test_curation.py index 5de69f1f7..2aa748a6d 100644 --- a/phy/apps/large_recording/tests/test_curation.py +++ b/phy/apps/large_recording/tests/test_curation.py @@ -44,6 +44,12 @@ def make_session(tmp_path): 'global_spike_ids_file': '_phy_spike_global_ids.npy', 'windows_file': 'windows.npy', 'base_metadata': source.metadata, + 'capabilities': { + 'merge': True, + 'label': True, + 'split': False, + 'predicate_split_attributes': ['amplitudes.npy'], + }, 'bounded_files': { name: hash_file(fixture.bounded / name) for name in ( @@ -253,3 +259,168 @@ def test_session_close_releases_own_file_mappings(tmp_path): session.close() assert all(mapping.closed for mapping in mappings) session.close() + + +def test_stale_session_save_rejected_without_losing_first_commit(tmp_path): + _, first = make_session(tmp_path) + second = BoundedSession(first.path) + first.record_merge([0, 1], 100, {'group': 'good'}) + second.record_merge([1, 2], 100, {'group': 'noise'}) + first.save(extra_documents={'curation_review.json': {'accepted': [100]}}) + with pytest.raises(ValueError, match='reopen'): + second.save(extra_documents={'curation_review.json': {'rejected': [100]}}) + reopened = BoundedSession(first.path) + assert reopened.events == first.events + assert reopened.extra_documents == first.extra_documents + assert second.events != reopened.events + # The winning session can commit again without reopening. + first.record_label('group', [100], 'mua') + first.save() + assert BoundedSession(first.path).metadata['group'][100] == 'mua' + + +def test_failed_save_releases_commit_lock(tmp_path, monkeypatch): + from phy.apps.large_recording import curation + + _, session = make_session(tmp_path) + session.save() + other = BoundedSession(session.path) + original = curation._write_json + + def fail(path, value): + if path.name == 'journal.json': + raise OSError('injected locked save failure') + return original(path, value) + + with monkeypatch.context() as patch: + patch.setattr(curation, '_write_json', fail) + with pytest.raises(OSError, match='locked'): + session.save() + other.record_label('group', [0], 'mua') + other.save() + assert BoundedSession(session.path).metadata['group'][0] == 'mua' + + +def _concurrent_save_worker(path, barrier, results, label): + session = BoundedSession(path) + try: + session.record_label('group', [0], label) + barrier.wait(timeout=20) + try: + session.save() + except ValueError as error: + results.put(('conflict', str(error))) + else: + results.put(('saved', label)) + finally: + session.close() + + +def test_concurrent_process_saves_compare_generation_under_lock(tmp_path): + import multiprocessing + + _, session = make_session(tmp_path) + session.save() + context = multiprocessing.get_context('spawn') + barrier = context.Barrier(2) + results = context.Queue() + processes = [ + context.Process( + target=_concurrent_save_worker, + args=(str(session.path), barrier, results, label), + ) + for label in ('good', 'noise') + ] + for process in processes: + process.start() + try: + outcomes = [results.get(timeout=30) for _ in processes] + for process in processes: + process.join(timeout=10) + assert process.exitcode == 0 + assert sorted(status for status, _ in outcomes) == ['conflict', 'saved'] + winner = next(value for status, value in outcomes if status == 'saved') + assert 'reopen' in next(value for status, value in outcomes if status == 'conflict') + assert BoundedSession(session.path).metadata['group'][0] == winner + finally: + for process in processes: + if process.is_alive(): + process.terminate() + process.join(timeout=5) + results.close() + + +def _replace_capabilities(session, capabilities): + session.close() + path = session.path / '_phy_curation_manifest.json' + manifest = json.loads(path.read_text()) + if capabilities is None: + manifest.pop('capabilities', None) + else: + manifest['capabilities'] = capabilities + path.write_text(json.dumps(manifest)) + return BoundedSession(session.path) + + +@pytest.mark.parametrize( + 'capabilities', [None, {}, {'merge': False, 'label': False, 'split': False}] +) +def test_readonly_capabilities_reject_public_mutations_without_state_changes( + tmp_path, capabilities +): + _, session = make_session(tmp_path) + session = _replace_capabilities(session, capabilities) + before = session.snapshot() + predicate = { + 'attribute': 'amplitudes.npy', + 'operator': '<', + 'threshold': 15.0, + 'nonfinite': 'keep', + } + commands = [ + lambda: session.preflight_merge([0, 1], 100), + lambda: session.record_merge([0, 1], 100), + lambda: session.preflight_label('group', [0], 'good'), + lambda: session.record_label('group', [0], 'good'), + lambda: session.preflight_split(2, 100, 101, predicate), + lambda: session.record_split(2, 100, 101, predicate), + lambda: session.record_threshold_split(2, [101, 100], predicate), + ] + for command in commands: + with pytest.raises(ValueError, match='capability'): + command() + assert session.events == before['events'] + assert session.metadata == before['metadata'] + assert session.next_cluster_id == before['next_cluster_id'] + assert np.array_equal(session.assignments, before['assignments']) + + +@pytest.mark.parametrize( + 'capabilities', + [ + {'merge': 'true'}, + {'label': 'false'}, + {'stored_waveforms': 1}, + {'raw_traces': None}, + {'split': True}, + {'predicate_split_attributes': 'amplitudes.npy'}, + {'predicate_split_attributes': ['amplitudes.npy', 'amplitudes.npy']}, + {'predicate_split_attributes': ['spike_templates.npy']}, + {'predicate_split_attributes': ['waveform_peak']}, + {'predicate_split_attributes': [True]}, + {'full_attributes': 'amplitude'}, + ], +) +def test_malformed_or_unsupported_capabilities_fail_validation(tmp_path, capabilities): + _, session = make_session(tmp_path) + with pytest.raises(ValueError, match='capability|capabilities|unsupported|Unsupported'): + _replace_capabilities(session, capabilities) + + +def test_predicate_capability_requires_an_available_scalar_source_attribute(tmp_path): + _, session = make_session(tmp_path) + session.close() + values = np.load(session.path / 'amplitudes.npy') + np.save(session.path / 'amplitudes.npy', np.column_stack([values, values])) + with pytest.raises(ValueError, match='source scalar'): + BoundedSession(session.path) From 551ab4b13ae374932e3086134f4f94c124c4976e Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 11:39:56 +0200 Subject: [PATCH 11/22] Harden evidence provenance, publication, and acquisition boundaries --- phy/apps/large_recording/prepare.py | 33 ++++++++++++-- phy/apps/large_recording/replay.py | 11 +++++ phy/apps/large_recording/source.py | 44 ++++++++++++++++--- .../large_recording/tests/test_prepare.py | 42 ++++++++++++++++++ phy/apps/large_recording/tests/test_source.py | 42 ++++++++++++++++++ 5 files changed, 163 insertions(+), 9 deletions(-) diff --git a/phy/apps/large_recording/prepare.py b/phy/apps/large_recording/prepare.py index 15920b1ef..308fca6b2 100644 --- a/phy/apps/large_recording/prepare.py +++ b/phy/apps/large_recording/prepare.py @@ -32,10 +32,12 @@ def _row_bounds(times, windows): ] -def _union(windows): +def _union(windows, block_starts=()): result = [] for start, end in sorted(windows): - if result and start <= result[-1][1]: + if result and ( + start < result[-1][1] or (start == result[-1][1] and start not in block_starts) + ): result[-1][1] = max(result[-1][1], int(end)) else: result.append([int(start), int(end)]) @@ -180,7 +182,7 @@ def _prepare_source( rng = np.random.default_rng(seed) def accept(start, end, kind, segment, stratum_id): - candidate = _union([*windows, [start, end]]) + candidate = _union([*windows, [start, end]], set(source.valid_intervals[:, 0])) n = sum(stop - first for first, stop in _row_bounds(times, candidate)) n_waveforms = _selected_waveform_count(source, candidate) size = fixed_bytes + n * row_bytes + n_waveforms * waveform_bytes + len(candidate) * 256 @@ -241,6 +243,17 @@ def accept(start, end, kind, segment, stratum_id): 'or shorten window_seconds (tied spikes remain together).' ) output_dir.parent.mkdir(parents=True, exist_ok=True) + estimated_bytes = ( + fixed_bytes + + n_bounded * row_bytes + + _selected_waveform_count(source, windows) * waveform_bytes + + len(windows) * 256 + ) + free = shutil.disk_usage(output_dir.parent).free + if free < estimated_bytes: + raise OSError( + f'Insufficient disk space for bounded preparation: estimated {estimated_bytes:,} bytes, {free:,} available.' + ) temporary = Path( tempfile.mkdtemp(prefix=f'.{output_dir.name}.prepare-', dir=output_dir.parent) ) @@ -280,6 +293,17 @@ def accept(start, end, kind, segment, stratum_id): shutil.copyfile(source.path / name, temporary / name) if source.arrays.keys() >= WAVEFORMS: _copy_waveforms(source, temporary, global_ids, row_bounds) + waveform_counts = {int(unit): 0 for unit in source.unit_ids} + waveform_ids_path = temporary / '_phy_spikes_subset.spikes.npy' + if waveform_ids_path.exists(): + waveform_ids = np.load(waveform_ids_path, mmap_mode='r') + for start in range(0, len(waveform_ids), batch_size): + ids, counts = np.unique( + base[waveform_ids[start : start + batch_size]], return_counts=True + ) + for unit, count in zip(ids, counts): + waveform_counts[int(unit)] += int(count) + waveform_ids._mmap.close() np.save(temporary / '_phy_curation_windows.npy', np.asarray(windows, dtype=np.int64)) _write_metadata(temporary, source.metadata) (temporary / '_phy_cluster_metadata.json').write_text( @@ -350,6 +374,7 @@ def accept(start, end, kind, segment, stratum_id): 'unit_ids': source.unit_ids.tolist(), 'counts': source.counts.tolist(), 'bounded_counts': [bounded_counts[int(unit)] for unit in source.unit_ids], + 'waveform_counts': [waveform_counts[int(unit)] for unit in source.unit_ids], 'next_cluster_id': source.next_cluster_id, 'global_spike_ids_file': '_phy_spike_global_ids.npy', 'base_assignments_file': '_phy_spike_clusters_base.npy', @@ -387,7 +412,7 @@ def accept(start, end, kind, segment, stratum_id): 'predicate_split_attributes': ( ['amplitudes.npy'] if 'amplitude' in scalar_attributes(source) else [] ), - 'stored_waveforms': source.arrays.keys() >= WAVEFORMS, + 'stored_waveforms': bool(sum(waveform_counts.values())), 'raw_traces': False, 'normalized_correlograms': False, }, diff --git a/phy/apps/large_recording/replay.py b/phy/apps/large_recording/replay.py index 0fa3355ec..965fde0f7 100644 --- a/phy/apps/large_recording/replay.py +++ b/phy/apps/large_recording/replay.py @@ -119,6 +119,17 @@ def _apply_curation(source, session, output_dir, batch_size): if output == source.path or source.path in output.parents: raise ValueError('Curated output must be outside the immutable source directory.') output.parent.mkdir(parents=True, exist_ok=True) + estimated_bytes = sum( + (source.path / name).stat().st_size + for name in source.arrays + if name != 'spike_clusters.npy' + ) + estimated_bytes += source.n_spikes * 8 + 1024 * 1024 + free = shutil.disk_usage(output.parent).free + if free < estimated_bytes: + raise OSError( + f'Insufficient disk space for full replay: estimated at least {estimated_bytes:,} bytes, {free:,} available.' + ) stage = Path(tempfile.mkdtemp(prefix=f'.{output.name}-', dir=output.parent)) curated = None assignments = None diff --git a/phy/apps/large_recording/source.py b/phy/apps/large_recording/source.py index 89fd2c48c..9d86c7b31 100644 --- a/phy/apps/large_recording/source.py +++ b/phy/apps/large_recording/source.py @@ -28,6 +28,7 @@ ( 'templates.npy', 'templates_ind.npy', + 'template_ind.npy', 'channel_map.npy', 'channel_positions.npy', 'channel_shanks.npy', @@ -181,6 +182,16 @@ class Source: def __init__( self, params_path, duration_seconds=None, valid_intervals=None, batch_size=100000 + ): + self.arrays = {} + try: + self._initialize(params_path, duration_seconds, valid_intervals, batch_size) + except BaseException: + self.close() + raise + + def _initialize( + self, params_path, duration_seconds=None, valid_intervals=None, batch_size=100000 ): self.params_path = Path(params_path).resolve() self.path = self.params_path.parent @@ -204,6 +215,7 @@ def __init__( raise ValueError('A positive finite sample_rate is required.') upstream = self.path / '_phy_spikes_subset.manifest.json' recording = {} + info = {} if upstream.exists(): info = json.loads(upstream.read_text(encoding='utf-8')) if info.get('format') != 'phy_spikes_subset' or info.get('format_version') != 1: @@ -318,6 +330,10 @@ def __init__( if not isinstance(unit, int) or unit < 0: raise ValueError('Lineage unit IDs must be nonnegative integers.') counts.setdefault(unit, 0) + if any(unit < 0 or unit > np.iinfo(np.int32).max for unit in counts): + raise ValueError( + 'Unit IDs must fit nonnegative int32 for the current Phy loader; spike sample/row coordinates remain int64.' + ) self.unit_ids = np.array(sorted(counts), dtype=np.int64) minimum_next = int(self.unit_ids[-1]) + 1 if len(self.unit_ids) else 0 self.next_cluster_id = lineage.get('next_cluster_id', minimum_next) @@ -355,6 +371,19 @@ def __init__( 'arrays': {name: hash_file(self.path / name) for name in immutable}, } self.identity['sha256'] = hash_json(self.identity) + declared_source = info.get('source_sorting', {}) + if not isinstance(declared_source, dict): + raise ValueError('Waveform manifest source_sorting must be a mapping.') + if declared_source.get('num_spikes', self.n_spikes) != self.n_spikes: + raise ValueError('Waveform reservoir source spike count does not match this sorting.') + declared_times = declared_source.get('spike_times_sha256') + if ( + declared_times is not None + and declared_times != self.identity['arrays']['spike_times.npy'] + ): + raise ValueError( + 'Waveform reservoir source coordinate fingerprint does not match this sorting.' + ) self.revision = assignment_revision(self.path, self.metadata) if lineage: if ( @@ -489,18 +518,23 @@ def validate(self): raise ValueError(f'{name} must contain a model-channel square matrix.') templates = self.arrays.get('templates.npy') if templates is not None: - sparse = self.arrays.get('templates_ind.npy') + # phylib uses singular template_ind; KS2's plural sidecar does + # not turn a dense tensor into a sparse tensor in the loader. + sparse = self.arrays.get('template_ind.npy') if templates.ndim != 3: raise ValueError('templates.npy must be a template/sample/channel tensor.') if sparse is None and templates.shape[2] != len(channels): raise ValueError('Dense templates must align with model channels.') - if sparse is not None: + for index_name in ('template_ind.npy', 'templates_ind.npy'): + sparse = self.arrays.get(index_name) + if sparse is None: + continue if sparse.shape != (len(templates), templates.shape[2]): - raise ValueError('templates_ind.npy must align with sparse templates.') + raise ValueError(f'{index_name} must align with sparse templates.') if not np.issubdtype(sparse.dtype, np.integer): - raise ValueError('templates_ind.npy must contain integer channel indices.') + raise ValueError(f'{index_name} must contain integer channel indices.') if np.any((sparse < -1) | (sparse >= len(channels))): - raise ValueError('templates_ind.npy contains invalid model channel IDs.') + raise ValueError(f'{index_name} contains invalid model channel IDs.') positions = self.arrays.get('channel_positions.npy') if positions is not None and (positions.ndim != 2 or len(positions) != len(channels)): raise ValueError('channel_positions.npy must align with model channels.') diff --git a/phy/apps/large_recording/tests/test_prepare.py b/phy/apps/large_recording/tests/test_prepare.py index 7b5b0bcb9..7dacb519b 100644 --- a/phy/apps/large_recording/tests/test_prepare.py +++ b/phy/apps/large_recording/tests/test_prepare.py @@ -136,6 +136,48 @@ def test_prepare_missing_waveforms_is_explicit(tmp_path): assert not (output / '_phy_spikes_subset.waveforms.npy').exists() +def test_spikeinterface_singular_sparse_template_indices(tmp_path): + params = make_sorting(tmp_path / 'full') + templates = np.load(params.parent / 'templates.npy')[:, :, :2] + templates[1, :, 1] = 0 + np.save(params.parent / 'templates.npy', templates) + indices = np.array([[0, 2], [1, -1], [2, 0]], dtype=np.int32) + np.save(params.parent / 'template_ind.npy', indices) + output = prepare_large(params, tmp_path / 'bounded', window_seconds=20, stratum_seconds=20) + model = load_model(output / 'params.py') + try: + np.testing.assert_array_equal(model.sparse_templates.cols, indices) + finally: + model.close() + + +def test_adjacent_acquisition_blocks_retain_observation_boundaries(tmp_path): + params = make_sorting(tmp_path / 'full') + output = prepare_large( + params, + tmp_path / 'bounded', + valid_intervals=[[0, 10], [10, 20]], + window_seconds=10, + stratum_seconds=10, + ) + manifest = json.loads((output / '_phy_curation_manifest.json').read_text()) + np.testing.assert_array_equal(np.load(output / manifest['windows_file']), [[0, 10], [10, 20]]) + assert manifest['windows'][0]['block'] != manifest['windows'][1]['block'] + + +def test_disk_preflight_rejects_before_writing_package(tmp_path, monkeypatch): + from types import SimpleNamespace + + from phy.apps.large_recording import prepare + + params = make_sorting(tmp_path / 'full') + monkeypatch.setattr(prepare.shutil, 'disk_usage', lambda path: SimpleNamespace(free=0)) + with pytest.raises(OSError, match='Insufficient disk'): + prepare_large(params, tmp_path / 'bounded', window_seconds=20, stratum_seconds=20) + assert not (tmp_path / 'bounded').exists() + assert not list(tmp_path.glob('.bounded.prepare-*')) + + def test_final_windows_records_match_retained_samples_and_gaps(tmp_path): params = make_sorting(tmp_path / 'full') output = prepare_large( diff --git a/phy/apps/large_recording/tests/test_source.py b/phy/apps/large_recording/tests/test_source.py index 0781ca843..b3c1c45ee 100644 --- a/phy/apps/large_recording/tests/test_source.py +++ b/phy/apps/large_recording/tests/test_source.py @@ -59,6 +59,48 @@ def test_source_batches_ties_counts_columns(tmp_path, columns): assert source.metadata['group'][99] == 'noise' +def test_declared_waveform_source_identity_is_checked(tmp_path): + params = make_sorting(tmp_path / 'full') + manifest = { + 'format': 'phy_spikes_subset', + 'format_version': 1, + 'recording': {'num_samples': 20, 'sampling_frequency_hz': 1}, + 'source_sorting': {'num_spikes': 12, 'spike_times_sha256': '0' * 64}, + } + path = params.parent / '_phy_spikes_subset.manifest.json' + path.write_text(json.dumps(manifest)) + with pytest.raises(ValueError, match='fingerprint'): + Source(params) + manifest['source_sorting']['spike_times_sha256'] = hash_file(params.parent / 'spike_times.npy') + path.write_text(json.dumps(manifest)) + Source(params).close() + manifest['source_sorting']['num_spikes'] = 13 + path.write_text(json.dumps(manifest)) + with pytest.raises(ValueError, match='spike count'): + Source(params) + + +def test_failed_source_validation_closes_readers_and_rejects_unsupported_ids( + tmp_path, monkeypatch +): + params = make_sorting(tmp_path / 'full') + labels = np.load(params.parent / 'spike_clusters.npy').astype(np.int64) + labels[-1] = 2**31 + np.save(params.parent / 'spike_clusters.npy', labels) + original = np.load + readers = [] + + def read(*args, **kwargs): + array = original(*args, **kwargs) + readers.append(array) + return array + + monkeypatch.setattr(np, 'load', read) + with pytest.raises(ValueError, match='int32'): + Source(params) + assert all(array._mmap.closed for array in readers) + + def test_identity_assignment_and_feature_layers(tmp_path): params = make_sorting(tmp_path / 'full') source = Source(params) From 28b510a59051cfe63cc4ffa32035a9bbbed9c884 Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 11:40:09 +0200 Subject: [PATCH 12/22] Compute sampled timing statistics within acquisition windows --- phy/apps/large_recording/statistics.py | 67 +++++++++++++++++++ .../large_recording/tests/test_statistics.py | 43 ++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 phy/apps/large_recording/statistics.py create mode 100644 phy/apps/large_recording/tests/test_statistics.py diff --git a/phy/apps/large_recording/statistics.py b/phy/apps/large_recording/statistics.py new file mode 100644 index 000000000..04742de84 --- /dev/null +++ b/phy/apps/large_recording/statistics.py @@ -0,0 +1,67 @@ +"""Descriptive statistics restricted to retained contiguous observation windows.""" + +import numpy as np +from phylib.stats import correlograms + + +def window_isi(samples, windows, sample_rate): + intervals = [] + for start, end in windows: + first, last = np.searchsorted(samples, [start, end]) + intervals.append(np.diff(samples[first:last]) / sample_rate) + return np.concatenate(intervals) if intervals else np.array([], dtype=np.float64) + + +def window_correlograms( + samples, clusters, windows, cluster_ids, sample_rate, bin_size, window_size +): + """Exact window-local pair counts, without a full-duration rate baseline. + + Positive/negative lag bins follow phylib's floor-to-bin convention. The + central bin counts unordered within-unit pairs and cross-unit pairs with + absolute delays below one bin. Cross-unit central counts sum both temporal + orientations, making them independent of equal-time source row order. + """ + selected = np.isin(clusters, cluster_ids) + order = np.argsort(cluster_ids) + sorted_ids = np.asarray(cluster_ids)[order] + result = None + for start, end in windows: + first, last = np.searchsorted(samples, [start, end]) + mask = selected[first:last] + ticks = samples[first:last][mask] - start + if len(ticks) and ticks.max() >= 2**50: + raise ValueError( + 'Observation window is too long for exact correlogram sample conversion.' + ) + # phylib truncates float times * rate to integer samples. A common + # quarter-sample offset preserves every integer tick after conversion + # without changing any pair delay, including late-clock recordings. + times = (ticks.astype(np.float64) + 0.25) / sample_rate + # Avoid phylib's lookup allocation indexed by absolute cluster ID. + labels = order[np.searchsorted(sorted_ids, clusters[first:last][mask])] + if np.any(np.bincount(labels, minlength=len(cluster_ids)) > 46340): + raise ValueError( + 'Evidence window has too many spikes for exact correlogram counts; prepare shorter windows.' + ) + positive = correlograms( + times, + labels, + sample_rate=sample_rate, + cluster_ids=np.arange(len(cluster_ids)), + bin_size=bin_size, + window_size=window_size, + symmetrize=False, + ).astype(np.int64) + # Accumulate before symmetrization to preserve exact central counts and + # int64 totals across many windows. Self-spike pairs are never counted. + if result is None: + result = positive + else: + result += positive + if result is None: + raise ValueError('Correlograms require at least one observation window.') + center = result[..., 0] + result[..., 0].T + np.fill_diagonal(center, np.diag(result[..., 0])) + result[..., 0] = center + return np.dstack((result[..., 1:][..., ::-1].transpose(1, 0, 2), result)) diff --git a/phy/apps/large_recording/tests/test_statistics.py b/phy/apps/large_recording/tests/test_statistics.py new file mode 100644 index 000000000..1bee50516 --- /dev/null +++ b/phy/apps/large_recording/tests/test_statistics.py @@ -0,0 +1,43 @@ +"""Independent pair-count oracle and observation-boundary regressions.""" + +import numpy as np + +from phy.apps.large_recording.statistics import window_correlograms, window_isi + + +def test_window_isi_excludes_missing_observation_periods_and_preserves_ties(): + samples = np.array([0, 1, 1, 2, 1000, 1002], dtype=np.int64) + windows = np.array([[0, 3], [1000, 1003]], dtype=np.int64) + np.testing.assert_array_equal(window_isi(samples, windows, 1), [1, 0, 1, 2]) + + +def test_late_sample_ccg_matches_all_pairs_oracle_with_sparse_ids(): + origin = 1000 * 3600 * 30000 + samples = origin + np.array([0, 1, 30, 30, 31, 60, 300, 301, 330], dtype=np.int64) + clusters = np.array([2_000_000_000, 2, 2, 2_000_000_000, 2, 2, 2, 2_000_000_000, 2]) + windows = np.array([[origin, origin + 100], [origin + 300, origin + 400]], dtype=np.int64) + ids = [2_000_000_000, 2] + actual = window_correlograms(samples, clusters, windows, ids, 30000, 0.001, 0.004) + expected = np.zeros((2, 2, 5), dtype=np.int64) + lookup = {cluster: index for index, cluster in enumerate(ids)} + for start, end in windows: + rows = [i for i, tick in enumerate(samples) if start <= tick < end] + for index, left in enumerate(rows): + for right in rows[index + 1 :]: + delay = int(samples[right] - samples[left]) // 30 + if delay > 2: + continue + a, b = lookup[clusters[left]], lookup[clusters[right]] + expected[a, b, 2 + delay] += 1 + if a != b or delay != 0: + expected[b, a, 2 - delay] += 1 + np.testing.assert_array_equal(actual, expected) + + +def test_cross_unit_central_pairs_do_not_depend_on_tied_row_order(): + samples = np.array([0, 0, 10, 10], dtype=np.int64) + windows = np.array([[0, 20]], dtype=np.int64) + a = window_correlograms(samples, np.array([0, 1, 1, 0]), windows, [0, 1], 30000, 0.001, 0.004) + b = window_correlograms(samples, np.array([1, 0, 1, 0]), windows, [0, 1], 30000, 0.001, 0.004) + np.testing.assert_array_equal(a, b) + assert a[0, 1, 2] == 4 From 2ad713b2025db386a5a6f113c76343ce0cbb231c Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 11:40:09 +0200 Subject: [PATCH 13/22] Integrate bounded curation GUI with transactional history and evidence views --- phy/apps/large_recording/adapter.py | 364 ++++++++++++++ phy/apps/large_recording/model.py | 53 ++ phy/apps/large_recording/stability.py | 176 +++++++ phy/apps/large_recording/supervisor.py | 459 ++++++++++++++++++ .../large_recording/tests/test_adapter.py | 447 +++++++++++++++++ .../tests/test_gui_lifecycle.py | 150 ++++++ phy/apps/large_recording/views.py | 23 + phy/apps/template/gui.py | 40 +- 8 files changed, 1710 insertions(+), 2 deletions(-) create mode 100644 phy/apps/large_recording/adapter.py create mode 100644 phy/apps/large_recording/model.py create mode 100644 phy/apps/large_recording/stability.py create mode 100644 phy/apps/large_recording/supervisor.py create mode 100644 phy/apps/large_recording/tests/test_adapter.py create mode 100644 phy/apps/large_recording/tests/test_gui_lifecycle.py create mode 100644 phy/apps/large_recording/views.py diff --git a/phy/apps/large_recording/adapter.py b/phy/apps/large_recording/adapter.py new file mode 100644 index 000000000..e4d332008 --- /dev/null +++ b/phy/apps/large_recording/adapter.py @@ -0,0 +1,364 @@ +"""Manifest-gated template controller for bounded recording evidence.""" + +from copy import deepcopy +from pathlib import Path + +import numpy as np +from phylib.io.model import get_template_params +from phylib.utils import Bunch + +from phy.cluster._propositions import MergePropositionController, decode_review_mapping + +from ..base import _allocate_spike_counts, _sample_spikes_evenly +from ..template.gui import TemplateController +from .curation import BoundedSession +from .model import BoundedTemplateModel +from .statistics import window_correlograms, window_isi +from .supervisor import BoundedSupervisor +from .views import EvidenceAmplitudeView, SampledCorrelogramView, SampledISIView + + +class BoundedTemplateController(TemplateController): + gui_name = 'BoundedTemplateGUI' + # Bounded mode has its own state namespace and initial view list. Importing + # ordinary saved dock geometry would suppress the new evidence views. + default_state_path = None + default_views = ( + 'UnitStabilityView', + 'WaveformView', + 'EvidenceAmplitudeView', + 'FeatureView', + 'ProbeView', + 'SampledISIView', + 'SampledCorrelogramView', + ) + + def __init__(self, dir_path=None, model=None, **kwargs): + if model is not None: + raise ValueError( + 'Open bounded packages from their directory, without a supplied model.' + ) + self.bounded_session = BoundedSession(dir_path) + self.evidence_window_index = 0 + kwargs['enable_threading'] = False + kwargs.update(get_template_params(Path(dir_path) / 'params.py')) + kwargs.pop('dir_path', None) + super().__init__(dir_path=dir_path, **kwargs) + + def _create_model(self, dir_path=None, **kwargs): + model = BoundedTemplateModel(dir_path=dir_path, session=self.bounded_session, **kwargs) + if model.sample_rate != self.bounded_session.manifest['sample_rate']: + model.close() + raise ValueError('Bounded params sampling rate disagrees with the manifest.') + model.spike_clusters = self.bounded_session.assignments.copy() + model.metadata = deepcopy(self.bounded_session.metadata) + model.duration = self.bounded_session.manifest['num_samples'] / model.sample_rate + + def reject_save(*args, **kwargs): + raise ValueError('Save bounded curation through supervisor.save() as one transaction.') + + model.save_spike_clusters = reject_save + model.save_metadata = reject_save + model.save_spikes_subset_waveforms = reject_save + model.freeze_source() + return model + + def _cache_methods(self): + # Ordinary persistent feature caches omit the current evidence window. + # Bounded queries are already capped; evaluate them against live state. + return + + def close(self, close_model=True): + super().close(close_model=close_model) + if close_model: + self.bounded_session.close() + + def _set_supervisor(self): + session = self.bounded_session + propositions = self._load_merge_propositions() + self.supervisor = BoundedSupervisor( + spike_clusters=self.model.spike_clusters.copy(), + cluster_groups=self.model.metadata.get('group', {}), + cluster_metrics=self.cluster_metrics, + cluster_labels=self.model.metadata, + similarity=self.similarity_functions[self.similarity], + session=session, + merge_propositions=propositions, + ) + self.supervisor._validate_native() + + def _load_merge_propositions(self): + controller = super()._load_merge_propositions() + reviews = self.bounded_session.extra_documents.get('curation_review.json') + if controller is not None and reviews is not None: + source, mapping = decode_review_mapping(reviews) + if source.get('sha256') != self._merge_proposition_sha256: + raise ValueError('Committed reviews belong to different merge propositions.') + controller = MergePropositionController(controller.catalog._replace(reviews=mapping)) + return controller + + def _set_cluster_metrics(self): + super()._set_cluster_metrics() + self.cluster_metrics['full_count'] = self.get_full_count + self.cluster_metrics['evidence_count'] = lambda c: self.supervisor.n_spikes(c) + self.cluster_metrics['waveform_count'] = self.get_waveform_count + self.cluster_metrics['evidence'] = lambda c: ( + 'pending replay' if self.get_full_count(c) is None else 'sampled windows' + ) + + def _set_view_creator(self): + super()._set_view_creator() + for name in ( + 'ISIView', + 'CorrelogramView', + 'FiringRateView', + 'TraceView', + 'TraceImageView', + ): + self.view_creator.pop(name, None) + self.view_creator.pop('AmplitudeView', None) + self.view_creator['EvidenceAmplitudeView'] = self.create_evidence_amplitude_view + self.view_creator['UnitStabilityView'] = self.create_unit_stability_view + self.view_creator['SampledISIView'] = lambda: SampledISIView(cluster_stat=self._get_isi) + self.view_creator['SampledCorrelogramView'] = lambda: SampledCorrelogramView( + correlograms=self._window_correlograms, sample_rate=self.model.sample_rate + ) + + def _get_waveforms_dict(self): + functions = super()._get_waveforms_dict() + if not self.bounded_session.manifest['capabilities']['stored_waveforms']: + functions.pop('waveforms', None) + functions.pop('mean_waveforms', None) + return functions + + def create_feature_view(self): + if ( + self.model.features is None + and not self.bounded_session.manifest['capabilities']['stored_waveforms'] + ): + return + view = super().create_feature_view() + if view is not None: + view.ex_status = self._window_status() + return view + + def _source_units(self, cluster_id): + version = self.bounded_session.events + cached = getattr(self, '_lineage_cache', None) + if cached is not None and cached[0] is version: + return cached[1].get(int(cluster_id)) + units = {int(c): {int(c)} for c in self.bounded_session.unit_ids} + for event in self.bounded_session.events: + if event['operation'] == 'merge': + parents = [units.pop(c) for c in event['parents']] + units[event['target']] = ( + None if any(p is None for p in parents) else set.union(*parents) + ) + elif event['operation'] == 'threshold_split': + units.pop(event['parent']) + units.update(dict.fromkeys(event['children'])) + self._lineage_cache = version, units + return units.get(int(cluster_id)) + + def get_full_count(self, cluster_id): + units = self._source_units(cluster_id) + if units is None: + return None + if not hasattr(self, '_full_counts'): + self._full_counts = dict( + zip(self.bounded_session.unit_ids, self.bounded_session.manifest['counts']) + ) + counts = self._full_counts + return sum(int(counts[c]) for c in units) + + def get_waveform_count(self, cluster_id): + stored = self.model.spike_waveforms + if stored is None: + return 0 + if ( + not hasattr(self, '_waveform_membership_cache') + or self._waveform_membership_cache[0] is not self.bounded_session.events + ): + labels = self.supervisor.clustering.spike_clusters[stored.spike_ids] + ids, counts = np.unique(labels, return_counts=True) + self._waveform_membership_cache = self.bounded_session.events, dict(zip(ids, counts)) + return int(self._waveform_membership_cache[1].get(cluster_id, 0)) + + def get_mean_firing_rate(self, cluster_id): + count = self.get_full_count(cluster_id) + if count is None: + return None + intervals = np.asarray(self.bounded_session.manifest['valid_intervals']) + exposure = np.sum(intervals[:, 1] - intervals[:, 0]) / self.model.sample_rate + return count / exposure + + @property + def evidence_windows(self): + if not hasattr(self, '_evidence_windows'): + self._evidence_windows = np.load( + self.dir_path / self.bounded_session.manifest['windows_file'] + ) + return self._evidence_windows + + def _get_isi(self, cluster_id): + ids = self.supervisor.clustering.spikes_per_cluster.get(cluster_id, []) + samples = self.model.spike_samples[ids] + return Bunch(data=window_isi(samples, self.evidence_windows, self.model.sample_rate)) + + def _window_correlograms(self, cluster_ids, bin_size, window_size): + return window_correlograms( + self.model.spike_samples, + self.supervisor.clustering.spike_clusters, + self.evidence_windows, + cluster_ids, + self.model.sample_rate, + bin_size, + window_size, + ) + + def create_unit_stability_view(self): + from .stability import UnitStabilityView + + return UnitStabilityView(self) + + @property + def current_evidence_window(self): + return self.evidence_windows[self.evidence_window_index] + + def _window_ids(self, cluster_id=None): + start, end = self.current_evidence_window + if cluster_id is None: + first, last = np.searchsorted(self.model.spike_samples, [start, end]) + return np.arange(first, last, dtype=np.int64) + ids = self.supervisor.clustering.spikes_per_cluster.get( + cluster_id, np.array([], dtype=np.int64) + ) + times = self.model.spike_samples[ids] + first, last = np.searchsorted(times, [start, end]) + return ids[first:last] + + def _window_time(self, ids): + # Subtract int64 samples before floating conversion, even at hour 1000. + return ( + self.model.spike_samples[ids] - self.current_evidence_window[0] + ) / self.model.sample_rate + + def _get_feature_view_spike_ids(self, cluster_id=None, load_all=False): + ids = self._window_ids(cluster_id) + if self.model.features is None: + if self.model.spike_waveforms is None: + return np.array([], dtype=np.int64) + ids = np.intersect1d(ids, self.model.spike_waveforms.spike_ids) + if getattr(self.model, 'features_rows', None) is not None: + ids = np.intersect1d(ids, self.model.features_rows) + limit = self.n_spikes_features_background if cluster_id is None else self.n_spikes_features + return ids if load_all else _sample_spikes_evenly(ids, limit) + + def _get_feature_view_spike_times(self, cluster_id=None, load_all=False): + ids = self._get_feature_view_spike_ids(cluster_id, load_all=load_all) + if not len(ids): + return + start, end = self.current_evidence_window + return Bunch( + data=self._window_time(ids), + spike_ids=ids, + lim=(0.0, (end - start) / self.model.sample_rate), + ) + + def _evidence_amplitudes(self, cluster_ids, load_all=False): + active = [c for c in cluster_ids if c is not None] + eligible = [self._window_ids(c) for c in active] + counts = _allocate_spike_counts( + [len(ids) for ids in eligible], + per_cluster=None if load_all else self.n_spikes_amplitudes, + total=None if load_all else self.n_spikes_amplitudes_total, + ) + values = self.bounded_session.attributes['amplitudes.npy'].reshape(-1) + output = [] + if None in cluster_ids: + ids = self._window_ids() + ids = ids[~np.isin(self.supervisor.clustering.spike_clusters[ids], active)] + ids = _sample_spikes_evenly(ids, self.n_spikes_amplitudes_background) + ids = ids[np.isfinite(values[ids])] + output.append( + Bunch(amplitudes=values[ids], spike_ids=ids, spike_times=self._window_time(ids)) + ) + for ids, count in zip(eligible, counts): + ids = _sample_spikes_evenly(ids, int(count)) + ids = ids[np.isfinite(values[ids])] + output.append( + Bunch(amplitudes=values[ids], spike_ids=ids, spike_times=self._window_time(ids)) + ) + return output + + def create_evidence_amplitude_view(self): + array = self.bounded_session.attributes.get('amplitudes.npy') + if array is None or (array.ndim != 1 and array.shape[1:] != (1,)): + return + start, end = self.current_evidence_window + view = EvidenceAmplitudeView( + amplitudes={'source': self._evidence_amplitudes}, + amplitudes_type='source', + duration=(end - start) / self.model.sample_rate, + split_is_eligible=lambda: False, + ) + view.ex_status = self._window_status() + return view + + def _window_status(self): + start, end = self.current_evidence_window + return ( + f'Evidence window {self.evidence_window_index}: {start / self.model.sample_rate:.3f}–' + f'{end / self.model.sample_rate:.3f} s; time axis is seconds from window start; nonfinite amplitudes omitted.' + ) + + def inspect_evidence_window(self, index): + index = int(index) + if not 0 <= index < len(self.evidence_windows): + raise ValueError('Evidence window index is outside the retained plan.') + self.evidence_window_index = index + gui = getattr(self.supervisor, 'gui', None) + if gui is not None: + start, end = self.current_evidence_window + for view in gui.list_views('EvidenceAmplitudeView', 'FeatureView'): + view.ex_status = self._window_status() + if isinstance(view, EvidenceAmplitudeView): + view.duration = (end - start) / self.model.sample_rate + view.canvas.panzoom.reset() + if view.cluster_ids: + view.plot() + view.update_status() + + def create_gui(self, *args, **kwargs): + gui = super().create_gui(*args, **kwargs) + gui.setWindowTitle( + f'phy — Bounded evidence ({self.model.n_spikes:,} / ' + f'{self.bounded_session.manifest["num_spikes"]:,} spikes)' + ) + + @self.supervisor.actions.add(prompt=True, name='Split by source amplitude') + def split_by_source_amplitude(threshold): + """Split one selected unit below a source amplitude threshold (source units).""" + ids = self.supervisor.selected + if len(ids) != 1: + raise ValueError('Select one unit for a source-amplitude threshold split.') + return self.supervisor.split_source_amplitude(ids[0], float(threshold)) + + @gui.view_actions.add(prompt=True, prompt_default=lambda: self.evidence_window_index) + def inspect_evidence_window(index): + """Inspect a retained evidence window by its zero-based index.""" + self.inspect_evidence_window(index) + + split_action = self.supervisor.actions.get('split') + if split_action is not None: + split_action.setEnabled(False) + split_action.setToolTip( + 'Selected-row splits cannot assign unseen source spikes; use a source-amplitude predicate.' + ) + predicate_action = self.supervisor.actions.get('Split by source amplitude') + if predicate_action is not None: + predicate_action.setEnabled( + 'amplitudes.npy' in self.bounded_session.capabilities['predicate_split_attributes'] + ) + + return gui diff --git a/phy/apps/large_recording/model.py b/phy/apps/large_recording/model.py new file mode 100644 index 000000000..cc0bf62b3 --- /dev/null +++ b/phy/apps/large_recording/model.py @@ -0,0 +1,53 @@ +"""Bounded template loading without dense caches indexed by cluster namespace.""" + +from types import MappingProxyType + +import numpy as np +from phylib.io.model import TemplateModel + + +class BoundedTemplateModel(TemplateModel): + """Load committed assignments and original templates as separate concepts. + + The controller derives live unit evidence from Supervisor assignments. + phylib's eager merged-cluster waveform cache allocates by the maximum + absolute ID and does not track subsequent GUI edits; bounded mode does not + expose that cache as current scientific evidence. + """ + + def __init__(self, *args, session, **kwargs): + self._bounded_session = session + super().__init__(*args, **kwargs) + self.sparse_clusters = None + + def freeze_source(self): + """Prevent public model edits from bypassing semantic curation.""" + names = set() + for name, value in vars(self).items(): + if not name.startswith('_') and isinstance(value, np.ndarray): + value.flags.writeable = False + names.add(name) + self.metadata = MappingProxyType( + {name: MappingProxyType(values) for name, values in self.metadata.items()} + ) + names.update( + ('metadata', 'save_spike_clusters', 'save_metadata', 'save_spikes_subset_waveforms') + ) + self._protected_source_names = frozenset(names) + + def __setattr__(self, name, value): + if name in getattr(self, '_protected_source_names', ()): + raise ValueError('Bounded model source is read-only; use semantic curation commands.') + super().__setattr__(name, value) + + def _load_spike_clusters(self): + return self._bounded_session.assignments.copy() + + def get_merge_map(self): + return {}, np.array([], dtype=np.int64) + + def cluster_waveforms(self): + return None + + def get_cluster_mean_waveforms(self, *args, **kwargs): + raise ValueError('Use the controller waveform/template providers for live bounded units.') diff --git a/phy/apps/large_recording/stability.py b/phy/apps/large_recording/stability.py new file mode 100644 index 000000000..131268fd1 --- /dev/null +++ b/phy/apps/large_recording/stability.py @@ -0,0 +1,176 @@ +"""Selected-unit full-duration evidence with explicit acquisition exposure.""" + +import numpy as np +from phylib.utils import Bunch, connect, unconnect + +from phy.cluster.views import ManualClusteringView +from phy.plot.plot import PlotCanvasMpl + + +class UnitStabilityView(ManualClusteringView): + """Full counts/rates, available source trends, gaps and retained evidence windows.""" + + plot_canvas_class = PlotCanvasMpl + max_n_clusters = 1 + _default_position = 'right' + ex_status = 'Full-duration evidence; sampling cannot establish chronic unit identity.' + + def __init__(self, controller): + super().__init__() + self.controller = controller + self.canvas.subplots(3, 1, sharex=True) + self._summary_arrays = {} + + def _array(self, name): + if name not in self._summary_arrays: + self._summary_arrays[name] = np.load(self.controller.dir_path / name, mmap_mode='r') + return self._summary_arrays[name] + + def get_data(self, cluster_id): + controller = self.controller + session = getattr(controller, 'bounded_session', None) + if session is None: + # Optional ordinary-data view: only the selected cluster is evaluated. + times = controller.get_spike_times(cluster_id) + edges = np.linspace(0, controller.model.duration, 101) + counts, _ = np.histogram(times, edges) + exposure = np.diff(edges) + return Bunch( + edges=edges, + counts=counts, + exposure=exposure, + windows=[], + intervals=[[0, controller.model.duration]], + trends={}, + provenance='Loaded recording; continuous acquisition assumed.', + ) + manifest = session.manifest + summary = manifest.get('summaries', manifest) + edges = self._array(summary['edges_file']) / controller.model.sample_rate + exposure = self._array(summary['exposure_file']) + units = controller._source_units(cluster_id) + if units is None: + return Bunch( + edges=edges, + counts=None, + exposure=exposure, + windows=[], + intervals=[], + trends={}, + provenance='Split evidence pending full-data replay.', + ) + lookup = {int(c): i for i, c in enumerate(session.unit_ids)} + rows = [lookup[c] for c in units] + # Bound temporaries by one unit's summary row, including merged units. + count_grid = self._array(summary['counts_file']) + counts = np.zeros(len(exposure), dtype=np.int64) + for row in rows: + counts += count_grid[row] + trends = {} + for attribute in ('amplitude', 'depth'): + sum_file, count_file = f'{attribute}_sum_file', f'{attribute}_count_file' + if sum_file not in summary: + continue + total, valid = np.zeros(len(exposure)), np.zeros(len(exposure), dtype=np.int64) + for row in rows: + total += self._array(summary[sum_file])[row] + valid += self._array(summary[count_file])[row] + mean = np.full(len(exposure), np.nan) + np.divide(total, valid, out=mean, where=valid > 0) + trends[attribute] = mean + return Bunch( + edges=edges, + counts=counts, + exposure=exposure, + trends=trends, + windows=controller.evidence_windows / controller.model.sample_rate, + intervals=np.asarray(manifest['valid_intervals']) / controller.model.sample_rate, + provenance='Complete source sorting; exact counts and finite-value means.', + ) + + def plot(self, **kwargs): + axes = list(self.canvas.iter_ax()) + for ax in axes: + ax.clear() + session = getattr(self.controller, 'bounded_session', None) + if not self.cluster_ids: + axes[0].text( + 0.02, + 0.6, + 'Select a unit to inspect full-duration evidence.', + transform=axes[0].transAxes, + ) + else: + cluster_id = self.cluster_ids[0] + data = self.get_data(cluster_id) + if data.counts is None: + axes[0].text(0.02, 0.6, data.provenance, transform=axes[0].transAxes) + else: + rates = np.full(len(data.exposure), np.nan) + np.divide(data.counts, data.exposure, out=rates, where=data.exposure > 0) + x = (data.edges[:-1] + data.edges[1:]) / 7200 + axes[0].plot(x, rates) + for ax, attribute in zip(axes[1:], ('amplitude', 'depth')): + if attribute in data.trends: + ax.plot(x, data.trends[attribute]) + else: + ax.text( + 0.02, + 0.6, + f'{attribute.title()} measurement unavailable.', + transform=ax.transAxes, + ) + for ax in axes: + for start, end in data.windows: + ax.axvspan(start / 3600, end / 3600, color='cyan', alpha=0.15) + previous = 0 + for start, end in data.intervals: + if start > previous: + ax.axvspan(previous / 3600, start / 3600, color='gray', alpha=0.4) + previous = end + if previous < data.edges[-1]: + ax.axvspan(previous / 3600, data.edges[-1] / 3600, color='gray', alpha=0.4) + axes[0].set_title(f'Unit {cluster_id} — {data.provenance}', fontsize=9) + axes[0].set_ylabel('Rate (Hz)') + axes[1].set_ylabel('Mean amplitude\n(source units)') + axes[2].set_ylabel('Mean depth\n(source units)') + axes[2].set_xlabel('Elapsed acquisition clock (hours)') + if session is not None: + missing = [ + c for c, n in zip(session.unit_ids, session.manifest['bounded_counts']) if not n + ] + if missing: + axes[2].text( + 0.02, + -0.42, + f'{len(missing)} source units without evidence: ' + f'{", ".join(map(str, missing[:12]))}' + (' …' if len(missing) > 12 else ''), + transform=axes[2].transAxes, + fontsize=8, + ) + self.canvas.figure.tight_layout() + self.canvas.update() + + def on_select(self, cluster_ids=None, **kwargs): + self.cluster_ids = tuple(cluster_ids or ())[:1] + self.plot(**kwargs) + + def attach(self, gui): + super().attach(gui) + + @self.actions.add(prompt=True) + def show_source_unit(cluster_id): + """Inspect a full source unit, including one without sampled evidence.""" + session = getattr(self.controller, 'bounded_session', None) + if session is not None and int(cluster_id) not in session.unit_ids: + raise ValueError('Unknown source unit ID.') + self.on_select([int(cluster_id)]) + + @connect(event='bounded_state_changed', sender=self.controller.supervisor) + def on_state(sender): + self.plot() + + @connect(event='close_view', sender=self) + def on_close(sender, *args): + unconnect(on_state, on_close) + self._summary_arrays.clear() diff --git a/phy/apps/large_recording/supervisor.py b/phy/apps/large_recording/supervisor.py new file mode 100644 index 000000000..a5765232f --- /dev/null +++ b/phy/apps/large_recording/supervisor.py @@ -0,0 +1,459 @@ +"""Guarded native commands paired with semantic state, history and checkpoints.""" + +from contextlib import contextmanager +from copy import deepcopy +from functools import wraps +from types import MappingProxyType + +import numpy as np +from phylib.utils import emit + +from phy.cluster._history import History +from phy.cluster._utils import ClusterMeta +from phy.cluster.clustering import Clustering +from phy.cluster.supervisor import Supervisor + +from .curation import evaluate_predicate, interpret_events + + +class MutationPolicy: + """Only semantic commands may mutate native bounded state.""" + + def __init__(self): + self.depth = 0 + + def require(self): + if not self.depth: + raise ValueError( + 'Bounded curation requires a semantic command. Use supervisor.merge(), ' + 'supervisor.label(), or split_source_amplitude(); arbitrary splits are unavailable.' + ) + + @contextmanager + def command(self): + self.depth += 1 + try: + yield + finally: + self.depth -= 1 + + +class GuardedClustering(Clustering): + def __init__(self, *args, policy, **kwargs): + self.policy = policy + super().__init__(*args, **kwargs) + + @property + def spike_clusters(self): + result = self._spike_clusters.view() + result.flags.writeable = bool(self.policy.depth) + return result + + @property + def cluster_ids(self): + result = self._cluster_ids.view() + result.flags.writeable = False + return result + + @property + def spikes_per_cluster(self): + return MappingProxyType(self._spikes_per_cluster) + + def _update_cluster_ids(self, *args, **kwargs): + super()._update_cluster_ids(*args, **kwargs) + for ids in self._spikes_per_cluster.values(): + ids.flags.writeable = False + + def merge(self, *args, **kwargs): + self.policy.require() + return super().merge(*args, **kwargs) + + def assign(self, *args, **kwargs): + self.policy.require() + return super().assign(*args, **kwargs) + + def reset(self): + self.policy.require() + return super().reset() + + def undo(self): + self.policy.require() + return super().undo() + + def redo(self): + self.policy.require() + return super().redo() + + +class GuardedMeta(ClusterMeta): + def __init__(self, policy): + self.policy = policy + super().__init__() + + def set(self, *args, **kwargs): + self.policy.require() + return super().set(*args, **kwargs) + + def add_field(self, *args, **kwargs): + self.policy.require() + return super().add_field(*args, **kwargs) + + def from_dict(self, *args, **kwargs): + self.policy.require() + return super().from_dict(*args, **kwargs) + + def undo(self): + self.policy.require() + return super().undo() + + def redo(self): + self.policy.require() + return super().redo() + + +class SessionHistory(History): + def __init__(self, session): + self.session = session + super().__init__(session.journal_state()) + + def capture(self): + self.add(self.session.journal_state()) + + def undo(self): + self.back() + self.session.restore_journal(self.current_item) + + def redo(self): + self.forward() + self.session.restore_journal(self.current_item) + + +def semantic_command(method): + @wraps(method) + def execute(self, *args, **kwargs): + with self._transaction(): + return method(self, *args, **kwargs) + + return execute + + +class BoundedSupervisor(Supervisor): + """Native UI/history operations paired with a validated semantic journal.""" + + def __init__(self, *args, session, **kwargs): + self.session = session + self.policy = MutationPolicy() + self.select_actions = None + self.cluster_view = None + self.similarity_view = None + + def clustering_factory(*args, **kwargs): + return GuardedClustering(*args, policy=self.policy, **kwargs) + + def meta_factory(groups, labels): + meta = GuardedMeta(self.policy) + data = {} + for field, values in labels.items(): + for cluster, value in values.items(): + data.setdefault(cluster, {})[field] = value + with self.policy.command(): + meta.add_field('group') + meta.from_dict(data) + return meta + + # Generation state supersedes disposable clustering caches. + kwargs['context'] = None + kwargs['new_cluster_id'] = session.next_cluster_id + kwargs['clustering_factory'] = clustering_factory + kwargs['cluster_meta_factory'] = meta_factory + super().__init__(*args, **kwargs) + self.session_history = SessionHistory(session) + + @contextmanager + def _transaction(self): + """Roll native and semantic state back if an observer or command fails.""" + clustering = self.clustering + arrays = ( + clustering._spike_clusters.copy(), + dict(clustering._spikes_per_cluster), + clustering._cluster_ids.copy(), + ) + data, fields = deepcopy(self.cluster_meta._data), dict(self.cluster_meta._fields) + histories = [ + clustering._undo_stack, + self.cluster_meta._undo_stack, + self._global_history, + self.session_history, + ] + if self.merge_propositions is not None: + histories.append(self.merge_propositions._history) + history_states = [(list(h._history), h._index) for h in histories] + journal, selection, dirty = ( + self.session.journal_state(), + self.selection.snapshot(), + self._is_dirty, + ) + propositions = ( + self.merge_propositions.snapshot() if self.merge_propositions is not None else None + ) + workflow, columns = self._workflow_context(), list(self.columns) + try: + yield + except Exception: + clustering._spike_clusters, clustering._spikes_per_cluster, clustering._cluster_ids = ( + arrays + ) + self.cluster_meta._data, self.cluster_meta._fields = data, fields + for history, (items, index) in zip(histories, history_states): + history._history, history._index = items, index + self.session.restore_journal(journal) + self.session.next_cluster_id = max( + self.session.next_cluster_id, clustering.new_cluster_id() + ) + self.selection.restore(selection) + if propositions is not None: + self.merge_propositions.restore(propositions) + self._is_dirty = dirty + self.columns = columns + self._lineage_cache = None + if self.gui is not None: + self._reset_cluster_view() + self._restore_history_context( + selection, + { + 'mode': 'merge' if selection.is_merge_mode else 'post_merge', + 'tables': workflow, + }, + 'undo', + ) + self._refresh_bounded() + self._update_save_feedback() + raise + + def _require_capability(self, name): + if not self.session.manifest.get('capabilities', {}).get(name, False): + raise ValueError(f'This bounded package does not allow {name} operations.') + + def get_cluster_info(self, cluster_id, exclude=()): + info = super().get_cluster_info(cluster_id, exclude=exclude) + # Producer TSV labels may use metric names. They must not overwrite + # authoritative complete-sorting counts/rates with inherited values. + for name in ( + 'n_spikes', + 'fr', + 'full_count', + 'evidence_count', + 'waveform_count', + 'evidence', + ): + if name not in exclude and name in self.cluster_metrics: + info[name] = self.cluster_metrics[name](cluster_id) + return info + + def _select_after_merge(self, *args, **kwargs): + if self.gui is not None: + return super()._select_after_merge(*args, **kwargs) + + def _select_after_split(self, *args, **kwargs): + if self.gui is not None: + return super()._select_after_split(*args, **kwargs) + + def _restore_history_context(self, *args, **kwargs): + if self.gui is not None: + return super()._restore_history_context(*args, **kwargs) + + def _reset_cluster_view(self, *args, **kwargs): + if self.gui is not None: + return super()._reset_cluster_view(*args, **kwargs) + + def _workflow_context(self): + return super()._workflow_context() if self.gui is not None else {} + + def _validate_native(self, metadata=True): + if not np.array_equal(self.clustering.spike_clusters, self.session.assignments): + raise ValueError('Native assignments disagree with the bounded semantic command.') + if metadata: + active, expected, _ = interpret_events( + self.session.unit_ids, self.session.base_metadata, self.session.events + ) + for field in set(self.cluster_meta.fields) | set(expected): + for cluster in active: + actual = ( + self.cluster_meta.get(field, cluster) + if field in self.cluster_meta.fields + else None + ) + if actual != expected.get(field, {}).get(cluster): + raise ValueError( + 'Native metadata disagrees with the bounded semantic command.' + ) + + def _synchronize_metadata(self): + # Native ClusterMeta.undo does not retain nonstacked inherited merge + # labels. The semantic projection is authoritative in bounded mode. + data = {} + for field, values in self.session.metadata.items(): + if field not in self.cluster_meta.fields: + with self.policy.command(): + self.cluster_meta.add_field(field) + for cluster, value in values.items(): + data.setdefault(cluster, {})[field] = value + self.cluster_meta._data = data + + def _refresh_bounded(self): + if self.gui is not None: + data = self.cluster_info + self.cluster_view.change(data) + self.similarity_view.change(data) + if self.merge_view is not None: + self.merge_view.change(data) + emit('bounded_state_changed', self) + + def _capture(self): + self._validate_native() + self.session_history.capture() + self._global_history.add_to_current_action(self.session_history) + self._is_dirty = True + self._update_save_feedback() + self._synchronize_metadata() + self._refresh_bounded() + + @semantic_command + def merge(self, cluster_ids=None, to=None): + self._require_capability('merge') + parents = list(self.selected if cluster_ids is None else cluster_ids) + if len(parents) < 2: + return + target = max(self.clustering.new_cluster_id(), self.session.next_cluster_id) + target = target if to is None else int(to) + self.session.preflight_merge(parents, target) + with self.policy.command(): + out = super().merge(cluster_ids=cluster_ids, to=target) + if out is None: + return + resolved = { + field: self.cluster_meta.get(field, target) for field in self.cluster_meta.fields + } + self.session.record_merge(parents, target, metadata=resolved) + self._capture() + return out + + @semantic_command + def label(self, name, value, cluster_ids=None): + self._require_capability('label') + if name in ( + 'n_spikes', + 'fr', + 'full_count', + 'evidence_count', + 'waveform_count', + 'evidence', + ): + raise ValueError('Bounded count/rate/evidence columns are read-only metrics.') + ids = list(self.selected if cluster_ids is None else np.atleast_1d(cluster_ids)) + if not ids or self.selection.state.is_merge_mode: + return + # Preflight against a copy before touching native metadata. + before = self.session.snapshot() + self.session.record_label(name, ids, value) + self.session.restore(before) + with self.policy.command(): + super().label(name, value, cluster_ids=ids) + self.session.record_label(name, ids, value) + self._capture() + + def split(self, *args, **kwargs): + raise ValueError( + 'Lasso, feature and waveform splits cannot be replayed on unseen spikes. ' + 'Use Split by source amplitude for a full-source scalar predicate.' + ) + + @semantic_command + def split_source_amplitude(self, cluster_id, threshold): + if 'amplitudes.npy' not in self.session.manifest.get('capabilities', {}).get( + 'predicate_split_attributes', [] + ): + raise ValueError('This package does not support source-amplitude predicate splits.') + if self.selection.state.is_merge_mode: + raise ValueError('Leave Merge mode before splitting by source amplitude.') + if 'amplitudes.npy' not in self.session.attributes: + raise ValueError('The source has no scalar per-spike amplitudes.') + predicate = { + 'attribute': 'amplitudes.npy', + 'operator': '<', + 'threshold': float(threshold), + 'nonfinite': 'keep', + } + ids = self.clustering.spikes_per_cluster.get(int(cluster_id), np.array([], dtype=np.int64)) + selected = ids[ + evaluate_predicate(self.session.attributes['amplitudes.npy'][ids], predicate) + ] + if not len(selected) or len(selected) == len(ids): + raise ValueError('Both sides of the threshold must have evidence spikes.') + selected_id = max(self.clustering.new_cluster_id(), self.session.next_cluster_id) + remainder_id = selected_id + 1 + self.clustering._new_cluster_id = selected_id + metadata = { + field: { + child: self.cluster_meta.get(field, cluster_id) + for child in (selected_id, remainder_id) + } + for field in self.cluster_meta.fields + } + before = self.session.snapshot() + self.session.record_threshold_split( + int(cluster_id), [remainder_id, selected_id], predicate, metadata=metadata + ) + self.session.restore(before) + with self.policy.command(): + out = Supervisor.split(self, selected) + self.session.record_threshold_split( + int(cluster_id), [remainder_id, selected_id], predicate, metadata=metadata + ) + self._capture() + return out + + @semantic_command + def undo(self): + with self.policy.command(): + super().undo() + self._after_history() + + @semantic_command + def redo(self): + with self.policy.command(): + super().redo() + self._after_history() + + def _after_history(self): + self._validate_native(metadata=False) + # Never reuse allocated IDs after branching or restoring a snapshot. + self.session.next_cluster_id = max( + self.session.next_cluster_id, self.clustering.new_cluster_id() + ) + self._is_dirty = True + self._update_save_feedback() + self._synchronize_metadata() + self._refresh_bounded() + + def save(self): + self._validate_native() + documents = None + if self.merge_propositions is not None: + from .source import hash_file + + documents = { + 'curation_review.json': self.merge_propositions.catalog.review_mapping( + source_sha256=hash_file(self.session.path / 'curation.json') + ) + } + self.session.save( + assignments=self.clustering.spike_clusters, + metadata=self.session.metadata, + next_cluster_id=max(self.session.next_cluster_id, self.clustering.new_cluster_id()), + extra_documents=documents, + ) + if self.merge_propositions is not None: + self.merge_propositions.mark_saved() + self._is_dirty = False + self._update_save_feedback(saved=True) diff --git a/phy/apps/large_recording/tests/test_adapter.py b/phy/apps/large_recording/tests/test_adapter.py new file mode 100644 index 000000000..937d45433 --- /dev/null +++ b/phy/apps/large_recording/tests/test_adapter.py @@ -0,0 +1,447 @@ +"""Bounded GUI correctness and ordinary-controller isolation.""" + +import json + +import numpy as np +import pytest +from click.testing import CliRunner +from phylib.utils import connect, unconnect + +from phy.apps import phycli +from phy.apps.large_recording.adapter import BoundedTemplateController +from phy.apps.large_recording.curation import BoundedSession +from phy.apps.large_recording.prepare import prepare_large +from phy.apps.large_recording.replay import apply_curation +from phy.apps.large_recording.tests.test_source import make_sorting +from phy.apps.template.gui import TemplateController + + +def make_controller(tmp_path, sparse=False): + params = make_gui_sorting(tmp_path / 'source') + output = prepare_large( + params, + tmp_path / 'bounded', + window_seconds=3 if sparse else 20, + stratum_seconds=20, + max_spikes=5 if sparse else 100, + bin_seconds=5, + batch_size=2, + ) + controller = TemplateController( + dir_path=output, + config_dir=tmp_path / 'config', + plugins=[], + enable_threading=False, + clear_cache=True, + ) + return params, controller + + +def make_gui_sorting(path): + params = make_sorting(path) + times = np.load(path / 'spike_times.npy') + np.save(path / 'spike_times.npy', times * 30000) + params.write_text( + params.read_text() + .replace('sample_rate = 1.0', 'sample_rate = 30000.0') + .replace('num_samples = 20', 'num_samples = 600000') + ) + return params + + +def test_manifest_factory_reserves_complete_ids_and_guards_mutations(tmp_path): + _, controller = make_controller(tmp_path, sparse=True) + try: + assert isinstance(controller, BoundedTemplateController) + with pytest.raises(ValueError): + controller.model.spike_clusters[0] = 123 + with pytest.raises(ValueError): + controller.model.spike_clusters = np.array([123]) + with pytest.raises(TypeError): + controller.model.metadata['group'][0] = 'noise' + supervisor = controller.supervisor + assert 99 not in supervisor.clustering.cluster_ids + assert supervisor.clustering.new_cluster_id() == 100 + assert controller.get_full_count(0) == 4 + assert controller.get_mean_firing_rate(0) == 0.2 + for operation in ( + lambda: supervisor.clustering.merge([0, 1]), + lambda: supervisor.clustering.assign([0]), + lambda: supervisor.clustering.split([0]), + supervisor.clustering.undo, + supervisor.clustering.redo, + supervisor.clustering.reset, + lambda: supervisor.cluster_meta.set('group', [0], 'noise', add_to_stack=False), + lambda: supervisor.cluster_meta.from_dict({0: {'group': 'noise'}}), + lambda: controller.model.save_spike_clusters(supervisor.clustering.spike_clusters), + lambda: controller.model.save_metadata('group', {0: 'noise'}), + lambda: supervisor.split([0]), + ): + with pytest.raises(ValueError): + operation() + with pytest.raises(ValueError): + supervisor.clustering.spike_clusters[0] = 8 + assert not controller.bounded_session.events + with pytest.raises(ValueError): + supervisor.cluster_meta.add_field('group', 'noise') + with pytest.raises(TypeError): + supervisor.clustering.spikes_per_cluster[0] = np.array([0]) + with pytest.raises(ValueError): + supervisor.clustering.spikes_per_cluster[0][0] = 1 + assert 'CorrelogramView' not in controller.view_creator + assert 'FiringRateView' not in controller.view_creator + finally: + controller.close() + + +def test_loader_and_native_history_do_not_allocate_by_sparse_unit_id(qtbot, tmp_path): + params = make_gui_sorting(tmp_path / 'source') + labels = np.load(params.parent / 'spike_clusters.npy').astype(np.int64) + labels[labels == 99] = 2_000_000_000 + np.save(params.parent / 'spike_clusters.npy', labels) + (params.parent / 'cluster_group.tsv').write_text( + 'cluster_id\tgroup\n0\tgood\n1\tmua\n2\tgood\n2000000000\tnoise\n' + ) + output = prepare_large(params, tmp_path / 'bounded', window_seconds=20, stratum_seconds=20) + controller = TemplateController(dir_path=output, config_dir=tmp_path / 'config', plugins=[]) + try: + assert controller.model.sparse_clusters is None + first = controller.supervisor.merge([0, 1]) + assert first.added == [2_000_000_001] + controller.supervisor.merge([2, 2_000_000_001]) + controller.supervisor.undo() + assert 2_000_000_001 in controller.supervisor.clustering.cluster_ids + values = controller._window_correlograms([2, 2_000_000_001], 0.001, 0.004) + assert values.shape == (2, 2, 5) + controller.supervisor.save() + finally: + controller.close() + reopened = TemplateController(dir_path=output, config_dir=tmp_path / 'config', plugins=[]) + try: + assert 2_000_000_001 in reopened.model.cluster_ids + assert reopened.model.sparse_clusters is None + finally: + reopened.close() + + +def test_merge_label_history_save_reopen_replay_regenerate(tmp_path): + params, controller = make_controller(tmp_path) + path = controller.dir_path + try: + supervisor = controller.supervisor + original_file = (path / 'spike_clusters.npy').read_bytes() + up = supervisor.merge([0, 1]) + assert up.added == [100] + assert controller.get_full_count(100) == 7 + supervisor.label('group', 'noise', [100]) + supervisor.undo() + assert controller.bounded_session.metadata['group'][100] == 'good' + assert supervisor.cluster_meta.get('group', 100) == 'good' + supervisor.redo() + assert controller.bounded_session.metadata['group'][100] == 'noise' + supervisor.undo() + supervisor.undo() + np.testing.assert_array_equal( + supervisor.clustering.spike_clusters, controller.bounded_session.base_assignments + ) + supervisor.merge([1, 2]) + assert supervisor.clustering.new_cluster_id() == 102 + supervisor.label('quality', 'reviewed', [101]) + supervisor.save() + assert not supervisor.is_dirty() + assert (path / 'spike_clusters.npy').read_bytes() == original_file + expected = supervisor.clustering.spike_clusters.copy() + finally: + controller.close() + reopened = TemplateController( + dir_path=path, config_dir=tmp_path / 'config', plugins=[], enable_threading=False + ) + try: + np.testing.assert_array_equal(reopened.supervisor.clustering.spike_clusters, expected) + assert reopened.supervisor.clustering.new_cluster_id() == 102 + assert reopened.supervisor.cluster_meta.get('quality', 101) == 'reviewed' + assert reopened.supervisor._global_history.current_position == 0 + finally: + reopened.close() + output = apply_curation(params, path, tmp_path / 'curated', batch_size=2) + source = np.load(params.parent / 'spike_clusters.npy') + oracle = source.copy() + oracle[np.isin(source, [1, 2])] = 101 + np.testing.assert_array_equal(np.load(output / 'spike_clusters.npy'), oracle) + regenerated = prepare_large( + output / 'params.py', + tmp_path / 'regenerated', + window_seconds=20, + stratum_seconds=20, + bin_seconds=5, + ) + assert BoundedSession(regenerated).unit_ids == [0, 99, 101] + + +def test_source_threshold_replays_every_spike_and_full_metrics_pending(tmp_path): + params, controller = make_controller(tmp_path) + try: + supervisor = controller.supervisor + up = supervisor.split_source_amplitude(0, 4) + assert set(up.added) == {100, 101} + assert controller.get_full_count(100) is None + assert controller.get_mean_firing_rate(101) is None + supervisor.undo() + assert controller.get_full_count(0) == 4 + supervisor.redo() + supervisor.save() + output = apply_curation(params, controller.dir_path, tmp_path / 'curated', batch_size=2) + source = np.load(params.parent / 'spike_clusters.npy') + amplitudes = np.load(params.parent / 'amplitudes.npy') + oracle = source.copy() + oracle[(source == 0) & (amplitudes < 4)] = 100 + oracle[(source == 0) & ~(amplitudes < 4)] = 101 + np.testing.assert_array_equal(np.load(output / 'spike_clusters.npy'), oracle) + finally: + controller.close() + + +def test_failed_save_leaves_dirty_previous_checkpoint(tmp_path, monkeypatch): + _, controller = make_controller(tmp_path) + try: + supervisor = controller.supervisor + supervisor.merge([0, 1]) + supervisor.save() + supervisor.label('group', 'noise', [100]) + from phy.apps.large_recording import curation + + original = curation._write_json + + def fail(path, value): + if path.name == 'journal.json': + raise OSError('interrupted') + return original(path, value) + + monkeypatch.setattr(curation, '_write_json', fail) + with pytest.raises(OSError, match='interrupted'): + supervisor.save() + assert supervisor.is_dirty() + assert BoundedSession(controller.dir_path).metadata['group'][100] == 'good' + finally: + controller.close() + + +def test_standard_controller_retains_existing_path_and_save_format(qtbot, tmp_path): + params = make_gui_sorting(tmp_path / 'ordinary') + controller = TemplateController( + dir_path=params.parent, + config_dir=tmp_path / 'config', + plugins=[], + enable_threading=False, + sample_rate=30000, + n_channels_dat=3, + dtype='int16', + ) + gui = controller.create_gui(default_views=[], do_prompt_save=False) + try: + assert type(controller) is TemplateController + assert controller.gui_name == 'TemplateGUI' + assert controller.default_views[0] == 'WaveformView' + assert 'FiringRateView' in controller.view_creator + up = controller.supervisor.merge([0, 1]) + controller.supervisor.save() + assert up.added == [100] + assert not (params.parent / '.phy-curation').exists() + assert not (params.parent / '_phy_curation_manifest.json').exists() + assert 100 in np.load(params.parent / 'spike_clusters.npy') + finally: + gui.close() + controller.close() + + +def test_malformed_manifest_fails_before_model_loading(tmp_path): + params = make_sorting(tmp_path / 'ordinary') + (params.parent / '_phy_curation_manifest.json').write_text(json.dumps({'format_version': 99})) + with pytest.raises(ValueError, match='Unsupported'): + TemplateController(dir_path=params.parent, plugins=[]) + + +def test_cli_preparation_and_replay(tmp_path): + params = make_sorting(tmp_path / 'source') + runner = CliRunner() + output = tmp_path / 'bounded' + result = runner.invoke( + phycli, + [ + 'prepare-large', + str(params), + str(output), + '--window-seconds', + '20', + '--stratum-seconds', + '20', + '--bin-seconds', + '5', + '--batch-size', + '2', + ], + ) + assert result.exit_code == 0, result.output + session = BoundedSession(output) + session.record_merge([0, 1], 100, {'group': 'good'}) + session.save() + result = runner.invoke( + phycli, + [ + 'apply-curation', + str(params), + str(output), + str(tmp_path / 'curated'), + '--batch-size', + '2', + ], + ) + assert result.exit_code == 0, result.output + + +def test_stability_gui_and_exact_trends(qtbot, tmp_path): + _, controller = make_controller(tmp_path, sparse=True) + gui = controller.create_gui(default_views=['UnitStabilityView'], do_prompt_save=False) + try: + assert 'Bounded evidence' in gui.windowTitle() + view = gui.list_views('UnitStabilityView')[0] + data = view.get_data(0) + assert data.counts.sum() == 4 + np.testing.assert_allclose(data.trends['amplitude'], [1.5, np.nan, 6, 9], equal_nan=True) + view.on_select([99]) # Unit absent from evidence still has full-duration counts. + assert view.get_data(99).counts.sum() == 2 + controller.supervisor.merge([0, 1]) + controller.supervisor.block() + assert view.get_data(100).counts.sum() == 7 + finally: + gui.close() + controller.close() + + +def test_observer_mutation_rolls_back_native_and_semantic_state(tmp_path): + _, controller = make_controller(tmp_path) + supervisor = controller.supervisor + once = [] + + @connect(event='cluster', sender=supervisor.clustering) + def mutate(sender, up): + if not once: + once.append(True) + sender.assign([0]) + + try: + with pytest.raises(ValueError, match='Native assignments'): + supervisor.merge([0, 1]) + np.testing.assert_array_equal( + supervisor.clustering.spike_clusters, controller.bounded_session.base_assignments + ) + assert not controller.bounded_session.events + assert supervisor._global_history.current_position == 0 + assert not supervisor.is_dirty() + finally: + unconnect(mutate) + controller.close() + + +def test_evidence_navigation_never_reuses_old_feature_cache(tmp_path): + _, controller = make_controller(tmp_path, sparse=True) + try: + first = controller._get_features(0, channel_ids=[0, 1], load_all=True) + assert first.spike_ids.tolist() == [0, 3] + controller.inspect_evidence_window(1) + assert not controller._get_feature_view_spike_ids(0, load_all=True).size + assert not controller._get_features(0, channel_ids=[0, 1], load_all=True) + finally: + controller.close() + + +def test_late_clock_evidence_preserves_submillisecond_positions(tmp_path): + params = make_gui_sorting(tmp_path / 'source') + origin = 1000 * 3600 * 30000 + times = np.load(params.parent / 'spike_times.npy') + origin + times[1:4] = origin + np.array([30, 31, 60]) + np.save(params.parent / 'spike_times.npy', times) + params.write_text( + params.read_text().replace('num_samples = 600000', f'num_samples = {origin + 600000}') + + f'valid_intervals = [[{origin}, {origin + 600000}]]\n' + ) + output = prepare_large( + params, tmp_path / 'bounded', window_seconds=20, stratum_seconds=20, bin_seconds=3600 + ) + controller = TemplateController(dir_path=output, config_dir=tmp_path / 'config', plugins=[]) + try: + positions = controller._window_time(np.array([1, 2])) + assert positions[1] - positions[0] == pytest.approx(1 / 30000) + assert np.float32(positions[0]) != np.float32(positions[1]) + finally: + controller.close() + + +def test_empty_window_and_nonfinite_amplitude_measurements(qtbot, tmp_path): + _, controller = make_controller(tmp_path, sparse=True) + view = controller.create_evidence_amplitude_view() + try: + controller.inspect_evidence_window(1) + view.on_select([0]) + assert view.data_bounds == (0, 0, view.duration, 1) + assert all(not len(b.amplitudes) for b in view._displayed_bunchs) + finally: + view.canvas.close() + controller.close() + + +def test_proposition_reviews_checkpoint_and_failed_review_history(tmp_path): + from phy.cluster._propositions import MergePropositionController, decode_curation_mapping + + _, controller = make_controller(tmp_path) + supervisor = controller.supervisor + mapping = {'format_version': '2', 'unit_ids': [0, 1, 2, 99], 'merges': [{'unit_ids': [0, 1]}]} + producer = controller.dir_path / 'curation.json' + producer.write_text(json.dumps(mapping)) + supervisor.merge_propositions = MergePropositionController(decode_curation_mapping(mapping)) + key = supervisor.merge_propositions.catalog.propositions[0].key + try: + with pytest.raises(RuntimeError, match='observer'), supervisor._transaction(): + supervisor.merge_propositions.accept(key, [0, 1], 100) + raise RuntimeError('observer') + assert supervisor.merge_propositions._history.current_position == 0 + assert not supervisor.merge_propositions.catalog.reviews + supervisor.merge_propositions.reject(key) + supervisor.save() + controller.close() + reopened = TemplateController( + dir_path=producer.parent, config_dir=tmp_path / 'config', plugins=[] + ) + try: + assert ( + reopened.supervisor.merge_propositions.catalog.status_for(key).value == 'rejected' + ) + assert not reopened.supervisor.is_dirty() + finally: + reopened.close() + finally: + controller.close() + + +def test_nonfinite_source_amplitudes_are_omitted_from_plots_and_kept_in_replay(qtbot, tmp_path): + params = make_gui_sorting(tmp_path / 'source') + amplitudes = np.load(params.parent / 'amplitudes.npy') + amplitudes[3] = np.inf + amplitudes[6] = np.nan + np.save(params.parent / 'amplitudes.npy', amplitudes) + output = prepare_large(params, tmp_path / 'bounded', window_seconds=20, stratum_seconds=20) + controller = TemplateController(dir_path=output, config_dir=tmp_path / 'config', plugins=[]) + view = controller.create_evidence_amplitude_view() + try: + view.on_select([0]) + assert np.all(np.isfinite(view.data_bounds)) + assert all(np.all(np.isfinite(b.amplitudes)) for b in view._displayed_bunchs) + controller.supervisor.split_source_amplitude(0, 4) + controller.supervisor.save() + curated = apply_curation(params, output, tmp_path / 'curated') + labels = np.load(curated / 'spike_clusters.npy') + assert labels[0] == 100 + assert labels[3] == labels[6] == 101 + finally: + view.canvas.close() + controller.close() diff --git a/phy/apps/large_recording/tests/test_gui_lifecycle.py b/phy/apps/large_recording/tests/test_gui_lifecycle.py new file mode 100644 index 000000000..c6d951b38 --- /dev/null +++ b/phy/apps/large_recording/tests/test_gui_lifecycle.py @@ -0,0 +1,150 @@ +"""GUI transaction, proposition review, and pending-metric regressions.""" + +import json + +import numpy as np +import pytest +from phylib.utils import connect, unconnect + +from phy.apps.large_recording.prepare import prepare_large +from phy.apps.large_recording.tests.test_adapter import make_controller, make_gui_sorting +from phy.apps.template.gui import TemplateController + + +def test_gui_observer_mutation_rolls_back_views_selection_and_journal(qtbot, tmp_path): + _, controller = make_controller(tmp_path) + gui = controller.create_gui(default_views=[], do_prompt_save=False) + supervisor = controller.supervisor + once = [] + + try: + supervisor.select([0]) + supervisor.block() + assignments = supervisor.clustering.spike_clusters.copy() + events = list(controller.bounded_session.events) + selection = supervisor.selection.snapshot() + cluster_ids = supervisor.cluster_view.get_ids() + similarity_ids = supervisor.similarity_view.get_ids() + histories = tuple( + (history._index, len(history._history)) + for history in ( + supervisor.clustering._undo_stack, + supervisor.cluster_meta._undo_stack, + supervisor._global_history, + supervisor.session_history, + ) + ) + dirty = supervisor.is_dirty() + + @connect(event='cluster', sender=supervisor.clustering) + def mutate(sender, up): + if not once: + once.append(True) + sender.assign([0]) + + with pytest.raises((ValueError, KeyError)): + supervisor.merge([0, 1]) + supervisor.block() + + np.testing.assert_array_equal(supervisor.clustering.spike_clusters, assignments) + assert controller.bounded_session.events == events + assert supervisor.selection.snapshot() == selection + assert supervisor.cluster_view.get_ids() == cluster_ids + assert supervisor.similarity_view.get_ids() == similarity_ids + assert ( + tuple( + (history._index, len(history._history)) + for history in ( + supervisor.clustering._undo_stack, + supervisor.cluster_meta._undo_stack, + supervisor._global_history, + supervisor.session_history, + ) + ) + == histories + ) + assert supervisor.is_dirty() == dirty + finally: + if 'mutate' in locals(): + unconnect(mutate) + gui.close() + controller.close() + + +def test_gui_proposition_review_undo_redo_and_checkpoint_reopen(qtbot, tmp_path): + params = make_gui_sorting(tmp_path / 'source') + proposal = { + 'format_version': '2', + 'unit_ids': [0, 1, 2, 99], + 'merges': [{'unit_ids': [0, 1]}], + } + (params.parent / 'curation.json').write_text(json.dumps(proposal), encoding='utf-8') + bounded = prepare_large( + params, + tmp_path / 'bounded', + window_seconds=20, + stratum_seconds=20, + bin_seconds=5, + batch_size=2, + ) + config = tmp_path / 'config' + controller = TemplateController( + dir_path=bounded, config_dir=config, plugins=[], enable_threading=False + ) + gui = controller.create_gui(default_views=[], do_prompt_save=False) + supervisor = controller.supervisor + proposition = supervisor.merge_propositions.catalog.propositions[0] + key = proposition.key + + try: + supervisor._review_merge_proposition(supervisor.merge_propositions_view, key) + assert supervisor.selection.state.is_merge_mode + assert supervisor.selected_merge == [0, 1] + + merged = supervisor.merge() + supervisor.block() + assert merged.added == [100] + assert supervisor.merge_propositions.catalog.status_for(key).value == 'accepted' + assert controller.bounded_session.events[-1]['target'] == 100 + + supervisor.undo() + supervisor.block() + assert supervisor.merge_propositions.catalog.status_for(key).value == 'pending' + assert controller.bounded_session.events == [] + + supervisor.redo() + supervisor.block() + assert supervisor.merge_propositions.catalog.status_for(key).value == 'accepted' + assert controller.bounded_session.events[-1]['target'] == 100 + supervisor.save() + finally: + gui.close() + controller.close() + + reopened = TemplateController( + dir_path=bounded, config_dir=config, plugins=[], enable_threading=False + ) + try: + key = reopened.supervisor.merge_propositions.catalog.propositions[0].key + assert reopened.supervisor.merge_propositions.catalog.status_for(key).value == 'accepted' + assert reopened.bounded_session.events[-1]['target'] == 100 + finally: + reopened.close() + + +def test_default_bounded_views_handle_threshold_children_with_pending_metrics(qtbot, tmp_path): + _, controller = make_controller(tmp_path) + gui = controller.create_gui(do_prompt_save=False) + try: + supervisor = controller.supervisor + update = supervisor.split_source_amplitude(0, 4) + supervisor.block() + assert set(update.added) == {100, 101} + for cluster_id in update.added: + row = supervisor.cluster_view._model.row_by_id(cluster_id) + assert row['fr'] is None + assert row['full_count'] is None + assert row['evidence'] == 'pending replay' + finally: + gui.close() + controller.close() diff --git a/phy/apps/large_recording/views.py b/phy/apps/large_recording/views.py new file mode 100644 index 000000000..d19d5190e --- /dev/null +++ b/phy/apps/large_recording/views.py @@ -0,0 +1,23 @@ +"""Explicitly sampled statistics and window-relative amplitude views.""" + +from phy.cluster.views import AmplitudeView, CorrelogramView, ISIView + + +class SampledISIView(ISIView): + ex_status = 'Selected windows only; intervals crossing window boundaries excluded.' + + +class SampledCorrelogramView(CorrelogramView): + ex_status = 'Selected windows only; raw pair counts, no full-recording rate baseline.' + + +class EvidenceAmplitudeView(AmplitudeView): + """Raw source amplitude in an explicitly rebased evidence window.""" + + def _get_data_bounds(self, bunchs): + if not any(len(bunch.amplitudes) for bunch in bunchs): + return (0, 0, self.duration, 1) + xmin, ymin, xmax, ymax = super()._get_data_bounds(bunchs) + if ymin == ymax: + ymin, ymax = ymin - 0.5, ymax + 0.5 + return xmin, ymin, xmax, ymax diff --git a/phy/apps/template/gui.py b/phy/apps/template/gui.py index bda606c42..d8c1db3ba 100644 --- a/phy/apps/template/gui.py +++ b/phy/apps/template/gui.py @@ -81,6 +81,14 @@ class TemplateController(WaveformMixin, FeatureMixin, TemplateMixin, TraceMixin, # Internal methods # ------------------------------------------------------------------------- + def __new__(cls, dir_path=None, *args, **kwargs): + if cls is TemplateController and dir_path is not None: + if (Path(dir_path) / '_phy_curation_manifest.json').exists(): + from ..large_recording.adapter import BoundedTemplateController + + return object.__new__(BoundedTemplateController) + return object.__new__(cls) + def _get_waveforms_dict(self): waveforms_dict = super()._get_waveforms_dict() # Remove waveforms and mean_waveforms if there is no raw data file. @@ -142,6 +150,7 @@ def _get_template_features(self, cluster_ids, load_all=False): def _set_view_creator(self): super()._set_view_creator() self.view_creator['TemplateFeatureView'] = self.create_template_feature_view + self.view_creator['UnitStabilityView'] = self.create_unit_stability_view # Public methods # ------------------------------------------------------------------------- @@ -255,6 +264,12 @@ def create_template_feature_view(self): return return TemplateFeatureView(coords=self._get_template_features) + def create_unit_stability_view(self): + """Optionally inspect selected-unit activity over the loaded recording.""" + from ..large_recording.stability import UnitStabilityView + + return UnitStabilityView(self) + # ------------------------------------------------------------------------------ # Template commands @@ -268,9 +283,14 @@ def template_gui(params_path, **kwargs): # pragma: no cover dir_path = p.parent _add_log_file(dir_path / 'phy.log') - model = load_model(params_path) + bounded = (dir_path / '_phy_curation_manifest.json').exists() + model = None if bounded else load_model(params_path) # Automatically export spike waveforms when using compressed raw ephys. - if model.spike_waveforms is None and isinstance(model.traces, MtscompEphysReader): + if ( + model is not None + and model.spike_waveforms is None + and isinstance(model.traces, MtscompEphysReader) + ): # TODO: customizable values below. model.save_spikes_subset_waveforms(max_n_spikes_per_template=500, max_n_channels=16) @@ -285,6 +305,22 @@ def template_gui(params_path, **kwargs): # pragma: no cover def template_describe(params_path): """Describe a template dataset.""" + if (Path(params_path).parent / '_phy_curation_manifest.json').exists(): + from ..large_recording.curation import BoundedSession + + session = BoundedSession(Path(params_path).parent) + try: + print(f'Bounded evidence: {len(session.assignments):,} spikes') + print( + f'Complete source: {session.manifest["num_spikes"]:,} spikes, {len(session.unit_ids):,} units' + ) + print( + f'Duration: {session.manifest["num_samples"] / session.manifest["sample_rate"]:.3f} s' + ) + print(f'Committed curation: {len(session.events)} semantic operations') + finally: + session.close() + return model = load_model(params_path) model.describe() model.close() From 983a23d6ce0639bdd63b68b6230bb7999463290f Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 11:40:09 +0200 Subject: [PATCH 14/22] Expose preparation and replay commands with reproducible capacity benchmark --- phy/apps/__init__.py | 61 +++++ tools/benchmark_long_recording.py | 398 ++++++++++++++++++++++++++++++ 2 files changed, 459 insertions(+) create mode 100644 tools/benchmark_long_recording.py diff --git a/phy/apps/__init__.py b/phy/apps/__init__.py index db51602ea..c6767d88c 100644 --- a/phy/apps/__init__.py +++ b/phy/apps/__init__.py @@ -174,6 +174,57 @@ def cli_template_describe(ctx, params_path): template_describe(params_path) +# ------------------------------------------------------------------------------ +# Long-recording batch commands +# ------------------------------------------------------------------------------ + + +@phycli.command('prepare-large') +@click.argument('params-path', type=click.Path(exists=True, dir_okay=False, path_type=Path)) +@click.argument('output-dir', type=click.Path(path_type=Path)) +@click.option('--duration', 'duration_seconds', type=click.FloatRange(min=0, min_open=True)) +@click.option('--valid-intervals', type=click.Path(exists=True, dir_okay=False, path_type=Path)) +@click.option('--max-spikes', type=click.IntRange(min=1), default=2000000, show_default=True) +@click.option('--max-bytes', type=click.IntRange(min=1), default=536870912, show_default=True) +@click.option('--window-seconds', type=click.FloatRange(min=0, min_open=True), default=30.0) +@click.option('--stratum-seconds', type=click.FloatRange(min=0, min_open=True), default=3600.0) +@click.option('--seed', type=click.IntRange(min=0), default=0) +@click.option('--bin-seconds', type=click.FloatRange(min=0, min_open=True), default=3600.0) +@click.option('--batch-size', type=click.IntRange(min=1), default=100000) +def cli_prepare_large(params_path, output_dir, valid_intervals=None, **kwargs): + """Prepare bounded shared-window evidence and complete-sorting summaries. + + VALID_INTERVALS is an optional int64 .npy array of acquisition sample [start, end) pairs. + Duration/exposure must be authoritative; it is never inferred from spike silence. + """ + import numpy as np + + from .large_recording.prepare import prepare_large + + try: + intervals = np.load(valid_intervals, allow_pickle=False) if valid_intervals else None + output = prepare_large(params_path, output_dir, valid_intervals=intervals, **kwargs) + except (ValueError, OSError) as error: + raise click.ClickException(str(error)) from error + click.echo(f'Prepared bounded evidence: {output}') + + +@phycli.command('apply-curation') +@click.argument('source-params', type=click.Path(exists=True, dir_okay=False, path_type=Path)) +@click.argument('bounded-dir', type=click.Path(exists=True, file_okay=False, path_type=Path)) +@click.argument('output-dir', type=click.Path(path_type=Path)) +@click.option('--batch-size', type=click.IntRange(min=1), default=100000) +def cli_apply_curation(source_params, bounded_dir, output_dir, batch_size): + """Replay committed bounded curation into a new complete sorting.""" + from .large_recording.replay import apply_curation + + try: + output = apply_curation(source_params, bounded_dir, output_dir, batch_size=batch_size) + except (ValueError, OSError) as error: + raise click.ClickException(str(error)) from error + click.echo(f'Published complete curated sorting: {output}') + + # ------------------------------------------------------------------------------ # Kwik GUI # ------------------------------------------------------------------------------ @@ -224,6 +275,11 @@ def cli_alf_convert(ctx, subdirs, out_dir): from phylib.io.merge import Merger from phylib.io.model import load_model + if any((Path(path) / '_phy_curation_manifest.json').exists() for path in subdirs): + raise click.ClickException( + 'Apply bounded curation to the complete sorting before ALF conversion.' + ) + out_dir = Path(out_dir) if len(subdirs) >= 2: @@ -253,6 +309,11 @@ def template_extract_waveforms( """Extract spike waveforms.""" from phylib.io.model import load_model + if (Path(params_path).parent / '_phy_curation_manifest.json').exists(): + raise click.ClickException( + 'Extract waveforms on the original source and regenerate bounded evidence; bounded package assets are immutable.' + ) + model = load_model(params_path) model.save_spikes_subset_waveforms( max_n_spikes_per_template=n_spikes_per_cluster, max_n_channels=nc diff --git a/tools/benchmark_long_recording.py b/tools/benchmark_long_recording.py new file mode 100644 index 000000000..b6bfabeef --- /dev/null +++ b/tools/benchmark_long_recording.py @@ -0,0 +1,398 @@ +"""Reproducible, file-backed capacity benchmark for long-recording services. + +Run from a development environment, for example:: + + uv run python tools/benchmark_long_recording.py --spikes 1000000 + +The benchmark creates synthetic Phy arrays without raw traces, times preparation +and replay in separate child processes, and checks replay against an independent +streamed oracle. It is intentionally capped at two million source spikes. +""" + +import argparse +import json +import os +import platform +import subprocess +import sys +import tempfile +import threading +import time +from pathlib import Path + +import numpy as np + +REPOSITORY = Path(__file__).resolve().parents[1] +if str(REPOSITORY) not in sys.path: + sys.path.insert(0, str(REPOSITORY)) + + +def _file_bytes(path): + path = Path(path) + return sum(item.stat().st_size for item in path.rglob('*') if item.is_file()) + + +def _make_source(path, spikes, units, duration_hours, batch_size): + """Write canonical arrays in bounded chunks, without allocating full vectors.""" + path.mkdir(parents=True) + duration_seconds = duration_hours * 3600 + sample_rate = 30_000 + num_samples = round(duration_seconds * sample_rate) + if num_samples <= 0 or num_samples > np.iinfo(np.int64).max: + raise ValueError('duration-hours produces an invalid int64 sample axis.') + + arrays = { + 'spike_times.npy': np.lib.format.open_memmap( + path / 'spike_times.npy', mode='w+', dtype=np.int64, shape=(spikes,) + ), + 'spike_clusters.npy': np.lib.format.open_memmap( + path / 'spike_clusters.npy', mode='w+', dtype=np.int32, shape=(spikes,) + ), + 'spike_templates.npy': np.lib.format.open_memmap( + path / 'spike_templates.npy', mode='w+', dtype=np.int32, shape=(spikes,) + ), + } + for start in range(0, spikes, batch_size): + stop = min(start + batch_size, spikes) + rows = np.arange(start, stop, dtype=np.int64) + arrays['spike_times.npy'][start:stop] = rows * (num_samples - 1) // spikes + assignments = (rows % units).astype(np.int32) + arrays['spike_clusters.npy'][start:stop] = assignments + arrays['spike_templates.npy'][start:stop] = assignments + for array in arrays.values(): + array.flush() + array._mmap.close() + + templates = np.lib.format.open_memmap( + path / 'templates.npy', mode='w+', dtype=np.float32, shape=(units, 4, 2) + ) + templates[:] = 0 + templates.flush() + templates._mmap.close() + np.save(path / 'channel_map.npy', np.array([0, 1], dtype=np.int32)) + np.save(path / 'channel_positions.npy', np.array([[0.0, 0.0], [20.0, 0.0]], dtype=np.float32)) + (path / 'params.py').write_text( + f'sample_rate = {sample_rate}.0\n' + f'num_samples = {num_samples}\n' + 'n_channels_dat = 2\n' + "dtype = 'int16'\n" + 'dat_path = None\n', + encoding='utf-8', + ) + return duration_seconds + + +def _peak_rss_bytes(): + """Return process peak RSS, or an explicit unavailable result.""" + if os.name != 'nt': + try: + import resource + + value = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss + # Linux and the BSDs report KiB; macOS reports bytes. + return int(value if sys.platform == 'darwin' else value * 1024), 'resource.ru_maxrss' + except (ImportError, AttributeError, OSError): + pass + + try: + import psutil + except ImportError: + return None, 'unavailable (install psutil for sampled peak RSS on Windows)' + + process = psutil.Process() + peak = [process.memory_info().rss] + stopped = threading.Event() + + def sample(): + while not stopped.wait(0.02): + try: + peak[0] = max(peak[0], process.memory_info().rss) + except psutil.Error: + return + + sampler = threading.Thread(target=sample, daemon=True) + sampler.start() + return _SampledRSS(stopped, sampler, peak) + + +class _SampledRSS: + def __init__(self, stopped, sampler, peak): + self.stopped = stopped + self.sampler = sampler + self.peak = peak + + def finish(self): + self.stopped.set() + self.sampler.join() + return int(self.peak[0]), 'psutil sampled every 20 ms' + + +def _measure_rss_start(): + value = _peak_rss_bytes() + return value if isinstance(value, _SampledRSS) else value + + +def _rss_result(handle): + return handle.finish() if isinstance(handle, _SampledRSS) else handle + + +def _phase_prepare(args): + from phy.apps.large_recording.prepare import prepare_large + + rss = _measure_rss_start() + started = time.perf_counter() + bounded = prepare_large( + args.params, + args.bounded_path, + duration_seconds=args.duration_seconds, + max_spikes=args.max_spikes, + max_bytes=args.max_bytes, + window_seconds=args.window_seconds, + stratum_seconds=args.stratum_seconds, + seed=args.seed, + batch_size=args.batch_size, + bin_seconds=args.bin_seconds, + ) + elapsed = time.perf_counter() - started + peak, method = _rss_result(rss) + print( + json.dumps( + { + 'phase': 'prepare', + 'wall_seconds': elapsed, + 'peak_rss_bytes': peak, + 'peak_rss_method': method, + 'bounded_path': str(bounded), + } + ) + ) + + +def _phase_curate(args): + from phy.apps.large_recording.curation import BoundedSession + + session = BoundedSession(args.bounded_path) + try: + if 0 not in session.unit_ids or 1 not in session.unit_ids: + raise ValueError('Synthetic source must contain units 0 and 1.') + session.record_merge([0, 1], session.next_cluster_id) + session.save() + finally: + session.close() + print(json.dumps({'phase': 'curate', 'saved': True})) + + +def _phase_replay(args): + from phy.apps.large_recording.replay import apply_curation + + rss = _measure_rss_start() + started = time.perf_counter() + output = apply_curation( + args.params, args.bounded_path, args.curated_path, batch_size=args.batch_size + ) + elapsed = time.perf_counter() - started + peak, method = _rss_result(rss) + print( + json.dumps( + { + 'phase': 'replay', + 'wall_seconds': elapsed, + 'peak_rss_bytes': peak, + 'peak_rss_method': method, + 'curated_path': str(output), + } + ) + ) + + +def _oracle(source_path, curated_path, spikes, units, batch_size): + """Independent streamed oracle for the benchmark's one known merge.""" + source = np.load(source_path / 'spike_clusters.npy', mmap_mode='r', allow_pickle=False) + output = np.load(curated_path / 'spike_clusters.npy', mmap_mode='r', allow_pickle=False) + expected_target = units + checked = 0 + matches = source.shape == output.shape == (spikes,) + for start in range(0, spikes, batch_size): + stop = min(start + batch_size, spikes) + expected = np.array(source[start:stop], copy=True) + expected[(expected == 0) | (expected == 1)] = expected_target + matches &= np.array_equal(expected, output[start:stop]) + checked += stop - start + source._mmap.close() + output._mmap.close() + return {'matches': bool(matches), 'rows_checked': checked, 'merge_target': expected_target} + + +def _run_phase( + script, + phase, + params, + bounded, + curated, + duration_seconds, + max_spikes, + max_bytes, + window_seconds, + stratum_seconds, + seed, + batch_size, + bin_seconds, +): + command = [ + sys.executable, + str(script), + '--_phase', + phase, + '--params', + str(params), + '--bounded-path', + str(bounded), + '--curated-path', + str(curated), + '--duration-seconds', + str(duration_seconds), + '--max-spikes', + str(max_spikes), + '--max-bytes', + str(max_bytes), + '--window-seconds', + str(window_seconds), + '--stratum-seconds', + str(stratum_seconds), + '--seed', + str(seed), + '--batch-size', + str(batch_size), + '--bin-seconds', + str(bin_seconds), + ] + try: + completed = subprocess.run( + command, cwd=REPOSITORY, check=True, capture_output=True, text=True + ) + except subprocess.CalledProcessError as error: + raise RuntimeError(error.stderr.strip() or error.stdout.strip()) from error + return json.loads(completed.stdout.strip().splitlines()[-1]) + + +def _run(args): + if args.spikes <= 0 or args.spikes > 2_000_000: + raise ValueError('--spikes must be between 1 and 2,000,000.') + if args.units < 2 or args.units > args.spikes: + raise ValueError('--units must be at least 2 and no greater than --spikes.') + if args.batch_size <= 0 or args.duration_hours <= 0: + raise ValueError('--batch-size and --duration-hours must be positive.') + + temporary = None + if args.output_dir: + root = Path(args.output_dir).resolve() + root.mkdir(parents=True, exist_ok=True) + else: + temporary = tempfile.TemporaryDirectory(prefix='phy-long-recording-benchmark-') + root = Path(temporary.name) + source_dir, bounded_dir, curated_dir = ( + root / name for name in ('source', 'bounded', 'curated') + ) + duration_seconds = _make_source( + source_dir, args.spikes, args.units, args.duration_hours, args.batch_size + ) + source_bytes = _file_bytes(source_dir) + common = { + 'params': source_dir / 'params.py', + 'bounded': bounded_dir, + 'curated': curated_dir, + 'duration_seconds': duration_seconds, + 'max_spikes': args.max_spikes, + 'max_bytes': args.max_bytes, + 'window_seconds': args.window_seconds, + 'stratum_seconds': args.stratum_seconds, + 'seed': args.seed, + 'batch_size': args.batch_size, + 'bin_seconds': args.bin_seconds, + } + prepare = _run_phase(Path(__file__).resolve(), 'prepare', **common) + _run_phase(Path(__file__).resolve(), 'curate', **common) + replay = _run_phase(Path(__file__).resolve(), 'replay', **common) + oracle = _oracle(source_dir, curated_dir, args.spikes, args.units, args.batch_size) + if not oracle['matches']: + raise RuntimeError('Independent streamed replay oracle did not match curated assignments.') + + result = { + 'benchmark': 'phy_long_recording_v1', + 'machine': { + 'platform': platform.platform(), + 'machine': platform.machine(), + 'processor': platform.processor(), + 'python': platform.python_version(), + 'numpy': np.__version__, + 'cpu_count': os.cpu_count(), + }, + 'parameters': { + 'spikes': args.spikes, + 'units': args.units, + 'duration_hours': args.duration_hours, + 'sample_rate_hz': 30000, + 'batch_size': args.batch_size, + 'max_spikes': args.max_spikes, + 'max_bytes': args.max_bytes, + 'window_seconds': args.window_seconds, + 'stratum_seconds': args.stratum_seconds, + 'seed': args.seed, + 'bin_seconds': args.bin_seconds, + }, + 'source_file_bytes': source_bytes, + 'bounded_file_bytes': _file_bytes(bounded_dir), + 'curated_file_bytes': _file_bytes(curated_dir), + 'bounded_spikes': int( + json.loads((bounded_dir / '_phy_curation_manifest.json').read_text(encoding='utf-8'))[ + 'bounded_num_spikes' + ] + ), + 'preparation': prepare, + 'replay': replay, + 'independent_streamed_replay_oracle': oracle, + 'output_dir': str(root), + 'output_dir_retained': temporary is None, + } + print(json.dumps(result, indent=2, sort_keys=True)) + if temporary is not None: + temporary.cleanup() + + +def _parser(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--spikes', type=int, default=1_000_000) + parser.add_argument('--units', type=int, default=1000) + parser.add_argument('--duration-hours', type=float, default=1000) + parser.add_argument('--batch-size', type=int, default=100_000) + parser.add_argument('--max-spikes', type=int, default=100_000) + parser.add_argument('--max-bytes', type=int, default=536_870_912) + parser.add_argument('--window-seconds', type=float, default=30) + parser.add_argument('--stratum-seconds', type=float, default=3600) + parser.add_argument('--seed', type=int, default=0) + parser.add_argument('--bin-seconds', type=float, default=3600) + parser.add_argument('--output-dir', type=Path) + parser.add_argument( + '--_phase', choices=('prepare', 'curate', 'replay'), help=argparse.SUPPRESS + ) + parser.add_argument('--params', type=Path, help=argparse.SUPPRESS) + parser.add_argument('--bounded-path', type=Path, help=argparse.SUPPRESS) + parser.add_argument('--curated-path', type=Path, help=argparse.SUPPRESS) + parser.add_argument('--duration-seconds', type=float, help=argparse.SUPPRESS) + return parser + + +def main(): + args = _parser().parse_args() + if args._phase == 'prepare': + _phase_prepare(args) + elif args._phase == 'curate': + _phase_curate(args) + elif args._phase == 'replay': + _phase_replay(args) + else: + _run(args) + + +if __name__ == '__main__': + main() From f212f069e5b5b19469cfa73781dac08de093d9a1 Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 11:40:53 +0200 Subject: [PATCH 15/22] Protect bounded source clock and channel schema from plugin mutation --- phy/apps/large_recording/model.py | 14 +++++++++++++- phy/apps/large_recording/tests/test_adapter.py | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/phy/apps/large_recording/model.py b/phy/apps/large_recording/model.py index cc0bf62b3..9f0de0389 100644 --- a/phy/apps/large_recording/model.py +++ b/phy/apps/large_recording/model.py @@ -31,7 +31,19 @@ def freeze_source(self): {name: MappingProxyType(values) for name, values in self.metadata.items()} ) names.update( - ('metadata', 'save_spike_clusters', 'save_metadata', 'save_spikes_subset_waveforms') + ( + 'metadata', + 'save_spike_clusters', + 'save_metadata', + 'save_spikes_subset_waveforms', + 'sample_rate', + 'duration', + 'n_channels', + 'n_channels_dat', + 'n_samples_waveforms', + 'dtype', + 'offset', + ) ) self._protected_source_names = frozenset(names) diff --git a/phy/apps/large_recording/tests/test_adapter.py b/phy/apps/large_recording/tests/test_adapter.py index 937d45433..76d4dda47 100644 --- a/phy/apps/large_recording/tests/test_adapter.py +++ b/phy/apps/large_recording/tests/test_adapter.py @@ -57,6 +57,8 @@ def test_manifest_factory_reserves_complete_ids_and_guards_mutations(tmp_path): controller.model.spike_clusters[0] = 123 with pytest.raises(ValueError): controller.model.spike_clusters = np.array([123]) + with pytest.raises(ValueError): + controller.model.sample_rate = 1.0 with pytest.raises(TypeError): controller.model.metadata['group'][0] = 'noise' supervisor = controller.supervisor From 7526e483907fcf5da2f493b754302888d276fbc1 Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 11:42:58 +0200 Subject: [PATCH 16/22] Validate GUI channel geometry and nonidentity waveform mappings --- phy/apps/large_recording/source.py | 8 ++++++-- phy/apps/large_recording/tests/test_prepare.py | 4 +++- phy/apps/large_recording/tests/test_source.py | 10 ++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/phy/apps/large_recording/source.py b/phy/apps/large_recording/source.py index 9d86c7b31..07bacf21f 100644 --- a/phy/apps/large_recording/source.py +++ b/phy/apps/large_recording/source.py @@ -536,8 +536,12 @@ def validate(self): if np.any((sparse < -1) | (sparse >= len(channels))): raise ValueError(f'{index_name} contains invalid model channel IDs.') positions = self.arrays.get('channel_positions.npy') - if positions is not None and (positions.ndim != 2 or len(positions) != len(channels)): - raise ValueError('channel_positions.npy must align with model channels.') + if positions is not None and ( + positions.shape != (len(channels), 2) or not np.all(np.isfinite(positions)) + ): + raise ValueError( + 'channel_positions.npy must contain finite x/y model channel coordinates.' + ) for feature, indices in ( ('pc_features.npy', 'pc_feature_ind.npy'), ('template_features.npy', 'template_feature_ind.npy'), diff --git a/phy/apps/large_recording/tests/test_prepare.py b/phy/apps/large_recording/tests/test_prepare.py index 7dacb519b..a3688fd8c 100644 --- a/phy/apps/large_recording/tests/test_prepare.py +++ b/phy/apps/large_recording/tests/test_prepare.py @@ -11,8 +11,10 @@ from phy.apps.large_recording.tests.test_source import make_sorting -def test_prepare_exact_arrays_waveforms_and_source_unchanged(tmp_path): +@pytest.mark.parametrize('channel_map', [[0, 1, 2], [2, 0, 1]]) +def test_prepare_exact_arrays_waveforms_and_source_unchanged(tmp_path, channel_map): params = make_sorting(tmp_path / 'full', columns=True) + np.save(params.parent / 'channel_map.npy', np.asarray(channel_map, dtype=np.int32)) before = {p.name: hash_file(p) for p in params.parent.iterdir()} output = prepare_large( params, diff --git a/phy/apps/large_recording/tests/test_source.py b/phy/apps/large_recording/tests/test_source.py index b3c1c45ee..1dfe30e7f 100644 --- a/phy/apps/large_recording/tests/test_source.py +++ b/phy/apps/large_recording/tests/test_source.py @@ -264,6 +264,16 @@ def test_exporter_channel_sidecars_and_raw_map_validation(tmp_path): Source(params) +@pytest.mark.parametrize( + 'positions', [np.zeros((3, 1)), np.zeros((3, 3)), np.full((3, 2), np.nan)] +) +def test_channel_geometry_must_match_gui_contract(tmp_path, positions): + params = make_sorting(tmp_path / 'source') + np.save(params.parent / 'channel_positions.npy', positions) + with pytest.raises(ValueError, match='finite x/y'): + Source(params) + + def test_exclusive_publish_preserves_racing_empty_destination(tmp_path): from phy.apps.large_recording.source import publish_directory From 064e71cf0c5ec956de6ff4a05119b5e3d08a5844 Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 11:43:49 +0200 Subject: [PATCH 17/22] Document bounded workflow, validation evidence, and scientific acceptance limits --- design/large-recording-curation.md | 11 +- design/large-recording-integration-plan.md | 26 ++-- design/large-recording-validation.md | 77 ++++++++++ docs/api.md | 16 +++ docs/changelog.md | 15 ++ docs/cli.md | 29 ++++ docs/long-recordings.md | 160 +++++++++++++++++++++ mkdocs.yml | 1 + 8 files changed, 321 insertions(+), 14 deletions(-) create mode 100644 design/large-recording-validation.md create mode 100644 docs/long-recordings.md diff --git a/design/large-recording-curation.md b/design/large-recording-curation.md index 7e9b11388..87707863a 100644 --- a/design/large-recording-curation.md +++ b/design/large-recording-curation.md @@ -1,9 +1,12 @@ # Long-recording curation in Phy 2.x: Phy-side design contract -**Status:** proposed; implementation sequence and file contracts for review. This -specification is for Phy-side development; it does not authorize changes to the -AIND/Code Ocean export pipeline. Current Phy behavior remains unchanged until -the implementation is complete and validated. +**Status:** implementation present; acceptance validation is ongoing. This +specification is for Phy-side behavior; it does not authorize changes to the +AIND/Code Ocean export pipeline. The current branch implements the bounded +workflow behind an explicit manifest while retaining standard behavior for +ordinary datasets. See the [integration plan](large-recording-integration-plan.md) +and [validation record](large-recording-validation.md) for implementation scope, +checks, and remaining acceptance work. The [integration audit and plan](large-recording-integration-plan.md) refines this proposal with assignment revisions, transactional persistence, capability diff --git a/design/large-recording-integration-plan.md b/design/large-recording-integration-plan.md index ee6270afa..de9e7043d 100644 --- a/design/large-recording-integration-plan.md +++ b/design/large-recording-integration-plan.md @@ -265,13 +265,19 @@ supports one segment and distinguishes Phy channel indices from exported origina channel IDs. Do not assume that arbitrary multi-session inputs already satisfy this contract or that a deployed exporter matches this inspected revision. -## Validation of this design branch - -On 2026-10-13, the locked development environment with phylib 2.7.1 passed -all ten reference tests, including the loader and returned waveform values. -`make test-apps format-check` passed all 165 application tests, lint and -formatting checks. Patch whitespace validation also passed. The test process -reported pending ipykernel tasks during shutdown after successful completion. -This branch changes design documents and reference tests only; it does not -implement preparation, replay, transactional saves or a stability view, and -does not establish realistic long-recording capacity. +## Implementation and validation status + +The branch now includes batched source validation and preparation, full-source +summaries, bounded GUI curation and checkpoints, semantic replay, Unit Stability, +and dedicated long-recording tests. The feature is implemented, but its +acceptance remains incomplete: this test and synthetic benchmark evidence does +not replace real chronic-recording review by domain curators. + +On 2026-10-13, `make test-full` completed with 745 passed and 1 skipped. Three +additional bounded GUI lifecycle regressions pass in +`phy/apps/large_recording/tests/test_gui_lifecycle.py`. +[`design/large-recording-validation.md`](large-recording-validation.md) records +the synthetic capacity runs and their limits. The separate 32-spike, 1000-hour +fixture verifies sample-coordinate handling and file mapping; it is not a +billion-spike capacity test or evidence of chronic biological identity. Curator +acceptance on real chronic recordings remains outstanding. diff --git a/design/large-recording-validation.md b/design/large-recording-validation.md new file mode 100644 index 000000000..2dcd3e761 --- /dev/null +++ b/design/large-recording-validation.md @@ -0,0 +1,77 @@ +# Long-recording implementation validation + +This record summarizes the current implementation checks and their limits. The +results validate the measured code paths and fixtures described here. They do +not establish capacity for every source layout or scientific suitability for +chronic curation. + +## Automated checks + +On 2026-10-13, `make test-full` completed with **756 passed and 1 +skipped** (496 non-application tests and 260 application tests). Final channel +geometry and nonidentity waveform-mapping additions passed a further focused +source/preparation run of **33 tests**. Lint, format checking, package build, +and the strict documentation build also passed. The dedicated bounded GUI lifecycle file passed all three +regressions: reentrant observer rollback with the GUI attached, merge-proposal +review through undo/redo/save/reopen, and pending full metrics for threshold +children in the default bounded views. + +The reference long-recording fixture is deliberately sparse: 32 spikes spread +over a 1000-hour sample clock. It checks long `int64` coordinates, tied times, +source-row mapping, waveform remapping, and loader compatibility. It is not a +billion-spike capacity test, a realistic chronic recording, or evidence of +biological identity across a recording. + +## Synthetic preparation and replay runs + +The reproducible benchmark is `uv run python +tools/benchmark_long_recording.py`. It writes synthetic source arrays in +batches, with no raw voltage data, and runs preparation and replay in separate +processes. Both runs below used Python 3.13.3, NumPy 2.4.3, Linux +`x86_64`/glibc 2.39, 30 kHz sampling, 1000 units, a 1000-hour sample axis, +100,000-row batches, 30-second windows, 3600-second strata, a 100,000-spike +budget, a 512 MiB output budget, seed 0, and 3600-second summary bins. The +oracle independently streamed every source and output assignment row and +matched the expected merge in both cases. + +| Synthetic source spikes | Source files | Bounded package | Bounded spikes | Curated output | Prepare time / peak RSS | Replay time / peak RSS | Oracle rows | +| ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | +| 250,000 | 4,032,892 B | 8,625,460 B | 2,389 | 5,038,086 B | 1.902 s / 215,773,184 B | 0.114 s / 214,847,488 B | 250,000 | +| 2,000,000 | 32,032,892 B | 9,157,120 B | 16,676 | 40,038,086 B | 1.227 s / 214,433,792 B | 0.292 s / 215,285,760 B | 2,000,000 | + +Each measurement is a single run, not a throughput curve. Preparation and +replay durations exclude child-process startup; peak RSS is the process high +water mark. The source is a regular synthetic distribution with tiny templates +and no stored waveforms, raw data, irregular acquisition gaps, or real feature +loads. These figures therefore do not predict every preparation cost or GUI +interaction on a chronic dataset. The full JSON reports are retained at +`/tmp/phy-long-recording-benchmark-250k.json` and +`/tmp/phy-long-recording-benchmark-2m.json` on the validation workstation. + +## Ordinary-dataset smoke comparison + +A separate three-run comparison used fresh subprocesses, configs, and caches in +the same Python environment. It compared baseline `a30d5c65` with current +`f212f069e5b5b19469cfa73781dac08de093d9a1` on a 12,000-spike, two-cluster +dataset with 1,024 stored waveform rows of shape `[40, 4]` and dense template +features. Counts and output dimensions matched exactly. + +| Measure (median of 3) | Baseline | Current | +| --- | ---: | ---: | +| Controller startup | 0.03879 s | 0.02822 s | +| Waveform provider | 0.00353 s | 0.00293 s | +| Feature provider | 0.00372 s | 0.00302 s | + +This small case showed no regression; the apparent gains are within the range +where run-to-run noise matters. The comparison did not measure Qt rendering, +raw-voltage I/O, or large-dataset selection churn. Its report is retained at +`/tmp/phy-standard-recording-comparison.json` on the validation workstation. + +## Remaining acceptance work + +Real chronic-recording review by domain curators remains outstanding. It must +cover drift, rare and bursting units, artifacts, gaps, waveform coverage, +intentionally incorrect merges, withheld contiguous windows, and full-data +diagnostics where available. Software integrity checks and synthetic throughput +do not establish that the evidence is scientifically sufficient or that a +cluster represents one biological unit throughout 1000 hours. diff --git a/docs/api.md b/docs/api.md index a5f0f2506..52733d154 100644 --- a/docs/api.md +++ b/docs/api.md @@ -10117,6 +10117,13 @@ Component that brings manual clustering facilities to a GUI: Whether automatic navigation and similar-cluster selection skip noise and MUA clusters. The default is True. +* `clustering_factory : callable, optional` + Construct the clustering model. Defaults to Clustering; bounded curation + supplies a guarded implementation with the same constructor interface. + +* `cluster_meta_factory : callable, optional` + Construct metadata from groups and labels. Defaults to create_cluster_meta. + **Events** When this component is attached to a GUI, the following events are emitted: @@ -13197,6 +13204,15 @@ Create a trace view. --- +#### TemplateController.create_unit_stability_view + + +**`TemplateController.create_unit_stability_view(self)`** + +Optionally inspect selected-unit activity over the loaded recording. + +--- + #### TemplateController.create_waveform_view diff --git a/docs/changelog.md b/docs/changelog.md index 2842a69f3..1fadb9629 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -11,10 +11,25 @@ been included in a stable release. The current entries cover all user-visible changes committed since 23 July 2026; test-only commits are represented by the behavior they verify rather than listed separately. +### Long recordings + +- Added `prepare-large` and `apply-curation` for bounded shared-window evidence, + full-duration exposure-aware summaries, semantic merges/labels/source-amplitude + splits, and replay into a new complete sorting. +- Added Unit Stability, precise window-relative amplitude/feature inspection, + sampled interval/correlogram views, and explicit full-versus-evidence counts. + Standard datasets retain their existing curation workflow and default layout. +- Bounded saves use validated atomic generations and reject conflicting saves + from stale sessions. Unsupported selected-row splits are blocked. +- Sparse cluster IDs no longer require dense allocations during clustering. + ### Documentation - Documented uv-first installation of exact previous phy releases in separate environments, including how to intentionally replace a tool installation. +- Added a long-recording workflow guide covering bounded evidence preparation, + supported curation, full-sorting replay, and limits on interpreting sampled + measurements. ### Added diff --git a/docs/cli.md b/docs/cli.md index 0bb61a764..16b554a1f 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -25,6 +25,35 @@ GUI commands accept: --clear-cache remove and rebuild the dataset .phy cache ``` +## Long recordings + +Prepare bounded evidence, curate it with `template-gui`, then replay supported +actions into a new full sorting. See the [long-recording guide](long-recordings.md) +for input requirements, interpretation limits, and the complete workflow. + +```bash +phy prepare-large /data/recording/params.py /data/recording-bounded \ + --duration 3600000 \ + --valid-intervals /data/recording/valid-intervals.npy \ + --max-spikes 2000000 \ + --max-bytes 536870912 \ + --window-seconds 30 \ + --stratum-seconds 3600 \ + --seed 0 \ + --bin-seconds 3600 \ + --batch-size 100000 + +phy template-gui /data/recording-bounded/params.py + +phy apply-curation /data/recording/params.py /data/recording-bounded \ + /data/recording-curated --batch-size 100000 +``` + +`--duration` is acquisition duration in seconds. `--valid-intervals` reads an +integer `.npy` array of `[start, end)` sample pairs. `--max-bytes` caps the +prepared package size, not process memory. The output directories must be new; +the original sorting remains the replay parent. + ## Raw trace viewer ```bash diff --git a/docs/long-recordings.md b/docs/long-recordings.md new file mode 100644 index 000000000..abff49b5e --- /dev/null +++ b/docs/long-recordings.md @@ -0,0 +1,160 @@ +# Curating long recordings + +Phy's long-recording workflow prepares a bounded evidence dataset for interactive +review, then replays supported curation actions against the complete local +sorting. Preparation reads source arrays in batches; it does not load the full +sorting into the GUI. The source dataset is retained unchanged, and replay +writes a separate output dataset. + +This workflow is intended for a Phy sorting with one fixed-rate, monotonic sample +clock. Multi-segment recordings are not supported. Supply acquisition duration +and valid acquisition intervals when they are not already recorded in the +dataset metadata. Duration describes exposure; Phy cannot infer acquisition +gaps from periods with no spikes. Intervals use half-open sample coordinates +`[start, end)`. + +## Prepare bounded evidence + +Run `prepare-large` with the source `params.py` and a new output directory: + +```bash +phy prepare-large /data/recording/params.py /data/recording-bounded \ + --duration 3600000 \ + --valid-intervals /data/recording/valid-intervals.npy \ + --max-spikes 2000000 \ + --max-bytes 536870912 \ + --window-seconds 30 \ + --stratum-seconds 3600 \ + --seed 0 \ + --bin-seconds 3600 \ + --batch-size 100000 +``` + +`--duration` is in seconds and must agree with declared acquisition metadata. +The `.npy` valid-interval file contains an integer array of shape `[W, 2]` with +ordered, nonoverlapping sample pairs. +Without it, the full declared duration is treated as valid exposure. Do not use +that default when the recording contains acquisition gaps. + +`--max-bytes` limits the bounded output package size, including its summaries and +window plan. It is not a process-memory or peak-RSS limit. The source unit IDs +must fit nonnegative `int32`; sample coordinates and full-source spike row IDs +use `int64`. + +Preparation chooses shared time windows under the spike and byte budgets. The +window length, strata, and seed make the plan reproducible; inspect the saved +window plan in the output package when documenting or repeating an analysis. +Windows that exceed the budget are omitted, so a high-density interval can +reduce retained evidence. Preparation does not shorten an over-budget window or +silently thin spikes inside it. A survey of shared windows is supplemented by +deterministic rescue evidence for units missed by the survey. This improves the +chance of seeing rare units, but makes the evidence selection unequal: rescue +windows must not be treated as a probability sample. + +Preparation records exact full-recording spike counts and rates using valid +acquisition exposure. If source scalar amplitudes or depths are available, it +also records per-bin finite-value means and availability counts. It does not +invent missing measurements or convert source values to physical units. Stored +waveforms are included only where available in the source; raw traces are not +required when stored waveform data are sufficient for the views being used. +Producer-supplied per-unit metrics and annotations remain inherited metadata; +Phy does not recalculate those values for merged or split units. Use the +full-count, rate, amplitude-mean, and depth-mean summaries produced by this +workflow for the measurements they explicitly cover. + +## Review and curate + +Open the bounded output with the normal GUI command: + +```bash +phy template-gui /data/recording-bounded/params.py +``` + +The bounded manifest explicitly selects this mode. Bounded mode has its own +configuration namespace and default view layout; it does not replace the normal +Phy layout or restore ordinary saved dock geometry. The GUI keeps full-recording +counts and rates distinct from counts in selected evidence rows. Unit Stability +shows time-binned counts/rates, available source scalar-amplitude means, +evidence windows, and acquisition gaps. Missing measurements and units without +evidence remain visible as unavailable. + +Evidence Amplitude shows raw source scalar amplitudes from the currently +selected evidence window. The Feature view also uses window-relative seconds; +both views label the current window and reset their time origin when it changes. +To inspect another retained window, choose **View > Inspect evidence window** +and enter its zero-based index. Unit Stability keeps the full-recording time +context visible while you inspect individual windows. + +The Sampled ISI view excludes intervals crossing retained-window boundaries. +The Sampled Correlogram view shows raw pair counts from retained windows; it +does not apply a full-recording rate baseline. Both views are explicitly labeled +as sampled evidence. Its central bin counts unordered within-unit pairs and +combines both temporal orientations for cross-unit pairs whose absolute delay +is less than one bin, so tied sample times do not depend on source row order. +For exact pair counts, each unit may have at most 46,340 spikes in an evidence +window; the view reports an error for a larger per-unit window. Prepare shorter +windows if this limit is reached. + +Bounded curation supports whole-unit merges, cluster labels, and a source +amplitude threshold action. Use the GUI action **Split by source amplitude** +with one unit selected and a threshold in the source amplitude units. The action +uses the source `amplitudes.npy` scalar for every spike during replay; nonfinite +values stay with the remainder. Child units show full-data metrics as pending +until the replayed sorting is re-prepared, because their complete counts and +trends have not yet been calculated. Merge and label actions are journaled with +the bounded assignments and metadata in an atomic checkpoint generation. +Reopening loads the last complete generation. A reopened session starts a new +undo baseline. Each save checks that the checkpoint has not changed since this +session opened. If another session has saved first, the stale save fails; reopen +the bounded dataset before continuing to avoid overwriting that generation. + +Lasso, feature, and waveform splits remain unavailable in bounded mode because +the selected rows do not define how unseen source spikes should be assigned. +Standard, unbounded datasets retain their existing curation behavior. + +## Unit Stability on ordinary recordings + +Unit Stability can also be opened as an optional view for an ordinary dataset. +It evaluates only the selected unit and bins its loaded spikes over the recording +duration. Since ordinary datasets do not supply valid acquisition intervals to +this view, its rate assumes continuous acquisition; the plot labels that +assumption. The ordinary default view layout remains unchanged. Use the bounded +manifest workflow above when known acquisition gaps must be represented +explicitly. + +## Apply to the complete sorting + +After saving the bounded session, replay its journal against the exact source +assignment revision used during preparation: + +```bash +phy apply-curation /data/recording/params.py /data/recording-bounded \ + /data/recording-curated --batch-size 100000 +``` + +Replay checks the source identity and parent assignment revision, streams the +complete assignment array in batches, and writes a new full sorting. It rejects +a journal prepared from a different source revision. Keep the original source +and bounded package; they establish the lineage of the curated output. To review +the curated full sorting with bounded evidence again, run `prepare-large` on +the curated output to produce a fresh package and revision-specific summaries. +This replay and re-preparation step also resolves full-data counts and trends +for threshold-split children. + +## Interpreting evidence + +Full counts and exposure-based rates describe the complete sorting. Window plots, +waveforms, feature scatterplots, and other bounded measurements describe only +the retained evidence. Survey and rescue selection can overrepresent some +periods or units, and waveform availability can vary across units and time. +These views do not establish full-recording quality, contamination, refractory +violations, or continuous biological identity. Use them to guide review, not as +scientific claims about unseen spikes. Long-duration coordinates preserve the +source sample clock; silence alone is never evidence that the acquisition was +inactive. + +For reproducible synthetic capacity measurements, run +`uv run python tools/benchmark_long_recording.py`. The benchmark reports +preparation and replay time and peak memory in separate processes and checks +replay against a streamed oracle. It is capped at two million synthetic spikes; +its results are not a substitute for measurements on real chronic datasets. diff --git a/mkdocs.yml b/mkdocs.yml index bf8a4ad12..f59e59417 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -17,6 +17,7 @@ nav: - How-to and customization: - Configuration and state: configuration.md - Performance and spike sampling: performance.md + - Curating long recordings: long-recordings.md - Change keyboard shortcuts: keyboard_customization.md - Plugin introduction: customization.md - Plugin examples: plugins.md From da93252287770e02026e051a74e232dd2a9f0237 Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 13:05:11 +0200 Subject: [PATCH 18/22] Fix Windows durable file flushing and close revision-test readers --- design/README.md | 2 +- design/large-recording-curation.md | 2 +- phy/apps/large_recording/curation.py | 3 ++- phy/apps/large_recording/prepare.py | 3 ++- phy/apps/large_recording/replay.py | 3 ++- phy/apps/large_recording/tests/test_source.py | 3 +++ 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/design/README.md b/design/README.md index 27af3605f..e52897a7a 100644 --- a/design/README.md +++ b/design/README.md @@ -61,7 +61,7 @@ The implementation and user documentation are complete on the unreleased phy ## Long-recording curation (proposed) The [long-recording curation Phy-side design contract](large-recording-curation.md) -describes bounded local datasets for ~1000-hour sortings, the three spike-index +describes bounded local datasets for ~1000-hour sorting datasets, the three spike-index spaces, optional upstream waveform evidence, full-duration metrics, replay safety, and the implementation stages. The accompanying synthetic 1000-hour fixture and reference tests are in `phy/apps/tests/large_recording_fixtures.py` diff --git a/design/large-recording-curation.md b/design/large-recording-curation.md index 87707863a..26f6d482e 100644 --- a/design/large-recording-curation.md +++ b/design/large-recording-curation.md @@ -15,7 +15,7 @@ over the original implementation sequence in Section 9. ## 1. Objective and boundaries -Curate chronic Neuropixels sortings of roughly 1000 hours without opening hundreds +Curate chronic Neuropixels sorting datasets of roughly 1000 hours without opening hundreds of millions or billions of spikes in the existing in-memory Phy clustering model. The workstation downloads the **complete sorter output once**; downloading the complete raw voltage recording is **not required**. All preparation, interactive diff --git a/phy/apps/large_recording/curation.py b/phy/apps/large_recording/curation.py index 52babbad6..6a45d7f70 100644 --- a/phy/apps/large_recording/curation.py +++ b/phy/apps/large_recording/curation.py @@ -757,7 +757,8 @@ def _save_generation(self, generations, values, metadata, events, next_id, docum pointer_tmp = root / f'.current-{identifier}.tmp' try: np.save(stage / 'spike_clusters.npy', values) - with (stage / 'spike_clusters.npy').open('rb') as stream: + # Windows _commit (os.fsync) requires a writable descriptor. + with (stage / 'spike_clusters.npy').open('r+b') as stream: os.fsync(stream.fileno()) _write_json(stage / 'journal.json', events) _write_json(stage / 'metadata.json', metadata) diff --git a/phy/apps/large_recording/prepare.py b/phy/apps/large_recording/prepare.py index 308fca6b2..4f4b5e3dc 100644 --- a/phy/apps/large_recording/prepare.py +++ b/phy/apps/large_recording/prepare.py @@ -464,7 +464,8 @@ def accept(start, end, kind, segment, stratum_id): close_array(array) for path in temporary.iterdir(): if path.is_file(): - with path.open('rb') as stream: + # Windows _commit (os.fsync) requires a writable descriptor. + with path.open('r+b') as stream: os.fsync(stream.fileno()) _fsync_directory(temporary) if output_dir.exists(): diff --git a/phy/apps/large_recording/replay.py b/phy/apps/large_recording/replay.py index 965fde0f7..96c39ba8c 100644 --- a/phy/apps/large_recording/replay.py +++ b/phy/apps/large_recording/replay.py @@ -211,7 +211,8 @@ def _apply_curation(source, session, output_dir, batch_size): curated.close() for path in stage.iterdir(): if path.is_file(): - with path.open('rb') as stream: + # Windows _commit (os.fsync) requires a writable descriptor. + with path.open('r+b') as stream: os.fsync(stream.fileno()) _fsync_directory(stage) # Refuse replacement even when a racing caller creates the target. diff --git a/phy/apps/large_recording/tests/test_source.py b/phy/apps/large_recording/tests/test_source.py index 1dfe30e7f..05578bf9d 100644 --- a/phy/apps/large_recording/tests/test_source.py +++ b/phy/apps/large_recording/tests/test_source.py @@ -104,16 +104,19 @@ def read(*args, **kwargs): def test_identity_assignment_and_feature_layers(tmp_path): params = make_sorting(tmp_path / 'full') source = Source(params) + source.close() clusters = np.load(params.parent / 'spike_clusters.npy') clusters[clusters == 1] = 0 np.save(params.parent / 'spike_clusters.npy', clusters) merged = Source(params) + merged.close() assert merged.identity == source.identity assert merged.revision != source.revision values = np.load(params.parent / 'amplitudes.npy') values[0] = 99 np.save(params.parent / 'amplitudes.npy', values) altered = Source(params) + altered.close() assert altered.identity != merged.identity assert altered.revision == merged.revision assert ( From 8d2e13de4deea7fd418a456c1827fc09edbd5a4e Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 13:10:09 +0200 Subject: [PATCH 19/22] Add reproducible screenshots of bounded evidence views --- docs/images/long-recording-evidence.png | Bin 0 -> 211062 bytes docs/images/long-recording-overview.png | Bin 0 -> 123786 bytes docs/long-recordings.md | 21 ++ tools/capture_long_recording_views.py | 254 ++++++++++++++++++++++++ 4 files changed, 275 insertions(+) create mode 100644 docs/images/long-recording-evidence.png create mode 100644 docs/images/long-recording-overview.png create mode 100644 tools/capture_long_recording_views.py diff --git a/docs/images/long-recording-evidence.png b/docs/images/long-recording-evidence.png new file mode 100644 index 0000000000000000000000000000000000000000..f7649941ce5c4ed8c950553bf6f723dda51d0abc GIT binary patch literal 211062 zcma&OcRZE<{|Brk4N+DRA}h1(t&}+SI`$|l*?WshB%zL#EfS8sR|v_<9w&QelfAiL zNAeLWtZJ{`_=UGMQ4&)4(yeCMwyFNuGi{5%d04n9Kafieyb9yboo=^VV1 z@RR4o)O7H_b2d_%_Bc2MkFo!qNEJ(Yii2|l2l3#Zs!Pnmkh2GIPyg2yuKe=8^>@-Y z=x)$(ODLX@AiQ_^vTBy{>07jJXHHxu-q^Jx$-R;Alc^LBPe8$ntYXSaSz=ZkQP-90jc2GI+V8(7 zc|Z8n-{;!+r!(_^G|9e3dTn3-^1(2IxWid=W7Q|F8YL+?F6)t^|G+eERRJtdM?zu7X@39U+$Zmi`#11rMaKBv)zmy``Z1M zr&fC-&a2=7UXAT&4^`$vkC2t?3$K>4A62<8xa%*F^X)L2i#S~RJ1W!e z^`+}wmYbW_jD@IIgyJYiLCq_kOO|XtgjBK3Wa2JErQ6$4W6#G86pU-AvnY3ei7Z*N z`w-UTxz{ZqGes#nc~YaQuRIao_qi1^`BwSC<&-_h4qS>%65;@uqXp1+bOe?%6`iVU4-a9B@DS*rYK zX%W3SwCrVjUpdfD1aUMFLMYz2?Rc0PJy2*tf|+V%6cbv**q!9DUVJ@sPo^z;>x+O# zXH=KhmpeJlg?w){9kT>Gt~}}AQLV~y-Uz_|y?V*4w-S>OZRlX7`+DPtujYMg3o?p< zrQPzl-I))YqN%U^4iCC3h9(kelMJ${OZOXEqX=Zrmm2ykC z_H(r+Rp9BCX9>rh$89Jpp%gLF_|fM(raTh?*MhTp<@Ps!M*8S3k2tMIQ*IvZl;-Ze z*=DvzP!CU!?cH?t*o#m6RbgE* z*S=X%SCeNxQAAq%c>{B>+NIfJMGAbU&BK@#_ho5frN8z_aO6>i6ubRvR7ALy z;MPQgdGFJXODPg$_V(|Uhr+Juof;>?1mW#k=cn}v1esJs9re7qe)-y1Bbrd0Y}j!j zojTa_j%S-6SIR}|sFj}2Pi{6<5mp7H@OO1_+VP1EyXJ4U3S_=HvI)5<#??&KmtQ)K zJMB5~yZSImbf+{SeImc*o|iUeNMkjn^=-k$`LSYLCmmKFLUBipb=@~_CQG#4&tx35 zRVOA;7x@k!uITb5f7u=X6{6B_DMXBU@=OE2DT2bSbzk(*nkogsmU*|jO5%En2nlD_-!+?sbI0a zb4`KWlF;t1O^)bIp8Jo^?g%^@vn|C+^{%A}{n(O^^V8*B@szqtulN=8 zJ(4d3<5}}EKU@A1r$_%xFO(!vrs~}$hF|2)?fVfQw_XwK*wx}rVH)BSU#CXbM}AHC!i%{_2`!oEFLULZzmSR^IxJO6nDw`<+Gf5bLrOh@4~RX zyan;p@C=^=|5Bb0AJj=wCOG6JNNTb%x)q#ay4yQX1DG?&idc1>OJtRAWxrF5pA-xJ zl_ri%?@5}SX%kyONHrGnTby}Pl(j!D^{p_rW(v*zt=)0E-5Y;xWGK!|>6KZVP{p!_ zFYUh7j&{`x$2Bqj5A%fbT{{y`R(l{WCN1+DN&VP7V}0b*^Nxm6y6)Yl*C%f7#k}^~ z$)DJfry;iQe}5mrfW%u~@+^7jBs|A|K03u9f1$+ARP{pZp^8ZZRhcNDfyp-IMi|3-4;j<5eEbL_x&GHBF8lE}0 zJh&EO@OTkM! zm`1biQMK4ep(7qgo8U`qv`N`i+clNu(;n+JEyGCt*UlI(k9D=J`&@gDul=q1mck{6 z_t;b}D{qhTiN%nv)|F6bJuE8uWo>^HlHBd`h-|ihP>hb3r?91c&!Cyr{arMHeu+uq zDb&Lo!>qMZbX~D?U$1CQmz^(EQd*|J zRz^^^D;7L5ScEKp9*~hV>^1$|gi5aA%-@wLd5b75EyWkX<>oXS?tdRET4p)zTdzg< z{@+T4R!`oUdnl)@`Oj*y@Q~fKc$Y4*7p4TMX@xGPF72-Jw^hnaRgx51bg3AoPCx#4 zFFAdu;J@3v-6XXBgG-9pc>isMw_CD;oSfy%oquwlp(qrd)AVpVa zrz$cqD5!EitDMSny~8}K^s@;*B%&UZd<2TydicwUQ@Ex=NMuW6BX)fLM2wuAoWv66 z@bLo!11mQB&7=9O*%8WY+2VK~nVNRirU@toL*a^!o?l!X$}?`3j}?RwhJ6`3I#~AN z(8#%q*O8@Lt{}SeY4dW}YT^?b)+ue1kT%Aqt{>+4@!FeoPr^^AY;bN?lgQVUfcZYcQB% znFw~36nV_XZ^gTCv1Y=uYw(Rcimg&i$h_7Gw zSQ-@2%(8F{>M?`0f5I!aJX%t|5rTNHJjj&(L^jk)FXIv_yEX7sM(o-z`7;d$uA z%g6`W80Wd}TY`dRWfiKeV>TJOnrd@QAN?0S>-eWd7!sN$?u|xYQ zcp@y{P{Gp>G@2xAIh+oWjR_{_ncKkV6P!PfUdmBXR{pFIe>mhkf*gJ&pF$z(vAw^u zc3)f^J@88C`lb2{9A9#b8d2=JWgh!0^-4-gjvdWlbPwNNwcT9k>&t(l5Xo70lVICi z`V8aAlP80y#q0aju3i)HwXt*M7A`3pr;cGHJc+?W4gbk)>)*V@F6 z8X4pHuLr#;dqN%%~(9i;#G4U<33>SBI zvE7*@N+G8VD@l^vfyL~~-MInlsznDumYq`;{ROjt^Q^zDJXF~Dx6mJ5GJg3aGEwkZ zeVGUnDroQ_9IttGVGEWCT&Uojnyqb6VPa#w-2v>vDcp7RQ#JpE}DxPmk=gu(PvkPX zh#hVlmJekuuB@)U2?|<*X$=%vo;rE5U_ev|B_;T}0Oy@M9WA!lQXj4oqcHgw z1>jS0BJP5*@|X+GTDg4|7s%LSz=k$|xZl0&-C_EpsVPq@6W%6kU|^7~S7CO$WO8!y z^38{I^z>opWg7AZQxvGnhbj&0gHShBksHBchgXH17JTt3_74t*W@*{jEWf?JoFX5~ z+yi!BzF0JH{=x<4=~a4^_C~NagVk-Q zPS9Vw=-ZpAO)cW4s^g(EWXdfc#od^{6APxV_Uy>z_U^b1zuvQ*DTp`<<|^g)N!hfz z6D2MnP*<*8VUUX|c+y6NLhy#r#AaL z&*%4f?5@uSi|(2p>~5Sna|VrG8maPv;g5J7RYa#-w#JKzK{5zoR4~(h@ZiB)DiOEs z-(%pc50g4(9ezzt?(eU)VQmUR8nJ|}U@SI3u`QFbc`zZAEi4v#)b({6-@i#*7%b%y z5*jcoe6~I2C;ocwvnk7b!~2`dU)JOsb9`8vFJHb4xvQnEO#y*`9my&&adX>^5wI8C z9z8{nwf#4tD;}*UGrV@+T)5?_M`qW#C=7071MH zGN~o+0E%9w^5}36C0E*&0am`+$k-MmpfdLefueGqe2>xh(p3tTgug~xSKjJb1*EO$C$w*z9eu-BnSbPKQT_&4x!v?|$I0xB5cFQMfxDpN6) zLh5G41Nv^W$#nr_<|;dRtieQS@r*NSTo2OgcqmA?{8r`g(MD zUmD5;ANPJ~pz0QyM8b7Gvv~N~o+TSg1RbJytJ3V zsm5|Ax+R1`&Q5~CZDX#`v?Gz%vOiRq;l_>8F+XZ52+#07eb*_Hkj6;|!C-2!C3L%D zzD$>n^N=GLOQy%WtY`og*;<8j9g@_U!f{H*RfmU%a#7qJYKc-PBW`lIIqWQz%MEVs zZX-@GWy|kxuRUptb1ck(Oae~Ut<=f&#}9EflGfKNYRB3QE@qL13Bis+NCOl^zBmeo zi49ONv));Uc(22qo58}g&3S0_lh&BDrH0D=)#mtTyJ-ti{^y7oenj)N4Gav_*QbC_ z8!M<18`r%dfv2VA1z1-d6scO&_H?xHjab~i3a$wzeE{*Vs{3L&8g1U2(FY08kps=@ zSGzK3-&RUX1V{=JM*u0C9rDp;$-8&&z_VQ-;`e8i^_Y3C)RE~$hVRmu|NnrYKQ_P zXTDmMjQIvq@Hs6FYRWKfK!AS+;UCF+2-{%QmnSiw=yh}m(bhPv!N>e!Wo0F7+V1Xr zHl)r1b~6tN`ck39?ui}kuR$(j5fl*> ztz4yAblL;=lm2XBr-a;qK+tpk!rt!g_xgH*>-;(0+y#)!;0dKE$0j?mkc2eo7spFGnB7&~o5!c@NIOVKWV)HRt^9!>wTHc#f7VYEY?G%lmS4~&( ztId5>eKNX*!RMWEseaWnYLDOd^z?=yXG;gRyj(VW{CF(qajjLwM(=Qi`_|IXUI0fW zle?^xR0CvO@%#7b5z53<0N=WBHQ&E@@q%6^-1L56K!A3h5u!Ai9D=I@Y!76T)n%`v zJxOX$VhW1+v;g!8Br;RYTwGk7ZNT5(UlZ17u+&~XL*ovZ3~I}p4w1Z?^7M>}S>Me+ zHt+3=bSqP9{-wGqQA#Yavyk8Bdx_F*brM12Q(U|y!%?vgS^NmQ&wiIg+}2Ia%;vUN zCg4huiv}y>%%shAS^`*jGU76U&&HVxPIkxeyOFUmlKA;H zq-sF?%(LV048Kd1Xr|2e*{&2ne2ULu`#o{Luu(qEbq#_{CU4u@fyGUDaCxt+6p9$s zKeK(z9HT-*KOIofBg*E`>EUeJ;W05DkZcB>1}v-gR|DpAe*BPKEWU+66&E{ia4c1+ zBIOW>zACRHY%W?HCwY!r1o4_vdvX(gtWr^bQ6MM7wQ87wI1xXf0L6l zZ!inCu^b`{IJpxfE*ABy!E$G7U1IrcQs;0DWFrRS3^kGSh^KSfRb^@ErXP`9GI~ky zUdUmK?tj_zc5i7+jEx9Nr!l_~U<8;Q#HfOSMHJmDUtf0ZqJ>^ z%TsQ0B=TT9fCG}V5ohEBSAWxjno|M-0)PeBoqg2-08nLmIF|659-QSq>wx#I;c)m7hAvar1_rKE>!Iwd(JB|j~AkHE&m zLW2*dBJ>NQKZ38W z9;gcm##;T%d8}n5j;Exms;Z&E51AwHiLtRUJe7=;)GR+4kX{);dFHvA4aF)t1mKv1 zy^$lTt5-EPa|#N$(|gRg$qx<=A~^I#-PUIyv6V3#r0ZN$WDlt0gj_|!qE^zcL~K0O z6qc@@owYg$h2vCnggR$^W?#Y6t}X>JUCys6m&=Ei+|nVWnrB!1nwsKy+WCpu+*ADl z>Qf}wlO@PDsi`yd)L#2gHJrV8RWbiFGZrMeFBTGr?PI4?1fZ(;4ii%YptkAhfPg}J zKspsxLuG*dX5ja|v_ub+Y_WCI;!5dsTyslH=1dB>R{D%2Ob8eN5s&R0!trnZL}3me zDU%N5!rWQR#3)5QT#ZWq| zQ-V<;!%6@0oHqU}lrbeczoKO-m}FRJ*$~PQLjkkWHn093t94%NM=sg#zDcwgC|VqL zU)C)&>zV6G$6^eK(5dJ$>yb)n->E2?FuF7_@#V_BEYe6q@$J1mvGw-*Q*p^?GiBvY z#(0lJOMt1Wof2wl;qx2!!6hNtBkgh+Zr`>6&%xTNon0R9W3BwoCfHg{i298u3FK3_ zczAkZ?Ts}dXE=vd`?o~%nG3u?^W0W{mIBl5e?VO3v?yrtGbfBiy?=2N{AJLtnT;xA zdC`V{80-+r5ImaJSRpbhDl2YsHqrn>13;EwOu+m@fNyDSRYN*LpaaAPG)Pvl!TL-G zggJLdp@V6$BhCDd-RR{~6c>^5wa;HUdsOQ|=+|s^T0Rw^s*HGlo7dZa|T?q~?=lp6vW`^5TFhx{9`T#I_ zcVj*Tg@QkeVG*S{@ty`;#l3XB#CGC4Oz8`34nVvmf{rnp68+Rt6B6{0^@vq5CJ(QO z5X+%-mz{33Ozb4SPfw9ym7hiAD5%Sp&MAdj|H0M9ZP~AiXAAHNR;c%Lp)zEIO~`KM zRj(l215v~Szemv_k$g~`03f9RRFqp!)pZF-6{zm4F~6yk5M-bp+$Lj8Bjamr=Ce1x9H zzIgc(@Z-+!S^_VCA`rG3T3Q?#Cp-WfOg4rn#PF{`KK}mwJ4A~@RDOZ0<>EI$GxlKb z&Eafo8yh6z#H6GUGs<#uauzh9z{N&nOJ84KwN42QjSur1Xk_|=lY6PcmY<(r@HMW7 z+Qsi_ApMfxeWAPAnEJZ9*^OkfyigKCLYro` zV$~hr5%=YaSV2ke_; zogXI`7nIAs1k{y)g)IB(^V>uR0PTQh>s?TnLWPEfk&u#-Qc?~<90%JpHI^~6f7)YE zsHH1ITT@fR{8WIB?!mku8(ZemNt_-t&G4xYA3i|I{!l3t%r)%GTKYi7-T?yxL->zy z281$zCqQ}-X&&9a%Ea>*QF346LChC8&iATiY5}Ea-plGtO9ZK}#bgbbpZZ{Guf4@$ z>;8f?)JvJqt?I;6kQ-gc{TTsbO-@V@5fTzoQ0&bl1&33_6OyIeGu8|W40KGnfJEl! z=VO;8uO6Pc0F_ubEfEmN*z5`wo3v>A&}X^mrmWJFfLkG`tEF!Q@(s5)>8GRnf&Ihs zeoe^B$)tj+pMZYTF0x2lRX5DBRRy$)M|(#jjrU1slPx z*#Z+2lPM4(_wL=xntZguz``;Q8Alusfnw&s>-c!z4~VMsG>1??kB=J=Fw~&0AyC+$ zV(<+wGtLz}S3Oh95yC>*B?8l(Ug^Uyk%RTF<8-@>_-oz~K~bL^v2d%vzb5Zo5OX6L z-60>FEZ}sOYrU`tGZPaktKZs0_bh;@0iP3pjV)6kr8tT_)#JS!NQe0N@gqQP^rrww z1y5z}Fq?gXq)fqUF@r5&XoZB_yHk~*l4B8g(*Fq&0?DTc#m-EF=oC9#3HCZ%i|_xD zT|1^xVA^5dCh{b|Z&JEcOo9cWJS7L_29(_)ysO77dT)FC%faRVC2rIwaEG8!5`AuweFZS?#1Z|Ilq?(G2`(@&CQ z2El<20i3}GHH3VKwtN6Y(P%eUS1dn{x@lcHMQT|nX<(2@nrwQvzlF=?_oKx_V)5hBS)qY2T-dd;-)*X z#1fjh2CwQ2BE`HaS$5AGqxclOrZQ)x5wf!I zFvF>Ub4_+(_`yLz?4_LGwZDKoXlZT+QpjyCEd?siG+lKEhjpkD^rKfW-(OuIBjwOz z_4z}5hDkPCl}?2>G&FQ~tEO}bfO|w+m8EGVYYMkMx_uhlVi1^i+Ge{&^DI?%csLfH z*Sr(QOX|3K`La@q$ls+*^-4CEH|>j2MLJfbs@Z316-J4AmYH|dR=+%ptrhK>=hTLS z)NJ;EPhitT_s=>!1A?ZXyR5_X%gT2OpfJ_}l7@;54Gg$LBn}JKPw4`V+!d3hYkcZ9 zicSQc0Yw1d#e{@MfRdrTV4n6FRs}4zKyrws^j(t|x@#7KgGsIiBxO0kP&WLK;|)0@ z$0sJ{*Y6xby$3au#Yp84N#qA1=cShfq8d|Ep_9Mf^G0VTzO>}kcC@~&e#aFH|q>OQ_GYZES2D09FmUF3?%# zI1h0`ZOh@GzgKoXja_gmS36U^k*Jp0oIKz>0?e^4Z^xHoN+XijGOEu4GAPz%i@ShM zcbe@?Zerivg4*?9DVzaJ*xiUEw#6$!=?F!{|Zu_1NrtLbaTlF+M&H zl#Ulz2hcWPUAx{VPAMxZ&wbSYyJ8z@4!<8k!vi{IlL5X4+~iO!2V#k@K!ptLVk>|r zz@@iA6QS7`-)(E@04mJd*pk-(j)a`8pm1(#ZO#T~ZFon6jl6w%ohUlTx_Y7k=qj{z`d5fCV)Qo9W` zsC08va%LyL+j?p^`QJvyT|+Fi3U5i948SG6cC8dTiBPPAcXslypwTeRL7ojy!L8)>Qw{^jr@6oogIqUO82GGXW-zQ>A0BPXtL?G@aYj{!PBZnA@(MzpS~IUS&Y4AR>(J?R*L zQtCrpLt|4@8xR)Uf$D=Q1TX^ykC|$q`$~h5;!qaEIx==0ezWe>!9g7)5(-ZUL^^U$ zoiUJMMv0l((I~(C0+55(*XD|5fPC} z=KDc-@tr$&VD+GB>D{XZl?q&aHxKsrsoWQGr{mnS!o$R|>?lwu=1S?(p%hej1O&_7 zX(1_Q@~LR8qM(W*zdWKpu6@^#7AbI3(;v#ySONRblW`E5fEF4kbX}iOvOIV$bNBAo zQv||_Lt4bV(Tjf6&t3-yivbX@waqoJ;?*W6By5LXFk_rcB5X2`e4$bC0H0-l0kk9! z_O_yB8Prcp%-4*J9DyOma2iX4SFG=LHp>Y^1r6;r9_!)3gF0#+MMcGTAtBiLMJL{{ ziUP9&7O=UMRR*=*#F8z%@{Op+5_%O-m_WAJf!`%Zfi+S=`v;tPz96Qg#HE;3tH2a` zU?%yclfiU|)zwwAuFowHDPB$DcdhbUE<4^JAgT>hjjy_ zy4iqwF*rErzn3`zojjD2Rzw_fC{t2VS>TXqlCXsht-{2uy}1JcOFS=`UnY zsP19rS89XO1)Lw-y8-+h6LVcNytcM>VtgFnXg?as68s}y=z0)%0kCdcfMKEj0g}wm zuNY_;us(HNN2G}C6rU&n;A;YQlaK^u7Oi0p(EQXrla5L7)&(;JK(m*)3>+@gw66`=^D%$I{a@EeO|o+xH<%}8nWuDluKGk$@bUhr+_XI zaGX-axv5!y)E z&%RXuq_Q|AFQjrU`+3)|V&9@8|7@hZygM#y$jai~vB;%FR*8_}-vGKj)x5-x9BIcSUI9E=i%qoSiee26h5 zc}}@E?CIFyRrxby!D6Nw`>m4eIyCw$f21jKH_jGR99ZA9wkG>Ue~!jSk;MM{VatdW zrf`0k?dTgO>{&p2;mlh5sQE#&c5eprE5Aye1M@fItye#_4?M|q*;rz-)>I~Geig3= z+za35Qbz`OgSX7ru=TgT=lQ-%wUMMjVsPNP_0aUSfau8%%9&aB*2(2o<2Qzw4a!8 zIBgm9<-mMo$3{O+Ys$DmR8-F-e`@@5b-g4{G$k?)7Y6b5R8~$l$+2SEyPs3Xao|)% z&G|!(qop!2dlDKSQP$KOV;DInSH&s~{j{c8&w;kKA%~$0ZfP;um(g=Mkt}=XX?$)w zP^|r!xuP$wiX;(7(dl-vADnf%EM75WzQwr5tHo@7ACE>-Z2Qpfz*#o7U|sP&^V{5; z!&-O7zkT|+Oi3?{UGMG+mPPY3#|rI)@O8^Fr}KrB`uSs0Sw%lJFU@(hHB=RLmyY;! znPknCi_<%lRh22Xq*QuNWLkI9ag<*X9c_HFWIfGtj;1j$Yp_1$FaotdDg3SkJ}C4XH>q7YkC}{@ z@w)V#ba6ZyKW9q8Jg=`oQ$j(i{V&$KF>89eWxc1~@ArTIl`$0OxwrT@FRFMNQ!rD- zlh&(_XSndXSWSLo@AsHcaY6J!btir2H$?NLTo^VtCnsId7?|Zceps*2Zw>C2D`g(Am>qC;dg-;(AKg*=ILd z9~}Fyo1O8$eRT1rU)kFdy)f@C*+x;mIs53Hk3oyTTKzNy-@&wlQcs$$rI;9IqKs^P ziqX&U=MQ9PX8xjez>7DIYJ(NWT8`Sg?5 za_A{G{M|)34{@z$t1FKpV+{{DgD4TXsp3+CNnYN?X6&qa;YS;fC-~xfMwsTmFS|QO z^mi2w1mbgIqvU9w6TMgFqbY1(M^VVEI`Y)sQTbE>>95j_yO-f-IQvsgds;OA|ISn- z-r$8hyyrgt`M;LI@nf-1!7GXaA+8uf|EOFNyM4{a(ESofC*TrY0w2#Jof~ zII=H)V>Hs-1Z1(gYKQFtK||@w3d){64|) z>uvf{2S$D95Kzkkg6Zak7BpNS&obnV=9qtaLo@v4ix7W%9S_C+}Iot2PhwrFj7Gw%lPB_=Q@EOUJ{JP8%qYN2B{Kil8oe_3G8m_Vx$a z&p&?rXs+OWiAF;$e(P2mGF`1d4%i4l+Yn@IG(jYikdQDL7ZVfHTyeECxwfs11Gt7s zDle}i<#SYjjAM?MAM!P_5VU$FB^p>VokZg4>3lKhUeMFmS@51cefpB3k6Ryl|s=WP;@>w z1g@fuZeN9tNi>i7XUm5VA41c+Dj~sJ=xhX#(v;9C95bDH{>Nfu$g0mJJO&lZ?W>>& z1eOPwpJ&f1>kJ-;Un6->*J#QOYMUtN-@;4n29EE6uyY^Yb`^L45JmvG)yd1n#RXNQ zoX5$qcGA93x@Nn+*gs$Wnyg?oa{@=57J>5c^wfQSj^=@ji;JQnAyG@}YiQx5^FV8J zvK2I1(t>|BW7N*!TxQHWW6hMVb5Q##5x<(Q?OQ({C{q61qConvS|0huuU z>(}SxWF?!E-g^+ER4}?0LuG|o<;QR5CXbM|5zof>L4Dxo*PIs<9UUDR`82=pgTwus zCWTrui{OV@N$$f)`*L=2Ya0|D?Cs0y1gzT7`rAi2BvOu{3%ZQZ%}QZNv}^Jfzi6KT|>4S$UM6GQ0$0&YABC0LjO>5iyx-@ZL8VrZOo z00R=Z9yB`oDD$nPo}QlWX+{S@T`4Ik;H0s#F*`eUosxIa(E|;%B94;b#ua+mn0XLJ z3|UQk)*4Hq=w4P6UcEZAxM*3Zb>aMZ3toz&q~p|d*HVYM`W%+uVoayUAy7sZ=H%Ew zy<1&f4ZZ_WE{I`?;vE{z8_mYU!*lcIeI!ysX>R-^Jz{lZqXL>`g)LxVZ~=b`4$mc| zNq?MoKuQW5VrOp;N@MKkVinvmD!=!cmCjY@jes6f{aifA)4@fwGJAa~NsfIXqELpO z|3m^ie{3rR+r&g#8qnef+U+7)`jt}dksYh2q!(d1*}x^r3XFt*R4NP{(y)#0o{hv*3%tbYTaVsB@saSZ=)?phMY zm`Vxf2Dl}#$(YS3=?pjFKfC>YkpVPL%I=^|17co>N7%!|BSS5H&p9o8OFtWfVZcuy z<$(_0)8358qG{-ff0`4Q0R48F$it-EkK<;4y!#S_SYJ8>2-P8xf*8)K7|4tAAw5a^ z>ppkcHT$`sj?X{B7rCzbIW?7ukB^U^Ut<6?uAGsw`@Mroo4U%x5)d3-y(+XE;ALlT zHR6O+&&tBm+_LSXmmT~Xd*PiwFX+6aV`he~Ge}!n7Ds(*Z&!q*iU<1O0N96zF{zS! z&R`T0N=yr?y2jQQ^ZS0dA18t1sbhmAa0Rxuw*4lsRnTyUo}i0le}3b!j#P`4)UUSM zsEJ-Y+*n_KhO#z8Xv!jJ`|tsHHDK%JZTO*+uNf|rJa_)m zCElwS19_B!ohpDy+E`oTif#c40`j!SuMz~Z2SNZq4NM?t7p}4KXx3gjJ|g1XOkVAe zn~+Ro+hU7H133mP9{fpIs0+}9jg1XxLJC^2!rl^_>U%%-jl zZ%*|SBvE{k(=dRIet3UlV+r}BY<3JC0sqVMz*dEB}!OmKn2&1;oDjZ?Cx&yUIB}+Dfv5=hT?@Oko zrEQ4anPaZkZ95o0pOUO9X#YzVW&*JTBnj`~WX&)183`o_aR5!psi@eS?cle7WLgfL zh$TSI3*7*n6B4t{&p69N9{eHZ6P5^LQW;Tnr6@l<8c?UNtRSSM;EmAF%E@V;Kx!1u zRsjWAY&E1c5CTXbBt#{J$cD;#aKpm-W;7q5x~ET{f}hdQ(1^c=a`+lNVN zbCGT|sZaU?Bf^ibxH!GcpWcu{o0^(hTEgfcgYUfV~hHB;&y3iShCt;7QT)03a zt^@KlKqOQOthlQ37cQ2d6;)+gTFX$k-k{>+tvMs*<3%&Epk@^RPZGut7=0iDWz}Es zeLbK~IfbA(9S!2{{QUNk9`}D*fP9GVJ}L2+d#UO~fRZ#a`jnlW-Dm``WNY+vF`QEX znI2R=MXsxpji3VClKG{#ODq9$e~^I>WVC(thS>V%O(!i8_NWb0KphH&vXh`6Je$Sc zUxmk$+V%&OD3W2#i;W*d=l;OOo}&Ss2Pol|O@cQ1opmLNM*hLz=DZB1H)qv(kE@%R zH_#n{QYIumUSC!9lOs)Y9&0m-?kRzyer51JUqizNxQ<(m_-mLYjO{;`bM9=l|L%kh zwmblvGuCwCzwT6iuo|oE3@gH}#&wLwRm@VVAGPbvI6#mY1z)Vti;swih>X;X7kE#8 zf~{Jn(Qc56!xidHNKl&Y~sS*n?OLh5_5WlXWk5g}%3sssQ(qaQ)I}b)DY4IXH z{>JL6p!=qUVbiuM=K3W`EiJ9a(FZ0b49-|O0xoYifZGwYNaWhu8i!7aV%{$wwHED^ zu2()jp~C!vf?6_&Z}~@7P~SpI04%}8B&8Gz<&=75hVrKXz+PSje;$NGPW^(Y5? z2+$@^p1_%*$QBb&y}K3YqdxgkYTpE95#%T+mVF3GNEYAGH4Y4vL+pYo*d$+ogClrd z^Y4>{f#76UIDO_>Da| zlz$#^cY*bx67-B%sPD+q@2qx{{I)jY2qq{_-hs z$N;2={#8{~dfANjegyJ_zeM_MB)}JD|d9uRO`u9v>9h4 z2(j(qm?gI9DAdg0%@WdQ!CqKzRm|5Qg~P4(jqdmRTd z1_YT~Xg00WX;jSXuW`>v7@Zcp@q?bLQI<1g&yjJjQnX4eyl*J-2YqB?Yh^_o!C}K; zR_ucHrk?q$oi9}p0ajH9o7&bDh3V<@a9Xr!x!(qrWX@+#`*r&PPBU>vN$1Fj7%wlW z{{vLxk*~}JRD*^f*aI&N7VA0xZy+e|o5=!*| z{rzz`xa0=f{h0lksMZ)9Z<0Its?0o~SclBO#TC+GA~SUJcpGpMNGrzhtxYX0D?ovZ zYBYL`mGY~kslF4D>IdZY_3PI&WI8rYN#-KZK2v)$tHwk!t@HZ~BaK-#_@ct0Ph4DF z;moljIN^s&oO3NcUkvoSmtEW3ffHIg6LQzt*%|0Q5Q2$q<^~rQ6nvQ$S?&Y1KWyf$ zU{3qQ1^(%pF&kZ7U2gIXVbL2nOwUKv20J_RKx|o5RAkES_G3i%c&y&!wk zLui*DcB?3`iOjj`(Y}9OXAm133+fVUQ`6s`V){}7jY=l+#INjI*Mz5IB6ljQ_GyY+ zOF`|qw6p|KSV3O?5}b+-4$cq7$H}8CJ<~Df78W{H&!7f{9{T>z zpFiPG&UwxEQby1Og(X4tA74((!yLLzf zO^rSdT2F3druC7oAJvF{T@VfvI;yf`?9&p+NkAAoI{!%jC-i;cN=Sz2pP9+FEf^+^ zD4R(P5Ix#yi(h3L`^IeFdZteaYKivF?(S|-ZT(=NVcZ>t;)RaL6-E>t71cClCo#*8 zGwMS7zTpm=qoX7J>>qEt`_ywzCBDh40yIG&Gu#AmQYAbVCrRStwLS1 z>*@Lja}Q`&ei{bHVqZFEZe`WVNQ4p;5`qIy%4ywp-v`(|FC{sgc(iED8EL2$9&+c8 z2dGvUKJ47u*zjDkkKg<4C*}c%UV)c}au<6>WoPJ?yj`e`LD-pcx$9jeKRh#ASi__# z1?)bRmkW*X^YBb@owlDnLGC9z(HTwzxed;Lz)^ijl995&dKsCR_}X0s zgBrn#h$mKDU|ShN{Oczcd;_KH=W?+|?2WV?^m+u=H)LB+$+#OnLG|aMe0*CVn*tWC zw6M?-u*;)IH{MIJ=6^CaX*9yB=|3tq{IDy%-o=3PNJ6;nf?sXi^pssG0Btw_7m>#K zeUK6(Bd_Jw{J{)g&2GkMc$Vr|0U-eh?D{28cFHp3CwkK~(EU6?fg^vPiP+5C9Mm%^ zl9KfxorTj;SAy#mgtTsi{0R$8S8Dtd!I#3Mb8+!-GU%suR8+cNk?CC(9)z2?$%l%q zsogdIY)fdgv1Rw$uKVzBgqSx9U^+XMe|C0sD5Z#p208rQ0r`fh@pW@GSJP(b_HDK-DBzUjHA>zO(e!btnK~Dq1j5O6Z9>;8%_mts%NR-}FcC9@< zJyRj)5FikP#cs}C{ZpZYzl_A@{gly|3$MgKDoQD{k_!DY)zzgO`}2DiacI7#%EwJh z&|Yp^%L6%Jv~eS44Daz4fEKc>yc|LZP=Yb`ub!xKMoykSp28!E<0WMxKJVz@aC(06 zA^`!lfSr+(Q}5P+^40~CTjYUOpelqTAt*sXK{zKPcKdb?5Z|LS?d|Q8lSVs!L_m`X z?+}5cr#JDB{$7d}deExW(>nI{YisdG`=gK5)zxA1;cP!=B&%h;qJNA%s2%TdUcQ|# z%diG2!0w(N@Y&-fYZm+S?`L1AGJ29u(Ei@8CA1nd)_g`1n!6~;g0 zUP?8KBV-Z{Pnr2T)pxdTKUm*Oy$uQ?<&{@Z*sHWQiBUh^gcvFl>}CZ}m{88g!6;l|dMd)yO~Qk|fdp5x+;|321cnJ4!S*Vi3{shnGPDycKRs?5oM zd=aS$1&Slb@o-Y9;A@Jktpd3{_huF4u(|~t942iaqPwN`t*?L+;kPh}l=VF^NU zJvTou(k7Fv4CW&7==hsB-oiEK5;6p)$;ruKYvD8nYZ@GMb8-2Qyw)6J&rTWur$gzt zyWuoEoW6uV8^N5h7yR=SbN>%nUmX_J`h`1qY%HV>CDmBPRNFz#&l!PFC*UX&XeV+T=`R5!J_U!%b?_29#?^^3!=PcS$o-Z}w zr61$`m{Skm2JY>Ikc-kB%2VCnzhTaOCRu3CB_ zS7EfAl?y)=ejBV{pJ#wDfYY%GyfGHwGEKP^;To zwzhM?DZc8ngXbn(P&Vo1TT>;;UJ0Aw9Xr8Jk8cCqDP3pJo`sDIfWt{x0@xENsUE~0 zzpag@rzfhAj&p?1J?iP{3Flr~S^`2KN!fjucwvjG3+g%vCOjg* z)RK-b2GVA%W{<5F2TVqfOx^8t!z#5OSgZI%HVS4M`nqnpj{2=#~VGp* zW|OSQbndd~O;J%c_9SI%emVzc1fuAbg>^NdU=&V%nSm4J5uBX3GJ2BhNfov_)NN6x zDY@1XJFG%WRK^*oGUpzBcl#!m(qj`iId|toh|tvT0jw)w{~y~jb7>)b9ioV*Eh<_r z3auc=82|kFb12h%a{DFFhTp$i4pNhaRJo63l6L7khwCWWQ=)UBy!jQ`Pv#!MO7{9s ztcOMbngH_$hLel?2(n`8;A0Q*K@d|vPqLPRY0H`eLjf5+RhC3m7ETwFU+KD6qN&^XO9h{~B z{_A+y)?k&u;1ox41c+XqfbvhVITWR2zz#kSYX8)N*nn}};2 zL_`4Sw7jWlTnx^vl#o!>uZ7YyL;f^Lx2bpFYK5WxU6Ank5KBsk>oB&RDq-p@$bsc=4Aot#uLT2RmmG@HE94UYib}d<_g5sWeyjtSnoPmOE#)bXm(b8J*Gv8 z5Mrz4mCwC5xdmo|CxtWO5{c83odL7+?;D}}Lt;Z;zP!+2VXCUGehcO5@ruYh#oU+A zxq_>OmYD?D0_UzuOG-(pNt5L~k?e(SI1E)P;GxjK^@1f+WzjyjrAmCBkkd0s_5X;1 z+Y-I(Vn_Hy$}!$jc4v`X`PM6SnI|T-lK?U=GEpXsjE>egkJ7{{sEl$Vgm^AS{RFrL zAP1H~X5E;NcsW^a&X@#2b;fU3?*lClS&?`zD6D?`__2UVC|F5`uK;|zEKipHXVSq3 z5>0y2oh?NFwK)?(`W{xw$M9nN`ueoIPl-waNaFIQ)w`>qp;17}&l?=;MzQ&3&3XIy z9PfC7hHc~R>l<i@I_V7TCt-_2t4to8%swID0EKRs<%gYv#E< zq>lb?6g9xM+#O}%`D16tPYF;1gPca#+#|TDaKeiMjgQ|r#)Gx(W*La(MMP+$uBLIY`4^hM0am7WRa-$0!%~oJo)jTDL`Y z?1*t`y$lKIA@wNUM_I5x!(y?tEq~h+NXgPJtD%|GA364AWEn%LoC%+t{g zp*{5X4)pa=Kr#C&v}OHG`*8D}Jy>)&`mlb99ZVOal5E}_y)?j-(#0U zKmyuhcAjV)?gmA#d?8+Q%}G>h>in-?ogxrY6%YCwJPp4B(!8sG_x2h+v0H%(U9XsK zzx)E^1C;gye1-HPklt(hYo~0Ufq$9vsN3G&1{h;+($@_){R|9TT%16(%oK`%mdMS1 zhX!;(%`_`3tG?rHC8mo6*W;PBj+**DKW_(Tt?t+_;w?_8Qt_bx2Z4JF=k9%k^@R01 z#hTn9rVrmZGGb&-K-(A2MTE_yf`QO;_i~`)ulRLv?A|QO6IN{7>Nd{MHj}#hhoQQq zpg}aZc_qV@E6Xb@wm1W73x>SgfR1hor9iX8YY6jnAElr?!4<)85wOktJX^*KqH)kv zi~d*ra?JIp=9ReESnBGH%}t(QQzSib8_v#fb`n4c4G>+rdY;NR&Kw1<%&Dqw zm0mI0a}jZAf`i|_rA~&vDnHty0*;Q2Dm^`&o`J#IH1j_B;88FV(CrMUYxQBHWZtFY zD!;+H%o;;qReAI&6EM=Rt%HKHJWIr3cm8KZL&`PB-0uJ9#p15~k#u!%Z~)AC@34zD zRw2&bP&|Q3)-0&84(s%}jz9!JTwj3|=d^<~qT#HE5m@NPXu zd-S}7xOm%lI9m~26?$e2C{NfX1c2Q<-$H^9{3xHqt{LE$?w1+Z+UB95e9P>yv9+=B^Y>>it6PmuHI%#}^O`S78636j zwkK9Tw{LK85S+9XznGAaH_NCdoSqwZpMUtV3SZ(g}jRcM06y+H2wV5%bqydIq0v!=IH%%@6 zG?Q^dA&AI8^9j27Vij`JR9WC&EN_$C4py%3?sNuSQqfln8vwzC{*c|pim+q?rr(~q zmoo@JkifF~`kpusWC9Mf0!F%W2sHSQZ)d&w$Bn6pGMV z*=+6R_98GWn&aE&m!;Mo9{hBhc~9lhE!yV{7#IH@)_XjF0l(4tn|&Nk#(4uHF%PQ4RktaSOU)hAm5CY)!oF7k5P;9|8o1FmvJ8 zukztVNWsPrUOcsSUKwQ|-#XDqV0X(N-2GAxjjdpZ)hh(72oY~=urN2H;`0Nx&cs4kqO9Upn1Yd?$sqvT*~xpt^PLPHR^>W#*@&>2i_a4Rp78g zYDRzOPN6PqWMF&)n9dP^-;0ZjQ0nEN8yU*j4@(Yckr|l1pCo^Gno3Xp=ErO)Bh5fU zG@K9M5IEAr4gg$5E>0%5Z)paq-l!uv6Ct1iS}MJ^rr?$A(NNg}(*p$c3Gmy%4FgAh z^X9u~J_GrF!Fz$=IKbs#0jW=YhjJNnb93)*?vug@S4YB!+-P%oJOiv6Ko7#FRQM$8 zZN5@KUc%R4c$A1Zd z8@w0-syP<{rGSvs+|DIlRW|k-Dx|WsTH$+8TW)S{Vq)SO0~|nMsN|`t5}MQ!;!H%y zu5x7#>gntIuDJqWhi@q;=vZ$A4n~owvwC`EH;6I*B#m!jIRj}0-gQu@Po)G*UcGW9 z3ld0nb|;gC%*UhsoqSy>shfz?!2rVazW1fV`A6zPc- z(|_hWD@UX-6Np5dykFnmiterKW1147_RfR`A<(@DO$LCrXS!1>**gkk4V>&spsIkq z+w^!x{|#C!*|VYJPkSSXxJVpi-;dI;JH(4;^r%DDUQJDj!>lTBKx_`^HHZWtgci;) z{UgTwi8@LSToDk>QoR{;@AjaYnKUB+>WaYr|IsZ)dG^^=78I~UP4C4hSiv3}&Y3%8 z4tIG{F455eN&#ODRBuoaY%bK#ZDNc{OCUo4?J@e2u(gHtNmjS?wT9xi`6y=_>KbI? z+#_J}x5q_+=R9{svbMe@-8Z(fk`fw9B}QkP>{Fe;T!X5lNrKXk*#|5tED(_}BGY z@_*d_M?$vxvCHo#-Fc}AT##iKfQ>3I?J1u#)r`-8in_Tn)n(SZ1qiV~ z;H3EQB?#ww*931SN{cw5TB)~X=t23cW!n|YXaor zI_{21%!SIoi0+RC-U%Xt?sM!omCF?!a=$t7UiA+-+cOMV64SD>cmm{!X9eihe}J1P zBeJD3($ZI=2CO7{HVR znqvZrm-s2X`2DE5wpf2prY9hg|1dBlDeHti&*`PC?847NqdHJT%`3Lh@XtL@vNs3> zMqc#s=~+}v`~6RXP=A=PI;9qGo<5-eiuY22l5APA1w5YJ zn>J)^#^K>dhna)rq|tTdPZH)C99y0xV_9$7B+lz3M>mgg)UTTrNFY$s0zlU+t*rFc z0HDS8^yrSI1L;isXlkd5J?@0}cH;PPc=+5tJC3CEjEt@s56rTTnj7{}792isaOdc( zZvXcy$zUUsxWDCDf_*$Jt=uo5z}6`;0hc)ddkTES&=8~>kjj{chySfE*NN{(3(165 zg=SI4psGYH45(i{MO#-TCPgxY2cPSmPr6Q3P{87}Q@p#GfiX0+hC1_triD zSpqWz)FHMGA~%SEF`n%IU1+Kn5)P>6kT{2=va~c0drDUtUDyA#yA4<%Q^;$fTjCnxLv@CDneOMxi|V8UD+krRJE9#*38{l*NIg}* zD$hx`R_cP_WEXykcU7cRBU4E~10rOADiIrRwmcStKDX>Hix;&|L;?ZP)LN%6LCbBK zO}tClVT;+LA-^aR-+C=K+~Vu6i^~{y@Ofgr{P?21InE=CDn5aEUggiO#jSId3MF=9 zCdB2>i@Vp3D14GAtSmx$l-{bnS)!e$Iwv<{N_ayIj{$2u-PJoPPJF3av__ zR@`v21Kn$e1bU1(J9`fw!%@r+v@rho+`&*Ac0Jf-Q@)~rGPtY5mXvA<86mt6zf?i? zaobI)4zy|&QZ5%qjusL3ZQdx_(6G@ck3X*bA(4kbDxx(+w<3pc40zNLmnWp^7W{5u zDl!Rc7uLrA1MQ6K!8WytDe0^5A}4IB4X9Q$65WP2^bIc}ibv{Xl! zoKwUxiUnZ&9qsX#MO?zzsLe;LeH>dqZ^flbwO5k%PwDNXvLfv;uPV<&wfd1d*VO&1 z6?Y9>8DyP*WAeHyA8sSZ`$OF&v#1hpYZ-M?*$Rg#-M}3R?>28-F3{LX8$K%VAGv*6 zS5}lF!R*?2m1e4cljk_LseQ|zJsgow*4)q8gj;mRtw{LR3{R@;ehc_lMGmu$ne=#T z?036Z>zJhSjlze-mX;A4(Z6h7e-D z5vv@CJ1HW2Swn6FKSq6wJNWyUSkjs;DN)>?bvjinJ}IdFVbdSi^d-wC@0>FawVL|b ztT7M!25awLaphJ2pyaGVe)rmiSk~P3S&MR%jd}VAH zM~NHidCG<(!_XvDE4jKYTjOds&f>``9v1lPR*$v)>ytf78-0yas=0QC0$+NslNeDT ztP78{ol;`Q-@~(44H2{#iiFcrIs>|6_3|TW_?}Ovl;BtIL|now;D5wG%$v zH(fHcf}RTFD}OQaA~ERxCJ$a4tMrSn!BD(AkK_b8b*-OJCY0k;3w9CLdX+LTzC32> zKSaEr7$OImv3*UqlL>_;TBV0cr?mxG(m$ip z!V>toZqiL17l=Dt+rQhv>JXyjZXfq^(CwqD&d7DsUnaR5PvDFjzIG(O`4DS3r*7h^ z;*5bEi*e*E8XH9eic6j4>V5;$>@2j(dI8|pSxH}tkg*V>D z$>Z`QSJuLlWfGPJRf=>;+kn8$imGMxvk58L+v_Q()XTgZ$#`+_(Me%PVD8Gz-RO-w z!YI+K+WrUC71y%oxkuFAD;48{4N>8ZAL`zqr7Kk3&8URlsMllby2yOd$Pe9F28aK7&wCjPvoZJL+I))6KIOjBmhFDyvR z^kEjtr}}T>*3m6q%L`dszS#ZOp0Swai=~?$xGQ*;3g_m-2%E$E!fNs!rxHJ+TR82u z9}k<_bi8W1ujSYFeE)KFqI~X2MqD*>?A|RR9LVY1!>;UMjVE^op^EJA#?|f5`ps)e zgqobDl|Wa~y)Fj`0N#V3<3S8h{XEE5w)`1128`@dkADq$E7Tg>Kq0lKR-RX`XYjwz z)O?oz;HYiRS5UAyXsD+r+k9qH=U@&TT4c82^>Q(T!{7R9oF|m)=K`)hW^~Iv>^21& z&5DuXvfF+;{L`q(&%hz!zSiyZA7_YfA;+$HZ-)19(N@MEQaxc2fOA|Qbs1L!6!u*) zQ{oL;jRA>|wHm130v*SEG{DP1DCuh4z^SZ&ieutc>)8*{V)hvu5i$B|kLo;ufj!j- zqKL#+FE;R79j$WwbPK7NL5LHg(Y3(I(}iR}O>1DZZf#y8gm+N&2qj;wgyO7euUcmA zCz1x8N|x+gGw3tad+Bo}1G9oGXO*sQ?5~K{+@X&TauEJZ7s>b=BaPp;IkeN88zZZ@ z_?`GOBm|g${2x292EdAa438uS_Tvh~FE#@uQ`7!{EhH8^4}CT!W`?E4xO%?UoIthYna_s}#ILNAc+gTF-aUpz!RXS}5}`v?Hp)|GU%nip`;wa8E2o@(H@s zN-LSeCv6pDi*f9p;MmXdG#A<}GCVxRb6LZ|2=_0y-&LY*%D)24ec+EvlMlzehXQxL zW(R>lAy#V3L1uCZ_xeLL^|g3jv$dcrK2!=3-H?5&M~SW|a|E&37uO2u4;vxf_A5fKw&c`DH+ zrMooE;@C?qg6+K1I=7~U_s#VG$Ys{%0%6@Fb0K@>o#^3xn?JZ(!B+Kq#8oKz0K#`5 zf~b+bCkE7k@0k0iXjpKByd|!2qp0$eDl)@el4U90MZo{lZHB$c?jR?hR|EE?HuRVj z9+zRg=$4dL`&;>sWB1?u886I)rB9>t`JAj@LIN}s|(#Xt2g&Ez17uYLz%RRmngWi z<2g6cdBbKnn0Ry*pn8h+p3?9_B@>pl{*LDw>K)OfRX@CrR7-q@=N`DXpH~ zo6qe3^}JYCZyrmBz@ifGYvuKGsi{2Roa`Dwqmf+7E5v6-blx_6LfI^MEwFuYK}%0r z*WwX#oh`p+m?VB1mx*mMN!YlA z4g6F$m)x68s-Oy4)1(n#4T+v&((ur7Q9|3+@Bv=DPRAkE^_19@Z zOYxg}f4MFc=`?v2c)BK3D>tA^(xu+Z8;yoGwDMgXBbJ&W5HvR+QLgTQG+P`?N?_gB z1mnr&{kDoaf#-$v?3hq%h~1o-{br7#&Fa@kW`|f-(`$jQmZ^K3=n4pZ&w8-*m!c}W z7K8A=!YP07RE)Qygee-&~yqg-yct4+S0*L;HI>aPB}|{JztsQG@EQlnKYp$jUoA;a)Yv@zY}uGpQ0s zFvsnU(ya#1k-p(Fe8XGAov?Op*W{pUXG?z19Tm7a!mN@0V%kZv`63^FJH|L@sBSAg zHesW`5woSaDW#y`r##|HlZ4YMx7!+J!Run1bn83oB)X*^Y^EZ4u#QBhMXaatpp6&i za@ppddu8LoZ0*kKjGXv6#*J0l$seZe-ucX$%+0)%WM=whjX|Kg(X3PHUV)|M@V;tQ zi@YH|&xRvaa@DlL?6sQg8ZAJgtQTHU8-K#TuAE0LASWCK&6kE43g4YbaiVV-bNzWh zY(dg};`VB+9TS1(BsY?_7OrR;(azi$35Q(tZf2qvGywnlQ&Hce;+wi3?WxaIxz{9U z*m))C2CKL7kocA|J9D71pT*3agLQ|JhVoEall+eJT(iaId3ob^CqxwtcBf#G7X1 z3F~4((H7+)!W-CAq_X1*3lTj$*E7wzcRd#8%H#5=#WUOb!ICw(!xz`}eRFpn#{G!l zD}(BWjNj6JB$5x{WD?9+14oPMC-WcS8*F6aC+vkedrIeJ2EX8bSv<8k^6oUyZ>FHI z4h+{ONF0VHLw@^kx8-mbvTb1z!8>`ue*1rh2qKI?#uCPn!R;UHlpKz1r3Dk{w<%Q$ zb)5tj*`u_jSOSrgXT>Q8 z15T?m(J}=X-^8azBMj+pPC0g`1YK_$+k$|d#y(}^Yz2k7Jc3gP$`rnQxhW+TIF<{z z0}5^ky8gd^6T&7)y+I3zEKw1PP-&#|>}w435qnru*B3!|qm{Q*wo<9R^Yr@Z6IswL ze7iBB?qidjYfsO5|9%hfJKm$ z6cqK_9Jbxs+RFQi_ibL!ge-CP-w&+NGg$>y54cS_cu-mIYpDEFENV)=8RNWS_Ug)f z^)y`^38nxL0Yf4JcZUO2skQyB_^LK_|k?{Q>e{gP{mss`n=2|0kO1)}+*G_A0 z(w_}Hv2q-^%FPvl=&-R6_&DL&+fMBAGQ_h8jWW+o2^yL!nTirU=sX zFJZ2T>*1y=ln!PC3Iy?oo^mWREJTRzg=L_#HyuHanUyIG`KIjEB{vgCx4z8l8sf%& z4W6x+BQtsqCKkVx>pwH>3y3kgkc3S%n>DG}sIBaBs-N1okALg49IF-KDI>Uhw_+m6 z)z7@I^Dr7Q*qvr_PQvjTYW_OPfD+o{psVJ5GgP7kFFBfX;-Qy>+=!>{XTnOroCNa% z!SaT1XpJcis~0AkF`3SfHCA>NnRjxnT#|REWQ$k8x9~uj) zct*TlZ-djz8E4!Ojd0*8l@#$UUUJtzGgxoMU~6H$gytg%hu#>ojaQ0HYhSYu`nw?$ zORaCxH!;x+WfW8Mpp6a^36mSIMF8WQLW2ZID84Nz2?nIEJZcN~gcx`UB}1xyWu8|z z8mGSR{olHP*?7S zd7e*Yc%d4tRAR8VS0m=zFf3Xljd+({3qsvye+u=bU}PMy=Ag1o_#46?s_ea=tgU^Z zML7)+I&gG!VsLysQyF8no<0P{DT^ajZz=-`e5@t|ROpBnXzz@NCcnw_mm6uhY4x|Z z>Cxkj$;{mcb3p|5C&NaY3Lhe5rKPtMY*WJZnbpS8>E%mZs$^kadnc~H^*ckBWC&!L zF-SZUSQpUO;B8nehlZLN-r(&n^8=6Xl+qyXeO27c4x-8LZhzsd{cWRd)_nD!wP?>2 z>tk%PaPRWO>|F`g7~@mluAD)|*`Xw500g9VJS%9;qhF64$cKIs_uA!84+NFs@w zo1x-w`@YQ&a`Qa&ic0W3w~Y#$Fs5?ZvyqBwT5{_G?v;XJ9l3i5Ir zrzZb?6afj;E4}L%qdtuI5(qlkDh?M>KIWwaGo3GMK#HI2?3 zh@xbqSKKgaL%AbmIkDN*=M^U{Yf8dF$?!IAG&6DI0p1lto4?mtrJQ`4kdqg7yKE9M zOMD^IjxTt8m(Su@@D%v$p3Rhcm3(*T*$IAC*OTBi_JxRov2qme3G`CK>9(kb?q=&` z$<_4=6?)2N*NzXOloD|@-OGup%8J7R4Hq+iGQH{O8b-gzMRYgY=&hKv49nh9aKshC zy`4vw4i^c2LOA4%gacCCrB!&a_qtNvFPko=k?7VPl-+IB(dg`qrgvMto;=r=ge5$t z>y0(rcG1HP!0`q2KC?6$U}X|g`lF>4eU%q^yCV%Ly(*bU9i=pmW3ks0XX@!UlZ#JO z!0;*As8G_w-c?lcJDx+ui0h*5rQClochKsvG)S~k`QGhkS(z~CJdAC(>Y9cw5|tqB zEX-!g5vx3j^eH>*IuNBys}lSZ=npB#2KXq+X%29(G_}U)1m>7ZPneHC*DcgVM!fJ~hISKGX-O)IgVjTxO5+S{iz ziq6O!#iP)fIC<=TaPuJ-X4K&)x(8=2=8M1Gbr&^yBQV2snXJF`*~ahb6rLMU5id*Bcx2gy(cz+3_DSr#jH38wmt3NR6Y$W;#}9|MIN5$$leqTT4BwpTjvN z9d+sEr5B2&n(mS?pd44Hf~LS9rb%&PRK_`p&m2+(#Yh7w$yX9LQv*M9UGK@txyfL4 z-V#5}98oPkI0k&ymkxW1jamU&|{@_F1d7cktGG5CJ&4*O$ ztiChi zYUv-!)!F#WM|dH=uYqlxh}*ZJ#4J;Hs;P_DqxrBOney3K7?OgRnu>B(R|meulad)Z z(-+ipHgGs?oOHztWIRp>RVHV&<6E(!Qet3maV|KOVOr;wJRd%CgQ8+fV#@;#UK$~$ zb#KvRmi`Q?imKEUUGRc%`mOInnTXmxMsqrj(6;x3H2s z{)M2*$KwcD_Wr>1?_{!SqVHp*wy^?*8A+Q1DsNr|Z$$$$n%QBj-?d`Q{X_eNCLKSn zLaQW=)f#=7*;MB>vY+?ZdXQ)Y(OMA-F%X)30l;QSBW#}=5O*Hp9kC^g_yRx$={l*U zi||LsXzNV)568rbOo<*>!DKq(x*-ujE#;gRV`mXkWa&|&tA2zy2;N+lxEbxR^y9Cm zjgR)@Ckam&o1#LfZbcuH;|d9}sAJ@K^^M|fl72~Ojv42K<4j@5S?XKpuniWqdw%3i z;Tsdaw%Faf*Pgz3qFJ7?w!hb&)!qHb$A{(J-X@CprLy*fmN_<8q+-5eFvc(1Dyo~t z@Rc|J_J7;F01}b#&qw5zwSVn@tr#0)^{DymR9w+y{9jzE{s6=}W$Rwa6~;6M&+hH+ z%O7ddy+C?sEa}?a6-Im8*=iO)qVUds` z?2P7i#d2Bt%5n~7vf;#Atmzzm z@BjWKM?^vC?DX$Gz7t+;_uK`HNqK*^L_*S?jU4&%cDlGDghVf=}qbM$^h$%~@O&>Ek=Y5Eh(mnGS2uJ5)CjYfz>J15!2lWwa0!)Hj`b{^5M z-yhm&JUckj>upptUy-~IjLK=g2I+*F9yY^-+R-_i4oJu(LoyYQ8hRbU_ z=lfCmZ}B%4)nw+M$*s`nRT>yuQAdtE2t2Q0uFcZ;E?+@iex&x~IIR zw-3KMvlrhq$T+iewk_;(lY)Q46aIHiZm1d}y%fS9=5~Z_7pWygKf^-FINi9AyO=NK zcUX9PsH_l1r+bGL^?{(_A zGUu{!RbiqbmTk9s2;CX9YIKE0VSCO(B^Rvya?{stJ2C`+5ZYcIJHCZV`SbGZs}BFp zYZx8bfiWw_h`#!gwc?+}(HuM&WU%g!wXEmMH+t0X=-3JHWlp>$l@2^4yTKY#uHo3B zik(co((A=T+m&g*WMbDcaa*^bKp@d;kD^1BXRZQ~Wc#b=cy5RSQZQTj z60xdnj+KK-6w8>Ezmnn-d96)*|M>T6m7QYcA=_$mpWq>$t&nvB`H-)u$kN!AX}w~a z{O2Qep@V6M@&MR4Kgp{kV?<3%YW%*Y|N8lG-h=azgQ~Jb94H$uPoOR&RUG@0Yhp+S zWrDalNdJ$}EQ2HSzfatKBUS|4ALK>rNVYy<&kdq~LF8P9?0g8W=cew=P2D+VYE9iw zi#0d46nzTqmX^v9NS^0rxhflfm&1Q3Z~P@(DkSr{Y6?iSs@7Zu>X8 zcO2`j@*dUjkiKr}e(CH{1oHmVuXYnR2q$x{iBfl<{uPoohU9z^JQrcRX}$B}m{h(m z>g7{k%Wt5A2o_){RQM6#%u!lT!`#;W-_5hV0proeJ`1$Dy>P6+K;tkqBXf zVD$m_6YbT?jpoQx$;O|qbPv7$I<3S)x(ChIk8YrDs`6#NsxshdzW!XRbK@SFZabdW zkX`(Sl9R8Jw^gdb_@=Z*x6Gfyc5aT^YX1qlOnPlCsaH;Arapf?7PeNp->me)eow`etbU0{Z=(@5P?e6 z2NE(sykg+oOr{#|4L^3!yvjaf*~Z+m8XMeDgRn~ zK(f`HBE3&3&&jNJ9$2%hwXf1?bE1n%zSp|`#px> ze7WW?#mH3K@uyE8;U#VlTN{hxpQt~l!hEP!{;usmLu=*p=$relgc$F*r#V>lmjV}~ z{kzyOM+z@3Eenp0TMI7Dnu%g}_9YmCe_m|-I%fTzE|$zh@NP*TZ1F48@Nc8cgx8UO z;Y_bL23e@{esSkB-FOWh8y3+!04wxe^UquH+?V#g)FW~_9b;U}PPikKa%+ZpCvbC`Uc+@Tw-B_ZQAqpe2n=_40rd& zJza-_bZ(sizv+!biG0#-kY%50b-OKxB2&nH`{Ngqjop4)8)>k>YG@o} zdCLjOGg6(qWfS}`tZG>WjL;TtYmD6Ns}ie<8(Y}mbZ37Dt9KhkX4bp++DN{UK?;d6 zm4mFoj;3juoxjP`5tQPbJri};Tx0xO9mRz<+g!!1^XX&PY6k3YL=Tvd9#omUmnYI0 ze0OkdP=KoL8&vS{mP#*N!xt+$LE9a%TEHUgZA!& zo#&Ur9CfR9#J{IX*W>qIvs9RFF3Z1Nxgt1vjw-LE$u{cGkYI;8=fejWIb@{tr`6so zi7A;Mwf-|SmvQ zAtPHRql~=Kh9K(q{f6w*oorJlm7@e?j}6@mO7eCLq(;;n@BaJ z`3v^}8I*4@2jga|_pu(dnDxa=cslF$Z-)5)$?N?7hC8KJpyU02FNPY5Rhc#D3T?>eLRJ+jE_u+K$VfZvi|Lks zZ8E0qJoDbN-zBp|O}C`vL7O~ng1DWr30?iWm;cq&{uX|pk;%#Y^p0vCTS+n*@&ZPV z?iI3Tf$bP7$mUIRUB{D1(G!6$3;U;kK8)3}Ui|53Y|Aw3+O2H;o7D6!OE=RLPxrl5D&2!y;tnMYbt>gwA9g?SxXr#=fG!-+4Z0=HY{Z&*!B;Q5x$$g7p^=Dr##*t? z<6gy6V7>$8=4-)Jo1t3`2I zPVRfdRw8MH$a%J=B?_pu>2dCs>l(cV`pzlO*T6i#OK=zkTQQ@@pLW#U6|bQdr`Qr4fksL*|8tsHcZFsU%Rxy7SD@N0xZVre|a%g7`gyGME(o&3Dv zl&`8uwjT{mO9Ms_6Eja|b02V<72%$4;z4UNU0y&m^WI7Pu%Qh)byv)|6i z%!`J{rOCT6H@0dYoR9u~p^I71hc2IxZkTEBOyX=ZJ%T`T1@*PAH`1y<5$qVU(Q&nF zze>S5%1KR@^33o{XOk}PSH9iTrgb%AU#rzce`U#h-1*_Zdg_aN1e`Z_+eZyWYi-|c zD;GT#-Y=~fNzCF?E0V2l2I{=$u@$VOv*13cQIFb?O-l)>ZcoB5F(QyuM91**j2rLe zxh3KlnJL_FEm6z5#niyrH0O_1ao-B=iQl)SOSL%47V5lE`E4&Yjh%Ymc%mAko$KxJ zjE#BZ?Y!*|92|oJg#(2M*IOA59m+kER&~l~4utHniifMyAnrw&?+6`K6K{_purEOn z8%9v8!o16Imn~4vfU&~4Fb+CqvIdkBMPOo-bIthd%1U-}ay9(+DN2@FlRf`SA+#F{ zL#{A0%hJ-)rN$q|szH5+wu#9Y^H>ecpoOcwF|3${!v8o>X)5TtD{uKQ&$!Ea#mvb$ zJ-w!<(IX^x^yJLd#ms~dm3E)e6G0We`{|=oX3}P#7HOUR%ks5uIrde5qv`m-Jc}(q zf0$L%IwEYW)vNs3qk633@3W`OD~i*nq$v>Z+IN4yKmWe1?c*~#N_zTVOGbzsHfZO7 z-s8%+xL%l|4s%xnAYae~>PvMNrr?n}~ym;GU_d;ak@4siP0W*(XAL^!kCKaQr>C8~}{+#*Suau3Z zG@ZPhqZ3V^o95L%aUWi!@Si*4xcxVj_Cq!I?zh>+IKO}OH}xM2E#6sJVp#W5aBsN* zqz}bxZ+0-WvUeo1LN7L9F8Bn`3B>6EXbe1lmfj2R;m{01Wc~0KdO-XghVaqWt-xqN z7^7R~IK)F?SmmG#e@U9i)IWW`3r7CjhsA&aUxcKXs_L^ym_;`c403q^tL>N(!gzO( z&B_ERQ;>*Ic@?B{*^FN7I%744Qe!@Ue0y}gSj;k&161ex40MZGr61>Moz6j4n27t8 z{285F4lgkdR{Pq)N+%vm?@QSa8T40;>S_GA_VIt>y=~}GRq0m?-UeQVYt-sAa?-qATPZ!;ieq4TQbQ+tm zC|Fibw-I(R&p9(bUt_s4&UvtdBAkU%%&Eo-1L3i|wTFAMk8+e{wB?%b)ezhYG|Lvk z2nm=Rki?sV7$OdB`Y~e6rmI^^pqULB9GE)}QzQZk zCdm*~7>}7w5ccIsc>|TAghDqM1_}*ING;I)tNj}Yt+Ak{xDO3lYA8`Y7)kJC@^q&R zui66gJ)Er}+hD(#;qth@y3#^w!JCsYRUC&FcWWqYhAhQ+Gyjos!?YU)tM$s%A3=Uf;x|p+*Mh2ZAaZ)@ z6pRP}$#?IDanKpXElb#axi(te0@DmtOr;U1Fw1|H*+;8k$}tb*t6&uP+?nrdtE+XN z0|NsBvY?j~60|T(B5OfWw(Ox0;bjQ=Pjc-3Ub+A8bf@GGiCJYO%ok#uUfEFfAj^sn zwRH*+P!>aznNUeRYus@puLqxxTj_~yK^rWOJn5qa$ zE37OmFn`rh4g@U%;tBnq$exXPM93NzZ(B|Gf)L1qHPnr&J4=Q%gWF~#%nyZO zcK!`C2)0g;#1!{gWMdS=-v)tH5NlBfiD}mgnDIQjDDM?ru>xY`4ZbS}P~z+gy1hRq zjv=U6U;rWLY(i6(pqjv3iY_$rFr51Yil6JwFyyT_fczd+ldGQIAPje_g$7G77w`dD zS5mueQ4yC$lNeG2a}CAzY*3t;W72oND3km{51IxDN%b`8LZ3H{+#jiHqJv9oevyTE zf<$-+d>u3d!CL+#nqbHu`-*46ZY?%%2?8awD*?Y-!Hf{ZcUFY|IesP;hH1hCZy3j@ zyGJ~gpc`22IJBJUI}sHZ=L%M>!lp-Z>mx!|P7b6i!A1|kAj46Y2JUOua=Ow5eWX`=n^HvOILfvAZp4#o<1|8cIFCE!xkPGB zyY%l2E6l?;R}i9kU|V4d`UcF#!)}F~M<{1NLAh#%@Df~d1r&;4XVD8gi9%N&^e#7! zg8JwV$W3f-&lqdGnhzw1pF+vH3^Vf#6cz}cxg!T7hhYTnLUzzj$Agt~2stYl9s%R? z{ASZ^kDvMX0u4IrgRBe zeSQH8`;1k20q2@t2;pzb zw0F(47is)xH^QCQY9w$g@8i$x!wU%ISeQA!2Ro}ht?OSz<1%F6K}p3BtP{Lz==t;6 z45b87a^E@=m~d{}8>;o88KmNk%B_@|mq7a5hURx0IvIseuGj*bQbowD3RVScqFm6v%a4{|N*wK`;;YFz@{^ z=q@-2-J*^MWjXkebDg7B0{;R-13Umu4ukUN>W@!^MWF${Y?1%6!VkyH^9OFfbicZE z${1jZf4kg6be`cfz8hg&c0vwmr{dH#dW^(Jpt51m;#E<%9EDhV*QP&u;2pAH03v(~ zhi;*wy}9QRwy&3iW@kiZoNqS7y+|^aXJ@e?)8zU;?7eqbQ{DD1%4b7BK~Y4ceG~;j zK&96xRX_ph9Tfqop?8P{DbhhisRAOM&^tt_N|oM;^xk{T9l>w^_CEjJbMJG`Uwb}J zG+||}tU1@5qs{S-ci@UYmB?eZlK=6FUgkC227;q=kj(>h8*nnrk-j3!sIMR^uP?s(-rO2(~Fz_ ziD40N8D^eWdREZ$Nw(($)mB_GM6!(Yo~QU_<6~!k+P5YMUWI)rEV*0A9xn9<7z`V- zl$}C<(cOo-l7CtXKCDmhx!LZ2>|%I!5J83ZGVi;^+QHrg)%K|m7AzVE^KG^CgnMxf zoPSk{VT(;I8lIuH7f+O}oHd!|=l4N5<{R9c6MrjO#_ICZkhi_qUDvew`j=8b^CB~1s_$l_o1!}wB zojUH4Y=v$M^MMWIDk{&aBLnFBRx(o@svZ$~I}qUu3R3OqV@9LY6Rtt!w9vaa#nu<4nSu;fDH|3a^8jW zhfBN?*ARuQgT+lV^z}V)J!sE}bPn(A#f|=Arl@F_VjeE~-IfO09xnf71x|wbAD^uFr%7Zz-GW7dr8n;iHMBeFaC>~x> z_4y_D-C=N8Y|h_kzk@R;`1Ow7dhKAaW45dQXzgxxD6jk^o#Y?049e+o~v z9dQ>in+xMOIgNM+?Bqvd4P@v9)+3u;^rkXJ&jL^szjFmUYPU_wUmcz_sob8OVjiR| zcRV0$iaK9aE){2AZPDd)Z(WVPs#vJrk_EYs74AH_REo}5QSD~1WBe+H`+@6O@Rxfa zQtB|*sfR9G&W{)kCHiTzf2DGSThcG}cPmqhg}_w`N_t9%m6y)?&;OMRu#Kd%FutPu znwXTNJ+#44*Q$7M(NU*}v%(HQf&Uya}y4VT$3d50JIK1lA7V96Y! zq@cc(>$d9V#IyDj6OSAh9yxUA{n^*|2A7Bw#SS;iPCoX7zDA;Mf3DJcPAMHY z9~Yf>q-5{z-aLxWHbEC6qQ} zg67BBa+{6J#ZW(@cEVmy7i9R5Q%ZV)+r)arej+*fSP(LH-57U9EWJLY)Q?(bQqm)0 z4@EsLwDe$06arv2Ip8Gyc4zEYHT6oLbx}HE8ogYTo%?4UE@`6q$bY zTgB}R;x>!R=8rSd7frtAxIAXE7Mo)woj+o9(Q$)*#4(cPF z%to9jgcf=yj1+tB;AcIz?mi1v3#-u_qQkP#(kLKe**E!0POZwU*?R(EU}}2pymWRD zZu6&i6{GaMMZT=L%Y5bK{R?%QrhY8JQuWvCY4$w!%su7=NfwJwk#Ju-vU{XlWg4s6 zQtl~mrSfPzL62*_&7(2vwbd^6m0^Cog$j*#ej*3oQ^WkiE-eV^Yf^NM6X~^;mk4{- zDUxiP8jPh&RN7+Hu@*N^p`ZJ<898~_v5rQ%W!!w+y?nqhHq%CC zK$oieB;2iPV7gJn(CD<<<_MJy2Gdo2*+%zpE65UMDZJ%?y?2q~uDxgVyOepV){0Td z7sxfi7DfMq_POCPwKjk>2W5?`^gWb#Ml6^?fIx?gp>dE_qtETx!95$WhqSZ8GsXeok6hzrfnZRm%FM)04 z2a#H0csAZ75Rf{pP8_mPu%TkW0IB&@#>sLhgfAsiP8iB~BtAv{N%FnxjL#OMxB4@g zw4T*ve#9{FT8&O)mt;GIjOGs}8|HX2O$Lbet5vjzSAV?BsHT~{sN)p#17Xr(s=h;5 z%xBi~>HmFvm8s&UkavEA8k8;!EwJo%9PrGb|0F;YUIh9<6TM#pl%-{}QDu z={y|QF|bn1UHpPY;2h=Wk1DArc9)~`J3Zc*b2=jr_5|cpmZNxVjIulr(e|fCZkHI; z7o$B&#Mqi5u9TXf3WN;|PSf=~UY|Nzbn-mv$xPCEma=d#S3`Ai*IS{)>6Tu^$foy} zg4*U+Pg;J|-ch4arB!9~ZEB}-&KE6VfxGI&)`x<-hov%irA!v0d6DK3(t+u0NgN#y*y9I&1r??Sv7IjI{Sm(M~dh zyTv)A4-cO-#;NM$1-Hdk-oM6^ZTaB$d8d)6okL;l0t}=jZetZ|fmpvh|3yunpMT!d z($}_N$t^>Fr}e$W@Sgo<_{(h3Y@rYP@eKU?Hi<|UtEq>W?!v134_=u;e%8{szOddyeYWH#lH>Ss9+rd}2YT@4glHQ5B z0?Y1Gxmq+p&#Y58O{)XMbdJ!_VP9?mZ+L zu<}AWL*&dVWb;JKtUg|v-RQEXy>Ruj?N@V+zy3OMG?UxIk}WP2be+R|d#RH4lKAYo zkgoTtI+C?Pf$x60Tu8HQioF`|JeT&xvfukDtE~3QL?M|7-(1~taj>G++G-P56=p*6 zh;S{XBs?)uN|M>J>3w^=Si$<16)(;$^_Qop=11S>^g3HumJc2~x^Lo`5T6Pxq?J;1 zOuDnx(!N{T1&M~(X?C^=Rg~p1q@`?IcV*J5FZLiwHyZ_0XU)GnOq)1MN@63ODP+@Q zxYZeueww!DvFMj5F`I=AD|J=L_j*hQuTZykIaa#oqczUY_Zl^znWpO;QPZJ1W`~)` z7YF-f=F01v&tzgn4p;hYb)J3nzDqn?eJ+iH?P7ysoLTSBhTxR0RH`}7vhsDI; zRkZFN)hm&4@x|NYhWR7Zn;jr0 zt+BpZ?plD&pO~F-C#zrF`B>7~5a<{1xLZ6u>NI`POZ1(ow2E)sD%Smst*-ot^*LWp z%bJ)EMykjuJNwZzF5)sWZ+d}wJN6y&h!bL&LzfJGS3dFeb=cV_Gscunw9jb7Y0{)f zHHSp;h6U4d8S7fl9bU1Wy`r1)RP}sXl>GwC1kOB0#rk=YDEo7eMUXHS7-PM2EwD^z zX(xEuoRG%J<2g^2LX791d=%DRDm_M+|ba4AN?e=5RO zUog7ZA}q&gIjzp7tu)bMD|eEf472&}2LE9%ul)dSiG;oNtSOKZn|v`TdpFZd@^*Hk zMt;P@r6V`P&3@xiz&nM(UC&@4UOTT-gibWY*W1E%o$Q})_@S3lo%W{H-dq!{6yd(f z*P8Cq|7m^IJamXK%kh;@i-NDb($m6fg+=32Y9wOwhNS$)cgXXcV7OPO|%}?L!fA zNtn#R+;;byDMON{3)<<)oe>%3hcUthJ+oSGRUf3ImM%!d-S4?Kgte)1DaJ1E}5YBX5N+ZsW;{NqbAt0bJJ=QI~b~>+&;SNiZ zMX!Op#=hgCjRrRE=lb;0Bb>+4+Akfe^22(C(54TxMQgN!XVYAS9BEg0q(c&ExS+~8M6|3i2a5_T49H!j{U`o`R{{{e<3kB?3fj@ zjBjoXI+6zin3bMILYBiB=efg#^N%hHbKaRo$8wlU+_~5ZG|EmU#7`an>Gx0!N+x~?< z$Fhn-ulF+QL6zY~>XO63dsdU~8?-vzJj@Pt1#j<@1$ZWU@cMj=m@BlP$z*2dUXo+WDrIo%b1hh0UK?9pd16~uQr#~i zY+$LN~k5y8G_%RVF1sz^Htr?Ft?C=l8TCI#}mF;3- z^ApV5J;@og{6RFT=07txwZ=yHP=4!0(@WXqjy6ZLXyVW^v)0C(?`>peV|bf1i;3<< zbf?r_9y&#s5OeTg9!x(8wA*UkNT>>GXd*1YL7tDN#BPG4pJZymR=$21-F(Cg*(46mq$yr-(Q5 zy%tZ;NQ%Y<{2(W?uxX>EZ7Vzye--&6^jKq_a-!@SiiJB>|P8eX4{FL_$K-rIA#?wr;BPI#r=-Kf{u z_WL69cm$Vh}?DjAGPA02hHplWg&)FGTZZekZi}9{aOVi6JWQLBaQocEI zslTd7rB-ZXw7%XFnA;)Ukyth77i<_?W(bGJ9CiJa8ng7hkI+86ut0nzX9uZveI*Ga_ zrDJVyFzLYqMCFdPZna1G&5Almvs$Sqn&Qdy%#N26S7lUJTER_&9=OjB{s#*U-g zbN31F_HNITG)oMTe@K9R_yren=6f6do^so^>1g`qsE&U8Vp=)JMOcuw-wVL@~jwy$CY>V9c<~5 zaakSo?ENU%=*z;2IhQKNC0*X~Bq_BgDV4}aq3nLy2_p~0M8uY6kZ6tl-6jV?2`S=| z6X1KlcecR7R(J%v#s_<@IwOJR9*cPFlclM6U>$j<8Mn0pE~KfoKO zTbMlWli-BYtw6RXsdCQ+YvyK6*X|uw$!|E`gjHdrc-nul&`4$>XFIFeGKVZXU(td> zuL8Lb#|T(C+1WF`cghFFpTq4K$J-%2W_JpfJM1STRf69aJ+JPc41C1G$XC%Z5b+a* zXyi;XF1K3b%6R_H7g;&dMrNLG*j;}a2~76{N;d>sD`j003xg12aqD6It72*y$w32# zhj*kJ=x)8Bx{LogN(Q(7&cN64Tha|pKE?V=Z#~=U3XdX49rRZnDM}usE6)=msJSa$ z&ePYl2J~%oULy0*ZvK=7XIg(HzM|mk8(~Sm-xNfup@3R!49VoVVGmB95p5^ucOBRi z>H=1!g@tDv7tg;x*>i;SaXji7RD*Nh6H>tb>&3ya0Or`xiA8+s>C3za(?d?-Y^u&M77oU#qGI>;Kt&f7B>BB!kQ%awh5_`h;KL{~ZK_XUwmAGw>duZrM-1Td_xY*XMjp{MKB z|8&jw&YvGS$8_8W-OrGz0K|RH<;SV8Mr8l|`S@PpvVz>V3v9y6cryg@$Q70booxfQa3zw9WN5{^zLw+@~cCNtunI=-^p8EHux+_*wyK9oDS**miJWWB&bBCItRqESVo zidcOuiVg1Aou<}h4XMkU!;EUBEuu`zn6jwO#~FHUO%gPM4QaYAzvbgk4ZDjB#+K|h z;5@fA62+zmZyy|bKxINjjQ!sJe89Qw{=q+Cd;Bf@Hfr@2J+iS3oIs%VtmlGG=}6M> zz7DI=;IN_caOERaIxRASP}y3096MM!r*!(uCGGNj?$$eV{r#&)luJ$FmM^lT-YXkx z4o15bQ?&E%S;TDhRyQXGLBiRv8)j!|s*ow}z+ET(3buaR{q}5JrQ*nLdv^XD%kdM% z-@&(Xnnywf*>RO7jWMxAf_AJ__bvBG%POn14kR@Dsixok{q9LrN?8XL;Z)`J_n`-q z<9QNRw7b>crv8$Xr1IAKof^R1-|!W)r8SKf!#$*PbL^)uWC={=naq_fCy`VCkKyK= z|2>8t(fdID$<=j?S@`LpQ~c5@ze1MSsDi%(g$u!Sp<$#a&*${VzkU!2Th*)Z2kIDX z{G~vd=d@NnFB}wYZT|6TL$>>3GFP-G-vw&S6sz!~3Wk8{|z4d!t?uI)xcKy2s(+Lc!Do7MwdRAhq?S#47FU0L<2xM`b0Id*sD6T?q0PpN zCWzfzw08-Mb9MiKMj5M5(&5}^-KXryla}-h>BwT%`cxq9)HxVO%{I;wYpa^?%!uQUp7D9tivDreHtX|!XkOaKSCP+w{J;+ zl)xW*M%zcf^e5Zy{q;YaiumIMbjR?4xBWe^-o)2{dXsSKmH?1@rS-8{d*a{ zl==74APB}2tNqjd`vddRcUr)qiF+Vkrak8bV;YRffV;FNME{-b5_SNOktFZSN#c;VhV-3>e|DRHjpV3$G7jn}LT2<9p@@b>dd+dnEJ^)n=bX=P~_ zPRF?|)%sn6BocZ)i#|xV1sWAfN=g<+V3~sxKk}G%ygp3=sXtPZH>HkK9e#%a+6Wq3 zDn9oqikE%54RTj4x>DOAw+hOp*;Nw(qct$|LRJxEpFuqxw?bw736tmlh@^|5kX^?D zc}3^KE?h*Ra4%oJ1R?``DyR2TFCQN+?SdcW6nMGH%D={CjYmm+J~7vkERU`7fQ%lu zg}&SvNa_Q6@5`4jt3nnVUL;aQRavM^y>Zwjk9r$TSKv-*_RltE01%68NkyDKtm%HjP?W ztW=YHHGTIZ*RWv(l8+(b$hGvv@ok;>=e8bwy!{jg{OzGV6nlhBPl}7l?|TN`IN-;L z6?YDKTq60iD${X&0c)Uiz@L5G{?RQ;^|}t-YLIKS>39rN;H3GZ2wAz$0C|h;#E&mu zm^*pK$Ht_CXs9k;99>MrpB=+5eS9TWY9WWY4akmF{B(B`cwe0t3ws}S((szS$6zqU z^Z3bQJ@Q9$ezpM80;qlt`QpL0`a-d-PFRm(a7ds$$__xkxdHmUJihaZgD8zTM1h3) zJ;9k1%2KY6??olPe3{5d8Is8J_?_})Q+<-Z-=#hXXZ)M-`U7-=4|&Jm3=W-c*x~6q z@v}M9VHa*ph+*3@o;z(dql`_$?56mWpON6vc}m*4#|r$j?Tfyg(cSgww-?S|g(*5Jx+Pu)Y)&6d)-NXk#e!@T2-tndx}> zDGAQl3(1BlD=Sym)Ih=3SSX?|8>WzwG4n@UTxE-S|GoZ#atbr!1kRuj25zK+=Df0)SpqRej0`ynuf9kVmmq%PZE z#9maN7*{{QI_RyPhRHL*RCkOu9(#=u68G-i!xJW=79p$9)6>)5-v0D4+UB#x9|J>` z6gd0Z=Qkm{+X7}ItV~FlM!{lfisaJxSO3i|@RLWC6cUQ{OKm4X%9S}SXDhM3e*OBx zEv>Nlc!Tyo(~I|yH4{+}1+Rb?dvt6JXk9k;Y^#{?4mUynAG~Dh^Jj*J>}AJBkfN8# zzbBy9e@w>zzQ>Ok0l|OA;s5tIyu@*UoXnmfe`#{o?Ud4Gc=-i#FS4n)8oDMfH^vJ>cQ-T|`tNM?nSBK5+*y@h+~|9y{tj{hA8{3!hIjRV`I zx8eZ7VvtpqqQoob&kL#)$7+w@eV0F1RUgpR0E1#`YAVQ0Ja`Lu16A#h>j^ZzW$ujTQAxGcmaWvTs5QnkAass)|7{*b28J99u~cUsNvfxPXR|SmT<#EgU>_UyeWI{fDdg-}iq8=)dFe|7{#_I-uxu z+piO}UD!JNnH63a%1^RIPROX*OX07`MwNYR5FcMXPg%_#za|I>4p2`G4FMYx4=yP1 z+QkDO1mFiL^ez(o_5&nb0nmAaAQ3+cerh<2Vts8b$eeqV-y)88I0$}xhkBg=0s_~o zeb&CvtUF5B$qHOjwlY?LP_IO;AwRI|ZW>USU30TX4#^Ej}XX}a`^hsU)N*cG4xQHEI z#u5++3J3{#dwKN@4gv_4kCpWWz@NM+*~>Vg2Nd99AL#EE~qG_P;#g(V~^0TnQ-Kz&>VC0H3Gyw6eHl{_076}8u`VL;)b#7FS2 z2x~|UXg0vlZ2n}4$J1v3uNGiL0p_VA1zVr2!m$dJFw`_Ox4eG8Ci-0PPh2*njncsV zF-$8U=FZH_dfBb!fYCG)ZLa~tNVd3HQu60lqRs6UJm6B{)+{!xmv7DTof`WnaPOIDeo$_9I~9J0!ilC??8$J2WSvFuk32@O$!^oWtp zPHrwPJP;A({RX7SIs3 zK`E4({|<&oPtY~qbkD;*ao-FL^wBm3SLw0uI9hIOYz%1S`TqQr(oz>dWW(}oixbtc zsRN@sgh66&YjGaP*L&yDx}|F^{8$KcQC7{*%m^4YzE{uEmJPFC9ji;0j|56S^(Te+ z;UiGJ(Vd}z0W5p30qPJ>1$g!LZvd*(qYi9LsY98U*xxob4i9?_mpSZjFCzda4e;H) zU*&)Y6Ly&Ef|A7(i;JRwwu4w)q=9E?LB0~JGut^fpDP^Nfb?tq#GL{GMCkNLnFFvF zBHM{>008}9XBCPJw=^`Ev?odd^|_UmRdOr|?yiy+xZ}n!?V*$Az%mV?IA|b?H0@u* zW5FwXKr!O)WxWjnRg?7xv>t@j(!F{Yap3zd8(+)e-gT8Nc9s$6@j$?D;)!h#sH213 zb?75%KC2jRO0_z;yrkqDjleG;$rTpfuYOAcf@nPMOsX!de6Xn=mpd*32vl^>3YZc=0G5*tbiv7aTAD-LZAWRFsJGgN%o$lCJhU5xks|H z7sY4n%K$P60Qn8Tws{lnZ7*X$%mXr+h+)IE5|%YYLMgfQb*r~vWc$B9q6V%KUteE9 zyAl!-B9c%4)mR4-8q@~e)vGUdx(5baK?|@&q<{W=@9Zi(Eq>FE2^b3g=gwiwE%68p zOiLe9S~l5n;EaKbAUnSJi6;OovM=96QCYd8^Pf_Gabb7kBJ}{637|!NupieZn?SCC zbewLB2l_-jYExDW{~5x(WBy#%T63>~r3v3^QYTV+1yJjEBVUtJK|jz7J3d7By1Ba6 z*VV;}c?>i)0Vr4dx~U^zfbnr9hz^d8jiqa##msv$0jFx?eJjoeCK5mMC2`-13K3wj z?43W40kCjKef<P7 zW`OA%@PTxqt^lk33Sn49BYdF?0s`l#M(0VdhzK=MdjQbZ)zwwc)^!2+DXiPcsVRt} zeV7;rj5#YS>kgQu!0^oIW$oltoRh<41Lhz%cLBjGE+GM7u;gST zS+PM7r!XS{VJyJG@hI#IMA6N7qN>L$zU8AKIBIHY3bro)fj021Lm&z$dtsV5EcDrc zE{6u{19)U*6%|ny=FkBF`nyZ3kwS)BYVM>j$0!qn0!*}dlBY*CWKtoGdNty zz4PZTeW11XoSGL6$k~u%w87n%GMi%Rl&kC zJ)%ZfzCLs;#dFU#YXEhKZGR24)1f zUq%_HocV5ECeBhfH#9UfGJ;s+g{xOtWtEBI89?d!!77AkFF!21a+h^upcR#tuJ7c$ z%F1<;kQBe~1UE};0Jwc1trUvQhU_8`p&-xUW>*xyFrQz-VlYsJ!T$<}5V%&>)+=vG zDC4vj@3{al8XPEcaZOE4(7jjnLCYp9Q;DAiPIVybuECK+$f<>~PZVe`Lj4DTuxmiX z93q2+r%&Spd}*A=`h-AHma4`N<_!QyNl5&E{rUw(J|v~2`UeKmRny5w6mhVUK?It@ zI@9;uodkq?Lw)@c2yaldM(k&t&p^-R<(puqgYeX;o&9|b1i6J`ft9qFIexg%JW@Jo zwmYLY8d+s(X-RwSS{cCU*QeVMi&3vwwmamxfOypk^fexf>wf3vP3Xa==x8vvoZ<2y zDfPya>>Ak>HsjJDE%hBVxC94Cg2YvkysFw z+aqpVfB*fhtxXZ#3*55WIy&>4dr&k3Y{sD>U25v+zCO(?b)7Kd$Xi++Fj-+0ZZ7n5 zgM@_bmLck6J9Gut1m1BE+Q1;+_)!fSq`H{h)I%azfMSlW#A_ z8-f)9JlKbYf@v|Ipyby?ZOhxa@;k5%J39M52+mK@wC? z;FT7?)ljN>)_{Z?&B{Y6n7&Xw;QY2dxi~Og2?z?l_4dBzxw*N?%gsGMQdvFd22Gh}HZGz?InUH>v z+pvO-K*J-E=x(!4=xum7s2SAim=uE~2wKGc0yh!~43SG+>1z0*1j9~Pj;BpvBrSpk z1qP43eF4mr=;%Q_@dQvYh_xjD754z7henomL|j~UHxxoC9MvWS*J-vh1?Dy}1MIfl zg$gfV9hvh)!OsJ!+LQ0EPhU4J1+j{^EkHeiU3!5YCr z%+h7%06jb35Ws0rrRyyBMAq5Gr8`Zf0Zd8+0tfer_X!?8bPsz*@Cp3BorETj%fxlC zfws23ejWpl7;dKu8~{)kAT35mN3SC*@TvrsC2XTYpTT5>@*<7-_Ma=jSxJSjYG>TwFDj1IfwUjo;B{j>nHs4quAIJQwcw2{yOE*fV3JuDhl6AyYehS;0;Ffh`7g@zg=iipvFgCJ}js zDo=IB!y^vw$uB5Deh(_-Ij(1^AnB4hqI*?$)<-p&c3(s|sVMAmkIUkIxKo%iIa5)9 z^_{Aaxgvk0boSEI8(uE)24mT+$fvG5D;u({%gc)EwBwAT@)8k*Lk4=2X%*5EaA8w7 z^%|m|qp>L4jqSQXb%=tyXPn?5glfS;VMc6dK zid?(9yzTZbJ7+&Ke_518_AEoDNBw~-ALDfvcEj zlZ&5CwwqSmmVO=+Ww!AxOZBjhYB0O@i_zCQ{XyR1a{1D8pKob*x+P5V)!i>S6R4wkV zRBWWQy@Q){5YJ^Qb(riXzqmV$ZnNPwHoT|IPWn6gpA6hi%99|qLQru?&}THu=_KeI zhz;w$t=#r6L~?p0-{*}s8yRmcKAMXB`RL&}srP|5tafteH_3E_`nwnM1onrsFco?_ z3|@KdU$9kfM-zkR7cGYOk!iWsk7Qf7|CI}{9>X^kY^pvgv=c4WmLe@$QL-z;(p$c5 z1aIAw7#WGRmkD%#RdQYg|YwHlLPVGwnE&GOZP=V*RAv1)JO zUY@?~%x$}EKMFBZr-1E;$>|=ERx}xhW#RsX5>2zC=%b^Wl{JC6D37Q8L*b&4Ef(9~ zh=#-Fe{@HWv>LRh=&PCgoQWOLtC|#dfhUzrd5C{fFI5YzM9Y77np|=y8yY%zm;LoQ zv0L@F51Znr^wl3Oon?{6{4P<4oBK78nyjRiI!~%yw(P3v{_L6igafv%tWQon)vW5E zKR%L?JS?1tp#epQ9kA}|&fL~+X+djaE0xr`_cC6l(z`_wC0Ld3?1jz_d%HU^GK!A( z`D|WJ*XC*)c05v$Q&*SkN=6&xQHXzZt0;5E27ZKqTgW&fz-;fA>|t1qFz!oy)Y#)M z@`gQ*t1TrhZNvaJr)?p1F+RoGnC%em?Gyw`Qidp-2$O`=gsKGeZ(d@kjZ{@)hQ z^}`NzP*TXf7hT&vCk(@s!>bk1E`v?Cc|t5aMsyrzjCG|QrNw_3j8ory8?4sY->3J*olU}8UpU2xe%zl}d~UGEt#|0Pm3KrbwODfXVj zVBM=#%+?*scdp~4FT^!Aa&E1Ct@h~1?b2gfSkBtNSWd3^Xj7GSUQsx<#3OZhcoVyd zNhrp+%`6GLZMnueUr{-}w}dN3@WActR7E8W- z*~zhsHgR-#OdL-A#;Dv>n6qx;1@~BW^=rP0+2?m&s5HJ+q-K9)C9=(#U2K7vSJL$6 z6TZWE>()-&_ArIGCW7CrJM_sTad-P~udbte+?spFU?a3fG!G5s6u`#@WdJj-_`US|l1cH}JVs zVEv|PA=tNDXBYbP$*Z!($+S|83e7>K&veVTyvyQ3k?9=rfbGtd`D1VZv zr^4duOU+`MyLpxl{(n)21?UStPHsczzIB=k)x~1t7xv??NeRbId3gGb2%B_uoc!w! z-05Gawz;WJRQrf|sGsT2rwtgl!XV|d4E=?%1xL*sFv5vbAFxOyzY;NnYF1Un#lu1N z9;pFk-u(r+Jp-miI;~LYvZqqW`R5ff8^13sOnxQXJQK)o?)t#!N&j@@$KOVa-Qs5x zJfFI}@LZ#RlR?bjRc$wyHh~$jtwIQKFR#mQjPx^s?&D=-;Jv=rK_9N&e+A*sc78;& zXxr8Pnewyd^H`)bPp<320!^bWXUNa$fXhl7gQj~&d!0^q3$=(YK4ri?w0QB<^_K2} zW$gPnm0$y{uHxm_CmGVTdND7O?;c5=^*@8=>bK(+;t=M(d9brkG$sC^NGwT%o~VbJ zg+*F_*Ze8UDc{XMfBcYA8t2Hs$8OnREu3Jz#AhW?M2Drura$W!Kt+j% zk`h}{IJ=V(?^zSR143BlZOXTXj zFTIkD%0Ma1s}A-wcIXb<*Ux&fvlDg~KmIh>ZK^paO+J-%MYo6MQ+IZma-M~VP5e~- zm{039SDu&)>BjMT3OnnMB*?llYu0|xI2>9oI|+L^v~@ov!nHb&C@?hZmUC5pj5R57 zOKW$L-9j$5wvr8QI5L^Py`3SrQ#|++MVfJgD9sgPP?LoF)Y00nYdP8Rqf_?!w^!+zs8t+sF%)6X&+WE5t%=(e zbBcZ+Gcp*twOn$IIH?6@Y5I4 zWL07H+G(Pc3`}heFNn`>{w(c6=<{y;Z1MNHRL>u`FHxIbZY*Tf$x5ordo7yEDJH zayXWG^TL>;KiIW>(fimf>Ea}t&&9DkYIfstk(df;t<+%;R^jddE$T((rvaBomVxJQ z(E63{IB@Y7-p=5*Fx1=`sB#P&&Y}HjGR>18=JkB3t8eh|dxEzghT6$ozo$iuquGoM zOCB5UvY7I!u;p!{YcUe}h5qXJjZd69kC&4!nF?bIO82ANJvzG>!9ZJ6NwgLpc9c~z zex|CbtDJXZXQwPJHU``n+EtB#P@-+Rh|e2)6S^QI{Nwo7`-r+MDG4W&X?7=Egx}_@ zL@h*zg}Y8=WVf0nWbf8{3lmWr6kbd$(SMgWyWsDKI#+a4JALrq4M*{2J)QaZ(P39iWTCuO%I&5xhjF|-asQq5i2AK<`8xyW**n&GMwpaE zg-*HU=onRKsYs-|G4DSeymV;ndh@MPp}u_!E)i9WMr#r=2nG#=yE}_7?z0$E^*kIJ z3DzE9f7_8T->cCXtYEA0k*-jyz`$M4Zl=?blr5oP{nL(<>PjP>S_TE8{B9uYLki4F>?N7BgHw29&YSSY;xlUUQ#~S`NtG*Ej%7nHX8li z{;fs)!4~>}oGy19@yL=wd~s-XecUE;N)*Y7_h`t;liISWhZ`ZLUj5LPu1J*g*}hv~ zCiBn4rQe0$cLjsJFV#25Eg6zAkML|XWw-_pQt5>}WsYGL;z~-o`gE(K?M^So`Dp1G z!s<8Ls$75-F}c#vHh9ykI=h=ihTMviH>S>bB*(6;zPn32&-Bi;eH6AK@O}N3`M3nf zrBScd`$L9==HNKZ-sy<#93iSu%W4{ADsvey3zy&|WSNi9N0XYmkIkR1YIhNjrz)6T z?{?C^*4ApmT0!MTulR)L){MSWR6w366jd!9saksP_ zg&t?Lm94HvF=Zd_xgp$j^@goXeS56m47|=k3Z;`|TlQV(GSx(w$ojHzoum3ZvOD;y zU_U&%a0xr;-rIp}OPP_>Z^ksCgiK3#1~)1S5~3r~m`@3pTtds8VlOVySrI?&o^0{# zpBLMoD!9Rq;NCKRp!;fKqj6BQ2Bn?D!6RdE!O41)zCHGgW11^!)UI_WE_3f$!=9W} zmYBzUjAq%GZj;#X0&}5a+bxzUrpOkwAO~PAmyEg1Kh}Fic&|QLC zi-|Q+Cmx5`Zw*rHcW#QGed=DQA*vJAPo=s0@X$2T>Sq9!(Lp>u2embyq;A0ON|ncV zu#?*tv>dQi6zcU!K4q33GndNsYmP#_=ZfGbEhny5-6lrHMC|75KVRg7&8)a<`mn2+ zj8A6v-SFL8LJy;qP;F~iyJB!QcUjdE^pl+r_~w^exH$J2tb~zyVqqc=rg(3yuvkKNvnWozF^xYzn_Mb`O|JX;gz>|gctBX&2KY?kL7__;Ut zHrU-rrMgme_O0RtaYJbA5p_6=y=i2XL4_X97U!sFogMr$D|hsFsF){~Q{+M{*IIS) z;YM+n$rE9Ro~&;#w#AmoToOJ==?|U9!QXPI^h3&O_R=Xy~g=xLt@{3d)dZ(C*2NVw0BOmidsP}we z%y>b`tph=A8w`$B)anF-*9Aczl(vhQ6ieQlqt!|+Yn#Ju8J=B6gzYkdvSqHzM%8!B z^``OpYvnShP8ml&zsM|a-UR#4Zh9sj>c&Mz?WDP*-Ch`t!)qZ4y(xM_c07#JeOwuw zUuGl~ejo@>q?h;RUM`#X{dwanI*6{XLo0&9V^aHlLg~S``S0CO^V4+=HBxtaSh%ff z#G>a2N`QHO>Phj!L3i7@NQ3geqSX&r^SKDQH3*Vw`|bVJ>GL_BpXM=|b{vmb)_5DL_RNCkS4OkW>%6vqw)=&5`q|yP zdFz=%q%%$IoTQMc22N856$U;49W*%!CO2&2YfgB5^PeJNTb2+WHrK)7X#LU9V z50mRQ7?Uh{BBGwFuH14m@CDx=iHA=k{G;s(dp*l(sgGM(dP;S3XZ9A^RXZ-TW6#Ex z97{G%pB8#6&Tw-fhPJ!i>7AopM5|S+S`^Awgbg-~`1t02OKzXAqmE`Y^xYV*nihqp zo3?6;-DBB0s5DvbcJvS$>|WkToXkBrO+VK%-@zMIy{Y+GjrFoPYr5b-inOHhkcS{Y zU%mC`;aan{TXhRw7plv4zhvp0F`(mio}~y6{;Nrt8yBcpO=wZ-D7-UN|MaI%(2Zdt z|6j9rx$`nKwMO(*e|9t~KmTGf6ToNQzt>6cqrbb7G`w0zPpDpU{?n21R1|JWp2IQE z_H*ZDPvAh$QeveD>uB$mm6WL;+VALOWa^~Vjd^H!u8!YeZI)uoD!XUN@aUZ{Py+`B zmI^GpWPOTw)ZU^ux>3D@bfVc5o_3mQUN!QtxE%KU#iPj2e*Dc+=*}x&nExNf-UAxW zaBCYLiHMd&5WNivM(@4EL>)DQs6+Hl^j;Do5j_UcBMcdW=!}-AK@bKLU5MVIj_!MM z&Uw$f&Ux3r)^9D=jHloCv-iFCwfDX@YB~p{V`iIx={)Xis-W#u?J@z%TB3VY=B5I* z-Q$4;iyy<+Mnm;?hJsfTtqfDs#@Cxg^ZeH8Wj0dph1Fm93(&2ed@<4Mx|sRV z9igR3hENR}zqlGd?a^k7qQD#+AMGZ+4rurtD|esQ}3_Vv-8bvhtJGR21ssRa>e0a8zkQT z%3}KuQ-+<4G5GlDdtgm6Y&mUpJ>1Ei3BG;bX9L@ZQAzjfeRZ2i{@@b{0vfkGo4@`UByNx(C#k=W(MmAC^omFK%sEO5^j=6)$j(b5(lLS3@>3SA2kof9TkY)c|yt z6PXY0k#miQBfkKO7(99_D}eJR5$9^WxXY~F^f68D>7k@0El}#>>nrP|8Stw1k*Sva z>6es+@1}8A9|zE=ofF2E_5x~_Exf|Quwhwz;`nQpS{H8Rk2=I)!!pBu&h6uw?I0)C zjwj~_LEz4o-53ECs`S86C)|_$3VLQmjiZXtdT-28fqM?_mF?QV*#(PuMU=O&o>Y?z zL>Z$)oL~NU>H#nKt1YRaPYeCrUoqaT^mGd6KVZVhFMg$294ya~c)G=eZ?$v}6G*3!)M z=ql*S!iNL$BTF>TxywPR2bK%#M#%j%YcxG6T{>kl=ioI%4l`3jJ1MOv9pFCZD zzG-P0$iH;sa5y8Kb#0N+M6^iN%~V_KgH0KOvlShL+hx?VKPFzAmwR9nHmGjJNh)+P zLnBHP=4emi5^Q7=yd#M!rhpbV;mXm1>M5CV4cR7c4+k9cy7oYp+Lf?0tHtnXXSa$f~x3HGJRXxo$CuT!`weVIx$Yl|cbToYg)SG!h*Thcr~~5B*4B9oRzjK;M36ZeeId?+v;Be0Q{- zO`qdpkQ`N5hj$$t?J|bI#t^Va6}qffxScBry7R7vTq{Ni^YG7-nJajl!d66Lw?uVn z)Fis2aG3cP^AY9XMtNL^+0hebX$RL>XTWDGpXuz->D<2DdXFm8Q~#xa^<3+!j{dBNUoYO#S>yH>8p6#9sxiBT(c8CS`86(= zd7dq|nAP=5TMDaFO8hh19K0>tJS)OIC8kCufuE8$F!iyfp_9-JX-i(0uX2_SC^Nbur+ zbxHkcLZZkQ7g)T{Z>D>?lzwN5VSA5Pn*807dun`teJ6v7pbDveV7%$!*>rBg+kpAS zmm9JWg^9^h6M1hi1i)&TW;Pm;jy`DI`NhVi%+3(QrWJ%_-?U{#%RSVoBk!wj0aa$! zyCg*Mg!j?gr2CNlIp6Rnq5hZQrqU$gXX*aFXMSm;xxlO6Em3dCU0Q$U2&?#}=s(R(@n*6@ zz@*Lf8S_gaVWl-{oMtZ>Nwa>bXXL^*&bw_Y$vb56cC2Laol*}-M&sdmK!|3W+f^rW z^+W7gVM)AcaFfAfV#MT@rleSqw>OFc`jJuWNS%z7$BQ(1q^T*zi|hrtw%b&zLwb32i9+e5Qkjf(Rf&llv| z_?N8xowS~QQ-j|LM2r1>gsDi$>N#&Q-7~qm#28*Ia~0%O8xq%IW3k2fgqh~G^Nz}# zZ&IhYyDO5#w-0OnLR;ya39c6H4i#(GM>}#m7ne1;<<4Nf_1g@1=avPJI%j9<0!^5@ zXIOa#K*3FlR*v+H6|mu~^VTD=tE~f^IN%LR4}U)SwO8W7e289&&d2N~@-;*3pKk|h z_>CU&TG*EWGL9<-voO zTdWlqe)DHp)(22WkMc{$$0Ofb2reBGn2m>*H(85W*O-7zxl5Ev!IlTr$B%W?U@|GMv=wsp5f*!fEyUA1fq`pmE&l^vOCW?zC4M@QUkYL=_;VM@6 z>BaJoSBa3~ojir#rK8EgJNJ8DZ8GN_oq0&!ihTF>duft_`_!>f8!W`e=_wS|cI}Cr9%b zy8Xy^z|*+jIeMIWOW|Bn0xS$!_>LD;3%wlqc9<*!j@mw2_rLP48kmgueemu2PN86s z_t7vP)xdI5x0ChG$bEZi$LhD@yH0^`QNdX(@>30F8c<@xMSSrQsm0+1NrB`sKm1+a zK(Sf{Eu(><+@D=2W{R=RIOpoJaxZA+kqdYmw4+`}HLD;j%)-hcvinMo3 zzFxWg<5rK_1kc9iyL#pKwpJWMp4{kG+s+$(n0!9;JFL3h;$#VCZW`2=gLRqpFgYOP zL>#d0x5m-$rC;4>6FqBthM(~nTy?j7qp&}}{q1h}4X*ohC&7;G=^k1WHtbZvPg^pw z0CdwmUa~E4almabkBMAUM^m$*F<5C%#yQ`QwPEv_v9*`E>(Bh*HA@|1&w|xSv08%k z!AQG}6n{Yzrdj{s0O;}Zufcz5i|KNh84!5oX6!{{d$KOtQ%11X=dBw7HqLo>@Thf_ z%cY9h?7)>VW-BxroE3aSi@EYQ>^TMLD^5g^uiN@Z3QkV$9KhqhL2&ak8KHk z(!p1!x)(j|NhE5Lb=B1`37QS|XcqNy-haDd)BvLR6dLHc@K)Hx!t#lGfNgzH5UIx@ ze*3ad*83{7qjE4IM|alu&(&Gy^@@9EmpD zoV#21dSuM%6?c326@#m$Fgi0y!Qnx3>9Y;Ld$LST?^IlMoy*7SCT-1P`JyX=kAsJ9 zUCnKnC6rxmo44Fa+3jPzI@UkkdT?`6_DIgNzx)ajz=-~zTmby+&AHw8=Y9Aq`+?fF zpP$3VnmjJf&c_m4oOoA{yvu^}oDY@oY9E`}0bB?O`;K0}m}K3aIs74hv0C*^=P6ZN zW7Y9NOXwtd^xw@slfN0V*F1*CXdHcK?WG=+avrV_Rge>?{QDQbrB3ZB?~R zg>0_WOV|$rUL=$_N44QDC}-^FOK(A!vjM>;N03)c|GXNg_2kvu@zOhwi=7)>ja{b) z!VZ^1I~Mi7pYQN*H9Av3BjXTKE2o-j%G{tB-OJ7E;UTlZnmD{5BjG`TCj*g8OdrEJ1 zvZ&HOHWBBbK7XPDp75WW|2}IJ(LExre|-4&AF+=@QqTYW?eDJnN-CcNng8oJDtn!O zJovv)=BQ`&>@V>4cLc40oJnEwMcb>J|JsasX$M%T|F|+24H09=oFe*4I>jOGpZ{ZM z|G$^~-vj=2zhWQ1Ma9tOta(5Dj|cdnM*M&8#L3~5@L!kv=g#?wAIual*Df#SKhTEz z2MyW&u>wZ&KTh=jZzNvI|L1V!=fCKR)_o@xWDDQ-QuE(Y7+q8H>O1t;;uj3I9|L<9 z>24oJz8tBwR1(AKJTAcL{e?OIJvr@!YdJCgnQz^c!Zr8p@kVWt+Lk>Qk&f9Ij71 zZjleR?rs6Pfk~Sn7{y(Fb#>JIk&5Y@3BOnz)qWM4Yk75iht(wAh%1C%j8fRV9)1B& zR7P&>b@%-H1^CwsCev}?DS19DKG0RGd)^=J)~f;fk*VK>@MydHV~SSi^;`EeeA8a| zRT;1SMVTrlMu)pAw7&iuA!xN)@yh6`OrS0wc@3!1yesN~apR0IecFuwjZsOR1^UJN z9Iz^$f79k|-L1X)Y4GH!P6IwaZ?0+ICGT>$E_%P`zlPk$-ib;uZ~XVp@fMkxx7Do& znVGx0L$ki%jWcl6PA)g$Fj==k2+z`X=vp3Y&@P?uHR;VX#jDaLE;SNRKGHWUbvRY- zVAMa%t4r`|k?T)to4MT5*Sv6!%c+X%TE;c zJY?AqI<~2%-R}g+M}!STdR(ri&`%6cKd5-Oyn7dfx=lJLv zz9Acak(Uy-7rz$7xS ztgJn|3m{?(&kY$9rE>UhgOa|z%Mk534K_6ml7AtG*-oWZZ$7Ki>GI_d-E=DJoAO7k zT&+D*1sU&;NydeQnOSJFj^pQ*w;sYFW16v~|K~BOWq0~yJ4 z<$3SWoX``dAonHk@R@Gau;jEqKF(c~>tU*d+(qnzSGv!lk|dTi?|eT!yYjvAwl7?G z;C>w2rjU`T^H41u=n=wtwq?|MnV02OyY^hL{Z81?d}zPoe#K7;#((R#zgK5?VX*z> zY~kFc^*o(+=jUfTqf%CS1^02glxU}yw{#UQ{5E3xL@G7vXRgMY-p&wF8eC??x5+3y zd$E6K@#g)Y-Qvq_#cdiW{OA?SPZ;T}W^xfv;A*Ad+^OwSNB8t)Yw_iZn;`TCqcz9B zMChM7>XE)3o>%b{v41FOA&=iXNna%_#5IO*VPk=Gjf#+kgu9nJZN5vN+Qu+D(qBXI zgfpKn{KJptb^FsDF!CVo6!zUzX81w{N4o27%Ic7O2psRc@>i^zB%a!>K{BYyON(;|SOdYz8ms-fOC;y5{=kEgEOZYRC;BVddP zH4u5p>gEjb*S^s7m{{_qorRbbMUjifO=V?Oh?0YhdrmZSa&9uK9R!uyMd?8c;Vp`r zQP!Cf{K*Ys40chjzS-I+xG=HKQbbP%P_}W1vs46-lex>I`U)T{wRpYtWWZxEPx0!N z;`uM26J9Vw9&L{ALZ*ahMm9}694aw&6pg(o4mkP{^_fLs6PfhMYI<_?z^Ox>cdYMc zZ21|?!GSAbY})zG2sb6;8fO7z}-cWgFrYk|K~n5uxA^ zOIY)#_xTZ&BAk>be%{{4ORfl3C%QHlH~x8_N?9V55egelo%qVqB3b7uE(wt9hkg3e z%YkX)0+jhtoBlH#seS6$bC?Vw_zNo+Wlu=BCR*&6L!$fV+||Wgk9DP{V2ck>#2A04 z0VqfV($%LXCZs)P<+6dLXwZ-dRjrR6;-dVO?yZkj<3@~6tl_s7JoJKmWtdetLGvQo zrM4nhOK0+B-{DX=MnQp+-k#2_wQb0kOzB6PS%l8oC)+*Ev3PZ(B6uSF)Gu$S`7XzO ztt#?I%RplO`FMS6YOk$(^KSQ2f4ct}$KU?MKqpRsV(ZUdzu;NxT-%C@gKXqTzdl;< ze#)=(YTXmv-RVD8Pn5-E`ox&QM@{afD<|-Ag`K#h{*+!_#%|l8>k)TBw2qnI?DL%5 ze0A*~ljn=xaG+Y1^3-mUPRX#)zGn6`GpF}ABQx{m4-3{<5kGHzEEG%L)?AKWy9t_t zp(d*=-Wh!*CMo<4W0rKSrjwnk>NZUy{JDZr<4K*RrQik+MDJ!SFKc#4!f-wG-5h0Q z{JD~y1yaO0pT6d4hZIIq{rcgp%I>Kl#=u?MTUVb7a|qF*-~PtG0K+8*eVo|19*e_LX47sN%vsGVg&IiYq`#BZsn?S+oY>zqN;g zE6d8lvxq*#4WNle9~pI8Z)l?YhBkVJ+2gb|?ick~%Yg5&Dv*PK3L~KZ6 z^@Of+fiS8H7McWWS-`XnElrm6>k^?-IFemwq(nPTxcFUAb~(@7$nx_+f9Fv{`|RDg zo!heyb}ia#dI^TF@?X3}^mt*dD`)EXqd=gXk;>uK9?BSUn;pr~4?iF|42f4J5{zMi zLdnMnhn29NU$8N?f{nWop2MpsU*Gd0AqfQrx2>t;c*+lVp(Jbluko9vZP1n6|C!68 z#>wc7!0277h{LXh3U z!Xko)$=*h$U{pat15Evg3Y|CecdC9B3c8?qUxSKMQGnL0{+pwY~j-p_L<5om# zIwK9tuuzQN24oJo{)OvzxvQUt7^WWXw106bOvGUuBF3P~$sLhDniIVn#$H)vX%d7? zQpfFQKXkexeXxPl(Y)W9)*EH1V1984+}4QiMA#uQ7^tS2{%qB;&=vc)#U?;B`1IKV zN9 zmD%q>VwHrD=|?}*=m$CVTDo}+P5ScN#Abi;^nMU)e)SkSSpR8ATs$5{4O(75c#!>CJ zAXbK78AUS8IPQW1u=}$B+aiko5pXIy5&s@*(C6HJmBwj{DH_}~ow6n9 zkUHA;X^PdbHX3vJ>FQF}dtCUuTRZU;6=}=w zVWAX+B-;C^gVTG8Lfp*bwUxifyDdmw_(#saajwtXf^ODq<)56r1Jt!(*lsLP;Tomk z2UtIEaTPNS#Q!i495_>Iy#ggo#)lxG^;Tthlp^h7wD#3jPv`A=0(tZ9#Ij9g@BC@@ zOjh6eDl1n(GfOKU3W)}tr zO-sTug+V_+(HepIJJ-LkqTtel{@LdZ!}qM!P$KAUfwoS3@LJkkng_3iXw=sE3eFEsAsc!{BNUSICWC=j2LOUOpP#$Xj^$1ETGi zse>M9T={f;xJpfHTG<^wp7{(d!!- z-{m@h(i+!b69r4+7k3yGh+oMIHv0iDe4o$hy0I%Csx)#QNPG9g=SRgQb~zh1RY=C+ z*^{-40t4B1(a+GZ*OL1u1*va(e|}P4$TcPh)sgO+Dzvq@XVbg4#Jgl(1B6#U`X= z+%o);@aKn7-jk3Olc{Gf?zRI9@P{TSyj7dLcO>-|{#&z_lUAL0-uZnSqXJS=l? zffdYnN{oD8buq&ZqTkQVW>Sa9-jFJ?B6LRy)2BM1N?wr-OrFe>&idWcmbsaH4r>Y$)J? zE>-Fyj*)O>+?+XB!@j!3=r{l6InZkvVES1Syj&2Zj8R5|Whp|b1K~V-(7$QYotLPwy%{aTCS?aO=sop#F8CN>t?r8dMqqn{LD5m8z&=0;& z738+)01b56*|ZA1MiMa&d!Ps7x}Wc4j;36JAlfi4Pd#+xTC2_dqP}_F1|2pT@I-;Y zwfF7wM-#kGn&M_sU;}SOK(8Ub2G}S#%@;@T9_(>M3{po6B@_8n&EN1L1k9nmzi#0C z!S3G6fO>;TnVR%#!)j`R)g(UUdnog?A=;>S)G+~Y_qwf_nU}t2ALp`ep9TDhDiUWT z;wb!b!rRECTP%nb0|iXhNgBDxQbo|&5Q31`pzZp?>(N>X6t!QXQKQ^*9>SMN$-yRk zX-_vx*8R5=x?I6&%U)%zSB_{gK^E3W-z*@s>9AMkMm$}_8I+0Pl6L?haTWw;Cqz4i|N7+S=gdXpGbBw}wT;?^2o11GUO7Q!|Q zq+;Y5IN!Py~q=kLs zOO_dGv=Gv`W2x_dYjP_vQkwlHV4P9eRFWiryWjDepaE1{tT-ojM`|!aLAH#>w2YRy zon+>2chR`p&b0_LK9|ZOUs)86xbfpgWU*-4@ZlRIt`J-MzUx5w8t8NuT5VBw!|tbc z4k)hf(;|zg0Hx>42KLm4rn{MEXslnLK! z5XX8y>Kl$Du&Jl(w$`qePKRxIXX7}M1+$94c76LkgV@x**8w5gA}3WlX9y3m_^(e@ z)vK+vVtPa~{W|gflSlh*ZXQkyAZjT=Z-LYiNW74}-a6^yQts3rHB(uc3QV8iGF&Mq zlF+(Tm=)Eyreid!9#=B5O@OMIn*PAc~g_4h1IaLM(c>F*+tA^lgYQq$T!|P1kU$VdrZc+F|oQA zn#Td&`>9qi0aSJM1S@x~+egj{fLm}Da2?Dar1B7b4L&)ag#I#MNRCDzsxgDaYveEV zKb6c##oYFHogN?cDYF87;RIXsF0r_{g{HyF4HSsm$K+Ji$Hh3132AS6mMGwbKI!no z0dQY-TgH&Chci2fCW0*rl4?+*t`7Q9xZy2U7ItA5Bo_1q-;=R?V9WsF`hf)5c_`&(I~VmOxlF3IOH zU!zo*TQ2Qj&)ZCUvf=f>3*MR$?jk26gKEz?qxD*APq+MM@Y19N3Xf&4APHF`9KpQy zkeLbhK@}9yMj2}QzSC1x^()q|Nx!%SfX&fSMTl{6M`2zD1a_mM)r`i5>cen9Wegpv3E>}#Hdx4( zJRkRgZaccS@?-}K`KfU3Uxx(e1$T-A1+Ygv9Uno31nza8Y<7?LzB)hhV(1dz8ed+{ zDv`CosTSzg)ze9z#2D*xy4Gwo_vvT9c1-b4fYzu2GT$Y%*!pFWx(tj%6nd_A1i=5rQ6hB z*YlOq@I$;Wg9Ie)e||nAwt|zw?tu$j&!{Fgy$~Lyxq`5RmFV4L@m|~L5xjJ`Y@Xu06zTg3A?GPav4}z>-cE$krcyhhy3*Ju z%GiYaeu)MhmofzL`RUh3cjONWSTBe{0B6?um+N-`evWy7qvlI@8WZR zj|BVu@g#{*bdvDyF%_s(I&a38=(h%1A4Xz=;PLeed&KT3{?GtD3=@V`z&PCoZ^0^t zY|BOBhCv1pZ3rm^6?@l7>-r^KTRDeLJ(UdX+cRu)l_{T?*aL>LLr;}et+h~z=Ywv~ zk;U-R=aeGfh1{K-F|%R>PnlN)ef?NA%@oWF+_{DU_^k+zd(xwVrT+_%nVGH^Od^wp zlfSWwOU|i&Gscafe8k)|#V|Dn>mU0?iM{7psI67y!py{i2*3kMKggeTiY3B>I`_4- zucM^E=8)K=-nffE?|o{BcNFLgRNH%Tmp`WSh%KPPKxQGZwl?$rmj?+{ciTUIDlCfs zW*7GC3+U^|ZmRg*Lv`amoO#SiUSNZz3Q#u%r`8 zs6|507&E#al>q)7UI^0M4YD%+)(c{5w_~jGZ(Dp1=FYFSdWSJZg zXalJw>Jnu65ZN3(ln11MT8y0kShPeS!CgD#Nn|BlNkA^MWxNzxYzZe!v;H0v6Gk0`hBqKAaW6;0du>9TMc-#u5j<7wzC|d_NPOqJT<~17m z@^r<;Uot9>d$rzAcljR4=h@or**!L+n&_!8C+5=AJS$YE%$_C1N*f>6DkGN!q79t2 z$JT80eU37k;nhd?rY-UM{={>@a=7fWy>-^|1LW=z4zm%{dHWy$6#rg?DYVR>1dGQ7 z&fn4N&{30+t!z|zPM1#A00;Qei4;|Q=`Q=t4gmlD$l>CMMPidulsjgP z6J%WLd~bybR0ps*0e**I=$a-Km(J#rWb6;nn!V3hM?`a7cp5KCKPcbsZiGEbfQOoV zaDa^smH~%hkx^oXJXXjTBvxi=?6&t;ga^M0k;c8mMti2!*60ag*Pap8OylPu)a0<@ z?nUh4E+Lp9LPMPwyrL0^93lO34J%eXF&yoggIsjY(ubw8gIG|n$R9aP1`JI(W$qY1 zx$*vJcWSJo-P|VkG-<$GZKWV4~T@(z;HWgzBDyB=o9lZt(41dsh5KOF3CG@eRi`k*&al z@+@c^a*q@dE=@UMEO19O?wOly8&UIp@+)Lrn-4Xt7b z*+9S?B}Wf0pE1HvG((K=^!t{5&*H=E`BXu54eo;UcYvJ}_Vv_y0Qi?194zmlUAYRd zHJJX!)Q@kCO)g-#&PqoiIb*fPM}TZLbu9=F1y{9P06s6WsP@^Vd*x55p&z7(kB7z%S0M63Vu`Ul@ztMNd^7eWRv69w zy=EB3WqO>ZUrogZ;8qMl1DG%#(JtFZDvP|7F*$XJWpfT&9TAhM%V((aSgqw=w$;!B zfT8Pi_<2t_lVX@0=-FV~`I2DxZmeaE+u6~S$IXb+a*Q*;rd8WW2m-kNIP-?)yocmZ zLN2K-ZbDZJ9-ues4LGPkLPJ86DZRMKso)`&SinS>$w>y8!_*1h`#sLmLYuV2y{gsE zb#)2usnUX)zIZ>Ss?dtup(ectDOM@C_OyDDF6v|X{s<=m2a#{v&bkLB&7>jtT)H@P zkqR3ZYL#;R86QO)A%`lrE1M4?v@ypqL-&xG7==C|(x@ohk{tNv%a6LRk+3cQ8To+$ zS`Cdo6`JH-YB zLw=C~q;MVpu~U89#TLL8Ih3au4vT3=W+kc5XxV zJoua}JB?cGBCsKJSV-ti`kuqHmhEo8q|KK8o!uHmpen)iZJ8M@u zS~d2>x|*7t5XD~vl+m4Uls=2(SsL-dq2}PAxe<%I)-LFpsXBUaE7B?tq}x~TB@O+? zpLPQzC^Z<|wa{zdaW|ry1}TGrqB~Oi`k+>EPDG#wgP|zrvNUMRkUZ%9my^=eK7QX{ z^@opYRV)PM)9yV~>v;G(GFrM=&)KE1S(YKkAXIVg_6s`jfNyo}4Ez)(-g>$C#?ccs z%TG=H6#ig;G^QvyL~aL z9&T=Ke|1R5FB-o3lof(ZDlF38Vfe)C zkV%AUv3x8Jed}u^mv3NzW(U`n{cve2&%gcM23q=SujeHtd`Exzc{}$sB*BII64Un0(DB4L4 zBnIPvnZRy<7{$u`Hc~;1jDsucsJ#yq_zf8YQ7Db~>~bLJ3o$*;ckVkOOwHs;?tV7hvKZ>@7S7aHqza&F}yb=>QhsZyW+)~E=Mx)=nSWr z_EeL$%+{O&6;@62{TLWT=)%isFGD)C`nT5DKn%xyyv2%6F2zR2rKLR*tHzXzO|5=>89ni9Vy? zCTToiG9fSChb^4j9RZz(FBv26& z1|fZzx<^l@@6;jNua2drKL*u=q)+g>5u~X1)SzkRShvcprIQf0r2|I;?%G+;@$7S+CxYZK z#Wby1BR4`{m-~BEFdS{HgVEt_AIv{hLd>(ckDzwM6_vFxD4+n~DZK8ER~*n=A1)OMBtA?w zC=q6|SPhIR>%M1gNfB4!o|zKW%>KZThpA*M*~?SGGW=|ip&K!=>7#u;LO4!)$oA6Y zwL8Az7(Q-qc@u%Z(bHIs@!a$snzETP2h6kT2P}7X?vg&upctyFe{~j%0IQmemqio! z`rZ%)JxBHzo>RfFN+3{O5&zq_k7bOopn0@cpxYxQ6{FWZQ+0P1jGQgxSgiO4jAN2GicF?j_nj%2N@K^pQGU|5N4Fv;IF&Vhmv-MT z$}I<0(09M^32Jp3*KySFN63KY0mja)HUAptv65~N0h2015Rhd?WU2C68#UtIGfeFH za@Fr)?nuqzdVxi*y4=j8?7D8*>G4ULTnf(sP8f0F+4qq@nbGn^^|xH_eG z@=Qnp$aZQT9ghw+eSGy-IS?AX28@(x%(t&i3Hs|sD)?@VgG)Bzj+UwZrSLQ_Q@L`g zDy(N+YJU$xjv1VGFIIG9?V?C}a3AzOr!t)kaf z;zCGv{4~H4f=Jj1n4oa@ZCZ8~LZX#uq*}q_S0hDi#5?SPP-?Ip_!@*4+HA;!Na-a{ z5n+#Fv*oaP0B&!+`zu`aP@n+R?!WSGMc#c%Hl=rpD&}q!MFbP79GM0uinv1oQsxd- zBnCvIRi9fOWe(QysE=tVLd^K$hwjC6-k$27?^MIi4{@GSWxp1Y5T!J+#OKf_ef12nPNz|sodpQ!1RO8ig8vcbGI+S zL0w{QIy}B^atgU4hkq5zPPv6U@xz)82@TNeSK1sm!%XDj4j%f)3joOY!tT__+OvxV zAfu+NV38V6s)2GH+|pkSrBrXsH|TSo>?wE*`gy+-2v35E7c%`G9U75?Qs|pxQiISf z7XWmbQshhY^{kvxL6GCV3mpKY(xG}nt|B%tV+}b5B^`K67Z1xmKrhK^-}F9_9J?eB2iGQH-|IkKfaUXjuD+$y8(+myBP4=lxk!%{ zFZA;A=bp`=LCfByH`$3ob#?N+zn>u#*Ux}dB2y$RlM58j`Gkopf;vo#Cj;!SD_(9xzm20($ItT?H1%tv4|uhPaq!?~9i|jWjzX1*#25hag%8U1UfKP0R<@f&u1takErk3 zCx-=AWb75U-?Of8+o^V2HDh_S69oqjlgyT6RDD;a{}HGWc%^+sB*e>tBk(ie*?6Pk zp?=wY7s@K$iUd-BnN}A0dG(yD-F7w_XVrn0sCZ+|e#U4e5~suFKZA5noQVC~FX5~PJp8#hDLy2C<<7CAbkHJk$*p%l71v$;vV$`-0jydo@fnMr3=i>a zjH;!h%f`j!2I=D_OGf0NI;V#Qic=2;dP4Y>8qxOE(+4bNQ$&&CHl=glg6u`VPmA(5 zf&WL-S4TzleQysXB{(!9-5t^mBi#($B@I#%(lJPb@S(w>LAtx7OS)USyFui=et+w| zYt0|CVD3G2&)NIg&)yG{2?sv5;Ft?X19k6LbC(pycZpvIoRoMRF4~F=3<4^Tkh8hb zh8da_U**)sYL>9}y0pK&^?`HHrCfeH`g^`mom4ziesRykB#h34XO7SWYm>H>9!`r+ zLgz{%Ve7RHF%7faVLO_1{i4Ut@Q-%g?ZC&H*Aj6h{qQH!S8RCU=BrEM6j^c-@(+-R zad8=2QupVpyrJzc#hU*?QTmxL?h%w(@Nz+D5*gsoif6>yuNM(YR_`r9oUv0bLm%N+ zHX*=WFLy5jG34&aqvg;P_6*i z0;tlsi_&t+?4FY-%jCCsx4yrRCYuzL2+S)$qRp=u5AU-pjp^|VNHdF$lPT&mm!@h+ z89C_)Ski$wjHNvN<^8JuG}b}+6D&Z&^Ng+{0C70h4|le3|M0nq%1^PlZrlYvSLeL` zR_8GLsK&Sw^Vw}Bc=u<#!cNHVq}yA9^g@mFH^J}s7<>ff_<4jnf7W#Www4YDXhS&) zmZ@d}5YmgbZqVl*E11&0KGql9f*xh=V`i$P$82bErR|keb6cg^rSDQ&qH)U5iUwKU zS#%${y**~-v0AyWXz7vbi`0m|NAB=^NOrQny2k`ExY0ngp;>?iXqHp}#W|*M5rl2wedGQ%bD-cj@zN=l%mS7e%7`r4Nc5*l!S$@N zg&28bH+3z52B%+)-*wylD-Hr@(k2M|XUNG3aLAPrTTyCiybjiJ6XeclhXJ13@|_Mr zR9m{;3bdFt$+gY4pZLl73KbN8d13e|(Ka@&FC1!HPy<-|gdnPIw}@VkRG-yrLg?L&Ko2E@035v0Scl$)UNHnE>+6mcQZHE;tW7r6B8T6ex6ms8Ne zb-wI6B7X4GGWoK*&?`_6)>eo@K?;8tfqCARQaMZ0Mef#h-T*5E4XX}M2K&)J6HY(r zCmM6=uYdr!h_?!YK~NMm%3jN3hR|;Efgu#h)ID{3!x9beAj?%Vz3=HB2zzEB_R7N; zKSMzTOzUGiXcCS;l+c?gahthG=m5_-;hUM{x1t#apmbG${B(sqsMK{3}p@>(?0l|11{w<}TTRC*lJ0nkNF_TUx=_fm3_Uhjb6r%2}xPDL)VXww{ zt>|L3i;g35S0ne9d6^@W_PM4?w2Mz-odYfj>DrrZt9Pj01Oh7|0jfqD;X{dI3be7> z%>M3klf*E_EC|@2a^|IDIFo}3pS@gLUxe1O6>M?16ckJKu?cwZDYS_avFYmlt=?mG z^j|9(gi~F!y!G~eRKqM#DQF`GMmE!5mE%budg$S=8yVTdXYc4jf+T%yR_vAJaEW1n zl3aRb&BLZvGI~cwB_m61k%UoF8b-fIpdbrC5#{CMyw5V4crPC?Byx}u({Kycy{8@WLZ7!iO?>2@2!@~-DB?Hu z;aA^aWxKuxAH4M}UcXmUK;W4ZD9^OH8A!QohXmoc>hUNb@U?y_S7HPbb$e8vsyKi3 zc$L(;88f?g6xO3(c;r-#G{n8535`({Wg??OEYN=|-1(@AksSg>phO6+AV@}&(4PiL zAbKVChX$ULOAWpnds~24swjc+6DhU8_GNa}{&oHeQ}4(ANDwk5Hm7#D-|WSqlJYWX zRDG8I&4CQ0I3)H;4%}vy9<#^{tm40{U%%QSgUMKx(8 ztC+pl3CG-`o^`dDwE3(FD%{dw;9F@gE(7|3=8_K;e9yRt7s*>TXw4flJ9>B}d0yuj zP;y!~f17i8lZHEY_&~mA!KR2vdfCQQy|}TonE#J>O9OS`6sEqK-z{xOSp+It@x>OHz181p=Rbic-_3->x#_WI~sa2vWk4RP%FL;lq|6{7Tt0!{g4>1B;He`7B6f=DLv`liV|=%O4tq2LS;b;)7m!dLdyH zXu}s{**8zt0JS!0WPUyrJF=^Qz}VPdZ*o_ExR*3@oY@(GUVp zCT-x~2qY&`TeCrz04$+X5;H{))VcuvWCs(;I+|5ls%C`y`@G9acu-)ZkcQw%?)H54TYU}k^uh0s7Fn}d`Onj8);&Ozl|8iQ zITCu?R(tapY^%agVr^d^NVx#phwq6+>P=B?r&p-Hdxdz;xMLe55XWWTequQwxYa_$ z`8SOgtHcgu(Xef`Ax!@+<|Sk*Bu5RjB|qJ!Te&W(1_kb}Uwqs`(0UVng8d#IPouB3X1W2*NuD+Qyunvsu{5Q)CGKJ|@oYf;! z7M^t)Fe|576|v6y229rI7IJAnn3vyDFs>54?)Q87Sm0`T5>DB&_q|-3WBv$VLSpdx z`Q=vIZlTf9=Z{Ln+psHQKo9jzM*aIMkzcPIiiz)lNh_UwnQaiZT%?9!t(PN-%AkP^ zA!2#9iiQxY*A_!H3;xA#XM@!ATatLM<84a#(71mu)m+s7uZdq?tzQndja(msFXii7 zZ1l)#9PknvP9l%I?*uA&>u(Stb#$ysi!Q_OnuA77YZIWZ0tQ+2YaZI49{eX8Hpb{0 zcb@QC{4KCh)`q!y={}YjzaR}9Bv__Q)j6h!vu*R|%v?Sv9T@9A_^mRA^=vqwQuwm8 z?LEFR`&x9wb7@LA1pL~Omn!byiKt}u!uuJ;NL-_M#fWq8(zvQqyh3xAm4!~e<%~mb zPN4`3d#@H-N5z?36q^dOu-P=-dGDOfA~Rv9i8c-P(Q&ygg?Pdsvh`S^sXqgFltAXF zGyyD;RaUxs<4JG1Vcx^A$~Rz*he*kdMjKJdpfl*!RUi{}tVHp&UXuhta$hs?8|91$ z$C<#WW!ne2rJAW^lq|_sYG9#0h|rj2e%r~XZBDduG%#5{bKF|l`K7e;do^#UX6LE) zE7#p(o!yS}91_sH24ogl-M3pklly0D7auLYX4$i#~_4;Fw1Acliv8#_`PAYt0rr-i5YL7b%c7c~OAs#i* zXz?0!CODQ63b~kWTW`S6$|-aexI^%t!O|szadjKiIcA1|WPWI<`!~|*O>o#R;pKdr zNZ|j!0b#>77(b^Q{eVO>Q(B@tiVXUr&sZl)ynTcU4DDFYTSYENNRWgEHv*`WAmSPo zF*T0r-$G8KW0p6G>1$X|mokpuDFPBa^hht=#lmWt90bSFVb#QFrPb^b3&lj=y(4hR zR|4jEf_m3PFOVuDf+kku zHXW$ZELatE6Uob+NOE{Amc<)CVY*a2{3S5jvx)7OGm#gpzj=Vq%q!4pQ^%z$f#= z*g&;3-O~`VB(^rFnaTXTDmb#~1OB(#kD;G4&(;n=o)yNPeA(Omxwy;EBGXEsz?nwz zh8Hb$tWQ6ZJZq$-+(^fI%ovpj)F+lqmOEQ;q8DQ?rrKDusK>&rc`M+C40g=22u?^Z)PduRA|q|mvO5!H&$f%x52a+iIdNjs6qc=`b@I+`+a1f@7I;YZK+I^!iJ$gVbLOyi5OPL+4d9EneS%U!1$IEoh=XNNO)jr3??MZ_L~o<$0{{0kcZ= zZ6E#9as=HhGb_*gX?R~ArYpI1L$Yh|Biw0Le|ek8I^tz;dn=0tSuf^Hgv4*dq&BPT z_~uVofc5qsMbdtjn!amh981zP8jgaff&s%DN$n)LF#O1;7w0?I0LTpd=Tuc;z^hW$l1{Fb~VoV|rt@qAxE570J3Nfc{UtmCy4uL8Q z`Z9Kd1oWsb-0sKLxlWy*Q&rZ|b@9s3+2ZVwBCf<|Uq$Wp^sAja zeBRqD~F^AJvupg@)dDyeIj0m#Vms=3(Yv6;m1$3f=>$HX74MkEja%2A6swzd4rL%w#-V#`@ey( zsA5Eq{E9N<`Rhs3fhND;5vuyaZTlMx@;a#AOrzin`9;ktBZD19w%k>M?$M`XuJT!z z?`W=f{MRP+e4aQdS^*6DX}NpDffw8#q?y%lh9v=#LuMUZHhImVEO3KoKlGWj-BA4b z&4#sqyB;*-@uS-+JuO?h_ochzi_XIMl+Svx(sy^!u>Wm{)5vDg(t2t3ybAZJe(I_5otu{dhgowb{q_%9)B)< z{L`eT;57Uon8`K>>{Du+^F$1Ts(%G$I#JP~G=4@VEe!`Mt(i%jQB)uhOaePzjUgT} zsGYXWt6a#gO=0Z8SJfj4XIG+&bce|QhR1|rd2r(^hqRVotVvGs`6Vi>_-8XbS z0o%oA^4{MxgF*X)|HT`P)6i`bS`F*0@nb|CWeS4{rFa<`5!5GfpN#))4Pc+U{@dAK zmo?Uhpg?K)=zLJ1cd}aAfE|HUU)%N8W}k_dl^@<&D6l%kLMXYw2*{MLL z;?U6gu$_!3k4+(Xfq1y?PU3z21J?_~i`c>)GA^>)my!;FNoM}#!I_B_F_7MU%t1uuTRNplVMs?adhlmQ_G z+Eb5H?}Sb*aJ6dx{s0(P4=W#5y>Y6fsN0Qy7j8?Fe4$$KS@|y1dI*ig-6W|Wo>^Qv zrc)R!Ts|~chiW`KhPu)oEP6X!%h~L?K?Z)fpXeS;`B>Q&pG>j#X5~x&I1}`KFmAs9 z_oGGWCIms(tM3&OdNv&Ns(#Sk`g3`m+aFsu*)!1jZwz0Anf6CkWz#p-6AZ^Es_W|3 zixC#6oy9J!rR?O;7<-oq`M2?Te$haru0O%{9Vp>2o}K>BF?VFHxT}I7!g~FvZgxeP z=OU`MLT}3eeazyQA2U$h3Y5)=LDhRD;%%M2xyw&u8^6DwWBTH+AaC&(>bN`QP5PaY zDpBMo7d91)ix3&XBAQDEOKmlav-@=Ah{B`IO| z9qZ7TM-QKTruiQg0r{Uq-IkYq;@FyzB*8$bciN#Vk$LyCzl4tLN5@k>!VLWi`84kL zSnl&9AXC*WR=8iOyN<_IZi1AP`_}52XZa@w|7b^(i6VFq*sZ;T}!veBs*R zTdI{t;lERzmf}dlos{)9$RIOZ%%l({v9h8 zymLtc_ui&=z|+?6o4iihY7^J)T}h)78XR@(BY3=YoA2Ek)y){3*iCh1juuY$^1Uhz zMrVu0z~k~_Po)r7Fvyux8W*)1jv$MQ0YEJD;XZDwkO-X&F^-~Fi5u1+1eAP}r|?Je z?oA}4<$q?|To|r-^3?6D=S1lX9!vZ+&%%xA`YEs`*Y%8q;;JYa5hSs}-p-%!i*E_T;aIk2**!sCK)1*+g8PA@`$*|uXDTeB?6s)c*lAb# zp;0|uX3R#sS(OPLQc0V514;#bEIp{=x~#ijjM-CI2%{W`?WoZpfRgI|zKsaE zr;#V1j{WJ=7>}}if{-vk-=Hnv$r>lZ2rXR6GHNd^Wr>%odfC1DGH+D*A4$IeZp8J? zjr-@%gEfYg^C|zk9G43damR~QOw?5VG~af2N+t$csI5yLS8x#`ZEVAdXqL0)f+Y)t z!fJE~w)-u(w6w5#boKSq0hwG)=Ivx%*>763;l1ul_<>=AHeNVBhrq#K+`ZJlS5w$)ba(jJ^93nZ*vzT`F9!dk_ zQ9e37jg_LVII?=5=Gxr$9!lk72N2Gxb${`Urlq9;8m)8HN4B#vHYd>aJH3>OmvUW9 z*5L~Vxb;6pfU)5!VV$hc)h8VAy4T2)lUK#ING z@O|hba}ow#4FhgOMFqQjf?fU6ZNJ45|y`|yZ^#9x&M!E&o;QXLzQw`PUC0TgE`X3G|ZMux- zbBbV%q8;7FB|+S!8;JA0v&Ey*!%}g1COJA_VxcHr4mbbvT=_89x$ODJJdWQXsUvI# zTYzlW(dvSwnHG3Sm+vCqyUrN38Dv+Hx#eh28-SGbrc9R4g_3d-mf1Dv_G=PYLaF_#x~z-ZA68cOl@_U2IrQhvXD zX*RCJgGi}6oL(qTf4sz)cOTiQ$z_a}%hv+WFppBgG?@wH6S_B?YhzV?{amP1$?<&d zYL3#k&U6dv0$p@;=70XXB;Kd>66=)CUX<#bsAV-gf6HZ5;x%8s{YkV&sYt|9uz7ju znxjSu%NG)AI9vK}|81RUjfnX7QLEgD*wa`|Y7#=>uh$c5$|rM?TYvvFZ?5!CZ9)p5 z@p;8FlTLDePY4n#uUrS5AM!e57^}(yI0?~PljBEOIoR3tH5JGnTIw9La)F}|jpKQD ztPB3F8h;8A^lfD4@<9Z`n55wD>DefMC8hpx=fcYn+^6r}=Ivio@@}D|@Z(aaeV7?B zAV>m8GMiVojv(Pcf+T>k6efvzA1~KzXw2lX<=lXMR|eFHWQu(M{ymVhAxDcF@%ipL zQ`EETmP+VRbGvyR1mf^%_dX!9a^VuV{Crg1wNX^UKPLQ`r>SBZEi5GDalFvgp(U*j z`sr?@m&`UYymytOCYQW3G$g;=pd*?&l#KwQnwg%akx!^NN}Q6T&1D>(nMrh9&Skv4 zxp7?fn0{hSQ!;LLEzo6cc+`^0oBR-l?e6Ygo!~6+8Zq*;%%MkPyJr&+5KvSbUd(|O?6}-z%1IuVCGrJ2?@k+@b2>R# zVcn-T%*LTr;pebTlz!wO3HJ8!0YuU>M7jC+v{?z4KS`=50+QBJ)Cj=1<=56;9WU0F zWg-0JK6>C5$KJC_1kP!WnZ1fKZbO-?lbAm9<6lNbMp?d>L;5X@pl`Icrl#2ssZfA4 z8b!pCq>v%3$Vw>ud0&m$eOg?U6dOo`-QDG5*}&zzlVIyE>o?4s)4Z&Ax229Jrl7F? z?^F~{fkX)!_J)2#vKuF(?>`(%>2-7B+JTjYhQS{qZ-4P4fDjzA{4)Hnr;lBiOla^k zSVum5_%QnSV1HjA;ID7Hahw#j&)u5gN2xq@`GmrvBC;aCa2r48U&y8}f1j1CzbVlp z1xW~f2VC-F+m?#u_4W1D)zMg^oA}kx28OlCNtcaol)|efqlg46OXX=0B|b)|tW0h^ znuYqg z3Msq><@djr$<-X4Fqo!>fUH(K{=%JRKx!5TEpWI4L8Lk)6F|Z$?au>wuJMK0SDIHn z%P#BxdqaJC(l4ot=7BBaDaz32-R524ee#h;xRy6#81VMd?}WB1P`J5WD>@mlL}NY? z99~)2V+pu2#)~{+6$*ZPyk&U0eG-4n^L}i>k1oLO=y#RAUp(5m5-;aa=0Wl_Rfp(i z_ZIbbp4>#CsAEOig+om=5jQq^6!xl|=B^Li`u)VHmLaSgL691YG&cDBT zE&v?LZM`W*e`_QrCeP>g7y%>+mXVP`qjKPH zw-~^l=24!85#s2T@_YcpfHa$0p~NXGveJZ6zx%t5pmqqSRZ8;V)z(a{aErIc+2V9# zc~NPtMglEFj*~dLZwrNF2sxxo>ldM5e7JqL1ZTEP-sHuF%lH*Gg&!5CHxJROECQX! zEN`u3i2OJF$#MKdgx7FL@%+_C#snyrJpJb0SQZiVSqX4L10{}0PXw>+baWas_wkAe z_z6RDoMi!})y1}jRvj%Z<>}NjIrD9atm2?E&c(j-^YcHOP)hv8FXulv1*=8GPXzfu zrqNqK?y#yz*X4?iNk?42`RHDgN4fR+77--Di2wez1)J>K!hR>V zXqmiv{S#~r@96)AKAz9v59$L4LApv2zoK2VG}BBgxBqY6;+O2KPW9GDf6Gf&w`b$U zf(x%UP3CeF!5~h;SvAU829zz8b{j$>zvb*+hFGdP%_~gqnLE8_=W(=Yr7FA`*^W77 z{5qcXLAHIx`K20-D%7PJB~I%2a5G}Z@!Zzd3_nR0ih&a|R4RF_$c_Aca|eFJ^jC?) zHNP}Tjzw)%dZKk%=WYk*jw5H`0>W*Jw42Q_p`}Y5{He>xpdWqcRYz#1Kr)^(5d~=f z~NyJK+VW$aiiIx}5Om1Wr^8nb4meMIY1 ztcr?FMld*6j7e!L_CyX{eX)qq($bn)V^25nTq~(27Z>W;{yISh2}c5P!Q1Ov&i(NZ zVd6avfSp?(Hk%N%dLjj)`Q-No1{{k!De$lXCJ!;?UW6yv_E)_3vWRYE^hE`-MbHH}qoWa0txG=)E(h##c!a)Hs`9IOBLY@7$pYIR6XX1c&3gsjqBgj9}vkd@;Np?w=F+;t}f zvb=6yQT^NG{9pv?-TX?!%ClSfL%4II?T4VtugQ^ePi6E_)9#3Cby_u6&0@_YVNrXT zrh?4u#NkUapABs=;gZ5R;R2Hz;FFes$Jt}r-^}Pd-6C87joumJ<~oU`V#keuL8t~? zHZKHNaHQk=42$QF&~lt<4>2QYY&z^i?BC<)X{2{KfYSuaEcF~vSMl@G3hK0m-ao`q zqHZo{9j@NJjzr%15h#rzp_iB+SmFVyc{bORTN7h&1ZO*-ewU*)94CU(H1CUnDCHQX zJS34(jx(uVaiE4tZ_56uQD9SgZfRg6kr(u4B8^>8YKRD=M$ZQgreF5jW6}MV4@OYK zcA~g8>Y3ox>L+H2q>iMv4~!0{jS#y@-Tzf2Cx`u?RNUIb?3km*oUAyb^7k7uOp8o8 z+SKfX8)F`lS$DtB9~Wv^`R>qyC+6o| zf8tSPM}uUT*46&+dJB)URmiBi*Yw2uKts!%-r(3seAa`QOeeUKs#6>qh!{vKUvU(f z>lGG81X;+EoW@MN|0sa|VH~rDkc9jOxIF!T%MFh9ttf=}rS-I=*!-dld=N^o&C!M$%V_esvYhY zk{k>*>^rhh*wErmx{KmQ)EzLS+kNE&9Mt1uWEf*I%mxsfh`PB~pux+OIEZ?IMqQPQFZb;i!HbC$$r5cZxzYWRIsPiyGGCJ^a~Ey z<6U?ca~~pOsvMzIcej1#Hrax$mGw-lf3X`r2!S$}!uFSmYfL&NYWD|J=O)Z-jL9FB z?xwY{l?*}h%#@A=xw|?Q9^J&mZZ5h>Ox??y+~Q;pQooX$SJJ%17nRMux7ELbM`Zr= z4>Q(2-JLlZ{8$(1%!g%iarygLTZg`*85ix*>Lyir=bOI3ObK%)n;%0gpxy174&za_ z;1W!)npmvXWyOsEvThdxxnzh@&5aR?BCT4R~u3`FGUYMJ(vG4~H>&2l(hnDJj3z8KTy zq9CRh_HDU9sN$pP_i;h@lB9=aynDZcX zO>CS9wU5-auiAp8L<_aB`!^L#vPdS7w=xOW*`PQeu%rFF}a zCw%?-RbMBUrAMf5>mpA!jt^z0r6Mjat})adG0=X#f|sm5wXkmXi@7-<*J<{>iqTW# zLEp=ZgXdH14M{e_bHe`HWJ`jmzJr4UE8U{j%=}td-njpN%4~>eA-lYN<@`NDTBWnT zVgZ-i@;x;gPbTOL9TVPO7sD~bGkOgxMA9zK&Q-Hh0kc&qB_*dT&9$>%a(T<9{d%rd zTRl$f2*QDe0J-Zaab&`Ce=1o=0A#BCFUn8l*TI(sZ7B~X~5U9xwB3<1=(s`31 zsBic%xzm0Dv#}5oRU|aj@ZsxYz7*Z~-H)kRt#_(CR__(Bju{E(Y`wgi0D}#&J68(5 z`SXQuv!?#uNbO}rCD2h&R6_o%R&VdHr$(y7>RD*DuESSgx;_iFGnsuymRx9XTpq4c zNrWb^eiR*!s0?^MdgsvpJo(7$B5)+78L|-+@%yJ33`pf|6Y_~iNwlD3rS%YfMg2joXiccjMz zIXishAEq!+>AowF?yVmqx4XqZkI|JQ1@#lHY^CwZpiB5+HTE(f^XaeHBkW3Wfm(4=Ce%B zcbTta0ub=C5h$fa5t7Hr8cQFn$avRgm7n_H4C!=>TLYt;=6lmzj_W{?s#x#oHW@yS z4-(T+wK+LO-}2%mUgv|*3d>ckRi3H89UqZA%w~Az$Yh@5Q4gEC;e@{d^&2wz9QN=r zh_EUI=TgD^258~ae6Zmh8>j2Hjaz|nbW+94;Gl$5lhf-@BtcX#(t&2*hszSP?_k2Z z8L7=74wk%egh2mO)Pm}*cc0~(h0!n_{*|%QqRe~>RK?5GPF-A?R$a&5HZGmj)h+T8 z=?Hl72Z51;La8ffk2E8`E!1LBN&6x~h@?EW#qMofj`3xFFpUELP;kz}7KMSK{MxeZ zM-b$3v%qSmRU+4Ong4}gpK`>NlUP%#Z{YJ!6XbO|7!L{7G>@>5FcLhE5&_ADHBYYvygQ}UPn}M zZ_U9h4EKD@!Z9Rk{YrGGjUv4Jk?tIUQWM^2y*HLA7Mge-Yu%YiESN3NXuc;hi~73b z?5RT)fk4d{*E5FNHRd+0Vo#_6UVTX~}= zY@i;w92}G@{jv{?Vtm3N$f0Yf0R%k6x`)ziJh>=PIah z0DM^tg72}hvwOqmmBLr)#|jg*OJ}e4#vAE+tdbSj(#gPnt(xA&o^eTvmLts4il9}eI<`d6qP44kGfE>%@ zNh17OF}xq^If1sMl`q}-5gz|Y1GlmjPLFG0%k3*e7JERFQytZ<)^l8+$M0xuxabu>H2Zi!y4mtw9S8B1zsmH&o5tcuZ6^`%NV z_A6&{UU9>JiW|tF%QBgr{(r$J7}rH+vKpW6;O(K2(Rn9Hr`+|f;v6WWDgk^1Pbx5jx>laoPU zX2K{yBp_u3xb<3MnFb8Z$C?i<)-P|Us+vd#KNa?>I5ua+QAz9z0)Yv) zy;PT}po|Eip*}5+2to$067EBAmW$cz@UE(fc>|4_4q+ZaH#-`3TcaMK$k9-qY z7Nq_vt!hK(HA8&Wuu!D56+_2|VMVB4Jfpf4`uoVi5)dWqqP-#%+;3MVeDkMr%S#+I z_(4|aYpmCLdwCqrwuHk#{Jr8!@@%F5y$-MrBKCe%R}7v@GA(T+PSrP$*uM)`vzI>8 zdqB~(MfwGB6s#$urP-FWf8@XFZoqljY(xN6Wn+u5i9b21eZj_Q^gSL2VEhV(8FCOM zD{_mhfnqP5AI09MC?>+Alcl4U0KurGtyPsV~0}H1VP--q4*p zW^2A?_?G=R>8~1r2>JnDxT4!RjF>}+X-VGK#91MK6SGsC#B~?Ghg*qZ|68w6CzU`1 zGXx9Nq1fX;R0!I)a-bi-S`+`<^=q?+R0TY5Wd?F;47!&wn-sjbn`&+h-)oVH!AJUW`Easj+p1;&CxTex^Y2QO8Fr5bEb zElf>f+D63A2VwhNE+bTdY~TWs39z)=3wc7o?|FIY?qX!Fe$_NYp@=V+AyL06@AsfC3_y}lz5U5; zV6{$hmEl^=%dUjm;r9@jEJo85RYTe_z!3qC*i;3xxo8}QK7hBAJ_>QlC6U8_>M6TT!sF!4sf@dDr z(urDymhhD^TpNXSwd2 z_})WDXL4OSR^G_SNV6d}C{?#pm(@Jl=@6m^MOI)NNzcksEt+;Evol!3iU$Eu zyy^q80r{foMF&EVu6!-mai^l9VwzIn!@6p-$)?YZIrnG$*49ur>tltvJHL5%bgCl( zbe9;r({AA%`ywgzeE2A$f?NWOiypSnu=)#cVsJEh?MdbH84G03!}G$`{aCa#!TuAc z?l>zeD-T127OI9qam5j^!v|A>A-?PDtmv#hK4~@?;LBn^IVRrM7XD`H=mUMGnZqt+ zOWR|a7@(iVCFa$P@(FuiDvs86*dWBH0ECLv1s0MCS@!Vupy_x~9CdXcz~stHf7)i~ zu+T546AmyY5ttFlkM9`s5U_VIrbG=6LDjE(xA4^Rc}F+HH5hl3Z|Tm+IIq9KIq{yg zR(hFAn>Xv>w-XHwoDbvc87^+}L%Bt`r=&{3ul@N$oEECn?-u~XT zvi9-V=8AcObJR@lAZT35wTA4q@gGGg=Dlsm2*Hq!Gt6KKCQF^|j_&66GU@;&sjJsh>eC*#MOR`W+)3dRY+K^{EinOKCp zDl`z91>5ZWKU&vyXn>>6`wHVz-@o(ue?vgoh>S)>H5AWz8ct_Ia|Bkl&G%6+!Yy|M z)t+%#?Z(ZQr|sUk0OxstARsg#b)K}K zloLq{Pf;kiTNCeC350X}`AU4?%5t#OE9<>0Q@S69yUuH;+_^20%P&%AGLh@yQY|Ll z-!OGIlV1=1$Xor?yiBNw+L;`1q-u9%vBDn}`l&;bHJfv%vQVFhYUTx}gG% zN)kWBkEdhxs{w|gLh+ek6(qfj)}+T3_gdywQryT8$I&o~JZA z<+WfDF+Vs!zb~(2O#T!&9mMN&NM!7OO*G|&1j{qqhPNz~P#yvf9SMs5NGf52%Qr~G zV~266igNVmYLmaB0TwG9FgVN^7YWw4j)^@`ut3NT?hmq0_ZT$WH+0wrL_$q`Qz+1Jacx;^=5O5mO zxf>NQMzbyErc&kf(_toRi^2m2yc#(J!@y)`s8BPX|n;@O?IvtlL3(=Y|BK-y|-=Xg|ND+tiH zl>DaTRL#|I$);j$V()031bG&wiz2N9YThd|wiatWecX9l zonJ>_rjC=8-Le%r2PyDrr7Z2R5b_obIDD$M(^kRuih-Uy%F}dClw3BS>7?U!R*Mig zoX&xwt4)X>np*=p6YphQhFGm}0GfBENGkgAml%LUxnYu4u#*&4IeP;8=57aPEJ!vk zSN$HFFM|+B9rRTwo+3pCKU?Z}b&LFkg)c{;E7jv(N5ANBa9=~_(=^QHfR2?EdP5695q^XN&ILLJ_OL<)XviO&>)@(EQc24rI=ERM}c#8TQ*oz4zLVb zW*R9#$3uAaL(`CZB+KhBAWA@vyf3R#^Oe&pxmeFeg5n5c!KKAxYJe3IYxiH#e1Zqg zc=4Dq00JV*-x!T>AFX&r_G|!3jlC5Fht_|Y{#;kq;Bs(J>JmpC3t)f(!AbQE9};yN z<4san-qFE3oO$oJIrtSb7gdiH8XQw|d+*9#trXKx!8J@;tmZExx_!@wD!E=(AJYO# zRI+p`|GYMCD;ADFjG8H-mb_+dcfK7>HO9C;>6>IPfk{S94x4X14gjalJjR6Qd_SJ3 zXup&V{?>K>y3tPNmh`)t?u`C`4c4y210k8X?3 zY}-Nl3Zw?gdT`tPvN?ehj{O7m5o)wNbkWJDsF(=DO+Ud>{OAzvr}trThacw zyBD!{|L_hnV58WcF=v)|Z)H0q_WZ$$cW#%sgSo?kZgm(JA7CB06P&i^BCUTYiW9VB3VXd_L31;i)9j2|F z6ilLu^gg;GV>_e0@F2B6zmNU}bcbV!>SY82c4em)TxjJ~+JDa|-q{x_jIJ2w3oy{4 zW=L!M|MeK`C1_L?k=0zHIYzewgH{VZXy26n2GVle!mWu0Vuh2+(hskqy=nYbOSX}D z%TE16p%}eLpe|OmaT)yIyWw^0jVcP^@fmD?j$bg&1ek5q8N?0J?rolNzbJ%jaO{kC z7K|I=*Z-LRky^lWaeSC$K_=V*3Vz*-G>*8r+{Z)LVKhR--a*D)Qk~L)rA-hB;e0Fj zc=Y%OpeCMLtRL!mpB@`@UFYMT{6Fg6Ix5QWTN@ri9aLlp=`Ja03F%QnknR>nx=T95 zp=1c9q$P%sZfOJo>6R`Lh7UjzH2c_!I^xO^mv!u1~ZdE+xRAAr;|G{U}{V_B; zC{Poh>CMi4f+63s^zs9wA)PwIVpY`Isii9_B3*XJwZd{R-yQo>=vJhD{i^<S6-oO!+PbY3(>*}7aj_c${u zx3c127!oADpZAuY7W_Vmmdy89@Ot&P<=2P2VFy!fuU`&M5JAifGj?~GYffD@-boQi z9Xys^vMSTt0e4gS8q~qd)vJwJmJsYZW8MPT>jXzYA#dRTJ9(St5~mgWEsX<$eP5sLDCMmpcuHgSbbnGKB=u-gb4vj#npzi~+3o_FXkU%j!wA zisTQ)sQ-$vRoI}mDdEDWO~hUdg!STCh457*WMZ=6gG{e;z=FaO#&qkAV~0xkkB;=s zIhb!r<1NRmv@m3BS(Vip2oM&jT;g|5fI~37{?%_wwDeRJWweQLeP`Wto}OgQA?F3-k|-Mo_h#_X*}(riKE zU~2;Gd4=60h~8whwqsfjG7SF9nU+q-!sOs(v-9cYOg{@3dq&}TbRn}(^$3~&MqaE! zb??vqM{ihWNq(upgGRM^lnZwkH|CZMJy<(uUx_W}B~LwJlHyU|*h{k<_Xq{{MfGx0 z!BOtLhi{Fa!&KVl% zShIiNAZzL9sEyAD?3RJ8+Z#i6(FP}RO&-9Vglm0Tj`p~GxBvY`3-6k<2mys+`0l4I z3RiZ9|4Lu%pJoCcl-zXP?B%SGzw#{V{)omes#EXtmEF6pK_{i;P!E>c2np3W>K;P! zd%D>;s5$?0ebMip5@~tG$>24y z)P+)iN14mA{9$L2k?1#Xq=cj+-zj2e zl5buus)-;zJat(VA}YH&F0ORh7?`<8P)%6oWl?t7#%-q)p4@>fiRt)n5_@z<4x}88 zUH^TxKY_KEw)yW?Q8|6cuNH@?iHmpl1_qXk!<5xjAm@tRs#;duuhh+J!~E(yyzS{T zG@D%p>!Oxw=cQjDIv(Jc6n_*+Ice$8{+T&gf_E602*>+npu;jt>5=YLsy*l^o^s<^ zh&yvi5>;?a_n!w+eBI9|2%%|y{V?%o*~~whBEh{1t8pBO*}~mTH(knPDuMxA8*~jB zeZ zgV6j|Rio}I_g@oS`kep61*lJ;!t`IzDP)}}MtnCOl8wM%&oOA4lP3Oq6i7`u7504E zDB}wcN=jsm@t3HjO|k`iM&q*o)UQ$$7`fXs;xUXEzRoJjiH&=Qr+ib)VYdhK{uUB* zWLk)VN_iPPmrV=H9CxW6b>(Jp@4TmOShfAHzlF&FUZqWlSLugL;mD1!rA?Qy`qwmX z%KAm>KBPKa`N4LU1+ak&VUMfmH(5|GSE3IW@8&|MQkV#P1uRxUo|9GSJJb-Rmn| zAet_9@=oex=^cS&jbzs+*glN1>t>+jA9Q_fZ8c3?^^-I$)Y8#W)Aj&ry26fg)`FA- zt=|7B{k@C(?ps2Yv1)k43wVbZeT`ki|zE5<$`7ZU3ifEvRSTkuFc)7pY7r6f@ zu>J0I!18gx?(u@x3jR^uiimEh(dnRPi-4r$6v^Y7yNP2r4o1cM;P- zBs)SDS{?M}EudNEByTjI+k1T3ymXnn^s%h&SE#Zn*fkwZ&iJ#Lobgoqu;}cPL{>ds z#$|u{`K8cap{jqcOWI#UA;-C!DFD6T-Jz)^Y|muT9vX6Ahy2zA1T6bSMsy{H8ZjBZ zq&y}U7Y9Sf7n|(Q2sw1J*xvK+E3gC64X+`IW9GP?Fj}8=s>KsIC8a(vonPHIM!UjT zh$4#0T6{ns`5V1RSdErCi7W*_xY(Z?H5*Le6~+xSsGL7G-(pLC8*{M<-h8%M)Oy^! zYwSKEYYIrWPn4-X=5c^hw0DKVRd^k|cSG8NXlo77uQ=arz5Y^EdIq}KOS&uT#AoHI zsIW2pr16}~vYA2R5f6&(HkJ9Ua^CP!GriZ62M1LkUsn?i+XdX`OL5w&ZN}DyG6VlE zeN*-OMSLT@d%jb5{fp-+TZ`lJq+7~S+{zQYVhZk~)}hR#`7BC!f&AYwC=AKI4~74D zi*qLc$noq06_^><0)c+L%o3}4MJUe5Q>)q_sCfORmKD$E1w34qkK%E8SfWsUYt<3e6n>32=_ zCU7Qk=~r5hWM|owX5WAEFilOa7)VWzR~EahbQ$~Yb*^;B+zGO+IqRZwLdt{#F(t;P zPyZ1EmoZn)@O~eE$b$S(64ADV^WnZ)B!^ga|+Ie3*mNZn{8f2q~AIGnhv; zMPY{-k|?>>^Z8xL!*R{U>#O6iKg~B2aJgMlxA5f}u*14O#aHfO-6Q34rpD~lElN5s zwSmDY2qp&aqI)7ALu-Lb|IOvWpZppHhQw;EKiRO>zED;8=CKHOu-)Pa^?@t1m^& z^AA&u_~?#rWaqCjRjKB{>noeFyb{AYM*xh*NE}W5+ZgL8TL?Jc$&rgXYbR?No|&PH z=}zJ?4Zx&(-YhThR+`-7yqk$6AM~!{1WU7|bPGJ!yHI36U*coK)&PH?gV5lyRoZ%W zwztwvC+hmTeD=%D2XrxMZiC?a!M5u(2kqgdPQDTNa4WHcCubV!u_E?BbVpzI>bAhy zfn0h?Nr|fD>2La4b@fm}Z8tbY1$DRRn{9H40(*K&SJ~6(xW3h2dtO7kB|1f5i`d!O zt)u}8Vr^}0M;O5*S*{~6GeAzAAdXeppuyedtD6vDV`6y!GmLBR!7PI@x&9j_1;i}! z0$eUm_JFSJT#emi2${)Oup;q@S^L58L#YaH?p!zn(|mQdW%sjKzs6RZKl!3dxJ6x+ zqX_)Y&z;&6r0h@?x+dPMt4XGy7-aPmAEMl{Riy z_HF6{#_s#hUofE;H+vddWjSyLo_lm*;p%S(f$$%%=F_!QOn>qLkl;vm<3>|U`20gB znVgL(@!*?jJ_IYl42a4dJd!$nak4v6qCDr(ER0+WJ!qp`j;2Cd^MOYF;Vh1c2 zy)o$ok|&^z^?&u9$K<6t`T(J@&;s;({?}U0aEfK4$?`#+eZ&PHO6{>V;ZRhMw21&Qt|#9l?rQxhQ9#1YlJD zN+z>qm05NN&Z$#;(r+a>c2W&4xw0Xsax*}sYXhmrhh>2hnL~lQzKeEFPGzP^8Y;>B z7Bkg0Jgpb|f94zC(L;lm280)1G809TKBjEH%?a-R-B2YLq>Vf^&pW$Y@W~T@puu}2 zUWP_nz*7ISgwezUtduq>q*p6vTV-@lY{zGvS|!5qwc?lI>A+5WUA+9`d1FXT15R&N zmICvBB>3?Zlj+2z%8c%}tcn6XLHjWW%dHNx4^$V>V;hQSA``#u3ZVP)9jtWM-#-Xv zYg1EG0p8gNln>xpyn0SbH;*K(nfJ0D4BexbpJ0)lK+o6|DPuQukjQO(7m{S;`l8+_ zV6T&GD`v6Y&C1Sh3&^=O0_CAB+bU2`#sBF~^YH?xyrByHppri%ib(^usZx#2@3?Uh zzm)?$F6gk@n?R0G9;5C)J*sPMezP-^jE2nkN;%ZS7+ZRys?m9Zwv|8R;hf5&^#MZfT3UKXpDG`4FLi3a`~k?;6215PHjOA-^I)XO#D)_P!d!A5$8BA^xjYSBmfFj);eIv=%&<VOG{8hFiac_98Bk}uD({Tql#fQP%Zk;EO zz{>r9|E18%XS?tv;s^(~=Su1gPNCbU4<{Vp>LjaN;1W0Y@}giC31-NZ=v`ncc-H@Q zf&WiGQhvyC3<8&ewL#TUctGedtbq?)S}~9T{QO~a_Mz+sf$jGKFhcG*j`;6KTfrs< zdrqNSB+G_RktIl^#IPmQMR80cMGkg1H{KXXj|*ZR#R)JH;;-Dryw!Sl*WxP^wDZYh zv<)fxZM>1cb;5EKJqcQ{(1x-LTl)URBT}aL;p%%Udyy-9tR2oF&LL`nkKSje3DK+^ zFn&0V_&%otDEHc9ug|--$c|r?^@()e#4Vh4^1aWM~-c%TJlFCDlEsg zU-z#ysU9ODW0f=tXH!xnlN3HUSfI-9pF27@UL9!JDhl33y7P7+$+OqkdfAbgQ!&EA ziysuziKF;~xDYrrx1;T51_lN)W4f(2fXd6uPnJcP=`@1%NRIdX8aCvnX)gmL;*t^M zWSeK&Bi0GAeVT=08ifZ4zVuN<%kJT&oIMf$BiifNnq!$PafJ%GY|lUNJu%WEk=^hl zXTV3$Alw_|siAPpr#0n)0pWZNGPxY0l`pU)W+G3}8{6ZOu|uT0^5{H(9eP$r6{F$f z&2hN#at+8rc2(|gs$`+u*Q;9(R_Lz1q-vkt*bp_~bIj4VW;ZB<#gHZomM(Zz6c4Ox zu<}%XRXY*8E0}1jhn4`7-EuTz_iX-sOf?(&8nHdq_oQU+m+ufVAR5e!mxwRqiMvJM4~W!eDK>{$_*-n9JgdXR4h=J z4D)6rDO_kjHE!Mas&8UVIymCgsrO z94W`$S#n${F`sH8-1(ME=9_P%0&9>e5(}bG$n+e2QKz^%0RLw5b%d=~TC)z%;&lf! z-A+GH$aY){)xl}!e_eQVWWIAS*Y_xyGU{rlK>ar8r2b5iE=w4l_SR(uciW*WVEU)d zjth@Sgkv3^Mye;S#u`N&qz*+{Gbc#Zy81Rcn&68zxYgSO^oy*6Y$7)i!~GXQ8Ft<9 zUT4()qm6&=41;_AvHRs_)H2p$m;_ql_S`(DQ<;a}`+R{rcP(a#%=lJLAN;FW_HAfkOKGVP(cbKUz+{1!qHSV_f_IzZKy4s7$ z^!gQXkX^n9m| z8zAJ(y0Mj;{o=ZbL%8; z3mYu~5K?pILjw!ZQyL~39Z65J@zn8C@Lq)NISfgZlK9gj5;oU3()Ft|63C4?kwta_ zUv~HEd>4~;4fK*bKrJs7o!iwZhR5hDZ&IJJ|KUWl_uw}qp`y)9jk0o}sN>u<2p`lr z9_DmBl~W;1K{d{?F+o4b&{5uH7xTN`DGj_e`(?t6c1F}!A8C}T!c%(LW16$2q`^*e z?C>KOA>L|NuwQFk{bKUGB;n9O$A9D5?XcL&frDE2sAd0Gvp5EBa0TxvkIVwCOT|$a9fQb^~H>rTHH7+a8bl(HFxm z5b3ymYB1Rk1qWo-H9!2=*0cY6hrCyQ_&>9~APxCI`|Q}+*Ju}y{hmy@YOgweRrx2_ zW7LKQ5hQkho_xV9NuKgad`)R55Y&AHJ?#etG2EwtI4n$FdM*@ z+6)Syl@;z_wm2V#x#6$G=TSfq$Tp3q@r>*-uljS-NFub}(Qln+z~GAShpS7|ca0Rs zQglQnSdCP}B{Do^9)H1tIGqF>dPNE2CDX*1(ng~3Z1ygNBRii(yY(r@7Si=};>OPY&0*pL}vhl_};smB{;le1RHH zJ-sM5eqH9;5?vvS?@~x$eEfWZhY$X=%SDkLzDi%NDlGNP|1HzSn_xAKu@rZIP4utl zj2LSJ_3*mB)#h4>&qbx=Syhg>bEXc_>ON6sf+opklw*UY7x~@rF7SuV z4;m5Yr4f0$`L8YrLqjTvNVGuU)de`%O7$wTuRehU!Y!G}Jr)Rif>ele2crs3$B28MSV@4?iQH|OwPoah5<$v``PQJl}lle2{TSddpK77pAA zC-O(`>HKhKodUVoIqWIj%a)Cw?|15!av2cbop4)Jr<~)b|Fo* zGzy1gadlz8YRIF(az;+AH#j|voDMC=lC%D3;r}EK@7h;}ncrYC(0^NR;aGKi92Y&$ zZ=foG@>E32@1ORq>@j!wO6(4ptJ9Qd-X4hUXZ?>SXvSa^i@&?|HvWz{4_qN7mLKy% zx$iU}Gy3;AeEW-*AA6ZHE17x&Tb%b#-h~pa2fik#Q7;%2Lbr04fjH#EoWnu^4=SNw z*kr;MPaX$xjM=bo(mdr>)SMdtlhJ2ZPa$k z3021r&dIQHlN_m(%;@RQA%U12UoKi!?PTcU2fsB86~cR=VN0a(AlMale|AwN=P$L! z$5CGGEegv&YZ`wZX74e7WwJ00Txx-x8`beu)) z5xNV90uifi5T+T{*iNK-E_jc~k`*o?U28j_`pDcT1B}dMxbYgqS$t_Rmi-LBhekK7 z*yi;(v|}c5CeKY!YH_7J%K1{3`jGOjV^f!Ti@XhN`=tF&xS16iEQxOV>LeIaO{2Fk zgKXsR5~>^{rwq^7Szk|dGwKjgu}RZNIxvSJ2_2ITN>=%a&22S_?<_&gQs*?$S8DMA zF116fBxqqMoDfCP)(I3qwq73Ohrq2SVU?kK;|jme+b;v7!Mv&GV4wA-WaltHE!9AdABMDex#WMg--<5gCuLNLh(I znd5YIIDpQwfsPXMzEffiN9vAdGCR(VcxgyVD3%7?uTxN1j?s=9^cU2EKnm1m-tN5~ zLWGXsK_Hn?os}|wO$wQF=Zv^{?53VxX0QCFj8=A^oi%xs3pBS{?VJLYCkdsaD@OO^ zh)A*y8cRobKD#HFrR~3#6TV4t3#B^P*w{3AOgp0{56g7|wdU97C}PXkE44sNx+ zC$lQBGN8uhP17WIWSUAQVyLPGiO2>fp3H#!5!B za;xWcbM~(7qNyR_Jq27MM^g#c+ znLYghLV@S$;1@s1$s{7ed2Ae(u7y&ad?98FpE`pbyIxoB)iqb|G&7@|El9a;IN80B z70ZHqNfTY3A6)KBT7Hsj1f}F*nj254Q-$+4>inN4Za zelO^2BYe5&E=%EMmKg+7RP*s?b&Inw3mSBG_~C&-i6WWF4F^vz^tSnwefd&LZp$q+7oXC#1AW2~1Q_U|$qgW<=vH9kD4Tj~uFk=mrlfXoFl;l{HePyxHi1@2--0 z1v#*&PD48tZwT zSRny4WSIpWP-cP~K2>JF{WF#H?*``=O{faTi~5xrIQ%@M5=ic2zZEo*QOB6NV|OSf zyTS8LAXV)@k?+Uoz0Qd5rV~fkElVPFGe_5P3jMV^pLTKDP837B%`;=3OBU!z73lZ| zDyi7aXg5UXzEl#OIL2BcQnsrtu4!rQ;DrR4*}uSp2!X-}Gz!~~|AWY)prL;&P<9LPK#Eh;Z4IafXT=OjsBxsV zZZ`-E=JwD05$R}>+ojIbG9b*wlx%~ zOg&P}J|X|DQ4iVBLkCculBS07nabhGDxN1-Bc+Hx%dB!6_=V#a22c!ZU+Omv$g=1(`EdSPdtCLe;AFn&|slQbB zluIVF%7#bs%jO>gtv7O0e$x3W&)68z54#|ci)FC>o{?we=B3-ExF`Z2c!_sixcwiG z*+iNm%nPS{RlmbaMLfW&MD-J0j69xqVO7=f?q!Ny>FFFs@_0Qb<_urnb`4kw+wp>* zKYxOh7RVv*6q#PyiqrBW^cRJ7LOhG+sm;Fl!ZF`lc10c-RyVQ*;(`RsP{8-@C$}O+x+@`>NKWzMGoWD zyt{r1)T)g^AYk%kkt*Z*R)RY}-5Ua+y9aw-LeK?H(vFD=MOg6 z(IoZK?0=C}E<#y;-wBZ^9{$-DgvbYte=2C>_J*yE??B$h;skQBNSKT*$cGDWKcTiF zCwo_)HO6&~uEk#gQnALC=f4~4avC^pl^`Eak& zPS$X3HPMr=o>S8U)d6(V(`50@20TTnk@0G^vAZ9BeCI=4ai%)dIH-m{IrWP;IC$K5 zXG*^iio7y(JCKFeYbYX1`RpFGRbxJ;fEvSc|nS8U_L z{-Wa_SI?)ytrg{i4%?bzRoZBAHn?)l-g{ga1i|KCtWhsWDPh{H!yaPx6-pSS4iTWn z5HV0I&gP70S4@>vO)t`j-G;Qlni5|!71{{D<`*{9IYCOXgKAkpan2*WjD1}uET5JSlIc!uP_!?J zFKqtsUQhtOX{h@`izf1xHtoyF_u@&-|um?`|{2f1Yo{J^CLmz`xN_sfLZb zQ_`+{qeX%^uerH#5^j~6yLuJ3nH2DaaIMg z@8)K&8Pn!2%Ct69OMQRmihgTf?3|ks>PpLNe(!>DekwH5%HMERF;j*I0ZV#O#H6c9 z<{e@0`q{_Vt^v&agjpDe^BVZ_^Nlst)VF)VrD%VrsOLY`XZnO&KpMF9YO6H>g!m?2 z%OPD`kz_oy03KbuzFb70o+zhE_#Of1_ols6fPH=T{etqX7IgioB3OzzZMdIS8;IKO zVn?Vc_Gah3K>nkrkG~7ISB!(0Mm?Y5ON6BU+QYck>yKDB>n6W|Dl@n9%RuQ_SM}Jf z?y5UFny7QN=yHT8!4v4c7?Kbh{}LKnQe*d^4`Fw&w?S+ka^T~QhZ?r-_%u^Py+zV7 zWw3SH0XZs~E)LyGp0g%dtxiW*;jQM}XL2`Tb~V%-+cq$+3v;XAS#=$nmvW5ZobQ!3 zM-m}lLdbU;9xA$#d(ty^lrZ3jk;B^fJElI{uq$&ieut$%Adm=pUg#do)+4Q}B~@v9 z?fede)Z3*0z(`pv75IRaZ6~&0*`yJ(HdY3BdgLAJ2|I77f2m*;33M8uR@o-q`IJC_g6%rqn6Y;mr zk`Ma&@imjo53+Wt4V4KEn7GqyodId71ZzwM1Y{Oezf26EKgx!`_z|`7&s;h3h4)(r zsSb*`gEIal_Q$y*1eW;A-%(ge5HL?R3w>sLz~{}=!*WU0$B zsV63xPwajI?Cc7_Oj{fInUY?A=^+;YM{e2g<)jO|*wd86EJ4RiE?b)YSr~%UA}Zca zIf^qI4GQaWL{c(3a2nN3bt8o&?zPgHZNC_5EHMjjD%4okINHw{)!p}c=4}cMR=dfF zccHicT?!PhJ5%z)aTzYXI7Q&S8D_rMCm8{s)E zZn!LN_t=@PnDSEYyZy~^Hp7~ngq{`6!XjUQ947C8s)pN46wNXjM(DFej2$cNR(V(3|(LF zT<`Nhc!5o6Jxy(`2i7OU|7cpk=1cZ{*5Kig3O({ADiKfwI#Vb(I3ucZY_DiQ;OB$8jgoP*?f0 zovzG=6Gl%Gs^qJ`V*8hZ+%!XB{3gHUz*w>9(vXl!ssV(=@nxJv(PqY(^J%+(QphIT zyh1G~;1Fpps5#{Mqys}&iX{pLY18P!%GS6W6=D5ETsHL-Xz)hH zaf_Jr;&G6K(=)X3P;>useHXpZA=iyUJoH;m%qpNzM@T# z0P^zt)QDgtU(Be`n4fYu>1^Ij07k}2#11zw^7Jnxaa<3bnPHI)pA6M}fGN6nD|)yj z@d*ySyaFKu-rq{hL%&60_%mxAaoUcr&w4G{*)g{fPvLr#MMyo3j3R)-M18}Hj4jF; zxo50PjIBgL?>^3Z#huX0R4sqw;+L$tt}qJ#uL%F1EyOv?qJ-%?S^Kh|e^z;pMuhrP zok@%wBU!h3ql2$5+I62~XVS=R;D#*(_L%tDdd~c4t4gZSjewQvdYk0#Ff7n+y%pzDop(WS|&Af@^o0|!({Q>We|L>$wH)Ul07 z;07m2IC)5#nxhUI#CIv~>Kmp?j9%EwcwHA)mBTbsh>nR#Eu$Wc}CkU%g&_ zqzq0cSDWyxiQ4*j@+>w6P2NFl61;Emp?Jgcwg!)aho@-Mr@Y3f0h}YpNRmZUdl^ta zmrr7A^@H*Cn@It=Dtts#UT1C^RZPs}As51sBO#~MmsRF@(m{H(K;81+?^`XVo3hZ& zxXg>+H>4UsM9I$#XqZiM{JMM_;sxjuHyJq4n-0(*wmj!tx^0XV!tGHfu z8a9aSJTE^Y__;@OIP7*TMDwv-nFEfr#u#^WcZZlO{daNWOjIncUcpu*e{y&{H+*RN zO$ZDkvUU!J<74O_yT&gZS@#L7&h6n8P(DSgPV+IYK4P#~>fCAU35cI|5jT_qdg^$) z$l{?HpJKi|Bc=46pvT{Zh75H%Xm%)N!_^y}k3C@e%|P-nSRsP&49>OIZ9W?;oy3pF zJ8=M^FSGG{p0n#J$qDWHS{mjOfdzJJsW5V^ z*}+PY48sC~IGf^&^0PpM`6lxv$i)w zh3qWw^}0|#QKAT_3uH-q(!WTJ?asG&h2M67NE+84CD*-v<}^Ed&_ZXangRgF$wMQU zJy$~XS77*va7#)X$9V56Q+0UXdi4-dbo||`*9*!tQ1fk*q)}9j&S(kzB`40*D z2O(~>1R2!&w&TaE^^xEGO$oMC6)5fn4?f3+COgolzyybNc&*&IIR zMO61!FvzBap-gM8ug=TuAZ<2TSqze#+@>wm5D^S$`3CZ5vyfMNzdAuzmM=prkXId{ z_#yCR)vMpCfZdgR(R-%*Db`G#Uvx~+m|a+l1E{kH6sP#k=~5$y{GLFCNFojUEP`V@ zPHnj6#L`+*`e=@tB0|;I{N!sWxgA^5hnzS_HG!L#m&Z~=c$%W{J2^Vqkt$>`Hg+E< zmJd&R+lXf{zHSA5TS!^j_6-0dz>yEtlOtE-7J#Z4Sl$01U>L9y1!Vvp^q~ez-~AOV z_N|B3?T$Mo8imZ?-N)QRyjl(BwG02{X%l@W#~t=)k@(yb%nKi5{GdwYYU1#CDGquW zJ(?FP<$Wh>BqfhQ@G)h{B)xw2R>aG-B$?r5Z@8jvxIg@5*Qbf25l?4Hjmaiv=|_m+ z*gFJRsIh9*@piAsk3HASziW(2lk(>~v{ec`w(}=BMpjx~;E8z}fpY^69Rh z3IC136zW^_P=rKl5I-PcJ-F(VQMPH>8_y1?8D%RXH>ML`crJ+Vc98%1k^hdJshH2d zb$~^Af)+V|eRsBU!>{4-TfRqT?5mRqB}o1@6qZ{ z#nqs#Hz$(hw*i5P0)9U$EiZjb1hS+_X@N4EGb4Y%KsZ>{u&{lu0X6RBLlG*^s{W{; zpE8?OveoazTB=Lv#hP7knr(q$SmG!c23OLU;yd-8K_T~1Wh&@)X)n26C60%rKm*+e z21ULP9kC=o=eyElu9Ta^gUfbh>}=bsvJMHLura%dig#$_9Xz!|=YD)rX1nZTe*NO9 zzpsPT_eYE$!eBG%+?hwbHbJbWZ{umwo^|v@%){Nqj!F=IFZfSGz~Y5T6T|I-KMx$V z=U@&GVL(>GKIj?9X}(;WBMByE#Ny6&zk{h$#DnN7+dX4r`2GkB7mnSw)HKigfQX-y z$h%0dy0K-eI?p)QM!9qg!Nop-6tO3ls@ys5vta#hh#n1o8H)WJV#)i4n}Li{?on3& z^S+%i$Ob2ZbP!goEE_K>K7I>5r&jn(=6lOp;6 znJt3l7|Bz9@ws)SVi|>00O>zr!V?{3HEd6CvHbjuic4?%%*(y+vY{!frQiSdm9UZ+{ zq;pES_I!#DdD)8~-;Lj&@Voki!DlwuqddI7K z>+EA_GhBD;EK%XLTOeJ=-w*&MPdm+;?F(W#N89|gQ>KDooCCPqB#jB&{X=ae7Zw6o z`^xf3bn@!6wzv-?%`0@e_d*nGXHG}faXZ*<{N|ff@@lc~ss4V*lvZKC(7=lt<(I13 zz)cYSOo&ZhVxt^|zSQkoZB=0H z;MpNG_vf*-&P0EW2Mhqu$3+1vddm&-?{m0N&xL+|Y|m7fvXNtN=A{LKyRbH(s%XHS zDfhJ47G__&bC1$z_t;ptWJ^~Fw_#1Aft}JpO2%q|3f_y281is$%Cf=D(tv3Ne-@@2 zECYL91}3<`nj0TRKzBO`9Pv+~!S+Iifq##7W_JNr4jQ@l#68MwVhjTB+E|bbzhOkBY*^C72q(maW4+%GmzKWMkdcB2m&mO@1zPP!6!Lzi z^nw#E4>+j2h`nM=UaV>6{1(FynHKHsljr=RvWlU@)*_4BL*P@ilwb9f@5idPQ*H5mMm=5-O}V?rlu9jaN~t_80kexKgCea&|$FBgE-0 z6G^_iqqt=1Xng#`AP58GQ#9XO;+YD-j-?S(`8TnW_{Ff^l?8IYXyduTSc64lg9zzt zz!yKA{BMlEM_;?@Gx8B;Nx+-5xWHiGU*9qc2=>8apSes-r+-b)f9lLmmCqOz7@8QL zLoSxL1y___hr{z^8LcWWW~h8(r2L2xT4L%hnhv)DeVO;YKqtIi9j9miK|Uh~2d77@ zaaa6H8;cAMZ|?(h?fWcwY3pl792KUSKe&K{bE<9C{e?W$ICsfH6c z_!cz$lcCQA;rHSj_a?F^R;cLac{=KHqd+|>CK=`Hr`RycN9&ZL$@t*_f5q0=6N|Zx z$oQH7wJ5%4RKRyP%wv~LXYh|pJdfOui5){$;bHB|M`=) zUIe5&RE8ppbjxl-9;TgGkMh#mkz@2pu|<{|LVby_jy6hq^iorBP1CVG@RaGZm@Fcvpq`Th+0LR1EdjJ=~aTrG&WkHA|p z^BdZI;h7G10~Fy<332^A?s^iQ>B*?)m_-T;+5hJ74~o8{&t20Qrp%dP_nU zJkri2$&(H)qcv5SIiP%~j>j>?eytsX5&6J#f6te+Ol5(K_4Ow6LAY1@LDBqd%4{XR|A;$@- zv`OSEZA}*TySAP@lwq(KJl3_Wa)JRfggL~sO}jA!PC_U*q)7L1%=#H&5G2b3bx6I6 z;+5#Ge-zQ3CWIRHPCS&dGwjPZ6MvlEGI=~SntPY%bF;kSB{=z!o*%8aiji+^TMLbz zz2sK>LBZXckrvB8H1%N6>Iv8Su7@!e?>9jw+jW>Fv8x%^&*gK-E5eVTNg#?c&inhI zDVNTyyt;c+?>+*u{U zi2cJ4GZY5*ZG;-$$^+#C!hJ&94iP(Y>dzGPMO$G|7p$LmzC|l`u29>4d)M{o5mZ?a z^&F;!Cljy8z9KVhp91~dHq}M1C(WKPN`eh|5e4y-n2fwravbTe%i`Tr)*S_|Cgv|? zSpjl<1wbb|DkuKKZB zsO4XEy{5O_6CG_1+djJN!I!s}dez@{;)d_?=LNYbb(G|m2xrx_@ZFHFdB&M4rt{8M z9-1``_zVIGDJZ_UeShWimC?6(XmU>TCi!0N5O`gQ$I~uuOc?SLQtbhKe_1(t>r66< z2*(+czx*dO*ZvlSy-X3!9sL{`KWpS^Rb%k_J_JDEMKA$A$I@n_hYSp>=#llGuJx_K zcPP6A8XYs=A4^E1+47YEG;Z-b^5Y-7R(8d(O-ZI)fSpMFz&O2R%{RXfY2`{<UnX_yeznJlFau#OcY`)HPl>2wPY4*db4`?i^BY5b|$v3gl$a&)?3>v8=V z*Fc=%=kJ3M`cG#1d?=g_Her+|!2`d62;iEn9x$f2!~(ItuG)^bUPBp=UqEHp&^D76 z0F)tynCvwrOxt(Am<;b+N?ZoKq8QNDJvD`t={w|V>AYzF)D>1eb)?r(E-JO&AlrqE ze_VU1!0jo^_@Uj44qV&v>(280kmD?^7V4A;yz3-21gx z9k0;q1-jsw2%rFrERHw@sieJ7KK03=XW@#cS(uW?BzGT0%bSDkx0522!iN`VWbm~2 z6Av!2xvXT&*oGbZLnw_Rt7fSke<N0Y)W9<`a)Z+HcVZ;g5_$BF^$ z_KFt$IO03-ZD|4EiTc6?o=cJlJ61P>tc)(DYp zZP6e7{vuQU^SI15e0Y2B(j?JMGhQGc6j|}_dmMdwM{{(^V8pi)Fu*J=@a}f9^ge)YEwETw$OSweNaSVC%V}A%Bk}gO$|%db+Ojb%p3ae zlCxJYD!jD0gyLccWd15jqFcyuy zdiWrLRh|(tym21IF3&0R*IbC|HNWo085a9usgCeurSV}-xwUg$ZCd%UILk>rflR$`}f^jV?m}seFle)-VDB7sx>3dgSO$ucz3n; zD^1f%%o27%;kwLmeNx~ATdHdJmZ7M zYL0Zbm;K~n%B}b-47+RYAr<7FkwK+( z32&+JLSB4qG^Wn6fi8W*T$VQbC*)yCX8_1vaN{ft{<3U-iB~%0z)iVIS|OS*=^$;l zY;bj8Qs)h zwR!zoQqf?k&5g7Fo24DK4tUhchxAAnn$+O)x$K#X$ z%=(;0ithdg!LYsw`N5vWy^b!CQ|GRHy-t?IO@fFNG6Cc*P^pRT@2%%X|MfBR)Y-ew zxG1>WsPFob&S5Yi0zFEp9tAd!AUprJBKxK)FPjZou_hDRNEnXLrbW+v*`f*`UG3EMcqA&4MmE+Rkc>t@eV#tb7( zVI_PoQVI%DbX}1m7;)42RZFD1T~EnYZ+l}|Y+HTLzx#LNqgTY)TZ2v|ewg7_n;_GB z((NS!l`)o&>;lz!3GOTZV&eb{eb7(#-BgNn zg)*^HxZuA6u$Ta;_toy~3`? zG>@2M%1u<4*emFFoU9Pz-&$0CdUq=7M5)P(!w)-D>Cykk1&9fQRLf+?Dm<7JUAk>d zTI*3*w5;W?B>n3ekU>nkgk->4`g)Js-%)p)~%vIy$OP*53KU z#SbQpzTu>>($+v>6W|{-d75DgWsT>~Ne}^VL)POpiL%$bZRFZoy-x0wawDHQb;6c4 z49JLU0vF*)Y}nUfY_qMXxbse20>6CKdvhipWV3h9vLgu@dmm=tgNFd(SBzAe8$6~o zDUs2S*E4y{>>Y4qxJ&195j+@FY)V2|`1;}^|BuxiBMoDWv+p2&{zfLuRM-#(HsUTg zTEh_M?hwHF^K)BhX-Rj&yiYHyLij8Wl21-Q1sVAoe|20dFM$4!z9J;@c#=2 zEje!8N0!`GBM(>$!g7x>z3$6i?F>Z=B{Mf%ui8hxB4kF1<76Idjw+*}zj*9xpg;-u zh~TVRD=6fmWcxw^#21YIn`YM*dRXxZGD2Pbv~qi!g67Ajo~cD{XcBBmi48f<=eC#l zHY~KZzMfU6XcC>92HbM$6Ys0r?_&3>`y-@&O}h&iJ)P}lYRQ!ZZJhTb6gmb>ImqZ5l zayW9n<=oYzLy|SDSUyN^$c%@?)oe}+HXPsOO&g`7ETUle;JG>(HQ|vwUi<15W0H%yzw#FF1 zBhSf^`9AFCAxsQUJhIDSha_FPUs3mZpEb>Cm?S@^-yW<^pYuBTIT3{ka73Ikz0ruIzsVp8ty^X89=Fg zNTf*8137fkvdsfTGm2c5Vjf9nD0exmiZpbD(rS@PDI*E>x}rITOz^UV#zOJa$;ESS zCD*HNYRDm86>|p{d?4fCP)vTvA-hkGNr$2hyVcDug?CqhnGDTzp^Yx|cFA+Hirk7l z=37~2Q~uTnw^BWraL1L%q-vWQ;3%LF#s6ipa!h}wF_^$;Kivv1E$n}wTgf$GWBuc>6jg89exrL`H$wvr)hX;v<38*`_| z=AL!ZQ|A`J&DRiwiB07e9LFFXF;wK=@`BT2$Fba6X3Mpto$N`PgO{%lcb67j4OlLs z=5yO-nzcIDgQot!tv?|eSxQS=wgB=|!aAl=6b!vFQ3GF8f9*fZ7r5vykl)}dU@q4( z(PDri3nM0plCQFg9~Qd0g>fMuji%1?zcb**KE7s#MuxRWQ~Mi?y7I>jcX$8yVmAR% zZlS-Wf>qvaD^_`GyXYt;>AB^>_PhcEACQoukb@^2)_JB1yCk>lJbV-sXjMf_59f8# znUmAQg>1parVdBr<&s9=5l*@5eQy%5#ka)Dr;mi!t`Nh6n{RkQiEd zm}~g9=^41Mu}ReuWc{r4_=D*k%POGU>tUo!r{Br{DOgmVh6+Ri>H{Q;Afl|er#yE_ zql=Bw+aL8mq2{$X2DW~{hWI%ed3l&-C+%vLI7if~lxxB}>&)==NR0}#+OnBtF9_AF zQ{{N$+9w(0Zt6-f(8GsVg;jBnduOYBXzHZJ{89_UsR2n1Dyga}o4Yp^cp>fo+jCC` z?d9>Jbf>@`-smc}d0DYIcCXrV3FIT0$7E7aFQ-k~<1@Q6Ki9wNU~YSrgj@^RGVJf2 zsF<@^)dh@kOh{4HREZGZ4=(z+rLB#NR479SO8hG9(Ej0(m&oNK6Q+EMlwPpXzI z7<7He-x#&9_tlknqmW?R^*+HVu340UxBa{eTMu)UBp>?BjryEO`sY2mWVwa6Ra zLff@a?aO>*e{u>z_w4=Fo3^5=rBAoJK0uvlz6Z70dq#u$LbGd6aEN2(n%chdH?x15 zufg74-SzjlV{bpjh#uUyeZefEl~ zeSpJ}ZNv9v6tSRo>4OX~a<th)PZR9$u@wjT!oaHGApyQ&Ao%0u}5421)~-} zY(DTZ?7KAy+hQdL!1y*$)q23$1a9$Bw5oHZGkh~$PhNO zs&a&c+R^Zf-Cgeq5XatAk!F0Kl2c!tXuQ}@3qbv?mkX&cz0`ztDxPMLi`lVr%)hoJ zXyhlOFyNZPxQ2t`lZ}zN_bUg^4t_YJJ4yMi>Bn*NiH#JaF-gbe9NoJsVzAe`qMBcm zo(G{H8wnJ&K*m?Tr`2b698%qlcHXrOIE>Dav2Z8_1X`x|=f!u+&M<-i>Cb zzr{Y)gAV%ML|2O@M}2iUb$fN@K_WBLKDz1Nc~+%?fE>Ar7SJRr`4M1ywGgNqwr}SW zpU*>7v_9WOg!M_X%oj0OY~1m`b*{XpEJAy?37>Cpv7;^6mVjlGRIkD`IFpjJ)n?}# z2QQBMhMjNruT`M7f;hTNBPWIsq7H*u=@C?XzRwT|Q2I-s zE8spUs8MA&?SZ~oWtWaex5IpJjsJcS<~MEGq(|8gTnEsu|{n@oe53|vO?WI z+CTM59$lfqTG3#?Pq4eb26hHE8kS@yd?X^2;$+NeKJkm2rF_@0uwRXi3I0!C^U3ie z?s~P2SuvxQy*_rROQG3+WdI_Z&3c0}j%Pi{VOgCK4*a;jvh^6N`w*>u_u{h>Xzyu0 zK8IkHED%R;QDCh07}&~U@u64f26e?S=j|M;mzOsJ1wIQWp|)4rjDbkWh6s^?aio%l z6zM*fX6>e5Ydd2W^(;wI6yZPc_I_8sCLXZ_{lnhGwitiO-HH_!R7X9MD3IZa@rxLR zcVVR=X@FLh$iST1w~q|>D|a11j45ncmWoO8)$M=zyw-ZKA#F1`aJB1}QTQ94!Sxj> zKX%t#+#SZDwS=CnV6z{gk=UkP3I+-~M<}^0|F(1XpUf_=$0k~pANd`r+n>(?djf6- zhs$GLrxHnFKMO6Jn^R>;{gP#;tI|S0+gJ4Izm`&)%T4phztyUyH&z-)aXIMDq#~#| zEbf*Nb!nY`$Uj@^qfl&6oQ#IhE}86=++Z;2T!f5H5M5zhF1X!1T)CFyqI*7Q$Gt=?;f9De+!=p z6uI)n!U%!Ljbm%uJ;_3ANtC`T2HE8=H=!x)m$sLs;M}40=_r|NJQ>dTqC0PJ(obkR zggLTsgyo5!_+9Bi;mn*fSyR9vRzl{2+fzO1bjG6p^Wa^#hvvj~-ZBm+?a znMdVN4UtTGX#GkO()y>m72SezjJ(;BY7`mIUK~jPI%E<32wyS0&uqG51sEbYa5d1Y zj~SY7s5mJ{d3w7(AoO6+efUR6cC}tijGDKd#!W|_?z~et1jsdnf^ot*&2*KJTQK2- z#R>N7zq0zc46!H-FfW!nL;d}V!0F3-dmNO@$MA{B8h-H+z8Eki(1F3_#V{m% z4&k<)9paq}jJ_niaiKRJhsms7lkz9fUFXPny~=>&U<-`exi&!b0wi7RlQB>JF0{9Ed> zh!|^U;8lZ2zzJteVX}4kNzq1PGbs!x>C0GC!L?P8S{~_gpGLm%_kRIKDGpnX?Vs{( zR7*yuI-e5LO#ZEbt5BBc6}4OpHtV1HOHT_IYB+%_1G7WD_(xo!#&c+&wfk-P zsvjR;lT)DOd#eG84y>Prg?HU}!nfm_97}ElCZF4G4+4<>ilsBux--ncrSt6~$gm5c z)-i?FVk`0R;J|D-Alc!hmDvfG=^?|b;DgQhv%$@GHV!Yf+Hc8Eyc|p($B8&OuR}pr z+O7%t=xk2Hke67!&CR<2;B#gd*3C|ApewA8KgxuhgMH__M8T z>0qe>Cg-5+!l-av|KI>vatd}5!j4ORmz^{;3ryz1x>h+i{|5r-toX5o z`##64F^N;0c()qF$)2=-4cai4*PKYt$olp2_bu|4yw7%ELIqe`7>B7{KOX=S{fefo zLY+Y|>iHRqpHwI4iQ^Dfv^Z}0n;G9b;^-6n`&IbLfuc!dm{ti*K#0Eg$bUg z2jk3o9ve7J9tkCRBnc*uFnnYNr_TmZBp-O#h7D1hPYIvR$nSPk!v!mqO+HA+5|_>} z7(RMb3XvZ!iW4_J?r2tU-zgsanu3}o{JVqdQPdh{*VDe&y!kj=qXm2tdUKOuhYeo& z9l`!w_dAFo^VAa%H@=Kk(_8!{ge{4ek|b=r&J=rnj1vvh%M}mY>AXDEy0tPQhP+Oa zpx|R7XO!R;qO?atct5$q6yK{2omRODp`ZoEFAur3e3pA9n9#AiTqVY_dg*UhhZlte z?^lt;4Yd+8ZwS9|*{1BD*piuy5$?u{Xi()N!I;EqtT-}L-gSTLPs&_;lAp1UHh=sc zu~8e%RjuappPr*HA0RGW>l9di64duU+AE{ z)n9nG6u9<*p{|ghW%T6Z?=ECTm(?`^Wqn zNx_2Vk9iJPORmUM-_r(Ul}nroD<)(1;Aty^f}MzqP`hPYQ|CJq+EY0_rSsaDsItNE z#PB9^a(A#GXY|v$3;I-;r3OBmv^_FkB1#rH5J9lh&pfKwGz4j{&(mBRaNcyj!X89L z3f;<2)ytjarB?BIRdEKm)PMuDx33NQWr8VJBnJ#AG?Bz0<3?}vno2RGl{)e)l%tbA zK*(yW?7faK2HzBm{n&>87%W4xAzRLq%XGO-yV2c#&4EN-M$ERUKC5>KcsJBoBbY;4 z2a@i**Ib>#Z|3RYaxp8auv}AHDCu`6?b*rVaeP5H$yt(r99ZQ+_Fufu6Hip8b&UHd zmEK|*OJ*zbA@@9?Gc7B&;~Btg#(|R|ZbhD~6lt3x1W>h9JPl@FuBK79snSoHii^tB zgRShPL0uVkM?KnTvET3tb*abiywE5lkN+qZ@LdHzbcIxtj$FgiDf_Hf?+qY6)qdef zY=|tBBDe{tSbt>tice~Lh6JzWI8x0fVt0mM5<*J|BFj-B^QgLy4{f;Nk_-Vf;3?XgNlJ z=~zO8A@8Cpg<>QTRPxecrg=P~y>&A-vsJD=liDh%&p%Bd&dOn%ZqXiiuA9SOY5B8H zVjP0d?Kn&Ls#FYZG~YQxOYIPBC`meXvRY!J#{6Z_>FW{;X9GCyGhANt^tM;10NABJ zR1rjR*NvHMZPjJe@i>(;t$<0J%zrO^eBazCTg7@+%;otZ=rK>*$@26oPvfIHLn{Bd z^!1<o1lr6HxXO9TMJTmf2v=#`3!AUW0~`LW2U)Q!9t$5tgW*-k zvmYMsX&dcoW?M1%B(wmxyu6!QH|5S_edwbETk4L^S=UZJ`|wKq?^W58$EfA|L61tj z9p{dtm>{Up3$Pa;cTy4U`v;@HGYhBO*I2Z(p7$qzYn>1y5~H}nW|~j1e$qsI5WXOl zk)_$iExswM=nV-{vN~dwI0}@fzy#+?ho}*mB(1)f9*(~WFvPN=zZZEkEZ}%i-Ql&R z$`XEUKkOM5k8;_{8ykJY=D)nz{GHccu40I`#|LBxo!uw9PI7BVpx{(Gg_1y30NVU2 z{>pVolrlJTmZ+19&oOk zV1euXa1gcx+wAZ5=`oF>O%0z2TTzDrgkP8k_9o z-?c{*K}$HwuAw%UaQ(Dt*h26~%`VhYBlIibnwv7Gza z>LUc(#ImMQv^=eMbC&*!*~?9V$^N0=Xykf38H%#6-qV69Az(_H7Qy{&PDBua8EDaX z5EIgC@i9>Ts8t++z^u2GSQN{QMGkv^^)3KP0LcGNKmH`{m_R zN3WlnbP4&#%W9;ym#EKVPvFL_RE~oR67!b-D-`s`4E=WYH10L)U%hwb*pZJ3O~Q+F zKmGLmq*{#=Us_wRzsj-4l9Cc06f$CeT>lAM(8${HdtXFXdEoQMlqt7dGtql}otI4v zg~AC!9{eG^!22_*wRWt;s^`L1zFz<48wuM$?bzD?#OKRQ>S?v_z>+kKxc!odhuEh$ zv7Z-igc8(Inu9=hvjOvzzZ^UB$3pK`ko0SQKig+ggZkhVP^dzEP9I{h1uqQ2%lxN_oeno2}?y4 zQya7wI>%~cdT$%S-F-d(qQ2iXP>p{wVp@?T2-f&Q8}_h{c;byoC(n|ydY4&u5~oc{8^B_>qW!;NJ+- zhm5gPgZA~Hx0j2Hi+KUb_B-?LS5Y{KQ1b0`yQ%}qSV-H|9CzZH%B#s}Nf?gM=)a(k z{Pid9N+93A@1y{eKH8dJx)$&$t=-&SWvjJk>MNJ|j&h_jQ1axenP!~Fo3SkIN7M~) z$rgYtbx{T#yLq5VA(8Oe!&5uaN6b;^ER2%Kl!~QxoEy8bl(D`5F7HNdOZ|+F*c;bshSLIDyKobJ>CK>;mxX6I z=%|DKAu~ec+pYGylLT~<>pw2gbd`Xi3)Qs9aK1AipdS8S$eS&#;u90`1B4fR)hTVV%rp)oX3VY#mZSR)ETp`g zC_MkjmkMBGP^DS`uCMd9jdMwL?>C%_)WyLT^-H($=#o3~O6(~WwnGzt*B5rGU-C!B z(Vay44pY=!%*_i`87M+C$;DbfPwZa-y5_0{CM;p5wk&WU3#y`AB(^2Iq5| z)@na;)>uq++@j7-;qSxF6JN!@y5gQJ;jBDRArEG+dV5^kS8Uw|00iJ7^>N4C(Opc4 z_%5757|UpHFs6GpQb&&1Pjuj9xBdN#pcCD$v_PUwXci?2=-+YSq7a5Bj^gj!iX<(O zMQ&n2a?fZVG2|oZk}|wyA%+EdY{37O0pZ2cqbJW5Wfdjk*i@QVk|aU&5)AS(e0-)k zJ(ahK9QJ@=rL*dC(ye89!;Zt2u0(mtP}mtHc^mirz#zw;>P#F^OuE`GxWWK@N=Y?b zi0t3LPO{Qw93lPx#|2>PcwsmY4#B(>V)s96kHO!7+gw^>Zy@(qilO^Ypx>2xlSsO= z>*r6^ngxmc-_-`~o@eW%QIhZaf9+p^^MMf;DK&QkZB5M??v*A^%INY&ixsW|Txp<* z7BfgiX>M%%Urmil(r(yi6MtK+8qI)`FTwQK!(Feh@wc8KYWb?^nVBei#s7_CLCVV! zHG+4mz5*RmkBrUBIeif_%r>}4B9M*J5e%r*XiI57Hb zr?9Z_KMDFvK-D-$z=P>t`-gR{0Xr-RX`qo00 zuFVHFD-2D;z)b2_jIlC&+D_JVQ{cL}h_Q5Z9d9WGe>cYd6U)nkqt1}Yf9?x_SbjC{ z9}7{prhDqN^1G#DFfL6bCdim{iMIfVVE+}xW@O~7;3n?6ws+Gh&DwgTWBzm{i_DKo zokE<)?+c?K@B3z_RD$HOX>mPer0tliI}-#!r^k-yniZm1%DGq@A|BM;^!JE7Z&&6T z^LlwWQrZ;)-QU0#K&~kkW8r_8gZ_>+g;AFl+K5>6&=O7cFnD%d604i=6`v~#7;t81 zPLs(wCTLZJ9p$Bjt2}81@jYuqL@%5eAnU0hs9)fl0C--iK740=8wh7fFL zWMsts`e>nhdUSMjeEbd_h*H3?2yDVglRO;LwE60%|cF;+p%Lg9iaORs8x6R-62LCxG&dL z0zp=`XXe12A}G{PHM0Qtn5RqKtVGbo7^<8k!@{lA^m^|b#JdYU}b-{6k~S6 zUC)K5JXp>n=oi_Z`hy{Ht;VzlmpNAfYIflM_+3Q=_@NIl@M~6{p0{0LM&NDLHo>dD zg}Iy>SXi&eA6y?}X_oB%0tJi1&r0It$AABV(HESyczOxE03rQ%@8BcKKA~WKa29&H zd9ygcTZxyyXj&a67cu_D5~?ahChGoI)tP`Hjsq%Q09X}BQq}(axyh$ozYQj~>ZLC7 zxCT^dl6-+bzqC-E48^_WM!V`GGJaPYhA80N$kOa%NvT2dRaIqi|ON9;a-UZ_W~Vv$t77`{-O zIqF2w)f+vLTS%FJhdX83nlSVw=zk>2%E%1uj;1|5JtdHflA%ZN_g&oP#=i=W)pHZN z$(z-t7ux_4LSu$Yudeg1b)o*n@295t+<_z&r5xZ60BG_PQ0yp})NO0}e_~{rI56Ay z7WTSNY3`3|BDlpZ$(E%9?0$jC(aZ{1h^)4@c2H2zZ})`!k{Uz%&+VS9zxjoK2%^A; zRH39M5A;m!B-SA0Qyi9b>$hDjJ#vP@eo^`FlVi9Z>>d}Z6bq>kHRgKDZmX6}EVhD` z(L-^^2?OXCNPbB9c4~t+nyU&2FE!cvuKKj0cDNjkKQPL4E7T6eaI4VI{?)Ty?)rr{hLb`VYYqz`?;eb>3)g;)1~s zBxZ6xM<>l!5B{5?Uw{&P9nVRXJHCRh)-(9*y?wGjt9YQN8OX{k)MQ6vIce z{=A^D9zyCT%h2Y18Igo%1JsRw2sY#gk)&9ShNTm+Nll^Ji;Yw1QMjmf)>^$?t z#+LPxWN851ay^B*rOJJu*ji`4cObwuo_pMxZ;bz=64!6GhQ`MCF@qk3&!OJ{CwaX( zVCopaW9>}zusFYpEvYCn6c5`17u?=U*`T0;KxV5mGdKj%h_s}nq;76*UN;YmeA%2O zhIJ95)3;p+U_Rr}s74NXj>Cfk@!6OIoN5xMUu8Xbjh@@vaiL^-Q@)|!fcQ8uF~N&K z4tPa>X0ywjpH+mX!HyF9(lD=?NTPf2j$TGXoWn(j*TV_eOZBp33tgpgNil&OHoO?G zl)n2Wn*{$KCqC3*b9hiv?Jwby&dvZwN5`*@+{}3}W<2ZjP5U~Jo1D&Q3@R=a(Euul z;%WTwMOW8!2#a<`VLVzSuuLtxbK!RbIA4-#N+{W)wV=Sv#H6?6U73rl?f?E=;_pBLAsC8(oei9YPO)0Ic7Bxy3sk{d3{Pl^nHBK`Yfx7 zz>G)SOUj%QO`s3(hA=}p`>@p{diXu6{N(Q={ zZa1EdfXB(uzVXiNnBI%x6mB2PM@v~v_id##?^UKf3H6Uv=|vMz+QV9ZNhLmj2mSR^ z%6)y8%uvetu?r1keps9k(EoPb?#bg-a+6zZL(&5?C*x}9xR9PR&7{O70)!2?P<=K&^ce^ixf|IDAAJ;ooiIh} zn$`Pt=wtR+P9n!t<|s+C!2ndWH*7%rlE{OIhCNgIeX8uDwqs~+hh}nG-$~`miB0}2 zC}`QFw&AVvR0}8WI78y;zPL@6dZWDz(`CIEl9DW#%6q*oNjUK&*gicyEs#m@^zaCy z#!_yOE>xgr)Q*O=>K*vrU`4Gpf#RhH%;|^?xs<9^CgkXE4C4d2)gM>xFpi6{aw{$U zp$L6Z2?p$_%HPtnM>jghTHYTuHNW0ZCCbu#`<7W;R?f8FL5MS4S7}%g73)TF=yl z&(f?`z9*Vfp@Y>5Rpknj*%agEN5kUYsWR)aM-CJn`D&b-WLlPeO0w_?gYQr;TU85* z{f4b1bJw-5H=oXDmA0SNe;kbn4>DLdx_ON5+dO41>|UT9qE3S$kka# zqo9R#bhW8_4s!a!pjYVCy*gjR!~~L6M$j(qZ9co+)X^&Fd@34CT8+-2bvulsp#JF?PQayo1Z@_@`MG+ zh{^q;G%-ziFZo^EZlNCF3BLRisZ#S7bR?5rhnT&Gm_`hoDTYn2x)dsa4Z-2UnAeTKLPpq}a_PGV4l> zMRUKa9ueqw^n!5x2!G9-Euc3Eggs4l{;G{Zg*8!SW{3HP0fS9{6PMb>P1`p$-PGZ_ zO*zJd`x{dhB2CQ{lOm!GG*B$piYLL8*gUtToH?VBR3Aa}jXGtXQ@re#Nh3QmqVNmZ zxo>t|8u{7YmRK_bTxbx<`3A)Vl1bNz4&XI4)S2;lQ7*A71K!+=`43)O;jJ8P#XY1Z z*tSP=kMR)9We74gw8vFcOk>?2zIYr&{w% zo)89P>D^ejm;ue1NDdmTJy7tctS0&i!MQMg<^bo z?{l4!kEfF&Z3@uXFolrG%rm_yCZiHW9{-9f6b zWuIN#B(C!EY;W$r_g|bgzkTL)TEch?+<(r71s@Hc`T&)89H}GUdI?RZHCPbdgn?(A zYsB}d+m0m`ZnnV9gWcJc(No-7gE$-EpxaO~2H8n|e#>Q;G`S zzEFXA=(ZEQnxHX1-@R}{-R9EX8ej#G-MpQB)P@ey(9i&`sn6>8|9Nq)8_|=-)*Gkg z-kJ&ub^e7O@xhFK;K`hv%n_Oy^9!QqoyLOQ9f)CH*UJJbN%KFI!IVQTT7dhksS!NqdT{rK_v!SCbrI#*~1-+9P+-SchIN>GA1F|AbJ#UjRmo zEzR$*Ne&34px)x3e>)x|RY$mqo6MrUt?~7&+ufSpIiABZRz+DkS2Sp%bm61Bcx?UB z@$1V|Rzwx>u}#3!OkAe~D6=#Qs8r(2BZFvIr@LuCiJ39Vku_> zN;h9x%zz?Gn)vu`rF!Ax^KViK-F@q^PVc66p$wDsF3pQ}+_30I_Z*1q{?AA|f5ah?!L< z3f}lsJZh*V=LmW=38<{v>Ci)DRa8{CfRC<{kh+)m4ZT5 zKV;ZT|AGm2ZSAnsq1QR(yQ2~FADfZHsm)sa0Pp!yHGM@9Mc!!~+t!paiIw%KE8uOKYT2P)2CJPGR+tTMR;d`wX&` z1%EX&DX%)#f9OFX7LzuX{TgNkmyQ!KSUcWL^d)AG*NweX_u4_Iil9(uiD^^$4)s*4 zNh+BIQ${Z04>Jl^Edi%bW+g!xs~#**w^z|WC_>FyN>2ElY)5#QvVk?uC>VL0bzK!< zIUF4DIm7?8crv2eJ)%^4dEQ~9UM6=?XoCKXPOetWdl4c+CKvP^)Bf{4iVS3}6W3-^ z=l#){b$A3tZzOk3jd;3*ZZb!B<@0-ZlWX9FoEDU9;8frfQ&rB?$EMTeT0~;o25nU& z<{0S+OdMCO->+Q8O@3^dkR%v-Lbnv`n${~dB4$SqtlN7(>#cvMZA7W`C7}xB5iA+} z2vQZj>YQ#=3E5pm(Ps#CVOX14dsVhGd99y3s+SlSrdDg1&=!=ag$D&=d*C4Prv|&} z1I8bU#L=4HNSgg0d@YVmxoEs?Cl$)NHm*#YQ!ArI<=j3Zs|9my!UM$UIDWT_of5lp z2Sh}~+tU>*8`6c8uK};K4YTCwY47F94FoSPlKehGlWwCje^Dtuho83Nff^9^0pc|m z#s{UypUNTh7*=D=N^UMJ0s)N4$0;Y}HFPjyuD01~B^<*YD~Mi_G$d_G4ip}z{dIlB zv)RN^c=YE@`&iBp(xo}hE3v3ituOilu;?I~b{rho+mYXs%06En$ebq#ExK0HJFy1B zbRHKjG^*7uSPT3gUby>~PZwbRbGgBP9M~PZGP3JbzTebNKFYgK?e$m5>o|Nl->^9# zlNM$c-TgbbSJ>x&mTN9O-h@4qWPF7aDg_(-@bDmAkZ)~LqIA=bRI2y|Zue7BvDHUQ zs0^jnji1ql5IbgpK9}~_<3_L6S408G=8N;ebkTd{T6TlB1_4UXZ{x1xp^Jm2E&-gh zW|g0q;$mYP=myp|yVkBc4i0P z=w@wH7uqzgT%o((spgOQ2f{haS|*1}_4|)cO~ZBBllu`75yX3IZ~_P%(2?EC^Yil@ zY*QrO{OTiRB_;m&8O2Bk0;m9*ltG2}jf9)YC%J});&leahk1t)?2S7(WN$7PyKg3f zzu2c0BRdn*l}A}6NIO3@T=$OH%lNgIm-p%ewqlr6wtUv)D^2|Sq2Jn0CehK>7}MXY zL73%#618e0=}xqo5NOvJ0;|s%X&C$?_;~>>Nrh#Nt-;-8{ld}6 z4QlP_LdbDl?mqK6M~=vmd>yA|RDNA=m3%ArhY#viT3`7ttB`BSX||i4h;ODe$|&G} zoWX(|akKI&^mTP=qa1E~Eg{E(5vcmaP#v~3R4PUu98(D?daEvc!B+>+xh0z>+sk3K zz(PAVLjV#I(t={70b80rj%iG~a!3T~KfbtJ49CV5tC>=5%-Iu=fhSMzwGgE*8g==% zW?=fcxJ@xZd)KnGF%S)?o$cP{h^(=6Y*u zta8%>r8XlG*O+b*TXYWng6VHCE zZ@d~0lTT8f!)(Ri^q}e=dHuIQ?C4p%;yvl=#T#3joosA5sL`V^1gzJRnI|%O22~XTa)zZ$H5(h7aVW@mrN>dJ zOE3BzHxb$dfj1t&`G`8z6^ zKZ*N6C5<%GK@Gf~E?;5MCek&tJ)p|G2rS&9ww2LqYw!w}4i~j$3JNogy?2-p!>UDw ziB(2#7OS!9z3A@eyJ2dhM1i}h>B7Jh3AYR08r?m=`9C^;djvrW%of9CREH1hk<@ax z?q$4iU12+_qmWF&T_1)x@fAbR0M;Myw=;p(Db@Y1`MD;21N(8a<&pdQdjO!2zZ{ZN zgR*hRDFOcFIIPFX;cq$qIqG2|@pLAa&qnUy zqLqyUn4ceu%v!^uRBuyLegs@`ZSeA&Y58=WFNqc=q@Itid@FpEqzp80)ETJew!oQK zl#^kfmr;g3#n)QXYnl#l8Q;08@U<3*W?>w8z3qM${w*a!b-aBIs10;ZFUM{9h*@_wBJ zf!YOX*wfwc=_djQ2$fFrG%y0uKw}D`W$$u2kdU_8u_Cz?X9ft6u%ju6Bc5{t0!crLlp1iXKEczAsK zU1wZSp~;Fl+bWFqL``t3t}Ma>a}6I>IR`X5Y5 zNy+~HzP{5=+v)1+>YqPUAo!G}`>&wjGoM}cGOeohA$=V+ac!fzI*e-^aQ^fS>YShq zfm``Q3T=_!1V0QYd0K4hy$~!AEZOKk)6U(5&0D!tJQyDh@;8%OS$cXpI#w?wMNVhr z$Jo4*n321@FV`y;uVx2Cq<_{XkWFc1@P3U1L`O##f)(o)&*}J*`;P_IN0YslDsbJ@w2ziaJQX2Y5oe&oO3*g*uU(7Q z-*PiWB}s@X4TwmGMjl-(cO(*D!~jn4%vwB?3~0rB|7jy$_1)ily8$xOm1~LzT00LL zwZwRgdB2@AA#Z6`(gyW_L6MRT{>{q+@&2KicEG|#0Qviv z)(n@>pJ#rvcl`T?5_y7GSC{8DRE)VrPpL53KqdMs^jL==j#wI2ZeXoap&n$el7n=T84Obc|FCwJ+ z@Sh(?$OTbjUj{k7JeRy>mJ$2GHoo3Wa8*yUlGkN+-AgJ`2Um~;dAF>A)p%F{^O)Do zL9eulygK!4y>NY#sn;-J)#T^2Nqikzo;AI$hsA8p ziVoGsYe7Pmm8W$n5D8z!gie^v*^U=rRWEnW<+ro_INK;@@|7c86D3@uL|H4K^<-`B z9p{is^x%(upZRhY7YHk*H{w6ClI0h!d4>r#|LZ&|iM%9PZ2uZ91AAO6ZTfHKT^g;o zwYYM_FYKUTQLjedlL87J?kiy~(X!ZF1(N&lJR*u%b=v$r#Ftj)UdMr~)=#aMT~>#4 zQ}vP$3HfU^j7u<9_x+b)MlCn$M+P0?h9u8Ac^!~{G{s%(q=(!B{ERbSv^6^xenVq9 z$1y`~Btyqsf_okABbH*k-g?EKlt>_R-3h;-oZN20B?({=I@IQhCInO2NAlks%R^u&hMsFkAf5` zh|iV7?gm~u!%{rV#+b%6MPF8Sj)KT$%L8wb8kbCbk**qg6f2*5jcD`Ue7`ZT^W909 zz3#mr4`>U)x~&}^gZZys78Sb5lmF6p&oGQR1D$YJntZxtET}Ti8S7*~w%a5x>Vim( z(gub6uV$smN?wN}t-J4Y62rO3N!rlGwuQ&MBCs!x$#{|oE@LmtL{(Xlg4uBT6^PLH>q?x-92j&deL*M|UWXtvLOSLp|SpEvKMlL+QqE($3!`IH|Mm_mm1MW*`2K z3y_qR!uA}ZA-{&0I`{j0Uoxhxu|qQxSn2a&7RPR zesV{xf>eWhM{E;BYtdYT3*ix_Qt{%KhyT#6)t1aq+piB7zXF^h=M|(U^l!LSb+8FP z9wTx%ow=5Pp7eI6pHlNKJ*3WeSd@$R9xE&RRP;0b87UY=5-K@|#Q$H$89l^(FZ<=V zL{5tVziEI4txN=Thu3OAfUW;c@>bp(`rERH5npo8<`Lf_GhD`+Z^}@{95inaCaUDm z(I4mf9XJ2D!q$q+13azY=8RTu8_C`1uU5x3G@d5w#txf5u1DSE;RF_=)QUEPh6!lZM zeQW+;E_GQM_p1zWxCemjKC^MyXT(g~u1ysz&wM10JiYS=;K%R) zZ?o-F$~fgP-x@t`_}{5(;DNbZL+0%!@f3UhtK9vo#GMh`V3;E@@@;!vY1;{xKoa(6 zyPp<9iirpKdPi+^5m5jVMx4z=LlvM;BU#DZ(q%Ru?pDKOMLzhoTwpn1uhyRVHdx*? z^bo_skDoL-rB3lw_?I`p0YvIjPn}gI!t%i)4Fy1!IlTxLFpNpJe40wk;y!o#cb7%V zv5A@nPcI0H6k2V?)ZB+y{yF;MJx^7t<7_BnG>`S~JsV4Hagy-e(V3_KfZO|5bzh!5 zlV+t4_g$a-@tqVd{=RISDNI1*ciZnaB=DWfX#b2taScn-=kZJc*C=f(2%7)}T*OdmxZcC`{&FMm8J+}$ zanO1>&53QY_(xi@XrpU>c^LW-i!CF2{Lozd6Js+s5Up+rx{sIGQ$rwu4@ABG?&tS3 z1EjQ19sNK0r)j4!2X_Ye&Mk1`(hmK1Nk&T~a%=;B9q%>%uFn*j1BG4h6g*8Uqsj^? zEL%X;jhy|-O$M4pS7xt0an~ZMf3y>irrszu9vXGkN9b>9e%t|=Uq?;+)7+UgL;_#y zO(_q6=_5I^$FK1R5+~HezJU`Up!=&jeHD<<6UvNgriF^>__TPFKQj!6o~lMZ5h(216;a zKii8D!p&Pb^o{;udmb#|w`}4ceIGLlYqwrgJ=L^DW5u=5FGCnqBM%Fx1}D}nu~j;6 zyHgbbO1nlNZTRFL?BZ|Pi$;rX@ak z?S|D$eE8T2UumH@1>YR4*1r5$Bo*ab`o9Kvv}b*FRO) zO|GpQ?WYz9_kr-`7nw7=zvTR2WYRR9V)$0t$;<2y68nV?gqe~M*N8B;&5&WL)-j&K zC<{LYb4L8DRV4x&JuFlQC8p@Np*7HOjyD<~VzJXg$p z$-wBy8%c{3@7h#joQNTqEMO3Lw@3NzSaWTvr_`Lt>z}1_j*RF8hx+ZYs|qqlr=+ct zoUE5EdbIHQ@mpDu_eaIT*Bl}i!jotTf*YCR$ne{IU7wWfrkR;3Bnixs4NhH61V*5Z zE=3X3;Bp|_mz8f;bleSAvQ}H0QKkjUS&hE*qS<(O^4&zFPXh0gJDR6WYC5(`Jo91e zbC|dEw(Y9#?&LO)yoP0?_o)xi^utU<-p^yGR9(a_Gi;u@c zBut))+L0FK`&K|AXec%5PZ5;rI}3QV;CV(5+>|#6)}Sni^5PBe1IOQ!J6E49epP%s z5C-7p;8XwgE9=wk8|?r6pZ|KfDi>Vuf4!9T;C&n6|NE8ye2SNoND~~X|Hq|XsXTYZ z|GyW$`b+KBJF@>V7I?{6mpbjy|9WXCru{F$|F{fzGl6_=9iMUZMN!c>cK^ByNa_KO z`yK$&86gDk@_7S_#g!1i89eRM>W|8hcJUR;8^tv};GmF)X4$-Gn^oW-2cTvMq&vwj zgA{BhtT!g;+D&@z zzd^_Bev2#&$3K;1b^+nn#W`Rv`b|Z`gd8G08ZD3!6%yM0WO25j&R$hpOF~2h;Bb{b zBJw}$xoNNNz^QE(IR~2wINcDR^Q*i>^i>ek!;k*HBcYe_{2Je-2xY2bg))VgS395s z02%Y2@6X?{st5}U&s`kUf@brC8Uvk9wSV%l4T!`Bb`1|{-nZmDD9~{P3^HZIT>)mY_VG<*f zhch0iB7@=#K=phq-fYK#Z$$xR^2{=B5@%A0!8Vuxj-CcD?D^qbs~e_UD_}P^n6WDN z>(v7xwfa_DdkC0^BNdn}&exyH9@e8kOwwWic(PSyQ8BUChkxE2?(Llo%$*Gcvv*>4N=r+xmV5Bw79AZO+-G-@ zG!X_Cxlt)$iNt^Pahv7$)>Z_jI|6a=60v-fl-_S!PGbb}w`STIyRqSvcDdn#XcVlp z1Jm5?<7Z%CXkAJ$IoSMjdWJ(G7RWL=$ZuJkPN8X6ZsG@#1Z=;%C+0XLvQY>~Ne?Dp zCLZhqdGvkLZ0C|a-^-pkQ(@DWuaTNP{7Njw=T1sWN`=#@`iQaYUe;Ao z4?IT6*xswpXi4vnlKw}M8rjn|ub6#;9(^e;=1%N8u6(93Qss0HLata32;2dR64VLo z&66OGuojoTm=*vZT8(iY`r}1p?}-YAiVnyu#L=lprkL7ulCu=J~nkr zjWgm&&fMwjp}EgeJlG8_dw|uqX&BZl(g%{nkPjmnY~I5;gGX8n)|7AFliamzL2XC!vQ=_z9$I zB2Gp!mwjYtBQhl17L;U9hDj6dX4w!NragLvhaE350W=#e{-xMf4C zTVPi8xuEM;=1qu!K~HzLrGS1)VeSnCh(g!AfcOCFdXagAbhVjevgs)~uvg?1JI~ z0z>QaS8CG!sfGW(#U=Q+S0L+uvR059HC=PwNv3tSo7n1iw$lT$mw*lGQa2{okb*Re z5^OOjuO-;Nz1F+JnaANPJ{Orl`v~(@0L8bL&#Dr`x^|7>=!Z?B*|>!F_TRR`!a~Y~ ztI3gq2TdY#^yTvMimdnH-0|S@Kq?3so0xE2=@7e(sp>1V2#5z>DMm@`%I@*mC;k@i zy;U6u;A#Fbcm8M2|L-*h@71gjV|`tu@eLp;ynp?--p+N9$olo%e*<}hKwM^CtYw;e z42Zsa_l|{yrG)QFQ+jmc;L|mCIwYQwtTvS9+a3E|L@UwPUtXLFzPkxb0z|@VJ+7z- z?2xhRazJZ(mew!R$_nkg=l9DpFGI;@8JC<~7LM7|^?=r{dAyABefara@>HUVI*>qJ zuD%KcQgD23P8JS71B?7H5+gAPcF#p+=J_`OJacvZp7$Q;V$VoGuwcqp`@G|WrGR%S zJ#M1h>LF0Wpa=Ut+G2}A$6$Xs)kWrMR1{49)p62XY7&36@|AMWw_AX-15xvKoT^#_ z7j-N*Y67=@6*z?}!3Zv8ft*`$#ZLj)9VsO&YYG3U=9f>SD}a)_xU9uECKuFrjE#A1 zRHGAAA0W`!doE3Gwzl~`#o1tQfpoI-WW`b_d&VoX=)3ZuVPC!J=3B5;fLh(pVL1P) z%>g!|iy!7*l=OiSj_)<{^YI@-#G&J>lub}eVwK(r=!oxyDzt3B=fAqwC3nemO^{#w z2gLR5p#?D8Sr00dUGPDedOi(6 zLY4wYWtS&qNEk#w!(+O}2@pY+>vQd2F_MJ~K1)!``z;Nu%i_;yLrU5#%C^4*4a(<0 z*u9sNU#3K9tCG-3d5TIm=zhw<7EMN^5#zz;tXTThn}8RgC-{> zP1Jk5^svTlg$Un#l&@O4!K6q^1vLPAWQDkfocVnY4PZBj9^ z)nMcRf&9v?|NYmVroH2g$N#4r6xMXi`7%(>5ebuug75xhQ9BEtP-jFA`49jX1SbFK zhb{QV5OYFH^8faY{-=BOznrH3U*1?vV{tjn05TvEvIK_NEA?HBR!TUcDF=gQ;hI%Hzmz0I2aFDhd_%%qSHm=^3bLHh_<<;5_qyYK%1qv5zi^^}>H*i^GPi76@q zBcFEh2MDf=yGr;0O?bH@d!bZfI1P0F)#mh*0SumJC|*vktJ{48c#&tl&}QXE|GMwF z_yNCRWu^#wWnr(F2OvkQO0vE{#Vxwmmm$uvB^;dKOO*dTw*P;R?PhkUmwBQuK^Fj& zBqhA9W}~o>bGim`)WI<8-p30}yPByy5Cq;Tm${ZJ^T}=aO*v2ZQ|2*nJmu1YjcN|M%*_EwK-Qzi;dt8ygFx-+U3-*4C!YQ3c#Muw?;<1n;vpASt{z!TXbr zucOJVpAp}9cXe&HSm5t^(7o*a^#LaTb?Lh}@b_QcRhvou;iC)2kONSdIzWI;AP0)F zP+(_UMM;mZlU^C7C%`@)0q#b%7*<7{gMX7am&*f}5!*C!bc89URnVD88Bju5NPoBltbAc z@WfirmiSG~IKZm*T|Z#ET84$RLpE2`)y0O$KPg_y=IL_6pq`$dRWDe|2v=A(fV}_%PWUt@M$n3kGH7~`K2sydy26QU=dB)uk5vbv#=;^;N;{4 zaC2R-CiZD)YVyfNUkxfgkqS0j)t9_~8o+r63cw{-w~!xk+y@LH-AsvQiDd_W@>rvVOmd%EGiF2Amp=KY*gM z=AR`=Dc67-=l)-}^by?B-;65>`XAcu|I72@{~wRAVJ=>v2Qj#-!E4r(d2xc>)DB*u zKz;=W_9+aXf!DPip1a^@UH?Ca-&GBmy!Erlt{20vMA9{>J}Gtxd{+vB8D~J5;3y^L zXjh4U4bJ68-^T1SR;n9J!S{z0Z-IT2PWXT3FpJ~}14pF+q$nQlHS_mcQ8j&!1 zj(;Z$gGq%Xn79BsRiEgm!A4zKOAz3~*hFY^eI5S!BTp4=kNWM9b6SKct4|odx;)@9GAwq<>g`@TD{jUx@iwqKxY%bXNsh1up{N4pD!-%j zq17Q9_a4=&i@hzzgp`AUec2PVz`$JZ^@b@@^YmNw_zk04P5Z*VBgbOe83}-P>7!f9 z>uhjZ&wF?#yA+RZx4P7qDQ5_IdbQ^sn4#zPe(uU~#OG}E9$wJTwU9!PEq$E|TFc1@ z@xIBcv&vqnRrq90`hcxop+3eEtfDkKOiC^7E9-cx)}JGji_G0$4)f)g&t%*n53`_I zwNA%-Y~ByznqGu7E!aa~khp4bZ<2E}f8V%yFMRvErqiDiLD#a7nL%5r>A)0>WffbTUK7Qn%};MC|-YxJAOR2F4lK7Uz~4F_NLLBc@i>JJ~Lrl$=IHn7-Oo8xM<`G|;<&+GlWUpOu@L-2zTC|mYB*NSJZn^|r|KU({s4TZ?$7C|6IC)F?9Eb?At z&WB~e^}H1I0~SBRE!d?uN;42WkO;k5GbO)iUfnWCH&Lp z=16E>8u?#^_w|uhqwt;^kY%6O&5oH<+~vn)^v4eia8@_wNk>RaAIG|^5p1Z1k?r-jMR>djg$2H*?#C>IolZ{%F&PO{~exs ze_r=p#JiJzj{K6xyhyO7;ZS?lmUZc%Hf|_CEvAf;SjK7W)_eb`F1)iNWX$k@bM8b9BOubPxPIyvQ8nYN>Tj;pc6ujDmqQp3M`Bc{S(1r2fta-gcK5-vIaH&M8i&`xP@E)geEO zBTcA?G&9XswzHXaQ(#@W9JCqYPAQ^2l6|#5T~s9HJ<*~o)wv}Uf9o9D=W{faO7Db3 zjboQaTC?MHBdI#IO`#8Hteyy3jfJgjO9@aDeduTnUFgE>JYuw@rW(ztT{(Tk%A`Qv z1?s6Z?6->X%hZ{@gk1APVg(y}$byVJa4_VP2P z&RVG6c7XO070a%rsjhy6r-tOyjQdRg%vpgAVp+-f?>2$^GR;b>t~{$MMWj`5r@RVO zfv(w}T(~sv8mzim*0)#8r)z9*G3!_K$}g7FGbwAim+KnPxNgt`63X|Z$}Yj_^iPXz zrTzPMHQ5L=U*Wm(8xXF>R*O`L;5Nch`751!ed+zrzxhK6b2lN33ZaJ&6m5JD5n}~f zNsSk^N4qF^Pfc}&!Zd={(^See3F#yWSgJ3=||As(HG=FA8SdhL;uD1As9&Jz5KG#;|8g zs+HzZMKu{^!n;GmtVTC{?dnCJuQ#zq+>LA$(7n);S5TFdcSLzmzh#$J5Bj~IH3V7< zpU2_~~C1WActYP~37cTKbhe>c7gsDdzm#oWKnT9WmpEo=*y~B~mjPgKUVOr%QI<2XkK|OSE2-}`^yZAL2C*eNAUZhdPRu**^JJR zK#z_*Wq6dXyp+vx$}3MJVxyhe4hLr$ijQk)M$?zd2l4EL?5w4A2CL>I5Wkfv?-gTo zU8~qZ3YJg6Dn_@#(uMh_kFZg&R=<&k2>g0SYNM+?wLARkK;fc#Wy5!JxY#9!#aB!P0?oT11kO<1 z{D*rBJ4fJ*boq9rv|?%nu+{{s?e*~aw`SZE=dQ2CO%0hadCb%p{VO9^wC!iKZqEKn zcZgYAGaf1W*nqv5a^rJo_%880WqF#m$jJ4WRq1EG_RlDwNf`6Cq7=ICusEc|eTMXO z5d`7IIZkiGyQv>^S`q2xv3SbZSCOaX5;XAR{d)Y}OzqnZOY^Tvg*NXJ=a%F0nTNmd z^u_5Ss6gW4HR`+UAo+`(p0-FPC)QC zO@A3b?>y*-O`B!hidOP+S@Bq9KgIVib&NAY_khrB#E4Mb+TbFmL_CW8JXUnltK50% zVWbmGcbJo$tg6=Ik-Ap;_P5&?JC-1_$e!vuHHW2`r7vGzJ~osgg)xWL=)TBFFd~Bt zd8K=~d>p^EjFWvGe)5q2niVK}7iB2a=laAGVox9pM_of0-0TruC+McO>c_$5KVl?G zv3x>j=%jUE_3tmpMq(QV-t1{%d}cH6Zt?Ct&X2nl%oqm1Q4w)U15sNHc6|K{wJn^{ zm=E$tG=4#treaD!{QW+f4cse2_d z<(FGo31TrbxTdbT=fr?FPIuxV^~rSiBU zeJ!#@yhRzAX7h=RtZO=^SMB_hPh=yU^0Wd=UpPj2%rkftGlJ`w@eaSf zU{`+lyIUh%u-d`E>r4P=Di2j6EEjG3CRyWu;PP`p(QLbadFn^mWABVZ2T~MnR)tZ{ zF@=5;p&qRaB3hF*8~oKfnRl%yR-JIIr2(R|P40bVT2Q7^?1_at3U|iPe&(BBf3Y*& zSy}k$tgMP7EQYnWf(VjtXP>g%P|B*3rTsByRDh^M^| z#A6iX{t~o#nZ2wL(jlyWK;Nng`$+xw{ZFr(nKL7mZiv&OVO~T#-SkhbkJ9&Mlg59* z2XVd+Lmb|hhZUk}a^Q1GJB%tZtub~1F3emi;)*%Nwgvx8c~#ykEP!(H%8l-ae_MMa zxE36Zx5Z1|1I=G_z0uq_;}3ynIf(ulYXTNO`R@b7hetP=(U`{)o?-@~uN938Lin0=Ice8h!l-EjCACO0s z0^+>`i9uZaud_Sls6Fxv41u@IgD|e1F;j6X>H$uE1=Z7~ks73Nm)r9U{;Aig9J6W4 zM{07JHQy48#_AZ6lFq+HEYMZ!CTnxI;%@ku=Z>aqP*RtEn)YQ`M5E*xi5@vNFQiO0 zdJg}4nUav>lty|3b0GB7~l4kicH znneI?Krjq%|$K$sDKcsYfBhk*n#LKAF43j+{>Ls!~DeWdE$P2#=Ruk%Sm z3zL&~3OQv9^sK(-2@dt*{3PfOlzRJ?Kno*q+6Db~$ZvrSoasXS0V9!bm(aJ=+uQ5g z-17HxkZcmj9me#sT7kA56E*4TY>GOd;vreRyER7^3&Pe)IXXQcGH$zj+~nbVq8f?O zEgT&h(&nM8bb1SNQ2$0b&Cu87l=F2%6@mp525dd*O|53;5P+=rz#G0fmoi|B3ZTG8 zxj9Tv$$%aoN*`s%h3P)|Z!PwwJSXB%ZRNR_@kW0{D1WkPVw6Ol;GLXG%-I`V0|Ue_ z1P>)}u1BguLqnsZqjd{KUP8JUGE**ZfUZtmFUptS*bW+imSfaJuRT4%_c{cGlEYhb z14&~@yHZI*@39g>UOyYpIX(-J2L?Iz*nXr@j>1gS?@jvs`!m z9U1cTBgW5~1s(I>uOij?Mm&Qgj<d4(L_p6FjSlL2_j#>_KG@kudgOoV=uXT% zwqzwOG%OCVyO)^a)iZ2%s2=_F(hVG3K<5fY0jC|8CF3+InqjvNI58O9QoztcO zVLdW30{H6xtuTuq7B1Wqy4g2ZLhf=@OQUw-B#&T75Ybc3gEAfawPEH0H(Hf_W6=@VmR)I`;g3WV3d>wgjdFx0VwXpP- zBk2uo)yG-dAZ^768xnD{w=Xg-A??P`rjF`*QAkcfV1_=Y?XKB)QO=>FD?#U6+K`H6 zK;gg)8KGI)tLk?wuAy+C{IvN$KR}LjjrkHm0&Yw-uj2JUN?T-PAQnWzQu=6+Mm1(! z@%j0H7;z@oMp}N2Aw)g^y0}8mUFYd_nW7fkJNxK|0lrUALcejd`Ix8%2YKn32-?fw z*PWMIen~=B9a|fp&Cw#BE=F$CpxX;#q5b_oD`v)LOK;$(E z=O5kgkJB*^CvproKMCNIgg~kjFS!xhb|%Flnv8K_ZQd_1cY?gcuRUr{o0#c!YZ{oi zXCRDnr3~aN2%OjL%E%8O3hN?%aUTwap%OGbZDkN!Hlwo&D`fAw(ai7 zJr&(IBV&kuH+Q-flK!7`Z&U=1W?d!Z*OD-2*`^ngR{1M7%Qm)q4_VVIzUijaZqW4o zw!LSis;mIxi%@XZ9pi@JXFSc_Yy7ZdBr}(!yDnt-nhu6s7D~-vhgI;>yRa5EJtLn> zRaOr7K?W9GsOtno_Z`c{iT^>V&ey4R%sV{Jx~;2GOpk|!ai{d+sv|2+E&KO^7j4A3v4~Iae}_Mkvb8~FSmSA1B_eF~(UV(7MCcf}LY z0fhK+lve`PuYMU>YAwPnh>#U&;5AEFw#fUAxo)+GAyB4Zj$7&J0NB)pfoLx)M!dd8 z!3e9(Id9U5{OTaJpXRhq$SvHFM{RXMr>@1F-Y0D*&F`4PefzzBHEq?mrsw*EI>BxK z=@urUk(!ZFipD}|IGSS@)VTbSwV%DA7L`Vd|yE)WK6dK!_jAIG|C&&Ok zKz*%wX^=Z&C)?TQmS&eyRMh>V93*8=T@*1YX6OOi$^pz4fFo&vCUIN+SIJynO1H29PQc|@=+EuLq|z5y^GvsO}bq1 z%RDbbpX7iAQDuvbgH5{4J}%_x>r!1>GIr9+bI+%>3t+D3zI&;QOVM5>jXaHal6}UL zF;sQ^cCVZ1%a<>;Q1{Hfd&2`(hq6HG`zVH7Rud@ek;zHICW6BFu2Kh2vqN}U9rj_K z)mwNE>EqDO6YMqY90}xPKK=dE3;|V|R=E|)Qo%VIh<65wFMS^Q;C5~{$HCztd#uVO zN}sFx&DN}aH7#)nfBhoqC9qU?37%V9cb0FwR`I?3=b0^CbB=rA_MsdktX_$z;wfZk zeY40!J2t=mtyz*Emy!=|6Ru!u-OKz9R0i#om~69{bf#&+<5dB^sLYg4FVI=Bo{Myi z64`{6u_#Ov7*H^o4x``>6oi0m1h5t)CSvA;)0!{3sYks0Jv~P+n@{(FvIkLhkOp?I z_id&RRp7`2LDfDV8V+OpxX*PQ&cq>TjbqC1kMCVYuBR^S9WjY4{9siy_Pxh zq~D-fmhb-h=BBf(*qTp9Q4vtfL;JIq-x0nIZ|!eEH1l=A#Yyvoi)cd?i0?}+N<>!L zkBtm}{nx;TN< zwS~j3OMY4hk_c+tK})~`)1eB04y-cujx>|@c{FvXckF*o#39{!Rlda%LQ><8)pJ$h?tPmc=r;xi?xk&mK*c+DHQ+7*Bq0F5hHhw}N z(4|;b(YT2-rqi`8p`K{W{eF*#_R&el{yI8l8agJqjHi-=FTTB)E=kWQbDgO!pI~?| zf00SzFok(9pEL5n)in9H{>X6|e%$>KQXy*SnE`y0fsV3EAa5=+`I*4}YXz9IChIJJ zUz}j*=a4&?HFrrX>Y5crg84TiYqB?tEO>THi$h-+kjpZukYx?s?#iBfSqa}lS5G~t zn0YwecIwugQOgs*@^tVC5A@Mb+z0p;N6+!rGH=*!7*CYFu|BN9IvHZEUTHav&on=Y zWWCrkiv0ZC;QZ68I7laa>sBAv?iojq6ZE~cDuczVnLAmZ2$s55e;po06GA>eb^7%1 zVDFQxG&@;d>fK*TA^cCrXMc_&OY-po1*3!*ZQs8nN?Os0_PqhwVY8@qXCJ*|BARWi zpx-QYJ(0y(fSmNfnmVq2Xi~uRO}hXa(X~O?z@6Q*eT`?F5X*>c_<)-Smx`)#D(iWG zP<;Y$?V;`V&n}*oOW35?Ogr~q;Lx**-m^C9xTbrUorh+%joOUiZl(9ey~Lxv4an#C z`%Z0+x0@7i;OE_y`^-6JTDvZBTa$|w668b0%ba(CR6rOIDE)lP96gtOzjuR#Ktevi zfNw5F*;I78^GqQjlZSjgGPd$t$of8s=m&pk7mJc*5sLn~_}a%Y67oX%$(1|^`OS~d z&mtL#Qu8f}&MVGlwO_?&)0LvNR(<Qb?OVgDM~>Wy6*QDNn=wiGUIA5AZUpmXE)Ua%)S1RK=oV(i^%b_YDYN2( z#Hp#l7-)s#n}Mc&NdS>oc5x}Qc@~xplgE!?rTyTT0)Nzv6Hy!%;Z0VLjEX{KMyV4L zete-MqykR5kU);G0LD%RI`uqVGBUCnr%%}v)QH2YGXl+F+;4#NF=|(ocA@AwXF@&A z83tgQFlSsC`e5-_{^=Hnmb*?hq7r^Bx4Jf@RH_FnM&|@pt=2*PB0!M*vk)F~d@=jwH*z4f9 z0!Mu^J9MiQup=*cQ9O$Q!M;b&nt3w9-hK1t=kqz)0^V!;)_Ai#IX7cP>yN zD>tVeUc?e0TbP*d<|qE}fHDE=@M>1{DwOr&#e&n8$7aLk;-YnlA!wrMF#fF&jm=oO z4pQyg1r5U8pg}?c?uPLzJLNcYhEIQlroT8wK4~4Cm{qme*(Y0Ha}cqbcNL00Vv#48 z`@Fti4M8d9Tvv4C1Z{o;O#ZU(;INdfIu4_<0i&QFEneVr>Weom_46#1``2)ASw&#~ z=3OUTV$PPJ0Nwrrw;_C7Q}|8Jde-X$J6oR79(w*eXWthrw;tz6&4Xv9A78}7RBdR@ z$E-e~>3vGM6lq`!KK{Z5`7fUS4(uRoVC(C-7SzWTAL(o0`Qv)PkFQJb2%}<(l`L9P zYBK_V4QqD%wc_StdG6GYPldn1`NueYI<|;HR8n9v^LI>kZ&K?h=ou*3p5&NjojgYvJX?Pbt%fH{=1V z1jk*Dvr%I9bn`uZ+p+`?xey34FI zeeJPHO4Q^?k3E?ZElGQ*`zuSbJGBFYk?%poabA79-#H)+9T_z_Ec4OxE*ifFe;F@O z)GH~fYWNWyWM(%`%xz-4*fsz9&p7w&b`?C!enIPL?2Q zN3Hp(eVKrfEew4ff8gdJ^^?I0({6a+S4PL%1muB%D=HaJm+A_59A*TdKYl&399t`< z$r!6@vMKk`8h+6C^rz5G*mIuMhP0LYWL^IG$%5fxDh-+mjdvcWY&>2M)+R$z(L5ZA z(?ODw&L4~EkV848GzTkqP_dGmyOsiysp;^}B&arX=X>!MRestJn+?U+f?mr*zWkWr z>As<%AcX-@m_>;mfnUu%Miy?4R1Co9>|nABfkEwO^M!TaYkl2 zwcQrK`A!-~$Okb!(OJLmet+H2a4Y7c+K^rO?+6wu?DHTA%q;cSg(^BSiWhd_c-#2e z#9^4~;pWcD5OHV0U}++wPHwVpeD$)?YJgKu-4AnEYb~6<7i)y-DO3UY1sYt!w{3zi z(YXPjAE4{ZvZcVdh^Pd{=dDAvWGd0!KzhY`$Jak}@S(ou>AwlPpJ)hMr4U;YFfv0s z!hUOTLc$xI`Fl#xA`3pCA00J>I@?<}fj2Ob$f{i+$P{Jrf`8G*k2E ztdCL+T#?@4K9G&05)Rjb7T0j;B$EeIBlqgeQVgqj zATUmi&=+wlyxq1u#lOi#nIO;QjB+^aRPn&7Iy7Wd@<2X*S{Mi;wNyWV$LdbvcHvu> zVdf&?$108q70HZ9&}`8QI}TP={K-AS!tW65Z0Al;+gYzdGe?7ACr?O3OfN2kB~+(q zlt+z!z^IzpoXJ7M&1;n69aNt=_bB%pO3#;i#MMw-6U)e|?H?U5B`uqD6?hCy1=xI*3l=Xzk`w5Y5>fAUC1S z0U+KbhPYO>nSXhVo58qJP{`(w{+Md3KN3bKuJJRsR4db`zWa>8 z5cFXONtWFbQP4Qay>zvZjMFKKJ@SKaXlCwmg3;9`_!zH?Cj)o}?TYUVxGRG2`$b)WUj`Jxh zRNSlRk<*A_qj+y*sE_7GuFikYFQT(@8;KZqoD}=mbIZPcLGczJY9{&BFMVp^FmQfO zT~4vD9uV-pAx3c>eS?uc>jQ^dKOgcj%Wx7WR7FEgU$q9aV=7=f3Sp!Qd)UM%Bs@)D z$*}|1qEtl46Rk9WwmFcWVGFnd%`qNsPL)6N-#Pm7v%M?mD!y&nk7>Q_s&_U;8x3uv?SR<8I?q@m`&nR;CM%zY+?EPbd#oV7Rw zMWb&RVng2(6XCb=0P>~z#5-UPV_4#P&_@i-%NmS#T1!nKF^o#%VtDw|6fI~EQFp?s zc{zqm(7v#@L@z|UMi*^Z)20NI)z~!e?%p0V68v7CC>R<@0Qo_fF|F~8>L|-zCfh(u zvvvC@IQ9s-B>$(F^y$p6>M{Zd?g&@^l-@@?Cbp^YwaSULl(af0L;>#xUP}t96<}{z z%daW@j30jG!7qQqXx@jjTebAmz4|1~ZuwoC77}=ScxOt@7XZEfhA#TIx5;$ENNf|s zuO(vCw3Jq^CmDs52f@?t*t}|-& zbXNT~{jO$-f{1KxNL}S=PFS3A`GnGWp-*@<9ui(g1%Yys>9Sc{$RHFss_b898Hj4pg@SgVgsNP4SXD<&%}CbJEE{~Z6ri^wjQ9d)2462 z)d1SKR#ltD?3YxF@NbC)TP3zk#PGMp!3{FE?BDZV$_`=zHbV;-0%}O?`sw6iu3j>! z)HpuV^3U5{{!wf1LtmkPog`eUE!#j=y)+}Bk9ErQzsR#mJ4S4vwl3}bPY7_Pzi#VF zJYa7~!mb{>6&rgO-(#!3m8GwpleH--FJXt?t=?fV6uoq=HRM8BkP?;Z8Q{Arj}Yq@ zSNq^1Z6a|CJF>6V1ukFKpUD@B6x8x)H}KL&eE8Stt1NfFbtxtV<1dh0;^z8d^kQ@r!9X2KPalI`WVp-F}!x> zFN64IUMpQ@7E`0Z+?;LX`iF`;zB$1lQXzn!njjD@y#)v+hHDV~(MG}#C;g%@f?IF? z8w-Gespe>qA$#DcijCE^oJICeUCm4GEGt=$3VSBfnnlPX8%vt~_y66`f!OpM+py_* zrFmrymF!61St5__4CHb|>aFADnjOB>)AOhSm;>8v^Rh(MJWGMqsCiP=Lk4M@=28{` z&yMPl%*6ZtUj$N$mTemKbHd4x(q8^Avn;1PYGH5L2~_hGn0-%N)o=V*-LTQHN-1kO zu`kpIFjd-|4NhsGv~9@Io}b2k}1(+gt>x1+rlx{UKEm~ABToc%F2`` zEr;ccJ0<3C{8|d1Y;Jk$>nr9mOLyzNBOEc~o7?6(s&NeY^xJMZk~qY*T%C zA?Ne{p(;O_*0-n(dp)rt0Noe0xcrzcAtEw5JFK!OaJw_89DQ*AS7d~@#&a=wWuatH z^rj}1tbf1Y^vJEp&AvK?VJ_vMDOuO9q^MhRGtOp%FR|by=2ILjLpK8h?U^i{o{%=k z6&W9Y9iOcYx$#%%29l18JZh5ft~ILMRL{XNSA2!{dZ2KgS9Tm|D*LQ*y7wd}ELM+3 zn0fTw21L6UeRlnQeRG+8a6#J;V=mIW(86)7Ue`h! z+T27yHdHGnmx9|+gg;|@L<*GoMBEb>BeoSvj*h;YTt4sVn{+u~)Wc!LpP-s}hj=q7 z!V5h2WeKwApPoXTH}L`R{Q~O?F#L|w^q{+A}%C-61AE zncH|`%-%h*y1E){mo6diOK#&Kk+yhD*ymfQTkm*!@Wv>-_U2nMwJ#<*GJd|>TXh(? ztf=T^`?ofiyFhAYBo+*d3w1fyeF6y3vfiN3QQ;%Q^rt5|5mlN3(_h`_&|eV}kq&8? z%Ufq2M~@`x=l$2i<_@-u{7w)CPXf|Een6L)tVn3Gl*F$1q?BT%qKoER{uvo@A8KVn zAX+aT7&KMsCMV=(+dYBv(-F7+p34*&=+o3xrp1`DKjTabJEZ^jY-Ly9dRflv&SxU- zM0R#Ig^pD^hNy>{qgMX;WJ2ogjQ7Icj$%0Osd@GjeG+CW%%EwscF!)I7A$Pei5UpN z@bo*%LCcMw&0}L=rRcZVeT8~DUUIgEx4v3wqZALEl6!>pTIucy(>SQHp}#dNsN}K~ zDs!3G-(&F77^vx&U^-vgRc6h;9n7#OLjwh5svf?lv+CqsASk@7N;D#s^|Lz z;kVfvkVle+8KfPBgQ*w6KK*I%T$?AD#B)j&;%8a(&>(G@Wd1=Y%fsg!^4^GOX^@>> zE69}bJ<|T(am#UHc-2u7b9%ga=kLWbzK;5yuAHfW1QS7f`5p0-tN7f9(y+Lf-@xa{0l+hwhuLuy3y3~no_{o7pcYUVFilm{Jb!O9it(m6KBI{O4(22^jWc6dMgs9g3J~@a0 zx1>@TK1?QVPs!vg`I#53$VY+`A_(*k*2;E(!+%b6U;8ix5F@yS%7Fec#MW;v75LRj zf8oKFB_p1Hu~CL9fG6vn^M?RRhX}AeM5N;ahwM>c`?EbZ}^)nwoJ}avacv&z!ZR*=n#E{j>$9dPn+)YQ?;Ru5f))yh= zTudn(AI>ZVm>}BGtn`+(HidLlcah!1j|jfhMpNHs>^2(3$=r>S<$?BiohNwveY*S! zZxu>DtNnj?I?J#qyEa@uAn2e7LyvUB&?O-tIMOBE-Q6J|J#@FUv^0o-G?D@W(kX*< zBQ3q3ckkod{N~57n6>V@?(@<=)Y>>PQH%z)Me6!qvE|i&1ktWZ>hmgr`0PeSN&<1-RfaT9U3!mWW`3` z>omddoc%s*2`(SPZ3!C9|B&(W@+wvx_Ymb3E!1gjy%~7(hVoh2UMZtmD*4fil?Bob zhgpi%o%(8r?8(54;W>Cu;A98^Q^oYfq?I07*moEGI&Bc9Usd(|zgLPEEbVNnifroS zBrlmrd@0Qo>JIE1z=l^h)wVqp-cCz+V$>lv_0Mo%e&BS#wONSF^v27b+zJ$0xnx`O z?H;u%m#G``w`(J}6vtSnZEN-y1;7A89P3(QGi{q@!%rzT?1H(NJ7k$f;OU#2K4=az zivUF+@^RhAp#jN#hdZbNwB$VAt&jt0Tq2^;cuOb(c3C ztuqT6?VrfD`#bQcfx}i%64elE;cYt4d+~msTzGJu{&>**Dw#@lH1gf5`RMyi`sBe# z(X~jC%yI2#3)_5&$Sg<_AiFRBDE3h5$l!N_*6+Jzr{VZ$7R?&#z)v!|=eN7QH`N|T zcWIa2s4edX_Y3K%_Eg7iAtPN~d_-^9+=l9)v%&UJJUrt)8AD>AE;}3Xjhm2E1e7+4 zcJ#{7fU2SLS={M)?)RHZu_r)%tL z?F7bcaOKOVJy)qzLnB8=8%9Ot#m^-c{{{|{T#@^6>p}0v&*H#8^b6{F=N@rsG1Os1 zpmn~@`A;|4lD)2<_j13JsUIw0_9sb)-wj-~p?{JcRCLpx?9gG+=uxIIXU=Hm%o(Nr zc)7&A_+=57^b=I_QCK2g@S`a%e|Z^UUP0$=o3*Y<_j^^heRf|*zTDK_Rk7^TMw$yL z3j!c;afn5=--(e1wm9r#)>7>dtygZnS!tAM5oCrE$y#)&Y_IV;#XfaF$W%Ty6N&@3 zLkZM9Tzz~9(w_kl1=g09jMzPmG>vP52*~gkDQRip=XLO6{CqEmn?EzcSU@Rx=`Lt; z3bU-|4%zUgq>;eqnYLG@;p)%bV&~)>ILA0WJx!Ttr188x?`seyGcegAsA1#S#4-U8 z5IMNner<_?N4B;OB{a8Rg~fjQvQ|b?1^9zh1V9pdj$i zIf#dvy1Mf4_iiFmSYHa@+kRmJ-2$(=v=&N7{jPBf`dufhmp*2n+)_h=!Lx4IGh-87 zrS$RFvYClMXJe32(MYB}nXGQ5$5_)x2USt}`XcK$SC({$SA9}+83%4GFUG#8MOO4Y z+4~h!QjK|T+OEk;68)+_B&<%t+1U0bQ9)G>IZ&sH0*v;IFn(2p?`mzA(u_y(@WI?#ku@U5lPIa{%Z3`HP($oGCLvu} zT=urUnf+ok(E*8ql6W?I1HO7he7POI>gd&dg$Ya#k5ttZ?iUk|ghkN;|NIp9jt>0l z48@Yb zQ%^q-9!#8L%8_8rW35z_qjf>bvP$}|9@rQn3!rOogMgN%%YanZ4~mM90b?XKVgg16 zIj8-Kq1>m92?16U-p0CFD=s2a>RUKob(5>hVNn-lpR@(2RDce4*!Zr$xx$KKiaz8_ z%-S|IT$CEP9}hqJUeLd;1J`!l0tt`80S!VPe+;itjntT>xtN9qXH+v~vGl2*Bm@kr z;&TdeiRLwcsa;Ka52whlasZm3gw#{!;wI7nKUDHi29kNyAi{*MLxsH6JI>bP)g+pC*QjiOMaSx0LAtSVRW7JgnAef8? z5sLaEA(NF8XMwGyLW*vzAeTAfuQOy$s1mamDWNe*i1g1&Kn+uAfeTJnk=bF)p^@{i>RkMa&V^5kGh7Q zdS8gRp@__av(L8VOEG2}Dug2%6~oo6MWDVLW;QCc)#mq^8nU^y1U{D+zBjyXp$ESfrg_4@hB*}XIi8vqqw zfU-->c^0NJ^VOVjt;O+I;#2`Z&rSL3oMp|-r%}WibY4J^n*dxsUfOP2iyMw96IWN> z@C^{d0qHu~XA_KLv1nG0a?k}2vfYp~efR(y6-!+lgK^@E%bWCQ>=Dp*pnSMpuTqZ@ z)XJJD2sSSv%{w;&<InbkJDnI-heV=_X~$AiqKzzcY|;276qz*|E!Sw>rbpK{@@ zA@S|a3u%#F#|`PQW7RU)*0*ig(Zo4a937@=S(FVZ25f6>T+jiZz?X+ih{pflyZvs^ z>FDkYJ3G59d~t(hZ&{wa#HkY(G#ah1uMe!{@lhmurNDEiQe~`Y6ytD}sYW6`v|hai zA#gJJ%I&RG3o#*outtDMtHXc;-|lc_?5fQIlbuv>R7O~j#h{LjQR0>o z^c5aEwY0J_BYi7ZW|LWB0}|~a3sgH&;()l#b_-!(1EXnTN+0vJVf%fv{e?f$ipbS- zHbj!0hF)0?Uc6DKQmVcZbJbx~GrMNr{BOU>9|O5g`WVsozSU%3K=JvS4Jz;a&Livc zUk@kY(>_x?8bY$-UY9=?aLwP{K@zLV(px8=%SX|Tk*|}6Za7}s3&z}i)l9znAcEul z{dBY@{n?kN+``-5%b;Quig3P zBS2aMn38bG@oXrraW-Ce_b29$GAfGaoW;Ix#iNth{&d)imk;-Ozok++cZkb6*H7i8 zz52kvxHUr&$cT6Z;5#GvLb++*cRw$m55g$3d|5>p76{o{jF&O2VPkh|{_0Ra*L(}TzL(HyTEx047AKJ{jGN(XTk0nJiYs`h#9U2y;j`K{S2MrB{{ztrzVS9*;GOa z1NVJWwVf(X1G*|~MMZM(^1@#w!X2uvG2QjviocaG416LT3%Pd%N&7j>UW1;+<7r~V zs+tAcS<|~R0S~2IN?d6%v}_F2XYn5GNisz*>eXLjDl5>d)2POXS})4Tl{0(v2=3pk zg&j*U^6q(8^j|)vG1@=4bJFlAU1LVb#0(@4zKAjF8OQ+=p`~nlgUieBedB(O!GxEO zhx6Qi|NDrxmG0o%eY$$4L6rY5{aEk_=eqSD!;{mT>sYTWH4-%OUw_}S2zEs!Eqn7V zoPWhY>Hv@glRMY9kOef)u($ojiG;^@&8s9{+&Uz6pF5Y0gSMm^OeB z8(~@AbF>vM2l%ZA_119)n*+w=@1^7eI^FNBE{BFMbJ6j5+f84XbEJyqjvc5?i$}0l z3;$`+t5fEO%;(6E^C`ys`nE;X?c7?8N|#}V#NOP0+iQGohK1N1x;=Y~Oh~m`_=Nas z^@F89T&--Ye*Ov329KH3+y&8a6!Nc-m`06}SGGaPRiC}57~&YmO;zbVW%`6E8_vwY zfC`X__=x<;l&qszVXLd75ni|*sas{6NuH0wg!uSApo$s7xv{u5yaiOt2w=FpX|c3% z$JA!(DwI>=C}yPK*2xK}qOS3DW}82Fbx zAhd~MO&`m$)Kp39aefWa^blw1ADGyAC`g6eO7{GFh8X3`DrMixz{yEYjx!qwrOWQr ztr!Xa6H(2?_4<Ti+(rV2ER`@1J*12|7zE-a-2? zA!e8%TpvnGtz;(URNTM25I1tg%n!XE+`4rybQy6`jaqd!j4zOh_%!ZJZsqE#DhC=V zgOC|=C-NOrkYeI|5lPzUN@95e38~3iaxE_ys0BUk<#Q+ytqlrkX zVTw@P{Za#~rG7@8oE2k|D>vln8>p4BF>+NUBY}sJ5@zOtE(n@e`;DEh(qY)Svw@^a z+IrjKq#wOBs5!xFkf;(p8y^#+-}ZjI?!e2hlPP&;O+@^&xC}+$=Ur838;N9mIScSn z6-VyMuI2uAWyMSM$aFpQeW;h8Rj%5HthlwMHt%{}<|U_0qnUGwfCmY}c9j}VPIjVb zNnnmXqVuUXZ%PjC?IpstCOrNn zFGIiKIXYQ&;r4N&r$i{9o>K67iE?)H*pL3PzlLG6wVqlWUC~dLArkCDG-HC`q7>MX z%()UaRwMiRD- zaB!i@;yV|!4af7{;NU{R-yadwugo7eo6hXc#vFwEO2;Khyi?DqXB@+fEm%>Ii^SXI zjTyMUxwNe3?`qa{Xwx^8EXSe|m&-{w2uq|dlCt5(_8aBYoB6l~h)6JB__H2r z&%gVlJZfH&-uo2Dy8KPyCKet$T4-QR9t666{#4KdYz?4DPX_$Xq+wAu392m%ge}A+ z(5>T0Mu-yQ)Z`;I2I5z^UBY4f*hcmZS!qizb0~4*FK>n9g!ahZAPL%Py1e7IZ?n{p z19`>=|JR+uqtSB3_Zs!yCF9zAIUN^xPKF6Vcsw(#wXMEA6CAIXp{g8@zc)qovUlrq+*$MA89Q=HBfE(`cgbL-h-Fy(lz@0mG1mCkc zoP8sQ@ned&rUZw$1V+~B~hUQ060&5Y>6jym!9g1bmr%7ae7_B&V10+%InUKskG#z z;QE!jJsX8=GsnrLMlIJ}BF3eOeW?$RJhCnt1irj`aP*CRSx1vxM`SEHJ>g9!K#z%Q zEAJvTq3KyEJ&sam0iW8^l4&6^2c7!dOS}sK#E>pwyIKta@|w@#a%H85f@F<0CFSH< zcB#;lKtnkq$qdyLik8=F-s%z8KBs8O2{b)F%F0KyX&@q_rJ_ehQ+uB8#z^2VVP+5) zWSGGvb@7Hou&Mq_Y{>|HSY`@KHo<5lR20C^f2-=xlIkUQQLk|=v_+eQ|DjD$e3hZ`J^HE@E$Z;|yODiPHdJlrsv40GnVT&!>1<^_n zDKUFIdSv8s69J%{t;i9yBN~-KlbJa0!FIVs)t_bYv~Xh*MdWCaKn!J7wDZ-FeZDg* z&46AoZ+aI zfslSJ)v`Iti_@^bf28cG^b6gIjDEa0l@ZcA~!d}YBtDLF78>=l)7ZjVe z=Xm@ko5ZK*@*RArwqUBLlKVnP@fn&vLV<=0NczGF`9$~ctS zpz~pec>>v$eN@6{micm0KgAWG!AMB_l0KoMC=A7TW%f#(v;RfR0CpkzFC~qSzs~WH z;Mgc%BMq;RQc_V)MgLR%W+^|GH&1);TOXFxmR&)D>YD)sxdJ^Q(((HK>sFs=bixzd;~1NvK+^n6kYpik1nAf66+~g@ztS^b-cYiZhv<(Xub%5MCaL3#^sw+pDTSv zw_kjsqf8+y?`d6F2M`*#FZu=KiW_p5kEqBA*i(5=-a?W;H4+LnC@v%io*Ea+nd{Gh z71i3*&~+}zxy-Z#KMn}DTVx%mF}y3C-lgm@R*myrz9n77Fk70PZMy6VVt`A(05cIt zessr!YP+KY3qw4V2fJ`Y!5A6#WxnUlFB=ON`o#ANDy!d-EF1iCd*!brWjMR2%0HhbRQupQ83^nqVw1Wi<*sgY401~T?5U%jS~a*~jx#w^8v98I?rce^V?Lxsym ze0h0Ab`9ij zH5nC>-Oz<(K(9}-iZwAwt%W!7U%RG!gY>LgdpnASIE!qcWcIM(V8_)O)5ks^KOFMh&3yfL+hu{Wv zxn>4K61R4IYE60!Ktm4Waz!!XTzmKY6%CSGO0TRn$t}=>a(e+s)KZW`zn%NvoYvpJ zy!y@_+mr3VkE~=|{Vsc&6GQCxHA-9bE2b6To%|xVS2OAFO=qiXSckS(X$@Yu443b2 zonCP^RL3sA)T5{Pt(hZe#*Niilf8;@4ra7YxZ>Qqn9O~iPgWR)fM^vXO*^|m_h zmuh~-(vNFV|6o(W1xXqV0EMrjU&4;pcFqoQi2v~JoIRhdLjGw9UwAd6(f;Tg38yj% zl@964icH@JgYCev2lICxp2BIv%zq=4gD_;gd80^U4#qvGR)Uqw2RgSMJ0Hea z1;hlrHpFdsl9Xi~h4EFq{sM{{@d};w6&-A7Gzq>Tfpi!x)z4_4yZK)W_9n|`p75x; z)2_UC*paaKGj^w|67{vf7|sBsC7EFWGIHY9;ZU6ZARETtT&jGm86L4n+J7G$e>`Q8 z{v7MpTp(e@rg+#yfx+{_2R+}kr8IEd4`w7VqGi`mkEmqNYYA889<^IYs2Ew$RnNO-J}lDUvf#0LPyt!``0kI@ot-V0ySlO3CkF z-g{lot?;7zIRM8*t-tanoMKuwGn^z}VzS<5Uv^F_J#2ABH%TI0n!TB;8DJy^+x{Cr zFWXO+H07ATr9{8^d&fM%ZOPuW)!G{48!>0mLN3WUwdcb@qUWYyml^VlpXNghZ`C{^ zjXNj7dCd-ds~FR7o>YAv!4*B)&>bl_ldHda;7U6@3W(#5gCsi>7CBd|ky>X;d^U;z%MSz;>A+3`PezjO5~2-guZcW2M$0ZaOVwqs_WgL#CWH!~ z`IS!^c7#t`gxzW{L1OU1o;q|ru>#Y>v8_gyLX#v#g2nCOv?&dbdGY8-=&N;n$3n7f zYHjXn8jB6$TX|8rvn@C%6Brc?#rn>C&bGHe*8C1d%S1n(ko)C^YF!&M5Gh=v$rM>a z7bE64q@)Vz9b22=JaQ|WpJ`0S6xj=8 zjuokDQ83|TA`#j4d`U==3LC&VY6A2*S}ZxG3(TSTAQkhwL}<EiEYb z{E*hL*--829d}0puLc0>Y>3k{^6oeq1Hqg%f)4Z}Ss(Wcg3Cyifhnp$wbZ!X^sXL^ z4v9mboHLzwiRa3d!R83{dkf3DI=GAX)A)T31^%9l?D}%fQ3$2(nHJ_*R2iewm}@wT zOwI~$zx3#FF%C&UqoL0mdj@wvE^AENWnd4QD;a*PU2kckh{yXv+nVRWd_VA4@QEZ^ z;G8q2ZvGWa*xhgFH{04)ZV&ysTJzG;*UVrN{mTZQcFhWd4%cF*Srfk-tOZ|jGV@2R z)#_vSUF@TkejKXKUN$@~R|Ao2Msc%qNB+aCV*~6={ohJ8Y@u&wJwOQH%EFv>Yk{f1 zf5*H%56#mze|wlo73uH8J31@}48tQtyzU2z_^P%Vc}p!v^s%aj7W#F1{#jQnvGl8z zUq_Y9$NU~I?L{y3J}^JJC`3XvG|C zd}ethA)TC}zDhEyQiyXqk@i=ZZ}9_XMgsJB!7mq$r*gGv6+wkBQL#vwdbzGa zj_&Mo-Mh)vizqa8uIfh$T>Mowi3#PxcAB(I0Riu>ARmnBzQ?TMu z%iZECF%H7JvIg8PHY{WY**t~ylR>nwwr#5ZVIw}>U$g&`|yP?mIZOMhEMV4Uj~>E zx;8`2i2yEQRbsebp`kP&o-#FVMbJuF2N)iSZ9~`Gbfaj<@qTi7fBM4Lao{{vFXl`a z%g>Fw<|83Fy4A?2?s4P{pqC2wE2wf+g^aA(1?G;A9ZlXWdS<>d%7W+n-I^BI|~=mtNr^ zXB5q^sKN3}mfpXx=@QxxIA@$5X|TBMH57nj7L!l%O76#aZ=e2|O^b5!=WSm5WLgxm zTTstOGiSMGKzU{Ir)7dC^D%I=`!3^1JR2)(NB-!QDGp^ygbXr~@MAbBHG^%zLJF_v z7w&r;nRznp%^nPE2pa$wSA^j{JQghe7dS{@gku+detgL__#{0;f;PqM|e?XnqzNPj}9Qn$r8miJ}^3HKmo#1gAgU&+4f|@KpPo zgY@SAkzld(Y7Cc4jHlXPRFu4UsI(N1v51q|qcpnxjsh%b^_khfTJ>T9%ty*wf;h{yy2|XxUyR!L78mr6piJ_jW7X ztdpewtezYpZGHT~;ewWtbZ7AqxB*CLU<*I}RWJB8A=lHH^bs|Ht(t5S^^#P}upw=0 zEf-PyncF+=)yw(-5`@goe4N-RimS43l8I9&iPeaN?fM%x0r&fLt(uNMM2sos@qeq@ zv_f-<>ORuP5JPw%6%@%L3IO9lzIygmG{DekM~=P7 z93lzv&Ppt&3dj{116VWm6O-uHE6Qcz(hz_cdfmK+T{?O2tiAtg zqCfIsuY2p(lJLOp%JorKmI~ppd1TebFTbUdbe9O?5ShA`DI7F$o{V1DqM6f|E<9B! zRVgrtetmglh;A11>$(sf?Cai|gY!CI2bC^-uhZG`t5IzkoQscaMzw=EHKAmC)j|#| z%;d+*62?97(9keokHjsWVMW&Ihgs;j*sIIfnBBUKQXS20R_;jwd6OR2p$JkCCFfhg z*2~?GOwe}mH^{%jg~a?Cm00!S(TRjWgXwR5q;kw|Rog9nO?bS-%`X8n;1dqj-f`BO zLKyCfR?wB_&aHgpd_}KXFJlA-jt=y_wmM!Yb-)L|y65r4f z7kK)(xDMUQmy-pQCO@Uq7N#v12E`OSnj<#IE#&+1&mi$>YssX-GyF~JyU0HBLEQkqTU#D=9akg~hy_qRY%uOZ@3vwT`A?il%h(vl^}yftzzXY&|nG~S&ZDPSKyLbesl)`-mNEL58=)!1<3 zb-=<#GsoyRl?7T}HlH{>h63xadN2PkYfHCERj%perUF8t>)k07qY*=6IRbC*4C!tg zYHnS2=e+RR+1uOO*@^V4C5!Ff^x@<%bDG_oC1-jgQ|WVgwPOGu#h6+45e~;V zJrJgtq>Y)D;BUSQ%q255?9qWe%Sw&479#h4@-$t?_3umvAUbX1yH8GHZ+#Pyxj1;H zS0;HmO>E>@QL(gxOnH{;OPBl_d0ZtgVZC&!-;YeeNL0AcWWqOHW!3GGF-hnu>mpUd zueRk;C?B-1c@|bV58KPugJ44XmcGS9lfD#yJ6wDVF=o%^gW8AA&N0WXwW@EVBYPcV zp1fdXz@N+{2HG4K*AUpE|BN*SL{h#I?C`n7{WRJu>|=T6xYH{ar1MDy6lW2WUcN0r z=K-K^5i(__BA@qq!f4Pe{W|d_FS(An%b4>Hc5IsX2e8UET~Q9tU$${$s!1f9$C@O!oFS9sh&xp1s%f-exzm6i@x0w(Zed?diL|y8hmbA7u{9tpp=eo?;WtQhUE;`PR(fM*dbS zsvOt%xXhweHtm_4&bht+I!Cv*Aa!^=MQsW{j5I39G??iEJ3I}wpM{i@hO?uO8rksW z?jMM*-jL^uYhWS>&9ICKT$MD$2AYFhK+TclAJ`ZJzFYY&H7F=T`ZqOs!DxVwKg~Pz zDn@SZFPTNFnSCm^t87YD%bJEZc8pRi5hP&jdh-c3nENQc2v_v&^<}8qk@hUg@&0yf z;?ghk?8xerWRJw?ge6+{)mQ~@kyBG|`A=-#dMyp?(_<6|z8#q!2TKS(J$M~{8x-YE z&v&2xXd>yq9YS~>)t%*|zJ8@-%jkNVloX*X_4-+RY|UXIk}w#vy8Z*NVQ-Y{Ya7qa z@^_EFJIKx`N9f31HquIe(@|%0e$oRbE&n)V0tP&ng6gufZ}&=mFetA z+ugtvp1lz*#&^eYoRa8lHCI)e0-AdL<<;kh`}&1(BA>QV?ZU3z9>3+&Ii6!Q}c1nVk9FQi00s^y|iJAJ^-@dhdnB?-@ zYw5d^9LP9sGle2WMWq$p(2U2qRIC1OTa1VKn2!{7xeLtvxz!O^v0ryyH zQ&^&_5r-0UbizDC=T15a7#~8ItmdQL9}k+ z!e~txX$v7f{_#+|K_C!BNc)w=#S{-6EB}cNKwMUi4p^$Il|2H=+*=B4Kt7w#bcc2To_k*ijD*C<*;XHk_H2 zG2iU#)#ld@8m{b-`3WM1RAIR#XM=IiIySvCa9l}2u{*R{aFqVP*@iLE*%h)Ue`{d*dD(+TBdv>GFM7r3 zJCT86<>w4hriu86_V?q0|Li$c(oxsM=asQeK}BAaBVrGEebGA<1GTwqc@MIs^?kY! z;<^oPi@(mk&)w{T1I&}7eB@Q zl?-IcuFg&u zY5~j>Z_z986S^OT-pDxX=Hj1?nhzcQeZ1BZH!`#?Anhw1J(0fa!H^ffMj`erxIV4V zarW0$b|*-T-#i^4!UU>iuhJ}XWEj_suQmP)RWl_@R9A1S zEbE~dIZwVr4!C0eYekOP>1xc54=MS*iURL_ojH&64||wl?SU&HTG!__?A=#VpP?A% zsm%xaL#%P9HHxQHWwy9xl8UUfXJ0HDu2LTt2dJ?a$T42-UK{ps73&kPx)*XEw$N;m zydd*3cy5;G_Aq)*6q*uB{m-)Q-+A!lGNyjxv9;0fYYKH*=1W2@8--aE5Wu8ZW>A(Gv9@r_(&Ta%wpDL zr~o#0_MH~WCj+dhLnkLEoBZ8~2-^l9P}FpP?~hcj(zF|xbb3Z3QKbnQQe0y9tYrJ< zG6{0FR)=w?^Wf8Z>RqW6pR^QE2gVd+%M>@3?Wz*y)F1Fa34_X&PJ)D_XcD*P?CL#m zc{c0c^)hB{Zs1+KH2D*s`x$Sv?Vzm~-M*%ZZo8zoOae{V@7w0e#gx9+(;&ACht7QFSN$4tb}AB~pMX-bSgf&O=BN>Ep{P}vvmL3mc1tyx z!BtZ@4QajB?~|p<+!a3KjuBl0g(V6|0&y|x2Ss|Tj(QH7vwUgX)DvktMg-26M4WA`OI&n2A^(+)jQ_D5;`ydOJ{FK$2BkVA2#OB)EJ z%BjfhonLQO=8nwavZhMC8}m143VlD&==9zYwZDHz+>Qn`=sN7hopG4e@MmS{A3|vW z=b*Z#tdZIc_OB~9C}v`>OhzI)7_g2#CfTQRv-1H~>KzdNvWSn<*4YE};^< zr|h7tH3`>W<5%s6odzY*NX0-d{*%SUpBTXBR!X@MBdn}ck0!5z?Tw94cO&;-9Oysf z`CjS3F=J=~y)s8i2}5fW5+oB&wnlt@mscNfeufGdG(j-}-pbG;2ZRn}C>ty}$U>e> z8Q@|epZZ*zE8n;2ZIz)Z#pIFul*F_N_(=ET&$FH9)T44a$I^qldIcpThP{)y^W6Fr zLUmWMUN$eXJnAA_#2slN8lnaM3gtOxV-3(i;1D!%dI@`cwVK)R@NhgC;6=%KG*jGZ z-CliYANOL%x*$IF5A)aQat9bG$}tsm@y(gz>LY_cyWCBtDm7jwD>g+R;NYE<**8Kl zF3Z2r;G3qL7E+{YzZ`8n!8N$;{srz%{_6!yDnIT>JSdqK6<7||5F;uO?gXrvgos)w zP*$dQ?gtSM#399yTBl}y0qT)F48Df|P=_m+av ze|4Dg)i~vilxp0ATe zhDOijDP)9=9$p7#9(5+>M8)5|lk46nF51D=hfE3Yw3_v|=*Ve%sf+N#P};iJi6t*! z0?Zz;y#*Qf@jfPWZI$FjT+eD1PjWQ^vASn#IU^0mDrP5aZnjt9odt)f%&rX2pokdN zm>s28(c(CNdH#IYFYcQC`J}dh!D~4l=yGCg56+q!t*hpG=k~OLwZ{Fa^b#D(D8XA> zfJJ=FyuF_f?U#5*?-QP?9{0)vEb`%8?@3lvm)(EYNUJDmG^eC8pXkOMF+x>GeU=4a zWK$j($}t5#gt4ziD_Y{vhE&|&#hkCsZ<<1_VQMrpQdfB5{)$35amP&tmjZe*eJRi* zoterbl)FJNlqk3%C6UEMJDPTmn%qp~`nRh$UxtWzrV1?1XSryv(Kl!=0;&<3&Zo zm#|sPcyzm4gS9T+gO@Ys$yr4)OT?-}8mmk$&LaG07k*;cJ&Q9`%5tD`vr;XfG)WEt zL0$Tx!ZrWq)Tk%ot6sCOp==39ZaSh|w)CC@kbDiz=U|o}wcR{CjVN(Kxt7mStgX@hPo6kk#W7KVV>DP|Ek8$yB+d#h`y+)m?I z@b~LeS{dsmlGD6*px}#8U7*TAICUbom9aF9A@Ju(gxpndQuvydzML$cbT$N@r zyS-~Cciwe~Yx99`Z;|=%FaSLz03*$Yt9SGn{a2s$00PNHcLQ{`P?PpT&v1DioE}?3 z8bF*mXVBd>A+tpB-8*TOuZ_xdn(r4^U%HQnnik=+ThfLJeGq#g-0pE`#64Lt^La2g zHihL|iU7qHXMuHANtMrmli=tBWA7gc1fBWB<$#0m(u&y@nf3>HnqVoLs{udPutR{165DY+DtwBS90#Y&S%N#9V)*D!*99=e&9jZOvpC9Dq}!qLhub zjOir)wtVgq1AriD6?*?{@va?-6jgqkJct7A*M=U4*9kb>SPv-wNpV2UJg<)CI3#LW zmmtZ5S(kl4^%(Kviji=>I`Rv@9$Bw`B2&P`@@}@K{RN+#iJuUThzx)v0w8je{#Dd7 zd&!@zURrT9?XxflU#hlz)qqKb_>K@)=m`reJC+(WU;7XIoipBjeHgVOCWc z9h_jhMs_sSC|8ag|Jt|HMYIy+&#?rJ7Q}lSqd8js^#LZ}^GlE_9c27RGi$G5w8Axq z!kcg|6wAIXmr4YqN-5Z_S~-0MN{96R0XuC!@3EB`2gIeSRhtuK1)9^kX9HA)Z-QU? zo>!AORDLe|?w8T?u1xgp*E;*y_5(JQJ*z8JbUa|Se(*^rDW^|*fPTl{dR+WiOn}3p zQVqik|A~{d?1HZ(6@p9jkeWX;W-wI>k2@;Gu;Bm!JLJZG7qM5Z2SI1-ZTbCkGu>9r zr*Xc`S_kNw;q{H6pnff~eC>qBjz@>{SA!)L)PITknii6L^FA$E6SOl6NQCxru{pg_ zl74zf$hdy_KwozU(3TrzyFN|!G7zfcIHVP%Jo1>ecD{*L$2fX{7-Ls3-bZi@vRGag}g@igE#kI{=9UHowMxtI5D$d9ML;iX^3 zIqQies8;5y5I;StCUSKzt2$aaDNK?U{A({GQPl0NXo2hoHElPdO@e;2?hU3TJ{Mxy zOLtJ!DdS@wzx^|ZVrwm`H!2`0&};vj1!$qV*a$WTUXnhCORP`rOi2RP?{a7>Zauvn zot>3u&n@e9*oZ@@6I4gJ`HxzFE&;)p>8?W9!zxJNTS^x6PxfOKi_sskUuTg5@0u)J z>1c)!`-dOXbK;5Wik5t;-ZB}z-y<~nR$E)!)`ktFObB~?$gg?~<@eM3K}sdI!tp;X zKEEnT*1iGIXG$no8q;0mhA}H_A9~ zwXYVW5limBUyQXL40K=>t(er4&o{i6eQH97krq0PStSS>sHJ?&sBPJ1TUP#Q{}A$S z=g#-rY%SAr!=_Z-ii^{ner}}ybwF_#4$!Y;;>wznd32NQ7MTjoA~_2OJJ%s}vRVx& z?>7q?a0z+~2JAh2w@Om>2|g)^vt)!BMU`4vA^Cbp$Wxc`FZWnxH;QWLOMlzIkE4~T zV&Lwg=RO$8@%n}M$08}5rVK3cgxe`9+V6orfHBTK)8Nuc*28xl7_YPu|Iq_F4-f5l z_>fuIqj(k6@z5!mj$YG4T(*zH{#V}5>702>|1liUy$+*XR_=C<9~LSS7w61L-n{MP znz5nATNY_gWyX*H;QOaV?IVyt)#!p^diMXdT=W2{i`2c)W|@VQ?l6R14pm$EG5#`&3{P1jRdqcIK@`2%-NmKOux77?GAw_~JF9oN z@!u3iboNG;qs?PL_WSFi;|Wo(H87`$YAI@=fLoA||^+ zr?8pb{!`6L@B4z*ODv|W^!8SIz((nGx6&y4ae~NGP+nfjg#}P8yIo1F^!R!c@}>%3 zeE4rGiO1dO;_u`eKkw7){n$XFm#vpUjpU}bf4Nl8Cgw?+4&R4ECp_B0%>BoPYnnx$ z(RF!8mdb)PpXrDIymaH#DQ2JJhAN>dC+Dw-ek7MW6wu{-z*nTD9!M7t%V8*SgBHuA>2B=f7?W z6|JssXR^@YNF%*3N&&p5>qotIZ53kR|8B|utmAvpeQpf9mW>R0;3vEq_Q$an06nHw z@_dJMN5P>F1b~Pi9ZIikJdnY4eNcsSGU0uL{c~ljeR;ApO%r9Za6eRO40nokxu44m z;w}B(H|8x|Dy{dP;dVP!^Af&BuY5afW&`4`>h!DIPpW(=av*|KZrQT4cPnodym7IQPdFkerX%0N`***Pl9@y)k%lm3Jn1{?qE-&7M=X;Kfbe4(}H*z8cK2 zp)T0!yw53$U1Yx>G^^a6cFG+1!pfwSzm3BJtWH@xzFVJeViqu|;XW7u5XR+lBmY!P zy`+FtguTk#aXQp1=T+VKc=i0nL-!ozBt~FXt`;QNH%nL?3TFOsF3iYbZ2|85XpTm7 zq>HPu7mDPb*^uw%5?;2vk^J!b>x@>F1Knt;6z9Y6&!BI?n~NLI zIGf$HA~QA(-_l1+KEVGQfyb-~st~>;jcp+C{r>r-n+|tpj{klWK;7ou;=i-;N#)kq zM9}==C@LcoR^-*x?2v90{ZcF;^U$CnByH#I$J?s-I};>dj9L^rfMe$HTs;0XPqQL9 zvX@`6Lgm%QjmyST`vGIiH>L&dwmdn3IEp zgPq-BJcZ08iBc%Z_YikY(qi$AeNj|tXA^&2n2+Yhe*8(c?GvJmeTIe|>qFDK6ITDK zUtiMq;>^VKq0DZK^Ql83Y5ClLUwjTms-)>n)|{`Tz7>*&wgwU| z>EsrOJ;>8FQ2@cZG@2dVkR2EkQ8Bq>fNELHb_>SGi@VTRzoXZVbJ-zhegPm>AMEzZ zd6P_&8Qdnlt*!MuP#mOnTlXK#5O&M=KJBImRs3&&+J37#?3FOL&5*otjtAd~Xz;{Jb?^ z<_P0Erec~GW)8n)*aeVWXy49#t8*0<+VwimzHIST2i}^=d69(yA5ZRlDRTlH?-fa? zDE@EeMJUtq>Mzo`nBpr&0;0C7FAClNIgo$>D2K$+A*eQK&i|8J>?>Eqk+%gafN2WI(l7!$wfh8R%iAZ`7^Sz|l znDL;Dx?l9oi^Ea)u0D!wH5bjS8j8;l%dC>*pmR7Il}Eu;cbZFZ!{IH&q3>xbRJU&- zt!ZkcGaOa#>SmCnPa+gmz!60|txX@*o~$Mqs>Ze5g{HK46kizBMI&U-8$xq+cfUf5 zgM-7*CD`iMYONa(&^fl1OmE}v&X+ux?J$+E@uUC3QO@Il9;p*rsqsVcJN}2WucH*Y zx`bJaYw}BJADgF$j4G88!3EzKVQo?xXvXQFnp=TUagyR)I{%314j)7B_rTr_;O2*A zpoLDIHd_X`Kg>Q1nwX1pda}smZuV_Rr+7EX`5FoN1-v|*YffBV-3%Z=T|0GS3@~f= zWo!H}`aYa6${%N;9r6TueR7-Tk8>PYh z=kC+1ab}xIg{?-G;ma7K4sSanJg)5Dj>VpJ$>3(U1ougrA*Wd7teB^0WQ7LilSU3d zMwKZsSfn}t0OB*$hDD5a%z*vqxAjiO>6KvisWuxw7uP3EmH3+P?h1>IzlEnp`f(Lg9ZV3br4k1YJ z-~@Mv;My?7@7_Ce|MN5t(+@1xS$+DPs@hh&_WnL1-Igd9TG%k!2kh;WWku!DbdRR| zV5pPn$hhi&ud`iEU}ap4b1y|A0tWA!{I)MPXOd1#r-)m6y!E+8qu(jjF~`-{)x>vk zHY$6zqKs%GrX^p$)YZ(XFr`MybrpDPgeI^SUc44#zk|=FytnYD4brIZ0L}`cqoWNg zF9EG791aKE&rt@x^UikpPV~M;IRU?aS}noe-bk}TJeOE_<`4LOs2Kd1@-K5*ubUq| zW^Ch8&T~^>yZUo1R52$=3h{Eb`&z5PF`OW36%x60xmv4_Kg@BJB~YKHWVD*ivz@0C zYPZ|5DXru5+WlYjSh^&BKR3G1LqL@skt=+;=P7(Gy~um@7urDet5>hE!heAkWJpSX ze%yC5ERi-g{Qe(O`lhhmrPs6GS)5oSkI9qB7_rxGiiZ;oa`Ro*HethFC@V;DebISP zNXN`iQBluKPt{WT(tGD#`XZ^Xop5ou?~1p85JSnz$#~z+#@Z}PpEpa&T$8z++CX1j z=O-2v^w1DcD$ud$HnNCzeo<3LQ)DB<2(uu1rubz5$urZ0pZjjpQAkJtWzr}rhlwUk zkk-RTzyZr<3%9wR=Ay;U3>(rxA|T>6uXmwqdnLWn;@Kc&^#mixLNd+iyN=3@bB;Z1 zI8;FMe!WVK<2v_k_XKrChMPmo8UT=xrvaN|*MG}mbM=;X%f-#gj{BhxxY}+RGqv-t zW-{g*WXOn^{LSP>qT1k5mj6DjS8{M3?=NGzj(v-*c=pP4pw~0WiCJxOnvijMQxvK| zf2e)av2xN~8EG&VWrtWkRrA?2ZD+A{N=;nd-rj&b_mk&l(^FgUyz{0fcyqEd-x2q;2`a8d^*GT_Joim(YEvUHWgFL=dRdBk$AoU_u)moM zv+OzyWe6xblrXj(Z{3GBK;554XE!AH^1Pb$Dol8!O-KKc=4UeAeuX#BB!Q39+(3Kj zz*IC`wel;`iMZF9c%XXNHTR;_&vroie1GV8``iqf>NC)r<90ojeUXS9{7 zPU{5XoE=qz>LU&}J(aDenl-zPH@OPot(E$tI9yx_cKM%$yqS3BpC36Cd&-a)S_tFL z)u`~^;N?z?)c|e$g~Hm468hawY`dCkCz%_+e<82vGqJ^7wwvAfSdBVHF#A$VhPHz5 z%JyD(E52abpfhp4HW&K!)v8^&<|9xZ-y6|>)A z%pmKbl9PVkhMCS!{N>%W(iMDY?Yx+@cju409U#ROwtK5YypX*k;G|)GGG8^M-w&%f zZ0seuwYegdJ*jWio1W`UaYqcwy7nV2Rv_nk&Lkw@v3%|}Li%$?@=`gUkTaC%r&5=A zXpPEWt_OjfhxfDV;S1My>d)JxpbDsAr|ex`<6Mpm8G==;8CiePl(455+?Xf>{tbbj zVECj-;YqI-W@vxz0iy})L~}EDVH!8sK+DzXTk$K=zH2u%Z9qY+i+VnHv8irTqWue( z3X@+c^*3dg^P)5j$#CT#F33#Mh-0H*%ChKo^|H1UyAZbP1V*~IWbbUI{9lM1PWPr? zafM?qB1*0ftEtXNOtkrj&KENM&TVfpgc1i7E(1(0iO3@{ns5NO8#EW4jbzJ-+gE%V zw+Frc+Z-U3j=&J#8d(vvPG{|1(^I8~^v%_;@Di*_g1O5j9tJI&eoPk(ro`lyI(W%6 z&>^1}TOUGy2F65rA$PiEw%BJ7s7Y*}z#h4x%bsPNel<5|Eywl36t}u?;$@xTJ`9S+ z5Z}f!4h|XJ=v&cmu-At@&mAE7=7xw-#-=puGKozWQEfL{Eu#q7n%z+H6Nl3{ivbr7 z!L#gRWF|l#z0L3rs?#0--yF(tY}`mb<;zjE3!;RLPMX9|!A7?9>cP!`;hx2S-*Hh; zCY~W)9A<%($roHtQ@~u?tp4OZQh*O6GbfmPo0+XYl9CrGWYA=KKfo^^W^>@PH6y~2-GJWQpj7y> zape5s!eQq7O4NvKytUgbOt1_F@ za`+kTOF(yA=ro*>kuhCqLxf2f~xm}?INe3rJ1 ziK+nHcl_{i*e%|t!xsQ&QXfpC0?)$PAm>Qt{XXAYOoDPC5sV|(wKQfriZlsEcdPh- zU41x=)MtB2&k=qz-EP=OMX4^s>xyVl2;f_$Dvg#VCeC;QPkAf_DTrSHe4@LnUXlC1 z(`{4WGdCyDMK1xRP{)j_!lqReyuVsQeL)O3&mrFd){ekYi|fu<;YI@O=5W^B*w{%z z&fR*s5q!5liP3X^Mx_b|P^zat$$7Zjl2ifwQkh`jNG}B;z%L*Erp<}!Hi0-T`Cr!6 z*Ed-vlc5Fynkn1L*80lIqYq?v%V5G<0mknL;HKYky8%nrXiQMJw-opQA4p*x**dLk zIqBc4Y!_b30aH0z%R4fK42g=4PAj?|lVkm+Q)6+yJDDWIBA)aSDCs%B_ep_ux+PKN z*~-g6fS_;)Ag-;ftiX33f9JoJ1EuwPGo$cf>(qOki*IX#7H~$ZPM?3%YsltxUInD; zJ~*$T-ko#LD$ZutRp{Eh`NRWxCe}gf29t`r`L*s_ADuThlc=KtHMoKu!epMCdeV zKt9}f^?-Z;9Afa}0qcF35I|;rblG;<>U-F@1@!EzvMgp9!81j2w1tfs58j#~QFdsJr-ZlW7Xg5I|baxLA;hXLJSdn{R z!FmyvJ5kA6ZV#Kue71A@sqr4Qj}8YtQE}D>=}?yp*tv_IXd*IT&q|w^9?j;q-M8>~ zfL?Y_n=!=EgBaW~NQ059gOK7buJs1=0|cq+rVI7*Ia*s=J320bK528EWOHCw_tPx1 zOUuh`ZEee~Ou+IDWdig{KlmQ#^Tv9(ihbba;85is=5qvJaC8hj?#2fV<@?DvjxEO@ zmyV2DecVy7qd>&Oe|CQU4M=l{p{j1%j$L-({dH{M-P%Sy z-g2SIeR6VAufZX!6Ztil-tr)tThh%%L%Tnaw1H{>PznNf2jI2LICc(wT7mKaI=ho^ z5%mrW{JgwgUC(*!X1?dT$VfpcxZeK#` zCQoxZ?>dq+EaLU=y^_)hu<#9bvj9Z=(PqAA2MYXfH}Y`Tjc-K!>eU$6K}!4G2Iq*N zTH7rBmY<#7*E{OWQ;F9r_aZqX&3j%janQlNN9wm<)q5B4@Tj1?ys0Bw3tr$+V^EEQLJ%Nqnp=IQS4Zs2uF;7TTA1X!E)^KXtM!hS#E!=*~Z*?55uYrh_H zH1s{FJE2S*YxTWcbn1EzKxKCU?K({&`qKSH1K5BL7GVM}X71+hE_5+t`q5ZfR*4MK z?0vd<0^x?7U0mG5mmc7Rw6O5R%wx7EPj(zvA4Bkf>n-~!ejw#yj_u37?x|*6&7S>i)I*w!u5u`o( zyB?}Fdoh1nFZPSx9E zf@l!;JyleT3WOx-4BGNv7_soMp$fQ6G^4mXsxEf(u82TQ#esDE_aDw(Vm)^S#1At- z6A8UpNUBo7;|HMNMhX~B@M9p6D>LZF9{j)W`+t7n|BwGh6DjfG{h$`c6MY;! z#!6QRem2f|7o#mt4jVN`js!uQctVE>c=u5%mZnq;hLZ~DkS>rp;2Fx?7%ux`u?bo_oq2I0-h{|wZ+9-$Gv2M083=PSdet&=6p}Eaddxp#E_~BM#lL}?>|$`e)qo~f%l5wY{1!L1V}4<96l0oQG+Yb2G%QWVtyV3a4(C; zcOIi8Abkj?`$iAvM!1snSzq>UroQPpHXqdMIkuhyVO|nBiHp74FuFJYFXKXEZ2O<7 zW*AHFNCU6tHai1c>*KEjv)x(E1R)?G@H+WTJ2y9Xd9-B2-^(=wCO*CBdJd=%64{mL z<8kp=B$yGYED&TAi@Mg-YBM^6=wEVBjNovfyddT=F9qHqiMsUTj5R98a(PfD;8kSAsrg+flUGKxMlH zPX{?2^bjHP<8H)ZuEHzCk}55Rj)3$L_^S$oX4!6ZFg1)s^&nh_DmZNFVe=}YQ@~iX zE@DE^+6#3S_C*q zqw8+g0F`jA*I*x%I$5q22rhYF%v$F7U(BK@k?=Y#=R92JAc*30e?Wa1utv1x1$+== zoYdpcKK%F4e*gE-I9wlxb{uI0V4??r9OiRo1HPj92dV@ag>hhtE!fy;SmuNXQtHxYgfi=r$7#T(67M;8mG<2h?m;|(1N3q`6+8m4i685r~(xNK%hxU z?`L|2H?x6`oKG7)go)e*yH=Fh7#S^raL%b-6ZKJoHkafg&xh}|LrJ%QOXA{^#8b&O9+VFfMEQuZw=9bknI1sWF=+n^#67` z=pP;p-v7E06bk`m|KFEJqkcYaO#b&J3!F!V`rnuSKfY4#7#gr7^c_$YLNx+TVp>Zb z?yV$6pl`W4Fs#>VyO_w234yd2wH+J^*s$F7P(}?ClA|G*k4)nM5(+K^z>I45j?O&3 z-z-|7zR;3npu{a=^ed(6-!kj0&iDD`QGYLNcg}+4pUhQ2bIXZwC1`BrRrm88a9!rB z7_;&sa$yqYjhw`X7~O(fbJepXJ8r|(3|TC&Q9fnyGU}bF_fENapa@DJXDM0U;&`)F z6sF417qW{oJmi-yfYWvnnSqVN=K`6O^%Qu*vX_G~tD^rO`p;X+xHs|Z!cYyoSN~HB zpid0NA+~(S5c=U9BYlIb=P*Lz@U!{lig-@tHZPz^*Ack3#;d1+7Rr9-ZYfYRXc;Cw z==W^J6=|6qEd0;lHF~3Y0tJa3ig6(6lE+Qb>qmCYsCtK1nl1xw5Z+dK+QhPzo6&eh z_Z3~=b?uAosb7B%lC!gpxeO_sM$ov*(IR-NR~_8{kU%=hwr;cn`OU#ub3cN-%#JY%aX}H1#7DeQb8P-72ceimM64(;(W`DA$zCSMjj1 z#C@w`{clnB*p%h5{s2?=`R}sdeAbRL&Vs1qNch(vy`{ga>wj<1X#{ zAxn##8%YHX(Mx9qNvMtfB;a;J{w?;ug{l4~QssAG2@IdAwc@{FsKf#~STnzqa9b46 zL`Lyz?byxD?Nc5dG=wgKgoK1N7FBM1=Pgy#MU zF;qM&Z-PGJ9R?e62u72>Q!n3Jf>oPzR#w$l@dZ*E-{Q@KKmV|9bI7cIvEQaY>_ja4 zNxHO|k<#J>IwTlAW}{P~l^8^q?YwRWc-7OKPB%|+^|M+MP35Hz_8k-e@Bv>=VWbI# z8#VBK06(yXk}Q=kid{p)UpS|%4BMoZ_)EJoukdr`%hO;DVYh53MS9Ut22Z7%+2MR6 zXwhg*S#ZeH6@#WX?a!FCeBOxpaLZ@F1tQ`hbeO6*A!H@Spv|;6PHq>Kr%A0)zj3j3 zylNy0bnD;3>+0%+b1LiV+`YVJ_RfpO$LkwW3e`VLC=HJowwJlEdw%gQgMQLpz)~k+LW_9V6yVAU2I!H0*TwPFohsjPa};L9SWTe{ z$5?P4EAp;qOtgt4{^D0C#}l{rI!?fx5R%P`V<TO3zp%o)Yl*UEj)?aWK3!()byEje`({QAtjhh(}E8 zIG3bLyrl3kj6LBr(R$S(!77Em z&S0HO_x-4cy)`med=6)A9N=$sp}pX>s0xu0-;Q`kKgl(;b&4qtf^Fd(P!3%AT#*Y2 z7pX_v-TgcS<>`DF>Pu3Pdn+6{bRwAvZ+<##<^tT z=?e4c4wu>kZ!W5_)s4*lFfVG5p#=Sm(^_jbnp#8BQaZ-Q>5kRZS|X2tK;pTKR07^` zaHumSpO`0AB?Wgd3orS}Hl%L$m{l{TWE7-=@=B{mSqyytb(@!OAfC%{!92tDe)q~ zDePd|^aJIHAeQzIsejX{;lUG~(~&zfxXPo-;#@tia0_MQv5IE3=**aH#jP4OlSN*k zzrjX?93g3+{9e~anQAvF z>DD}^3m^Zeb3F7g*T%upqZbgY!lx~Zb4bCsA>YAhWeP7WIa0>%J)5!oLY6(KafT~B z-xj!4^wzKt=+i?DVor6rn}w2qc`SI%721EA^LwNqWZPCBL%&+nL4RtjeJ{4D0YeC3 zzEKlnLU}uosK@F!QPDN*bj9SjT}p}@8ZzWPTun2t5cS#H@aO>>-QZp6ChrL19XIKb z@NKj_ipqtS_p8mPx?fUx(@1#jcG5U$=16q)3JSl9nogf<(qIP zBCQnk=fC-5+Px*4Yi2jYOS}o4=cqPtEN=4POXgE>3>%eCcgh*Yf_)Yx|L%8vG8QM~ zdjSIP;=D;VsXqN!O9MK$R`N5admrv*>a;;c>+X)Mx0(_1kPfgp1$peaA&Z5~&&o7X zuUrPE?HyVVqpKF(F6Tbv>kYV`k8KLYQxSfQ8`xkPXgU)njIMHD`FE>6>3=1x0TZ7sKu(|9s zGNR{i4yO!@uqomNyJ==Wwb4}rM@z+hkrBL{pV}YtB+U67=USVxf4!gvAy5P*2pF2u z-vm-kFe5`)gPKm;r9ADwqw_(QW7OnhWA?q059ZcmF4Yn1YMZ(Td!GJ|J01LrRw%DZ z?FbD@y;i3`QDGr?R#sLFrPxq7rz<*{J3quD2KD5A*M_ZKTS_hg0T&sR^KJ&3F1bYGY_m1KWd|ZItI!lZJF>KUFvnB zJq`^YV0<`;5jX_I=)irmw%@sEX-$`=#D|bDzHRW2DL3Yve*qbrq3}LbFs6A`2@i`? zkl#Z!jxU4RNGgr?7oT6r^fK@#$L)wDk{uL=tfxxO(W#pt_JWud88C9))hI_-2~ftp zv`xSL$7c{2V8^5}7lj{1dM>zqWYKhAFA)eyW6 z)!1U59G+p}@d_0U5e9|(|}TPlNjs}J&51oz`R%fHH36FD`ppDsts?I*!UYP zh)`kWhlbqhf+CSNX7RN3=RSG%og1Fx=`Ro!e>uN@hzu7Z8oQ2?grYhnC?JT(<0Mms zeTLa@F%7J=bnn5{RK5}#nU>9RiD+s}(n7< zSxniyQDL0_&A}^i#YgSF1!PAx_9{4%D#(y=F1e)@-z9E}L{%}2{`M8uRUr7$K=5M@ z7JfCF;-8-${cHN+DPe^kp4UgB5QAM_H}X^6^yls%}~P>UmW^} zMsKd);hjX)7>9Q0yO~+}?^#_{!(<-n1U!nm>iM111r`~|zsw3pd8(dgYf*J#J=&(HnLQf~oBWF}Aq+uH zuZaS8io+`wlC3khSc5V1IA~OLzaQkSCAR;889`BBU;lLZ@+1f!>#YTgh7D!QGzZ61 zDH`WLe=sk@&K&+2X%^)$PpAiAH;Q!20Fd)krUAeX`O!GNNPxBY4%JDlVT90m*tJpL z$jC@dEy35!%Bl}eXdA_>igQWzJ>oN|-B2_@fg0G>=^=R?vDIQuC0qFvS(s;Wscw?% z!PSk+B3)G4+uk_6N2aSZkmPcX(f``v5HvpB<5bXxbfT#n!#I{Q3mwdUZs;86x?MWV zjV@pydJ@mk%}9xzd@QTbDQ0f%6=JTs4y28-6S4G=p-V!VTq(4z1G}3qPG{#=75L{@ z@4fv(RCh0LB~{!a*@qhem34cL>Wu?RNRu4(2|XIQnu_Kgej=F)zXP6Ut5Xs(Ei_1c zhyEp>(cZCsaT)z^g9S(L$@TS``>TFFYBNGp6&+zcodEve&y8j15JXYjE#~f37YHBm zeI0pAmVDDOn$#yF9Dxs=F~`4ZReavD@tP3Oj~Bq0CTg$O{+uw3Q|0~0!I0Xq?_6Gp z!T!#~b8M_~HZ}1~XKKaoUYn(OBxI)vYJdPOT+`!GQt0uOQpfO*e)@Lc2x}MMFZ&F% z_r7$jJKHBzYCG;B0_Vtz4H5IBqyI{k{B62EJ_m;+%vt0%0S`YFU%(gxE5o@LEog;wyU6GMVewdJgIsKy3$%_!6{*KpY(A$%}^u3fD!zgT% zX~4&V>KvXo0kJN4=_}~#%7+T7g1*RLV8zrhC!j?+ro2O-3+nPNF9R*MTX*8~*9(al z#a{!+;tPD==9;ffw=C@`=uYXaeW;^tR8OK~5p>Vp@{pX(`TgDrQGr?PSd+PVp=R|h zM3f#kR*;p}cTn8H%*@QrZqPYXlpG^kN<(AFqNa;7-$a2kvi4J633`-;xj0&%p~yeHJY`9HxPOi<)CEKSj0i-t=_M z_R|;$c{)H=u;d^!wma(~dilwOKZDt<#)pQJjSEM~Qt(gXitS>$HiUsAeL@7Kmn z3QpXI>f!V`tOvZkkXIQQAhAqn3fk{mTU$*{O$#@ap%m3j(^FF)#VLB70X>ar)y(zT zteB4PZpi%)hs19GcfhH53i`9ri;w?0D9#WG3}7Qjq>`CF2S-!9yd`@+?z}A=uUa)Q zbe|(Z>IY6vt7hU7XrFekPF!p^lAwUScv;z|OXGjeExaqIiK3<6C;-w0@Cs4vJls1T zyC4c1*&=%N>gNjEmS7He-|O`Bbik0z*+V5`5|vhDoo?a1ltT^$=X=0fCXRUt3JVJE zzZe&`L|?Gh`(wq00ZlF96BNvpr~0%eo#+x2VlUueL{&Ih-I6)>q&GYURYwH#nT0sT z+!m*TE2tQalfLq6Yii=>>9d*h04q#F65YGD6}Z-HnY@|~QQm#xeu{C>|y@a)OL zR}Nur8kOCmU+{arEsZENQ&YC=&L_y7(ejB*Q?(>JXH=bNJYjYf<-SI|EkBgmo^>5~ zKftC1R!^%$mo3CAhAb4u*E8FdG$J!a$Re{0r`;>ZC;l2wF?j$|NPxx=c-|_eNw5!C z7+tpRsHGEGPOdd?{lsK_6;7ko%W56CDSmAoPfSi;-vzV+5soHwp{qUl;DDd$Z(@1( zt@!LJ$b7B?Iq-CKx!V0ut&}G)i??Nngv(Eiz_jx{+pFmQ>dYaF@f|mEjDKE&O%*Sn zKL^LwXswHh>>87xqJeywC!%|0Wkuq(7__wF@k0YkT*8c}0=}%ip}{siS(++_n2&>> zACTj~A*;t%faB{pz6Noe>-OemY^S!!y2$#~$CcA-GabCI)!|{8*vlVtIeV>aN-l5V zAB}(PYiPtt!(2%tyMdT47!4Qt!8lE#K#!vp7ej;z ze-_AW)4(M1Roa)1dKe^Bn3Ap%rr8NVMzHqR)>BSyvvgEf{5v&zQ2X`hG&+e`e4jxi z&XD_N=+%Bh%@=!63j2^DFo#=C|ANcRatakO^r3bYA|rE+9c}DtX43)e`rNm(Ox!)G z0(Zetu8jZ5E=}dxhpaNwgq>0f6_)(&Udt4~mb*M{-=sP{VtGpZzQpbYtizjf3#*W? zhiiBVA9^RQqTWLn)b9;*odkhmUcB3<&!^86ogiHR7n@adz-ysA=JNw9fuIi4#g30M z&X%vBeMGf51{LJ;8Q>Y|!CLtzGrs@l+(I&3ZI`Uw;ulve;!I49e)5M^_AAjVn_@K@8ehW8Ma(U* zOS6Rz-yY5sX4ZfE_6?9clLT*&8b^WhftaYM#7!k-F_TGqVu&nJGzZ#z_TkRFd#rMq z#+#(q*pTJs!?jRtqnls%PnqczjZ)2TH03bp4ffCPNB()CbgX#`rp?F6W@U#a({v+= zPSuwy+4Ccc*3qeo%laR_*n)@tB%L$lUVIZ6a+-hL(m!L+xmSN$YVoEyKnU|iQx2~{}z3QjJ5;LGprfwVxFoIlNOAA=5CbXwdK7^11yQjgZB^A+KFM%jXDlW~P;ZAJnOpcK`clbO^C|xS( z7JmPp?doFAkv2i5VcR$g*xaEs&fZpCUSf~ig(64p4+1yMTn-cPj3)MCYoB*8*?E)@ z$d|Uq4=Lp2x&>J4B5EnALn~Xolz~Zn^rF0V1Wmoo|O zxeTM%SH5FKZuHy+Dm`>VA8YuBtH+X)M8;!fF<_udX!GXglX-YObA$;?3a5fvd_n!+ zzlapJs`QV9w~ho)AWZ6sLs41IIB=!bS>RnF02sm3mM}wdu5G!y<2> z`ALa4T?VOINUjE%Nt~x#T8Baow`$dyH>(CXuJdX&yd47tzfaNd^2F2@Pa}3n{ipkz?9UpKWeZboqH?e@O$q77gf;qZh~ma5Q3oF;6=ww#`OfB zku+Tbl7`Edj{=J9e4uu}#wj|+)rFUg0q=o6&CiH@RQ?kp;FCbGAugU}gDgKJZD=9* zW%A6_FI7W2FuRG~*elU++7KM>MzdL4rVU-M_+@*w{`FFPg)f-_tS4iOA>;=qPLm`K zZji+sH{^z}2Em4;ci{TgY*sz7E4>IQO2tM_^^@z1&v|a1f`VD)mUEIgB9WD;s1J}T{Cll3%Olu+MdEMQ zUWVA$`h7$yzl{t)rT)ZUZpNIcyl?92=%)U&ooj^$Ul-o+_bX}6)3>hKy={1MQT?${ zLMfOQ9r7MubmD8SXKI0pSkov)`PPHVFVS<@TbJ+2XJk!ZDnn%=_A5;yrdie_c2sN# z#Z;m`FrB1{v#!6Xzv1_ZJ^0irmpr40X@E>U5uyDd z%k8fd@olZ$?B-p8@fEdofDX2EHWRDmSHDdFVkZ;yCPvLX9r76$_OkzkTO;dx1`6db zl3q(^2UkOCnVhesjZ@#2d<947`dzEE7wbm|OjFH#!Uk6SX4vY}EUYmlpRidG1gH$^ zCOhw%1;U1ZFNmcpBLoQ~tMuzZ3tfH;!$k_u7FejLJ2)vF990e{jNLj#-`568C|rg# z1tEo72S4cg?VT*NYjh@z)xJ&Kg-M5ieGlrBC-ZNfQ^}m5gxHj5;tR%$DwuGJDdTik ze+8tc=U!)iZC~i_kNu1JM0@sdA>y#w=g-s&#|2Z$C(mE*d~~-9Q<$wPOZMal_uSO4 zsXij7O+=!FA%zk3_S8${qXfnD^x*pY9~NOkI-u6vL+o=gzfU%IcV9kxrfyjS`y7%- zpiY9hNnK#0hVgdsM}w38TDK?zb=u}nB-HrM_p%rq=g(nm;^AvE9o}58+?#de8f%ys zy$w8hm6bkA;h&T>g~TOCI!jU?&PS@Eh5nLcjvMD0D`sIVO*~0BZ*HO)hrfmfy(|%lJHYZw(+^_`|$aT;jRG|``0{@AVcf8UJ>Kq2d4R2Vo_4LD7c@2Nik>DtrA zV>ECa$E0}s~rf6H5((3jIdQy|!xZTU1T+W`&ksQDcZzStPg|#C?!?W!JN=emnArL*G zY(v>MIjq9joiqxrZ>zkvyvQYtXacE5;3^r0i3#Y=oKl$%l=+@L`A$&)9~ z8ctVgQ<`zbgFkz(%~}7z{bh@?VlE?_ZXppbY^YX~%-#o>pK3-Law1d*+`CQU_!Qq+ zoWcElf0>A#`84D1$kcI@ShEDaWd57JBjT3Z87?|o3-KK40z1v*fI)DY$%PM7-uwot zvCh?0Pfadq_xR3mWX?moR?x&s!G3OK#TcYAW#kIi9DzbEZ{aN^VS6Dt5vRUxP z3^&s9f2FGbpIQLz$@&wI!|IB%3(uGD{oDJ@k^yQ$?9xAazK~d1wwg^Yz=$S7z)A67MCC71If&ukJ zIS@Cizx~yY_Z~X;@GG2uksC&(|&?x$4Sr7dlz$Np`nRBZaz48cQci zTT5*5A83$FeSHz{U&Gz_%=+8I&BRJL;l0@Jnw0wL4r+_Cc=2Y6eBpzgLl(j)DN|*| zA#|v=g~~#?gZ)uErttdQoV9eA^y2p^wj7^wgbu}*8>lbRuFt583RDRw&Lw%36o^Ii;h{_+`VHPb;WNJF7Lg z9|Yy2_`&G$p2MmX6WaVH#bF!^&BUjzhwsHpOHc~lC(1@-DdA$h-5M5GdiQBP(rar$ z-vfEyi)=FFmtHpt%BK!&p`OuW6PuZ%$z)bN?%W6&=xnR6=j%8+p=6{<8#v-B+6Qv% zUIeEfC0K7!9dLa-_e|mQZ7>Q!7)C$Tyo02-e(|;iMweSM<>7zb=yUl(NZ9Fq3C%d< zm9={M63MdNv;E2VE|Pd<1yIvAbD?68^H)&TeBY;%$IXWJHZo2Aeu7E8z%93TT(e&A zkMlqttTu*hr|O{V`feuy3ksoxVXm?S_ag{KeLKCDrL}@^Y*~xnWuh`gB1L^N!TbVY zdq1Z$7n8QRlVN}=dF)ZyVC)xjno9l);%5$zf;df76HxGAy>@cIiqEZud|zUV+4I@4 zd0jXeug(~O{C=WZ>Uq9ma!L+A{d%3Bumb@&hZM?AJ|2-n@F0}>$#q(9&pS*Nh>3`S z(TyjG#$n;&;8Fn$-bbeLN@cp43)r*?d+=}s1`UG?9fMcMJV!)01!u~7%yXEsm}>c} zjh;eCCdO+y4v2KsTV-hkQJMsH1y14@DMof&c&DMZg-%E*Tqd|W0fWQ8Nao^kx?5wB z#s2xU?zsK6e;FAsKN+;)$d>j5xy3_j>fO^>vnuUpS8y?%n1b;?fBuLvY_K$_D<{@Y z3*bRh^9W=>&Zw`cg7Bl&EZ?lDDgxvqVjWUvk$2a-H6acODD)oCO&$nOmZW<_%{S80RA9js_!C>+Hh`?4%c7cryR6)XEe#nm z;PPTX_}#H~eQt*L0K3BY*|lE;lU%)l8r{`-o@A zOi*9GSF!RHYBvrGwK?g@<(>Vc>c{uD@qC&dV?UIT0Z(zuW@(jN}9* zBp?7>+E7e0g;EMOXZ9PT=UKkF7U690Um0d9!NIE&!fQtkMF9fCJ zb-~#OUWYjl(V~@qY~rIrz~FOSZkb|ZnyY6n?>$mdV;FEDp>R)&>T0wmC^A1_z){3O zchLA=SXcAypRK*q7TCSOX$K%!o}R2#^HNcPfCEcv)A^Dy7vaAnz4C}h4K@?&X>5k9fNu>hxNd!4b*Ug}kve7hh;HBZ&AX-C8 zk)+C9;wDM)h(}bqW~uQX-`{fCpJJbFR_ip_IJmM%tAbXOYsq-PF>f1(2CFUEjXxIY z|Gq}dfS07U#(wSB=4a3=w^jcGT6owpc!@;`J)Gh=j7EYqRWx(D&l6e3r(wHlxF45B zr#w$SpXVIWpU0|B;c_(@FH%T3ae?W>RK@(eh_Z-&Tp)?ReV)=))J_P|c4JS7iM`wM z7c<*b@0>)=%f4kfMdnu%#eI;5A* zsz`|%ADS7U6jQ&&as&9*=WhkyKlSiCO1^1oQsy;LiF0y5!tIFI$XeTdU0gJNHh~nB z%By(dysWtYUa8D-q_DC~0wpejBX^KxcfM-aTMV4!Il>d=|8_>x*92uBko`SbrB+-k zVUm@Wh_|t^oyOpB6lC&KPljhs6G;8gPPFswSmS#=U>&rmZWGAuYs+?J9E%ERBHl_f zb8)0`t@kOG-Vq=jDgL<(3+a7n#T?8j zC?TFpw2x)n&tN*mIz4PGKlJC6y3HV4nb|em-F@hziXI&X1RWz~BaaCmfwx0*+|Sv_`xP$sLkGjw|7<2mm)->=20KwXCZkvwTHKkww%`Q?J? z#b4iVb`8l#UGZOWZa8A^D9B+>vQ7v>BkGEGIf~ctt;;#Y0ogLHWTC6n_ybC**>s=j zZ-aF;cN6keXVR)mfgh~GH)6i;2{=Qz^Oml?J$$=w`r&YLO zHDjo}e!=^np}_z3gxdS{=u>9 zboHr<-`_b2Kj^<(9rGmVO(?kYnbM28*4)dqM(ps`@Mp>aWLZ$rciS}tu0aiG-lc!E z4U9G%Bz2Q>=x`!RCjx?=h_VJfg+LDwu5$O+;WK2(^FStf_fCfRd*MrJs3v3nz!dVTh}eM38X$r zN7Gz$1w?XWG9Yyu8xec=h8$@V=Z3?#B$kcM0-z5rf(9$RWzDNCXROxnvk#*J&2P=u zHS>on1b|*x%uA@Y7k3C8Da^{VI8t& zMNe-}`s#2EBK>}A`w4zme3OCCZ0mb!tidXDwlT52a&D~@qwIRVKA>kA&(3!|`j$rs zOMZMm(On!GYWzcEiayx|bWLU>GqbSp$EYzRnQYv644%z5x;i@%o9Z(py&!4Iy$r%k z&&e^;)^EugEhsDVz1RSp2gz1cP8rQHNIhhyhn}w!zV;v>0_t zGV||9JA6hX3OhbAX+z{-=ePT|jUW1Qb9s4P^k3PCJkW~#{KX3sSTZjwBGbsw(3=ch zrIE!CsHiu$DfGB)IksHl;)~ikd~MYxm8=&cx3eP-=@0Lt>LfS}_6N>lzz5nufk+hm zZ|}THb59PO|Kk(-mQJR75J!!+rVVOEbo=tY#Pm`4#F%}VWai=~l*dtMo$zg{VDIAW z3@2X3V0z9+^Jx9)5r5?FTce}!7JM3u7|l&C6LLHX$eS$xS=qU@*k5`lQ>q(vMm}}j zS@^6jue0V{1AXpDsp#)da9uZRV|L(|3#fbQYI;*>#?Q2c16T6QYk4U{T;CWF4EpO% zxrR%u_TVzKrcEZKC}t^Zoc{|(Y85BWJqy}0pf)Sh6fm6)U2JIZ8~h1Zo#zY zw!PfxHTxO^2*i?v;xD|>s)YU*hT{aeh6=Zyt*tzMGMHey{9v;zC(Ibm+fsQ}1m8_c zD7Hz;NS7-s1AT!F4f$Rss5-?2^g4?P^8Xi2XW>ux|Nj5Om?Or~9Y=RFZH}03rcF6-42F*P+EQ%8+qVpG4@`}4bf&tJgtbUm-UhZ*jPQT6UL0icbyC4#vI%Y?DisPvW2JWoqh;K~Tdz%`w1@wqV!?n3`LalAk zacHE27Rp^Z>NPuVF6BKm&1S2|_hJcAW}zXR%$?(!79nJw-qKAj&I2zV-zRK)1Z(-tDv&e4y_t^tlf`hOK;ftoxie_KU=*sb2@@{bXRFSz;HCq8v29~j0T<{@rNXs=#{WqT zwerm8!nC4&4~hGEU)2zTVM`toleC(rXg@=!f8tJ}%&!#_h@<*T2ekL3UOK{J)JYB! zutABsAP-Wzj{;94#8DKu@P9=k-y4Vcr5v)!dDLL+uep=hts4zhtW`+yUDh_nP_fmL-)~VwrJ9`_~m7TR`E$ zK-8}rbmLJb}Td%so9sQEFkS_ zmagDIjw!cr4oP&YD!brz`r9YvjRc^bZh5B#aPWQY{hm|E*r140X&9p1?A1lrV8v2A z@rSj}BB8RVoC`+`#?cX-POCVv8b{7ye^t%FOSE8w3f>nAj7nO^1Q{E53MGI4YXKD) zOx@!l+R^P7EDPd|O!luLcmmDVY1|3SNhoTuo=qY54D07tAI4`Uf})7?78rJ%hql;< z<7%G3?z{7o7?U6%NWy!x!>Ink)0S5VoMDM!a`7H|Xq6QLSj%kFE;c5h+|#lkHs`v zP0GQOHp%-+MLN}nQIOQsR98N|ub$TO$NX`}6}e)6WY;Y*w>dHk9VEp6!z-Ha|^P}LCNN7;mr7Drx#=<^@Z zihSAI<)+OS?)p00izy&E9j!`{%u^dA+VFO?B<%@A!sj%K;a3!|IlRw{wd8}6$l0pTe(5<-r%I}o}(T5ig4>@hBTw}USMeE{| zpJkU2!blXcxp50)xJ=Bce0FHgJGrET2}Cl;ac(JaXN6l={eQzAr3q@(1$kd+7U&Zs zb)p&MwhnzG=gR&e^kbYb~fkbpM5ZN#n806lbd>l$4inB%XIq` zh&EHuXkAD7J_YR*k5t18C$;fKIzchG=I(+{{vRj zqCX=%;g1wpxSx@z^-xEA(!M$3SO0eYsLL(WUE`CjXJEWQ3CrMi;Hc)pL8DM(E-`CS z0;8n-$dh-cdDSf{DVhyUXP;h0$(hHS#LS8fmB`}k#99U_DIQRjXwGJf?>-k5>m07I zJezM;qxagrCeM5DKYN<>w#Z0Bc(Nx1$V$o!4aHMfnOa78sXkRv0uIIYRycRY{z&Lp`3YCzo9`{UIKtG4 z<>ee>!g}@Nw&wx)Tuhb^EX_ zXDO@O8%uPOxk#L3?81)Aco)>VN)Rxrq$AiRR=+FG@}ce1t4WpMK5$f&cx! z+Kxpg!r&*bcwM{}juDB%#O~n!#2|*aFouIyMFcZ82*V-FTZEqz1hy*wQ_kmmQu8ZN zAwS?<04u;BF&7r1uzSC~Poz2XXPS>{<8cEyPYFs%6*mCs>Q;%7u?CAH>Zk5&n|-b1 zXrFtA!TCPwcC(Nc4${OyFiMW+-_*b7a_mKTp9jlTo;wQ^?InCa7il{!34eNlH|dtS zuFXHmp=y{BI&1J_os{GtAXFNxfY2ZozHK>2z zgKh9qtjE*s@BwCz-PfgxZ;6BmG%*+<48(xlhh_$+fCWYjl+TGQupnE6q6lFu2KTVK zn}iay-YKb5k%1Tu4x(HeIuMBcv=rJMZ+@o+!VSInmSf)5Eh=lJ-l=)7`I8(zzf;o1 zZ17$ZqhGhe-ST8K9M>ssH~P(#PLneqoJ=K63?YWV=tq1~*RTRmEj6>KB+2rE{@KR? zi^iZ_0%7&greg+fSAoApDdkXoe_<}oFE`)1(e<;BS*@Nu(!oSs zHeue?p)(_H!nNI`lAEhh*jTvk=d0+DAtDb}_?v6hJ-x> z`Sus}p*B3Jb(%_OhT zI;2%Tg&e+L=;ND#6=Dj698I64eHcq z6x&8VlA57BnPW{R&p^xK3F)fEfCdiEUJL^d@H49rfe!ixbldYs9Y3YL-E$0eD>Bae z_=%Z{TD(emE$R^GB@vk)k15iigN|EE6+Y;K0kn_uuQE*AYXn(wp#tG@iltq9A}qTc zCV?B<#eKmTsQ87Ayc{v}!QW9XSEC^^V-&+iYzi#QAP<2g$$#09ue7M-Sw}_iCbzz@ z=>+66v%Gs}`{ri^%iPFv^B_gU3uK4Mw|OEO5Cv9*g0hjq(^QqIYeIQB7$!96mwmk? z#vX2$GNr%y!i5xE`*Mr2(!%}yDr!8T3Cnk@@{C}d8_LA#p+TXQ+f4+aGDL3C3+V`C3^xVhDsR3nlK163WHbkWBCnaMngE53#Ov=+UcwZCXT5`=!27?gOu zcJ-;Uk}IjdwyNr5$td`*C*xU20pu%VkBzZjw`{9FpHi7gH7_4uPM*Wf1EWn5n6#t4 zSD3n?AwE97?l(SkP_c{R6${FZ%_{fvroeas!yc$Gtz zfS(I6ty61~C;|jBfN1ueaIi)C)X#bX1}0LRP#O@%OQ^&7{YMGA$ObW2>}V4^xJ^sv zvZmvszn}rdGajy2M=OH_s-Q=VC0*pz0H97e2m`zu)jpf3^g_8+tWGl z=ncE-6X=$3g+myAJtM`oaHpd{R0{W4n;GwasXr#w8QWq=@2WQkb+?kW{JxKwrmr@f znw)?n=?yTdbK0e({b^isIDRI68DJ(@7SRp6ko>SFT-#Ml^7NB~J4G~*KD-fD*VI19 zp3ZM5)x)==)10ivxrN6Zs`XfB;>Iu-5VWVU-DP=Wme`yn#56^E;~RtsX)lkrkW4E3}{pUR8bE&-qh(~L%>@BAioKI1I?(BL5ed}E63JEc!44M`85MoC}7 zI1pv5=pYD;0ZyV}Bclj;+g63avmC99-|7m`(z@WqkdI>_^IL{i<=zV z3ZcNS1oEzsurfxo`Q`Hj?>o<+5k+)%vz9^rufu=1@JUlchbm5U_gSV3indXhwxS*a{$98juw8s>lKjgHB`OE=dHshxzPzomK|~doq(W z3Jd_P$_|6G$-LH!Dz;=55ht(8 zYZWz~i;sLk2O04fem3AyL}nnqb*x=Ky)Fg83|Ik?(0d3s$4syILUJ>jY9 zImT_EfI#;k-@yQ_t6MN~`#vnu(VwD63iY%@CUadDP+7aq8!e_idLVH{TbJIS@+K_GipBCU{!xEdwGtkwWW#v~3E#j8P{Pv)Tn2Q#? z0n}ZdE#e8%e+@T7(XW$;bo;h`3ALbg|2)HYMtEfxQ$5Bn^eJ(_b;3w}Jf!bqc?C0u zBD;z*y9!MKH|mVI7yRt-Uk@J%py7%{-v@1YuL(7qkGOZDlyExPhhJ#qn%1%AE~T`eh(hJaH?pOuQZQ}FYHI;YduJTBFXqOzjDR>!#|<1f)@?k7xd%Hhi$!IFrv0QU>d)HF$nqdQf|sIHU4`SVMssqQzT6mM#wUbMK4sU-Pe;!QA_e5%KtGh(RDlJsJp}P;Te5L4OO}1jWdE6I%p4xL zts9k%YyIvG{@iivY5YT6_J#5*2tQoj*pRXVF{%&IhEBGg1V;<(wkPj;{nh8>6OLw1 zd@8N!S|hyoO`IH4i5Ew>dVTGeiX*M0jPjTDVuNZ{a-XGI%PFS>LBI@OJZsrB9b_o%K_3kX-zdC0hU{%%uV^xG=_N_Q170x61yFrMF=Rqqwg zes!S+;Uo64d9)Ix4ji6-L*8#~&PxB_Y`(ITeRwQrI{33GjS3zEreFmvrn(bNE&sG`_Os6A5ulc99=X7QB1V~E?5WB-h3xc-=mi`Lm$aoO z)zMaqlp!Rr*U%F+W|`8}kJ5Ch%+qW4v=R0cPT7X+BwJE{T7NTY!cR|6=>f|~%jwZk zhsV!I!syu=)7V0KRo%h1AtPpmwrO@plVs*ZrpC_|)$D>m3E8n_`~ZR7bZdbf7d%{o z`6S=XvK!@0UrFJBB6{_Sz25K>eewPFUg+u)KPwn?<0C4$@RO1izG>7aeJdGE9lHO< z?=LJoJe-DP59#mg3(!ZtO#l92FIY)@-a8#I_WPfto2$TK%)(a@mU`~5j+>rk&+*&* zD(=}S=qGIRrgrhwfO56qso7|PUtFr53ih<*#DuBeJQ$BH`%#5d{v2=qH99&Pdh3>u zb8&HTnxoot0QNMaP(h4Q_ypiH!F99LIX-;B9`)%gfk3et4j0{6@R%l@t!|Q=ma`NX znZ}&0S~qXc(u_Rzq8?U~E)UE!Gnw%>nS@yshORlV-?~^-4}P<`y*^ETq@kxzPLGH5 zfALg72feuuT?^4pQyGGqNql$Hi9S`!SWh}GG0iHf4dYsp#0O(uvh=k1$y;JTSynW> znbcKqK^0|q&YxJe;53dKdVdZjt@M>(cqO`)YQsP}8kL(NTAz~OP-oCaIM*m1G2L{1s-9;TH&v;lPO~Xx2 zaWxQmoFv_8%7Y!Ul@&Uox7JNmzIVtkRh;EC8Maid!XD3y2Z#RroOI9;pj&@~>#3eW z3>Fa$+x8DS6KI9-7JDC&-=WzUckB%E0(}@V_;UCBC_I;M>T{CRlTq~V3?C(|)boi# zF8upB&KB$?oW~Ci)4x{@6=Z#B%4mG`u7(lxTF&n9?WWNblpA|;?VH*5ZqNS1x5p$5 zz1XNg3?AK%lKzlA5ITG;nixN|EsY!+uRHGtvoy>#bG)+$k-UMb%L9%Qha;7 zjKuw^En&6t3KUl%F}H9%(Mnq&VsH;F-evd%GxI`X5yeVVjKO^L+Dj_>{%J@fN7dcN z-;9i$my#-i;0O{`M1kW6<|bR?g-bidI@`bq2<4}->xO1pJ{f6)T~IhZhF;#wmf%ue zn^KO@7a67qI9iZ6In3v(pVF94i?zps`=pNo#U_iR9(|cxgC2$SAbN_oVoH#fGD7 z0{^fH5roVMYgR5~N5p^w8@=rF*m$N9=*nc#WDJi!`hH3wNKU~4bL>-Z8X~aKPNF;P zgH)r_qLIGO6WeDo$*_3h(sk$>Y2 zN_8~$Z-0=c*qdK#zQ-fomT?@o5N93x7vw_AG*^2xelZjU`d)kVSTNvmuGO&QL}KoXtQNBG|7${$XeG6Od%*5x z;LDSHawQeR69u@oK{*0|0)**EGw3`Lld;(z z-J$pM{gp`XB6>?cv8T9_B-XPpHboK->IFH0&3_2L1Tzj|Zpd0u_*>D}$8V^*+{ZLO zTrqYmNnOltz3XAR1RmnocUlumxGGaWu4UKOqq%bleht4Aptmnb?kxEhqn*kihQs~U zNRGlm=|tsxMAeq{AA#KyYBY$#(WsfZ8a|8|8!8kn?tnv2FX?}WWI~=;sw}p zT}apJ1L>kUk=!UXi%^c_=`g^CM=EyeZ4OfAui)>ciDuNF+~>=xCN4S9KGZ(sH>9Ep zg)XhQXNzz2_hK?cDVU|l6vEqOy4>kM0M4ywGPlJ?Gi)dF3N>hPY97{s@RouXXVu3n zPCVf>4D+@*scUZtY)1Ek!3A|?ZcsF~N>F1_5Cw=%tC)AuPr8$GVZ%gv_TB0sFQvswN}=H|FX z-j3{Ft@6Hi%DQ*osv0ChE5F4OfQKo_3SVbimaQun9mtoFVMNwd>nM_LhaROSwsLM^ zE4D4KNxQEAwBcXy(BR%B}->W(dY`Fp@Zbkh|mYQ0IdDshNh>ku5qviC= zAngPX7CBda%>jcue;PA39Gu{ESsgx-K$|MG_PNQ4$Lx?~BS~8A-|a0B8EZqCZ&KaN zvprK?VL6IgIWGuL(_ARr@3a$7>vo_(@!&SA%eZ4D)OoeJ7-y6?>W~EH`TOsU!!Nv> z@Bdyd2@c=rORULCaC)E2A1xVH-k(?yM5eRfk_&Hu_u5xXqoD%lCoiuS$hPIRKXa2ui(vzc_mn>*Acly}PH0u40G(M)9{#b}C{-aSD z=xS$B!Cl^lh>==1n;?9}9;b0&n3cGK1uIKYm(k~DC5$_Gp?W~5ahuNFLMbW!ftMyg zEOZmQJXk7QcGp7s!~ms2GMr?VT>^!Jp|19xruhLLwjk2%Z_cMtE zTs?l7z+{CD40PCSWVsKqLBDu-HU^5myH~q%G4YBuWY(&%b?1uTe4cAy%a&bhzZo;K zHua#JBOf|nYRpJ%q+!5|h|rrcOB6TKjBSv}waiNCz()r&gRDM#*Qzy+{3Cx0^6IMy zJiq0hjxykJsS3JeA;YZCa}pv3rG)+Fii~c;t;Go&Tf)mAh1-GpINE4=t+2j~w2;*< zj-`S;Bk1-%{L;MjVW5N{*nv_Y)d09=ccJ(=AaME^CWi0h%g!q?1(Ux_E)q2*niomGkg}@ zE8`rvVIHou5<@6gG1wB;9}pVDJFO|QtUdXL83sAv!-R(+i#tzoUU%`>QD zWxZa)h$9fXUbyktp{$0D7GdZ9^L&jb6cZI@({%PNe1i7AO3EXx#zKJA;^J_O-kOHr zUeAf#GSQulELws%irh5^SMGWJmzLO=3qcz!N&A6J$|K~nO4If(l674uItXOjVFy(z zE33#KMV+cKgEl))>7V1JrdaqkU`&+N05jMhrpjaIQ1jZ?3BKm&pTN}|aj6qz{T?O@ zT8w|Ji>5`948PW*vWBw|*^nq*s6u>7^Uv@2Q&}Eill2eOsOu74@MguS0-v>q%a54&H6X z8}5qJB47WygQbB+oUolvk&S1}CIR=Sz?Gb#UdN3q?2b@6YfSp1dJ@AQp^fmac_)|H zeNWZn-AXxU4UJv#L|Ek{V?Gb&xoLQ&%nf`_nr^at0XWLlUccyRBE5U+U}Tdc1J?z; z7{J`6ApjHmgZ3OoqTt(K`$MYDgM>d~0$F4ughkTFl2?)j3)0m!?Po-Z^gyx|3*=I# z!=0KjBW|L#-HEIl#K?`2$QcA30+hmw0qRE=V@R@Pl@nQsCqCR&nq^=P6RT$bCs*`V zi9U#~G!yq-`FD+!O^?6X)A>&*(KVPVz7aYxA5bSARJ}0VG^?zhH;)I%nYWL{(*aUB zJaK!R9YO27wVFLg`g`a_RPj2lcDpQaUFzKz*IT9@+rT^B9hd(F48UNGi9TFD20jz;9$f?IxlV{CL$|v}d-dj}jv$C_S8$%#EzK^i=Zs#u?9Ox-Jm>=j8t`rdDA1~^fIK!h zB=UA*zPF4qVTE|%Dyg2E0N@PaY;-Bz@jf*&V`H5i&(lz;1;A%{1yUOkWVXNarRL}ElwmEwr4y4jSC(8vw zO=b|~Sl#HLzMZ29+#cJX_Vgls#@d#XZZ3E^m7az3%>-mtE>FTr8y99~r8UQt$tLk- zmx*L79Zq5mus~?9eIT;++(+#|%o-gHeSUUUxnX6R?f^d!U(OG!fM7y9?Hj0}%wt+R z7gN>5vRdVwJS5$g)$M7Tl9TnPkJ<>>q&cvyE|WN2AnP#LZD?D~j0?R$=3m|uM^FDv zIR(cR{&|MS>@7ZYjrL+zc%`{0X`i@X*M8sQ5#IT!8wQ*vQ1GG6gYyKhIjGKgUW1bvv@A3Q)j|`kh0398WCgJ8E7|bs(_dHDU?HnYW9-ppfSF# zx+3c`LPyWwE8)Kev!o}TFGu1pg96RZC7%*ofAf8mgmz^siTP990`t%gVDTF6m`zqJ zP0RFLUU|z57E`4~Jk?$^MWIxtHT!@Hp#zyk+*6!Rp&o50+-8K9hIswzcrZ}h=l6S@ zo%D%y+j1Yp{VhhXS!M2DGOqDqX}F}nCEA|h8tr>`xL?ZfqV6E_dAR1N-;>hC8fBxW z*cc3h=;AB0w~MdVhPZxg?N)DTBBLi~(g*uW1FcBJUdrjY&yptsLq!vMaFp%WUYx z{O;Bk2oub_eRU-LTUl^4DxhtN*)$2_cJw}0TTbWX1G663G9%a4iyZ)?2qFG>4+Ge| zDwIgkel(R}Zxu?TWEP8s1Dk*FBlF-XE0KKm)w`h3^^2|5Mkk7g(54`0?&PSKc$~cy zpGBj3Tg``d<4<~e1_UqU-i%)V&4tMF7CWe4AY5(WjFZ?Xam9m`k9>amh^=#y{5tOp z-yu(CIBe1%JJ#Gqu}WdpPcQ`fVH4J=U+dmff=Ywi^VCy+SwGUp{%jAbktsOZ8)}!y>fp6KArBeLl{r%WL|Yam{r6kFh%k>(Z#wjgS_TJZi~* zA(o7&4kbZyPppJp87i@~dY;c}tJ_w_D(S;B+t-%!jW(B*Q{`B32t4d`+qWPPWzaV@ z(%JI*H|ryzdoW=$XGd4BYJM_D#ax7(jqi8!f)75SF8TS&9&iv;yuiY!>qH!%JhDc1 zKIVd}S^6lDbGQHkO_qE+0asuP8Mg2L{rWx4J}}j7XgTEdJIle(uR91xjE1mdXHe(S z2ZMv~e=E>+_`ZgMf13YusI40>{9efy_}od||6iH}RBQv<^IQHcq~8;H5F6|6=P!vM z!K%WBVh%U6kTXqctz6BTn}dP!4cb(Y_=V2QqB1MI;JeaLZ$vB8yzY7{0E%$T&e=Kz z7j%a_6kLw#B3-4wwZ)yicZP9@m39-qEXG99yLR&%ue`>OSlTAzf)o^=`U=&iKh zx+SItBn)Ln@&BloZtEhbFqfaJF>OF~F3->=`p~Nmvb;WybDe6fsbH74v0(wBLC}#y z0R{RM>KgM>?$Z}Es%?_Of@xvuc_SDlz5S1ABdCM3N5RqEoduQ4fESrowP$lDF@vnHpZ0)Br zDbjfNFAieuM4(GpiDlj}V)6N#CcE1(PoST?h>X(@2#Vis&rRT6CRp~=Hz>P&<$~|FmE@GhaM|J&zeX5 z4SD#7Z-0&u7|iHfC8v+|BEE5oZ#R*8Gubk+mj5os?=8uqblPORKTEQ+y4^e{G15bK zW9(yJle%+B8>(lRoPf1f`hb%%A9AIp?4-*bcO{jl}2F`$FA6;f$+gAYxvK6*9j z9dDz66&EUZWOZ|)B+p4^>vXsC3+< zq$c_{8T67}m;Yp(#2(}h0>++Y6}r&LV2i2@UZ`-PJFg4P^d-w$Tzy}oRx zwl1owGhMU=5}?-SAHRV+5Fsh#Re|;rCgl9R^B>^1P~(R>>G%}R!vvZd!r)E(cUh;`&e@#s z_u9BN=#W=xs~lF}53bL1 zbPYgaiX*iq)#j*==68Mr4#$axM=~HZW#*2lXLKDO4{*hY_7EP2eV6`SO_UCH^|a3( zeJxL~UMCo6T&Od8>LXrDe{WMdXzuG1dv@|jwx##?PFrR}wRn$^5oAT-L@W3a1c`JRn*T|_MrNr{j0;E z#9YL;YpHVs*C{5@C$#;0EUvGQZm58NFW~_vKlZ`%QDSz+d8nrRosySv zb}T|ZtsckT=bK$sf_4^x14!u>*ZSjI&6n6vpkz~QpPaaXj7&_NgsFb@O2k~~`*argP#UhA3Zf4X6{YAO{@;Co5 zpG6in;I75uu8ew@{GVc(IVr4Q#CUf{wr&Iq1Q+NR%n(u0D)_asrgubif|W&lI>KkqCZTg1E_wlCbG5aUfiLz@*! z0Q9cHt@lGC@1LZm&@VVuwynmLG*L*}8RsZ;g>U!5KVEnCuDT|g%oh@kt2O(+RfpcO`Dk_lGmH#$D~|b==hyqsL7+|vWt>S8`69B? zI|cW!SK=3l&4j0PAOcf6!>qI*0`zBZiMc~a0@2S}dz4Ru=aAC$YPjoC-OOBVG8i;J zdVFbW`#4x?i(#E&q5a`UqZL;3SIf$TWJDXu|pk_ z^`EIfSMHbM3W1rUTHETUiXYhGb}Q+LA|B60$qES-`LO!Dfu4Z|O0b!);XQrP{A{0i z5+%jA8PeI337uQtQZWeCK`h5=uADzZ`%gw3t~K=pfdTf6$PZjUd@lfbkL+a9`pK7rxgl-1oZ6fYRT zb^pE?%cBeqvOH1*y*7GQZ*!Xc43#mz=oNGmGbe%rf@bU?%(-4#1XOqaR**S+9rWd^ zqeyC&vY~~N%Y23Z(;tB8E8;-e za3g;%7T}7xD`7DF(?ziPSigG0bS*9&9I8SFdhz75T|%XM;N@GgB?XNiI2UT=_)-l1Yx(hFd~d-IM~Li`6K7HV|WgSSQyZ z;o;^^NJ?rpbsKV8OncDlvY6ae5~&_qbR3JTG$9<0ttt4J6$8DbQ@%QlZ@6@StdUh1 zTvZ1WUjZ7cOJf*-grjvqgA50Cx7_?b9eRSC3;whi93kf(#7E_v~LrKXv!$fdR?L{rx}C5@x>y?rO*l41U+? zixKkwfs_vCa(%|lm18=$Q@yGut2@Y%-&3|gnvezQp0 ze|Pkg8vRS;nN-9x24|DR87B&WsVGhRUQnzjmu6j~UCTS~`c+yITPnqC4zOX%z6M$Z z=;QVMl6uK6O@Xn$ou`k(J?X&O>^Tt4KKju0{9zLvw38R=)Xc`u87Z`7EbNiGCU1T% z!|l)>TjyjE#KIo^`BPZW}RkUAh@+o zoD!S-ynU?g)Eo7Mqgp_8uHdszR^7FRYyxS1w_bIgTIof7Cs8zTiVJL|y`g*3r>4|c zxob|b=Bun`s#AgMeM!mt$kXug9kPsc+bLzgsV8C|o>gA_xEmUAJXzHegqpyWvom&S zu*v*~^kd%J{YAyi;7HdLf6JO_0phRFDkI@<9EPDxQ_DHzSRF+NWa>x-mbv2Ayn+-I#Rm6AmNq zXr&#Ly%b+Lm)1-DQL2yr#_qf*6|q9*>O9bK^AC*5#dAbTrbXInz7(`;y78Y{wbP zSMd90`qwU0yGA!QB5oNams5 zTX_g=5L)>*Ouqfh;(oCuivxy+Y&^%adHuTAlLn?-puK-^U~FO0J@n#TQDR>*6bhy5%3UK*sWa3ud~fexG@{o;P;+%tQN<&95tI1*`w7^HP4>kRwdW zme`N7MgL`piD-Dcx>nbnv2ludk1bHw-YtwjyibR5uwk`|VheA=xOsW6uCH5Kkoozq zC~o_Qw23C)h` z&$ku)rLo>n)$x6c8JRi2|08rcn`5>67*M&@E`2pCrmWZZ=sxA>yw`v0Iv%! z=b&VCUsS7XmI8=8^l^=cF^itVTBSIzw43s!)}MQ=ilJAPY~e5|=l5M7A(^x&Cq{uz zI$krKc?cBrDdF#gfy4!C_!}+h`FVA+oiEsX^;&M_v`{hJ3fx>YwjUn}#vjY5KN?RR-)Q``i2u7lWlh;IF3t zb=jNIE%DS{z$9Ic%3w1@b8=+i=tt zq_NrJ$-1SJvBWIxImrtKM>T=W2T)rp8V8>TLT#nei1X+7p8}FON#hmA>J1GI3zgn&e4L9NDRWttx$z}GdYvGYm2lMV=}8AlNKVci z+cm`#MsGH&eoZg@xJm3{j*~W1T+FiI3&eap0_M#)Me$MC`)^SCE#G#YUZeq^%*oXFDWUZO?vmQJ&KXBMxj-PtXE+X_+w?kQ3EEOo;LX4bm% znO*GjiV}r8op)nLWx~0uWGo-P5xKE3er?MwIaYuBvOX%K4>xjnSK|2WPx@#K`$wxS zaZTRzD|~_}-SV*KR2MGI>J3Z#XFhm1=iq+vj;=49+qT3qM{!310Wzia^@~5Xzf{Ge zsAo8yf+ixZj2WYqzmzu^gpEl@eMOekS9psRC7g0Au`0yj-|wObBsA=hD^}wY>#B4_ zK4T1wUc2;yx$7(?QdexhJIyVtG%Sf`nwhxLCBMc0YVZG-T4{0WVsWaIQ|)Z@(S1~> zue|yQ1pC(N?M!BEgUr9mANaT}a`H)wyOAVKA_hXJQr`PGvze4Hh4FTQW z9{gkc7>WbW9XAaDJ-d#|=!D{j1PmgN(#EGasIz=ZeV$*~Eg`=&7$ zzj?W8#oZTn<}Z=FzmZKhRd@UD73;(?F|+2vv>QA1`zqW|ELIpkGsJ$@3b>K&9~iP+ zSagxpU?rbwAX0gf&kFkV6C7_^KrQWP0TO1BzANlF}bL&unchb%geWF0nsw>0rDmxUzc&EPWdw^{llo&ZPEfh)Z12l z5%Har6C%1+lJ|@3y}*}`eHE%ib^UUN&~$0&h>_A{_NHR+$VZ|e?uO0NW#22eCP$T& zBR!*a&4G(+XmGQ8B_P^r(1|xv;UuwJpWI~iXF&_z7qUEomGKq4=qI`yd|ZHK?{#C(A>|rx%fB9>E&EF^n+?K&DYpsd*J2_>e6+T zPsWc{@tXDF?kv(k=V(?Xvza5^_T7~83MhCbEC9W-g@es;7pQPscwckT7} z_wW66*@;+)#K+>~b30U+(+LSpGRL;gkj+MuCe;cg5vYsd40((Q*;p&%EI~$Qz<;BB zAnKgU>iV}t+$#4p1+LI~8MSwTCEbj(k)1iUX1^<^fQKD9TQyI2qxhjIC&tY1-GWZA zEY<0ySc230x&*5w6XNoX*Q-+Di`GA5gW&Klc-}MilGb%*^E!*&-_ghTTcV<6_Wku9 zjEs!x#(bykov(!2J`(&ZoKQk*(*>Eiy5$kvjhnZHL=0ugE`XW@VxsD#v6@}X};pZidmDJC!cj(Y8o3=eXXhy3;%A% zQH#Pm_BG7NUvwLlg9>9*XaO~@!C_^^!u#sPptYm5A|Q{z$Y3QJ;@%){O=MS~V__O){wg3) z{ogr|RGUuF)`o#OufFl1CQvQ?o@owbg07D(it;l3EG{7D+6B8Cv1ug1Nhg$Kh&p{ZVu}$i%9Rml2IFG-SzFgu5jC5kbuc@KJ4lT{1cp9 zu`9#Pz~r?pU&ER7$zNNR?wbOtB1Teqp{%ny@li2I8uBl6TG#`P>0{2^3F%|ruCHPq zMSuO_l0ga=7l2+2s_qiD{E4NJN{=Z>VV7Y>h-9WLs3;%{dR?cV@8lU*^?8iA$T-$1 zQw$GXbfXJ(F4!2L7JU?})GfAGEx777n+M8DqStC(j@c>2pldj`XSty{jeg~r8mgcW$za5tadQ)} zLDXe&>erFe65N=fATf`X6OV~JB5=ndngS9F^Q=DZ@4tz*N>D1&EUjcaX8w)r>Kt*L zsTXYP4HR#=*b8JXpC>(n1$S9g8#>D(CWkBlG5AnZYs=FaF6tpHQNPr4PlL>Xnc0>tPvOZ=7ARY!V zO0?2IpE6eC8zH!-Sw4j_ZsB3>5$ELEuaVZWL^6C-XYE*{qoLuR^z#v;VNETElFJ%$ z67&?;{`b#CSk8339Fl3dmgl@<{ZwHPH!^h_k2f<9C3*9#d*o-J7Vf1mrW$igh5lNa zD#rj4*k4m+bkl&S;;mS$RLZ+YFbEa#vaR{Xd@1HL^NTU_S{%JdDY^Pj0^l(LdUbyX z?Mqd*dsrs{zVq*pObNV8AzlK;heAF#}dnoZU<}8}Z9Q)GwhGT8mGl2mvs19dP#wZ|Azs*Nvaji?7?UgxOJWai`aUx)$Vl>!O8nSXB?TZd0e`F=!<>DV z?E2J8=q5g&-?36hM9G?QMndRPqW4EGufW(PwrezL+2Dt%Z93SjXvyA}#Tk&NwKZb| zCEojQ&D)pbh|0(k_IG57mEWzLoYf;dfDE*`8$cUS!^P3DbkZ3pK?5ueWKLzGjWuMX z-RMxJ7}tMP=xaedJpm@VmXZ|ca^9h%-L$BMM_v}%^UceN9%p?`CrU$^`5 zN^ffsq3GpJN8ZeLi8MHGv8<}7r~r`CV>_s6Xe5xHZ|`NfDryZe2-A`$Yo${>s5dR2 zY_fbUyRk3p0iS2ZTn-*XO> zVSQgxFZh>A#N&J;exQ_xubmF*-yC?p8WQ(ukh%Ac>^74Sw1Day@*) zi0sk`@Lq~~qk2(Gu{_}38e(bi+mI&)K^M(m5pf2_ElTt3iv7qKwkMTwGlJ=o4xB zgeVgi7$Ne>PDF$NU{5hzkzj)l&)sbDwIvgP@feWP0HVVciUxCraM84TI^T#(3EI>d z6H7jQ`eyT_f9;S}Ey1*M>dvtFN}D^fhxKr3U~Fc1g#wwy;9g!dij@vB zvZ`1P;Fnl=O#qFj%FU5^zsS=HerA+vtY*$E)b-W} z80tQH-y4;0iJu4Gyx)w{1Y-6N{SQb&Vu83ML=J?iuZnzEOp<`~mo@-G1kKYHl=uSk z4a?g%M`V7O@3f~4HWg5)R3i&(oDP%ToT##-H@nz?KE-VawpdzWbUJ{l{yCvHfSn66 z+Ot^#bsVKevK#(0NN>6qEW2~d>lc# zXQ(8Oi!}v>cFfWXq>&^eWB-&+BT)9WpC5}qeHxf6?lN%k+%MtVk@EKwKk;?^<dSv8auLafAfsD-}CtU#9O@dVDRf5#s+f3<(DJe=k2|8=C!JOgS4o9Wc)okhP zUzjSVED>!g4lc29q1UZh&pdB_qKz3bY^qSSJBaw?*Bm;!=|5;s5hVnXrB1w?8hN9N zF{kQTH=$zle4Ba6{93@JTiJs!JPGF48!%YrTT;P$s&FXSY<4i+odECKiRLeelN+B(O;rfQokOAKV5<0ysp=>p_*sG?%)v+~I6aVPM(R4T-uxfBr0Y zMJGNKS~=bv&kw_1tnq5)$p#&+4rEJsVE+^(-dvJxDzjX2wHP7dG7{&Z$BM<66QL4W(;trSL z<#k#99{Fk{&uw7+Cf+xr{q4Gu^|dv(x%#pyDqA}{8Q(u-jEsv(0hEIDo+1bWCS9`R zH`#`Yir=?q>+%CvVkagh`uqFMr)kAqP2Jsh!*ARIitaQ0TEBt!RFfQ^SxD%hVcMFI zlr$eeQ>61~P0q+T8{o_*VvwE)YpAZSW>$*Ik@Df-=dX-3zmJEg-nF;~`%?)0>X!KYLy~wY6 z`0i=NP4_#0v9fGsWo6nL%FoQa48V$4`9+qNmY$!Vk0{`-*D^plIywS;d_L!hdHTE?7N(mrN3H*FVZDDu#X^Oi;xzDulMqy2?Y2OH~VKpV)k> zvO?Tkkj2Aue0GJF$73XhU|CV zVNX^Emf-?$dolr4o=4#1J9tg{R1Y4sp0C8oL5`bFrYuYL+nMGT z;gn~i`*y1)G-n1kDu%ySe+q{uy-3Ga! zb^wEcS)K-)a=a==e1M6`>FJFCDVyUZl=?4TjD6rXxI_HtLrzXkM#l7*Hehvlw4#nl z53>UI+Rj|Xvps_B?N(GBhkSwkQu zm%N{mrKG0H_-)nuq5q0JVocrv4kS7RH)2M9`$sb~G$= z>n@2Q*MsEbusF}`39%qBFtO9g|LO)+Vq{0|oteqW<&IhdM)2GM${5yc3;-7Q?6rm83 z#}NbM9<#LmTA`i}1`B6(EeGN-XMkrMuXVeF7rtIJjn3e=INd6TVXu!yR11Xo_*@rT zg8&@$WyxVUN!JssQf{!|gRpAz$`w+71WH2Jwl|&@a7lnX7kx(LOaONUygny~zA!10 zjw*uEGZkRbL!?ER=?w`e#X zp6460Hb{dtOjk?G{$X)_y)V$uVu6fMttp>~!_YqHg_+qV@~#Y^DDZi=x>;&IQ=1yo zVDwO?5YSyP=1TjeAlHDBT_Xbn1m7C*EMN5|FwBo><2i<|l$wUqX~pH#cx8ptQ3z0a zDt!mv{M7tQ_=W_VB~Uq<@UKIcBClL0a^5a>nd9M6Uu!5oGsOF+g@=F5D*Lod)(!Zy zgbGlH{I~oVBtG6ZKl}`!LUid}0U++uOZ*1n_~(}Y-~T;Q_wTDXVkcDXzjcw7q9e#q zUy)ZzwE9XsZ#x0UIFctLT)OVfaazWo?xqWWY5qlja$@p(3m3<=qx7k<#K5HMc!Sm$ zwi9+nL(5yS{$oV@dV6SgB&vVQT52`#wv^f;nwQw}XzRPOj@c^>Aic}3G1w8XUI}3< zjs?lh{t`Sq?5OZ4fF&r*y5a)1F4y&s-d$1s_{sG*ADYZ((%qkm*s(wq5Ipmcms1QU zr&T;2A-~$vXoDbeKfcN!F2=7?UAnEzB0xeaq2HQfsU*ii?bV9I_8YU)D6Qi(9foDz{DlrqfYX;)Q1fK^rEY_Y~He z$SX>40^@cYfAzGxeL9*ws@(SOb&2c3*%5YXw^nZ19H(5rO|dqka%sL~P;Kvaj&XDg zLnu<-EZ(KI1{2Q>5K{_m73p#o-LYLEpPHM2ZW2F3sSZ4sL~u0R1goB0TmTDdUqMVh zTaj%yci?JAawp1AYjRCDM}h>G1DTH(nIelOf zUB}jTK#~J6&8GCqR9}eGQghIVEUxRdW#z1GQ`1o$!A=iNwa}YlLHVRt)lz&P>*APV z?PA%ySeL9rS_>^<{F3$COOsblO1*qM$gGf(_!xEZ{W{A;r%9z{Wo6fr43f+#o!Im% z^U{ZP>TR1leF_VnEvBHC#!MiwN{@$109%fsFE5fQQq4etzH2xX{cY`6 z6L$(eZ*MmWG9t7!w2nXctq++Puqi8l_0k-aQvs10kdbR#jYz|=p~p3pQ=JAcKo_7pqIH+1b4c#4K-r5pL6m`gb9mMl%+*+ctAKw_N%QJH|d25H=7CG${3b`1#xbpTZzK@zc*;}Fng}{v0l>zPXStsA>JRKR7);r!F7{i2Y&& zvvk;Xd(FW>zxR9J6;YtShHBN6;b-Kf9|WgYT;&jkT|kKWyY6hX+7FgQ{x%XvuQ7KR<3xTA6vzMhg^Kdkhi*Mpz+bw;!AoIxR5fGuPXa>{rCb~Y zxyi{X7wyiI5yk6>mT{V zg@qMExsXw3VSAsj-*~OqLd7^)I4}-_!6nft%&Ma;F3u?_F|mv%Slzh1U1N(~4!~V{ zkARpfQ<+pcNOj9Iv`h2ERZ|X~i~V+flVgz)W9o~}I@+ez?74ekWlQzy^>X8dv*i*+?^V+~np9{dSto#TvP51L=jXY^_6 z`AFFrFf3hwx>yf)qA^x~{7xGe1CCKt#le299#r_`lO&OANOz=s z#(`}c-1j^ z$%5sDdHIc>kCkFQwuOW4chIx2HtrOHCT8Q9b{}@DTO?jy#=D~^cV^~DR6D{9zf+>? zY1(lv-cOX?y{!S|PV5F_sbe1odP*gXw96Q)9(E5Xl;t*7L{d^vbvL$LA?v0pb^C<; z#1WSXm1xJ0>F(|OC`{~qTO|+Zr9=aq0vHMXr&YN%4CN&GHiy|}+^So`^7n1|Wf2NK zFuTpdvN3!C+Mb4Lln$9A#NbvXYy{-VdS2d8NL3o^Vzmd7Sun`b+G(>+&B*=S#L8CyZc*}^FnMWFW_0O=z3Y~Ey@T~OI^u* zSLKLM4aJkA7a~GOg9QF#(5t#r)GyEtxkvDjGNF*(=&kPO*FH_H|6JR zN!yXN`>Uh77w5l;-8gl3Im>-8kcme077JS8VpNXe{Rp@hAqTxsi<=C1uX!axMO$dqw>Td_Bxva&1w}6yV1~QhEbFqg@*&ypTYF%!ViiYY2mDV-o%c@a_HE5!l z0}hI{``VhzJIqX0Sr)4Ue!m`kOL9P*`@#S{%H}5GZ3z=0l(#eh&OsbTY04)vrGa7i z|7xD^%lReA$2sO+SlU)DCJ$NowR}xbA4b;jX)1R&GM;Z|bQCd32XnF7?QIKv=Ie?< z6}DDs1(dzf+lK_DgVC15s=W~d|5robpe6x`=-<`$;DVBZY87w6Y(h0c-nenS*|O0Gl^-7n5a?fM6E2G(8bN=gwukox?Dq6`XR6)1j4>#?%dZe(I-9v>IYh7j z!KJX9Q9+w^LRvLZO{ML3zn-Fu71@YqmE_~n8s_j=9zlJRo-j#2uPhdE@py#}J2?1T zwe{zK1sTf@aMv8MOj^ON20@2N<@AM{j9-QdQ&n|pw!Ryva(`y(u+|o2(txNhY&CKv zvY5U+X%FE?R0)iUd)4TZ3Jgy>iavVJ5wNIkTxDpKy-B|4Ggx6HBTULP*gu0qt>VY- zH3>N)dr)kiInxfpRy_8@Ua}Z3GTK36BT!E53u4O2uLPY0#aryIhFbP2UK(pfVY!+H z4i93~Dd=eEe6Q%Bnn3nV)u06v$p&K){ZO`N^P#)mO?xY)_G_CnH+PLHy!k=ZDzX8B z9gFg6opr35yP05Ts&Q)`bOmS*6(#!zY7+*roYS$IyZ_M`ylH{WwYWf~W}ynToD^nw zn28U+pLbUO-464k`x2Pl&q#r}+dUzgny)6{5C&vWo$)J~BPa8vv$|_2j6D~7o;3~* z#T}mSEonTu>f9>Q_Y9eHhxCm z%`?B;i^~CdM#CS*FU~ZXraup2v1MiHA^CmTSd|{~a)K_aac8df18A~sFwMm`y#cp# z+`ly_ZSLo_A%IEk+U_G;Wo6RGG%)r`s(g)Q)IAUTt-w|t_ zt7_8X_e(|hjWv8!`^s#wy74qb zmymbO$J&qqfgA+`Lxo&O(>H-6md)4EcgsIc z+?h{c?})--Fkz?flgWji30YkhDqjRB-(^4BP5tzNOlqQ}?)idnWPGM^*OFPwuRXX} zVKqM8oVZktQNt#6%K26MqA+Y;H&IR;M-MYBGkjjOa@Z|Q#G7pG?UX5-f$-iOkSPhi z4$O})>X_)~HOy-F57;gclpEvDWLEhOvJSlVH+$1q^{CzV_Xw>O_9S2Jg`!!Cs_)jE z^*}DhX*TOK>_?M?*#L!x;{2J8c4_v`d;3t`n;P9NlQP}xl4R@h6eYsI?ScG z{01U=A$rPvy;m1!lK3RbzVfa%)Vn%!dnvWqHOn8^KDS8A&n~`l8rCMI(E^zjkV*di ztuemvZpnLZ4@>BjW&(!pluZG^$JvdJqd3%OHd{)jbNkut=(##9 zA?|VJ$(`l&Je1K&U|5i$qIYnh6==|TTPF0}?DP+vu0N@r#?)n%i8XDdS@TMNzV;ns z-i&8^j!OklHYK9pKTNR&Yp(;W86Gipld;BaPrxncaID(YDCwc#U3LH4x??jhDb>Vk z^_uE`cL~ZaaKC*C>aJIWd*Cn6{K=obeM$U5yToM&NEc2&1@9Nt(7F2Wdi$V~{n1?2K40E^l?KLq(aVo>m?map4Q{#HLvx3bFlVV~=QXl#4K@94W?;t1?&N(YJu_PeJQG8s>b zCrxRrlw2ru2X)pTES$VA zN%9=mNM*LOz6~llF&0|55M&HJ&X|#Cq{-x?#$5P`^fkh2W~+wW?#?Yxx1rB4BrJ#Y zsA|@F&6VUzC_2+wKh+P(OQ}#57;KPScD+*kieHl^pXLowRoC7U?)WwKNY^nwicsOb zV6fdnoCTkPX8hkiOTB0NDwUANvnXmSUBsxZbQ z5qdn8jA&Qzy4LI6y-*^>HKC?TrRaBWx#$pE1e?3?%wK)69WBrmp zyQ7a52=z&9b?rgJavx#srm~cv0Rll>8yox?!tiEN%vmzc$U>X!yd&4#S?GiyA!%St z%y|kpEPuafV*n)hkdNAKad?Dt@sTCE^Uqn(7L_gvSG0dUb@NS`FD_nOK^L-$<{0w& zI_0X;z<`{Bhp3XnN@SZ+pmi+hiHzI%G|LZjV17O>-*<;wT;FiY{nw?xcn-lnist_e*Z!Jy1Br7M`T-S}{?o#r z?*I2iP45Io*5B6un=_tNR(U@L&Tjn|1Ju#~rr}3%o~zD(9fJKIhxmWvZiJcN2TQ%4 RFZhcH4HX^bDn*-!{{g_|pojnf literal 0 HcmV?d00001 diff --git a/docs/images/long-recording-overview.png b/docs/images/long-recording-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..cfd729bf71ad5a30f68f39e77f5228398c9cc710 GIT binary patch literal 123786 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
g#`$IT`j_dPomW6G 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 z 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 JCeNEs{|ot@^T+@I literal 0 HcmV?d00001 diff --git a/docs/long-recordings.md b/docs/long-recordings.md index abff49b5e..03596d771 100644 --- a/docs/long-recordings.md +++ b/docs/long-recordings.md @@ -13,6 +13,27 @@ dataset metadata. Duration describes exposure; Phy cannot infer acquisition gaps from periods with no spikes. Intervals use half-open sample coordinates `[start, end)`. +The screenshots below show the actual bounded GUI views using a deterministic +synthetic eight-hour sorting. The overview plots full-duration rates and +available source means; gray marks the synthetic acquisition gap and cyan marks +the inspected evidence window. The evidence view places windowed amplitudes at +top left, sampled ISI at top right, sampled correlograms at middle right, and +features below. They illustrate the interface and its sampling context; they +are not biological data or scientific examples. + +![Full-duration Unit Stability with a synthetic acquisition gap](images/long-recording-overview.png) + +![Windowed source amplitudes, features, sampled ISI and correlogram](images/long-recording-evidence.png) + +Recreate these images from source with Qt's X11 platform and software OpenGL +(the script writes a temporary synthetic source and bounded package): + +```bash +QT_QPA_PLATFORM=xcb LIBGL_ALWAYS_SOFTWARE=1 \ + xvfb-run -a -s '-screen 0 2400x1600x24 +extension GLX' \ + uv run python tools/capture_long_recording_views.py +``` + ## Prepare bounded evidence Run `prepare-large` with the source `params.py` and a new output directory: diff --git a/tools/capture_long_recording_views.py b/tools/capture_long_recording_views.py new file mode 100644 index 000000000..1c40089c8 --- /dev/null +++ b/tools/capture_long_recording_views.py @@ -0,0 +1,254 @@ +"""Capture reproducible screenshots of the bounded-evidence Qt views. + +The script builds a temporary synthetic Phy sorting, prepares it with the real +long-recording workflow, opens the real GUI, and saves two screenshots. It does +not download or modify a recording. + +Run with a display, or under a virtual X server:: + + QT_QPA_PLATFORM=xcb LIBGL_ALWAYS_SOFTWARE=1 \ + xvfb-run -a -s '-screen 0 2400x1600x24 +extension GLX' \ + uv run python tools/capture_long_recording_views.py +""" + +import argparse +import sys +import tempfile +from pathlib import Path + +import numpy as np +from PyQt5.QtTest import QTest + +from phy.apps.large_recording.prepare import prepare_large +from phy.apps.template.gui import TemplateController +from phy.gui.qt import QApplication, Qt + +REPOSITORY = Path(__file__).resolve().parents[1] +DEFAULT_OUTPUT = REPOSITORY / 'docs' / 'images' +SAMPLE_RATE = 30_000 +HOURS = 8 +CLUSTER_IDS = np.array([0, 2, 7, 99], dtype=np.int32) + + +def _make_source(path): + """Write a varied but deterministic synthetic source sorting.""" + path.mkdir(parents=True) + rng = np.random.default_rng(20261013) + samples = SAMPLE_RATE * 3600 * HOURS + intervals = np.array( + [[0, 3 * 3600 * SAMPLE_RATE], [int(3.5 * 3600 * SAMPLE_RATE), samples]], + dtype=np.int64, + ) + valid = intervals[:, 1] - intervals[:, 0] + cumulative = np.cumsum(valid) + offsets = rng.integers(0, cumulative[-1], size=120_000, dtype=np.int64) + interval_index = np.searchsorted(cumulative, offsets, side='right') + previous = np.where(interval_index == 0, 0, cumulative[np.maximum(interval_index - 1, 0)]) + spike_times = intervals[interval_index, 0] + offsets - previous + order = np.argsort(spike_times, kind='stable') + spike_times = spike_times[order] + + unit_index = np.arange(len(spike_times), dtype=np.int64) % len(CLUSTER_IDS) + unit_index = unit_index[order] + elapsed = spike_times / SAMPLE_RATE + hour_phase = elapsed / 3600 + amplitudes = ( + 35 + + unit_index * 9 + + 5 * np.sin(hour_phase * np.pi / 3) + + 2 * hour_phase + + rng.normal(0, 2.5, len(spike_times)) + ).astype(np.float32) + depths = ( + 250 + + unit_index * 180 + + 20 * np.sin(hour_phase * np.pi / 2) + + rng.normal(0, 8, len(spike_times)) + ).astype(np.float32) + templates_for_spike = unit_index.astype(np.int32) + + np.save(path / 'spike_times.npy', spike_times.astype(np.int64)) + np.save(path / 'spike_clusters.npy', CLUSTER_IDS[unit_index]) + np.save(path / 'spike_templates.npy', templates_for_spike) + np.save(path / 'amplitudes.npy', amplitudes) + np.save(path / 'spike_depths.npy', depths) + + channel_map = np.arange(4, dtype=np.int32) + channel_positions = np.array([[0, 0], [20, 100], [0, 200], [20, 300]], dtype=np.float32) + np.save(path / 'channel_map.npy', channel_map) + np.save(path / 'channel_positions.npy', channel_positions) + + templates = np.zeros((len(CLUSTER_IDS), 40, len(channel_map)), dtype=np.float32) + time = np.arange(40, dtype=np.float32) + for unit in range(len(CLUSTER_IDS)): + center = 13 + unit * 3 + pulse = -np.exp(-0.5 * ((time - center) / 3.5) ** 2) * (35 + 8 * unit) + for channel in range(len(channel_map)): + templates[unit, :, channel] = pulse * np.exp(-0.7 * abs(channel - unit)) + np.save(path / 'templates.npy', templates) + + pc_feature_ind = np.array( + [ + [unit, (unit + 1) % len(channel_map), (unit + 2) % len(channel_map)] + for unit in range(len(CLUSTER_IDS)) + ], + dtype=np.int32, + ) + np.save(path / 'pc_feature_ind.npy', pc_feature_ind) + features = np.empty((len(spike_times), 3, 3), dtype=np.float32) + features[:, 0, :] = unit_index[:, None] * 3.5 + rng.normal(0, 0.65, (len(spike_times), 3)) + features[:, 1, :] = np.sin(hour_phase[:, None] * np.pi / 2) + rng.normal( + 0, 0.7, (len(spike_times), 3) + ) + features[:, 2, :] = np.cos(hour_phase[:, None] * np.pi / 3) + rng.normal( + 0, 0.6, (len(spike_times), 3) + ) + np.save(path / 'pc_features.npy', features) + + # Stored waveforms are a display reservoir, aligned to sorted source rows. + waveform_ids = np.arange(0, len(spike_times), 8, dtype=np.int64) + waveform_channels = np.tile( + np.arange(len(channel_map), dtype=np.int32), (len(waveform_ids), 1) + ) + waveforms = templates[unit_index[waveform_ids]].copy() + waveforms += rng.normal(0, 2.2, waveforms.shape).astype(np.float32) + stem = '_phy_spikes_subset' + np.save(path / f'{stem}.spikes.npy', waveform_ids) + np.save(path / f'{stem}.channels.npy', waveform_channels) + np.save(path / f'{stem}.waveforms.npy', waveforms) + + with (path / 'cluster_group.tsv').open('w', encoding='utf-8') as stream: + stream.write('cluster_id\tgroup\n0\tgood\n2\tgood\n7\tmua\n99\tgood\n') + (path / 'params.py').write_text( + f'sample_rate = {SAMPLE_RATE}.0\n' + f'num_samples = {samples}\n' + 'n_channels_dat = 4\n' + "dtype = 'int16'\n" + 'dat_path = None\n' + f'valid_intervals = {intervals.tolist()!r}\n', + encoding='utf-8', + ) + return path / 'params.py', intervals + + +def _wait_for_render(): + QApplication.processEvents() + QTest.qWait(1200) + QApplication.processEvents() + + +def _capture(gui, destination): + _wait_for_render() + # Phy's OpenGL canvases are native child windows. QWidget.grab() omits + # those children on some Qt/X11 combinations, so grab the rendered screen + # and crop to the application window instead. + screen = QApplication.primaryScreen() + frame = gui.frameGeometry() + pixmap = screen.grabWindow(0).copy(frame.x(), frame.y(), frame.width(), frame.height()) + if not pixmap.save(str(destination), 'PNG'): + raise OSError(f'Could not save screenshot: {destination}') + + +def _capture_views(bounded, config_dir, output_dir, stability): + views = ( + ['UnitStabilityView'] + if stability + else [ + 'EvidenceAmplitudeView', + 'FeatureView', + 'SampledISIView', + 'SampledCorrelogramView', + ] + ) + controller = TemplateController( + dir_path=bounded, + config_dir=config_dir, + plugins=[], + enable_threading=False, + ) + gui = controller.create_gui(default_views=views, do_prompt_save=False) + try: + gui.resize(2100, 1200) + gui.show() + _wait_for_render() + # Focus the captures on the plotted evidence rather than the GUI tables. + similarity = gui.get_view('SimilarityView') + if similarity is not None: + similarity.dock.hide() + cluster_table = gui.get_view('ClusterView') + if cluster_table is not None: + cluster_table.dock.hide() + if not stability: + amplitude, feature, isi, correlogram = ( + gui.get_view(name) + for name in ( + 'EvidenceAmplitudeView', + 'FeatureView', + 'SampledISIView', + 'SampledCorrelogramView', + ) + ) + gui.splitDockWidget(amplitude.dock, feature.dock, Qt.Vertical) + gui.splitDockWidget(amplitude.dock, isi.dock, Qt.Horizontal) + gui.splitDockWidget(isi.dock, correlogram.dock, Qt.Vertical) + gui.resizeDocks([amplitude.dock, isi.dock], [1000, 1000], Qt.Horizontal) + gui.resizeDocks([amplitude.dock, feature.dock], [550, 550], Qt.Vertical) + gui.resizeDocks([isi.dock, correlogram.dock], [550, 550], Qt.Vertical) + _wait_for_render() + windows = controller.evidence_windows + times = controller.model.spike_samples + counts = [ + int(np.searchsorted(times, end) - np.searchsorted(times, start)) + for start, end in windows + ] + best_window = int(np.argmax(counts)) + controller.inspect_evidence_window(best_window) + selected = [0] if stability else [0, 2] + controller.supervisor.select(selected) + controller.supervisor.block() + _wait_for_render() + if stability: + filename = 'long-recording-overview.png' + else: + filename = 'long-recording-evidence.png' + destination = output_dir / filename + _capture(gui, destination) + print( + f'{destination} ({gui.width()}x{gui.height()}, window {best_window}, ' + f'{counts[best_window]} evidence spikes)' + ) + finally: + gui.close() + controller.close() + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--output-dir', type=Path, default=DEFAULT_OUTPUT) + args = parser.parse_args() + args.output_dir.mkdir(parents=True, exist_ok=True) + app = QApplication.instance() or QApplication(sys.argv[:1]) + + with tempfile.TemporaryDirectory(prefix='phy-long-recording-screenshots-') as temporary: + root = Path(temporary) + params, intervals = _make_source(root / 'source') + bounded = prepare_large( + params, + root / 'bounded', + duration_seconds=SAMPLE_RATE * 3600 * HOURS / SAMPLE_RATE, + valid_intervals=intervals, + max_spikes=20_000, + max_bytes=268_435_456, + window_seconds=30, + stratum_seconds=3600, + seed=0, + batch_size=50_000, + bin_seconds=1800, + ) + _capture_views(bounded, root / 'config-stability', args.output_dir, stability=True) + _capture_views(bounded, root / 'config-evidence', args.output_dir, stability=False) + app.quit() + + +if __name__ == '__main__': + main() From e189567852ce71a4647f1b74dd153e0cd05e8624 Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 13:12:01 +0200 Subject: [PATCH 20/22] Release mapped readers before intentional corruption in Windows tests --- phy/apps/large_recording/tests/test_curation.py | 1 + phy/apps/large_recording/tests/test_replay.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/phy/apps/large_recording/tests/test_curation.py b/phy/apps/large_recording/tests/test_curation.py index 2aa748a6d..9997bc9cf 100644 --- a/phy/apps/large_recording/tests/test_curation.py +++ b/phy/apps/large_recording/tests/test_curation.py @@ -144,6 +144,7 @@ def test_checkpoint_corruption_is_rejected(tmp_path): def test_bound_base_corruption_is_rejected(tmp_path): _, session = make_session(tmp_path) + session.close() shutil.copyfile(session.path / 'spike_times.npy', session.path / BASE_ASSIGNMENTS) with pytest.raises(ValueError, match='integrity'): BoundedSession(session.path) diff --git a/phy/apps/large_recording/tests/test_replay.py b/phy/apps/large_recording/tests/test_replay.py index fefeb52ab..408f536fd 100644 --- a/phy/apps/large_recording/tests/test_replay.py +++ b/phy/apps/large_recording/tests/test_replay.py @@ -45,11 +45,12 @@ def test_source_revision_and_feature_identity_are_independently_bound(tmp_path): source, session = make_session(tmp_path) session.save() clusters = source.arrays['spike_clusters.npy'].copy() + amplitudes = source.arrays['amplitudes.npy'].copy() + source.close() clusters[0] = 2 np.save(source.path / 'spike_clusters.npy', clusters) with pytest.raises(ValueError, match='revision'): apply_curation(source.params_path, session.path, tmp_path / 'wrong_revision') - amplitudes = source.arrays['amplitudes.npy'].copy() amplitudes[0] += 1 np.save(source.path / 'amplitudes.npy', amplitudes) with pytest.raises(ValueError, match='identity'): @@ -132,6 +133,7 @@ def test_replay_preserves_empty_split_children_and_allocator_lineage(tmp_path): def test_bounded_threshold_attribute_must_match_exact_source_rows(tmp_path): source, session = make_session(tmp_path) session.save() + session.close() # Even a manifest that does not hash this optional attribute must not allow # evidence values different from those used by the full-data predicate. values = np.load(session.path / 'amplitudes.npy') From 94adf85227d94d19a2b295503653df1cf8414016 Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 13:12:35 +0200 Subject: [PATCH 21/22] Clarify stability screenshot marks all retained evidence windows --- docs/long-recordings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/long-recordings.md b/docs/long-recordings.md index 03596d771..454a372db 100644 --- a/docs/long-recordings.md +++ b/docs/long-recordings.md @@ -16,7 +16,7 @@ gaps from periods with no spikes. Intervals use half-open sample coordinates The screenshots below show the actual bounded GUI views using a deterministic synthetic eight-hour sorting. The overview plots full-duration rates and available source means; gray marks the synthetic acquisition gap and cyan marks -the inspected evidence window. The evidence view places windowed amplitudes at +the retained evidence windows. The evidence view places windowed amplitudes at top left, sampled ISI at top right, sampled correlograms at middle right, and features below. They illustrate the interface and its sampling context; they are not biological data or scientific examples. From 4c8e74f3627486679e87aec8302ad351d1b77516 Mon Sep 17 00:00:00 2001 From: Cyrille Rossant Date: Tue, 13 Oct 2026 14:13:46 +0200 Subject: [PATCH 22/22] Label evidence-window time axes and display absolute recording range --- docs/changelog.md | 2 ++ docs/images/long-recording-evidence.png | Bin 211062 -> 217430 bytes docs/long-recordings.md | 6 +++-- phy/apps/large_recording/adapter.py | 8 +++++++ .../tests/test_gui_lifecycle.py | 19 +++++++++++++++ phy/apps/large_recording/views.py | 22 ++++++++++++++++++ 6 files changed, 55 insertions(+), 2 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index 1fadb9629..f18f7b05f 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -22,6 +22,8 @@ behavior they verify rather than listed separately. - Bounded saves use validated atomic generations and reject conflicting saves from stale sessions. Unsupported selected-row splits are blocked. - Sparse cluster IDs no longer require dense allocations during clustering. +- Bounded amplitude plots label seconds from window start and display the + window's recording-time range above the plot. ### Documentation diff --git a/docs/images/long-recording-evidence.png b/docs/images/long-recording-evidence.png index f7649941ce5c4ed8c950553bf6f723dda51d0abc..294d03924c4f24cab645ea6c6af1ae6cd311d969 100644 GIT binary patch literal 217430 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⁣tv~5sSKs=Yd;PluV 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

|Uox@!s{G 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

d2l*AMv!)BMA2v8y~2v%Pz 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 (m*~yhpL8ZR-pAQub9E@aR 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 (; z>%ql@wP=&mnqY@WUJ<;96&L#STSPpkaS6DuL&F>b5iLs)#cRoNGV1SPNY2Vri*2P3 z%d7i)FM=0^N}C3Chy91#&w_itr-KYSLu8AL33N%}FOZA-v*2BD$67vIor2@cfKf2w zQ*6d31fj2ppzg#(YYGquQbZG@rE2!Wj}Qbh;&S`F?fy9xV!PuF&3APiXN_cSuGTNs zuMv3ZWU3_KT4_6UtUrEcY+D$}Gy#G74*#40R_D6^dk8kkQ~uY2ChD=d$wgPcjKu8d zYIhqf?y9Awt6h6j|N6?yL%P|8mzMn!j4?xjmqI@boA$F*@lzUCbl5Ki{mz_Ms5T6s zGfD9Jpw%31JDI|&2RY2qfG&I($@7tDE7)B7KPv(J^t~9gwiT#doJtyiFC^z1X22i*KrTBZY09=rG;^`HxY{`Yo0(*Sg=n)n7r# z^p6fTh%n1mpOtz8gr6@jFNQ(gNxav~>V8wbRiU@pLM>%0(Ob zT5Y%ASv>Q;Ga8pP<*B8wlK5mBbX%9JMwe8#VrPFk2rHC3X}2B^lT0@szh=?-(!RNR zn(W)=Tekdt<@I30SjS{l^IivC0oI4TvDSyt@JO?l!`WaI;pCU=RTLM6KjvANYiO%> z_huV}a37cJOymw=9&F0(kB>Qsn{#rrXdSRsIpgE7*Sd!fq^@*=g)2|H=`W|gbRgbs zND;1xUzai~c!O7ap3FF(R>_HA>xpH7rYoESaIOUQJ^71^i zOxD`5wM6?Gnm~LOE>5S=Px%`yb z6iH7g0Y^+`__C)X>HX6InFIa?xiL%g(T0)I($h%*W3*t@eBpw;i|1!z&-3L8my>GS6Y|W>!02lj1=4E)tGQah0V2Ay6 z_q&P3q3xUn5JyoV!}^Q!((F?jz8{kP(upR@>S=6lPfrLVGkomE z5nlq%f`EH~6mi!%-|Kp0(BUXe*<>&3Lbb0ro*K(yI7`b*Z-%NYgT7@a2l`T}nK~YHI$+xmo16%~q&vK(`%Wl3Yt?c6|Ks)CoT;Y4)uAO#u z{s`AM(-X5z`b-hW=POk@IM$mZew5v)u`N}+!lT9U&7!RGmd$v9fEA=h?0Hr%o4$r3 zR`8YCl(yNOpVm|RGbEbPmtrhSYjo-A5=y$ZnjbUb96#57wx2XmmGD5Aydtc-a?xk| z9N^=DrmBJ82Y0(1#>5)?egd0CrH(*?3tRGkO*dDRWoEN;hRF>j7uVoG6W7j*?SWI4 zHYqh;Xm5#}*5TFpbb@RAlCVYF^{y7EW*fL%WN|&e@bzb(bnAM)_q*rFzkh%C{*>BX zJD*2?dcFMHsb=ZvJ@+#2=g+sgwe6wT@6FSmwQdRB4(&rrOnQQp$@VVIq=6_#lojkohx^mm%`~}Zn{(Q5` zyS$FgQJ^O(oB;$Bqo+h){=T4K=l{u>N&j9cuf3akTingo-6biqa_h;qL#fw{LCQYZ zd;hMV^U?HmxXF~TedW%1RUN5oW2Z;f{>(Fa<+w;>_OHL!LF$0xDnh4Et@gFEdGLe< zB7lQj*rh52JfsdH`)opGAU}k8M)wdWn57UxZ3a(nZZ2^35=T>n(!`D`35YF!dDVqi zhGaQjnGCVN*hy=uR9(Ppi0jWRnrNoJ)ekJ?AmMgv&J`<0FegzWvp5K@=wq&57H~)k z2pS?y_MOdq;%EU;*5b8R7%Xm(tcIjvk0-*Ui$9p(uY4?c_k3V3NTsK%pUXO@geCx; CWApm} literal 211062 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 RFZhcH4HX^bDn*-!{{g_|pojnf diff --git a/docs/long-recordings.md b/docs/long-recordings.md index 454a372db..b5bf8d424 100644 --- a/docs/long-recordings.md +++ b/docs/long-recordings.md @@ -100,8 +100,10 @@ evidence windows, and acquisition gaps. Missing measurements and units without evidence remain visible as unavailable. Evidence Amplitude shows raw source scalar amplitudes from the currently -selected evidence window. The Feature view also uses window-relative seconds; -both views label the current window and reset their time origin when it changes. +selected evidence window. The Feature view also uses window-relative seconds. +The amplitude plot labels this axis as **Seconds from window start** and shows +the window's recording-time range above the plot. +Both views label the current window and reset their time origin when it changes. To inspect another retained window, choose **View > Inspect evidence window** and enter its zero-based index. Unit Stability keeps the full-recording time context visible while you inspect individual windows. diff --git a/phy/apps/large_recording/adapter.py b/phy/apps/large_recording/adapter.py index e4d332008..cc5a351ac 100644 --- a/phy/apps/large_recording/adapter.py +++ b/phy/apps/large_recording/adapter.py @@ -303,6 +303,11 @@ def create_evidence_amplitude_view(self): split_is_eligible=lambda: False, ) view.ex_status = self._window_status() + view.set_window_context( + self.evidence_window_index, + start / self.model.sample_rate, + end / self.model.sample_rate, + ) return view def _window_status(self): @@ -324,6 +329,9 @@ def inspect_evidence_window(self, index): view.ex_status = self._window_status() if isinstance(view, EvidenceAmplitudeView): view.duration = (end - start) / self.model.sample_rate + view.set_window_context( + index, start / self.model.sample_rate, end / self.model.sample_rate + ) view.canvas.panzoom.reset() if view.cluster_ids: view.plot() diff --git a/phy/apps/large_recording/tests/test_gui_lifecycle.py b/phy/apps/large_recording/tests/test_gui_lifecycle.py index c6d951b38..d2286b9eb 100644 --- a/phy/apps/large_recording/tests/test_gui_lifecycle.py +++ b/phy/apps/large_recording/tests/test_gui_lifecycle.py @@ -11,6 +11,25 @@ from phy.apps.template.gui import TemplateController +def test_window_time_labels_follow_navigation(qtbot, tmp_path): + _, controller = make_controller(tmp_path, sparse=True) + gui = controller.create_gui(default_views=['EvidenceAmplitudeView'], do_prompt_save=False) + try: + view = gui.get_view('EvidenceAmplitudeView') + assert view.time_axis_label.text() == 'Seconds from window start' + initial = view.window_label.text() + controller.inspect_evidence_window(1) + start, end = controller.current_evidence_window / controller.model.sample_rate + assert view.window_label.text() == ( + f'Evidence window 1 | Recording time: {start:.3f}–{end:.3f} s' + ) + assert view.window_label.text() != initial + assert view.duration == end - start + finally: + gui.close() + controller.close() + + def test_gui_observer_mutation_rolls_back_views_selection_and_journal(qtbot, tmp_path): _, controller = make_controller(tmp_path) gui = controller.create_gui(default_views=[], do_prompt_save=False) diff --git a/phy/apps/large_recording/views.py b/phy/apps/large_recording/views.py index d19d5190e..c96fabf09 100644 --- a/phy/apps/large_recording/views.py +++ b/phy/apps/large_recording/views.py @@ -1,6 +1,7 @@ """Explicitly sampled statistics and window-relative amplitude views.""" from phy.cluster.views import AmplitudeView, CorrelogramView, ISIView +from phy.gui.qt import QLabel, Qt class SampledISIView(ISIView): @@ -14,6 +15,27 @@ class SampledCorrelogramView(CorrelogramView): class EvidenceAmplitudeView(AmplitudeView): """Raw source amplitude in an explicitly rebased evidence window.""" + window_caption = 'Recording time unavailable' + + def set_window_context(self, index, start_seconds, end_seconds): + self.window_caption = ( + f'Evidence window {index} | Recording time: {start_seconds:.3f}–{end_seconds:.3f} s' + ) + if hasattr(self, 'window_label'): + self.window_label.setText(self.window_caption) + + def attach(self, gui): + super().attach(gui) + layout = self.dock.widget().layout() + self.window_label = QLabel(self.window_caption) + self.window_label.setWordWrap(True) + self.time_axis_label = QLabel('Seconds from window start') + for label in (self.window_label, self.time_axis_label): + label.setAlignment(Qt.AlignCenter) + label.setStyleSheet('color: white; background-color: black; padding: 4px;') + layout.insertWidget(0, self.window_label) + layout.insertWidget(layout.count() - 1, self.time_axis_label) + def _get_data_bounds(self, bunchs): if not any(len(bunch.amplitudes) for bunch in bunchs): return (0, 0, self.duration, 1)