Skip to content

Commit a89f5df

Browse files
committed
Add documentation, test, fix some bugs
1 parent b072fd8 commit a89f5df

File tree

15 files changed

+1329
-302
lines changed

15 files changed

+1329
-302
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "SignalIndices"
22
uuid = "18f53e89-494d-4131-905c-653e8ada6cd8"
33
authors = ["Galen Lynch <galen@galenlynch.com>"]
4-
version = "0.1.1"
4+
version = "0.1.2"
55

66
[deps]
77
IterTools = "c8e1da08-722c-5040-9ed9-7db0dc04731e"

README.md

Lines changed: 19 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -2,92 +2,33 @@
22

33
Utilities for working with regularly sampled time series data, including index-time conversions, signal processing primitives, and array manipulation functions.
44

5-
## Overview
6-
7-
This package provides low-level building blocks for signal processing workflows, particularly for neuroscience and electrophysiology applications where data is regularly sampled at a known frequency. The focus is on efficient, allocation-conscious implementations suitable for processing large datasets.
8-
9-
## Features
10-
11-
### Index/Time Conversion
12-
13-
Convert between sample indices and time values for regularly sampled data:
5+
## Quick Example
146

157
```julia
168
using SignalIndices
179

18-
fs = 30000.0 # 30 kHz sampling rate
19-
start_t = 0.0
20-
21-
# Convert time to index
22-
idx = t_to_ndx(0.5, fs, start_t) # First sample at or after 0.5s
23-
24-
# Convert index to time
25-
t = ndx_to_t(15001, fs, start_t) # Time of sample 15001
26-
27-
# Duration and time intervals
28-
dur = duration(30001, fs) # Duration spanned by 30001 samples
29-
interval = time_interval(30001, fs, start_t) # (start_t, end_t) tuple
30-
```
31-
32-
### Signal Processing Primitives
33-
34-
```julia
35-
# Sliding window sum (no zero-padding)
36-
sums = moving_sum(signal, window_size)
10+
fs = 30_000.0 # 30 kHz sampling rate
3711

38-
# Find threshold crossings (edge triggers)
39-
rising_edges = find_all_edge_triggers(signal, threshold)
40-
first_edge = find_first_edge_trigger(signal, threshold)
12+
# Convert between sample indices and time
13+
t = ndx_to_t(15001, fs) # 0.5 s
14+
idx = t_to_ndx(0.5, fs) # 15001
4115

42-
# Find local extrema
43-
maxima_indices = local_extrema(signal, >)
44-
minima_indices = local_extrema(signal, <)
16+
# Detect threshold crossings in a signal
17+
edges = find_all_edge_triggers(signal, threshold)
4518

46-
# Fast histogram for regularly-spaced bins
47-
counts = uniformhist(values, bin_edges)
19+
# Sliding window sum (no zero-padding) and fast histogram
20+
sums = moving_sum(signal, 100)
21+
counts = uniformhist(spike_times, 0.0:0.001:1.0)
4822
```
4923

