text:
#TODO: this should be a macro
@inline get_symm_f(f::Array{Complex{Float64},1}, i::Int64) = (i < 0) ? conj(f[-i]) : f[i+1]
@inline get_symm_f(f::Array{Complex{Float64},2}, i::Int64) = (i < 0) ? conj(f[-i,:]) : f[i+1,:]
@inline get_symm_f(f::Array{Complex{Interval{Float64}},2}, i::Int64) = (i < 0) ? conj(f[-i,:]) : f[i+1,:]
store_symm_f(f::Array{T, 1}, range::UnitRange{Int64}) where T <: Number = [get_symm_f(f,i) for i in range]
store_symm_f(f::Array{T, 2}, range::UnitRange{Int64}) where T <: Number = [get_symm_f(f,i) for i in range]

# This function exploits, that χ(ν, ω) = χ*(-ν, -ω) and a storage of χ with only positive fermionic frequencies
# TODO: For now a fixed order of axis is assumed

function default_sum_range(mid_index::Int, lim_tuple::Tuple{Int,Int}) where T
    return union((mid_index - lim_tuple[2]):(mid_index - lim_tuple[1]), (mid_index + lim_tuple[1]):(mid_index + lim_tuple[2]))
end

function reduce_range(range::AbstractArray, red_prct::Float64)
    sub = floor(Int, length(range)/2 * red_prct)
    lst = maximum([last(range)-sub, ceil(Int,length(range)/2 + iseven(length(range)))])
    fst = minimum([first(range)+sub, ceil(Int,length(range)/2)])
    return fst:lst
end

split_n(str, n) = [str[(i-n+1):(i)] for i in n:n:length(str)]
split_n(str, n, len) = [str[(i-n+1):(i)] for i in n:n:len]

"""
    print 4 digits of the real part of `x`
"""
printr_s(x::Complex{Float64}) = round(real(x), digits=4)
printr_s(x::Float64) = round(x, digits=4)

function setup_LDGA(kGrid::ReducedKGrid, freqList::AbstractArray, mP::ModelParameters, sP::SimulationParameters, env::EnvironmentVars)
    fft_range = -(sP.n_iν+sP.n_iω):(sP.n_iν+sP.n_iω-1)
    in_file = env.inputVars
    if(myid() == 1)
        if env.inputDataType == "text"
            convert_from_fortran(sP, env, false)
            if env.loadAsymptotics
                readEDAsymptotics(env, mP)
            end
        elseif env.inputDataType == "parquet"
            convert_from_fortran_pq(sP, env)
            if env.loadAsymptotics
                readEDAsymptotics_parquet(env)
            end
        elseif env.inputDataType == "jld2"
            if env.loadAsymptotics
                readEDAsymptotics_julia(env)
            end
            in_file = env.inputDir*"/"*env.inputVars
        end
        f = load(in_file)
        Γch = f["Γch"]
        Γsp = f["Γsp"]
        χDMFTch = f["χDMFTch"]
        χDMFTsp = f["χDMFTsp"]
        gImp_in, Σ_loc = if haskey(f, "g0")
            gImp_in = copy(f["gImp"])
            g0 = copy(f["g0"])
            Σ_loc = Σ_Dyson(g0, gImp_in)
            gImp_in, Σ_loc
        else
            gImp_in = copy(f["gImp"])
            Σ_loc = copy(f["SigmaLoc"])
            gImp_in, Σ_loc
        end
        FUpDo_in = FUpDo_from_χDMFT(0.5 .* (χDMFTch - χDMFTsp), gImp_in, freqList, mP, sP)
        gImp_sym = store_symm_f(gImp_in, fft_range)
        gImp = reshape(gImp_sym, (length(gImp_sym),1))
        gLoc = G_from_Σ(Σ_loc, expandKArr(kGrid, kGrid.ϵkGrid)[:], fft_range, mP);
        gLoc_fft_in = flatten_2D(map(x->fft(reshape(x, gridshape(kGrid)...)), gLoc))
    end
    FUpDo = SharedArray{Complex{Float64},3}(size(FUpDo_in),pids=procs());copy!(FUpDo, FUpDo_in)
    gImp_fft = SharedArray{Complex{Float64}}(size(gImp),pids=procs());copy!(gImp_fft, gImp)
    gLoc_fft = SharedArray{Complex{Float64}}(size(gLoc_fft_in),pids=procs());copy!(gLoc_fft, gLoc_fft_in)
    χDMFTch_new = SharedArray{Complex{Float64},3}(size(χDMFTch),pids=procs());copy!(χDMFTch_new, χDMFTch)
    χDMFTsp_new = SharedArray{Complex{Float64},3}(size(χDMFTsp),pids=procs());copy!(χDMFTsp_new, χDMFTsp)
    Γch_new = SharedArray{Complex{Float64},3}(size(Γch),pids=procs());copy!(Γch_new, Γch)
    Γsp_new = SharedArray{Complex{Float64},3}(size(Γsp),pids=procs());copy!(Γsp_new, Γsp)
    @warn "TODO: check beta consistency, config <-> g0man, chi_dir <-> gamma dir"
    if env.loadAsymptotics
        asympt_vars = load(env.asymptVars)
        χchAsympt = asympt_vars["chi_ch_asympt"]
        χspAsympt = asympt_vars["chi_sp_asympt"]
    end
    #TODO: unify checks
    (sP.ωsum_type == :full && (sP.tc_type_b != :nothing)) && @warn "Full Sums combined with tail correction will probably yield wrong results due to border effects."
    sP.ωsum_type == :individual && println(stderr, "Individual ranges not tested yet")
    ((sP.n_iν < 30 || sP.n_iω < 15) && (sP.tc_type_f != :nothing)) && @warn "Improved sums usually require at least 30 positive fermionic frequencies"

    #TODO: this should no assume consecutive frequencies
    #νGrid = [(i,j) for i in 1:(2*sP.n_iω+1) for j in (1:2*sP.n_iν) .- trunc(Int64,sP.shift*(i-sP.n_iω-1)/2)]
    νGrid = Array{AbstractArray}(undef, 2*sP.n_iω+1);
    for i in 1:length(νGrid)
        νGrid[i] = (1:2*sP.n_iν) .- trunc(Int64,sP.shift*(i-1-sP.n_iω)/2)
    end
    #TODO: fix this! do not assume anything about freqGrid without reading from file

    sh_f = get_sum_helper(2*sP.n_iν, sP, :f)

    χLocsp_ω = sum_freq(χDMFTsp, [2,3], sh_f, mP.β)[:,1,1]
    χLocch_ω = sum_freq(χDMFTch, [2,3], sh_f, mP.β)[:,1,1]
    ωZero = sP.n_iω
    χLocsp_ω_tmp = deepcopy(χLocsp_ω)
    χLocch_ω_tmp = deepcopy(χLocch_ω)

    if sP.ω_smoothing == :full
        filter_MA!(χLocsp_ω[1:ωZero],3,χLocsp_ω[1:ωZero])
        filter_MA!(χLocsp_ω[ωZero:end],3,χLocsp_ω[ωZero:end])
        filter_MA!(χLocch_ω[1:ωZero],3,χLocch_ω[1:ωZero])
        filter_MA!(χLocch_ω[ωZero:end],3,χLocch_ω[ωZero:end])
        χLocsp_ω_tmp = deepcopy(χLocsp_ω)
        χLocch_ω_tmp = deepcopy(χLocch_ω)
    elseif sP.ω_smoothing == :range
        χLocsp_ω_tmp[1:ωZero]   = filter_MA(3,χLocsp_ω[1:ωZero])
        χLocsp_ω_tmp[ωZero:end] = filter_MA(3,χLocsp_ω[ωZero:end])
        χLocch_ω_tmp[1:ωZero]   = filter_MA(3,χLocch_ω[1:ωZero])
        χLocch_ω_tmp[ωZero:end] = filter_MA(3,χLocch_ω[ωZero:end])
    end

    usable_loc_sp = find_usable_interval(real(χLocsp_ω_tmp), sum_type=sP.ωsum_type)
    usable_loc_ch = find_usable_interval(real(χLocch_ω_tmp), sum_type=sP.ωsum_type)
    #if sP.tc_type_f != :nothing
    #    usable_loc_sp = reduce_range(usable_loc_sp, 1.0)
    #    usable_loc_ch = reduce_range(usable_loc_ch, 1.0)
    #end
    loc_range = intersect(usable_loc_sp, usable_loc_ch)
    if sP.ωsum_type == :common
        @info "setting usable ranges of sp and ch channel from $usable_loc_sp and $usable_loc_ch to the same range of $loc_range"
        usable_loc_ch = loc_range
        usable_loc_sp = loc_range
    end

    E_kin_ED, E_pot_ED = 0.0, 0.0
    if sP.tc_type_b == :coeffs
    if isfile(env.inputDir * "/gm_wim") && isfile(env.inputDir * "/hubb.andpar")
        @info "Computing kinetic energie for improved bosonic sums."
        iνₙ, GImp    = readGImp(env.inputDir * "/gm_wim", only_positive=true)
        ϵₖ, Vₖ, μ    = read_anderson_parameters(env.inputDir * "/hubb.andpar");
        E_kin_ED, E_pot_ED  = calc_E_ED(iνₙ[1:length(GImp)], ϵₖ, Vₖ, GImp, mP)
    else
        @warn "Could not find hubb.andpar and gm_wim for kinetic energy. proceding without improved bosonic sums!"
    end
    end

    sh_b_sp = get_sum_helper(usable_loc_sp, sP, :b)
    sh_b_ch = get_sum_helper(usable_loc_ch, sP, :b)

    χLocsp = sum_freq(χLocsp_ω[usable_loc_sp], [1], sh_b_sp, mP.β)[1]
    χLocch = sum_freq(χLocch_ω[usable_loc_ch], [1], sh_b_ch, mP.β)[1]

    impQ_sp = ImpurityQuantities(Γsp_new, χDMFTsp_new, χLocsp_ω, χLocsp, usable_loc_sp, [0,0,E_kin_ED])
    impQ_ch = ImpurityQuantities(Γch_new, χDMFTch_new, χLocch_ω, χLocch, usable_loc_ch, [0,0,E_kin_ED])

    χupup_ω = 0.5 * (χLocsp_ω + χLocch_ω)
    iωn = 1im .* 2 .* (-sP.n_iω:sP.n_iω)[loc_range] .* π ./ mP.β
    χupup_DMFT_ω_sub = subtract_tail(χupup_ω[loc_range], E_kin_ED, iωn)

    sh_b = get_sum_helper(loc_range, sP, :b)
    imp_density_pure = real(sum_freq(χupup_DMFT_ω_sub, [1], Naive(), mP.β, corr=-E_kin_ED*mP.β^2/12))
    imp_density = real(sum_freq(χupup_DMFT_ω_sub, [1], sh_b, mP.β, corr=-E_kin_ED*mP.β^2/12))

    @info """Inputs Read. Starting Computation.
      Local susceptibilities with ranges are:
      χLoc_sp($(impQ_sp.usable_ω)) = $(printr_s(impQ_sp.χ_loc)), χLoc_ch($(impQ_ch.usable_ω)) = $(printr_s(impQ_ch.χ_loc))
      sum χupup check (fit, tail sub, tail sub + fit, expected): $(0.5 .* real(χLocsp + χLocch)) ?≈? $(imp_density_pure) ?=? $(imp_density) ?≈? $(mP.n/2 * ( 1 - mP.n/2))"
      """
    return νGrid, sh_f, impQ_sp, impQ_ch, gImp_fft, gLoc_fft, Σ_loc, FUpDo, gImp, gLoc
end

function flatten_2D(arr)
    res = zeros(eltype(arr[1]),length(arr), length(arr[1]))
    for i in 1:length(arr)
        res[i,:] = arr[i][:]
    end
    return res
