Skip to content

Commit c6dcd11

Browse files
committed
add test
1 parent 2f16741 commit c6dcd11

File tree

3 files changed

+41
-8
lines changed

3 files changed

+41
-8
lines changed

docs/src/tutorials/noise.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,13 @@ The default option `midrise = true` includes both end points as possible output
151151

152152

153153
## Sampling with AD effects
154-
The block [`SampleWithADEffects`](@ref) combines a [`Sampler`](@ref), a [`NormalNoise](@ref) and a [`Quantization`](@ref) block to simulate the effects of practical sampling, noise and quantization in an AD converter. The block has the connectors `input` and `output`, where the input is the continuous-time signal to be sampled, and the output is the quantized, noisy signal. Example
154+
The block [`SampleWithADEffects`](@ref) combines an ideal [`Sampler`](@ref), a [`NormalNoise](@ref) and a [`Quantization`](@ref) block to simulate the undesirable but practically occurring effects of sampling, noise and quantization in an AD converter. The block has the connectors `input` and `output`, where the input is the continuous-time signal to be sampled, and the output is the quantized, noisy signal. Example:
155155

156156
```@example QUANT
157157
@mtkmodel PracticalSamplerModel begin
158158
@components begin
159159
input = Sine(amplitude=1.2, frequency=1, smooth=false)
160-
sampling = SampleWithADEffects(; dt=0.03, bits=3, y_min = -1, y_max = 1, sigma = 0.05, noisy = false, quantized=false, midrise=true)
160+
sampling = SampleWithADEffects(; dt=0.03, bits=3, y_min = -1, y_max = 1, sigma = 0.1, noisy = true, quantized=true, midrise=true)
161161
end
162162
@variables begin
163163
x(t) = 0 # Dummy variable to work around a bug for models without continuous-time state
@@ -170,10 +170,16 @@ end
170170
@named m = PracticalSamplerModel()
171171
m = complete(m)
172172
ssys = structural_simplify(IRSystem(m))
173-
# prob = ODEProblem(ssys, [m.sampling.noise.y(z-1) => 0], (0.0, 2.0))
174-
prob = ODEProblem(ssys, [], (0.0, 2.0))
173+
prob = ODEProblem(ssys, [m.sampling.noise.y(z-1) => 0], (0.0, 2.0))
175174
sol = solve(prob, Tsit5())
176175
plot(sol, idxs=m.input.output.u)
177176
plot!(sol, idxs=m.sampling.y, label="AD converted output")
178-
# plot!(sol, idxs=m.sampling.sampler.y, label="AD converted output")
179-
```
177+
```
178+
179+
Both quantization and noise addition are optional and turned off by default. In the example above, we turn them on with keywords `noisy = true` and `quantized = true`. The noise is Gaussian white noise with standard deviation `sigma`, and the quantization is a 3-bit midrise quantizer (8 output levels) with limits `y_min` and `y_max`. Limits have to be provided when quantization is used. The `dt` parameter is the sampling time, if left unspecified, it will be inferred from context.
180+
181+
Things to notice in the plot:
182+
- The sampled signal is saturated at the quantization limits ±1.
183+
- The noise is added to the signal before quantization, which means that the sampled signal has ``2^\text{bits}`` distinct output levels only.
184+
- 0 is not a possible output value. In situations where 0 is an important value (such as in the presence of integration of a quantized value that is expected to be close to 0), the mid-tread quantizer should be used instead by passing `midrise = false`.
185+

src/discrete_blocks.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,7 @@ This block is not differentiable, the derivative is zero everywhere exect for at
910910
@parameters begin
911911
y_max = 1, [description = "Upper limit of output"]
912912
y_min = -1, [description = "Lower limit of output"]
913-
bits::Int = 8, [description = "Number of bits of quantization"]
913+
bits = 8, [description = "Number of bits of quantization"]
914914
quantized::Bool = true, [description = "If quantization effects shall be computed."]
915915
end
916916
@equations begin
@@ -1057,7 +1057,7 @@ The operations occur in the order
10571057
else
10581058
noise = Gain(; k = 1)
10591059
end
1060-
quantization = Quantization(; y_min, y_max, midrise, quantized)
1060+
quantization = Quantization(; bits, y_min, y_max, midrise, quantized)
10611061
end
10621062
@equations begin
10631063
connect(input, sampler.input)

test/test_discrete_blocks.jl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,4 +514,31 @@ end
514514
@test sol(0.999, idxs=m.filter.y) == 0
515515
@test sol(1.1, idxs=m.filter.y) > 0
516516

517+
end
518+
519+
@testset "sampling with AD effects" begin
520+
@info "Testing sampling with AD effects"
521+
522+
@mtkmodel PracticalSamplerModel begin
523+
@components begin
524+
input = Sine(amplitude=1.2, frequency=1, smooth=false)
525+
sampling = SampleWithADEffects(; dt=0.03, bits=3, y_min = -1, y_max = 1, sigma = 0.1, noisy = true, quantized=true, midrise=true)
526+
end
527+
@variables begin
528+
x(t) = 0 # Dummy variable to work around a bug for models without continuous-time state
529+
end
530+
@equations begin
531+
connect(input.output, sampling.input)
532+
D(x) ~ Hold(sampling.y) # Dummy equation
533+
end
534+
end
535+
@named m = PracticalSamplerModel()
536+
m = complete(m)
537+
ssys = structural_simplify(IRSystem(m))
538+
prob = ODEProblem(ssys, [m.sampling.noise.y(z-1) => 0], (0.0, 2.0))
539+
sol = solve(prob, Tsit5())
540+
541+
@test length(unique(sol[m.sampling.y])) == 8
542+
@test maximum(abs, sol(0:0.03:1, idxs=m.sampling.y) - sol(0:0.03:1, idxs=m.sampling.u)) < 0.3
543+
517544
end

0 commit comments

Comments
 (0)