https://github.com/baggepinnen/signalalignment.jl
Align signals to each other
Science Score: 13.0%
This score indicates how likely this project is to be science-related based on various indicators:
-
○CITATION.cff file
-
✓codemeta.json file
Found codemeta.json file -
○.zenodo.json file
-
○DOI references
-
○Academic publication links
-
○Academic email domains
-
○Institutional organization owner
-
○JOSS paper metadata
-
○Scientific vocabulary similarity
Low similarity (9.7%) to scientific vocabulary
Keywords
Repository
Align signals to each other
Basic Info
Statistics
- Stars: 23
- Watchers: 2
- Forks: 0
- Open Issues: 4
- Releases: 3
Topics
Metadata Files
README.md
SignalAlignment
This package takes a vector of signals and tries to align them.
One use case for this is when two different instruments are used to record something that is going on, but they may record at different sample rates, have no synchronization, or have different time offsets. Before analyzing such experiments, it may be helpful to align the signals to each other.
Function reference
align_signals(signals, method; master, by, output): Main entrypoint for signal alignmentsyncplot: takes the same arguments asalign_signals(exceptoutput) and plots the aligned signals
Method reference
The method indicates how alignment is computed. The method is specified by passing a method argument to align_signals. The following methods are available:
Delay(; delay_method): Align signals by shifting them with respect to each otherdelay_method = DTWDelay(): Align signals by computing the optimal delay using Dynamic-Time Warping. This can be computationally expensive for very long signals, but is more robust thanXcorrDelay.delay_method = XcorrDelay(): Align signals by computing the optimal delay using cross-correlation
Warp(; warp_method): Align signals by warping them with respect to each otherwarp_method = DTW(; radius, ...): Align signals by computing the optimal warp using Dynamic-Time Warping. See DynamicAxisWarping.jl for options toDTW.warp_method = GDTW(): Align signals by computing the optimal warp using Generalized Dynamic-Time Warping. See DynamicAxisWarping.jl for options toGDTWor the example below.
Master reference
The master indicates which signal is used as the reference signal to which the other signals are aligned. The master is specified by passing a master argument to align_signals. The following masters are available:
Index: Align all signals to a particular signal. The default isIndex(1)which aligns all signals to the first signal.Longest: Align all signals to the longest signalShortest: Align all signals to the shortest signalCentroid: Align all signals to the computed centroid (generalized median) of all signals. The metric used to compute the centroid is specified by, e.g.,Centroid(SqEuclidean()).Barycenter: Align all signals to the computed barycenter (generalized mean) of all signals. The metric used to compute the barycenter is specified by, e.g.,Barycenter(SqEuclidean()).
Output reference
The output indicates what is returned by align_signals. The output is specified by passing an output argument to align_signals. The following output options are available:
Indices(): Return the indices that align the signals.Signals(): Return the aligned signals.
The map from indices to aligned signals is
julia
aligned_signals = [signals[i][inds[i]] for i in eachindex(signals)]
Examples
Align shifted signals to one particular signal
We can indicate that we want to align a vector of signals to a particular signal by passing the index of the signal we want to align to as the master argument to align_signals. The default master if none is provided is Index(1) like we use below.
```julia
using SignalAlignment
s0 = sin.((0:0.05:2pi)) # A noisy signal
s1 = s0[1:end-10] # A second signal, misaligned with the first
s2 = s0[20:end] # A third signal
signals = [s0, s1, s2] # A vector of signals we want to align
signals = [s .+ 0.02 .* randn(length(s)) for s in signals] # Add some noise to the signals
master = Index(1) # Indicate which signal is the master to which the others are aligned
method = Delay(delaymethod=DTWDelay()) # Indicate that we want to align the signals by shifting them, and the delay between them is computed using DTW
output = Indices() # Indicate that we want the aligning indices as output
inds = alignsignals(signals, method; master, output)
3-element Vector{UnitRange{Int64}}:
2:1884
2:1884
1:1883
```
The indices returned by align_signals can be used to align the signals to the master signal.
julia
aligned_signals = [signals[i][inds[i]] for i in eachindex(signals)]
plot(signals, label=["s0" "s1" "s2"], l=(:dash, ))
plot!(aligned_signals, label=["s0 aligned" "s1 aligned" "s2 aligned"], c=(1:3)', size=(600, 400))

The example above used Dynamic-Time Warping (DTW) to find the optimal delay with which to shift the signals to the master. Rather than DTW, we can compute the delay using cross-correlation as well
julia
method = Delay(delay_method = XcorrDelay())
If we want to obtain the aligned signals directly as output rather than the aligning indices, we pass output = Signals().
Align signals with different sample rates
In this example, the second signal has a sample rate that is 2x lower than the first signal. We can align the signals by warping them using Dynamic-Time Warping (DTW) to fit the first signal. DTW is handled by the DynamicAxisWarping.jl package. ```julia using SignalAlignment s0 = sin.((0:0.05:2pi)) # A noisy signal s1 = s0[1:2:end-10] # A second signal with 2x lower sample rate s2 = s0[20:end] # A third signal signals = [s0, s1, s2] # A vector of signals we want to align signals = [s .+ 0.02 .* randn(length(s)) for s in signals] # Add some noise to the signals
master = Index(1) # Indicate which signal is the master to which the others are aligned method = Warp(warp_method=DTW(radius=20)) output = Signals() # Indicate that we want the aligned signals as output
syncplot(signals, method; master) # Call this if you only want to plot the aligned signals
alignedsignals = alignsignals(signals, method; master, output)
plot(signals, label=["s0" "s1" "s2"], l=(:dash, ))
plot!(aligned_signals, label=["s0 aligned" "s1 aligned" "s2 aligned"], c=(1:3)', size=(600, 400))
```

Notice how the signal that was sampled slowly has been stretched to fit the first signal. This introduces some artifacts, where some samples have been repeated. If undesired, these artifacts can be mitigated somewhat by using generalized DTW, shown below. If the signals are instead aligned to the shortest signal, the longer signals are subsampled:
julia
master = Shortest()
aligned_signals = align_signals(signals, method; master, output)
plot(signals, label=["s0" "s1" "s2"], l=(:dash, ))
plot!(aligned_signals, label=["s0 aligned" "s1 aligned" "s2 aligned"], c=(1:3)', size=(600, 400))

To get a smoother result, use generalized DTW (GDTW) instead of DTW.
julia
master = Shortest()
method = Warp(warp_method=GDTW(symmetric=false))
aligned_signals = align_signals(signals, method; master, output)
plot(signals, label=["s0" "s1" "s2"], l=(:dash, ))
plot!(aligned_signals, label=["s0 aligned" "s1 aligned" "s2 aligned"], c=(1:3)', size=(600, 400))

Owner
- Name: Fredrik Bagge Carlson
- Login: baggepinnen
- Kind: user
- Location: Lund, Sweden
- Website: baggepinnen.github.io
- Twitter: baggepinnen
- Repositories: 59
- Profile: https://github.com/baggepinnen
Control systems, system identification, signal processing and machine learning
GitHub Events
Total
- Release event: 1
- Watch event: 9
- Delete event: 1
- Issue comment event: 3
- Push event: 2
- Pull request event: 2
- Create event: 2
Last Year
- Release event: 1
- Watch event: 9
- Delete event: 1
- Issue comment event: 3
- Push event: 2
- Pull request event: 2
- Create event: 2
Issues and Pull Requests
Last synced: 8 months ago
All Time
- Total issues: 5
- Total pull requests: 14
- Average time to close issues: less than a minute
- Average time to close pull requests: over 1 year
- Total issue authors: 2
- Total pull request authors: 1
- Average comments per issue: 1.8
- Average comments per pull request: 0.0
- Merged pull requests: 2
- Bot issues: 0
- Bot pull requests: 14
Past Year
- Issues: 0
- Pull requests: 0
- Average time to close issues: N/A
- Average time to close pull requests: N/A
- Issue authors: 0
- Pull request authors: 0
- Average comments per issue: 0
- Average comments per pull request: 0
- Merged pull requests: 0
- Bot issues: 0
- Bot pull requests: 0
Top Authors
Issue Authors
- baggepinnen (4)
- JuliaTagBot (1)
Pull Request Authors
- github-actions[bot] (16)
Top Labels
Issue Labels
Pull Request Labels
Packages
- Total packages: 1
-
Total downloads:
- julia 2 total
- Total dependent packages: 0
- Total dependent repositories: 0
- Total versions: 3
juliahub.com: SignalAlignment
Align signals to each other
- Documentation: https://docs.juliahub.com/General/SignalAlignment/stable/
- License: MIT
-
Latest release: 0.1.2
published about 1 year ago
Rankings
Dependencies
- JuliaRegistries/TagBot v1 composite
- actions/cache v1 composite
- actions/checkout v2 composite
- codecov/codecov-action v1 composite
- julia-actions/julia-buildpkg v1 composite
- julia-actions/julia-processcoverage v1 composite
- julia-actions/julia-runtest v1 composite
- julia-actions/setup-julia v1 composite