end

# ================== Noise Filter ==================

function filter_MA(m::Int, X::AbstractArray{T,1}) where T <: Number
    res = deepcopy(X)
    offset = trunc(Int,m/2)
    res[1+offset] = sum(@view X[1:m])/m
    for (ii,i) in enumerate((2+offset):(length(X)-offset))
        res[i] = res[i-1] + (X[m+ii] - X[ii])/m
    end
    return res
end

function filter_MA!(res::AbstractArray{T,1}, m::Int, X::AbstractArray{T,1}) where T <: Number
    offset = trunc(Int,m/2)
    res[1+offset] = sum(@view X[1:m])/m
    for (ii,i) in enumerate((2+offset):(length(X)-offset))
        res[i] = res[i-1] + (X[m+ii] - X[ii])/m
    end
    return res
end

function filter_KZ(m::Int, k::Int, X::AbstractArray{T,1}) where T <: Number
    res = filter_MA(m, X)
    for ki in 2:k
        res = filter_MA!(res, m, res)
    end
    return res
end

# ================== FFT + Intervals Workaround ==================
lo(arr::Array{Interval{Float64}}) = map(x->x.lo,arr)
hi(arr::Array{Interval{Float64}}) = map(x->x.hi,arr)
lo(arr::Array{Complex{Interval{Float64}}}) = map(x->x.lo,real.(arr)) .+ map(x->x.lo,imag.(arr)) .* im
hi(arr::Array{Complex{Interval{Float64}}}) = map(x->x.hi,real.(arr)) .+ map(x->x.hi,imag.(arr)) .* im
cmplx_interval(x::Tuple{Complex{Float64},Complex{Float64}}) = Complex(interval(minimum(real.(x)),maximum(real.(x))),
                                                                      interval(minimum(imag.(x)),maximum(imag.(x))))
AbstractFFTs.fft(arr::Array{Interval{Float64}}) = map(x->interval(minimum(x),maximum(x)),zip(fft(lo(arr)), fft(lo(arr))))
AbstractFFTs.fft(arr::Array{Complex{Interval{Float64}}}) = map(x->cmplx_interval(x),zip(fft(lo(arr)), fft(hi(arr))))
AbstractFFTs.ifft(arr::Array{Interval{Float64}}) = map(x->interval(minimum(x),maximum(x)),zip(ifft(lo(arr)), ifft(lo(arr))))
AbstractFFTs.ifft(arr::Array{Complex{Interval{Float64}}}) = map(x->cmplx_interval(x),zip(ifft(lo(arr)), ifft(hi(arr))))


text:
# Autogenerated wrapper script for flex_jll for aarch64-linux-musl
export flex, flexpp, libfl

