Skip to content

Commit

Permalink
fix handling of negative resolutions in export (#81)
Browse files Browse the repository at this point in the history
* test negative resolutions

* the fix

* okay the actual fix
  • Loading branch information
kleinschmidt authored Jul 19, 2023
1 parent 7f34243 commit fc8709d
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 21 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "OndaEDF"
uuid = "e3ed2cd1-99bf-415e-bb8f-38f4b42a544e"
authors = ["Beacon Biosignals, Inc."]
version = "0.12.0"
version = "0.12.1"

[deps]
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
Expand Down
2 changes: 2 additions & 0 deletions src/export_edf.jl
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ function reencode_samples(samples::Samples, sample_type::Type{<:Integer}=Int16)
samples.info.sample_resolution_in_unit,
samples.info.sample_offset_in_unit,
(smin, smax))
# make sure we handle negative resolutions properly!
smin, smax = extrema((smin, smax))
end
if smin >= typemin(sample_type) && smax <= typemax(sample_type)
# XXX: we're being a bit clever here in order to not allocate a
Expand Down
61 changes: 41 additions & 20 deletions test/export.jl
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,11 @@

# test that we can encode ≈ the full range of values expressible in each
# possible Onda sample type.
@testset "encoding $T" for T in onda_types
@testset "encoding $T, resolution $res" for T in onda_types, res in (-0.2, 0.2)
info = SamplesInfoV2(; sensor_type="x",
channels=["x"],
sample_unit="microvolt",
sample_resolution_in_unit=2,
sample_resolution_in_unit=res,
sample_offset_in_unit=1,
sample_type=T,
sample_rate=1)
Expand All @@ -155,6 +155,7 @@

data = reshape(data, 1, :)
samples = Samples(data, info, true)
samples = Onda.decode(samples)

# for r e a s o n s we need to be a bit careful with just how large
# the values are that we're trying to use; EDF.jl (and maybe EDF
Expand All @@ -175,11 +176,11 @@
@test vec(decode(samples).data) EDF.decode(signal)
end

@testset "skip reencoding" begin
@testset "skip reencoding (res = $res)" for res in (-2, 2)
info = SamplesInfoV2(; sensor_type="x",
channels=["x"],
sample_unit="microvolt",
sample_resolution_in_unit=2,
sample_resolution_in_unit=res,
sample_offset_in_unit=1,
sample_type=Int32,
sample_rate=1)
Expand All @@ -188,39 +189,59 @@

samples = Samples(data, info, true)
# data is re-used if already encoded
@test OndaEDF.reencode_samples(samples, Int16).data === samples.data
samples_reenc = OndaEDF.reencode_samples(samples, Int16)
@test samples_reenc.data === samples.data
signal = only(OndaEDF.onda_samples_to_edf_signals([samples], 1.0))
@test EDF.decode(signal) == vec(decode(samples).data)

# make sure it works with decoded too
signal2 = only(OndaEDF.onda_samples_to_edf_signals([Onda.decode(samples)], 1.0))
@test EDF.decode(signal2) == vec(decode(samples).data)
# to confirm quantization settings are the same
@test signal.header == signal2.header
samples_dec = Onda.decode(samples)
samples_dec_reenc = OndaEDF.reencode_samples(samples_dec, Int16)
@test samples_dec_reenc.data !== samples_reenc.data
@test encode(samples_dec_reenc).data == encode(samples).data
@test samples_dec_reenc == samples_reenc
signal2 = only(OndaEDF.onda_samples_to_edf_signals([samples_dec], 1.0))
@test EDF.decode(signal2) == vec(samples_dec.data)

# bump just outside the range representable as Int16
samples.data .+= Int32[-1 1]
new_samples = OndaEDF.reencode_samples(samples, Int16)
@test new_samples != samples
@test decode(new_samples).data == decode(samples).data
samples = Samples(data .+ Int32[-1 1], info, true)
samples_reenc = OndaEDF.reencode_samples(samples, Int16)
# make sure encoding has changed:
@test encode(samples_reenc).data != encode(samples).data
# but actual stored values have not
@test decode(samples_reenc).data == decode(samples).data

signal = only(OndaEDF.onda_samples_to_edf_signals([samples], 1.0))
@test EDF.decode(signal) == vec(decode(samples).data)
# to confirm quantization settings are changed
@test signal.header != signal2.header


# make sure it works with decoded too
samples_dec = decode(samples)
samples_dec_reenc = OndaEDF.reencode_samples(samples_dec, Int16)
@test encode(samples_dec_reenc).data == encode(samples_reenc).data
# different encoding
@test encode(samples_dec_reenc).data != encode(samples).data
# ... that's teh same as passing in encoded samples
@test encode(samples_dec_reenc).data == encode(samples_reenc).data
# same decoded values
@test decode(samples_dec_reenc).data == decode(samples).data

signal3 = only(OndaEDF.onda_samples_to_edf_signals([Onda.decode(samples)], 1.0))
@test EDF.decode(signal3) == vec(decode(samples).data)

# UInt64
uinfo = SamplesInfoV2(Tables.rowmerge(info; sample_type="uint64"))
data = UInt64[0 typemax(Int16)]
samples = Samples(data, uinfo, true)
@test OndaEDF.reencode_samples(samples, Int16).data === samples.data
samples_reenc = OndaEDF.reencode_samples(samples, Int16)
@test samples_reenc.data === samples.data
signal = only(OndaEDF.onda_samples_to_edf_signals([samples], 1.0))
@test EDF.decode(signal) == vec(decode(samples).data)

samples.data .+= UInt64[0 1]
new_samples = OndaEDF.reencode_samples(samples, Int16)
@test new_samples != samples
@test decode(new_samples).data == decode(samples).data
samples_reenc = OndaEDF.reencode_samples(samples, Int16)
@test samples_reenc != samples
@test encode(samples_reenc).data != encode(samples).data
@test decode(samples_reenc).data == decode(samples).data

signal = only(OndaEDF.onda_samples_to_edf_signals([samples], 1.0))
@test EDF.decode(signal) == vec(decode(samples).data)
Expand Down

2 comments on commit fc8709d

@kleinschmidt
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
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/87831

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 v0.12.1 -m "<description of version>" fc8709d84e2a55b77cd86d1f9fbc3003d5a95c6d
git push origin v0.12.1

Please sign in to comment.