Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fully Document BloqadeWaveforms #470

Merged
merged 12 commits into from
Dec 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 9 additions & 6 deletions docs/src/waveform.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ The generated waveforms can be directly used to build the time-dependent Hamilto
## Creating Waveforms

In Bloqade, the waveforms are defined as a [`Waveform`](@ref) object,
which is a composition of a callable object and a real number `duration`:

```@docs
BloqadeWaveforms.Waveform
```
which is a created by providing a callable object and a real number `duration`:

Bloqade gives users the flexibility to specify general waveforms by inputting functions. The following code constructs a sinusoidal waveform with a time duration of 2 μs:

Expand Down Expand Up @@ -157,13 +153,20 @@ fig

## References


```@docs
BloqadeWaveforms.Waveform
Waveform(f; duration::Real)
BloqadeWaveforms.:(..)
sample_values
sample_clock
piecewise_linear
piecewise_constant
piecewise_linear_interpolate
piecewise_constant_interpolate
linear_ramp
constant
sinusoidal
BloqadeWaveforms.LinearAlgebra.norm
append
smooth
smooth(kernel, Xi::Vector, Yi::Vector, kernel_radius::Real)
Expand Down
6 changes: 6 additions & 0 deletions lib/BloqadeWaveforms/src/interpolate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ function piecewise_linear_interpolate(wf::Waveform;

end

"""
piecewise_constant_interpolate(wf::Waveform; min_step::Real=0.0, atol::Real = 1.0e-5)

Converts `wf` to a [`piecewise_constant`](@ref) waveform subject to `min_step`
(the smallest allowable time step) and tolerance `atol`.
"""
function piecewise_constant_interpolate(wf::Waveform;
min_step::Real=0.0,
atol::Real = 1.0e-5)
Expand Down
124 changes: 123 additions & 1 deletion lib/BloqadeWaveforms/src/waveform.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
struct Waveform
struct Waveform{F,T<:Real}

Type for waveforms. `Waveform`s are defined
as a function combined with a real number
Expand All @@ -26,7 +26,11 @@ function Base.:(==)(lhs::Waveform, rhs::Waveform)
end


"""
LinearAlgebra.norm(x::Waveform;p::Real=1)

Defines the norm function on [`Waveform`](@ref) type.
"""
function LinearAlgebra.norm(x::Waveform;p::Real=1)
if isfinite(p) # p-norm
kernel = t->abs.(x(t)) .^ p
Expand Down Expand Up @@ -105,10 +109,71 @@ function (wf::Waveform)(t::Real, offset::Real = zero(t))
return wf.f(min(t - offset, wf.duration))
end

"""
sample_clock(wf::Waveform; offset::Real = zero(eltype(wf)), dt::Real = 1e-3)

Generates range of time values based on `wf`'s duration
with `dt` time between each time value along with
`offset` time added to the beginning and end of the waveform's time span.

See also [`sample_values`](@ref)

```jldoctest; setup=:(using BloqadeWaveforms)
julia> wf = sinusoidal(duration=2, amplitude=2π*2.2); # create a waveform

julia> sample_clock(wf;) # range from 0.0 to 2.0 with step of 0.001 (default arg)
0.0:0.001:2.0

julia> sample_clock(wf; offset=0.1) # offset beginning and end by 0.1
0.1:0.001:2.1

julia> sample_clock(wf; dt = 2e-3) # set step size of 2e-3
0.0:0.002:2.0
```
"""
function sample_clock(wf::Waveform; offset::Real = zero(eltype(wf)), dt::Real = 1e-3)
return offset:dt:wf.duration+offset
end

"""
sample_values(wf::Waveform, clocks; offset::Real = zero(eltype(wf)))
sample_values(wf::Waveform; offset::Real = zero(eltype(wf)), dt::Real = 1e-3)

Samples of waveform `wf` values obtainable by either providing an iterable `clocks`
containing exact time values to sample from or providing `offset` and `dt` values
which specify the offset to add to the beginning and end of the waveforms time span and
the step between time values.

See also [`sample_clock`](@ref)

```jldoctest; setup:=using(using BloqadeWaveforms)
julia> wf = linear_ramp(duration=0.5, start_value=0.0, stop_value=2π*1.0);

julia> sample_values(wf,0.0:0.1:0.5) # sample waveform values from range
6-element Vector{Float64}:
0.0
1.2566370614359172
2.5132741228718345
3.7699111843077517
5.026548245743669
6.283185307179586

