Skip to content

Commit

Permalink
add missingval option to timeseries (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
Datseris authored Jun 28, 2020
1 parent eeb16dc commit 6f92f2c
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.

This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

# 1.5.0
* Option `missingval` for `timeseries`.

# 1.4.0
* New function `repeat`.
* `combine` now works with `Vector{Vector{<:Note}}` as well.
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "MusicManipulations"
uuid = "274955c0-c284-5bf7-b122-5ecd51c559de"
repo = "https://github.com/JuliaMusic/MusicManipulations.jl.git"
version = "1.4.1"
version = "1.5.0"

[deps]
MIDI = "f57c4921-e30c-5f49-b073-3f2f2ada663e"
Expand Down
19 changes: 10 additions & 9 deletions src/data_handling/timeseries.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export timeseries, segment

"""
timeseries(notes::Notes, property::Symbol, f, grid; segmented = false) -> tvec, ts
timeseries(notes::Notes, property::Symbol, f, grid; kwargs...) -> tvec, ts
Produce a timeseries of the `property` of the given notes, by
first quantizing on the given `grid` (to avoid actual quantization
use the grid `0:1//notes.tpq:1`). Return the time vector `tvec` in ticks
Expand All @@ -10,21 +10,21 @@ and the produced timeseries `ts`.
After quantization, it is often the case that many notes are in the same bin of
the grid. The **function** `f` denotes which value of the vector of the
`property` of the notes to keep. Typical values are `minimum, maximum, mean`,
etc. Notice that bins without any note in them obtain the value `missing`,
regardless of the function `f` or the `property`.
etc. Notice that bins without any note in them obtain the value of the keyword `missingval`,
which be default is just `missing`, regardless of the function `f` or the `property`.
If the `property` is `:velocity`, `:pitch`, or `:duration` the function
behaves exactly as described. The `property` can also be `:position`.
In this case, the timeseries `ts` contain the timing deviations of the notes
with respect to the `tvec` vector
(these numbers are known as *microtiming deviations* in the literature).
If 'segmented = true', the notes are segmented according to the grid in order to
respect the information of their duration, see [`segment`](@ref).
If given keyword 'segmented = true', the notes are segmented according to the grid
in order to respect the information of their duration, see [`segment`](@ref).
Otherwise the notes are treated as point events with no duration
(it makes no sense to choose `:duration` with `segmented`).
"""
function timeseries(notes, property, f, grid; segmented = false)
function timeseries(notes, property, f, grid; segmented = false, missingval = missing)
isgrid(grid)
if segmented == true
notes = segment(notes, grid)
Expand All @@ -35,7 +35,7 @@ function timeseries(notes, property, f, grid; segmented = false)
property (:velocity, :pitch, :duration, :position, :channel)
error("Unknown property!")
end
ts, tvec, quantizedpos = _init_timeseries_vectors(notes, grid)
ts, tvec, quantizedpos = _init_timeseries_vectors(notes, grid, missingval)
i = previdx = 1; L = length(quantizedpos); M = length(tvec)
while i L
# find entries of same grid bin
Expand Down Expand Up @@ -98,7 +98,7 @@ function produce_note_value(notes, property::Nothing, f, i, j)
val = Float64(f(v))
end

function _init_timeseries_vectors(notes, grid)
function _init_timeseries_vectors(notes, grid, missingval)
tpq = notes.tpq
qnotes = quantize(notes, grid)
quantizedpos = positions(qnotes)
Expand All @@ -114,6 +114,7 @@ function _init_timeseries_vectors(notes, grid)
append!(tvec, bins .+ c*tpq)
c += 1
end
ts = Vector{Union{Float64, Missing}}(undef, length(tvec))
ts = Vector{Union{Float64, typeof(missingval)}}(undef, length(tvec))
fill!(ts, missingval)
return ts, tvec, quantizedpos
end
4 changes: 4 additions & 0 deletions test/timeseries.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ using Statistics, Test, MusicManipulations
@test count(ismissing, [tseries[i] for i in 2:2:159*2+2]) == 160
@test count(x -> x isa Float64, [tseries[i] for i in 2:2:159*2+2]) == 0

tvec, tseries = timeseries(notes, :velocity, mean, grid; missingval = 0.0)
@test tseries isa Vector{Float64}
@test count(iszero, [tseries[i] for i in 2:2:159*2+2]) == 160

end

@testset "Pitch timeseries" begin
Expand Down

2 comments on commit 6f92f2c

@Datseris
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register()

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/17123

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.5.0 -m "<description of version>" 6f92f2cfbda878d9fbc99498c1ebbfb1693fcd31
git push origin v1.5.0

Please sign in to comment.