JLLWrappers.@generate_wrapper_header("flex")
JLLWrappers.@declare_executable_product(flex)
JLLWrappers.@declare_executable_product(flexpp)
JLLWrappers.@declare_library_product(libfl, "libfl.so.2")
function __init__()
    JLLWrappers.@generate_init_header()
    JLLWrappers.@init_executable_product(
        flex,
        "bin/flex",
    )

    JLLWrappers.@init_executable_product(
        flexpp,
        "bin/flex++",
    )

    JLLWrappers.@init_library_product(
        libfl,
        "lib/libfl.so",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()

ext: jl


text:
#########################################################
#=
Code to compare a local vrs non-local invariant quadratic estimate.
Corresponds to Figures 1 in the paper.
Run this script with the command `include("make_figure_1.jl")` entered into the Julia REPL in this directory.
Run this script from the Julia command line in this directory.
This script saves figure1.pdf to the current directory.
To include figure1.pdf in the paper it must be copied to the directory paper/
=#
#########################################################

using NonstationaryPhase
using PyPlot

savefigures = true # set to `true` if you want the generated figures saved

# --- set grid geometry
const d_const = 1
const period_const = 2π
const nside_const  = 2^12

# ---- Matern parameters for Cϕϕ
const σϕ, ρϕ, νϕ = 0.03, 0.1*2π, 3.0

#  --- Matern parameters for the base spectral density Ck
const σ, ρ, ν = 1, 0.025, 2

####################################
#=
Define two instances of PhaseParms which carries all the parameters
for the locally stationary model and the non-local-model
=#
#####################################

# ---- local invariant model
parms = PhaseParms(d_const, period_const, nside_const)
parms.ηk[:]       =  parms.k
parms.Ck[:]       =  maternk(parms.k; ν=ν, ρ=ρ, σ=σ)
parms.C1k[:]      =  Array{Complex{Float64}, 1}[ im .* parms.ηk[1] .* parms.Ck ./  (2π) ^ (1/2) ]
parms.C2k[1,1][:] =  -abs2(parms.ηk[1]) .* parms.Ck ./ ((2π)^(1/2)) ./ factorial(2)
parms.Cϕϕk[:]     =  maternk(parms.k; ν=νϕ, ρ=ρϕ, σ=σϕ)
parms.CZZmk[:]    = parms.Ck[:]
parms.ξk[:]       = Array{Complex{Float64},1}[ ones(parms.k[1]) ]
parms.CZZmobsk[:] = parms.CZZmk + parms.CNNk
parms.CZZmobsk[parms.r .< 1]              = Inf
parms.CZZmobsk[parms.r .>= 0.9*parms.nyq] = Inf

# ---- non local invariant model
parmsNLI          = deepcopy(parms)
parmsNLI.C1k[:]   = map(abs, parms.C1k)
parmsNLI.C2k[:]   = -parms.C2k[:]

####################################
#
#  Bias and variance spectra for local and non-local invariant models
#
#####################################

# ---  approximate variance
varℓ      = (2/√(2π)) .* NonstationaryPhase.local_Aℓ(true,  parms)
tld_varℓ  = (2/√(2π)) .* NonstationaryPhase.local_Aℓ(false, parmsNLI)

# ---  exact second order bias spectrum
θ2biask     = NonstationaryPhase.local_θ2bias(true,  parms)
tld_θ2biask = NonstationaryPhase.local_θ2bias(false, parmsNLI)

####################################
#=
Plot and save
=#
#####################################

fig1 = figure(figsize = (11,4))
    plotrng = 1:200

    # bias, signal and variance for the local invariant model
    f1 = subplot(1,2,1)
    loglog(abs2(parms.k[1][plotrng]) .* parms.Cϕϕk[plotrng], "k:", label = "signal spectral density", linewidth = 3.0)
    loglog(abs2(parms.k[1][plotrng]) .* θ2biask[plotrng]     , "r--",label = "bias spectral density", linewidth = 2.0)
    loglog(abs2(parms.k[1][plotrng]) .* varℓ[plotrng]        , "g",label = "variance spectral density", linewidth = 2.0)
    legend(loc="best",fontsize = 10)
    xlabel("frequency")
    ylabel("spectral density")
    title("Local invariant model")

    # bias, signal and variance for the non-local-invariant model
    f2 = subplot(1,2,2, sharex=f1, sharey=f1)
    loglog(abs2(parms.k[1][plotrng]) .* parms.Cϕϕk[plotrng], "k:"  , label = "signal spectral density", linewidth = 3.0)
    loglog(abs2(parms.k[1][plotrng]) .* tld_θ2biask[plotrng] , "r--", label = "bias spectral density", linewidth = 2.0)
    loglog(abs2(parms.k[1][plotrng]) .* tld_varℓ[plotrng]    , "g",label = "variance spectral density", linewidth = 2.0)
    xlabel("frequency")
    ylabel("spectral density")
    title("Non local invariant model")
    axis("tight")

if savefigures

    fig1[:savefig]("figure1.pdf", dpi=300, bbox_inches="tight", transparent=true)
    plt[:close](fig1)

end

#= #######################################################
---- Take a look at the weights for both models
---- Notice that the non-local invariant models puts too much emphasis on a few high frequency terms.
-----In contrast the local invariant weights are nearly flat over a wide region
-----(this which improves Gaussianity of the estimate, for one thing)
-----Not included in the paper. Saved for reference later.
=#
if false
   function getweights(islocvar::Bool, ell, parms)
        mlt = islocvar ? -1 : 1
        δ_0 = 1/(parms.deltk ^ 1)
        # locally stationary weights w_locst_k
        Aℓ = NonstationaryPhase.local_Aℓ(islocvar, parms)
        C1k_ell = NonstationaryPhase.shiftfk_by_ω(parms.C1k[1], ell, parms)
        CZZmobsk_ell = circshift(parms.CZZmobsk, -ell)
        w_locst_k   = abs2( parms.ξk[1][ell].*(parms.C1k[1] + mlt * C1k_ell) )
        w_locst_k ./= parms.CZZmobsk
        w_locst_k ./= CZZmobsk_ell
        w_locst_k .*= real(Aℓ[ell])
        return w_locst_k
    end
    δ_0 = 1/(parms.deltk ^ 1)
    weightsk     = getweights(true,  30, parms)
    weightsNLIk  = getweights(false, 30, parmsNLI)
    figure()
    semilogy(parms.k[1]|> fftshift, real(weightsk) |> fftshift, label="locally invariant stationary weights")
    semilogy(parms.k[1]|> fftshift, real(weightsNLIk) |> fftshift, label="non locally invariant weights")
    axis("tight")
    @show sum(δ_0 .* weightsk ./ ((2π)^(1/2))  )
    @show sum(δ_0 .* weightsNLIk ./ ((2π)^(1/2))  )
end


text:
@doc raw"""
    align(a⃗, b⃗, [w])

Solve [Wahba's problem](https://en.wikipedia.org/wiki/Wahba%27s_problem),
finding a rotation that aligns the set of points `a⃗` to a corresponding set of
points `b⃗` by minimizing the distance between the first set and the rotated
second set.

Here, `a⃗` and `b⃗` must be equally sized arrays of `QuatVec`s.  If present, `w`
must be an equally sized array of real numbers; if not, it is taken to be 1.
We define the loss function
```math
L(ℛ) ≔ Σᵢ wᵢ ‖a⃗ᵢ - ℛ b⃗ᵢ‖²
```
where ``ℛ`` is a rotation operator, and return the quaternion corresponding to
the optimal ``ℛ`` that minimizes this function.

Note that it is possible that the points do not uniquely determine a rotation —
as when one or both sets of points is rotationally symmetric.  In that case, the
loss function ``L(ℛ)`` will still be minimized and the points will still be
optimally aligned by the output quaternion, but that quaternion will not be
unique.

# Notes

In their book [_Fundamentals of Spacecraft Attitude Determination and Control_
(2014)](https://doi.org/10.1007/978-1-4939-0802-8), Markley and Crassidis say
that "Davenport’s method remains the best method for solving Wahba’s problem".
This method provides the optimal quaternion as the dominant eigenvector (the one
with the largest eigenvalue) of a certain matrix.  We start by defining the
supplementary matrix
```math
S ≔ Σᵢ wᵢ a⃗ᵢ b⃗ᵢᵀ
```
and vector
```math
s⃗ ≔ \begin{bmatrix}
S₂₃-S₃₂ \\
S₃₁-S₁₃ \\
S₁₂-S₂₁
\end{bmatrix}.
```
Then the key matrix is
```math
M ≔ \begin{bmatrix}
S + Sᵀ - (\mathrm{tr}S)\, I₃ & s⃗ \\
s⃗ᵀ & \mathrm{tr}S
\end{bmatrix}
```
It is possible for this matrix to have degenerate eigenvalues, corresponding to
cases where the points do not uniquely determine the rotation, as described
above.

"""
function align(a⃗::AbstractArray{<:QuatVec}, b⃗::AbstractArray{<:QuatVec}, w::AbstractArray{<:Real})
    # This is Eq. (5.11) from Markley and Crassidis
    S = sum(w[i] * a⃗[i].vec * b⃗[i].vec' for i in eachindex(a⃗, b⃗, w))
    return _align_Wahba(S)
end

function align(a⃗::AbstractArray{<:QuatVec}, b⃗::AbstractArray{<:QuatVec})
    # This is Eq. (5.11) from Markley and Crassidis
    S = sum(a⃗[i].vec * b⃗[i].vec' for i in eachindex(a⃗, b⃗))
    return _align_Wahba(S)
end

function _align_Wahba(S)
    # This is Eq. (5.17) from Markley and Crassidis, modified to suit our
    # conventions by flipping the sign of ``z``, and moving the final dimension
    # to the first dimension.
    M = Symmetric([
            S[1,1]+S[2,2]+S[3,3]      S[3,2]-S[2,3]         S[1,3]-S[3,1]           S[2,1]-S[1,2]
                S[3,2]-S[2,3]      S[1,1]-S[2,2]-S[3,3]     S[1,2]+S[2,1]           S[1,3]+S[3,1]
                S[1,3]-S[3,1]         S[1,2]+S[2,1]      -S[1,1]+S[2,2]-S[3,3]      S[2,3]+S[3,2]
                S[2,1]-S[1,2]         S[1,3]+S[3,1]         S[2,3]+S[3,2]       -S[1,1]-S[2,2]+S[3,3]
    ])
    # This extracts the dominant eigenvector, and interprets it as a Rotor.  In
    # particular, note that the _last_ eigenvector output by `eigen` (the 4th)
    # has the largest eigenvalue.
    return Rotor(eigen(M, 4:4).vectors[:, 1]...)
end

@doc raw"""
    align(A, B, [w])

Find a `Rotor` that aligns the set of rotors `A` to a corresponding set `B` by
minimizing the distance between the first set and the rotated second set.

Here, `A` and `B` must be equally sized arrays of `AbstractQuaternion`s.  If
present, `w` must be an equally sized array of real numbers; if not, it is
taken to be 1.  We define the loss function
```math
L(R) ≔ Σᵢ wᵢ |Aᵢ - R Bᵢ|²
```
where ``R`` is a `Rotor`, and return the quaternion corresponding to the optimal
``R`` that minimizes this function.

Note that it is possible that the input data do not uniquely determine a rotor,
which will happen when sum below is zero.  When this happens, the result will
contain `NaN`s, but no error will be raised.  When the sum is very close to —
but not exactly — zero, the accuracy of the result will be limited.  However,
the loss function will not depend strongly on the result in that case.

Be aware that this function _is_ sensitive to the signs of the input
quaternions.  See the [`unflip`](@ref) function for one way to avoid problems
related to signs.

## Notes

We can ensure that the loss function is minimized by multiplying ``R`` by an
exponential, differentiating with respect to the argument of the exponential,
and setting that argument to 0.  This derivative should be 0 at the minimum.  We
have
```math
∂ⱼ Σᵢ wᵢ |Aᵢ - \exp[vⱼ] R Bᵢ|²  →  2 ⟨ eⱼ R Σᵢ wᵢ Bᵢ Āᵢ ⟩₀
```
where → denotes taking ``vⱼ→0``, the symbol ``⟨⟩₀`` denotes taking the scalar
part, and ``eⱼ`` is the unit quaternionic vector in the ``j`` direction.  The
only way for this quantity to be zero for each choice of ``j`` is if
```math
R Σᵢ wᵢ Bᵢ Āᵢ
```
is itself a pure scalar.  This, in turn, can only happen if either (1) the sum
is 0 or (2) if ``R`` is proportional to the _conjugate_ of the sum:
```math
R ∝ Σᵢ wᵢ Aᵢ B̄ᵢ
```
Now, since we want ``R`` to be a rotor, we simply define it to be the normalized
sum.

"""
function align(A, B, w)
    Rotor(sum(w[i] * A[i] * conj(B[i]) for i in eachindex(A, B, w)))
end

function align(A, B)
    Rotor(sum(A[i] * conj(B[i]) for i in eachindex(A, B)))
end


text:
alphadef = ConstDef(5. *pi/180)
hdef = ConstDef(0.)
udef = ConstDef(1.)
full_kinem = KinemDef(alphadef, hdef, udef)
pvt = 0.25
geometry = "FlatPlate"
lespc = [10.15;]

surf = TwoDSurf(geometry, pvt, full_kinem, lespc, rho=0.016)

@test typeof(surf)==TwoDSurf

curfield = TwoDFlowField()

@test typeof(curfield) == TwoDFlowField

dtstar = find_tstep(alphadef)

t_tot = 7.

nsteps = Int(round(t_tot/dtstar))+1

startflag = 0

writeflag = 0

writeInterval = t_tot/10.

delvort = delNone()

mat, surf, curfield = ldvmLin(surf, curfield, nsteps, dtstar,startflag, writeflag, writeInterval, delvort)

cl_expected = 2*pi*alphadef.amp
cl_out = mat[end,6]

@test abs(cl_expected - cl_out) < 0.5*cl_expected


text:
module SMACOF

using LinearAlgebra:Matrix
using Reexport
@reexport using DSTools
using LinearAlgebra
using Distances
using Printf

import Base:axes, getindex, setindex!, last, *, size
import LinearAlgebra:AbstractMatrix,diagind
import LinearAlgebra:issymmetric, mul!
import Statistics: sum, mean

include("cmds.jl")
include("helpers.jl")
include("procrustes.jl")
include("smacof.jl")
include("wda_smacof.jl")

export align, align!
export classical_scaling
export stress
export smacof
export wda_smacof

end


text:
using URIParser

enc = "http%3A%2F%2Ffoo%20bar%2F"

dcd = unescape(enc)

println(enc, " => ", dcd)

max_stars_repo_name: ethansaxenian/RosettaDecode

max_issues_repo_name: ethansaxenian/RosettaDecode

max_forks_repo_name: ethansaxenian/RosettaDecode


text:
#=
This file is auto-generated. Do not edit.
=#

#! format: off

"""
    mutable struct ActivePowerDroop <: ActivePowerControl
        Rp::Float64
        ωz::Float64
        P_ref::Float64
        ext::Dict{String, Any}
        states::Vector{Symbol}
        n_states::Int
    end

Parameters of an Active Power droop controller

# Arguments
- `Rp::Float64`: Droop Gain, validation range: `(0, nothing)`
- `ωz::Float64`: filter frequency cutoff, validation range: `(0, nothing)`
- `P_ref::Float64`: Reference Power Set-point, validation range: `(0, nothing)`
- `ext::Dict{String, Any}`
- `states::Vector{Symbol}`: The states of the ActivePowerDroop model are:
	θ_oc: Phase angle displacement of the inverter model,
	p_oc: Measured active power of the inverter model
- `n_states::Int`: ActivePowerDroop has two states
"""
mutable struct ActivePowerDroop <: ActivePowerControl
    "Droop Gain"
    Rp::Float64
    "filter frequency cutoff"
    ωz::Float64
    "Reference Power Set-point"
    P_ref::Float64
    ext::Dict{String, Any}
    "The states of the ActivePowerDroop model are:
	θ_oc: Phase angle displacement of the inverter model,
	p_oc: Measured active power of the inverter model"
    states::Vector{Symbol}
    "ActivePowerDroop has two states"
    n_states::Int
end

function ActivePowerDroop(Rp, ωz, P_ref=1.0, ext=Dict{String, Any}(), )
    ActivePowerDroop(Rp, ωz, P_ref, ext, [:θ_oc, :p_oc], 2, )
end

function ActivePowerDroop(; Rp, ωz, P_ref=1.0, ext=Dict{String, Any}(), states=[:θ_oc, :p_oc], n_states=2, )
    ActivePowerDroop(Rp, ωz, P_ref, ext, states, n_states, )
end

# Constructor for demo purposes; non-functional.
function ActivePowerDroop(::Nothing)
    ActivePowerDroop(;
        Rp=0,
        ωz=0,
        P_ref=0,
        ext=Dict{String, Any}(),
    )
end

"""Get [`ActivePowerDroop`](@ref) `Rp`."""
get_Rp(value::ActivePowerDroop) = value.Rp
"""Get [`ActivePowerDroop`](@ref) `ωz`."""
get_ωz(value::ActivePowerDroop) = value.ωz
"""Get [`ActivePowerDroop`](@ref) `P_ref`."""
get_P_ref(value::ActivePowerDroop) = value.P_ref
"""Get [`ActivePowerDroop`](@ref) `ext`."""
get_ext(value::ActivePowerDroop) = value.ext
"""Get [`ActivePowerDroop`](@ref) `states`."""
get_states(value::ActivePowerDroop) = value.states
"""Get [`ActivePowerDroop`](@ref) `n_states`."""
get_n_states(value::ActivePowerDroop) = value.n_states

"""Set [`ActivePowerDroop`](@ref) `Rp`."""
set_Rp!(value::ActivePowerDroop, val) = value.Rp = val
"""Set [`ActivePowerDroop`](@ref) `ωz`."""
set_ωz!(value::ActivePowerDroop, val) = value.ωz = val
"""Set [`ActivePowerDroop`](@ref) `P_ref`."""
set_P_ref!(value::ActivePowerDroop, val) = value.P_ref = val
"""Set [`ActivePowerDroop`](@ref) `ext`."""
set_ext!(value::ActivePowerDroop, val) = value.ext = val


text:
#== # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Description
#
#   Functions related Data and Time conversion.
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# References
#
#   [1] Vallado, D. A (2013). Fundamentals of Astrodynamics and Applications.
#       Microcosm Press, Hawthorn, CA, USA.
#
#   [2] https://quasar.as.utexas.edu/BillInfo/JulianDatesG.html
#
#   [3] https://support.microsoft.com/en-us/help/214019/method-to-determine-whether-a-year-is-a-leap-year
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Remarks
#
# Information about the Julian Day obtained from [2] (Accessed on 2018-04-11).
# ============================================================================
#
# The Julian Day Count is a uniform count of days from a remote epoch in the
# past (-4712 January 1, 12 hours Greenwich Mean Time (Julian proleptic
# Calendar) = 4713 BCE January 1, 12 hours GMT (Julian proleptic Calendar) =
# 4714 BCE November 24, 12 hours GMT (Gregorian proleptic Calendar)). At this
# instant, the Julian Day Number is 0. It is convenient for astronomers to use
# since it is not necessary to worry about odd numbers of days in a month,
# leap years, etc. Once you have the Julian Day Number of a particular date
# in history, it is easy to calculate time elapsed between it and any other
# Julian Day Number.
#
# The Julian Day Count has nothing to do with the Julian Calendar introduced by
# Julius Caesar. It is named for Julius Scaliger, the father of Josephus Justus
# Scaliger, who invented the concept. It can also be thought of as a logical
# follow-on to the old Egyptian civil calendar, which also used years of
# constant lengths.
#
# Scaliger chose the particular date in the remote past because it was before
# recorded history and because in that year, three important cycles coincided
# with their first year of the cycle: The 19-year Metonic Cycle, the 15-year
# Indiction Cycle (a Roman Taxation Cycle) and the 28-year Solar Cycle (the
# length of time for the old Julian Calendar to repeat exactly).
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ==#

export DatetoJD, JDtoDate

################################################################################
#                                  Functions
################################################################################

"""
    function DatetoJD(Y::Int, M::Int, D::Int, h::Int, m::Int, s::Number)

Convert a date represented using the Gregorian Calendar (Year = `y`, Month = `M`
(1-12), Day = `D`, Hour = `h` (0-24), minute = `m`, and second = `s`) to Julian
Day.

# Remarks

The algorithm was obtained from \\[2] (Accessed on 2018-04-11).

"""
function DatetoJD(Y::Int, M::Int, D::Int, h::Int, m::Int, s::Number)
    # Check the input.
    ( (M < 1) || (M > 12) ) && throw(ArgumentError("Invalid month. It must be an integer between 1 and 12."))
    ( (D < 1) || (D > 31) ) && throw(ArgumentError("Invalid day. It must be an integer between 1 and 31."))
    ( (h < 0) || (h > 23) ) && throw(ArgumentError("Invalid hour. It must be an integer between 0 and 23."))
    ( (m < 0) || (m > 59) ) && throw(ArgumentError("Invalid minute. It must be an integer between 0 and 59."))
    ( (s < 0) || (s > 60) ) && throw(ArgumentError("Invalid second. It must be an integer between 0 and 60."))

    # Check if the date is valid in terms of number of days in a month.
    if M == 2
        if is_leap_year(Y)
            (D > 29) && throw(ArgumentError("Wrong day number given the year and the month."))
        else
            (D > 28) && throw(ArgumentError("Wrong day number given the year and the month."))
        end
    elseif M in [4, 6, 9, 11]
        (D > 30) && throw(ArgumentError("Wrong day number given the year and the month."))
    end

    # If the month is January / February, then consider it as the 13rd / 14th
    # month of the last year.
    if (M == 1) || (M == 2)
        Y -= 1
        M += 12
    end

    a = div(Y,100)
    b = div(a,4)
    c = 2-a+b
    e = floor(Int,365.25*(Y+4716))
    f = floor(Int,30.6001*(M+1))

    # Compute the Julian Day considering the time of day.
    #
    # Notice that the algorithm in [2] always return the Julian day at 00:00
    # GMT.
    c+D+e+f-1524.5 + ((h*60 + m)*60 + s)/86400
end

"""
    function DatetoJD(date::Date)

Convert the date `date` to Julian Day.

"""
function DatetoJD(date::Date)
    return DatetoJD(Dates.year(date), Dates.month(date), Dates.day(date),
                    0, 0, 0)
end

"""
    function DatetoJD(dateTime::DateTime)

Convert the date and time `dateTime` to Julian Day.

"""
function DatetoJD(dateTime::DateTime)
    return DatetoJD(Dates.year(dateTime),
                    Dates.month(dateTime),
                    Dates.day(dateTime),
                    Dates.hour(dateTime),
                    Dates.minute(dateTime),
                    Dates.second(dateTime))
end

"""
    function JDtoDate([T,] JD::Number)

Convert a date represented in Julian Day `JD` to Gregorian Calendar. The
optional parameter `T` defines the return type. If `T` is omitted, then it
defaults to `Int`.

# Returns

If `T` is omitted or `Int`, then a tuple with the following data will be
returned:

* Year.
* Month (`1` => **January**, `2` => **February**, ...).
* Day.
* Hour (0 - 24).
* Minute (0 - 59).
* Second (0 - 59).

Notice that if `T` is `Int`, then the seconds field will be Integer. Otherwise,
it will be floating point.

If `T` is `Date`, then it will return the Julia structure `Date`. Notice that
the hours, minutes, and seconds will be neglected because the structure `Date`
does not handle them.

If `T` is `DateTime`, then it will return the Julia structure `DateTime`.

# Remarks

The algorithm was obtained from \\[2] (Accessed on 2018-04-11). In [2], there is
the following warning:

> Note: This method will not give dates accurately on the Gregorian Proleptic
> Calendar, i.e., the calendar you get by extending the Gregorian calendar
> backwards to years earlier than 1582. using the Gregorian leap year rules.
> In particular, the method fails if Y<400.

"""
function JDtoDate(JD::Number)
    Q = JD + 0.5
    Z = floor(Int, Q)
    W = div(Z - 1867216.25,36524.25)
    X = div(W,4)
    A = Z+1+W-X
    B = A+1524
    C = div(B-122.1,365.25)
    D = floor(Int,365.25*C)
    E = div(B-D,30.6001)
    F = floor(Int,30.6001*E)

    # In this case, `dayf` will have the fractional part of the day.
    dayf   = B-D-F+(Q-Z)
    monthf = (E-1 <= 12) ? E-1 : E-13
    yearf  = ( (monthf == 1) || (monthf == 2) ) ? C-4715 : C-4716

    # Get the hour, minute, and second from the day.
    hf = (dayf % 1)*24
    mf = (hf   % 1)*60
    sf = (mf   % 1)*60

    # Transform everything in integers.
    year  = floor(Int, yearf)
    month = floor(Int, monthf)
    day   = floor(Int, dayf)
    h     = floor(Int, hf)
    m     = floor(Int, mf)
    s     = sf

    # Return.
    (year, month, day, h, m, s)
end

function JDtoDate(::Type{Int}, JD::Number)
    (year, month, day, h, m, s) = JDtoDate(JD)

    # If the seconds are large than 59.5, then we must take care of the
    # rounding. In this case, we should advance a minute that can trigger an
    # advance in all the other parameters. The safest way here is to just call
    # the function `JDtoDate` again with an offset.

    if s >= 59.5
        Δs = 60.01 - s
        (year, month, day, h, m, s) = JDtoDate(JD + Δs/86400)
    end

    (year, month, day, h, m, round(Int,s))
end

function JDtoDate(::Type{Date}, JD::Number)
    (Y, M, D, ~, ~, ~) = JDtoDate(JD)
    Date(Y,M,D)
end

JDtoDate(::Type{DateTime}, JD::Number) = julian2datetime(JD)


text:
"Simulation Controls"
global NUMBER_OF_WALKS = 1000
global MAX_STEPS_PER_WALK = 3*1485604
global THICK_ENZ = true  # thin enzyme == false
const FLOW_BIAS = true
const CATALASE_ON_WALLS = false

"Solvent Diffusion Step Sizes (microns per 2.7 microseconds)"
const SECONDS_PER_STEP = 0.0000027077
const WATER_STEP_SIZE = 0.1
const PPD_STEP_SIZE = 0

function set_ENZ_STEP_SIZE(enz_step::AbstractFloat=0.005)
    global ENZ_STEP_SIZE = enz_step
    global STEP_SIZE_DICT = Dict("water" => WATER_STEP_SIZE,
                                "enz" => ENZ_STEP_SIZE,
                                "ppd" => 0)
    nothing
end
set_ENZ_STEP_SIZE()

"Sensor/Walls Coordinates"
const SENSOR_HALF_WIDTH = 0.5 * 280
const WALL_Y = 0

"Enzyme Layer Dimensions"
function update_enz()
    if THICK_ENZ
        global ENZYME_MAX_Y = 2
        global ENZYME_MAX_Y_FROM_WALL = 2
    else
        global ENZYME_MAX_Y_FROM_WALL = 0.2
        global ENZYME_MAX_Y = 0.2
    end
    nothing
end

function set_THICK_ENZ(trueorfalse::Bool=true)
    global THICK_ENZ = trueorfalse
    update_enz()
    nothing
end

const ENZYME_RIGHT_X = 150
const ENZYME_LEFT_X = -150
update_enz()

"Spawn Inside Enzyme Layer"
const BORDER_CORRECTION = 0.001
const SPAWN_LEFT_X = ENZYME_LEFT_X + BORDER_CORRECTION
const SPAWN_RIGHT_X = ENZYME_RIGHT_X - BORDER_CORRECTION
const SPAWN_ENZYME_MAX_Y = ENZYME_MAX_Y - BORDER_CORRECTION

"Enzyme-Water Corners"
const CORNER_CUT_IN_ENZ = ENZ_STEP_SIZE * sqrt(2) / 2
const CORNER_CUT_IN_WATER = WATER_STEP_SIZE * sqrt(2) / 2
# test set: locationbools here
const WATER_TO_ENZ_NORTHEAST = [ENZYME_RIGHT_X - CORNER_CUT_IN_ENZ, ENZYME_MAX_Y - CORNER_CUT_IN_ENZ]
const WATER_TO_ENZ_NORTHWEST = [ENZYME_LEFT_X + CORNER_CUT_IN_ENZ, ENZYME_MAX_Y - CORNER_CUT_IN_ENZ]
const ENZ_TO_WATER_NORTHEAST = [ENZYME_RIGHT_X + CORNER_CUT_IN_WATER, ENZYME_MAX_Y + CORNER_CUT_IN_WATER]
const ENZ_TO_WATER_NORTHWEST = [ENZYME_LEFT_X - CORNER_CUT_IN_WATER, ENZYME_MAX_Y + CORNER_CUT_IN_WATER]

"Escape Bound Limits"
const ESCAPE_X = 3 * ENZYME_RIGHT_X
const ESCAPE_Y = ESCAPE_X

"Safe Bound Limits"
const MARGIN_OF_COLLISION = 2 * WATER_STEP_SIZE
const SAFE_MIN_Y = ENZYME_MAX_Y + MARGIN_OF_COLLISION
const SAFE_MAX_Y = ESCAPE_Y - MARGIN_OF_COLLISION
const SAFE_MAX_X = ESCAPE_X - MARGIN_OF_COLLISION

max_stars_repo_name: s-y-wu/HMCResearchRandomWalks

max_issues_repo_name: s-y-wu/HMCResearchRandomWalks

max_forks_repo_name: s-y-wu/HMCResearchRandomWalks


text:
module ThreadingExperiments

using .Threads

include("utils.jl")

export onthread

end # module


text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: drs
using AWS.Compat
using AWS.UUIDs

"""
    create_replication_configuration_template(associate_default_security_group, bandwidth_throttling, create_public_ip, data_plane_routing, default_large_staging_disk_type, ebs_encryption, pit_policy, replication_server_instance_type, replication_servers_security_groups_ids, staging_area_subnet_id, staging_area_tags, use_dedicated_replication_server)
    create_replication_configuration_template(associate_default_security_group, bandwidth_throttling, create_public_ip, data_plane_routing, default_large_staging_disk_type, ebs_encryption, pit_policy, replication_server_instance_type, replication_servers_security_groups_ids, staging_area_subnet_id, staging_area_tags, use_dedicated_replication_server, params::Dict{String,<:Any})

Creates a new ReplicationConfigurationTemplate.

# Arguments
- `associate_default_security_group`: Whether to associate the default Elastic Disaster
  Recovery Security group with the Replication Configuration Template.
- `bandwidth_throttling`: Configure bandwidth throttling for the outbound data transfer
  rate of the Source Server in Mbps.
- `create_public_ip`: Whether to create a Public IP for the Recovery Instance by default.
- `data_plane_routing`: The data plane routing mechanism that will be used for replication.
- `default_large_staging_disk_type`: The Staging Disk EBS volume type to be used during
  replication.
- `ebs_encryption`: The type of EBS encryption to be used during replication.
- `pit_policy`: The Point in time (PIT) policy to manage snapshots taken during replication.
- `replication_server_instance_type`: The instance type to be used for the replication
  server.
- `replication_servers_security_groups_ids`: The security group IDs that will be used by
  the replication server.
- `staging_area_subnet_id`: The subnet to be used by the replication staging area.
- `staging_area_tags`: A set of tags to be associated with all resources created in the
  replication staging area: EC2 replication server, EBS volumes, EBS snapshots, etc.
- `use_dedicated_replication_server`: Whether to use a dedicated Replication Server in the
  replication staging area.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"ebsEncryptionKeyArn"`: The ARN of the EBS encryption key to be used during replication.
- `"tags"`: A set of tags to be associated with the Replication Configuration Template
  resource.
"""
function create_replication_configuration_template(
    associateDefaultSecurityGroup,
    bandwidthThrottling,
    createPublicIP,
    dataPlaneRouting,
    defaultLargeStagingDiskType,
    ebsEncryption,
    pitPolicy,
    replicationServerInstanceType,
    replicationServersSecurityGroupsIDs,
    stagingAreaSubnetId,
    stagingAreaTags,
    useDedicatedReplicationServer;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/CreateReplicationConfigurationTemplate",
        Dict{String,Any}(
            "associateDefaultSecurityGroup" => associateDefaultSecurityGroup,
            "bandwidthThrottling" => bandwidthThrottling,
            "createPublicIP" => createPublicIP,
            "dataPlaneRouting" => dataPlaneRouting,
            "defaultLargeStagingDiskType" => defaultLargeStagingDiskType,
            "ebsEncryption" => ebsEncryption,
            "pitPolicy" => pitPolicy,
            "replicationServerInstanceType" => replicationServerInstanceType,
            "replicationServersSecurityGroupsIDs" => replicationServersSecurityGroupsIDs,
            "stagingAreaSubnetId" => stagingAreaSubnetId,
            "stagingAreaTags" => stagingAreaTags,
            "useDedicatedReplicationServer" => useDedicatedReplicationServer,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_replication_configuration_template(
    associateDefaultSecurityGroup,
    bandwidthThrottling,
    createPublicIP,
    dataPlaneRouting,
    defaultLargeStagingDiskType,
    ebsEncryption,
    pitPolicy,
    replicationServerInstanceType,
    replicationServersSecurityGroupsIDs,
    stagingAreaSubnetId,
    stagingAreaTags,
    useDedicatedReplicationServer,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/CreateReplicationConfigurationTemplate",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "associateDefaultSecurityGroup" => associateDefaultSecurityGroup,
                    "bandwidthThrottling" => bandwidthThrottling,
                    "createPublicIP" => createPublicIP,
                    "dataPlaneRouting" => dataPlaneRouting,
                    "defaultLargeStagingDiskType" => defaultLargeStagingDiskType,
                    "ebsEncryption" => ebsEncryption,
                    "pitPolicy" => pitPolicy,
                    "replicationServerInstanceType" => replicationServerInstanceType,
                    "replicationServersSecurityGroupsIDs" =>
                        replicationServersSecurityGroupsIDs,
                    "stagingAreaSubnetId" => stagingAreaSubnetId,
                    "stagingAreaTags" => stagingAreaTags,
                    "useDedicatedReplicationServer" => useDedicatedReplicationServer,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_job(job_id)
    delete_job(job_id, params::Dict{String,<:Any})

Deletes a single Job by ID.

# Arguments
- `job_id`: The ID of the Job to be deleted.

"""
function delete_job(jobID; aws_config::AbstractAWSConfig=global_aws_config())
    return drs(
        "POST",
        "/DeleteJob",
        Dict{String,Any}("jobID" => jobID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_job(
    jobID, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/DeleteJob",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("jobID" => jobID), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_recovery_instance(recovery_instance_id)
    delete_recovery_instance(recovery_instance_id, params::Dict{String,<:Any})

Deletes a single Recovery Instance by ID. This deletes the Recovery Instance resource from
Elastic Disaster Recovery. The Recovery Instance must be disconnected first in order to
delete it.

# Arguments
- `recovery_instance_id`: RThe ID of the Recovery Instance to be deleted.

"""
function delete_recovery_instance(
    recoveryInstanceID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/DeleteRecoveryInstance",
        Dict{String,Any}("recoveryInstanceID" => recoveryInstanceID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_recovery_instance(
    recoveryInstanceID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/DeleteRecoveryInstance",
        Dict{String,Any}(
            mergewith(
                _merge, Dict{String,Any}("recoveryInstanceID" => recoveryInstanceID), params
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_replication_configuration_template(replication_configuration_template_id)
    delete_replication_configuration_template(replication_configuration_template_id, params::Dict{String,<:Any})

Deletes a single Replication Configuration Template by ID

# Arguments
- `replication_configuration_template_id`: The ID of the Replication Configuration Template
  to be deleted.

"""
function delete_replication_configuration_template(
    replicationConfigurationTemplateID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/DeleteReplicationConfigurationTemplate",
        Dict{String,Any}(
            "replicationConfigurationTemplateID" => replicationConfigurationTemplateID
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_replication_configuration_template(
    replicationConfigurationTemplateID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/DeleteReplicationConfigurationTemplate",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "replicationConfigurationTemplateID" =>
                        replicationConfigurationTemplateID,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_source_server(source_server_id)
    delete_source_server(source_server_id, params::Dict{String,<:Any})

Deletes a single Source Server by ID. The Source Server must be disconnected first.

# Arguments
- `source_server_id`: The ID of the Source Server to be deleted.

"""
function delete_source_server(
    sourceServerID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/DeleteSourceServer",
        Dict{String,Any}("sourceServerID" => sourceServerID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_source_server(
    sourceServerID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/DeleteSourceServer",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("sourceServerID" => sourceServerID), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_job_log_items(job_id)
    describe_job_log_items(job_id, params::Dict{String,<:Any})

Retrieves a detailed Job log with pagination.

# Arguments
- `job_id`: The ID of the Job for which Job log items will be retrieved.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Maximum number of Job log items to retrieve.
- `"nextToken"`: The token of the next Job log items to retrieve.
"""
function describe_job_log_items(jobID; aws_config::AbstractAWSConfig=global_aws_config())
    return drs(
        "POST",
        "/DescribeJobLogItems",
        Dict{String,Any}("jobID" => jobID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_job_log_items(
    jobID, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/DescribeJobLogItems",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("jobID" => jobID), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_jobs(filters)
    describe_jobs(filters, params::Dict{String,<:Any})

Returns a list of Jobs. Use the JobsID and fromDate and toDate filters to limit which jobs
are returned. The response is sorted by creationDataTime - latest date first. Jobs are
created by the StartRecovery, TerminateRecoveryInstances and StartFailbackLaunch APIs. Jobs
are also created by DiagnosticLaunch and TerminateDiagnosticInstances, which are APIs
available only to *Support* and only used in response to relevant support tickets.

# Arguments
- `filters`: A set of filters by which to return Jobs.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Maximum number of Jobs to retrieve.
- `"nextToken"`: The token of the next Job to retrieve.
"""
function describe_jobs(filters; aws_config::AbstractAWSConfig=global_aws_config())
    return drs(
        "POST",
        "/DescribeJobs",
        Dict{String,Any}("filters" => filters);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_jobs(
    filters, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/DescribeJobs",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("filters" => filters), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_recovery_instances(filters)
    describe_recovery_instances(filters, params::Dict{String,<:Any})

Lists all Recovery Instances or multiple Recovery Instances by ID.

# Arguments
- `filters`: A set of filters by which to return Recovery Instances.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Maximum number of Recovery Instances to retrieve.
- `"nextToken"`: The token of the next Recovery Instance to retrieve.
"""
function describe_recovery_instances(
    filters; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/DescribeRecoveryInstances",
        Dict{String,Any}("filters" => filters);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_recovery_instances(
    filters, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/DescribeRecoveryInstances",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("filters" => filters), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_recovery_snapshots(source_server_id)
    describe_recovery_snapshots(source_server_id, params::Dict{String,<:Any})

Lists all Recovery Snapshots for a single Source Server.

# Arguments
- `source_server_id`: Filter Recovery Snapshots by Source Server ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"filters"`: A set of filters by which to return Recovery Snapshots.
- `"maxResults"`: Maximum number of Recovery Snapshots to retrieve.
- `"nextToken"`: The token of the next Recovery Snapshot to retrieve.
- `"order"`: The sorted ordering by which to return Recovery Snapshots.
"""
function describe_recovery_snapshots(
    sourceServerID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/DescribeRecoverySnapshots",
        Dict{String,Any}("sourceServerID" => sourceServerID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_recovery_snapshots(
    sourceServerID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/DescribeRecoverySnapshots",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("sourceServerID" => sourceServerID), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_replication_configuration_templates(replication_configuration_template_ids)
    describe_replication_configuration_templates(replication_configuration_template_ids, params::Dict{String,<:Any})

Lists all ReplicationConfigurationTemplates, filtered by Source Server IDs.

# Arguments
- `replication_configuration_template_ids`: The IDs of the Replication Configuration
  Templates to retrieve. An empty list means all Replication Configuration Templates.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Maximum number of Replication Configuration Templates to retrieve.
- `"nextToken"`: The token of the next Replication Configuration Template to retrieve.
"""
function describe_replication_configuration_templates(
    replicationConfigurationTemplateIDs; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/DescribeReplicationConfigurationTemplates",
        Dict{String,Any}(
            "replicationConfigurationTemplateIDs" => replicationConfigurationTemplateIDs
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_replication_configuration_templates(
    replicationConfigurationTemplateIDs,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/DescribeReplicationConfigurationTemplates",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "replicationConfigurationTemplateIDs" =>
                        replicationConfigurationTemplateIDs,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_source_servers(filters)
    describe_source_servers(filters, params::Dict{String,<:Any})

Lists all Source Servers or multiple Source Servers filtered by ID.

# Arguments
- `filters`: A set of filters by which to return Source Servers.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Maximum number of Source Servers to retrieve.
- `"nextToken"`: The token of the next Source Server to retrieve.
"""
function describe_source_servers(filters; aws_config::AbstractAWSConfig=global_aws_config())
    return drs(
        "POST",
        "/DescribeSourceServers",
        Dict{String,Any}("filters" => filters);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_source_servers(
    filters, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/DescribeSourceServers",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("filters" => filters), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    disconnect_recovery_instance(recovery_instance_id)
    disconnect_recovery_instance(recovery_instance_id, params::Dict{String,<:Any})

Disconnect a Recovery Instance from Elastic Disaster Recovery. Data replication is stopped
immediately. All AWS resources created by Elastic Disaster Recovery for enabling the
replication of the Recovery Instance will be terminated / deleted within 90 minutes. If the
agent on the Recovery Instance has not been prevented from communicating with the Elastic
Disaster Recovery service, then it will receive a command to uninstall itself (within
approximately 10 minutes). The following properties of the Recovery Instance will be
changed immediately: dataReplicationInfo.dataReplicationState will be set to DISCONNECTED;
The totalStorageBytes property for each of dataReplicationInfo.replicatedDisks will be set
to zero; dataReplicationInfo.lagDuration and dataReplicationInfo.lagDuration will be
nullified.

# Arguments
- `recovery_instance_id`: The ID of the Recovery Instance to disconnect.

"""
function disconnect_recovery_instance(
    recoveryInstanceID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/DisconnectRecoveryInstance",
        Dict{String,Any}("recoveryInstanceID" => recoveryInstanceID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function disconnect_recovery_instance(
    recoveryInstanceID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/DisconnectRecoveryInstance",
        Dict{String,Any}(
            mergewith(
                _merge, Dict{String,Any}("recoveryInstanceID" => recoveryInstanceID), params
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    disconnect_source_server(source_server_id)
    disconnect_source_server(source_server_id, params::Dict{String,<:Any})

Disconnects a specific Source Server from Elastic Disaster Recovery. Data replication is
stopped immediately. All AWS resources created by Elastic Disaster Recovery for enabling
the replication of the Source Server will be terminated / deleted within 90 minutes. You
cannot disconnect a Source Server if it has a Recovery Instance. If the agent on the Source
Server has not been prevented from communicating with the Elastic Disaster Recovery
service, then it will receive a command to uninstall itself (within approximately 10
minutes). The following properties of the SourceServer will be changed immediately:
dataReplicationInfo.dataReplicationState will be set to DISCONNECTED; The totalStorageBytes
property for each of dataReplicationInfo.replicatedDisks will be set to zero;
dataReplicationInfo.lagDuration and dataReplicationInfo.lagDuration will be nullified.

# Arguments
- `source_server_id`: The ID of the Source Server to disconnect.

"""
function disconnect_source_server(
    sourceServerID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/DisconnectSourceServer",
        Dict{String,Any}("sourceServerID" => sourceServerID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function disconnect_source_server(
    sourceServerID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/DisconnectSourceServer",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("sourceServerID" => sourceServerID), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_failback_replication_configuration(recovery_instance_id)
    get_failback_replication_configuration(recovery_instance_id, params::Dict{String,<:Any})

Lists all Failback ReplicationConfigurations, filtered by Recovery Instance ID.

# Arguments
- `recovery_instance_id`: The ID of the Recovery Instance whose failback replication
  configuration should be returned.

"""
function get_failback_replication_configuration(
    recoveryInstanceID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/GetFailbackReplicationConfiguration",
        Dict{String,Any}("recoveryInstanceID" => recoveryInstanceID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_failback_replication_configuration(
    recoveryInstanceID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/GetFailbackReplicationConfiguration",
        Dict{String,Any}(
            mergewith(
                _merge, Dict{String,Any}("recoveryInstanceID" => recoveryInstanceID), params
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_launch_configuration(source_server_id)
    get_launch_configuration(source_server_id, params::Dict{String,<:Any})

Gets a LaunchConfiguration, filtered by Source Server IDs.

# Arguments
- `source_server_id`: The ID of the Source Server that we want to retrieve a Launch
  Configuration for.

"""
function get_launch_configuration(
    sourceServerID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/GetLaunchConfiguration",
        Dict{String,Any}("sourceServerID" => sourceServerID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_launch_configuration(
    sourceServerID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/GetLaunchConfiguration",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("sourceServerID" => sourceServerID), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_replication_configuration(source_server_id)
    get_replication_configuration(source_server_id, params::Dict{String,<:Any})

Gets a ReplicationConfiguration, filtered by Source Server ID.

# Arguments
- `source_server_id`: The ID of the Source Serve for this Replication Configuration.r

"""
function get_replication_configuration(
    sourceServerID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/GetReplicationConfiguration",
        Dict{String,Any}("sourceServerID" => sourceServerID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_replication_configuration(
    sourceServerID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/GetReplicationConfiguration",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("sourceServerID" => sourceServerID), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    initialize_service()
    initialize_service(params::Dict{String,<:Any})

Initialize Elastic Disaster Recovery.

"""
function initialize_service(; aws_config::AbstractAWSConfig=global_aws_config())
    return drs(
        "POST", "/InitializeService"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function initialize_service(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/InitializeService",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_tags_for_resource(resource_arn)
    list_tags_for_resource(resource_arn, params::Dict{String,<:Any})

List all tags for your Elastic Disaster Recovery resources.

# Arguments
- `resource_arn`: The ARN of the resource whose tags should be returned.

"""
function list_tags_for_resource(
    resourceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "GET",
        "/tags/$(resourceArn)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_tags_for_resource(
    resourceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "GET",
        "/tags/$(resourceArn)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    retry_data_replication(source_server_id)
    retry_data_replication(source_server_id, params::Dict{String,<:Any})

Causes the data replication initiation sequence to begin immediately upon next Handshake
for the specified Source Server ID, regardless of when the previous initiation started.
This command will work only if the Source Server is stalled or is in a DISCONNECTED or
STOPPED state.

# Arguments
- `source_server_id`: The ID of the Source Server whose data replication should be retried.

"""
function retry_data_replication(
    sourceServerID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/RetryDataReplication",
        Dict{String,Any}("sourceServerID" => sourceServerID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function retry_data_replication(
    sourceServerID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/RetryDataReplication",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("sourceServerID" => sourceServerID), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    start_failback_launch(recovery_instance_ids)
    start_failback_launch(recovery_instance_ids, params::Dict{String,<:Any})

Initiates a Job for launching the machine that is being failed back to from the specified
Recovery Instance. This will run conversion on the failback client and will reboot your
machine, thus completing the failback process.

# Arguments
- `recovery_instance_ids`: The IDs of the Recovery Instance whose failback launch we want
  to request.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"tags"`: The tags to be associated with the failback launch Job.
"""
function start_failback_launch(
    recoveryInstanceIDs; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/StartFailbackLaunch",
        Dict{String,Any}("recoveryInstanceIDs" => recoveryInstanceIDs);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function start_failback_launch(
    recoveryInstanceIDs,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/StartFailbackLaunch",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("recoveryInstanceIDs" => recoveryInstanceIDs),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    start_recovery(source_servers)
    start_recovery(source_servers, params::Dict{String,<:Any})

Launches Recovery Instances for the specified Source Servers. For each Source Server you
may choose a point in time snapshot to launch from, or use an on demand snapshot.

# Arguments
- `source_servers`: The Source Servers that we want to start a Recovery Job for.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"isDrill"`: Whether this Source Server Recovery operation is a drill or not.
- `"tags"`: The tags to be associated with the Recovery Job.
"""
function start_recovery(sourceServers; aws_config::AbstractAWSConfig=global_aws_config())
    return drs(
        "POST",
        "/StartRecovery",
        Dict{String,Any}("sourceServers" => sourceServers);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function start_recovery(
    sourceServers,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/StartRecovery",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("sourceServers" => sourceServers), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    stop_failback(recovery_instance_id)
    stop_failback(recovery_instance_id, params::Dict{String,<:Any})

Stops the failback process for a specified Recovery Instance. This changes the Failback
State of the Recovery Instance back to FAILBACK_NOT_STARTED.

# Arguments
- `recovery_instance_id`: The ID of the Recovery Instance we want to stop failback for.

"""
function stop_failback(
    recoveryInstanceID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/StopFailback",
        Dict{String,Any}("recoveryInstanceID" => recoveryInstanceID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function stop_failback(
    recoveryInstanceID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/StopFailback",
        Dict{String,Any}(
            mergewith(
                _merge, Dict{String,Any}("recoveryInstanceID" => recoveryInstanceID), params
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    tag_resource(resource_arn, tags)
    tag_resource(resource_arn, tags, params::Dict{String,<:Any})

Adds or overwrites only the specified tags for the specified Elastic Disaster Recovery
resource or resources. When you specify an existing tag key, the value is overwritten with
the new value. Each resource can have a maximum of 50 tags. Each tag consists of a key and
optional value.

# Arguments
- `resource_arn`: ARN of the resource for which tags are to be added or updated.
- `tags`: Array of tags to be added or updated.

"""
function tag_resource(resourceArn, tags; aws_config::AbstractAWSConfig=global_aws_config())
    return drs(
        "POST",
        "/tags/$(resourceArn)",
        Dict{String,Any}("tags" => tags);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function tag_resource(
    resourceArn,
    tags,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/tags/$(resourceArn)",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("tags" => tags), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    terminate_recovery_instances(recovery_instance_ids)
    terminate_recovery_instances(recovery_instance_ids, params::Dict{String,<:Any})

Initiates a Job for terminating the EC2 resources associated with the specified Recovery
Instances, and then will delete the Recovery Instances from the Elastic Disaster Recovery
service.

# Arguments
- `recovery_instance_ids`: The IDs of the Recovery Instances that should be terminated.

"""
function terminate_recovery_instances(
    recoveryInstanceIDs; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/TerminateRecoveryInstances",
        Dict{String,Any}("recoveryInstanceIDs" => recoveryInstanceIDs);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function terminate_recovery_instances(
    recoveryInstanceIDs,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/TerminateRecoveryInstances",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("recoveryInstanceIDs" => recoveryInstanceIDs),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    untag_resource(resource_arn, tag_keys)
    untag_resource(resource_arn, tag_keys, params::Dict{String,<:Any})

Deletes the specified set of tags from the specified set of Elastic Disaster Recovery
resources.

# Arguments
- `resource_arn`: ARN of the resource for which tags are to be removed.
- `tag_keys`: Array of tags to be removed.

"""
function untag_resource(
    resourceArn, tagKeys; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "DELETE",
        "/tags/$(resourceArn)",
        Dict{String,Any}("tagKeys" => tagKeys);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function untag_resource(
    resourceArn,
    tagKeys,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "DELETE",
        "/tags/$(resourceArn)",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("tagKeys" => tagKeys), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_failback_replication_configuration(recovery_instance_id)
    update_failback_replication_configuration(recovery_instance_id, params::Dict{String,<:Any})

Allows you to update the failback replication configuration of a Recovery Instance by ID.

# Arguments
- `recovery_instance_id`: The ID of the Recovery Instance.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"bandwidthThrottling"`: Configure bandwidth throttling for the outbound data transfer
  rate of the Recovery Instance in Mbps.
- `"name"`: The name of the Failback Replication Configuration.
- `"usePrivateIP"`: Whether to use Private IP for the failback replication of the Recovery
  Instance.
"""
function update_failback_replication_configuration(
    recoveryInstanceID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/UpdateFailbackReplicationConfiguration",
        Dict{String,Any}("recoveryInstanceID" => recoveryInstanceID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_failback_replication_configuration(
    recoveryInstanceID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/UpdateFailbackReplicationConfiguration",
        Dict{String,Any}(
            mergewith(
                _merge, Dict{String,Any}("recoveryInstanceID" => recoveryInstanceID), params
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_launch_configuration(source_server_id)
    update_launch_configuration(source_server_id, params::Dict{String,<:Any})

Updates a LaunchConfiguration by Source Server ID.

# Arguments
- `source_server_id`: The ID of the Source Server that we want to retrieve a Launch
  Configuration for.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"copyPrivateIp"`: Whether we should copy the Private IP of the Source Server to the
  Recovery Instance.
- `"copyTags"`: Whether we want to copy the tags of the Source Server to the EC2 machine of
  the Recovery Instance.
- `"launchDisposition"`: The state of the Recovery Instance in EC2 after the recovery
  operation.
- `"licensing"`: The licensing configuration to be used for this launch configuration.
- `"name"`: The name of the launch configuration.
- `"targetInstanceTypeRightSizingMethod"`: Whether Elastic Disaster Recovery should try to
  automatically choose the instance type that best matches the OS, CPU, and RAM of your
  Source Server.
"""
function update_launch_configuration(
    sourceServerID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/UpdateLaunchConfiguration",
        Dict{String,Any}("sourceServerID" => sourceServerID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_launch_configuration(
    sourceServerID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/UpdateLaunchConfiguration",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("sourceServerID" => sourceServerID), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_replication_configuration(source_server_id)
    update_replication_configuration(source_server_id, params::Dict{String,<:Any})

Allows you to update a ReplicationConfiguration by Source Server ID.

# Arguments
- `source_server_id`: The ID of the Source Server for this Replication Configuration.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"associateDefaultSecurityGroup"`: Whether to associate the default Elastic Disaster
  Recovery Security group with the Replication Configuration.
- `"bandwidthThrottling"`: Configure bandwidth throttling for the outbound data transfer
  rate of the Source Server in Mbps.
- `"createPublicIP"`: Whether to create a Public IP for the Recovery Instance by default.
- `"dataPlaneRouting"`: The data plane routing mechanism that will be used for replication.
- `"defaultLargeStagingDiskType"`: The Staging Disk EBS volume type to be used during
  replication.
- `"ebsEncryption"`: The type of EBS encryption to be used during replication.
- `"ebsEncryptionKeyArn"`: The ARN of the EBS encryption key to be used during replication.
- `"name"`: The name of the Replication Configuration.
- `"pitPolicy"`: The Point in time (PIT) policy to manage snapshots taken during
  replication.
- `"replicatedDisks"`: The configuration of the disks of the Source Server to be replicated.
- `"replicationServerInstanceType"`: The instance type to be used for the replication
  server.
- `"replicationServersSecurityGroupsIDs"`: The security group IDs that will be used by the
  replication server.
- `"stagingAreaSubnetId"`: The subnet to be used by the replication staging area.
- `"stagingAreaTags"`: A set of tags to be associated with all resources created in the
  replication staging area: EC2 replication server, EBS volumes, EBS snapshots, etc.
- `"useDedicatedReplicationServer"`: Whether to use a dedicated Replication Server in the
  replication staging area.
"""
function update_replication_configuration(
    sourceServerID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/UpdateReplicationConfiguration",
        Dict{String,Any}("sourceServerID" => sourceServerID);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_replication_configuration(
    sourceServerID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/UpdateReplicationConfiguration",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("sourceServerID" => sourceServerID), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_replication_configuration_template(replication_configuration_template_id)
    update_replication_configuration_template(replication_configuration_template_id, params::Dict{String,<:Any})

Updates a ReplicationConfigurationTemplate by ID.

# Arguments
- `replication_configuration_template_id`: The Replication Configuration Template ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"arn"`: The Replication Configuration Template ARN.
- `"associateDefaultSecurityGroup"`: Whether to associate the default Elastic Disaster
  Recovery Security group with the Replication Configuration Template.
- `"bandwidthThrottling"`: Configure bandwidth throttling for the outbound data transfer
  rate of the Source Server in Mbps.
- `"createPublicIP"`: Whether to create a Public IP for the Recovery Instance by default.
- `"dataPlaneRouting"`: The data plane routing mechanism that will be used for replication.
- `"defaultLargeStagingDiskType"`: The Staging Disk EBS volume type to be used during
  replication.
- `"ebsEncryption"`: The type of EBS encryption to be used during replication.
- `"ebsEncryptionKeyArn"`: The ARN of the EBS encryption key to be used during replication.
- `"pitPolicy"`: The Point in time (PIT) policy to manage snapshots taken during
  replication.
- `"replicationServerInstanceType"`: The instance type to be used for the replication
  server.
- `"replicationServersSecurityGroupsIDs"`: The security group IDs that will be used by the
  replication server.
- `"stagingAreaSubnetId"`: The subnet to be used by the replication staging area.
- `"stagingAreaTags"`: A set of tags to be associated with all resources created in the
  replication staging area: EC2 replication server, EBS volumes, EBS snapshots, etc.
- `"useDedicatedReplicationServer"`: Whether to use a dedicated Replication Server in the
  replication staging area.
"""
function update_replication_configuration_template(
    replicationConfigurationTemplateID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return drs(
        "POST",
        "/UpdateReplicationConfigurationTemplate",
        Dict{String,Any}(
            "replicationConfigurationTemplateID" => replicationConfigurationTemplateID
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_replication_configuration_template(
    replicationConfigurationTemplateID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return drs(
        "POST",
        "/UpdateReplicationConfigurationTemplate",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "replicationConfigurationTemplateID" =>
                        replicationConfigurationTemplateID,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

include("model_AccessUri.jl")
include("model_AccessUriOutput.jl")
include("model_AccessUriRaw.jl")
include("model_ApiError.jl")
include("model_ApiErrorBase.jl")
include("model_CreationData.jl")
include("model_DiskList.jl")
include("model_DiskProperties.jl")
include("model_DiskSku.jl")
include("model_DiskUpdateProperties.jl")
include("model_EncryptionSettings.jl")
include("model_GrantAccessData.jl")
include("model_ImageDiskReference.jl")
include("model_InnerError.jl")
include("model_KeyVaultAndKeyReference.jl")
include("model_KeyVaultAndSecretReference.jl")
include("model_OperationStatusResponse.jl")
include("model_Resource.jl")
include("model_ResourceUpdate.jl")
include("model_SnapshotList.jl")
include("model_SourceVault.jl")
include("model_Disk.jl")
include("model_DiskUpdate.jl")
include("model_Snapshot.jl")
include("model_SnapshotUpdate.jl")


text:
"""
    mle(model, θ, vc=" ")

Maximum likelihood estimation.

* model should be a function that gives the vector of log likelihoods of
the observations
* θ is the parameter vector
* vc is the method for computing the variance, default is sandwich
* execute mleresults() for an example, or edit(mleresults,()) to see the code.

"""
function mle(model, θ, vc=1)
    avg_obj = θ -> -mean(vec(model(θ))) # average log likelihood
    thetahat, objvalue, converged = fminunc(avg_obj, θ) # do the minimization of -logL
    objvalue = -objvalue
    obj = θ -> vec(model(θ)) # unaveraged log likelihood
    n = size(obj(θ),1) # how many observations?
    scorecontrib = Calculus.jacobian(obj, vec(thetahat), :central)
    I = cov(scorecontrib)
    J = Calculus.hessian(avg_obj, vec(thetahat), :central)
    Jinv = inv(J)
    if vc==2
        V = Jinv/n      # other possibilities
    elseif vc==3
        V = inv(I)/n
    else
        V= Jinv*I*Jinv/n # sandwich form is preferred
    end
    return thetahat, objvalue, V, converged
end

function mle()
    println("mle(), with no arguments, runs mleresults(), which show usage")
    mleresults()
end

max_stars_repo_name: manuelmontesinos/Econometrics

max_issues_repo_name: manuelmontesinos/Econometrics

max_forks_repo_name: manuelmontesinos/Econometrics


text:
#! /usr/bin/julia
#! /mnt/d/p/Julia/juliaLinux/bin/julia
#PATH=/mnt/d/p/Julia/juliaLinux/bin:$PATH
using Statistics
using Printf
using Dates
Base.MainInclude.include("./RawFileofflineProc/BaseLib.jl")
# Base.MainInclude.include("RawFileofflineProc/interface.jl") # 如果需要适配不同的算法来分析相应文件，需要修改 intrface.jl 中包含的算法库
Base.MainInclude.include("./fileFind/filesfind.jl")
Base.MainInclude.include( "./RawFileofflineProc/ReadFiberData.jl")

Base.MainInclude.include( "./AlarmAnalyssys/AlarmPro/C01-RAW3AlgEntryRT.jl")
#####################Cfgs ##################################################
fileRawDataChannel = Channel(300)
rootdir = "../tem/cTemdata"

# rootdir = "\\tem\\cTemdata\\" #windows
rootdir = "./cTemdata" # linux

dt= "20190212"
startTime = dt * "131813"
endTime   =   dt * "134826"
startTime = ""
endTime   =  ""
##################### ##################################################

Base.@ccallable function julia_main1(ARGS::Vector{String})::Cint
    global fileRawDataChannel
    fileRawDataChannel = Channel(300)
    baseGlbPath = pwd()
    println( "Curpath is: ",baseGlbPath )

    # Name = getStringFromArray( fdobj.machineName )
    # baseGlbPath= replace(baseGlbPath,"\\"=>"/")
    # evs ="cfgRootfolder =\"$baseGlbPath\""
    # reps = Base.Meta.parse( evs )
    # Core.eval( Main,reps )

    # Name = getStringFromArray( fdobj.machineName )
    # evs ="machineName =\"$Name\""
    # reps = Base.Meta.parse( evs )
    # Core.eval( Main,reps )

    # println( "Curpath is: ",Main.cfgRootfolder )
    cfgFilename =joinpath(baseGlbPath,"../Jl-Aux/glbCfg/OfflineAnaCfg.jl")
    @warn "cfg file is: ",cfgFilename
    Main.getCfg(cfgFilename)

    rootdir=Main.rootdir
    @warn rootdir
    startTime=  Main.startTime
    endTime = Main.endTime
    # println(rootdir)
    # files = Main.findAllFiles(rootdir,".RAW3",startTime,endTime)
    # println("Total File Num is :",length(files) )
    # @async Main.readinPTFiles(files )
    @warn "------RAW3AlgEntryC01--------cur time is :", Dates.now()
    Main.SegParaAlarmProc.RAW3AlgEntryC01(false) ##Offline
    @warn "---------------------cur time is :", Dates.now()
    return 0
end
Base.@ccallable function julia_main_2(ARGS::Vector{String})::Cint
    global fileRawDataChannel
    fileRawDataChannel = Channel(300)
    baseGlbPath = pwd()
    println( baseGlbPath )
    Main.getCfg("../Jl-Aux/glbCfg/OfflineAnaCfg.jl")
    #Main.baseGlbPath = pwd()
    #println( Main.baseGlbPath)
    # println(@__DIR__ )
    rootdir=Main.rootdir
    startTime=  Main.startTime
    endTime = Main.endTime
    println(rootdir)
    files = Main.findAllFiles(rootdir,".RAW3",startTime,endTime)
    println("Total File Num is :",length(files) )
    @async Main.readinPTFiles(files )
    # @warn "---------------------cur time is :", Dates.now()
    Main.SegParaAlarmProc.RAW3AlgEntryC01(false) ##Offline
    # @warn "---------------------cur time is :", Dates.now()

    return 0
end

Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
    try
        return julia_main1(ARGS)
    catch e
        print(e)
    end

end

max_stars_repo_name: wangzhongtian/fiberAlarmAnalyseTool

max_issues_repo_name: wangzhongtian/fiberAlarmAnalyseTool

max_forks_repo_name: wangzhongtian/fiberAlarmAnalyseTool


text:
using Documenter, MathematicalSystems

makedocs(
    modules = [MathematicalSystems],
    # See https://github.com/JuliaDocs/Documenter.jl/issues/868
    format = Documenter.HTML(prettyurls = get(ENV, "CI", nothing) == "true"),
    assets = ["assets/juliareach.css"],
    sitename = "MathematicalSystems.jl",
    pages = [
        "Home" => "index.md",
        "Library" => Any[
        "Types" => "lib/types.md",
        "Methods" => "lib/methods.md"],
        "About" => "about.md"
    ],
    strict = true
)

deploydocs(
    repo = "github.com/JuliaReach/MathematicalSystems.jl.git",
)


text:
type Attr
    name::AbstractString
    value::AbstractString
end
Attr(name) = Attr(name, "")

type Tag
    t::Int
    name::AbstractString
    attrs::Vector{Attr}
end
Tag(t, rest) = Tag(t, rest[1], rest[2:end])

spc = Drop(Star(Space()))

doctype = E"<?" + p"[^?]*" + E"?>" |> x->Tag(0, x)
attrnq = p"[^ =<>/?]+" + E"=" + p"[^ =<>/?\"]+"
attrq = p"[^ =<>/?]+" + E"=" + p"\"[^\"]*\""
attre =  p"[^ =<>/?]+" + E" "
attr = attrnq | attrq | attre > Attr
tag = E"<" + p"[^?>/ ]*" + spc + Star(attr + spc) + E">" + spc |> x->Tag(1, x)
endtag = E"</" + spc + p"[^?>/ ]*" + spc + E">" + spc |> x->Tag(2, x)
stag = E"<" + p"[^?>/ ]*" + spc + Star(attr + spc) + E"/" + spc + E">" + spc |> x->Tag(3, x)
text = p"[^<]+"
comment = E"<!--" + Drop(p".+?-->") + spc
elem = comment | text | tag | stag | endtag
all = doctype[0:1] + spc + elem[1:end] + Eos()


text:
# This file is a part of BAT.jl, licensed under the MIT License (MIT).

_iscontiguous(A::Array) = true
_iscontiguous(A::AbstractArray) = Base.iscontiguous(A)

_car_cdr_impl() = ()
_car_cdr_impl(x, y...) = (x, (y...))
_car_cdr(tp::Tuple) = _car_cdr_impl(tp...)

function _all_lteq(A::AbstractArray, B::AbstractArray, C::AbstractArray)
    indices(A) == indices(B) == indices(C) || throw(DimensionMismatch("A, B and C must have the same indices"))
    result = 0
    @inbounds @simd for i in eachindex(A, B, C)
        result += ifelse(A[i] <= B[i] <= C[i], 1, 0)
    end
    result == length(linearindices(A))
end

@inline function _all_lteq_impl(a::Real, B::AbstractArray, c::Real)
    result = 0
    @inbounds @simd for b in B
        result += ifelse(a <= b <= c, 1, 0)
    end
    result == length(linearindices(B))
end

_all_lteq(a::Real, B::AbstractArray, c::Real) = _all_lteq_impl(a, B, c)

_all_in_ui(X::AbstractArray) = _all_lteq_impl(0, X, 1)

doc"""
    y = fromui(x::Real, lo::Real, hi::Real)
    y = fromui(x::Real, lo_hi::ClosedInterval{<:Real})

Linear bijective transformation from the unit inverval (i.e. `x ∈ 0..1`) to
`y ∈ lo..hi`.

Use `inv(fromui)` to get the the inverse transformation.

Use `@inbounds` to disable range checking on the input value.
"""
function fromui end
export fromui

@inline unsafe_fromui(x::Real, lo::Real, hi::Real) = muladd(x, (hi - lo), lo)

@inline function fromui(x::Real, lo::Real, hi::Real)
    @boundscheck x in 0..1 || throw(ArgumentError("Input value not in 0..1"))
    unsafe_fromui(x, lo, hi)
end

Base.@propagate_inbounds fromui(x::Real, lo_hi::ClosedInterval{<:Real}) =
    fromui(x, minimum(lo_hi), maximum(lo_hi))

@inline unsafe_inv_fromui(x::Real, lo::Real, hi::Real) = (x - lo) / (hi - lo)

@inline function inv_fromui(x::Real, lo::Real, hi::Real)
    @boundscheck x in lo..hi || throw(ArgumentError("Input value not in lo..hi"))
    unsafe_inv_fromui(x, lo, hi)
end

Base.@propagate_inbounds inv_fromui(x::Real, lo_hi::ClosedInterval{<:Real}) =
    inv_fromui(x, minimum(lo_hi), maximum(lo_hi))

@inline Base.inv(::typeof(fromui)) = inv_fromui
@inline Base.inv(::typeof(inv_fromui)) = fromui

doc"""
    @propagate_inbounds sum_first_dim(A::AbstractArray, j::Integer, ks::Integer...)

Calculate the equivalent of `sum(A[:, j, ks...])`.
"""
Base.@propagate_inbounds function sum_first_dim(A::AbstractArray, j::Integer, ks::Integer...)
    s = zero(eltype(A))
    @boundscheck if !Base.checkbounds_indices(Bool, Base.tail(indices(A)), (j, ks...))
        throw(BoundsError(A, (:, j)))
    end
    @inbounds for i in indices(A, 1)
        s += A[i, j, ks...]
    end
    s
end

doc"""
    @propagate_inbounds sum_first_dim(A::AbstractArray)

If `A` is a vector, return `sum(A)`, else `sum(A, 1)[:]`.
"""
sum_first_dim(A::AbstractArray) = sum(A, 1)[:]
sum_first_dim(A::AbstractVector) = sum(A)

const SingleArrayIndex = Union{Integer, CartesianIndex}

Base.@propagate_inbounds function _swap!(A::AbstractArray, i_A::SingleArrayIndex, B::AbstractArray, i_B::SingleArrayIndex)
    tmp = A[i_A]
    A[i_A] = B[i_B]
    B[i_B] = tmp
    A
end

function _swap!(A::AbstractArray, B::AbstractArray)
    size(A) == size(B) || throw(DimensionMismatch("Can only swap arrays with equal size"))
    @inbounds @simd for i in eachindex(A, B)
        _swap!(A, i, B, i)
    end
    A
end


text:
using PackageCompiler
import Pkg, Libdl

function compile_sysimg(args::Vector{<:AbstractString})
    args_len = length(args)
    args = abspath.(args)
    if args_len == 1
        env_path = img_path = args[1]
        exec_files = []
    elseif args_len >= 2
        env_path, img_path = args[1:2]
        exec_files = args[3:end]
    else
        error("at least one argument is required")
    end

    project_file = joinpath(env_path, "Project.toml")
    sysimg_file  = joinpath(img_path, "sysimg.$(Libdl.dlext)")

    project  = Pkg.API.read_project(project_file)
    packages = Symbol.(collect(keys(project.deps)))

    @info "Building a sysimage for the environment '$env_path' to '$img_path'."

    create_sysimage(packages; sysimage_path=sysimg_file, project=env_path,
        precompile_execution_file=exec_files)
end

function compile_app(args::Vector{<:AbstractString})
    args_len = length(args)
    args = abspath.(args)
    if args_len == 1
        pkg_dir = app_dir = args[1]
        exec_files = []
    elseif args_len >= 2
        pkg_dir,  app_dir = args[1:2]
        exec_files = args[3:end]
    else
        error("at least one argument is required when ")
    end

    @info "Building a binary app for package '$pkg_dir' to '$app_dir'."

    create_app(pkg_dir, app_dir; force=true,
        precompile_execution_file=exec_files)
end

function main(args::Vector{<:AbstractString})
    option = args[1]
    if option == "-s"
        compile_sysimg(args[2:end])
    elseif option == "-b"
        compile_app(args[2:end])
    else
        startswith(option, "-") && error("unknown compile option")
        compile_sysimg(args) # compile to a sysimage without a option
    end
end

if abspath(PROGRAM_FILE) == @__FILE__
    main(ARGS)
end

max_stars_repo_name: wangl-cc/coc-julia

max_issues_repo_name: wangl-cc/coc-julia

max_forks_repo_name: wangl-cc/coc-julia


text:
module Rita

#import Unitful
using StaticArrays: SVector
using LinearAlgebra: dot, normalize, norm
#using CoordinateTransformations, StaticArrays, Unitful, UnitfulAngles

export refract_dir

# location
const Pnt = SVector{3, Float64}
# difference between locations
const Diff = SVector{3, Float64}
# direction
const Dir = SVector{3, Float64}
Dir(a, b, c)::Dir = normalize([a, b, c])
Dir(alpha, beta)::Dir = Dir([ cos(alpha)*sin(beta),
                                                sin(alpha)*sin(beta),
                                                cos(beta)])

# Inspired heavily by JuliaGeometry/RayTraceEllipsoid

struct Ray
    orig::Pnt
    dir::Dir
    Ray(o::Pnt, d::Dir) = new(o, d)
end

# ray along z from origin
Ray() = Ray(Vec(0,0,0), Vec(1,0,0))

# dot(in, n) should be >0 in most cases
mirror_dir(in::Dir, n::Dir)::Dir = in - 2*dot(in, n)*n
# Snellius law
# Does also handle total internal reflection!
function refract_dir(in::Dir, n::Dir, n1::Float64, n2::Float64)::Dir
    in_parallel = dot(in, n) * n
    in_orthogonal = in - in_parallel
    q = n1/n2
    # println(in, " ", n, " ", n1, " ", n2)
    out = try
        q * in_orthogonal + sqrt(1 - q^2 * dot(in_orthogonal, in_orthogonal)) * in_parallel
    catch DomainError
        # total internal reflection
        mirror_dir(in, n)
    end
    normalize(out)
end

# Code excerpt from RayTraceEllipsoid.jl
function intersect_unit_sph(ray::Ray)::Tuple{Float64, Float64}
    v = - ray.orig
    b = dot(v, ray.dir)
    disc = b*b - dot(v, v) + 1
    if disc >= 0
        d = sqrt(disc)
        t2 = b + d
        if t2 >= 0
            t1 = b - d
            return t1 > 0 ? (t1, t2) : (Inf, t2)
        end
    end
    return (Inf, Inf)
end

end # module


text:
function real_abs(x::acb; analytic = false)
    # FIXME: The version in Arb contains a bug in one case, we check for this
    # manually. Once this is fixed in Arb we can remove it from here.
    if !analytic && !isnonnegative(real(x)) && !isnegative(real(x))
        return return parent(x)(setunion(real(x), -real(x)), setunion(imag(x), -imag(x)))
    end
    y = parent(x)()
    ccall(("acb_real_abs", Nemo.libarb), Cvoid, (Ref{acb}, Ref{acb}, Cint, Clong),
          y, x, analytic, precision(parent(x)))
    return y
end

"""
    rel_accuracy_bits(x)
> Compute the relatively accuracy of the ball `x` in bits.
"""
rel_accuracy_bits(x::acb) = ccall(("arb_rel_accuracy_bits", Nemo.libarb), Int,
                                  (Ref{acb},), x)


text:
"""
    For loading networks with stoichiometry stored in matrices.
    Assumed that the substrate and product stoichiometry matrices
    are stored as numspecies by numrxs matrices, with entry (i,j)
    giving the stoichiometric coefficient of species i within rx j.
"""

"""
    For dense matrices
"""
function loadrxnetwork(::MatrixNetwork,
                        rateexprs::AbstractVector,
                        substoich::AbstractMatrix,
                        prodstoich::AbstractMatrix;
                        species::AbstractVector=Any[],
                        params::AbstractVector=Any[])

    sz = size(substoich)
    @assert sz == size(prodstoich)
    numspecs = sz[1]
    numrxs = sz[2]

    # create the network
    rn = make_empty_network()
    t  = ModelingToolkit.get_iv(rn)

    # create the species if none passed in
    isempty(species) && (species = [funcsym(:S,t,i) for i=1:numspecs])
    foreach(s -> addspecies!(rn, s, disablechecks=true), species)

    # create the parameters
    foreach(p -> addparam!(rn, p, disablechecks=true), params)

    # create the reactions
    # we need to create new vectors each time as the ReactionSystem
    # takes ownership of them
    for j = 1:numrxs
        subs    = Any[]
        sstoich = Vector{eltype(substoich)}()
        prods   = Any[]
        pstoich = Vector{eltype(prodstoich)}()

        # stoich
        for i = 1:numspecs
            scoef = substoich[i,j]
            if (scoef > zero(scoef))
                push!(subs, species[i])
                push!(sstoich, scoef)
            end

            pcoef = prodstoich[i,j]
            if (pcoef > zero(pcoef))
                push!(prods, species[i])
                push!(pstoich, pcoef)
            end
        end

        addreaction!(rn, Reaction(rateexprs[j], subs, prods, sstoich, pstoich))
    end

    ParsedReactionNetwork(rn, nothing)
end

"""
    For sparse matrices
"""
function loadrxnetwork(ft::MatrixNetwork,
                        rateexprs::AbstractVector,
                        substoich::SparseMatrixCSC,
                        prodstoich::SparseMatrixCSC;
                        species::AbstractVector=Any[],
                        params::AbstractVector=Any[])

    sz = size(substoich)
    @assert sz == size(prodstoich)
    numspecs = sz[1]
    numrxs = sz[2]

    # create the network
    rn = make_empty_network()
    t  = ModelingToolkit.get_iv(rn)

    # create the species if none passed in
    isempty(species) && (species = [funcsym(:S,t,i) for i=1:numspecs])
    foreach(s -> addspecies!(rn, s, disablechecks=true), species)

    # create the parameters
    foreach(p -> addparam!(rn, p, disablechecks=true), params)

    # create the reactions
    srows = rowvals(substoich)
    svals = nonzeros(substoich)
    prows = rowvals(prodstoich)
    pvals = nonzeros(prodstoich)
    for j = 1:numrxs
        subs    = Any[]
        sstoich = Vector{eltype(substoich)}()
        prods   = Any[]
        pstoich = Vector{eltype(prodstoich)}()

        for ir in nzrange(substoich, j)
           i     = srows[ir]
           scoef = svals[ir]
           if scoef > zero(scoef)
                push!(subs, species[i])
                push!(sstoich, scoef)
           end
        end

        for ir in nzrange(prodstoich, j)
            i     = prows[ir]
            pcoef = pvals[ir]
            if pcoef > zero(pcoef)
                push!(prods, species[i])
                push!(pstoich, pcoef)
            end
        end

        addreaction!(rn, Reaction(rateexprs[j], subs, prods, sstoich, pstoich))
     end

    ParsedReactionNetwork(rn, nothing)
end