50-
### Array Utilities
51-
52-
```julia
53-
# Pairwise operations
54-
idxs = pairwise_idxs(n) # All (i,j) pairs where i > j
55-
diffs = map_pairwise(-, sorted_times) # Pairwise differences
56-
57-
# Filtering and searching
58-
idx = find_closest(array, target)
59-
non_colliding = filter_no_collisions(events_a, events_b, min_gap)
60-
duplicates = find_not_unique(array)
24+
## When to Use What
6125

62-
# Equality and comparison
63-
allsame([1, 1, 1]) # true — all elements equal
64-
allsame(length, [1,2], [3,4]) # true — all have same length
65-
anyeq(3, [1, 2, 3]) # true — element found in collection
66-
absdiff(5, 3) # 2 — absolute difference (unsigned-safe)
67-
68-
# Iterator utilities
69-
result = sum(skipnothing([1, nothing, 2, nothing, 3])) # 6
70-
```
71-
72-
## Relation to Other Packages
73-
74-
### vs DSP.jl
75-
76-
[DSP.jl](https://github.com/JuliaDSP/DSP.jl) provides comprehensive digital signal processing including filters, FFTs, and spectral analysis. SignalIndices.jl is complementary, focusing on:
77-
- Index/time bookkeeping for sampled data
78-
- Simple threshold and edge detection
79-
- Utilities commonly needed before/after DSP operations
80-
81-
### vs SampledSignals.jl
82-
83-
[SampledSignals.jl](https://github.com/JuliaAudio/SampledSignals.jl) focuses on audio I/O with rich type hierarchies for audio buffers. This package has different goals:
84-
- No audio-specific functionality
85-
- Focus on index/time math and signal primitives
86-
- Designed for neuroscience/electrophysiology workflows
87-
88-
### vs TimeSeries.jl
89-
90-
[TimeSeries.jl](https://github.com/JuliaStats/TimeSeries.jl) provides `TimeArray` types for financial/irregular time series. SignalIndices.jl assumes regular sampling and works with plain arrays, computing times from indices and sampling rates rather than storing timestamps.
26+
| Package | Focus |
27+
|---------|-------|
28+
| **SignalIndices.jl** | Index/time math, edge detection, and array primitives for regularly sampled data |
29+
| [DSP.jl](https://github.com/JuliaDSP/DSP.jl) | Filters, FFTs, spectral analysis — use *with* SignalIndices for bookkeeping |
30+
| [SampledSignals.jl](https://github.com/JuliaAudio/SampledSignals.jl) | Audio I/O with rich buffer types — audio-specific |
31+
| [TimeSeries.jl](https://github.com/JuliaStats/TimeSeries.jl) | `TimeArray` types for financial/irregular time series — stores timestamps per sample |
9132

9233
## Installation
9334

@@ -97,57 +38,9 @@ using Pkg
9738
Pkg.develop(path="/path/to/SignalIndices")
9839
```
9940

100-
## API Reference
101-
102-
### Type Utilities
103-
- `div_type(T)` - Determine appropriate floating-point type for division
104-
105-
### Index/Time Conversion
106-
- `ndx_to_t(i, fs, start_t)` - Index to time
107-
- `t_to_ndx(t, fs, start_t)` - Time to index (first sample at or after)
108-
- `t_to_last_ndx(t, fs, start_t)` - Time to index (last sample at or before)
109-
- `t_sup_to_ndx(t, fs, start_t)` - Time to index (last sample before)
110-
- `clip_ndx(idx, len)` - Clamp index to valid range
111-
- `n_ndx(start, stop)` - Count indices in range
112-
- `duration(npoints, fs)` - Time span of samples
113-
- `time_interval(npoints, fs, start_t)` - Start/end time tuple
114-
115-
### Bin/Window Operations
116-
- `bin_bounds(binno, binsize)` - Index bounds for a bin
117-
- `bin_center(binno, binsize)` - Center index of a bin
118-
- `expand_selection(ib, ie, imax, expansion)` - Expand index range
119-
120-
### Signal Processing
121-
- `moving_sum(signal, window)` / `moving_sum!(out, signal, window)` - Sliding sum
122-
- `find_all_edge_triggers(arr, threshold, comp)` - Find all threshold crossings
123-
- `find_first_edge_trigger(arr, threshold, comp)` - Find first crossing
124-
- `thresh_cross(arr, threshold, comp)` - Threshold crossing indices
125-
- `indices_above_thresh(arr, threshold)` - Contiguous regions above threshold
126-
- `local_extrema(signal, comp)` - Find local maxima/minima
127-
- `find_local_extrema(signal, start; findmax, right_on_ties)` - Hill-climb to extremum
128-
- `uniformhist(values, bins)` / `uniformhist!(counts, values, bins)` - Fast histogram
129-
- `filter_no_collisions(as, bs, radius)` - Remove elements too close to reference
130-
- `window_counts(times, duration)` - Count events in sliding window
41+
## Documentation
13142

132-
### Array Utilities
133-
- `weighted_mean(values, weights)` / `weighted_mean_dim(arr, weights, dim)` - Weighted averages
134-
- `simple_summary_stats(arr)` - Mean, std, SEM tuple
135-
- `find_closest(arr, target)` - Index of nearest value
136-
- `find_subseq(subseq, seq)` - Find subsequence occurrences
137-
- `subselect(vec, index_tuples)` - Extract subvectors by index ranges
138-
- `pairwise_idxs(n)` - Generate all unique pairs
139-
- `pairwise_idx(i, j, n)` - Linear index for pair
140-
- `map_pairwise(f, vec)` - Apply function to all pairs
141-
- `imap_product(f, as, bs)` - Lazy Cartesian product map
142-
- `filtermap(predicate, f, xs)` - Combined filter and map
143-
- `find_not_unique(arr)` - Indices of duplicate elements
144-
- `trailing_zeros_idx(arr)` - Last non-zero index
145-
- `clipsize!(vec, n)` - Resize and shrink capacity
146-
- `rev_view(vec)` - Reversed view
147-
- `allsame(collection)` / `allsame(f, args...)` - Check all elements (or mapped values) are equal
148-
- `anyeq(element, collection)` - Check if element exists in collection
149-
- `absdiff(a, b)` - Absolute difference (safe for unsigned integers)
150-
- `skipoftype(T, itr)` / `skipnothing(itr)` - Skip elements by type
43+
See the [full documentation](https://galenlynch.github.io/SignalIndices.jl/dev/) for a usage guide and API reference.
15144

15245
## Citing
15346

docs/make.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ makedocs(;
1414
),
1515
pages=[
1616
"Home" => "index.md",
17+
"Usage Guide" => "guide.md",
18+
"API Reference" => "api.md",
1719
],
20+
warnonly=[:missing_docs],
1821
)
1922

2023
deploydocs(;

docs/src/api.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
```@meta
2+
CurrentModule = SignalIndices
3+
```
4+
5+
# [API Reference](@id api)
6+
7+
```@index
8+
```
9+
10+
```@autodocs
11+
Modules = [SignalIndices]
12+
Public = true
13+
Private = false
14+
```

0 commit comments

Comments
 (0)