text:
using Logging

"""
    @capture_stdstreams(expr)

Evaluate the specified expression and return a `(stdout, stderr)` tuple.

This macro will attempt to capture every form of output, including via the
`Logging` module (_e.g._ the `@logmsg` and friend macros), but it's unable to
do this with perfect accuracy. Any code that stores a reference to `stdout` or
`stderr` before this is executed will retain those references to the original
streams.
For example, the original log instance may be obtained using
`Logging.global_logger()` because no attempt is made to set the global logger
instance.

# Examples
```julia-repl
julia> out, err = ComparativeAutograder.@capture_stdstreams begin
           println("I'm going to out!")
           println(stderr, "I'm going to err!")
       end
("I'm going to out!\\n", "I'm going to err!\\n")
```
"""
macro capture_stdstreams(expr)
    # We use a whole bunch of `gensym`'s to avoid polluting the namespace
    out, outread, outwrite, outtask = gensym.([:stdout, :outread, :outwrite, :outtask])
    err, errread, errwrite, errtask = gensym.([:stderr, :errread, :errwrite, :errtask])
    return quote
        $out, $err = Base.stdout, Base.stderr
        $outread, $outwrite = redirect_stdout()
        $errread, $errwrite = redirect_stderr()
        $outtask = @async read($outread, String)
        $errtask = @async read($errread, String)

        try
            with_logger(ConsoleLogger(Base.stderr, Logging.Debug)) do
                $(esc(expr))
            end
        catch (e)
            rethrow(e)
        finally
            redirect_stdout($out)
            redirect_stderr($err)
            close.([$outwrite, $errwrite])
        end

        fetch($outtask), fetch($errtask)
    end
end

"""
    smallrepr(x)

Generate a _small_ representation of `x` (_i.e._ what would be printed to the
console so as not to overwhelm the user with output).

# Examples
```julia-repl
julia> print(ComparativeAutograder.smallrepr(ones(2, 100)))
2×100 Array{Float64,2}:
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0  …  1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
```
"""
function smallrepr(x)
    buf = IOBuffer()
    ctx = IOContext(buf, :limit => true)
    show(ctx, "text/plain", x)
    return String(take!(buf))
end

"""
    trunctatestring(s[, l])

Take at most `l` characters of `s`; if the `s` is longer than `l`, then `l`
characters are taken and the string `...\n[ TRUNCATED ]` is appended to the end.

# Examples
```julia-repl
julia> println(ComparativeAutograder.truncatestring("foo\nbar\nspam", 5))
foo
b...
[ TRUNCATED ]
```
"""
function truncatestring(s::AbstractString, l::Int=16384)
    if length(s) > l
        return s[1:l] * "...\n[ TRUNCATED ]"
    end
    return s
end

"""
    errorstring(e)

Convert an exception into a human readable version.

# Examples
```julia-repl
julia> exc = nothing
julia> try
           1 + "foo"
       catch e
           global exc
           exc = e
       end
julia> println(errorstring(exc))
MethodError: no method matching +(::Int64, ::String)
Closest candidates are:
  +(::Any, ::Any, !Matched::Any, !Matched::Any...) at operators.jl:502
  +(::T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}, !Matched::T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} at int.jl:53
  +(::Union{Int16, Int32, Int64, Int8}, !Matched::BigInt) at gmp.jl:447
  ...
```
"""
errorstring(e::Exception) = sprint(showerror, e)
errorstring(e::ErrorException) = "ErrorException: $(e.msg)"
errorstring(e::AbstractString) = truncatestring(e)
errorstring(e::Any) = truncatestring(smallrepr(e))


text:
"""
Computes line extinction and associated quantities.
"""

"""
    function AtomicLine(χu::Unitful.Energy{T}, χl::Unitful.Energy{T},
                        χ∞::Unitful.Energy{T}, gu::Int, gl::Int, f_value::T,
                        atom_weight::Unitful.Mass{T}, Z::Int)  where T <: AbstractFloat

Structure for atomic line.
"""
struct AtomicLine{T <: AbstractFloat}
    Aji::Unitful.Frequency{T}
    # Units of Bij/Bji defined for J_lambda
    Bji::Unitful.Quantity{T, Unitful.𝐋 * Unitful.𝐓^2 / Unitful.𝐌}
    Bij::Unitful.Quantity{T, Unitful.𝐋 * Unitful.𝐓^2 / Unitful.𝐌}
    λ0::Unitful.Length{T}
    χi::Unitful.Energy{T}
    χj::Unitful.Energy{T}
    # Properties of atom, not line, but keeping here for now
    χ∞::Unitful.Energy{T}
    atom_weight::Unitful.Mass{T}
    Z::Int
    function AtomicLine(χu::Quantity{T}, χl::Quantity{T}, χ∞::Quantity{T},
                        gu::Int, gl::Int, f_value::T, atom_weight::Unitful.Mass{T},
                        Z::Int)  where T <: AbstractFloat
        χu = wavenumber_to_energy(χu)
        χl = wavenumber_to_energy(χl)
        χ∞ = wavenumber_to_energy(χ∞)
        # Add conversion from cm^-1 to aJ, if type of χu is L^-1
        @assert χ∞ > χu
        @assert χu > χl
        @assert gu > 0
        @assert gl > 0
        @assert f_value > 0
        @assert atom_weight > 0u"kg"
        @assert Z >= 1
        λ0 = convert(Quantity{T, Unitful.𝐋}, ((h * c_0) / (χu - χl)) |> u"nm")
        Aul = convert(Quantity{T, Unitful.𝐓^-1}, calc_Aji(λ0, gl / gu, f_value))
        Bul = calc_Bji(λ0, Aul)
        Blu = gu / gl * Bul
        new{T}(Aul, Bul, Blu, λ0, χl, χu, χ∞, atom_weight, Z)
    end
end

"""
If input is in wavenumber, convert to energy. Otherwise keep as energy.
"""
function wavenumber_to_energy(a::Quantity{T}) where T <: AbstractFloat
    if typeof(a) <: PerLength
        a = convert(Unitful.Quantity{T, Unitful.𝐋^2 * Unitful.𝐓^-2 * Unitful.𝐌},
                    (h * c_0 * a) |> u"aJ")
    end
    @assert typeof(a) <: Unitful.Energy{T} "Input units must either be wavenumber or energy"
    return a
end

"""
Compute line extinction given an `AtomicLine` struct, `profile` defined per wavelength,
and upper and lower population densities `n_u` and `n_l`.
"""
function αline_λ(line::AtomicLine, profile::PerLength, n_u::NumberDensity, n_l::NumberDensity)
    (h * c_0 / (4 * π * line.λ0) * profile * (n_l * line.Bij - n_u * line.Bji)) |> u"m^-1"
end

"""
Compute line emissivity given an `AtomicLine` struct, `profile` defined per wavelength,
and upper population density `n_u`.
"""
function jline_λ(line::AtomicLine, profile::PerLength, n_u::NumberDensity)
    (h * c_0 / (4 * π * line.λ0) * n_u * line.Aji * profile) |> u"W / (m^3 * nm)"
end

"""
Calculates the Blackbody (Planck) function per wavelength, for given
wavelength and temperature.
"""
function blackbody_λ(λ::Unitful.Length, temperature::Unitful.Temperature)
    (2h * c_0^2) / (λ^2 * λ^3 * (exp((h * c_0 / k_B) / (λ * temperature)) - 1))
end

"""
Calculates the Blackbody (Planck) function per frequency, for a given
frequency and temperature.
"""
function blackbody_ν(ν::Unitful.Frequency, temperature::Unitful.Temperature)
    (2h / c_0^2) * (ν^3 / (exp((h / k_B) * (ν / temperature)) - 1))
end

ext: jl


text:
# Helper functions for the staggered grid
"""
    avg(A)

4-point average of a matrix
"""
@views avg(A) = 0.25 .* ( A[1:end-1,1:end-1] .+ A[2:end,1:end-1] .+ A[1:end-1,2:end] .+ A[2:end,2:end] )

"""
    avg_x(A)

2-point average of a matrix's X axis
"""
@views avg_x(A) = 0.5 .* ( A[1:end-1,:] .+ A[2:end,:] )

"""
    avg_y(A)

2-point average of a matrix's Y axis
"""
@views avg_y(A) = 0.5 .* ( A[:,1:end-1] .+ A[:,2:end] )

"""
    diff_x(A)

2-point differential of a matrix's X axis
"""
@views diff_x(A) = (A[begin + 1:end, :] .- A[1:end - 1, :])

"""
    diff_y(A)

2-point differential of a matrix's Y axis
"""
@views diff_y(A) = (A[:, begin + 1:end] .- A[:, 1:end - 1])

"""
    inn(A)

Access the inner part of the matrix (-2,-2)
"""
@views inn(A) = A[2:end-1,2:end-1]

"""
fillNaN!(x, fill)

Convert empty matrix grid cells into fill value
"""
function fillNaN!(A, fill=zero(eltype(A)))
    for i in eachindex(A)
        @inbounds A[i] = ifelse(isnan(A[i]), fill, A[i])
    end
end

function fillNaN(A, fill=zero(eltype(A)))
    return @. ifelse(isnan(A), fill, A)
end

function fillZeros!(A, fill=NaN)
    for i in eachindex(A)
        @inbounds A[i] = ifelse(iszero(A[i]), fill, A[i])
    end
end

function fillZeros(A, fill=NaN)
    return @. ifelse(iszero(A), fill, A)
end

"""
    smooth!(A)

Smooth data contained in a matrix with one time step (CFL) of diffusion.
"""
@views function smooth!(A)
    A[2:end-1,2:end-1] .= A[2:end-1,2:end-1] .+ 1.0./4.1.*(diff(diff(A[:,2:end-1], dims=1), dims=1) .+ diff(diff(A[2:end-1,:], dims=2), dims=2))
    A[1,:]=A[2,:]; A[end,:]=A[end-1,:]; A[:,1]=A[:,2]; A[:,end]=A[:,end-1]
    return
end

function smooth(A)
    A_smooth = A[2:end-1,2:end-1] .+ 1.0./4.1.*(diff(diff(A[:,2:end-1], dims=1), dims=1) .+ diff(diff(A[2:end-1,:], dims=2), dims=2))
    @tullio A_smooth_pad[i,j] := A_smooth[pad(i-1,1,1),pad(j-1,1,1)] # Fill borders
    return A_smooth_pad
end


text:
### A Pluto.jl notebook ###
# v0.17.3

using Markdown
using InteractiveUtils

# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error).
macro bind(def, element)
    quote
        local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end
        local el = $(esc(element))
        global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el)
        el
    end
end

# ╔═╡ 8cf4d8ca-84eb-11eb-22d2-255ce7237090
begin
	using ClimateModels, MITgcmTools, PlutoUI, Plots, CSV
	exps=verification_experiments()
	"(packages are all set)"
end

# ╔═╡ 8784eb6f-f6ca-4466-97bc-eaa80872185c
begin
	md"""# ClimateModels.jl -- A Simple Interface To Climate Models

	### Gaël Forget, JuliaCon2021

	###

	[ClimateModels.jl](https://github.com/gaelforget/ClimateModels.jl) provides a uniform interface to climate models of varying complexity and completeness. Models that range from low dimensional to whole Earth System models are ran and analyzed via this simple interface.

	## Key Features

	- Climate Model Interface
	- Tracked Workflow Framework
	- Cloud + On-Premise File Support

	## Standard Workflow

	- create `ModelConfig` data structure
	- call `setup` (prepare run/ and log/)
	- call `build` (compile if needed)
	- call `launch` (run model / task)

	## The Four Examples

	- a stochastic path (zero-dimensional, **Julia function**)
	- a shallow water model (two-dimensional, **Julia package**)
	- a general circulation model (multi-dimensional, feature-rich `*`, **Fortran code**)
	- CMIP6 climate model output (retrieved from cloud storage, **replay mode**)

	`*` _MITgcm features incl. MPI parallelism, Multithreading, Automatic Differentiation, Coupled Modeling, Domain Nesting, and more. It is widely used for ocean state estimation, high-resolution ocean simulation, and more generally to study Oceans, Atmospheres, Seaice, Biogeochemistry, and Ecology._
	"""
end

# ╔═╡ 9f3e266b-7623-4c77-b381-4eafe3600a33
md""" [Link to recorded JuliaCon presentation (8')](https://youtu.be/XR5hKCja0uw)

$(Resource("https://user-images.githubusercontent.com/20276764/131556274-48f3df13-0608-4cd0-acf9-c3e29894a32c.png", :width => 300))
"""

# ╔═╡ 385d8630-2250-44d9-b1d1-3405841cd2d2
begin
	md"""## Example 1 :  Model = [Julia Function](https://gaelforget.github.io/ClimateModels.jl/stable/generated/RandomWalker/)

	##

	**Function documentation :**

	$(@doc ClimateModels.RandomWalker)

	NS= $(@bind NS TextField(; default="100"))

	**ModelConfig data structure :**

	"""
end

# ╔═╡ e1559cdc-b180-4976-ac46-e1afa991d62c
begin
	MC1=ModelConfig(model=ClimateModels.RandomWalker,inputs=Dict("NS" => parse(Int,NS)))

	setup(MC1)
	build(MC1)
	launch(MC1)

	MC1
end

# ╔═╡ 30273b0c-eb79-4fca-bda7-e8f72cf79e04
begin
	fil1=joinpath(MC1.folder,string(MC1.ID),"RandomWalker.csv")
	res1 = CSV.File(fil1)
	img=plot(res1.x,res1.y,frmt=:png,leg=:none)
end

