perf: cache bank designs, make numba/matplotlib optional (#59)
* perf: cache filter bank designs across octavefilter() calls
octavefilter() redesigned the full SOS bank on every call, dominating
runtime in loops. Designs are now reused via lru_cache (32 entries) keyed
on all design parameters; plotting calls bypass the cache. Banks are
immutable in non-stateful mode, so reuse is safe.
test_filterbank_reuse_performance now clears the cache per functional
call to keep measuring the redesign cost it was written for.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* perf: make numba optional with pure-Python impulse kernel fallback
numba is only used by the 'impulse' time-weighting kernel but is a heavy
install that pins numpy versions. It moves to the [perf] extra (also in
[full]); without it the undecorated kernel runs identically, just slower.
requirements.txt keeps numba so CI exercises the jitted path.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* perf: import matplotlib lazily and move it to the [plot] extra
matplotlib is only needed for show=True/plot_file. Importing it inside
_showfilter drops it as a hard dependency and speeds up package import.
Missing matplotlib now raises an actionable ImportError.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* perf: skip no-op resampling and avoid np.append loop in freq generation
- _resample_to_length returned a full FIR resample_poly(y, 1, 1) copy per
non-decimated band; return the input directly when nothing changes.
- getansifrequencies grew the frequency array with np.append (O(n^2));
accumulate in a list instead.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* perf: address review feedback on cache and resampling
- Return a copy of the freq list from OctaveFilterBank.filter(): with the
design cache, callers mutating the returned list would corrupt results
of subsequent octavefilter() calls.
- Pass limits=None through to the bank instead of duplicating the default
(12, 20000) in the cache key.
- Skip resample_poly entirely for factor == 1 (identity FIR call).
- Harden the lazy-import AST test to walk the full tree, not just
top-level statements.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
authored by