julia> sample_values(wf; dt=5e-2) #5e-2 time gap between each sampled valued
11-element Vector{Float64}:
0.0
0.6283185307179586
1.2566370614359172
1.8849555921538759
2.5132741228718345
3.141592653589793
3.7699111843077517
4.39822971502571
5.026548245743669
5.654866776461628
6.283185307179586

```
"""
function sample_values(wf::Waveform, clocks; offset::Real = zero(eltype(wf)))
return [wf(t, offset) for t in clocks]
end
Expand Down Expand Up @@ -452,3 +517,60 @@ function sinusoidal(; duration, amplitude = one(duration))
return amplitude * sin(2π * t)
end
end

"""
function (..)(first, last)

Comment on lines +520 to +523
Copy link
Member

Choose a reason for hiding this comment

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

this is nice! wasn't thinking to document this at all.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Made it a goal on my end to prioritize documenting anything that gets exported 😄

This was particularly tricky to document (trying to get the docstring to show) but I got some inspiration looking at the way you documented things in YaoSubspaceArrayReg!

Exported from [`Intervals`](https://github.com/invenia/Intervals.jl), creates a closed interval from `first..last`
and can be used with `Waveform` structs to obtain a slice of a Waveform's values, with the waveform slice's time adjusted to begin at 0 μs and
the duration being `last - first`.

# Example

```julia
julia> wf = Waveform(t->2.2*2π*sin(2π*t), duration = 2)
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀Waveform{_, Int64}⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
┌────────────────────────────────────────┐
3 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⡴⠋⠙⢦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡴⠋⠙⢦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⡼⠁⠀⠀⠈⢧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡼⠁⠀⠀⠈⢧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⢰⠃⠀⠀⠀⠀⠈⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠃⠀⠀⠀⠀⠈⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⢀⡏⠀⠀⠀⠀⠀⠀⢸⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡏⠀⠀⠀⠀⠀⠀⢸⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⡼⠀⠀⠀⠀⠀⠀⠀⠀⢧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡼⠀⠀⠀⠀⠀⠀⠀⠀⢧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
value (2π ⋅ MHz) │⠧⠤⠤⠤⠤⠤⠤⠤⠤⠼⡦⠤⠤⠤⠤⠤⠤⠤⠤⢤⠧⠤⠤⠤⠤⠤⠤⠤⠤⠼⡦⠤⠤⠤⠤⠤⠤⠤⠤⢤│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢳⠀⠀⠀⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢳⠀⠀⠀⠀⠀⠀⠀⠀⡞│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣇⠀⠀⠀⠀⠀⠀⢸⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣇⠀⠀⠀⠀⠀⠀⢸⠁│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡄⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡄⠀⠀⠀⠀⢀⠇⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢳⡀⠀⠀⢀⡞⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢳⡀⠀⠀⢀⡞⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠳⣄⣠⠞⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠳⣄⣠⠞⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀│
-3 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
└────────────────────────────────────────┘
⠀0⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀clock (μs)⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀2⠀

julia> wf[0.9..1.5]
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀Waveform{_, Float64}⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
┌────────────────────────────────────────┐
3 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⠤⠔⠒⠒⠒⠦⢤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡤⠞⠉⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠲⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡴⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠑⢦⡀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡴⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡴⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠳⣄⠀⠀⠀│
value (2π ⋅ MHz) │⠀⠀⠀⠀⠀⠀⠀⠀⣠⠎⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠳⡀⠀│
│⠀⠀⠀⠀⠀⠀⢀⡜⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦│
│⠉⠉⠉⠉⠉⡽⠋⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉│
│⠀⠀⠀⣠⠞⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⢀⡴⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⡴⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
-2 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
└────────────────────────────────────────┘
⠀0⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀clock (μs)⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀0.6⠀

```

"""
function (..) end
31 changes: 31 additions & 0 deletions lib/BloqadeWaveforms/test/docstrings.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using BloqadeWaveforms
using Test

function has_docstring(obj, sig::Type = Union{})
Docs.getdoc(obj, sig) === nothing || return true
binding = Docs.Binding(parentmodule(obj), nameof(obj))
for mod in Docs.modules
dict = Docs.meta(mod)
haskey(dict, binding) || continue
multidoc = dict[binding]
for msig in multidoc.order
sig <: msig && return true
end
end
return false
end



@testset "Docstring Present" begin
for symbol in names(BloqadeWaveforms)

obj = Base.eval(@__MODULE__, :(BloqadeWaveforms.$symbol))

typeof(obj) <: Union{Module} && continue

@testset "$symbol" begin
@test has_docstring(obj)
end
end
end
2 changes: 1 addition & 1 deletion lib/BloqadeWaveforms/test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Test

if "docstring" in ARGS
# include("docstrings.jl")
include("docstrings.jl")
exit()
end

Expand Down