# ╔═╡ 10c8fde5-ed53-47b2-8a8d-55ce21c12152
md"""## Example 2 :  Model = [Julia Package](https://gaelforget.github.io/ClimateModels.jl/stable/generated/ShallowWaters/)

[Here](https://gaelforget.github.io/ClimateModels.jl/stable/generated/ShallowWaters/) we use the shallow water equations, a simplification of the Navier Stokes equations, from [ShallowWaters.jl](https://github.com/milankl/ShallowWaters.jl).
"""

# ╔═╡ 6ef93b0e-859f-11eb-1b3b-d76b26d678dc
begin
	md"""## Example 3 : Model = [Fortran GCM](https://gaelforget.github.io/ClimateModels.jl/stable/generated/MITgcm/)

	###

	This example applies the same, simple, interface, but now to a general circulation model (`MITgcm`) written in `Fortran`  that can simulate, for example, either **atmospheric flows via the primitive equations** (`hs94.cs-32x32x5`) or **carbon emissions entering the oceans** (`tutorial_global_oce_biogeo`).

	The [ClimateModels.jl](https://github.com/gaelforget/ClimateModels.jl) interface for the [MIT general circulation model (MITgcm)](https://mitgcm.readthedocs.io/en/latest/?badge=latest) is implemented in [MITgcmTools.jl](https://gaelforget.github.io/MITgcmTools.jl/dev/).

	###

	#### Select Model Configuration

	###

	myexp = $(@bind myexp Select([exps[i].configuration for i in 1:length(exps)],default="hs94.cs-32x32x5"))

	#### MITGcm_config struct
	"""
end

# ╔═╡ eca925ba-8816-11eb-1d6d-39bf08bfe979
begin
	iexp=findall([exps[i].configuration==myexp for i in 1:length(exps)])[1]

	setup(exps[iexp])
    build(exps[iexp],"--allow-skip")

	exps[iexp]
end

# ╔═╡ 2499d523-f141-477a-be18-d46885c58546
md"""The previous code cell calls `setup` and `build` at once and displays the **MITgcm_config** data structure.

The **$(typeof(exps[iexp]))** type (a concrete type of the `AbstractModelConfig`, as is `ModelConfig`) is provided by `MITgcmTools.jl`. Doing this allows `setup`, `build`, `launch`, etc to readily dispatch to the appropriate methods which are also provided by `MITgcmTools.jl`. **A similar approach can be applied to any (?) other climate model.**

#### Launch Model

The next code cell calls `launch` and displays a completion message once done.
"""

# ╔═╡ 96492c18-86bd-11eb-35ca-dff79e6e7818
	begin
		launch(exps[iexp])

		md"""🎉 🎊 Model run for the **$(exps[iexp].configuration)** configuration has completed 🎉 🎊"""
	end

# ╔═╡ 6404fddf-3c46-4015-9580-b9159c76b30a
	md"""#### Explore Model Output

	###

	Below is a list of all files (by default) contained in the `run/` directory. Clicking on a list like this should expand its display.

	To narrow the selection, try typing something in the text field 👉 $(@bind search_txt TextField(; default=""))	👈
	"""

# ╔═╡ 6edcbba3-8485-44d2-940a-e4f2df019373
	begin
		rundir=joinpath(exps[iexp].folder,string(exps[iexp].ID),"run")
		list1=readdir(rundir)
		search_txt!=="*" ? list1[findall(occursin.(search_txt,list1))] : list1
	end

# ╔═╡ d0bbb668-86e0-11eb-1a9b-8f2b0175f7c1
begin
	filout=joinpath(rundir,"output.txt")
	filstat=joinpath(rundir,"onestat.txt")

	if exps[iexp].configuration=="tutorial_global_oce_biogeo"
		run(pipeline(`grep trcstat_ptracer01_mean $(filout)`,filstat))
		Tname="mean Diss. Inorg. Carbon"
	else
		run(pipeline(`grep dynstat_theta_mean $(filout)`,filstat))
		Tname="mean temperature"
	end

	tmp0 = read(filstat,String)
	tmp0 = split(tmp0,"\n")
	Tmean=[parse(Float64,split(tmp0[i],"=")[2]) for i in 1:length(tmp0)-1]

	md"""### Plot Model Result

	###

	Below we show **$(Tname)** in **$(exps[iexp].configuration)** as a function of time.

	"""
end

# ╔═╡ 8ad9d646-4eec-45b9-938b-21df34da2d6b
plot(Tmean,label=Tname)

# ╔═╡ 60a68f95-f5f4-4d75-9c5f-30e2ae141c4b
md"""## Example 4 :  Model = [Replay From Storage](https://gaelforget.github.io/ClimateModels.jl/stable/generated/CMIP6/)

[Here](https://gaelforget.github.io/ClimateModels.jl/stable/generated/CMIP6/) we replay climate model output from the CMIP6 archive to drive another modeling workflow, focused on deriving global means and climatologies, via the **ClimateModels.jl** interface which provides standardization, etc.

This example relies on climate model output stored in the cloud, but `replay mode` is also often used with model output stored on a local or remote drive, for workflows focused on analyzing model results rather generating them, or workflows that drive one model from another model's output (e.g. `tutorial_global_oce_biogeo` in **example 2**).
"""

# ╔═╡ 3d4fd8e0-0e89-4018-8275-103fb29a5000

# ╔═╡ 573e6c6b-055c-4e79-af42-15159e40f7be
md"""## Summary

##

#### Standard Workflow

- create model configuration data structure
- call `setup` (run/ and log/ folders)
- call `build` (compile if needed)
- call `launch` (run model / modeling task)

#### Key Features

- **Climate Model Interface** (`AbstractModelConfig`, `setup`, `build`, `launch`, ...)
- **Tracked Worklow Framework** (`Git.jl` + `UUIDs.jl` integration, `log/` folder, ...)
- **Cloud + On-Premise File Support** (`AWS.jl`, `Zarr.jl`, `CSV.jl`, `NetCDF.jl`, ...)
- **Package Design** (small, familiar tools, aligned with climate modeling practices)

#### ClimateModels.jl Provides

- **standardization** (e.g., same for Julia, Fortran, or replay)
- **simplicity** (regardless of underlying model complexity)
- **reproducibility** (via `Git.jl`, `UUIDs.jl`, `log/` folder)
- **composability** (daisy-chain `ModelConfig`'s via `input`)
- **interactivity** (e.g., `Pluto.jl` demos, parameter files)
- **bridge between communities** (e.g., Julia and Fortran)
"""

# ╔═╡ de12dd76-7641-4712-a944-814ffc427a26

# ╔═╡ ac7e1bd6-fa74-4067-bf35-e7f37bdddc68
md"""## Outlook

##

#### What's next?

- extend non-Julia model line-up (e.g. SPEEDY, HECTOR, ISCA)
- extend Julia model line-up (JuliaOcean, JuliaClimate, CLIMA)
- collaborate with major climate modeling groups (interface)
- extend standard method line-up

#### Want More?

- try ClimateModels.jl [on mybinder.org](https://mybinder.org/v2/gh/gaelforget/ClimateModels.jl/HEAD)
- see [JuliaClimate](https://github.com/JuliaClimate), [JuliaOcean](https://github.com/JuliaOcean) for related work
- JuliaCon 2021 : Marine Ecosystem workshop
- JuliaCon 2021 : OceanRobots.jl virtual poster
"""

# ╔═╡ 4f09cda6-5bf9-4a7b-9fa9-edc00f852c07

# ╔═╡ af176e6c-8695-11eb-3e34-91fbdb9c52fa
md"""### Appendix

###

Code cell below loads Julia packages used in this notebook, and the list of MITgcm experiments.
"""

# ╔═╡ 734e2b5a-8866-11eb-0025-bd9544f4c30d
begin
	#Read grid (as if rectangular domain for initial test)

	try
		XC=read_mdsio(rundir,"XC"); siz=size(XC)

		mread(xx::Array,x::MeshArray) = read(xx,x)
		function mread(fil::String,x::MeshArray)
			d=dirname(fil)
			b=basename(fil)[1:end-5]
			read(read_mdsio(d,b),x)
		end

		γ=gcmgrid(rundir,"PeriodicChannel",1,fill(siz,1), [siz[1] siz[2]], eltype(XC), mread, write)
		Γ=GridLoad(γ)
	catch e
		γ=[]
		Γ=[]
		println("no grid files")
	end

	md"""😸"""
end

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
ClimateModels = "f6adb021-9183-4f40-84dc-8cea6f651bb0"
MITgcmTools = "62725fbc-3a66-4df3-9000-e33e85b3a198"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"

[compat]
CSV = "~0.9.11"
ClimateModels = "~0.1.20"
MITgcmTools = "~0.1.32"
Plots = "~1.25.2"
PlutoUI = "~0.7.25"
"""

# ╔═╡ 00000000-0000-0000-0000-000000000002
PLUTO_MANIFEST_TOML_CONTENTS = """
# This file is machine-generated - editing it directly is not advised

julia_version = "1.7.0"
manifest_format = "2.0"

[[deps.AWS]]
deps = ["Base64", "Compat", "Dates", "Downloads", "GitHub", "HTTP", "IniFile", "JSON", "MbedTLS", "Mocking", "OrderedCollections", "Retry", "Sockets", "URIs", "UUIDs", "XMLDict"]
git-tree-sha1 = "82e9580aff0d2c1703f4bf38a9de79e927f252f9"
uuid = "fbe9abb3-538b-5e4e-ba9e-bc94f4f92ebc"
version = "1.74.0"

[[deps.AbstractPlutoDingetjes]]
deps = ["Pkg"]
git-tree-sha1 = "abb72771fd8895a7ebd83d5632dc4b989b022b5b"
uuid = "6e696c72-6542-2067-7265-42206c756150"
version = "1.1.2"

