Skip to content

Add command to extract mean timeseries activity from ABA regions#95

Merged
celefthe merged 25 commits into
mainfrom
celefthe/issue28
Jul 15, 2026
Merged

Add command to extract mean timeseries activity from ABA regions#95
celefthe merged 25 commits into
mainfrom
celefthe/issue28

Conversation

@celefthe

Copy link
Copy Markdown
Member

Closes #28

celefthe and others added 24 commits April 22, 2026 12:28
The tform is already inverted in a way that wrap function requires
Returning a lazy HDF5 dataset caused per-frame random I/O during
parallel warping. With the real-world chunk layout (1407, 5, 9)
each frame access required decompressing ~448 chunks from disk,
resulting in ~53 min for a 45 000-frame recording.

Changes:
- load_deltaf: load /F and /timestamps eagerly with [:] and use a
  context manager so the file is closed immediately after loading
- load_deltaf (NWB path): wrap lazy HDMF arrays with np.array()
  for the same reason
- landmarks_affine: add a defensive np.asarray() guard so the
  function is safe even when a lazy array is passed in directly

Measured on a 45 000 × 140 × 142 float32 recording (3.6 GB):
  before: ~3178 s  (lazy I/O × 10 threads fighting HDF5 cache)
  after:    ~14 s  (10 s load + 4 s parallel warp)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Duplicate load_deltaf implementations existed in both
mesoscopy.process and mesoscopy.register, with a third caller in
mesoscopy.export reaching across into mesoscopy.process. This made
it difficult to optimise the loading path in one place and led to
subtle behavioural differences between modules (e.g. the process
version left the h5py file handle open and did not eagerly load
arrays into RAM, while the register version used a context manager
and sliced with [:]).

Changes:
- Add a single canonical load_deltaf(path, nwb=False) to io.py,
  using the register-style implementation (context manager + eager
  [:] load)
- Remove local load_deltaf definitions from process/__init__.py and
  register/__init__.py; redirect all call sites to io.load_deltaf()
- Update export/__init__.py to call io.load_deltaf() directly,
  removing the now-unused mesoscopy.process import
- Move load_deltaf tests from test_registration.py to test_io.py
  where all other io function tests live

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…f-to-io

refactor: consolidate load_deltaf into io.py
- Load atlas and annotations once upfront instead of once per region call
- Use ThreadPoolExecutor to process all regions concurrently; NumPy
  releases the GIL during masked-array operations so threads run in
  parallel without serialising the large deltaf_series array
- Fix mutation of module-level DEFAULT_EXCLUDE list: copy it with
  list() before extending with caller-supplied excludes
- Fix region filter to use the computed excluded_regions set instead of
  the hard-coded DEFAULT_EXCLUDE constant

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
19 tests across two classes covering extract_region_activity and
extract_all_regions. Resources are mocked with a minimal synthetic
6×6 atlas (three regions, including one from DEFAULT_EXCLUDE) so
tests run without file I/O and stay deterministic.

TestExtractRegionActivity:
- Output shape for left / right / both hemispheres
- Output values verified against manual mask means
- Hemisphere argument is case-insensitive
- Invalid hemisphere raises ValueError
- Different regions yield different signals

TestExtractAllRegions:
- Returns dict with L_/R_-prefixed keys
- Each value has shape (n_frames,)
- DEFAULT_EXCLUDE regions absent by default
- ignore_default_exclude=True re-includes them
- Custom exclude list removes specified regions
- Custom exclude is additive with DEFAULT_EXCLUDE
- DEFAULT_EXCLUDE is not mutated by repeated calls
- Results are numerically consistent with extract_region_activity

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@celefthe celefthe linked an issue Jul 15, 2026 that may be closed by this pull request
@celefthe celefthe merged commit 169ce1a into main Jul 15, 2026
8 checks passed
@celefthe celefthe deleted the celefthe/issue28 branch July 15, 2026 13:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rewrite processing module to extract activity per area

2 participants