[[deps.Adapt]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "84918055d15b3114ede17ac6a7182f68870c16f7"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "3.3.1"

[[deps.ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"

[[deps.Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"

[[deps.Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[deps.Blosc]]
deps = ["Blosc_jll"]
git-tree-sha1 = "575bdd70552dd9a7eaeba08ef2533226cdc50779"
uuid = "a74b3585-a348-5f62-a45c-50e91977d574"
version = "0.7.2"

[[deps.Blosc_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Lz4_jll", "Pkg", "Zlib_jll", "Zstd_jll"]
git-tree-sha1 = "91d6baa911283650df649d0aea7c28639273ae7b"
uuid = "0b7ba130-8d10-5ba8-a3d6-c5182647fed9"
version = "1.21.1+0"

[[deps.Bzip2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "c3598e525718abcc440f69cc6d5f60dda0a1b61e"
uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0"
version = "1.0.6+5"

[[deps.CFTime]]
deps = ["Dates", "Printf"]
git-tree-sha1 = "bca6cb6ee746e6485ca4535f6cc29cf3579a0f20"
uuid = "179af706-886a-5703-950a-314cd64e0468"
version = "0.1.1"

[[deps.CSV]]
deps = ["CodecZlib", "Dates", "FilePathsBase", "InlineStrings", "Mmap", "Parsers", "PooledArrays", "SentinelArrays", "Tables", "Unicode", "WeakRefStrings"]
git-tree-sha1 = "49f14b6c56a2da47608fe30aed711b5882264d7a"
uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
version = "0.9.11"

[[deps.Cairo_jll]]
deps = ["Artifacts", "Bzip2_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "e2f47f6d8337369411569fd45ae5753ca10394c6"
uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a"
version = "1.16.0+6"

[[deps.CatViews]]
deps = ["Random", "Test"]
git-tree-sha1 = "23d1f1e10d4e24374112fcf800ac981d14a54b24"
uuid = "81a5f4ea-a946-549a-aa7e-2a7f63a27d31"
version = "1.0.0"

[[deps.ChainRulesCore]]
deps = ["Compat", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "4c26b4e9e91ca528ea212927326ece5918a04b47"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "1.11.2"

[[deps.ChangesOfVariables]]
deps = ["ChainRulesCore", "LinearAlgebra", "Test"]
git-tree-sha1 = "bf98fa45a0a4cee295de98d4c1462be26345b9a1"
uuid = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0"
version = "0.1.2"

[[deps.ClimateModels]]
deps = ["AWS", "CFTime", "CSV", "DataFrames", "Dates", "Downloads", "Git", "NetCDF", "OrderedCollections", "Pkg", "Statistics", "Suppressor", "TOML", "Test", "UUIDs", "Zarr"]
git-tree-sha1 = "15ba5b736e675d5e79fe5ad0e7a8f67a286ffe31"
uuid = "f6adb021-9183-4f40-84dc-8cea6f651bb0"
version = "0.1.20"

[[deps.CodecZlib]]
deps = ["TranscodingStreams", "Zlib_jll"]
git-tree-sha1 = "ded953804d019afa9a3f98981d99b33e3db7b6da"
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
version = "0.7.0"

[[deps.ColorSchemes]]
deps = ["ColorTypes", "Colors", "FixedPointNumbers", "Random"]
git-tree-sha1 = "a851fec56cb73cfdf43762999ec72eff5b86882a"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.15.0"

[[deps.ColorTypes]]
deps = ["FixedPointNumbers", "Random"]
git-tree-sha1 = "024fe24d83e4a5bf5fc80501a314ce0d1aa35597"
uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
version = "0.11.0"

[[deps.Colors]]
deps = ["ColorTypes", "FixedPointNumbers", "Reexport"]
git-tree-sha1 = "417b0ed7b8b838aa6ca0a87aadf1bb9eb111ce40"
uuid = "5ae59095-9a9b-59fe-a467-6f913c188581"
version = "0.12.8"

[[deps.Compat]]
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
git-tree-sha1 = "44c37b4636bc54afac5c574d2d02b625349d6582"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.41.0"

[[deps.CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"

[[deps.ConstructionBase]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "f74e9d5388b8620b4cee35d4c5a618dd4dc547f4"
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
version = "1.3.0"

[[deps.Contour]]
deps = ["StaticArrays"]
git-tree-sha1 = "9f02045d934dc030edad45944ea80dbd1f0ebea7"
uuid = "d38c429a-6771-53c6-b99e-75d170b6e991"
version = "0.5.7"

[[deps.Crayons]]
git-tree-sha1 = "3f71217b538d7aaee0b69ab47d9b7724ca8afa0d"
uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
version = "4.0.4"

[[deps.DataAPI]]
git-tree-sha1 = "cc70b17275652eb47bc9e5f81635981f13cea5c8"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.9.0"

[[deps.DataFrames]]
deps = ["Compat", "DataAPI", "Future", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrettyTables", "Printf", "REPL", "Reexport", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"]
git-tree-sha1 = "cfdfef912b7f93e4b848e80b9befdf9e331bc05a"
uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
version = "1.3.1"

[[deps.DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "3daef5523dd2e769dad2365274f760ff5f282c7d"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.11"

[[deps.DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"

[[deps.Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[deps.DelimitedFiles]]
deps = ["Mmap"]
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"

[[deps.DiskArrays]]
git-tree-sha1 = "6a50d800025a1664c99a8e819e0568c75e3ac0c7"
uuid = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3"
version = "0.2.12"

[[deps.Distances]]
deps = ["LinearAlgebra", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "3258d0659f812acde79e8a74b11f17ac06d0ca04"
uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
version = "0.10.7"

[[deps.Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"

[[deps.DocStringExtensions]]
deps = ["LibGit2"]
git-tree-sha1 = "b19534d1895d702889b219c382a6e18010797f0b"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.8.6"

[[deps.Downloads]]
deps = ["ArgTools", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"

[[deps.EarCut_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "3f3a2501fa7236e9b911e0f7a588c657e822bb6d"
uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5"
version = "2.2.3+0"

[[deps.Expat_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b3bfd02e98aedfa5cf885665493c5598c350cd2f"
uuid = "2e619515-83b5-522b-bb60-26c02a35a201"
version = "2.2.10+0"

[[deps.ExprTools]]
git-tree-sha1 = "b7e3d17636b348f005f11040025ae8c6f645fe92"
uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04"
version = "0.1.6"

[[deps.EzXML]]
deps = ["Printf", "XML2_jll"]
git-tree-sha1 = "0fa3b52a04a4e210aeb1626def9c90df3ae65268"
uuid = "8f5d6c58-4d21-5cfd-889c-e3ad7ee6a615"
version = "1.1.0"

[[deps.FFMPEG]]
deps = ["FFMPEG_jll"]
git-tree-sha1 = "b57e3acbe22f8484b4b5ff66a7499717fe1a9cc8"
uuid = "c87230d0-a227-11e9-1b43-d7ebe4e7570a"
version = "0.4.1"

[[deps.FFMPEG_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "LibVPX_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "Pkg", "Zlib_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"]
git-tree-sha1 = "3cc57ad0a213808473eafef4845a74766242e05f"
uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5"
version = "4.3.1+4"

[[deps.FilePathsBase]]
deps = ["Compat", "Dates", "Mmap", "Printf", "Test", "UUIDs"]
git-tree-sha1 = "04d13bfa8ef11720c24e4d840c0033d145537df7"
uuid = "48062228-2e41-5def-b9a4-89aafe57970f"
version = "0.9.17"

[[deps.FixedPointNumbers]]
deps = ["Statistics"]
git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc"
uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
version = "0.8.4"

[[deps.Fontconfig_jll]]
deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "35895cf184ceaab11fd778b4590144034a167a2f"
uuid = "a3f928ae-7b40-5064-980b-68af3947d34b"
version = "2.13.1+14"

[[deps.Formatting]]
deps = ["Printf"]
git-tree-sha1 = "8339d61043228fdd3eb658d86c926cb282ae72a8"
uuid = "59287772-0a20-5a39-b81b-1366585eb4c0"
version = "0.4.2"

[[deps.FreeType2_jll]]
deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "cbd58c9deb1d304f5a245a0b7eb841a2560cfec6"
uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7"
version = "2.10.1+5"

[[deps.FriBidi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "aa31987c2ba8704e23c6c8ba8a4f769d5d7e4f91"
uuid = "559328eb-81f9-559d-9380-de523a88c83c"
version = "1.0.10+0"

[[deps.Future]]
deps = ["Random"]
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"

[[deps.GLFW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pkg", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"]
git-tree-sha1 = "0c603255764a1fa0b61752d2bec14cfbd18f7fe8"
uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89"
version = "3.3.5+1"

[[deps.GR]]
deps = ["Base64", "DelimitedFiles", "GR_jll", "HTTP", "JSON", "Libdl", "LinearAlgebra", "Pkg", "Printf", "Random", "Serialization", "Sockets", "Test", "UUIDs"]
git-tree-sha1 = "30f2b340c2fff8410d89bfcdc9c0a6dd661ac5f7"
uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
version = "0.62.1"

[[deps.GR_jll]]
deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Pkg", "Qt5Base_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "d59e8320c2747553788e4fc42231489cc602fa50"
uuid = "d2c73de3-f751-5644-a686-071e5b155ba9"
version = "0.58.1+0"

[[deps.GeometryBasics]]
deps = ["EarCut_jll", "IterTools", "LinearAlgebra", "StaticArrays", "StructArrays", "Tables"]
git-tree-sha1 = "58bcdf5ebc057b085e58d95c138725628dd7453c"
uuid = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
version = "0.4.1"

[[deps.Gettext_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "8c14294a079216000a0bdca5ec5a447f073ddc9d"
uuid = "78b55507-aeef-58d4-861c-77aaff3498b1"
version = "0.20.1+7"

[[deps.Git]]
deps = ["Git_jll"]
git-tree-sha1 = "d7bffc3fe097e9589145493c08c41297b457e5d0"
uuid = "d7ba0133-e1db-5d97-8f8c-041e4b3a1eb2"
version = "1.2.1"

[[deps.GitHub]]
deps = ["Base64", "Dates", "HTTP", "JSON", "MbedTLS", "Sockets", "SodiumSeal"]
git-tree-sha1 = "c8594dff1ed76e232d8063b2a2555335900af6f3"
uuid = "bc5e4493-9b4d-5f90-b8aa-2b2bcaad7a26"
version = "5.7.0"

[[deps.Git_jll]]
deps = ["Artifacts", "Expat_jll", "Gettext_jll", "JLLWrappers", "LibCURL_jll", "Libdl", "Libiconv_jll", "OpenSSL_jll", "PCRE2_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "33be385f3432a5a5b7f6965af9592d4407f3167f"
uuid = "f8c6e375-362e-5223-8a59-34ff63f689eb"
version = "2.31.0+0"

[[deps.Glib_jll]]
deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "04690cc5008b38ecbdfede949220bc7d9ba26397"
uuid = "7746bdde-850d-59dc-9ae8-88ece973131d"
version = "2.59.0+4"

[[deps.Grisu]]
git-tree-sha1 = "53bb909d1151e57e2484c3d1b53e19552b887fb2"
uuid = "42e2da0e-8278-4e71-bc24-59509adca0fe"
version = "1.0.2"

[[deps.HDF5_jll]]
deps = ["Artifacts", "JLLWrappers", "LibCURL_jll", "Libdl", "OpenSSL_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "fd83fa0bde42e01952757f01149dd968c06c4dba"
uuid = "0234f1f7-429e-5d53-9886-15a909be8d59"
version = "1.12.0+1"

[[deps.HTTP]]
deps = ["Base64", "Dates", "IniFile", "Logging", "MbedTLS", "NetworkOptions", "Sockets", "URIs"]
git-tree-sha1 = "0fa77022fe4b511826b39c894c90daf5fce3334a"
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
version = "0.9.17"

[[deps.Hyperscript]]
deps = ["Test"]
git-tree-sha1 = "8d511d5b81240fc8e6802386302675bdf47737b9"
uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91"
version = "0.0.4"

[[deps.HypertextLiteral]]
git-tree-sha1 = "2b078b5a615c6c0396c77810d92ee8c6f470d238"
uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
version = "0.9.3"

[[deps.IOCapture]]
deps = ["Logging", "Random"]
git-tree-sha1 = "f7be53659ab06ddc986428d3a9dcc95f6fa6705a"
uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89"
version = "0.2.2"

[[deps.IniFile]]
deps = ["Test"]
git-tree-sha1 = "098e4d2c533924c921f9f9847274f2ad89e018b8"
uuid = "83e8ac13-25f8-5344-8a64-a9f2b223428f"
version = "0.5.0"

[[deps.InlineStrings]]
deps = ["Parsers"]
git-tree-sha1 = "8d70835a3759cdd75881426fced1508bb7b7e1b6"
uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48"
version = "1.1.1"

[[deps.InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[deps.InverseFunctions]]
deps = ["Test"]
git-tree-sha1 = "a7254c0acd8e62f1ac75ad24d5db43f5f19f3c65"
uuid = "3587e190-3f89-42d0-90ee-14403ec27112"
version = "0.1.2"

[[deps.InvertedIndices]]
git-tree-sha1 = "bee5f1ef5bf65df56bdd2e40447590b272a5471f"
uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
version = "1.1.0"

[[deps.IrrationalConstants]]
git-tree-sha1 = "7fd44fd4ff43fc60815f8e764c0f352b83c49151"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.1.1"

[[deps.IterTools]]
git-tree-sha1 = "fa6287a4469f5e048d763df38279ee729fbd44e5"
uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
version = "1.4.0"

[[deps.IteratorInterfaceExtensions]]
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
uuid = "82899510-4779-5014-852e-03e436cf321d"
version = "1.0.0"

[[deps.JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "642a199af8b68253517b80bd3bfd17eb4e84df6e"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.3.0"

[[deps.JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
git-tree-sha1 = "8076680b162ada2a031f707ac7b4953e30667a37"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.2"

[[deps.JpegTurbo_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "d735490ac75c5cb9f1b00d8b5509c11984dc6943"
uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8"
version = "2.1.0+0"

[[deps.LAME_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "f6250b16881adf048549549fba48b1161acdac8c"
uuid = "c1c5ebd0-6772-5130-a774-d5fcae4a789d"
version = "3.100.1+0"

[[deps.LZO_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "e5b909bcf985c5e2605737d2ce278ed791b89be6"
uuid = "dd4b983a-f0e5-5f8d-a1b7-129d4a5fb1ac"
version = "2.10.1+0"

[[deps.LaTeXStrings]]
git-tree-sha1 = "f2355693d6778a178ade15952b7ac47a4ff97996"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.3.0"

[[deps.Latexify]]
deps = ["Formatting", "InteractiveUtils", "LaTeXStrings", "MacroTools", "Markdown", "Printf", "Requires"]
git-tree-sha1 = "a8f4f279b6fa3c3c4f1adadd78a621b13a506bce"
uuid = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
version = "0.15.9"

[[deps.LazyArtifacts]]
deps = ["Artifacts", "Pkg"]
uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3"

[[deps.LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"

[[deps.LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"

[[deps.LibGit2]]
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

[[deps.LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"

[[deps.LibVPX_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "12ee7e23fa4d18361e7c2cde8f8337d4c3101bc7"
uuid = "dd192d2f-8180-539f-9fb4-cc70b1dcf69a"
version = "1.10.0+0"

[[deps.Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

[[deps.Libffi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "0b4a5d71f3e5200a7dff793393e09dfc2d874290"
uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490"
version = "3.2.2+1"

[[deps.Libgcrypt_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgpg_error_jll", "Pkg"]
git-tree-sha1 = "64613c82a59c120435c067c2b809fc61cf5166ae"
uuid = "d4300ac3-e22c-5743-9152-c294e39db1e4"
version = "1.8.7+0"

[[deps.Libglvnd_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll", "Xorg_libXext_jll"]
git-tree-sha1 = "7739f837d6447403596a75d19ed01fd08d6f56bf"
uuid = "7e76a0d4-f3c7-5321-8279-8d96eeed0f29"
version = "1.3.0+3"

[[deps.Libgpg_error_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "c333716e46366857753e273ce6a69ee0945a6db9"
uuid = "7add5ba3-2f88-524e-9cd5-f83b8a55f7b8"
version = "1.42.0+0"

[[deps.Libiconv_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "42b62845d70a619f063a7da093d995ec8e15e778"
uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531"
version = "1.16.1+1"

[[deps.Libmount_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "9c30530bf0effd46e15e0fdcf2b8636e78cbbd73"
uuid = "4b2f31a3-9ecc-558c-b454-b3730dcb73e9"
version = "2.35.0+0"

[[deps.Libtiff_jll]]
deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Pkg", "Zlib_jll", "Zstd_jll"]
git-tree-sha1 = "340e257aada13f95f98ee352d316c3bed37c8ab9"
uuid = "89763e89-9b03-5906-acba-b20f662cd828"
version = "4.3.0+0"

[[deps.Libuuid_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7f3efec06033682db852f8b3bc3c1d2b0a0ab066"
uuid = "38a345b3-de98-5d2b-a5d3-14cd9215e700"
version = "2.36.0+0"

[[deps.LinearAlgebra]]
deps = ["Libdl", "libblastrampoline_jll"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[[deps.LogExpFunctions]]
deps = ["ChainRulesCore", "ChangesOfVariables", "DocStringExtensions", "InverseFunctions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "e5718a00af0ab9756305a0392832c8952c7426c1"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.6"

[[deps.Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[deps.Lz4_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "5d494bc6e85c4c9b626ee0cab05daa4085486ab1"
uuid = "5ced341a-0733-55b8-9ab6-a4889d929147"
version = "1.9.3+0"

[[deps.MITgcmTools]]
deps = ["Artifacts", "ClimateModels", "DataFrames", "Dates", "LazyArtifacts", "MeshArrays", "NetCDF", "OrderedCollections", "Printf", "SparseArrays", "Suppressor", "UUIDs"]
git-tree-sha1 = "85fd18c07803b16af3e317e9568d526f5ca61853"
uuid = "62725fbc-3a66-4df3-9000-e33e85b3a198"
version = "0.1.32"

[[deps.MacroTools]]
deps = ["Markdown", "Random"]
git-tree-sha1 = "3d3e902b31198a27340d0bf00d6ac452866021cf"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.9"

[[deps.Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[deps.MbedTLS]]
deps = ["Dates", "MbedTLS_jll", "Random", "Sockets"]
git-tree-sha1 = "1c38e51c3d08ef2278062ebceade0e46cefc96fe"
uuid = "739be429-bea8-5141-9913-cc70e7f3736d"
version = "1.0.3"

[[deps.MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"

[[deps.Measures]]
git-tree-sha1 = "e498ddeee6f9fdb4551ce855a46f54dbd900245f"
uuid = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
version = "0.3.1"

[[deps.MeshArrays]]
deps = ["CatViews", "Dates", "Downloads", "LazyArtifacts", "NearestNeighbors", "Pkg", "Printf", "SparseArrays", "Statistics", "Unitful"]
git-tree-sha1 = "c5b9b98540a900934d9b531f8a153ce49016cec7"
uuid = "cb8c808f-1acf-59a3-9d2b-6e38d009f683"
version = "0.2.31"

[[deps.Missings]]
deps = ["DataAPI"]
git-tree-sha1 = "bf210ce90b6c9eed32d25dbcae1ebc565df2687f"
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
version = "1.0.2"

[[deps.Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[deps.Mocking]]
deps = ["Compat", "ExprTools"]
git-tree-sha1 = "29714d0a7a8083bba8427a4fbfb00a540c681ce7"
uuid = "78c3b35d-d492-501b-9361-3d52fe80e533"
version = "0.7.3"

[[deps.MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"

[[deps.NaNMath]]
git-tree-sha1 = "f755f36b19a5116bb580de457cda0c140153f283"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "0.3.6"

[[deps.NearestNeighbors]]
deps = ["Distances", "StaticArrays"]
git-tree-sha1 = "16baacfdc8758bc374882566c9187e785e85c2f0"
uuid = "b8a86587-4115-5ab1-83bc-aa920d37bbce"
version = "0.4.9"

[[deps.NetCDF]]
deps = ["DiskArrays", "Formatting", "NetCDF_jll"]
git-tree-sha1 = "23b0e32fde256a4e2e497e678abcf956ed26204b"
uuid = "30363a11-5582-574a-97bb-aa9a979735b9"
version = "0.11.3"

[[deps.NetCDF_jll]]
deps = ["Artifacts", "HDF5_jll", "JLLWrappers", "LibCURL_jll", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Pkg", "Zlib_jll", "nghttp2_jll"]
git-tree-sha1 = "0cf4d1bf2ef45156aed85c9ac5f8c7e697d9288c"
uuid = "7243133f-43d8-5620-bbf4-c2c921802cf3"
version = "400.702.400+0"

[[deps.NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"

[[deps.OffsetArrays]]
deps = ["Adapt"]
git-tree-sha1 = "043017e0bdeff61cfbb7afeb558ab29536bbb5ed"
uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
version = "1.10.8"

[[deps.Ogg_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7937eda4681660b4d6aeeecc2f7e1c81c8ee4e2f"
uuid = "e7412a2a-1a6e-54c0-be00-318e2571c051"
version = "1.3.5+0"

[[deps.OpenBLAS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"

[[deps.OpenSSL_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "15003dcb7d8db3c6c857fda14891a539a8f2705a"
uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
version = "1.1.10+0"

[[deps.Opus_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "51a08fb14ec28da2ec7a927c4337e4332c2a4720"
uuid = "91d4177d-7536-5919-b921-800302f37372"
version = "1.3.2+0"

[[deps.OrderedCollections]]
git-tree-sha1 = "85f8e6578bf1f9ee0d11e7bb1b1456435479d47c"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.4.1"

[[deps.PCRE2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "efcefdf7-47ab-520b-bdef-62a2eaa19f15"

[[deps.PCRE_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b2a7af664e098055a7529ad1a900ded962bca488"
uuid = "2f80f16e-611a-54ab-bc61-aa92de5b98fc"
version = "8.44.0+0"

[[deps.Parsers]]
deps = ["Dates"]
git-tree-sha1 = "d7fa6237da8004be601e19bd6666083056649918"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.1.3"

[[deps.Pixman_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b4f5d02549a10e20780a24fce72bea96b6329e29"
uuid = "30392449-352a-5448-841d-b1acce4e97dc"
version = "0.40.1+0"

[[deps.Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[[deps.PlotThemes]]
deps = ["PlotUtils", "Requires", "Statistics"]
git-tree-sha1 = "a3a964ce9dc7898193536002a6dd892b1b5a6f1d"
uuid = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
version = "2.0.1"

[[deps.PlotUtils]]
deps = ["ColorSchemes", "Colors", "Dates", "Printf", "Random", "Reexport", "Statistics"]
git-tree-sha1 = "e4fe0b50af3130ddd25e793b471cb43d5279e3e6"
uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043"
version = "1.1.1"

[[deps.Plots]]
deps = ["Base64", "Contour", "Dates", "Downloads", "FFMPEG", "FixedPointNumbers", "GR", "GeometryBasics", "JSON", "Latexify", "LinearAlgebra", "Measures", "NaNMath", "PlotThemes", "PlotUtils", "Printf", "REPL", "Random", "RecipesBase", "RecipesPipeline", "Reexport", "Requires", "Scratch", "Showoff", "SparseArrays", "Statistics", "StatsBase", "UUIDs", "UnicodeFun"]
git-tree-sha1 = "65ebc27d8c00c84276f14aaf4ff63cbe12016c70"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
version = "1.25.2"

[[deps.PlutoUI]]
deps = ["AbstractPlutoDingetjes", "Base64", "ColorTypes", "Dates", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "Markdown", "Random", "Reexport", "UUIDs"]
git-tree-sha1 = "93cf0910f09a9607add290a3a2585aa376b4feb6"
uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
version = "0.7.25"

[[deps.PooledArrays]]
deps = ["DataAPI", "Future"]
git-tree-sha1 = "db3a23166af8aebf4db5ef87ac5b00d36eb771e2"
uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720"
version = "1.4.0"

[[deps.Preferences]]
deps = ["TOML"]
git-tree-sha1 = "00cfd92944ca9c760982747e9a1d0d5d86ab1e5a"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.2.2"

[[deps.PrettyTables]]
deps = ["Crayons", "Formatting", "Markdown", "Reexport", "Tables"]
git-tree-sha1 = "b7ff9f9ce50eab241e978cd975ad4ae113f5a41f"
uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
version = "1.3.0"

[[deps.Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[deps.Qt5Base_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Fontconfig_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "OpenSSL_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libxcb_jll", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_keysyms_jll", "Xorg_xcb_util_renderutil_jll", "Xorg_xcb_util_wm_jll", "Zlib_jll", "xkbcommon_jll"]
git-tree-sha1 = "16626cfabbf7206d60d84f2bf4725af7b37d4a77"
uuid = "ea2cea3b-5b76-57ae-a6ef-0a8af62496e1"
version = "5.15.2+0"

[[deps.REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[deps.Random]]
deps = ["SHA", "Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[deps.RecipesBase]]
git-tree-sha1 = "6bf3f380ff52ce0832ddd3a2a7b9538ed1bcca7d"
uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
version = "1.2.1"

[[deps.RecipesPipeline]]
deps = ["Dates", "NaNMath", "PlotUtils", "RecipesBase"]
git-tree-sha1 = "7ad0dfa8d03b7bcf8c597f59f5292801730c55b8"
uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c"
version = "0.4.1"

[[deps.Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"

[[deps.Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "8f82019e525f4d5c669692772a6f4b0a58b06a6a"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.2.0"

[[deps.Retry]]
git-tree-sha1 = "41ac127cd281bb33e42aba46a9d3b25cd35fc6d5"
uuid = "20febd7b-183b-5ae2-ac4a-720e7ce64774"
version = "0.4.1"

[[deps.SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"

[[deps.Scratch]]
deps = ["Dates"]
git-tree-sha1 = "0b4b7f1393cff97c33891da2a0bf69c6ed241fda"
uuid = "6c6a2e73-6563-6170-7368-637461726353"
version = "1.1.0"

[[deps.SentinelArrays]]
deps = ["Dates", "Random"]
git-tree-sha1 = "244586bc07462d22aed0113af9c731f2a518c93e"
uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
version = "1.3.10"

[[deps.Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[deps.SharedArrays]]
deps = ["Distributed", "Mmap", "Random", "Serialization"]
uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383"

[[deps.Showoff]]
deps = ["Dates", "Grisu"]
git-tree-sha1 = "91eddf657aca81df9ae6ceb20b959ae5653ad1de"
uuid = "992d4aef-0814-514b-bc4d-f2e9a6c4116f"
version = "1.0.3"

[[deps.Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"

[[deps.SodiumSeal]]
deps = ["Base64", "Libdl", "libsodium_jll"]
git-tree-sha1 = "80cef67d2953e33935b41c6ab0a178b9987b1c99"
uuid = "2133526b-2bfb-4018-ac12-889fb3908a75"
version = "0.1.1"

[[deps.SortingAlgorithms]]
deps = ["DataStructures"]
git-tree-sha1 = "b3363d7460f7d098ca0912c69b082f75625d7508"
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
version = "1.0.1"

[[deps.SparseArrays]]
deps = ["LinearAlgebra", "Random"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[[deps.StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "3c76dde64d03699e074ac02eb2e8ba8254d428da"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.2.13"

[[deps.Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[[deps.StatsAPI]]
git-tree-sha1 = "0f2aa8e32d511f758a2ce49208181f7733a0936a"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.1.0"

[[deps.StatsBase]]
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "2bb0cb32026a66037360606510fca5984ccc6b75"
uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
version = "0.33.13"

[[deps.StructArrays]]
deps = ["Adapt", "DataAPI", "StaticArrays", "Tables"]
git-tree-sha1 = "2ce41e0d042c60ecd131e9fb7154a3bfadbf50d3"
uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
version = "0.6.3"

[[deps.Suppressor]]
git-tree-sha1 = "a819d77f31f83e5792a76081eee1ea6342ab8787"
uuid = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
version = "0.2.0"

[[deps.TOML]]
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[[deps.TableTraits]]
deps = ["IteratorInterfaceExtensions"]
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
version = "1.0.1"

[[deps.Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"]
git-tree-sha1 = "bb1064c9a84c52e277f1096cf41434b675cd368b"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.6.1"

[[deps.Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"

[[deps.Test]]
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[[deps.TranscodingStreams]]
deps = ["Random", "Test"]
git-tree-sha1 = "216b95ea110b5972db65aa90f88d8d89dcb8851c"
uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa"
version = "0.9.6"

[[deps.URIs]]
git-tree-sha1 = "97bbe755a53fe859669cd907f2d96aee8d2c1355"
uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
version = "1.3.0"

[[deps.UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[deps.Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[[deps.UnicodeFun]]
deps = ["REPL"]
git-tree-sha1 = "53915e50200959667e78a92a418594b428dffddf"
uuid = "1cfade01-22cf-5700-b092-accc4b62d6e1"
version = "0.4.1"

[[deps.Unitful]]
deps = ["ConstructionBase", "Dates", "LinearAlgebra", "Random"]
git-tree-sha1 = "0992ed0c3ef66b0390e5752fe60054e5ff93b908"
uuid = "1986cc42-f94f-5a68-af5c-568840ba703d"
version = "1.9.2"

[[deps.Wayland_jll]]
deps = ["Artifacts", "Expat_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "3e61f0b86f90dacb0bc0e73a0c5a83f6a8636e23"
uuid = "a2964d1f-97da-50d4-b82a-358c7fce9d89"
version = "1.19.0+0"

[[deps.Wayland_protocols_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "66d72dc6fcc86352f01676e8f0f698562e60510f"
uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91"
version = "1.23.0+0"

[[deps.WeakRefStrings]]
deps = ["DataAPI", "InlineStrings", "Parsers"]
git-tree-sha1 = "c69f9da3ff2f4f02e811c3323c22e5dfcb584cfa"
uuid = "ea10d353-3f73-51f8-a26c-33c1cb351aa5"
version = "1.4.1"

[[deps.XML2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "1acf5bdf07aa0907e0a37d3718bb88d4b687b74a"
uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a"
version = "2.9.12+0"

[[deps.XMLDict]]
deps = ["EzXML", "IterTools", "OrderedCollections"]
git-tree-sha1 = "d9a3faf078210e477b291c79117676fca54da9dd"
uuid = "228000da-037f-5747-90a9-8195ccbf91a5"
version = "0.4.1"

[[deps.XSLT_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgcrypt_jll", "Libgpg_error_jll", "Libiconv_jll", "Pkg", "XML2_jll", "Zlib_jll"]
git-tree-sha1 = "91844873c4085240b95e795f692c4cec4d805f8a"
uuid = "aed1982a-8fda-507f-9586-7b0439959a61"
version = "1.1.34+0"

[[deps.Xorg_libX11_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll", "Xorg_xtrans_jll"]
git-tree-sha1 = "5be649d550f3f4b95308bf0183b82e2582876527"
uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc"
version = "1.6.9+4"

[[deps.Xorg_libXau_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4e490d5c960c314f33885790ed410ff3a94ce67e"
uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec"
version = "1.0.9+4"

[[deps.Xorg_libXcursor_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "12e0eb3bc634fa2080c1c37fccf56f7c22989afd"
uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724"
version = "1.2.0+4"

[[deps.Xorg_libXdmcp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4fe47bd2247248125c428978740e18a681372dd4"
uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05"
version = "1.1.3+4"

[[deps.Xorg_libXext_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "b7c0aa8c376b31e4852b360222848637f481f8c3"
uuid = "1082639a-0dae-5f34-9b06-72781eeb8cb3"
version = "1.3.4+4"

[[deps.Xorg_libXfixes_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "0e0dc7431e7a0587559f9294aeec269471c991a4"
uuid = "d091e8ba-531a-589c-9de9-94069b037ed8"
version = "5.0.3+4"

[[deps.Xorg_libXi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXfixes_jll"]
git-tree-sha1 = "89b52bc2160aadc84d707093930ef0bffa641246"
uuid = "a51aa0fd-4e3c-5386-b890-e753decda492"
version = "1.7.10+4"

[[deps.Xorg_libXinerama_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll"]
git-tree-sha1 = "26be8b1c342929259317d8b9f7b53bf2bb73b123"
uuid = "d1454406-59df-5ea1-beac-c340f2130bc3"
version = "1.1.4+4"

[[deps.Xorg_libXrandr_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "34cea83cb726fb58f325887bf0612c6b3fb17631"
uuid = "ec84b674-ba8e-5d96-8ba1-2a689ba10484"
version = "1.5.2+4"

[[deps.Xorg_libXrender_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "19560f30fd49f4d4efbe7002a1037f8c43d43b96"
uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa"
version = "0.9.10+4"

[[deps.Xorg_libpthread_stubs_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "6783737e45d3c59a4a4c4091f5f88cdcf0908cbb"
uuid = "14d82f49-176c-5ed1-bb49-ad3f5cbd8c74"
version = "0.1.0+3"

[[deps.Xorg_libxcb_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"]
git-tree-sha1 = "daf17f441228e7a3833846cd048892861cff16d6"
uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b"
version = "1.13.0+3"

[[deps.Xorg_libxkbfile_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "926af861744212db0eb001d9e40b5d16292080b2"
uuid = "cc61e674-0454-545c-8b26-ed2c68acab7a"
version = "1.1.0+4"

[[deps.Xorg_xcb_util_image_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "0fab0a40349ba1cba2c1da699243396ff8e94b97"
uuid = "12413925-8142-5f55-bb0e-6d7ca50bb09b"
version = "0.4.0+1"

[[deps.Xorg_xcb_util_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll"]
git-tree-sha1 = "e7fd7b2881fa2eaa72717420894d3938177862d1"
uuid = "2def613f-5ad1-5310-b15b-b15d46f528f5"
version = "0.4.0+1"

[[deps.Xorg_xcb_util_keysyms_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "d1151e2c45a544f32441a567d1690e701ec89b00"
uuid = "975044d2-76e6-5fbe-bf08-97ce7c6574c7"
version = "0.4.0+1"

[[deps.Xorg_xcb_util_renderutil_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "dfd7a8f38d4613b6a575253b3174dd991ca6183e"
uuid = "0d47668e-0667-5a69-a72c-f761630bfb7e"
version = "0.3.9+1"

[[deps.Xorg_xcb_util_wm_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "e78d10aab01a4a154142c5006ed44fd9e8e31b67"
uuid = "c22f9ab0-d5fe-5066-847c-f4bb1cd4e361"
version = "0.4.1+1"

[[deps.Xorg_xkbcomp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxkbfile_jll"]
git-tree-sha1 = "4bcbf660f6c2e714f87e960a171b119d06ee163b"
uuid = "35661453-b289-5fab-8a00-3d9160c6a3a4"
version = "1.4.2+4"

[[deps.Xorg_xkeyboard_config_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xkbcomp_jll"]
git-tree-sha1 = "5c8424f8a67c3f2209646d4425f3d415fee5931d"
uuid = "33bec58e-1273-512f-9401-5d533626f822"
version = "2.27.0+4"

[[deps.Xorg_xtrans_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "79c31e7844f6ecf779705fbc12146eb190b7d845"
uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10"
version = "1.4.0+3"

[[deps.Zarr]]
deps = ["AWS", "Blosc", "CodecZlib", "DataStructures", "Dates", "DiskArrays", "HTTP", "JSON", "OffsetArrays", "Pkg"]
git-tree-sha1 = "18ac3fd29790edeee42bfed5020b12ae61a029d0"
uuid = "0a941bbe-ad1d-11e8-39d9-ab76183a1d99"
version = "0.6.3"

[[deps.Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"

[[deps.Zstd_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "cc4bf3fdde8b7e3e9fa0351bdeedba1cf3b7f6e6"
uuid = "3161d3a3-bdf6-5164-811a-617609db77b4"
version = "1.5.0+0"

[[deps.libass_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "acc685bcf777b2202a904cdcb49ad34c2fa1880c"
uuid = "0ac62f75-1d6f-5e53-bd7c-93b484bb37c0"
version = "0.14.0+4"

[[deps.libblastrampoline_jll]]
deps = ["Artifacts", "Libdl", "OpenBLAS_jll"]
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"

[[deps.libfdk_aac_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7a5780a0d9c6864184b3a2eeeb833a0c871f00ab"
uuid = "f638f0a6-7fb0-5443-88ba-1cc74229b280"
version = "0.1.6+4"

[[deps.libpng_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "94d180a6d2b5e55e447e2d27a29ed04fe79eb30c"
uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f"
version = "1.6.38+0"

[[deps.libsodium_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "848ab3d00fe39d6fbc2a8641048f8f272af1c51e"
uuid = "a9144af2-ca23-56d9-984f-0d03f7b5ccf8"
version = "1.0.20+0"

[[deps.libvorbis_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Ogg_jll", "Pkg"]
git-tree-sha1 = "c45f4e40e7aafe9d086379e5578947ec8b95a8fb"
uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a"
version = "1.3.7+0"

[[deps.nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"

[[deps.p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"

[[deps.x264_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "d713c1ce4deac133e3334ee12f4adff07f81778f"
uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a"
version = "2020.7.14+2"

[[deps.x265_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "487da2f8f2f0c8ee0e83f39d13037d6bbf0a45ab"
uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76"
version = "3.0.0+3"

[[deps.xkbcommon_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll", "Wayland_protocols_jll", "Xorg_libxcb_jll", "Xorg_xkeyboard_config_jll"]
git-tree-sha1 = "ece2350174195bb31de1a63bea3a41ae1aa593b6"
uuid = "d8fb68d0-12a3-5cfd-a85a-d49703b185fd"
version = "0.9.1+5"
"""

# ╔═╡ Cell order:
# ╟─8784eb6f-f6ca-4466-97bc-eaa80872185c
# ╟─9f3e266b-7623-4c77-b381-4eafe3600a33
# ╟─385d8630-2250-44d9-b1d1-3405841cd2d2
# ╟─e1559cdc-b180-4976-ac46-e1afa991d62c
# ╟─30273b0c-eb79-4fca-bda7-e8f72cf79e04
# ╟─10c8fde5-ed53-47b2-8a8d-55ce21c12152
# ╟─6ef93b0e-859f-11eb-1b3b-d76b26d678dc
# ╟─eca925ba-8816-11eb-1d6d-39bf08bfe979
# ╟─2499d523-f141-477a-be18-d46885c58546
# ╟─96492c18-86bd-11eb-35ca-dff79e6e7818
# ╟─d0bbb668-86e0-11eb-1a9b-8f2b0175f7c1
# ╟─8ad9d646-4eec-45b9-938b-21df34da2d6b
# ╟─6404fddf-3c46-4015-9580-b9159c76b30a
# ╟─6edcbba3-8485-44d2-940a-e4f2df019373
# ╟─60a68f95-f5f4-4d75-9c5f-30e2ae141c4b
# ╟─3d4fd8e0-0e89-4018-8275-103fb29a5000
# ╟─573e6c6b-055c-4e79-af42-15159e40f7be
# ╟─de12dd76-7641-4712-a944-814ffc427a26
# ╟─ac7e1bd6-fa74-4067-bf35-e7f37bdddc68
# ╟─4f09cda6-5bf9-4a7b-9fa9-edc00f852c07
# ╟─af176e6c-8695-11eb-3e34-91fbdb9c52fa
# ╟─8cf4d8ca-84eb-11eb-22d2-255ce7237090
# ╟─734e2b5a-8866-11eb-0025-bd9544f4c30d
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


text:
using DigitSetSudoku

root = Pkg.dir("DigitSetSudoku")

function timepuzzles(filehandle)
    timesum = 0.0
    timemax = 0.0
    n = 0
    for line in eachline(filehandle)
        puzzle = SudokuPuzzle(line)
        time = @elapsed solve(puzzle)
        timesum += time
        timemax = max(time, timemax)
        n += 1
    end
    @printf "Mean time: %.6f seconds.\n" timesum/n
    @printf "Max time: %.6f seconds.\n" timemax
end

println("50 easy puzzles")
open(timepuzzles, joinpath(root, "puzzledata", "easy50.txt"))
println()

println("95 hard puzzles")
open(timepuzzles, joinpath(root, "puzzledata", "top95.txt"))
println()

println("11 hardest puzzles")
open(timepuzzles, joinpath(root, "puzzledata", "hardest.txt"))
println()

println("20 very hard puzzles")
open(timepuzzles, joinpath(root, "puzzledata", "20veryhard.txt"))


text:
function shufflevector_instrs(W::Int, @nospecialize(T), I::Vector{String}, W2::Int)
    W2 > W && throw(ArgumentError("W for vector 1 must be at least W for vector two, but W₁ = $W < W₂ = $W2."))
    typ::String = (LLVM_TYPES[T])::String
    vtyp1::String = "<$W x $typ>"
    M::Int = length(I)
    vtyp3::String = "<$M x i32>"
    vtypr::String = "<$M x $typ>"
    mask::String = '<' * join(I, ", ")::String * '>'
    if ((W2 == 0) | (W2 == W))
        v2 = W2 == 0 ? "undef" : "%1"
        M, """
            %res = shufflevector $vtyp1 %0, $vtyp1 $v2, $vtyp3 $mask
            ret $vtypr %res
        """
    else
        vtyp0 = "<$W2 x $typ>"
        maskpad = '<' * join(map(w->string("i32 ", w > W2 ? "undef" : string(w-1)), 1:W), ", ") * '>'
        M, """
            %pad = shufflevector $vtyp0 %1, $vtyp0 undef, <$W x i32> $maskpad
            %res = shufflevector $vtyp1 %0, $vtyp1 %pad, $vtyp3 $mask
            ret $vtypr %res
        """
    end
end
function tupletostringvector(@nospecialize(x::NTuple{N,Int})) where {N}
  y = Vector{String}(undef, N)
  @inbounds for n ∈ 1:N
    y[n] = string("i32 ", x[n])
  end
  y
end
@generated function shufflevector(v1::Vec{W,T}, v2::Vec{W2,T}, ::Val{I}) where {W,W2,T,I}
    W ≥ W2 || throw(ArgumentError("`v1` should be at least as long as `v2`, but `v1` is a `Vec{$W,$T}` and `v2` is a `Vec{$W2,$T}`."))
    M, instrs = shufflevector_instrs(W, T, tupletostringvector(I), W2)
    quote
        $(Expr(:meta, :inline))
        Vec($LLVMCALL($instrs, _Vec{$M,$T}, Tuple{_Vec{$W,$T}, _Vec{$W2,$T}}, data(v1), data(v2)))
    end
end
@generated function shufflevector(v1::Vec{W,T}, ::Val{I}) where {W,T,I}
    M, instrs = shufflevector_instrs(W, T, tupletostringvector(I), 0)
    quote
        $(Expr(:meta, :inline))
        Vec($LLVMCALL($instrs, _Vec{$M,$T}, Tuple{_Vec{$W,$T}}, data(v1)))
    end
end
@generated function vresize(::Union{StaticInt{W},Val{W}}, v::Vec{L,T}) where {W,L,T}
    typ = LLVM_TYPES[T]
    mask = '<' * join(map(x->string("i32 ", x ≥ L ? "undef" : string(x)), 0:W-1), ", ") * '>'
    instrs = """
        %res = shufflevector <$L x $typ> %0, <$L x $typ> undef, <$W x i32> $mask
        ret <$W x $typ> %res
    """
    quote
        $(Expr(:meta, :inline))
        Vec($LLVMCALL($instrs, _Vec{$W,$T}, Tuple{_Vec{$L,$T}}, data(v)))
    end
end
@generated function vresize(::Union{StaticInt{W},Val{W}}, v::T) where {W,T<:NativeTypes}
    typ = LLVM_TYPES[T]
    vtyp = vtype(W, typ)
    instrs = """
        %ie = insertelement $vtyp undef, $typ %0, i32 0
        ret $vtyp %ie
    """
    quote
        $(Expr(:meta, :inline))
        Vec($LLVMCALL($instrs, _Vec{$W,$T}, Tuple{$T}, v))
    end
end
@generated function shufflevector(i::MM{W,X}, ::Val{I}) where {W,X,I}
    allincr = true
    L = length(I)
    for l ∈ 2:L
        allincr &= (I[l] == I[l-1] + 1)
    end
    allincr || return Expr(:block, Expr(:meta,:inline), :(shufflevector(Vec(i), Val{$I}())))
    Expr(:block, Expr(:meta,:inline), :(MM{$L,$X}( extractelement(i, $(first(I))) )))
end
@generated function Base.vcat(a::Vec{W1,T}, b::Vec{W2,T}) where {W1,W2,T}
    W1 ≥ W2 || throw(ArgumentError("`v1` should be at least as long as `v2`, but `v1` is a `Vec{$W1,$T}` and `v2` is a `Vec{$W2,$T}`."))
    mask = Vector{String}(undef, 2W1)
    for w ∈ 0:W1+W2-1
        mask[w+1] = string("i32 ", w)
    end
    for w ∈ W1+W2:2W1-1
        mask[w+1] = "i32 undef"
    end
    M, instrs = shufflevector_instrs(W1, T, mask, W2)
    quote
        $(Expr(:meta, :inline))
        Vec($LLVMCALL($instrs, _Vec{$M,$T}, Tuple{_Vec{$W1,$T}, _Vec{$W2,$T}}, data(a), data(b)))
    end
end

@inline Base.vcat(a::VecUnroll{N,W1,T,Vec{W1,T}},b::VecUnroll{N,W2,T,Vec{W2,T}}) where {N,W1,W2,T} = VecUnroll(fmap(vcat, data(a), data(b)))
@generated function Base.hcat(a::VecUnroll{N1,W,T,V}, b::VecUnroll{N2,W,T,V}) where {N1,N2,W,T,V}
    q = Expr(:block, Expr(:meta,:inline), :(da = data(a)), :(db = data(b)))
    t = Expr(:tuple)
    for (d,N) ∈ ((:da,N1),(:db,N2))
        for n ∈ 1:N
            push!(t.args, Expr(:call, :getfield, d, n, false))
        end
    end
    push!(q.args, :(VecUnroll($t)))
    q
end

function transpose_vecunroll_quote(W)
    ispow2(W) || throw(ArgumentError("Only supports powers of 2 for vector width and unrolling factor, but recieved $W = $W."))
    log2W = intlog2(W)
    q = Expr(:block, Expr(:meta, :inline), :(vud = data(vu)))
    N = W # N vectors of length W
    vectors1 = [Symbol(:v_, n) for n ∈ 0:N-1]
    vectors2 = [Symbol(:v_, n+N) for n ∈ 0:N-1]
    # z = Expr(:call, Expr(:curly, Expr(:(.), :VectorizationBase, QuoteNode(:MM)), W), 0)
    # for n ∈ 1:N
    #     push!(q.args, Expr(:(=), vectors1[n], Expr(:call, Expr(:(.), :VectorizationBase, QuoteNode(:vload)), :ptrA, Expr(:tuple, z, n-1))))
    # end
    for n ∈ 1:N
        push!(q.args, Expr(:(=), vectors1[n], Expr(:call, :getfield, :vud, n, false)))
    end
    Nhalf = N >>> 1
    vecstride = 1
    partition_stride = 2
    for nsplits in 0:log2W-1
        shuffle0 = transposeshuffle(nsplits, W, false)
        shuffle1 = transposeshuffle(nsplits, W, true)
        for partition ∈ 0:(W >>> (nsplits+1))-1
            for _n1 ∈ 1:vecstride
                n1 = partition * partition_stride + _n1
                n2 = n1 + vecstride
                v11 = vectors1[n1]
                v12 = vectors1[n2]
                v21 = vectors2[n1]
                v22 = vectors2[n2]
                shuff1 = Expr(:call, :shufflevector, v11, v12, shuffle0)
                shuff2 = Expr(:call, :shufflevector, v11, v12, shuffle1)
                push!(q.args, Expr(:(=), v21, shuff1))
                push!(q.args, Expr(:(=), v22, shuff2))
            end
        end
        vectors1, vectors2 = vectors2, vectors1
        vecstride <<= 1
        partition_stride <<= 1
        # @show vecstride <<= 1
    end
    t = Expr(:tuple)
    for n ∈ 1:N
        push!(t.args, vectors1[n])
    end
    # for n ∈ 1:N
    #     push!(q.args, Expr(:(=), vectors1[n], Expr(:call, Expr(:(.), :VectorizationBase, QuoteNode(:vstore!)), :ptrB, vectors1[n], Expr(:tuple, z, n-1))))
    # end
    push!(q.args, Expr(:call, :VecUnroll, t))
    q
end
function subset_tup(W, o)
    t = Expr(:tuple)
    for w ∈ o:W-1+o
        push!(t.args, w)
    end
    Expr(:call, Expr(:curly, :Val, t))
end
function transpose_vecunroll_quote_W_larger(N,W)
    (ispow2(W) & ispow2(N)) || throw(ArgumentError("Only supports powers of 2 for vector width and unrolling factor, but recieved $N and $W."))
    log2W = intlog2(W)
    log2N = intlog2(N)
    q = Expr(:block, Expr(:meta, :inline), :(vud = data(vu)))
    # N = W # N vectors of length W
    vectors1 = [Symbol(:v_, n) for n ∈ 0:N-1]
    vectors2 = [Symbol(:v_, n+N) for n ∈ 0:N-1]
    # z = Expr(:call, Expr(:curly, Expr(:(.), :VectorizationBase, QuoteNode(:MM)), W), 0)
    # for n ∈ 1:N
    #     push!(q.args, Expr(:(=), vectors1[n], Expr(:call, Expr(:(.), :VectorizationBase, QuoteNode(:vload)), :ptrA, Expr(:tuple, z, n-1))))
    # end
    for n ∈ 1:N
        push!(q.args, Expr(:(=), vectors1[n], Expr(:call, :getfield, :vud, n, false)))
    end
    Nhalf = N >>> 1
    vecstride = 1
    partition_stride = 2
    for nsplits in 0:log2N-1
        shuffle0 = transposeshuffle(nsplits, W, false)
        shuffle1 = transposeshuffle(nsplits, W, true)
        for partition ∈ 0:(N >>> (nsplits+1))-1
            for _n1 ∈ 1:vecstride
                n1 = partition * partition_stride + _n1
                n2 = n1 + vecstride
                v11 = vectors1[n1]
                v12 = vectors1[n2]
                v21 = vectors2[n1]
                v22 = vectors2[n2]
                shuff1 = Expr(:call, :shufflevector, v11, v12, shuffle0)
                shuff2 = Expr(:call, :shufflevector, v11, v12, shuffle1)
                push!(q.args, Expr(:(=), v21, shuff1))
                push!(q.args, Expr(:(=), v22, shuff2))
            end
        end
        vectors1, vectors2 = vectors2, vectors1
        vecstride <<= 1
        partition_stride <<= 1
        # @show vecstride <<= 1
    end
    # @show vecstride, partition_stride
    t = Expr(:tuple)
    o = 0
    for i ∈ 1:(1 << (log2W - log2N))
        extract = subset_tup(N, o)
        for n ∈ 1:N
            push!(t.args, Expr(:call, :shufflevector, vectors1[n], extract))
        end
        o += N
    end
    # for n ∈ 1:N
    #     push!(q.args, Expr(:(=), vectors1[n], Expr(:call, Expr(:(.), :VectorizationBase, QuoteNode(:vstore!)), :ptrB, vectors1[n], Expr(:tuple, z, n-1))))
    # end
    push!(q.args, Expr(:call, :VecUnroll, t))
    q
end
function transpose_vecunroll_quote_W_smaller(N,W)
    (ispow2(W) & ispow2(N)) || throw(ArgumentError("Only supports powers of 2 for vector width and unrolling factor, but recieved $N and $W."))
    N,W = W,N
    log2W = intlog2(W)
    log2N = intlog2(N)
    q = Expr(:block, Expr(:meta, :inline), :(vud = data(vu)))
    # N = W # N vectors of length W
    vectors1 = [Symbol(:v_, n) for n ∈ 0:N-1]
    vectors2 = [Symbol(:v_, n+N) for n ∈ 0:N-1]
    # z = Expr(:call, Expr(:curly, Expr(:(.), :VectorizationBase, QuoteNode(:MM)), W), 0)
    # for n ∈ 1:N
    #     push!(q.args, Expr(:(=), vectors1[n], Expr(:call, Expr(:(.), :VectorizationBase, QuoteNode(:vload)), :ptrA, Expr(:tuple, z, n-1))))
    # end
    vectors3 = [Symbol(:vpiece_, w) for w ∈ 0:W-1]
    for w ∈ 1:W
        push!(q.args, Expr(:(=), vectors3[w], Expr(:call, :getfield, :vud, w, false)))
    end
    Wtemp = W
    exprs = Vector{Expr}(undef, W >>> 1)
    initstride = W >>> (log2W - log2N)

    Ntemp = N;
    # Wtemp = W >>> 1
    Wratio_init = W ÷ N
    Wratio = Wratio_init
    1,3
    2,4
    vcat( vcat( 1, 3 ), vcat( 5, 7 ) )
    vcat( vcat( 2, 4 ), vcat( 6, 8 ) )
    while Wratio > 1
        Wratioh = Wratio >>> 1
        for w ∈ 0:(Wratioh)-1
            i = (2N)*w
            j = i + N
            for n ∈ 1:N
                exprs[n + N*w] = if Wratio == Wratio_init
                    Expr(:call, :vcat, vectors3[i+n], vectors3[j+n])
                else
                    Expr(:call, :vcat, exprs[i+n], exprs[j+n])
                end
            end
        end
        Wratio = Wratioh
    end
    for n ∈ 1:N
        push!(q.args, Expr(:(=), vectors1[n], exprs[n]))
    end
    Nhalf = N >>> 1
    vecstride = 1
    partition_stride = 2
    for nsplits in 0:log2N-1
        shuffle0 = transposeshuffle(nsplits, W, false)
        shuffle1 = transposeshuffle(nsplits, W, true)
        for partition ∈ 0:(N >>> (nsplits+1))-1
            for _n1 ∈ 1:vecstride
                n1 = partition * partition_stride + _n1
                n2 = n1 + vecstride
                v11 = vectors1[n1]
                v12 = vectors1[n2]
                v21 = vectors2[n1]
                v22 = vectors2[n2]
                shuff1 = Expr(:call, :shufflevector, v11, v12, shuffle0)
                shuff2 = Expr(:call, :shufflevector, v11, v12, shuffle1)
                push!(q.args, Expr(:(=), v21, shuff1))
                push!(q.args, Expr(:(=), v22, shuff2))
            end
        end
        vectors1, vectors2 = vectors2, vectors1
        vecstride <<= 1
        partition_stride <<= 1
        # @show vecstride <<= 1
    end
    # @show vecstride, partition_stride
    t = Expr(:tuple)
    for n ∈ 1:N
        push!(t.args, vectors1[n])
    end
    push!(q.args, Expr(:call, :VecUnroll, t))
    q
end
@generated function transpose_vecunroll(vu::VecUnroll{N,W}) where {N,W}
    # N+1 == W || throw(ArgumentError("Transposing is currently only supported for sets of vectors of size equal to their length, but received $(N+1) vectors of length $W."))
    # 1+2
    if N+1 == W
        W == 1 && return :vu
        transpose_vecunroll_quote(W)
    elseif W == 1
        v = Expr(:call, :Vec)
        for n ∈ 0:N
            push!(v.args, Expr(:call, GlobalRef(Core,:getfield), :vud, n+1, false))
        end
        Expr(:block, Expr(:meta,:inline), :(vud = data(vu)), v)
    elseif N+1 < W
        transpose_vecunroll_quote_W_larger(N+1, W)
    else# N+1 > W
        transpose_vecunroll_quote_W_smaller(N+1, W)
    end
    # code below lets LLVM do it.
    # q = Expr(:block, Expr(:meta,:inline), :(vud = data(vu)))
    # S = W
    # syms = Vector{Symbol}(undef, W)
    # gf = GlobalRef(Core, :getfield)
    # for w ∈ 1:W
    #     syms[w] = v = Symbol(:v_, w)
    #     push!(q.args, Expr(:(=), v, Expr(:call, gf, :vud, w, false)))
    # end
    # while S > 1
    #     S >>>= 1
    #     for s ∈ 1:S
    #         v1 = syms[2s-1]
    #         v2 = syms[2s  ]
    #         vc = Symbol(v1,:_,v2)
    #         push!(q.args, Expr(:(=), vc, Expr(:call, :vcat, v1, v2)))
    #         syms[s] = vc
    #     end
    # end
    # t = Expr(:tuple)
    # v1 = syms[1];# v2 = syms[2]
    # for w1 ∈ 0:N
    #     shufftup = Expr(:tuple)
    #     for w2 ∈ 0:N
    #         push!(shufftup.args, w2*W + w1)
    #     end
    #     push!(t.args, Expr(:call, :shufflevector, v1, Expr(:call, Expr(:curly, :Val, shufftup))))
    #     # push!(t.args, Expr(:call, :shufflevector, v1, v2, Expr(:call, Expr(:curly, :Val, shufftup))))
    # end
    # push!(q.args, Expr(:call, :VecUnroll, t))
    # q
end
@generated function vec_to_vecunroll(v::AbstractSIMDVector{W}) where {W}
    t = Expr(:tuple)
    for w ∈ 0:W-1
        push!(t.args, :(extractelement(v, $w)))
    end
    Expr(:block, Expr(:meta,:inline), :(VecUnroll($t)))
end

@inline shufflevector(vxu::VecUnroll, ::Val{I}) where {I} = VecUnroll(fmap(shufflevector, data(vxu), Val{I}()))

shuffleexpr(s::Expr) = Expr(:block, Expr(:meta,:inline), :(shufflevector(vx, Val{$s}())))
"""
  vpermilps177(vx::AbstractSIMD)

  Vec(0, 1, 2, 3, 4, 5, 6, 7) ->
    Vec(1, 0, 3, 2, 5, 4, 7, 6)
"""
@generated function vpermilps177(vx::AbstractSIMD{W}) where {W}
  s = Expr(:tuple)
  for w ∈ 1:2:W
    push!(s.args, w, w-1)
  end
  shuffleexpr(s)
end
"""
  vmovsldup(vx::AbstractSIMD)

  Vec(0, 1, 2, 3, 4, 5, 6, 7) ->
    Vec(0, 0, 2, 2, 4, 4, 6, 6),
"""
@generated function vmovsldup(vx::AbstractSIMD{W}) where {W}
  sl = Expr(:tuple)
  for w ∈ 1:2:W
    push!(sl.args, w-1, w-1)
  end
  shuffleexpr(sl)
end
"""
  vmovshdup(vx::AbstractSIMD)

  Vec(0, 1, 2, 3, 4, 5, 6, 7) ->
    Vec(1, 1, 3, 3, 5, 5, 7, 7)
"""
@generated function vmovshdup(vx::AbstractSIMD{W}) where {W}
  sh = Expr(:tuple)
  for w ∈ 1:2:W
    push!(sh.args, w, w)
  end
  shuffleexpr(sh)
end

@generated function uppervector(vx::AbstractSIMD{W}) where {W}
  s = Expr(:tuple)
  for i ∈ W>>>1:W-1
    push!(s.args,i)
  end
  shuffleexpr(s)
end
@generated function lowervector(vx::AbstractSIMD{W}) where {W}
  s = Expr(:tuple)
  for i ∈ 0:(W>>>1)-1
    push!(s.args,i)
  end
  shuffleexpr(s)
end
@inline splitvector(vx::AbstractSIMD) = lowervector(vx), uppervector(vx)

@generated function extractupper(vx::AbstractSIMD{W}) where {W}
  s = Expr(:tuple)
  for i ∈ 0:(W>>>1)-1
    push!(s.args, 2i)
  end
  shuffleexpr(s)
end
@generated function extractlower(vx::AbstractSIMD{W}) where {W}
  s = Expr(:tuple)
  for i ∈ 0:(W>>>1)-1
    push!(s.args, 2i+1)
  end
  shuffleexpr(s)
end


text:
# =========================================================================== #

# =========================================================================== #

#asked question:
#Mettre en place une heuristique de recherche locale (descente ou plus profonde descente) fondée sur deux voisinages (exemple : type “k-p exchange”).

#taking an array of lenght m
#returning another array of length m
include("DM1_1.jl")

function calculz(x,costs,m)
    z = 0
    for i in 1:m
        z+= x[i]*costs[i]
    end

    return z
end

function select(crts,matrix,m,j)
    for l in 1:m
        selec = selec && ( crts[l] + matrix[j,l] >= 1)
    end
end
function kpexchange!(
    x, # Notre solution
    k::Int,  # le nombre d'objet à retirer du conteneur
    p::Int, # le nombre d'objet à rajouter dans le conteneur
    n::Int,  # taille de x
    m::Int, # nombre de contraintes
    zbest::Int,  # solution trouvée
    z::Int, #solution actuelle
    couts, # tableau des coûts de x
    xbest, #meilleur solution trouvée
    crts, # vecteur des contraintes (on suppose que pout tout i crts[i] =< 1)
    matrix # la matrice des contraintes
    )
println("===============kp exchange =====================")
    sol = (xbest,zbest)
    println("x = ",x)

    if k > 0
        println("========= k =============")
        for i in 1:n
            println("======================")
            println("==> élément ",i," sur ",n)
            println("======================")
            if x[i] == 1
                println("======================")
                println("==> x[",i,"] = 1")
                println("======================")
                x_prime = copy(x)
                println("==> copie effectuée")
                x_prime[i] = 0
                println("==> x[",i,"] passé à 0")
                for crt in 1:m
                    if matrix[i,crt] == 1
                        crts[crt] = 0
                    end
                end
                println("======================")
                println("Appel récursif k")
                sol = kpexchange!(x_prime,k-1,p,n,m,zbest,z-couts[i],couts, xbest,crts)
            end
        end

    elseif p > 0
        println("========= p =============")
        for j in 1:n
            println("======================")
            println("==> élément ",j," sur ",n)
            println("======================")
            if x[j] == 0
                println("======================")
                println("==> x[",j,"] = 0")
                println("======================")
                selec = true # juste une initialisation
                # ici on regarde si on peu rajouter notre variable

                println("crts =", crts, "" )
                if select(crts,matrix,m,j)
                    x_prime = copy(x)
                    println("==> copie effectuée")
                    x_prime[j] = 1  # on rajoute la variable j à notre solution
                    println("==> x[",j,"] passé à 1")
                    println("======================")
                    println("Appel récursif")
                    z = calculz(x_prime,couts,m)
                    println("nouvelle solution : z = ",z)
                    if z > zbest #on regarde si on a amélioré notre solution
                        println("Z passe en meilleur solution")
                        xbest = x_prime
                        zbest  = z
                    end
                    for crt in 1:m # on met à jour nos contraintes
                        if matrix[j,crt] == 1
                            crts[crt] = 1
                        end
                    end
                end
                println("Appel récursif p")
                sol = kpexchange!(x_prime,k,p-1,n,m,zbest,z,couts, xbest,crts)
            end
        end
    else
        sol = (xbest,zbest)
        println("solution : ", sol)
        return sol
    end
end


text:
# Laplace distribution

export Laplace

@parameterized Laplace() ≪ (1/2) * Lebesgue(ℝ)

for N in AFFINEPARS
    @eval begin
        proxy(d::Laplace{$N}) = affine(params(d), Laplace())
        logdensity(d::Laplace{$N}, x) = logdensity(proxy(d), x)
        basemeasure(d::Laplace{$N}) = basemeasure(proxy(d))
    end
end

# @affinepars Laplace

function logdensity(d::Laplace{()} , x)
    return -abs(x)
end

Base.rand(rng::AbstractRNG, μ::Laplace{()}) = rand(rng, Dists.Laplace())

≪(::Laplace, ::Lebesgue{X}) where X <: Real = true

TV.as(::Laplace) = asℝ

distproxy(::Laplace{()}) = Dists.Laplace()
distproxy(d::Laplace{(:μ,)}) = Dists.Laplace(d.μ, 1.0)
distproxy(d::Laplace{(:σ,)}) = Dists.Laplace(0.0, d.σ)
distproxy(d::Laplace{(:μ,:σ)}) = Dists.Laplace(d.μ, d.σ)
distproxy(d::Laplace{(:ω,)}) = Dists.Laplace(0.0, inv(d.ω))
distproxy(d::Laplace{(:μ,:ω)}) = Dists.Laplace(d.μ, inv(d.ω))


text:
export GP

"""
    GP{Tm<:MeanFunction, Tk<:Kernel}

A Gaussian Process (GP) with known mean `m` and kernel `k`. A book-keeping object `gpc` is
also required, but only matters when composing `GP`s together.

# Zero Mean

If only two arguments are provided, assume the mean to be zero everywhere:
```jldoctest
julia> f = GP(Matern32(), GPC());

julia> x = randn(5);

julia> mean(f(x)) == zeros(5)
true

julia> cov(f(x)) == Stheno.pw(Matern32(), x)
true
```

### Constant Mean

If a `Real` is provided as the first argument, assume the mean function is constant with
that value
```jldoctest
julia> f = GP(5.0, EQ(), GPC());

julia> x = randn(5);

julia> mean(f(x)) == 5.0 .* ones(5)
true

julia> cov(f(x)) == Stheno.pw(EQ(), x)
true
```

### Custom Mean

Provide an arbitrary function to compute the mean:

```jldoctest
julia> f = GP(x -> sin(x) + cos(x / 2), RQ(3.2), GPC());

julia> x = randn(5);

julia> mean(f(x)) == sin.(x) .+ cos.(x ./ 2)
true

julia> cov(f(x)) == Stheno.pw(RQ(3.2), x)
true
```
"""
struct GP{Tm<:MeanFunction, Tk<:Kernel} <: AbstractGP
    m::Tm
    k::Tk
    n::Int
    gpc::GPC
    function GP{Tm, Tk}(m::Tm, k::Tk, gpc::GPC) where {Tm, Tk}
        gp = new{Tm, Tk}(m, k, next_index(gpc), gpc)
        gpc.n += 1
        return gp
    end
end
GP(m::Tm, k::Tk, gpc::GPC) where {Tm<:MeanFunction, Tk<:Kernel} = GP{Tm, Tk}(m, k, gpc)

GP(f, k::Kernel, gpc::GPC) = GP(CustomMean(f), k, gpc)
GP(m::Real, k::Kernel, gpc::GPC) = GP(ConstMean(m), k, gpc)
GP(k::Kernel, gpc::GPC) = GP(ZeroMean(), k, gpc)
GP(k::Kernel, m, gpc::GPC) = GP(m, k, gpc)

mean_vector(f::GP, x::AV) = ew(f.m, x)

cov(f::GP, x::AV) = pw(f.k, x)
cov_diag(f::GP, x::AV) = ew(f.k, x)

cov(f::GP, x::AV, x′::AV) = pw(f.k, x, x′)
cov_diag(f::GP, x::AV, x′::AV) = ew(f.k, x, x′)

function cov(f::GP, f′::GP, x::AV, x′::AV)
    return f === f′ ? cov(f, x, x′) : zeros(length(x), length(x′))
end
function cov_diag(f::GP, f′::GP, x::AV, x′::AV)
    return f === f′ ? cov_diag(f, x, x′) : zeros(length(x))
end


text:
"""
The Luxor package provides a set of vector drawing functions for creating graphical documents.
"""
module Luxor

using Juno, Cairo, Colors, FileIO, Dates

#= from Cairo use: CairoARGBSurface, CairoEPSSurface, CairoMatrix, CairoPDFSurface, CairoPattern, CairoPatternMesh, CairoSurface, CairoSVGSurface,
CairoContext, arc, arc_negative, circle, clip, clip_preserve, close_path,
convert_cairo_path_data, copy_path, copy_path_flat, curve_to, destroy, fill,
fill_preserve, finish, get_matrix, get_operator, height, image, line_to,
mesh_pattern_begin_patch, mesh_pattern_curve_to, mesh_pattern_end_patch,
mesh_pattern_line_to, mesh_pattern_move_to, mesh_pattern_set_corner_color_rgba,
move_to, new_path, new_sub_path, paint, paint_with_alpha,
pattern_add_color_stop_rgba, pattern_create_linear, pattern_create_radial,
read_from_png, rectangle, rel_line_to, rel_move_to, reset_clip, restore, rotate,
save, scale, select_font_face, set_antialias, set_font_face, set_font_size,
set_line_cap, set_line_join, set_dash, set_line_type, set_line_width,
set_matrix, set_operator, set_source, set_source_rgba, set_source_surface,
show_text, status, stroke, stroke_preserve, text, text_extents, text_path,
translate, width, write_to_png =#

include("drawings.jl")
include("point.jl")
include("basics.jl")
include("Turtle.jl")
include("shapes.jl")
include("BoundingBox.jl")
include("polygons.jl")
include("curves.jl")
include("tiles-grids.jl")
include("arrows.jl")
include("text.jl")
include("blends.jl")
include("matrix.jl")
include("juliagraphics.jl")
include("colors_styles.jl")
include("images.jl")
include("animate.jl")
include("bars.jl")
include("bezierpath.jl")
include("mesh.jl")
include("Table.jl")
include("Boxmaptile.jl")
include("noise.jl")
include("deprecations.jl")
include("graphlayout.jl")
#include("shapefile.jl") # don't load unless you've loaded Shapefile.jl

export Drawing,
    cm, inch, mm,
    paper_sizes,
    Tiler, Partition,
    rescale,

    finish, preview,
    origin, rulers, background,

    @png, @pdf, @svg, @eps, @draw,

    newpath, closepath, newsubpath,

    BezierPath, BezierPathSegment, bezier, bezier′, bezier′′, makebezierpath, drawbezierpath, bezierpathtopoly, beziertopoly, pathtobezierpaths,
    bezierfrompoints, beziercurvature, bezierstroke, setbezierhandles, shiftbezierhandles, brush,

    strokepath, fillpath,

    rect, box, cropmarks,

    setantialias, setline, setlinecap, setlinejoin, setdash,

    move, rmove, line, rule, rline, arrow, arrowhead, dimension,

    BoundingBox, boundingbox, boxwidth, boxheight, boxdiagonal, boxaspectratio,
    boxtop, boxbottom, boxtopleft, boxtopcenter, boxtopright, boxmiddleleft,
    boxmiddlecenter, boxmiddleright, boxbottomleft, boxbottomcenter,
    boxbottomright,

    intersectboundingboxes, boundingboxesintersect, pointcrossesboundingbox,

    Boxmaptile, boxmap,

    circle, circlepath, ellipse, hypotrochoid, epitrochoid, squircle, center3pts, curve,
    arc, carc, arc2r, carc2r, isarcclockwise, arc2sagitta, carc2sagitta,
    spiral, sector, intersection2circles,
    intersection_line_circle, intersectionlinecircle, intersectioncirclecircle, ispointonline,
    intersectlinepoly, polyintersect, polyintersections, circlepointtangent,
    circletangent2circles, pointinverse,

    ngon, ngonside, star, pie,
    do_action, paint, paint_with_alpha, fillstroke,

    Point, O, randompoint, randompointarray, midpoint, between, slope, intersectionlines,
    pointlinedistance, getnearestpointonline, isinside,
    perpendicular, crossproduct, dotproduct, distance,
    prettypoly, polysmooth, polysplit, poly, simplify,  polycentroid,
    polysortbyangle, polysortbydistance, offsetpoly, polyfit,

    polyperimeter, polydistances, polyportion, polyremainder, nearestindex,
    polyarea, polysample, insertvertices!,

    polymove!, polyscale!, polyrotate!, polyreflect!,

    @polar, polar,

    strokepreserve, fillpreserve,
    gsave, grestore, @layer,
    scale, rotate, translate,
    clip, clippreserve, clipreset,

    getpath, getpathflat, pathtopoly,

    fontface, fontsize, text, textpath, label,
    textextents, textoutlines, textcurve, textcentred, textcentered, textright,
    textcurvecentred, textcurvecentered,
    textwrap, textlines, splittext, textbox, texttrack,

    setcolor, setopacity, sethue, setgrey, setgray,
    randomhue, randomcolor, @setcolor_str,
    getmatrix, setmatrix, transform,

    setfont, settext,

    Blend, setblend, blend, addstop, blendadjust,
    blendmatrix, rotationmatrix, scalingmatrix, translationmatrix,
    cairotojuliamatrix, juliatocairomatrix, getrotation, getscale, gettranslation,

    setmode, getmode,

    GridHex, GridRect, nextgridpoint,

    Table, highlightcells,

    readpng, placeimage,

    julialogo, juliacircles,

    bars,

    mesh, setmesh, mask,

    # animation
    Sequence, Movie, Scene, animate,

    lineartween, easeinquad, easeoutquad, easeinoutquad, easeincubic, easeoutcubic,
    easeinoutcubic, easeinquart, easeoutquart, easeinoutquart, easeinquint, easeoutquint,
    easeinoutquint, easeinsine, easeoutsine, easeinoutsine, easeinexpo, easeoutexpo,
    easeinoutexpo, easeincirc, easeoutcirc, easeinoutcirc, easingflat, easeinoutinversequad, easeinoutbezier,

    # noise
    noise, initnoise,

    # experimental polygon functions
    polyremovecollinearpoints, polytriangulate!, polytriangulate,
    ispointinsidetriangle, ispolyclockwise, polyorientation,

    # misc
    layoutgraph

# basic unit conversion to Cairo/PostScript points
const inch = 72.0
const cm = 28.3464566929
const mm = 2.83464566929

end # module


text:
mutable struct WorkspacePanel <: GtkScrolledWindow
    handle::Ptr{Gtk.GObject}
    list::GtkTreeStore
    tree_view::GtkTreeView
    main_window::MainWindow

    function WorkspacePanel(main_window::MainWindow)

        (tv,list,cols) = give_me_a_treeview(2,["Name","Summary"])

        sc = GtkScrolledWindow()
        push!(sc,tv)
        t = new(sc.handle,list,tv,main_window)

        signal_connect(workspacepanel_treeview_clicked_cb,tv, "button-press-event",
                       Cint, (Ptr{Gtk.GdkEvent},), false,t)
        signal_connect(workspacepanel_treeview_keypress_cb,tv, "key-press-event",
                       Cint, (Ptr{Gtk.GdkEvent},), false,t)

        Gtk.gobject_move_ref(t,sc)
    end
end

function var_info(s::Symbol, mod)
    try
        #return string(typeof(getfield(mod,s))) #FIXME: call on worker
        return summary(Core.eval(mod,s))
    catch err
    end
    ""
end

function on_path_change(w::WorkspacePanel, path)

end

function update!(w::WorkspacePanel)

    !visible(w) && return nothing #updating is a bit costly

    mod = current_console(w.main_window).eval_in
    n = sort!(names(mod,all=true))
    t = map(s->var_info(s,mod),n)
    n = map(string,n)

    idx = (t .!= "Module") .& map(s->!startswith(s,"#"),n)
    n,t = n[idx], t[idx]

    #M = sortslices([t n n], dims=1)#FIXME use tree view sorting?
    #n = M[:,2]
    #t = M[:,1]

    #sel_val = selected(w.tree_view,w.list)
    empty!(w.list)
    for i = 1:length(t)
        push!(w.list,(n[i],t[i]))
    end

    #sel_val != nothing && select_value(w.tree_view,w.list,sel_val) #this crashes
end

function open_variable(treeview::GtkTreeView,list::GtkTreeStore,main_window::MainWindow)
    v = selected(treeview, list)
    if v != nothing
        GtkREPL.command(current_console(main_window),v[1])
        GtkREPL.on_return(current_console(main_window),v[1])
    end
end

@guarded (PROPAGATE) function workspacepanel_treeview_clicked_cb(widgetptr::Ptr, eventptr::Ptr, workspacepanel)

    treeview = convert(GtkTreeView, widgetptr)
    event = convert(Gtk.GdkEvent, eventptr)
    list = workspacepanel.list

    if event.button == 3

    else
        if event.event_type == Gtk.GdkEventType.DOUBLE_BUTTON_PRESS
            open_variable(treeview,list,workspacepanel.main_window)
        end
    end
    return PROPAGATE
end

@guarded (PROPAGATE) function workspacepanel_treeview_keypress_cb(widgetptr::Ptr, eventptr::Ptr, workspacepanel)
    treeview = convert(GtkTreeView, widgetptr)
    event = convert(Gtk.GdkEvent, eventptr)
    list = workspacepanel.list
    if event.keyval == GdkKeySyms.Return
        open_variable(treeview,list,workspacepanel.main_window)
    end
    return PROPAGATE
end


text:
"""
    proteinMutation(genotype::GEGenotype, gpExperimentInfo::GEInfo,
                        rng::Random.AbstractRNG, integerMutation::Function, varargs...)

Perform codons based mutation a **Grammatical Evolution** Individual, by means of
an integer mutation.

# Self-provided Arguments
- `genotype::GEGenotype`: individual genotype.
- `gpExperimentInfo::GEInfo`: information about grammatical evolution.
- `rng::Random.AbstractRNG`: random number generator for random number consistency along an experiment.

# User Arguments
- `integerMutation::Function`: integer mutation function.
- `varargs`: arguments for integerMutation.

!!! note
    `Selfprovided Arguments` are already provided by the library, so only `User Arguments` must be provided.
"""
function proteinMutation(genotype::GEGenotype, gpExperimentInfo::GEInfo,
                        rng::Random.AbstractRNG, integerMutation::Function, varargs...)

    protein, introns = pruneProtein(genotype)

    child = integerMutation(protein, rng, varargs...)

    child = generateTree(gpExperimentInfo, rng::Random.AbstractRNG, vcat(child._representation, introns))

    return child
end

"""
    proteinMutationGrow(genotype::GEGenotype, gpExperimentInfo::GEInfo,
                            rng::Random.AbstractRNG, integerMutation::Function, varargs...)

As proteinMutation, but instead, a growGenerator is used to ensure that all individuals are valids.
It is advisable to used along proteinCrossGrow.

# Self-provided Arguments
- `genotype::GEGenotype`: individual genotype.
- `gpExperimentInfo::GEInfo`: information about grammatical evolution.
- `rng::Random.AbstractRNG`: random number generator for random number consistency along an experiment.

# User Arguments
- `integerCross::Function`: integer crossover function.
- `varargs`: arguments for integerCross.

!!! note
    `Selfprovided Arguments` are already provided by the library, so only `User Arguments` must be provided.
"""
function proteinMutationGrow(genotype::GEGenotype, gpExperimentInfo::GEInfo,
                            rng::Random.AbstractRNG, integerMutation::Function, varargs...)

    protein, introns = pruneProtein(genotype)

    child = integerMutation(protein, rng, varargs...)

    child = growGenerator(gpExperimentInfo, rng::Random.AbstractRNG, vcat(child._representation, introns))

    return child
end

max_stars_repo_name: SergioGmezM/GeneticJulia

max_issues_repo_name: SergioGmezM/GeneticJulia

max_forks_repo_name: SergioGmezM/GeneticJulia


text:
using Chatterjee
using Test

@testset "Chatterjee.jl" begin
    # Write your tests here.
end


text:
function downloadInterestRates(directory::String)

    #Descarga de ficheros desde la página del Banco de España
    file = HTTP.get("https://www.bde.es/webbde/es/estadis/infoest/series/ti_1_7.csv").body

    isdir(joinpath(directory,"tipos")) || mkdir(joinpath(directory,"tipos")) # Si no hay directorio lo creamos

    io = open(joinpath(directory,"tipos","tInteres.csv"),"w")
    write(io,file)
    close(io)

end


text:
using PackageCompiler

# TODO: Compile into a version
# TODO: Make sure we are in the correct directory

create_app("./", "./build/Sialia", force=true, incremental=false, filter_stdlibs=true)


text:
# vim:set ft=julia ts=4 sw=4 sts=4 autoindent:

# Averaged perceptron implementation for sparse/dense feature vectors.
#
# Author:   Pontus Stenetorp    <pontus stenetorp se>
# Version:  2014-05-27

# TODO: Could use repeated(1) for binary features, but since it would be in a
#   tight loop we will use separate code-paths for now.
# TODO: What would you really call the variable `value`?

module Percep

export extend!, classify, spclassify, score, spscore, spupdate!, update!
export Perceptron, AvgPerceptron

type Perceptron
    weights::Vector{Float64}
    bias::Float64
end

function _spscore(fidxs, fvals, p)
    score = p.bias
    for (fidx, fval) in zip(fidxs, fvals)
        score += p.weights[fidx] * fval
    end
    return score
end

function _spscore(fidxs, p)
    score = p.bias
    for fidx in fidxs
        score += p.weights[fidx]
    end
    return score
end

_spclassify(fidxs, p) = _spscore(fidxs, p) > 0
_spclassify(fidxs, fvals, p) = _spscore(fidxs, fvals, p) > 0

spscore(fidxs, p) = _spscore(fidxs, p)
spscore(fidxs, fvals, p) = _spscore(fidxs, fvals, p)

score(fvec, p) = spscore(1:length(fvec), fvec, p)

spclassify(fidxs, p) = _spclassify(fidxs, p)
spclassify(fidxs, fvals, p) = _spclassify(fidxs, fvals, p)

classify(fvec, p) = spclassify(1:length(fvec), fvec, p)

type AvgPerceptron
    weights::Vector{Float64}
    bias::Float64
    weightsacc::Vector{Float64}
    biasacc::Float64
    count::Int
end

AvgPerceptron() = AvgPerceptron(Float64[], 0, Float64[], 0, 0)

function extend!(p, size)
    oldsize = length(p.weights)
    resize!(p.weights, size)
    resize!(p.weightsacc, size)
    # Initialise the new weights.
    p.weights[oldsize+1:end] = 0
    p.weightsacc[oldsize+1:end] = 0
    return p
end

function AvgPerceptron(size)
    p = AvgPerceptron()
    extend!(p, size)
end

# Convert an averaged perceptron to a its final vanilla perceptron stage.
function Perceptron(p)
    div = p.count
    Perceptron(p.weights - p.weightsacc / div, p.bias - p.biasacc / div)
end

function spscore(fidxs, p::AvgPerceptron)
    p.count += 1
    return _spscore(fidxs, p)
end

function spscore(fidxs, fvals, p::AvgPerceptron)
    p.count += 1
    return _spscore(fidxs, fvals, p)
end

function spclassify(fidxs, p::AvgPerceptron)
    p.count += 1
    return _spclassify(fidxs, p)
end

function spclassify(fidxs, fvals, p::AvgPerceptron)
    p.count += 1
    return _spclassify(fidxs, fvals, p)
end

function spupdate!(p, fidxs, value)
    for fidx in fidxs
        p.weights[fidx] += value
        p.weightsacc[fidx] += p.count * value
    end
    p.bias += value
    p.biasacc += p.count * value
end

function spupdate!(p, fidxs, fvals, value)
    for (fidx, fval) in zip(fidxs, fvals)
        p.weights[fidx] += value * fval
        p.weightsacc[fidx] += p.count * value * fval
    end
    p.bias += value
    p.biasacc += p.count * value
end

spupdate!(p, fidxs, value::Bool) = spupdate!(p, fidxs, value ? 1 : -1)
function spupdate!(p, fidxs, fvals, value::Bool)
    spupdate!(p, fidxs, fvals, value ? 1 : -1)
end

update!(p, fvec, value) = spupdate!(p, 1:length(fvec), fvec, value)

end

max_stars_repo_name: ninjin/allen

max_issues_repo_name: ninjin/allen

max_forks_repo_name: ninjin/allen


text:
@testset "231.power-of-two.jl" begin
    @test !is_power_of_two(-1)
    @test !is_power_of_two(-5)
    n = 1
    for _ in 1:30
        @test is_power_of_two(n)
        @test !is_power_of_two(n + 13)
        n <<= 1
    end
end


text:
#=
  IupGetAttribute/Int/Float: Example

  Uses IupGetAttribute/IupGetInt and IupGetFloat to print a number entered by the user.
  The printing will occur when the user exits the program. The number will be printed as an integer,
  a floating point and a text.
=#

module getattribute_

using IUP

export
	getattribute

include("../src/libiup_h.jl")

#------------------------example html/examples/C/getattribute.c ----------------------------------
function getattribute()
	IupOpen()                   # Initializes IUP

	field = IupText("")                                         # creates TEXT field
	IupSetCallback(field, "ACTION", cfunction(number_action, Int, (Ptr{Ihandle}, Cint)))   # registers callback
	IupSetCallback(field, "K_ANY", cfunction(k_any, Int, (Ptr{Ihandle}, Cint)))            # registers callback

	IupSetAttribute(field, "VALUE", "1.0")                      # defines initial value

	message = IupLabel("Please, type any number: ")             # creates message
	prompt = IupHbox(message, field)                            # creates prompt

	dlg = IupDialog(prompt)
	IupShow(dlg)                  # displays and creates dialog
	IupMainLoop()                 # interacts with user

	@printf("Integer number: %d\n", IupGetInt(field, "VALUE"))       # prints the integer number entered by the user
	@printf("Real number...: %f\n", IupGetFloat(field, "VALUE"))     # prints the real number entered by the user
	@printf("Text entered..: %s\n", bytestring(IupGetAttribute(field, "VALUE"))) # prints the text entered by the user

	IupClose()                                  # And close it when ready
end

function k_any(self::Ptr{Ihandle}, c::Cint)
	if (c == K_CR)
		return IUP_CLOSE
	end
	return IUP_CONTINUE
end

function number_action (self::Ptr{Ihandle}, c::Cint)
	caracteres_validos = "0123456789.+-Ee"

	if ((search(caracteres_validos, char(c))) > 0)     # c is a valid character
		return IUP_DEFAULT
	elseif (iscntrl(char(c)))                          # c is a control character (TAB, BACKSPACE, ...)
		return IUP_DEFAULT
	end

	return IUP_IGNORE
end

end 	# module