text:
export BrukerFile, recoData

include("Jcampdx.jl")

function latin1toutf8(str::AbstractString)
  buff = Char[]
  for c in Vector{UInt8}(str)
    push!(buff,c)
  end
  string(buff...)
end

function latin1toutf8(str::Nothing)
  error("Can not convert noting to UTF8!")
end

mutable struct BrukerFile <: MRIFile
  path::String
  params::JcampdxFile
  paramsProc::JcampdxFile
  methodRead
  acqpRead
  visupars_globalRead
  recoRead
  methrecoRead
  visuparsRead
  mpiParRead
  maxEntriesAcqp
end

function BrukerFile(path::String; maxEntriesAcqp=2000)
  params = JcampdxFile()
  paramsProc = JcampdxFile()

  return BrukerFile(path, params, paramsProc, false, false, false,
               false, false, false, false, maxEntriesAcqp)
end

function getindex(b::BrukerFile, parameter)#::String
  if !b.acqpRead && ( parameter=="NA" || parameter=="NR" || parameter=="NI" || parameter=="NSLICES" ||
                      parameter=="SW" || parameter[1:2] == "GO" || parameter[1:3] == "ACQ" )
    acqppath = joinpath(b.path, "acqp")
    read(b.params, acqppath, maxEntries=b.maxEntriesAcqp)
    b.acqpRead = true
  elseif !b.methodRead && length(parameter) >= 3 &&
         (parameter[1:3] == "PVM" || parameter[1:3] == "MPI")
    methodpath = joinpath(b.path, "method")
    read(b.params, methodpath)
    b.methodRead = true
  elseif !b.visupars_globalRead && length(parameter) >= 4 &&
         parameter[1:4] == "Visu"
    visupath = joinpath(b.path, "visu_pars")
    if isfile(visupath)
      keylist = ["VisuStudyId","VisuStudyNumber","VisuExperimentNumber","VisuSubjectName"]
      read(b.params, visupath,keylist)
      b.visupars_globalRead = true
    end
  elseif !b.mpiParRead && length(parameter) >= 6 &&
         parameter[1:6] == "CONFIG"
    mpiParPath = joinpath(b.path, "mpi.par")
    if isfile(mpiParPath)
      read(b.params, mpiParPath)
      b.mpiParRead = true
    end
  end

  if haskey(b.params, parameter)
    return b.params[parameter]
  else
    return ""
  end
end

# for pdata

function getindex(b::BrukerFile, parameter, procno::Int64)#::String
  if !b.recoRead && lowercase( parameter[1:4] ) == "reco"
    recopath = joinpath(b.path, "pdata", string(procno), "reco")
    read(b.paramsProc, recopath, maxEntries=13)
    b.recoRead = true
  elseif !b.methrecoRead && parameter[1:3] == "PVM"
    methrecopath = joinpath(b.path, "pdata", string(procno), "methreco")
    read(b.paramsProc, methrecopath)
    b.methrecoRead = true
  elseif !b.visuparsRead && parameter[1:4] == "Visu"
    visuparspath = joinpath(b.path, "pdata", string(procno), "visu_pars")
    if isfile(visuparspath)
      read(b.paramsProc, visuparspath)
      b.visuparsRead = true
    end
  end

  return b.paramsProc[parameter]
end

function Base.show(io::IO, b::BrukerFile)
  print(io, "BrukerFile: ", b.path)
end

# acquisition parameters
function acqStartTime(b::BrukerFile)
  m = match(r"<(.+)\+",b["ACQ_time"])
  timeString = replace(m.captures[1],"," => ".")
  return DateTime( timeString )
end
function acqNumFrames(b::BrukerFile)
  M = Int64(b["ACQ_jobs"][1][8])
  return div(M,acqNumPeriodsPerFrame(b))
end

acqNumAverages(b::BrukerFile) = parse(Int,b["NA"])
acqNumSlices(b::BrukerFile) = parse(Int,b["NSLICES"])
acqNumInterleaves(b::BrukerFile) = parse(Int,b["NI"])

function acqSize(b::BrukerFile)
  N = parse.(Int,b["ACQ_size"])
  N[1] = div(N[1],2)
  return N
end
function acqFov(b::BrukerFile)
  N = parse.(Float64,b["ACQ_fov"])./100
  if length(N) == 3
    return N
  else
    return push!(N, parse(Float64,b["ACQ_slice_sepn"][1])./100)
  end
end
##$PVM_EncAvailReceivers=1

acqNumCoils(b::BrukerFile) = parse(Int,b["PVM_EncNReceivers"])
acqNumEchos(b::BrukerFile) = parse(Int,b["ACQ_n_echo_images"])
acqPhaseFactor(b::BrukerFile) = parse(Int,b["ACQ_phase_factor"])
acqRareFactor(b::BrukerFile) = parse(Int,b["ACQ_phase_factor"])
acqSpatialSize1(b::BrukerFile) = parse(Int,b["ACQ_spatial_size_1"])
acqNumRepetitions(b::BrukerFile) = parse(Int,b["NR"])
acqObjOrder(b::BrukerFile) = parse.(Int,b["ACQ_obj_order"])
acqReadOffset(b::BrukerFile) = parse.(Float64,b["ACQ_read_offset"])
acqPhase1Offset(b::BrukerFile) = parse.(Float64,b["ACQ_phase1_offset"])
acqPhase2Offset(b::BrukerFile) = parse.(Float64,b["ACQ_phase2_offset"])
acqGradMatrix(b::BrukerFile) = parse.(Float64,b["ACQ_grad_matrix"])
acqSliceOffset(b::BrukerFile) = parse.(Float64,b["ACQ_slice_offset"])
acqFlipAngle(b::BrukerFile) = parse(Float64,b["ACQ_flip_angle"])
acqProtocolName(b::BrukerFile) = b["ACQ_protocol_name"]
acqInterEchoTime(b::BrukerFile) = parse(Float64,b["ACQ_inter_echo_time"][1])
acqEchoTime(b::BrukerFile) = parse(Float64,b["ACQ_echo_time"][1])
acqRepetitionTime(b::BrukerFile) = parse(Float64,b["ACQ_repetition_time"][1])

Base.ndims(b::BrukerFile) = parse(Int, b["ACQ_dim"])

pvmEncNReceivers(b::BrukerFile) =parse.(Int,b["PVM_EncNReceivers"])
pvmEncAvailReceivers(b::BrukerFile) =parse.(Int,b["PVM_EncAvailReceivers"])
pvmEncSteps1(b::BrukerFile) = parse.(Int,b["PVM_EncSteps1"])
pvmEncSteps2(b::BrukerFile) = parse.(Int,b["PVM_EncSteps2"])
pvmEncValues1(b::BrukerFile) = parse.(Float32,b["PVM_EncSteps1"])
pvmEncValues2(b::BrukerFile) = parse.(Float32,b["PVM_EncSteps2"])
pvmMatrix(b::BrukerFile) = parse.(Int,b["PVM_Matrix"])
pvmSpiralMode(b::BrukerFile) = b["PVM_SpiralMode"]
pvmSpiralNbOfInterleaves(b::BrukerFile) = parse.(Int,b["PVM_SpiralNbOfInterleaves"])
pvmSpiralNbOfGradientPoints(b::BrukerFile) = parse.(Int,b["PVM_SpiralNbOfGradientPoints"])
pvmSpiralNbOfAcqPoints(b::BrukerFile) = parse.(Int,b["PVM_SpiralNbOfAcqPoints"])
pvmSpiralEchoTime(b::BrukerFile) = parse.(Int,b["PVM_SpiralEchoTime"])
pvmSpiralAcqDwellTime(b::BrukerFile) = parse(Float32, b["PVM_SpiralAcqDwellTime"])
pvmSpiralAcquisitionTime(b::BrukerFile) = parse(Float32, b["PVM_SpiralAcquisitionTime"])
pvmSpiralNavSize(b::BrukerFile) = parse.(Int,b["PVM_SpiralNavSize"])
pvmSpiralPreSize(b::BrukerFile) = parse.(Int,b["PVM_SpiralPreSize"])
pvmSpiralSize(b::BrukerFile) = parse.(Int,b["PVM_SpiralSize"])
pvmSpiralPostSize(b::BrukerFile) = parse.(Int,b["PVM_SpiralPostSize"])
pvmSpiralPointsPerRotation(b::BrukerFile) = parse.(Int,b["PVM_SpiralPointsPerRotation"])
pvmSpiralShape1(b::BrukerFile) = parse.(Float32,b["PVM_SpiralShape1"])
pvmSpiralShape2(b::BrukerFile) = parse.(Float32,b["PVM_SpiralShape2"])

pvmTrajInterleaves(b::BrukerFile) = parse(Int,b["PVM_TrajInterleaves"])
pvmTrajSamples(b::BrukerFile) = parse(Int,b["PVM_TrajSamples"])
pvmTrajResultSize(b::BrukerFile) = parse(Int,b["PVM_TrajResultSize"])

pvmTrajKx(b::BrukerFile) = parse.(Float32,b["PVM_TrajKx"])
pvmTrajKy(b::BrukerFile) = parse.(Float32,b["PVM_TrajKy"])

"""
brukerParams(b::BrukerFile)

Generate a standard parameter dictionary from Bruker acquistion
Some fields needs to be filled outside lik

"""
function brukerParams(b::BrukerFile)
  params = Dict{String,Any}()
  params["trajectory"] = "cartesian"

  params["encodedSize"] = pvmMatrix(b)
  F = acqFov(b)
  params["encodedFOV"] = F
  params["receiverChannels"] = pvmEncNReceivers(b)
  params["H1resonanceFrequency_Hz"] = round(Int, parse(Float64,b["SW"])*1000000)
  params["studyID"] = b["VisuStudyId"]
  #params["studyDescription"] = b["ACQ_scan_name"]
  #params["studyInstanceUID"] =
  params["referringPhysicianName"] = latin1toutf8(b["ACQ_operator"])

  params["patientName"] = b["VisuSubjectName"]

  params["measurementID"] = parse(Int64,b["VisuExperimentNumber"])
  params["seriesDescription"] = b["ACQ_scan_name"]

  params["institutionName"] = latin1toutf8(b["ACQ_institution"])
  params["stationName"] = b["ACQ_station"]
  params["systemVendor"] = "Bruker"

  params["TR"] = acqRepetitionTime(b)
  params["TE"] = acqEchoTime(b)
  #params["TI"] = ???
  params["flipAngle_deg"] = acqFlipAngle(b)
  params["sequence_type"] = acqProtocolName(b)
  params["echo_spacing"] = acqInterEchoTime(b)

  return params
end

function acqDataType(b::BrukerFile)
  format = b["GO_raw_data_format"]
  if format == "GO_32BIT_SGN_INT"
    return Int32
  elseif format == "GO_16BIT_SGN_INT"
    return Int16
  elseif format == "GO_32BIT_FLOAT"
  else
    @error "Data type unknown: $(format)"
  end
  return Int8
end

function MRIBase.RawAcquisitionData(b::BrukerFile)
  if isfile(joinpath(b.path, "fid"))
    protocolName = acqProtocolName(b)
    @info "Bruker protocol name : $protocolName"
    if acqProtocolName(b) == "UTE3D"
      return RawAcquisitionData_3DUTE(b)
    elseif acqProtocolName(b) == "SPIRAL"
      return RawAcquisitionDataRawDataSpiral(b)
    else
      return RawAcquisitionDataFid(b) #standard cartesian cases
    end
  end
end

include("BrukerSequence.jl")

function RawAcquisitionDataRawDataSpiral(b::BrukerFile)
  # Have not a way to read out this. Not sure if its true
  T = Complex{Int32}

  filename = joinpath(b.path, "rawdata.job0")

  profileLength = pvmTrajSamples(b)
  phaseFactor = acqPhaseFactor(b)
  numSlices = acqNumSlices(b)
  numEchos = acqNumEchos(b)
  numRep = acqNumRepetitions(b)
  numProfiles = pvmTrajInterleaves(b)
  numChannels = acqNumCoils(b)

  I = open(filename,"r") do fd
    read!(fd,Array{T,7}(undef, profileLength,
                                   numChannels,
                                   numEchos,
                                   phaseFactor,
                                   numSlices,
                                   numProfiles,
                                   numRep))
  end

  # TODO the following of course is just for debugging
  return I
end

function RawAcquisitionDataFid(b::BrukerFile)
    T = Complex{acqDataType(b)}

    filename = joinpath(b.path, "fid")

    N = acqSize(b)
    # The data is padded in case it is not a multiple of 1024
    # For multi-channel acquisition data at concatenate then padded to a multiple of 1024 bytes
    numChannel = pvmEncNReceivers(b)
    profileLength = Int((ceil(N[1]*numChannel*sizeof(T)/1024))*1024/sizeof(T))
    numAvailableChannel = pvmEncAvailReceivers(b)
    phaseFactor = acqPhaseFactor(b)
    numSlices = acqNumSlices(b)
    numEchos = acqNumEchos(b)
    numEncSteps2 = length(N) == 3 ? N[3] : 1
    numRep = acqNumRepetitions(b)

    I = open(filename,"r") do fd
      read!(fd,Array{T,7}(undef, profileLength,
                                     numEchos,
                                     phaseFactor,
                                     numSlices,
                                     div(N[2], phaseFactor),
                                     numEncSteps2,
                                     numRep))[1:N[1]*numChannel,:,:,:,:,:,:]
    end

    encSteps1 = pvmEncSteps1(b)
    encSteps1 = encSteps1.-minimum(encSteps1)

    encSteps2 = pvmEncSteps2(b)
    encSteps2 = encSteps2.-minimum(encSteps2)

    objOrd = acqObjOrder(b)
    objOrd = objOrd.-minimum(objOrd)

    gradMatrix = acqGradMatrix(b)

    offset1 = acqReadOffset(b)
    offset2 = acqPhase1Offset(b)
    offset3 = ndims(b) == 2 ? acqSliceOffset(b) : acqPhase2Offset(b)

    profiles = Profile[]
    for nR = 1:numRep
      for nEnc2 = 1:numEncSteps2
        for nPhase2 = 1:div(N[2], phaseFactor)
          for nSl = 1:numSlices
            for nPhase1 = 1:phaseFactor
              for nEcho=1:numEchos
                  counter = EncodingCounters(kspace_encode_step_1=encSteps1[nPhase1+phaseFactor*(nPhase2-1)],
                                             kspace_encode_step_2=encSteps2[nEnc2],
                                             average=0,
                                             slice=objOrd[nSl],
                                             contrast=nEcho-1,
                                             phase=0,
                                             repetition=nR-1,
                                             set=0,
                                             segment=0 )

                  G = gradMatrix[:,:,nSl]
                  read_dir = (G[1,1],G[2,1],G[3,1])
                  phase_dir = (G[1,2],G[2,2],G[3,2])
                  slice_dir = (G[1,3],G[2,3],G[3,3])

                  # Not sure if the following is correct...
                  pos = offset1[nSl]*G[:,1] +
                        offset2[nSl]*G[:,2] +
                        offset3[nSl]*G[:,3]

                  position = (pos[1], pos[2], pos[3])

                  head = AcquisitionHeader(number_of_samples=N[1], idx=counter,
                                           read_dir=read_dir, phase_dir=phase_dir,
                                           slice_dir=slice_dir, position=position,
                                           center_sample=div(N[1],2),
                                           available_channels = numAvailableChannel, #TODO
                                           active_channels = numChannel)
                  traj = Matrix{Float32}(undef,0,0)
                  dat = map(T, reshape(I[:,nEcho,nPhase1,nSl,nPhase2,nEnc2,nR],:,numChannel))
                  push!(profiles, Profile(head,traj,dat) )
              end
            end
          end
        end
      end
    end

    params = brukerParams(b)
    params["trajectory"] = "cartesian"
    N = acqSize(b)
    if length(N) < 3
      N_ = ones(Int,3)
      N_[1:length(N)] .= N
      N = N_
    end
    params["encodedSize"] = N

    return RawAcquisitionData(params, profiles)
end

##### Reco
function recoData(f::BrukerFile)
  recoFilename = joinpath(f.path,"pdata", "1", "2dseq")
  N = recoSize(f)

  #if f["RECO_wordtype",1] != "_16BIT_SGN_INT"
  #  @error "Not yet implemented!"
  #end

  I = open(recoFilename,"r") do fd
    read!(fd,Array{Int16,length(N)}(undef,N...))
  end
  return map(Float32,I)
end

recoFov(f::BrukerFile) = push!(parse.(Float64,f["RECO_fov",1])./100,
                                parse(Float64,f["ACQ_slice_sepn"][1])./100)
recoFovCenter(f::BrukerFile) = zeros(3)
recoSize(f::BrukerFile) = push!(parse.(Int,f["RECO_size",1]),
                                parse(Int,f["RecoObjectsPerRepetition",1]))


text:
function heaviside(x)
# HEAVISIDE
# y = HEAVISIDE(x) returns 0 when x<0 and 1 when x>=0
y=zeros(size(x));
y[x.>=0].=1;
return y
end

ext: jl


text:
using DelimitedFiles
fishdata = readdlm("llist.txt",',',Int)
@show fishdata

fishages = zeros(Int,1,9)

function init_fishes(fd,fishages)
    for age in fd
        fishages[age+1] += 1
    end

    return fishages
end

function agefish(fishages)
    age0 = fishages[1]
    for fi in 2:length(fishages)
        fishages[fi-1] = fishages[fi]
    end
    fishages[7] += age0
    fishages[9] = age0
end

init_fishes(fishdata,fishages)
@show fishages

for days in 1:256
    agefish(fishages)
end

@show fishages
@show sum(fishages)


text:
using ProgressMeter

function train()
    train_x, train_y, test_x, test_y = setup_data()
    h5file = joinpath(dirname(@__FILE__), ".data/wordembeds_nyt100.h5")
    wordembeds = Lookup(h5read(h5file, "v"))
    model = setup_model(wordembeds)

    opt = SGD(0.00001)
    for epoch = 1:10
        println("epoch: $(epoch)")
        # opt.rate = 0.0075 / epoch
        prog = Progress(5000)
        loss = 0.0
        for i in randperm(5000)
            x, y = train_x[i], train_y[i]
            z = model(x)
            l = crossentropy(y, z)
            loss += mean(l.data)
            vars = gradient!(l)
            foreach(v -> opt(v.data,v.grad), vars)
            Merlin.update!(wordembeds, opt)

            next!(prog)
        end
        #loss = fit(train_x, train_y, model, crossentropy, opt)
        println("loss: $(loss)")
    end
end

max_stars_repo_name: hshindo/PairwiseMatrix

max_issues_repo_name: hshindo/PairwiseMatrix

max_forks_repo_name: hshindo/PairwiseMatrix


text:
"""
$(TYPEDEF)

Represents a differential operator.

# Fields
$(FIELDS)

# Examples

```jldoctest
julia> using ModelingToolkit

julia> @variables x y;

julia> D = Differential(x)
(D'~x())

julia> D(y)  # Differentiate y wrt. x
(D'~x())(y())
```
"""
struct Differential <: Function
    """The variable or expression to differentiate with respect to."""
    x::Expression
end
(D::Differential)(x) = Operation(D, Expression[x])

Base.show(io::IO, D::Differential) = print(io, "(D'~", D.x, ")")
Base.convert(::Type{Expr}, D::Differential) = D

Base.:(==)(D1::Differential, D2::Differential) = isequal(D1.x, D2.x)

"""
$(SIGNATURES)

TODO
"""
function expand_derivatives(O::Operation,simplify=true)
    @. O.args = expand_derivatives(O.args,false)

    if isa(O.op, Differential)
        (D, o) = (O.op, O.args[1])

        isequal(o, D.x)     && return Constant(1)
        occursin(D.x, o)    || return Constant(0)
        isa(o, Operation)   || return O
        isa(o.op, Variable) && return O

        x = sum(1:length(o.args)) do i
            derivative(o, i) * expand_derivatives(D(o.args[i]),false)
        end

        return simplify ? ModelingToolkit.simplify(x) : x
    end

    return simplify ? ModelingToolkit.simplify(O) : O
end
expand_derivatives(x,args...) = x

# Don't specialize on the function here
"""
$(SIGNATURES)

Calculate the derivative of the op `O` with respect to its argument with index
`idx`.

# Examples

```jldoctest label1
julia> using ModelingToolkit

julia> @variables x y;

julia> ModelingToolkit.derivative(sin(x), 1)
cos(x())
```

Note that the function does not recurse into the operation's arguments, i.e., the
chain rule is not applied:

```jldoctest label1
julia> myop = sin(x) * y^2
sin(x()) * y() ^ 2

julia> typeof(myop.op)  # Op is multiplication function
typeof(*)

julia> ModelingToolkit.derivative(myop, 1)  # wrt. sin(x)
y() ^ 2

julia> ModelingToolkit.derivative(myop, 2)  # wrt. y^2
sin(x())
```
"""
derivative(O::Operation, idx) = derivative(O.op, (O.args...,), Val(idx))
derivative(O::Constant, ::Any) = Constant(0)

# Pre-defined derivatives
import DiffRules, SpecialFunctions, NaNMath
for (modu, fun, arity) ∈ DiffRules.diffrules()
    fun in [:*, :+] && continue # special
    for i ∈ 1:arity
        @eval function derivative(::typeof($modu.$fun), args::NTuple{$arity,Any}, ::Val{$i})
            M, f = $(modu, fun)
            partials = DiffRules.diffrule(M, f, args...)
            dx = @static $arity == 1 ? partials : partials[$i]
            convert(Expression, dx)
        end
    end
end

derivative(::typeof(+), args::NTuple{N,Any}, ::Val) where {N} = 1
derivative(::typeof(*), args::NTuple{N,Any}, ::Val{i}) where {N,i} = Operation(*, deleteat!(collect(args), i))
derivative(::typeof(one), args::Tuple{<:Any}, ::Val) = 0

function count_order(x)
    @assert !(x isa Symbol) "The variable $x must have an order of differentiation that is greater or equal to 1!"
    n = 1
    while !(x.args[1] isa Symbol)
        n = n+1
        x = x.args[1]
    end
    n, x.args[1]
end

_repeat_apply(f, n) = n == 1 ? f : f ∘ _repeat_apply(f, n-1)
function _differential_macro(x)
    ex = Expr(:block)
    lhss = Symbol[]
    x = x isa Tuple && first(x).head == :tuple ? first(x).args : x # tuple handling
    x = flatten_expr!(x)
    for di in x
        @assert di isa Expr && di.args[1] == :~ "@derivatives expects a form that looks like `@derivatives D''~t E'~t` or `@derivatives (D''~t), (E'~t)`"
        lhs = di.args[2]
        rhs = di.args[3]
        order, lhs = count_order(lhs)
        push!(lhss, lhs)
        expr = :($lhs = $_repeat_apply(Differential($rhs), $order))
        push!(ex.args,  expr)
    end
    push!(ex.args, Expr(:tuple, lhss...))
    ex
end

"""
$(SIGNATURES)

Define one or more differentials.

# Examples

```jldoctest
julia> using ModelingToolkit

julia> @variables x y z;

julia> @derivatives Dx'~x Dy'~y  # Create differentials wrt. x and y
((D'~x()), (D'~y()))

julia> Dx(z)  # Differentiate z wrt. x
(D'~x())(z())

julia> Dy(z)  # Differentiate z wrt. y
(D'~y())(z())
```
"""
macro derivatives(x...)
    esc(_differential_macro(x))
end

function calculate_jacobian(eqs, dvs)
    Expression[Differential(dv)(eq) for eq ∈ eqs, dv ∈ dvs]
end


text:
import Base.in

struct Constraint
    name::String
    ranges::Vector{UnitRange{Int64}}
end
function Constraint(filestring::String)
    name, ranges = split(filestring, ':')
    a, b, c, d = parse.(Int64, match(r"(\d+)-(\d+)\D+(\d+)-(\d+)", ranges).captures)
    Constraint(name, [a:b, c:d])
end
in(value::Int64, constraint::Constraint) = any(value in range for range in constraint.ranges)

struct Ticket
    numbers::Vector{Int64}
end
Ticket(filestring::String) = Ticket(parse.(Int64, [m.match for m in eachmatch(r"\d+", filestring)]))

function loaddata(path::String)::Tuple{Vector{Constraint},Ticket,Vector{Ticket}}
    fieldsstr, myticketstr, otherticketsstr = split(strip(read(path, String)), "\n\n")
    fields = Constraint.(split(fieldsstr, '\n'))
    myticket = Ticket(string(myticketstr))
    othertickets = Ticket.(string.(split(otherticketsstr, '\n')[2:end]))
    (fields, myticket, othertickets)
end

fields, myticket, othertickets = loaddata("input.txt")

# part 1
sum(filter(number -> !any(number in field for field in fields), collect(Iterators.flatten(ticket.numbers for ticket in othertickets))))

# part 2
validtickets = filter(ticket -> all(number -> any(number in field for field in fields), ticket.numbers), othertickets)

function findconstraints(fields, myticket, validtickets)
    numbers = hcat((ticket.numbers for ticket in [myticket; validtickets])...)
    possiblefieldindices = []
    for field in fields
        push!(possiblefieldindices, (name = field.name, numbers = Set(findall(row -> all(number -> number in field, row), [eachrow(numbers)...]))))
    end
    sort!(possiblefieldindices, by=f -> length(f.numbers), lt=(>))

    fieldindices = Dict()
    while length(possiblefieldindices) > 0
        field = pop!(possiblefieldindices)
        n = first(field.numbers)
        fieldindices[field.name] = n
        for f in possiblefieldindices
            delete!(f.numbers, n)
        end
    end

    fieldindices
end

cs = findconstraints(fields, myticket, validtickets)
println(prod(myticket.numbers[i] for i in (c[2] for c in cs if startswith(c[1], "departure"))))

max_stars_repo_name: stellartux/advent-of-code

max_issues_repo_name: stellartux/advent-of-code

max_forks_repo_name: stellartux/advent-of-code


text:
module TestDict

using ConcurrentCollections
using ConcurrentCollections.Implementations: clusters, migrate!
using SyncBarriers: Barrier, cycle!
using Test
using ..Utils: ⊏

function test_expand_and_shrink(n = 17)
    d = ConcurrentDict{Int,Int}()
    @testset "expand" begin
        @testset for i in 1:n
            d[i] = -i
            @testset for k in 1:i
                @test d[k] == -k
            end
        end
    end
    nfull = length(d.slots)
    @testset "shrink" begin
        @testset for i in n:-1:1
            @test pop!(d, i) == -i
            @testset for k in 1:i-1
                @test d[k] == -k
            end
        end
    end
    @test length(d.slots) < nfull
    return d
end

function test_parallel_expand(n = 2^10, basesize = 8)
    d = ConcurrentDict{Int,Int}(pairs(1:n))
    nslots = length(d.slots)
    migrate!(d, true; basesize)
    @test nslots < length(d.slots)
    diffs = Pair{Int,Int}[]
    for k in 1:n
        v = d[k]
        if v != k
            push!(diffs, k => v)
        end
    end
    @test diffs == []
    return d
end

function test_dict()
    @testset for npairs in [2, 100]
        test_dict(npairs)
    end
end

function test_dict(npairs)
    @testset for Key in [Int8, Int32, Int64], Value in [Int]
        d = ConcurrentDict{Key,Value}()
        @testset for trial in 1:2
            for i in 1:npairs
                d[i] = -i
            end
            @testset "getindex" begin
                vals = [d[i] for i in 1:2]
                @test vals == [-1, -2]
            end
            @testset "iterate" begin
                kvs = sort!(collect(d))
                @test kvs == [i => -i for i in 1:npairs]
                ks = sort!(collect(keys(d)))
                @test ks == 1:npairs
                vs = sort!(collect(values(d)))
                @test vs == reverse((1:npairs) .* -1)
            end
        end
        @testset "maybepop!" begin
            @test maybeget(d, 1) === Some(-1)
            @test maybepop!(d, 1) === Some(-1)
            @test maybeget(d, 1) === nothing
            @test maybepop!(d, 1) === nothing
            @test 1 ∉ sort!(collect(keys(d)))
        end
        @testset "length_upper_bound" begin
            @test length_upper_bound(d) == mapreduce(_ -> 1, +, d)
        end

        @testset "typed constructor" begin
            ks = Key.(1:npairs)
            vs = Value.(1:npairs)
            @testset "$label" for (label, dict) in [
                "ConcurrentDict{Key,Value}(zip(ks, vs))" =>
                    ConcurrentDict{Key,Value}(zip(ks, vs)),
                "ConcurrentDict{Key,Value}(map(=>, ks, vs))" =>
                    ConcurrentDict{Key,Value}(map(=>, ks, vs)),
            ]
                @test sort!(collect(keys(dict))) == ks
                @test sort!(collect(values(dict))) == ks
            end
        end

        @testset "clusters" begin
            @test length(clusters(d)::Vector{UnitRange{Int}}) > 0
        end
    end

    @testset "ConcurrentDict{String,_}()" begin
        d = ConcurrentDict{String,Int}()
        str(i) = string(i; pad = 3)
        @testset for trial in 1:2
            for i in 1:npairs
                d[str(i)] = -i
            end
            @testset "getindex" begin
                vals = [d[str(i)] for i in 1:2]
                @test vals == [-1, -2]
            end
            @testset "iterate" begin
                kvs = sort!(collect(d))
                @test kvs == [str(i) => -i for i in 1:npairs]
            end
        end
        @testset "maybepop!" begin
            @test maybeget(d, "001") === Some(-1)
            @test maybepop!(d, "001") === Some(-1)
            @test maybeget(d, "001") === nothing
            @test maybepop!(d, "001") === nothing
            @test "001" ∉ sort!(collect(keys(d)))
        end
        @testset "clusters" begin
            @test length(clusters(d)::Vector{UnitRange{Int}}) > 0
        end
    end
end

function test_pairs_constructor()
    @testset for Key in [Int8, Int32, Int64], Value in [Int]
        @testset "$label" for (label, dict) in [
            "ConcurrentDict{_,_}(_ => _, ...)" =>
                ConcurrentDict{Key,Value}(Key(0) => Value(1), Key(2) => Value(3)),
            "ConcurrentDict(_ => _, ...)" =>
                ConcurrentDict(Key(0) => Value(1), Key(2) => Value(3)),
            "ConcurrentDict{_,_}(false => true, ...)" =>
                ConcurrentDict{Key,Value}(false => true, 2 => 3),
            "ConcurrentDict(false => true, ...)" =>
                ConcurrentDict(false => true, Key(2) => Value(3)),
        ]
            @test dict[0] == 1
            @test dict[2] == 3
        end
    end
end

function test_shrink()
    @testset for Key in [Int8, Int32, Int64], Value in [Int]
        ks = vs = 1:100
        d = ConcurrentDict{Key,Value}(zip(ks, vs))
        nslots = length(d.slots)
        for k in ks
            pop!(d, k)
        end
        @test collect(d) == []
        @test length(d.slots) < nslots
    end
end

function random_mutation!(dict; nkeys = 8, repeat = 2^20, ntasks = Threads.nthreads())
    ks = 1:nkeys
    locals = [
        (
            popped = zeros(valtype(dict), nkeys),  # sum of popped values
            added = zeros(valtype(dict), nkeys),   # sum of all inserted values
        ) for _ in 1:ntasks
    ]
    @sync for (; popped, added) in locals
        Threads.@spawn begin
            for _ in 1:repeat
                k = rand(ks)
                if rand(Bool)
                    y = maybepop!(dict, k)
                    if y !== nothing
                        popped[k] += something(y)
                    end
                else
                    added[k] += 1
                    modify!(dict, k) do ref
                        Base.@_inline_meta
                        Some(ref === nothing ? 1 : ref[] + 1)
                    end
                end
            end
        end
    end
    return locals
end

function test_random_mutation(; kwargs...)
    dict = ConcurrentDict{Int,Int}()
    nkeys = 16
    locals = random_mutation!(dict; kwargs..., nkeys)
    actual = zeros(valtype(dict), nkeys)
    desired = zeros(valtype(dict), nkeys)
    for (k, v) in dict
        actual[k] = v
    end
    for (; popped, added) in locals
        actual .+= popped
        desired .+= added
    end
    @test actual == desired
end

function phased_push_pop!(
    dict;
    nkeys = 16,
    repeat = 2^10,
    phases = 2^10,
    ntasks = Threads.nthreads(),
)
    locals = [
        (
            popped = zeros(valtype(dict), nkeys * phases),  # sum of popped values
            added = zeros(valtype(dict), nkeys * phases),   # sum of all inserted values
        ) for _ in 1:ntasks
    ]
    barrier = Barrier(ntasks)
    @sync for (itask, (; popped, added)) in enumerate(locals)
        Threads.@spawn begin
            for p in 1:phases
                k0 = (p - 1) * nkeys + 1
                ks = k0:k0+nkeys-1
                for _ in 1:repeat
                    k = rand(ks)
                    added[k] += 1
                    modify!(dict, k) do ref
                        Base.@_inline_meta
                        Some(ref === nothing ? 1 : ref[] + 1)
                    end
                end
                spin = 10_000  # spin for a few μs
                cycle!(barrier[itask], spin)
                for k in ks
                    popped[k] += something(maybepop!(dict, k), 0)
                end
            end
        end
    end
    return locals
end

function test_phased_push_pop(; nkeys = 16, phases = 2^10, kwargs...)
    dict = ConcurrentDict{Int,Int}()
    locals = phased_push_pop!(dict; kwargs..., nkeys, phases)
    actual = zeros(valtype(dict), nkeys * phases)
    desired = zeros(valtype(dict), nkeys * phases)
    for k in eachindex(actual)
        actual[k] = get(dict, k, 0)
    end
    for (; popped, added) in locals
        actual .+= popped
        desired .+= added
    end
    @test actual == desired
end

function concurrent_intern!(ys, xs)
    dict = ConcurrentDict{eltype(xs),eltype(xs)}()
    Threads.@threads for i in eachindex(ys, xs)
        x = xs[i]
        ys[i] = get!(dict, x, x)
    end
    return ys
end

function test_get_default()
    d = ConcurrentDict(:a => 111)
    @test get!(d, :a, 222) == 111
    @test get!(d, :b, 222) == 222
    @test Dict(d) == Dict(:a => 111, :b => 222)
end

function test_get_function()
    d = ConcurrentDict(:a => 111)
    @test get!(() -> 222, d, :a) == 111
    @test get!(() -> 222, d, :b) == 222
    @test Dict(d) == Dict(:a => 111, :b => 222)
end

concurrent_intern(xs) = concurrent_intern!(similar(xs), xs)

function check_concurrent_intern(nitems)
    strs = [string(i)^50 for i in 1:10]
    xs = map(s -> sprint(print, s), rand(strs, nitems))
    ys = concurrent_intern(xs)
    puv = map(pointer_from_objref, unique(ys))
    upv = unique(map(pointer_from_objref, ys))
    @test length(puv) == length(upv)
    @test puv == upv
end

function test_concurrent_intern()
    @testset for trial in 1:5, nitems in [2^n for n in 7:10]
        check_concurrent_intern(nitems)
    end
end

function test_print()
    d = ConcurrentDict(111 => 222, 333 => 444)
    str = sprint(show, "text/plain", d)
    @test "ConcurrentDict" ⊏ str
    @test "111 => 222" ⊏ str
    @test "333 => 444" ⊏ str
end

end  # module


text:
using BlochSim
using ForwardDiff
using LinearAlgebra
using MAT
using Statistics
using Test

@testset "BlochSim.jl" begin
    include("matlab.jl")
    include("magnetization.jl")
    include("blochmatrix.jl")
    include("spin.jl")
    include("spoiling.jl")
    include("expm.jl")
    include("freeprecess.jl")
    include("excite.jl")
    include("mese.jl")
    include("spgr.jl")
end


text:
using Yao, Yao.Boost, Yao.Intrinsics, StaticArrays, Yao.Blocks
using CuYao, CUDA
using BenchmarkTools, Profile

nbit = 12
c = chain(put(nbit, 2=>X), put(nbit, 2=>rot(X, 0.2)), control(nbit, 3, 2=>rot(X,0.3)))
#c = chain(c..., c...,c...)
cc = c |> KernelCompiled
reg = rand_state(nbit) |> cu

@benchmark $reg |> copy |> $c[1] seconds = 2
@benchmark $reg |> copy |> $cc seconds = 2

reg = rand_state(9, 1000)
creg = reg |> cu
@benchmark focus!(reg |> copy, 1) do r
    measure!(r)
    r
end

@benchmark focus!(creg|>copy, 1) do r
    measure!(r)
    r
end

@benchmark focus!(creg, 1) do r
    measure_reset!(r)
    r
end

@profile for i=1:10 focus!(creg |> copy, 1) do r
    measure!(r)
    r
end
end

a = randn(1<<10)
ca = a |> cu

gpu_call(ca, (x->x^2, ca)) do state, f, ca
    ilin = linear_index(state)
    ca[ilin] = f(ca[ilin])
    return
end

gpu_call(1:1<<10, (x->x^2, ca)) do state, f, ca
    ilin = linear_index(state)
    ca[ilin] = f(ca[ilin])
    return
end

function xx_kernel(bits::Ints)
    ctrl = controller(bits[1], 0)
    mask = bmask(bits...)
    function kernel(state, inds)
        i = inds[1]
        b = i-1
        ctrl(b) && swaprows!(piecewise(state, inds), i, flip(b, mask) + 1)
    end
end

using CuYao: x_kernel, y_kernel, z_kernel
fx = x_kernel((3,4))
fy = y_kernel(3)
fz = z_kernel((3,4))

a = randn(1<<10)
ca = a |> cu
fs = (fx, fz)

@benchmark gpu_call(ca, (fs, ca)) do state, f, ca
    #ilin = linear_index(state)
    ilin = @cartesianidx ca
    for fi in fs
        fi(ca, ilin)
    end
    return
end

@device_code_warntype gpu_call(ca, ((fx, fz), ca)) do state, fs, ca
    ilin = @cartesianidx ca
    #for fi in fs fi(ca, ilin) end
    @Base.Cartesian.@nexprs $(length(fs)) i->fs[i](ca, ilin)
    #fs(ca, ilin)
    return
end

a ≈ Vector(ca)

@edit controller(3,0)


text:
# This file was generated, do not modify it. # hide
train, validation = partition(1:length(y), 0.7)
fit!(mach_pipe, rows=train)

max_stars_repo_name: alan-turing-institute/MLJTutorials

max_issues_repo_name: alan-turing-institute/MLJTutorials

max_forks_repo_name: alan-turing-institute/MLJTutorials


text:
using GridLayoutBase
using GridLayoutBase: GridSubposition
using Test
using Observables

include("debugrect.jl")

@testset "GridLayout Zero Outside AlignMode" begin
    bbox = BBox(0, 1000, 0, 1000)
    layout = GridLayout(bbox = bbox, alignmode = Outside(0))
    dr = layout[1, 1] = DebugRect()

    @test computedbboxobservable(dr)[] == bbox

    dr.topprot[] = 100
    @test computedbboxobservable(dr)[] == BBox(0, 1000, 0, 900)
    dr.bottomprot[] = 100
    @test computedbboxobservable(dr)[] == BBox(0, 1000, 100, 900)
    dr.leftprot[] = 100
    @test computedbboxobservable(dr)[] == BBox(100, 1000, 100, 900)
    dr.rightprot[] = 100
    @test computedbboxobservable(dr)[] == BBox(100, 900, 100, 900)

    dr2 = layout[1, 2] = DebugRect()
    @test layout.nrows == 1 && layout.ncols == 2
    colgap!(layout, 1, Fixed(0))

    @test computedbboxobservable(dr)[].widths == computedbboxobservable(dr2)[].widths == Float32[400.0, 800.0]
end

@testset "GridLayout Outside AlignMode" begin
    bbox = Observable(BBox(0, 1000, 0, 1000)) # just as observable for bbox conversion test
    layout = GridLayout(bbox = bbox, alignmode = Outside(100, 200, 50, 150))
    dr = layout[1, 1] = DebugRect()

    @test computedbboxobservable(dr)[] == BBox(100, 800, 50, 850)

    dr.topprot[] = 100
    @test computedbboxobservable(dr)[] == BBox(100, 800, 50, 750)
    dr.bottomprot[] = 100
    @test computedbboxobservable(dr)[] == BBox(100, 800, 150, 750)
    dr.leftprot[] = 100
    @test computedbboxobservable(dr)[] == BBox(200, 800, 150, 750)
    dr.rightprot[] = 100
    @test computedbboxobservable(dr)[] == BBox(200, 700, 150, 750)
end

@testset "GridLayout Inside AlignMode" begin
    bbox = BBox(0, 1000, 0, 1000)
    layout = GridLayout(bbox = bbox, alignmode = Inside())
    dr = layout[1, 1] = DebugRect()

    @test computedbboxobservable(dr)[] == BBox(0, 1000, 0, 1000)

    dr.topprot[] = 100
    @test computedbboxobservable(dr)[] == BBox(0, 1000, 0, 1000)
    dr.bottomprot[] = 100
    @test computedbboxobservable(dr)[] == BBox(0, 1000, 0, 1000)
    dr.leftprot[] = 100
    @test computedbboxobservable(dr)[] == BBox(0, 1000, 0, 1000)
    dr.rightprot[] = 100
    @test computedbboxobservable(dr)[] == BBox(0, 1000, 0, 1000)
end

@testset "GridLayout Mixed AlignMode" begin
    bbox = BBox(0, 1000, 0, 1000)
    layout = GridLayout(bbox = bbox, alignmode = Mixed(left = 0, top = 100))
    dr = layout[1, 1] = DebugRect()

    @test GridLayoutBase.protrusion(layout, Left()) == 0
    @test GridLayoutBase.protrusion(layout, Right()) == 0
    @test GridLayoutBase.protrusion(layout, Bottom()) == 0
    @test GridLayoutBase.protrusion(layout, Top()) == 0

    @test computedbboxobservable(dr)[] == BBox(0, 1000, 0, 900)

    dr.topprot[] = 100
    @test GridLayoutBase.protrusion(layout, Top()) == 0
    @test computedbboxobservable(dr)[] == BBox(0, 1000, 0, 800)

    dr.bottomprot[] = 100
    @test GridLayoutBase.protrusion(layout, Bottom()) == 100
    @test computedbboxobservable(dr)[] == BBox(0, 1000, 0, 800)

    dr.leftprot[] = 100
    @test GridLayoutBase.protrusion(layout, Left()) == 0
    @test computedbboxobservable(dr)[] == BBox(100, 1000, 0, 800)

    dr.rightprot[] = 100
    @test GridLayoutBase.protrusion(layout, Right()) == 100
    @test computedbboxobservable(dr)[] == BBox(100, 1000, 0, 800)

    layout.alignmode[] = Mixed(
        left = Protrusion(50),
        right = Protrusion(60),
        bottom = Protrusion(70),
        top = Protrusion(80),
    )

    # set layout to forced protrusion alignment
    @test GridLayoutBase.protrusion(layout, Left()) == 50
    @test GridLayoutBase.protrusion(layout, Right()) == 60
    @test GridLayoutBase.protrusion(layout, Bottom()) == 70
    @test GridLayoutBase.protrusion(layout, Top()) == 80
    # bb of dr only depends on its protrusions now
    @test computedbboxobservable(dr)[] == BBox(100, 1000, 0, 800)

    # force different protrusions for dr
    dr.alignmode[] = Mixed(
        left = Protrusion(50),
        right = Protrusion(60),
        bottom = Protrusion(70),
        top = Protrusion(80),
    )
    # bb should follow
    @test computedbboxobservable(dr)[] == BBox(50, 940, 70, 920)
end

@testset "alignmodes and known size" begin
    gl = GridLayout()
    dr = gl[1, 1] = DebugRect(width = 200, height = 300, alignmode = Mixed(left = 1, right = 2, bottom = 3, top = 4))
    @test reportedsizeobservable(dr)[] == (203, 307)
    dr.alignmode[] = Inside()
    @test reportedsizeobservable(dr)[] == (200, 300)
    dr.alignmode[] = Mixed(left = Protrusion(10), right = Protrusion(10), bottom = Protrusion(10), top = Protrusion(10))
    # shouldn't this be without the protrusions? have to check implementation again
    @test_broken reportedsizeobservable(dr)[] == (200, 300)
end

@testset "assigning content to protrusions" begin

    bbox = BBox(0, 1000, 0, 1000)
    layout = GridLayout(bbox = bbox, alignmode = Outside(0))
    subgl = layout[1, 1] = GridLayout()

    subgl[1, 1, Left()] = DebugRect(width = Fixed(100))
    @test GridLayoutBase.protrusion(subgl, Left()) == 100

    subgl[1, 1, Top()] = DebugRect(height = 50)
    @test GridLayoutBase.protrusion(subgl, Top()) == 50

    subgl[1, 1, Right()] = DebugRect(width = 120)
    @test GridLayoutBase.protrusion(subgl, Right()) == 120

    subgl[1, 1, Bottom()] = DebugRect(height = 40)
    @test GridLayoutBase.protrusion(subgl, Bottom()) == 40

    subgl[1, 1, TopLeft()] = DebugRect(width = 200, height = 200)
    @test GridLayoutBase.protrusion(subgl, Left()) == 200
    @test GridLayoutBase.protrusion(subgl, Top()) == 200

    subgl[1, 1, TopRight()] = DebugRect(width = 210, height = 210)
    @test GridLayoutBase.protrusion(subgl, Right()) == 210
    @test GridLayoutBase.protrusion(subgl, Top()) == 210

    subgl[1, 1, BottomRight()] = DebugRect(width = 220, height = 220)
    @test GridLayoutBase.protrusion(subgl, Right()) == 220
    @test GridLayoutBase.protrusion(subgl, Bottom()) == 220

    subgl[1, 1, BottomLeft()] = DebugRect(width = 230, height = 230)
    @test GridLayoutBase.protrusion(subgl, Left()) == 230
    @test GridLayoutBase.protrusion(subgl, Bottom()) == 230

    # dr = subgl[1, 1, GridLayoutBase.Outer()] = DebugRect()
    # @test computedbboxobservable(dr)[].widths == (1000, 1000)
end

@testset "resizing through indexing out of range and trim!" begin

    bbox = BBox(0, 1000, 0, 1000)
    layout = GridLayout(bbox = bbox, alignmode = Outside(0))

    dr = layout[1, 1] = DebugRect()
    @test size(layout) == (1, 1)

    layout[1, 2] = dr
    @test size(layout) == (1, 2)

    layout[3, 2] = dr
    @test size(layout) == (3, 2)

    layout[4, 4] = dr
    @test size(layout) == (4, 4)

    layout[0, 1] = dr
    @test size(layout) == (5, 4)

    layout[1, 0] = dr
    @test size(layout) == (5, 5)

    layout[-1, -1] = dr
    @test size(layout) == (7, 7)

    layout[3, 3] = dr
    trim!(layout)
    @test size(layout) == (1, 1)

    layout[2:3, 4:5] = dr
    @test size(layout) == (3, 5)

    trim!(layout)
    @test size(layout) == (2, 2)
end

@testset "manually deleting rows / cols" begin
    layout = GridLayout(4, 4)

    deletecol!(layout, 2)
    @test size(layout) == (4, 3)

    deleterow!(layout, 3)
    @test size(layout) == (3, 3)

    deleterow!(layout, 1)
    @test size(layout) == (2, 3)

    deletecol!(layout, 1)
    @test size(layout) == (2, 2)

    deleterow!(layout, 2)
    @test size(layout) == (1, 2)

    deletecol!(layout, 2)
    @test size(layout) == (1, 1)

    @test_throws ErrorException deletecol!(layout, 2)
    @test_throws ErrorException deleterow!(layout, 2)
    @test_throws ErrorException deletecol!(layout, 1)
    @test_throws ErrorException deleterow!(layout, 1)

    dr = layout[1, 2] = DebugRect()
    @test length(layout.content) == 1
    deletecol!(layout, 2)
    @test isempty(layout.content)

    dr = layout[2, 1] = DebugRect()
    @test length(layout.content) == 1
    deleterow!(layout, 2)
    @test isempty(layout.content)
end

@testset "inserting rows / cols" begin

    layout = GridLayout(4, 4)
    dr1 = layout[1, 1] = DebugRect()
    dr2 = layout[1, 2:3] = DebugRect()
    dr3 = layout[1, 4] = DebugRect()
    dr4 = layout[2:3, 1] = DebugRect()
    dr5 = layout[4, 1] = DebugRect()
    dr6 = layout[2:3, 2:3] = DebugRect()
    dr7 = layout[1, 3] = DebugRect()
    dr8 = layout[3, 1] = DebugRect()

    @test_throws ErrorException insertcols!(layout, 0, 1)
    @test_throws ErrorException insertcols!(layout, 5, 1)
    @test_throws ErrorException insertrows!(layout, 0, 1)
    @test_throws ErrorException insertrows!(layout, 5, 1)

    insertcols!(layout, 3, 2)
    @test gridcontent(dr1).span.cols == 1:1
    @test gridcontent(dr2).span.cols == 2:5
    @test gridcontent(dr3).span.cols == 6:6

    insertrows!(layout, 3, 2)
    @test gridcontent(dr1).span.rows == 1:1
    @test gridcontent(dr4).span.rows == 2:5
    @test gridcontent(dr5).span.rows == 6:6

    @test gridcontent(dr6).span.cols == 2:5
    @test gridcontent(dr6).span.rows == 2:5

    @test gridcontent(dr7).span.cols == 5:5
    @test gridcontent(dr8).span.rows == 5:5
end

@testset "setting col and row sizes and gaps" begin
    bbox = BBox(0, 1000, 0, 1000)
    layout = GridLayout(3, 3, bbox = bbox, alignmode = Outside(0))

    colsize!(layout, 1, Fixed(10))
    @test layout.colsizes[1] == Fixed(10)

    colsize!(layout, 2, 20)
    @test layout.colsizes[2] == Fixed(20)

    rowsize!(layout, 1, Relative(0.2))
    @test layout.rowsizes[1] == Relative(0.2)

    rowsize!(layout, 2, 15.3)
    @test layout.rowsizes[2] == Fixed(15.3)

    @test_throws ErrorException colsize!(layout, 4, Auto())
    @test_throws ErrorException rowsize!(layout, 0, Auto())

    colgap!(layout, 1, Fixed(10))
    @test layout.addedcolgaps[1] == Fixed(10)
    rowgap!(layout, 2, Relative(0.3))
    @test layout.addedrowgaps[2] == Relative(0.3)

    colgap!(layout, 10)
    @test all(layout.addedcolgaps .== Ref(Fixed(10)))
    rowgap!(layout, 20)
    @test all(layout.addedrowgaps .== Ref(Fixed(20)))

    colgap!(layout, Fixed(30))
    @test all(layout.addedcolgaps .== Ref(Fixed(30)))
    rowgap!(layout, Fixed(40))
    @test all(layout.addedrowgaps .== Ref(Fixed(40)))

    @test_throws ErrorException colgap!(layout, 10, Fixed(10))
    @test_throws ErrorException rowgap!(layout, 10, Fixed(10))
end

@testset "some constructors" begin
    @test Outside() == Outside(0f0)
    @test Auto(2).ratio == 2.0
end

@testset "gridlayout constructor colsizes" begin
    gl = GridLayout(2, 2; colsizes = Fixed(10), rowsizes = Relative(0.5))

    @test gl.colsizes == GridLayoutBase.ContentSize[Fixed(10), Fixed(10)]
    @test gl.rowsizes == GridLayoutBase.ContentSize[Relative(0.5), Relative(0.5)]

    gl2 = GridLayout(2, 2;
        colsizes = [Fixed(10), Relative(0.3)],
        rowsizes = [Auto(false), Auto(true)])
    @test gl2.colsizes == GridLayoutBase.ContentSize[Fixed(10), Relative(0.3)]
    @test gl2.rowsizes == GridLayoutBase.ContentSize[Auto(false), Auto(true)]

    @test_throws ErrorException GridLayout(; colsizes = "abc")
    @test_throws ErrorException GridLayout(; rowsizes = missing)

    gl3 = GridLayout(3, 3; addedcolgaps = Fixed(20), addedrowgaps = Fixed(0))
    @test gl3.addedcolgaps == GridLayoutBase.GapSize[Fixed(20), Fixed(20)]
    @test gl3.addedrowgaps == GridLayoutBase.GapSize[Fixed(0), Fixed(0)]

    @test_throws ErrorException GridLayout(3, 1; addedcolgaps = "abc")
    @test_throws ErrorException GridLayout(1, 3; addedrowgaps = "abc")

    @test_throws ErrorException GridLayout(3, 1; addedcolgaps = [Fixed(20)])
    @test_throws ErrorException GridLayout(3, 1; addedrowgaps = [Fixed(30)])

    @test_throws ErrorException GridLayout(3, 1; rowsizes = [Fixed(20)])
    @test_throws ErrorException GridLayout(3, 2; colsizes = [Relative(0.4)])

    @test_throws ErrorException GridLayout(0, 1)
    @test_throws ErrorException GridLayout(1, 0)
end

@testset "printing gridlayouts" begin
    gl = GridLayout(3, 3)
    gl[1, 1] = DebugRect()
    gl[2:3, 4:5] = DebugRect()

    text_long = repr(MIME"text/plain"(), gl)
    @test text_long == """
    GridLayout[3, 5] with 2 children
     ┣━ [1, 1] DebugRect
     ┗━ [2:3, 4:5] DebugRect
    """
    text_short = repr(gl)
    @test text_short == "GridLayout[3, 5] (2 children)"

    subgl = gl[1, 2] = GridLayout()
    subgl[1:5, 3] = DebugRect()

    text_longer = repr(MIME"text/plain"(), gl)
    # this is actually a bit buggy with the newline space space newline at the end
    @test text_longer == "GridLayout[3, 5] with 3 children\n ┣━ [1, 1] DebugRect\n ┣━ [2:3, 4:5] DebugRect\n ┗━ [1, 2] GridLayout[5, 3] with 1 children\n   ┗━ [1:5, 3] DebugRect\n  \n"

    gl3 = GridLayout()
    gl4 = gl3[1, 1] = GridLayout()
    gl4[1, 1] = DebugRect()
    gl3[2, 2] = DebugRect()
    text_long_downconnection = repr(MIME"text/plain"(), gl3)

    # this is also a bit buggy for the same reason as above
    @test text_long_downconnection == "GridLayout[2, 2] with 2 children\n ┣━ [1, 1] GridLayout[1, 1] with 1 children\n ┃ ┗━ [1, 1] DebugRect\n ┃\n ┗━ [2, 2] DebugRect\n"
end

@testset "vector and array assigning" begin
    gl = GridLayout()
    gl[1, 1:3] = [DebugRect() for i in 1:3]
    @test size(gl) == (1, 3)

    gl2 = GridLayout()
    gl2[2:3, 2] = [DebugRect() for i in 1:2]
    @test size(gl2) == (3, 2)

    gl3 = GridLayout()
    gl3[1:3, 1:4] = [DebugRect() for i in 1:12]
    @test size(gl3) == (3, 4)

    gl4 = GridLayout()
    gl4[1:3, 1:4] = [DebugRect() for i in 1:3, j in 1:4]
    @test size(gl4) == (3, 4)

    @test_throws ErrorException gl[1, 1:3] = [DebugRect() for i in 1:2]
    @test_throws ErrorException gl[1:3, 2] = [DebugRect() for i in 1:2]
    @test_throws ErrorException gl[1:3, 1:3] = [DebugRect() for i in 1:10]
    @test_throws ErrorException gl[1:3, 1:3] = [DebugRect() for i in 1:3, j in 1:4]

    gl5 = GridLayout()
    gl5[] = [DebugRect() for i in 1:2, j in 1:3]
    @test size(gl5) == (2, 3)

    gl6 = GridLayout()
    gl6[:v] = [DebugRect() for i in 1:3]
    @test size(gl6) == (3, 1)

    gl7 = GridLayout()
    gl7[:h] = [DebugRect() for i in 1:3]
    @test size(gl7) == (1, 3)

    @test_throws ErrorException gl7[:abc] = [DebugRect() for i in 1:3]
    @test_throws ErrorException gl7[] = [DebugRect() for i in 1:3]
end

@testset "grid api" begin

    gl1 = grid!([1:2, 1:2] => DebugRect(), [3, :] => DebugRect())
    @test size(gl1) == (3, 2)
    @test gl1.content[1].span == GridLayoutBase.Span(1:2, 1:2)
    @test gl1.content[2].span == GridLayoutBase.Span(3:3, 1:2)

    gl2 = grid!([DebugRect() for i in 1:3, j in 1:2])
    @test size(gl2) == (3, 2)
    for i in 1:3, j in 1:2
        n = (i - 1) * 2 + j
        @test gl2.content[n].span == GridLayoutBase.Span(i:i, j:j)
    end

    gl3 = vbox!(DebugRect(), DebugRect())
    @test size(gl3) == (2, 1)
    for i in 1:2
        @test gl3.content[i].span == GridLayoutBase.Span(i:i, 1:1)
    end

    gl4 = hbox!(DebugRect(), DebugRect())
    @test size(gl4) == (1, 2)
    for i in 1:2
        @test gl4.content[i].span == GridLayoutBase.Span(1:1, i:i)
    end
end

@testset "gridnest" begin
    layout = GridLayout()
    dr = layout[1:2, 3:4] = DebugRect()
    subgl = gridnest!(layout, 1:2, 3:4)

    @test size(subgl) == (2, 2)
    @test subgl.content[1].span == GridLayoutBase.Span(1:2, 1:2)
end

@testset "invalid removal" begin
    layout = GridLayout()
    dr = layout[1, 1] = DebugRect()
    # remove the item outside of the normal path
    deleteat!(layout.content, 1)
    # place the item somewhere else, this should error now
    @test_throws ErrorException layout[1, 2] = dr
end

@testset "equal protrusion gaps" begin
    bbox = BBox(0, 1000, 0, 1000)
    layout = GridLayout(bbox = bbox, alignmode = Outside(0))
    subgl = layout[1, 1] = GridLayout(3, 3, equalprotrusiongaps = (true, true),
        addedcolgaps = Fixed(0), addedrowgaps = Fixed(0))
    subgl[1, 1, BottomRight()] = DebugRect(width = 100, height = 100)

    dr1 = subgl[1, 1] = DebugRect()
    dr2 = subgl[2, 2] = DebugRect()
    dr3 = subgl[3, 3] = DebugRect()

    @test width(computedbboxobservable(dr1)[]) ≈ (1000 - 2 * 100) / 3.0f0
    @test width(computedbboxobservable(dr2)[]) ≈ (1000 - 2 * 100) / 3.0f0
    @test width(computedbboxobservable(dr3)[]) ≈ (1000 - 2 * 100) / 3.0f0
    @test height(computedbboxobservable(dr1)[]) ≈ (1000 - 2 * 100) / 3.0f0
    @test height(computedbboxobservable(dr2)[]) ≈ (1000 - 2 * 100) / 3.0f0
    @test height(computedbboxobservable(dr3)[]) ≈ (1000 - 2 * 100) / 3.0f0
end

@testset "getindex gridposition" begin
    layout = GridLayout()
    dr = layout[2, 2] = DebugRect()

    @test layout[2, 2] == GridPosition(layout, 2, 2)
    @test layout[end, end] == GridPosition(layout, 2, 2)
    @test_throws ErrorException layout[2, 2, end]

    gp = GridPosition(layout, 1, 1)
    gp[] = dr
    @test gridcontent(dr).span == GridLayoutBase.Span(1:1, 1:1)
end

@testset "gridposition contents" begin
    layout = GridLayout()
    dr1 = layout[1, 1] = DebugRect()
    dr2 = layout[1, 2] = DebugRect()
    dr3 = layout[2, 1] = DebugRect()
    dr4 = layout[2, 2] = DebugRect()

    co = contents(layout[1, 1])
    @test co == [dr1]

    co = contents(layout[1:2, 1])
    @test co == [dr1, dr3]

    co = contents(layout[2, 1:2])
    @test co == [dr3, dr4]

    co = contents(layout[:, :])
    @test co == [dr1, dr2, dr3, dr4]

    dr5 = layout[2, 2, Right()] = DebugRect()

    co = contents(layout[:, :]) # implicit Inner() side
    @test co == [dr1, dr2, dr3, dr4]

    @test contents(layout[2, 2, Right()]) == [dr5]

    dr6 = layout[1:2, 2] = DebugRect()
    @test contents(layout[1:2, 2]) == [dr2, dr4, dr6]
    @test contents(layout[1:2, 2], exact = true) == [dr6]

    @test contents(layout) == [dr1, dr2, dr3, dr4, dr5, dr6]
end

@testset "span containment" begin
    Span = GridLayoutBase.Span
    @test Span(1:2, 2:3) in Span(1:2, 2:3)
    @test Span(1:2, 2:3) in Span(0:3, 1:4)
    @test !(Span(0:3, 1:4) in Span(1:2, 2:3))
    @test !(Span(1:2, 1:4) in Span(1:2, 2:3))
    @test !(Span(0:3, 2:3) in Span(1:2, 2:3))
end

@testset "layoutobservables undefined" begin
    struct MyType end
    @test_throws ErrorException GridLayoutBase.layoutobservables(MyType())
end

@testset "determine gridlayout size" begin
    gl = GridLayout(;alignmode = Outside(0))
    gl[1, 1] = DebugRect(width = 800, height = 600)

    @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row()) == 600
    @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col()) == 800

    gl[1, 1, Left()] = DebugRect(width = 200)
    @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col()) == 800 + 200
    gl[1, 1, Right()] = DebugRect(width = 200)
    @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col()) == 800 + 200 + 200

    gl[1, 1, Top()] = DebugRect(height = 100)
    @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row()) == 600 + 100
    gl[1, 1, Bottom()] = DebugRect(height = 100)
    @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row()) == 600 + 100 + 100

    gl.alignmode[] = Outside(50)
    @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col()) == 800 + 200 + 200 + 2 * 50
    @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row()) == 600 + 100 + 100 + 2 * 50

    gl.alignmode[] = Inside()
    @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col()) == 800
    @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row()) == 600
end

@testset "alignment" begin
    boxwidth = 1000
    boxheight = 800

    gl = GridLayout(; bbox = (0, boxwidth, 0, boxheight), alignmode = Outside(0))
    gl[1, 1] = DebugRect(width = boxwidth, height = boxheight)
    halign = Observable{Any}(:center)
    valign = Observable{Any}(:center)

    rectwidth = 400
    rectheight = 200

    dr = gl[1, 1] = DebugRect(width = rectwidth, height = 200, halign = halign, valign = valign)

    @test computedbboxobservable(dr)[] == BBox(boxwidth/2 - rectwidth/2, boxwidth/2 + rectwidth/2, boxheight/2 - rectheight/2, boxheight/2 + rectheight/2)
    halign[] = :left
    @test computedbboxobservable(dr)[] == BBox(0, rectwidth, boxheight/2 - rectheight/2, boxheight/2 + rectheight/2)
    halign[] = :right
    @test computedbboxobservable(dr)[] == BBox(boxwidth - rectwidth, boxwidth, boxheight/2 - rectheight/2, boxheight/2 + rectheight/2)
    valign[] = :top
    @test computedbboxobservable(dr)[] == BBox(boxwidth - rectwidth, boxwidth, boxheight - rectheight, boxheight)
    valign[] = :bottom
    @test computedbboxobservable(dr)[] == BBox(boxwidth - rectwidth, boxwidth, 0, rectheight)

    valign[] = 0.5
    @test computedbboxobservable(dr)[] == BBox(boxwidth - rectwidth, boxwidth,  boxheight/2 - rectheight/2, boxheight/2 + rectheight/2)
    halign[] = 0.5
    @test computedbboxobservable(dr)[] == BBox(boxwidth/2 - rectwidth/2, boxwidth/2 + rectwidth/2,  boxheight/2 - rectheight/2, boxheight/2 + rectheight/2)

    @test_throws ErrorException valign[] = :abc
    valign[] = 0.5
    @test_throws ErrorException halign[] = :abc
end

@testset "invalid gridlayout construction" begin
    @test_throws ErrorException GridLayout(2, 2; rowsizes = [Fixed(10)])
    @test_throws ErrorException GridLayout(2, 2; colsizes = [Fixed(10)])
    @test_throws ErrorException GridLayout(2, 2; addedrowgaps = [Fixed(10), Fixed(10)])
    @test_throws ErrorException GridLayout(2, 2; addedcolgaps = [Fixed(10), Fixed(10)])
    @test_throws ErrorException GridLayout(2, 2; rowsizes = [Fixed(10), Fixed(10)], addedrowgaps = [Fixed(10), Fixed(10)])
    @test_throws ErrorException GridLayout(2, 2; colsizes = [Fixed(10), Fixed(10)], addedcolgaps = [Fixed(10), Fixed(10)])
end

@testset "gridlayoutspec" begin
    dr = DebugRect()
    dr2 = DebugRect()
    dr3 = DebugRect()

    spec = GridLayoutSpec([
            (1, 1) => dr,
            (1:2, 4:5, Left()) => dr2,
            (:, 0) => GridLayoutSpec([
                (1:3, 2:4) => dr3
            ])
        ];
        alignmode = Outside()
    )

    gl = GridLayout(spec)
    @test contents(gl)[1] isa DebugRect
    @test contents(gl)[2] isa DebugRect
    @test contents(gl)[3] isa GridLayout
    @test contents(contents(gl)[3])[1] isa DebugRect
end

@testset "tellsize" begin
    dr = DebugRect(width = 100, height = 200, tellwidth = true, tellheight = false)

    @test dr.layoutobservables.reportedsize[] == (100, nothing)
end

@testset "aspect sizes referencing auto sizes" begin
    bbox = BBox(0, 1000, 0, 1000)
    layout = GridLayout(2, 2, bbox = bbox, alignmode = Outside(0))

    colgap!(layout, 0)
    rowgap!(layout, 0)

    dr = layout[1, 1] = DebugRect()

    colsize!(layout, 1, Aspect(1, 1.5))
    @test computedbboxobservable(dr)[] == BBox(0, 750, 500, 1000)

    colsize!(layout, 1, Auto())

    rowsize!(layout, 1, Aspect(1, 1.5))
    @test computedbboxobservable(dr)[] == BBox(0, 500, 250, 1000)

    @test_throws ErrorException colsize!(layout, 1, Aspect(1, 1))
end

@testset "integer rect2 suggestedbbox" begin
    layout = GridLayout(bbox = Observable(GridLayoutBase.GeometryBasics.Rect(0, 10, 20, 30)))
    @test suggestedbboxobservable(layout)[] == GridLayoutBase.GeometryBasics.Rect2f(0, 10, 20, 30)
end

@testset "GridSubpositions" begin
    l = GridLayout()
    gp = l[1, 1]
    @test gp isa GridPosition
    gsp = gp[1, 1]
    @test gsp isa GridSubposition
    @test isempty(contents(gp))
    r = gsp[] = DebugRect()
    @test content(gp) isa GridLayout
    @test content(gsp) == r

    r2 = l[1, 1][1, 2] = DebugRect()
    @test content(l[1, 1][1, 2]) == r2
    r3 = l[1, 1][1, 3][1, 1] = DebugRect()
    @test content(l[1, 1][1, 3][1, 1]) == r3
end

@testset "Parents" begin
    g = GridLayout()
    @test GridLayoutBase.parent(g) === nothing
    @test GridLayoutBase.top_parent(g) === nothing
    g2 = GridLayout()
    @test GridLayoutBase.parent(g2) === nothing
    g[1, 1] = g2
    @test GridLayoutBase.parent(g2) === g
    @test GridLayoutBase.top_parent(g2) === nothing
    @test GridLayoutBase.top_parent_grid(g2) === g

    g3 = GridLayout()
    @test GridLayoutBase.parent(g3) === nothing
    g2[1, 1] = g3
    @test GridLayoutBase.parent(g3) === g2
    @test GridLayoutBase.top_parent(g3) === nothing
    @test GridLayoutBase.top_parent_grid(g3) === g

    # make some arbitrary parent object with an id
    p = Dict()
    g.parent = p
    @test GridLayoutBase.parent(g) === p
    @test GridLayoutBase.top_parent(g) === p
    @test GridLayoutBase.top_parent(g2) === p
    @test GridLayoutBase.top_parent(g3) === p
    @test GridLayoutBase.top_parent_grid(g2) === g
    @test GridLayoutBase.top_parent_grid(g3) === g
end

@testset "Number of updates" begin
    g = GridLayout()
    n = Ref(0)
    on(g.layoutobservables.suggestedbbox) do _
        n[] += 1
    end

    g2 = GridLayout()
    g[1, 1] = g2
    @test n[] == 1

    m = Ref(0)
    on(g2.layoutobservables.suggestedbbox) do _
        m[] += 1
    end
    for i in 1:10
        g2[1, i] = GridLayout()
    end
    # one update for each gridlayout
    @test m[] == 10
    # g shouldn't have changed
    @test n[] == 1
    with_updates_suspended(g2) do
        for i in 1:10
            g2[1, i] = GridLayout()
        end
    end
    # only one update should have happened at the end
    @test m[] == 11
    # still nothing for g
    @test n[] == 1
end


text:
import PredictMD
import Test

Test.@test( isdir(PredictMD.package_directory()) )

Test.@test( isdir(PredictMD.package_directory("ci")) )

Test.@test( isdir(PredictMD.package_directory("ci", "travis")) )

Test.@test( isdir(PredictMD.package_directory(PredictMDTestModuleA)) )

Test.@test( isdir(PredictMD.package_directory(PredictMDTestModuleB)) )

Test.@test( isdir( PredictMD.package_directory(
            PredictMDTestModuleB, "directory2",
            ) ) )

Test.@test( isdir( PredictMD.package_directory(
            PredictMDTestModuleB, "directory2", "directory3",
            ) ) )

Test.@test_throws(
    ErrorException,
    PredictMD.package_directory(PredictMDTestModuleC),
    )


text:
struct HyperComplex5{T}
    a::T
    b::T
    c::T
    d::T
    e::T
end

function ⊕(x::HyperComplex5,y::HyperComplex5)
    promoted = promote_type(eltype(x.a), eltype(y.a))
    HyperComplex5{promoted}(    x.a + y.a,
                                x.b + y.b,
                                x.c + y.c,
                                x.d + y.d,
                                x.e + y.e,
    )
end

function ⊗(x::HyperComplex5,y::HyperComplex5)
    promoted = promote_type(eltype(x.a), eltype(y.a))
    HyperComplex5{promoted}(    x.a*y.a - x.b*y.b - x.c*y.c - x.d*y.d - x.e*y.e,
                                x.a*y.b + y.a*x.b,
                                x.a*y.c + y.a*x.c,
                                x.a*y.d + y.a*x.d,
                                x.a*y.e + y.a*x.e
    )
end

a = HyperComplex5{Int8}(1,1,1,1,1)
b = HyperComplex5{Int8}(1,2,1,2,1)

a ⊕ b
a ⊗ b

mutable struct ChiralGraph{T<:HyperComplex{Int8}} <: AbstractSimpleGraph{T}
    ne::Int
    fadjlist::Vector{Vector{T}} # [src]: (dst, dst, dst)
end


text:
module TestDoctest

import ContextualMacros
using Documenter: doctest
using Test

@testset "doctest" begin
    doctest(ContextualMacros; manual = false)
end

end  # module


text:
module PandaModels

import JuMP

import InfrastructureModels
const _IM = InfrastructureModels

import PowerModels
const _PM = PowerModels
import PowerModels: ids, ref, var, con, sol, nw_id_default

import Memento
const LOGGER = Memento.getlogger(PowerModels)

import JSON

import Cbc
import Ipopt
import Juniper

export run_powermodels_pf,
    run_powermodels_opf,
    run_powermodels_ots,
    run_powermodels_tnep,
    run_pandamodels_vd

include("input/pp_to_pm.jl")
include("input/tools.jl")

include("models/vd.jl")

include("models/call_pandamodels.jl")
include("models/call_powermodels.jl")

end


text:
struct TimeReturn
    seconds
end

Base.show(io::IO, tr::TimeReturn) = print(io, Jute.pprint_time(tr.seconds, meaningful_digits=3))

@testgroup "performance" begin

# Usually when testing performance in Julia one makes some
# "warm-up" runs for the JIT to work.
# The thing is that we're only running runtests() once;
# we do not really care how long it takes the second time.
# Same goes for including the test files.
#
# So, to replicate a real test run, we are measuring the time in a newly created process,
# running a bunch of dummy testcases.
function time_test_run(test_include_only::Bool)
    runtests_dir = Jute.get_runtests_dir()
    julia = Base.julia_cmd()
    benchmark = joinpath(runtests_dir, "performance", "runtests_benchmark.jl")
    cmd = `$julia $benchmark $(test_include_only ? "test_include_only" : "")`
    parse(Float64, strip(read(cmd, String)))
end

@testcase tags=[:perf] "full run" begin
    times = [time_test_run(false) for i in 1:5]
    @test_result TimeReturn(minimum(times))
end

# Only measure the time it takes to include the test files.
# TODO: in future we will collect the separate timings in a single run.
@testcase tags=[:perf] "include only" begin
    times = [time_test_run(true) for i in 1:5]
    @test_result TimeReturn(minimum(times))
end

end


text:
using ImageView
using TestImages
using Test

@testset "contrast with kwargs" begin
    # test for the fix in #228
    # Uses 2D images to verify the `axes` and `flipy` kwargs work
    # with a passed CLim argument
    mri = testimage("mri")
    vmin = Float32(minimum(mri))
    vmax = Float32(maximum(mri))
    clim = ImageView.CLim(vmin, vmax)

    ImageView.imshow(mri, clim; axes=(1, 2))
    @test true
    ImageView.imshow(mri, clim; axes=(3, 1), flipy=true)
    @test true
    ImageView.imshow(mri, clim; axes=(3, 2), flipy=true)
    @test true
end

@testset "window size with kwargs" begin
    gd = imshow([1 0; 0 1], canvassize=(500,500))
    get(ENV, "CI", nothing) === nothing && @test all(>=(500), size(gd["gui"]["window"]))
end


text:
module Icons

using Genie, Stipple, StippleUI, StippleUI.API
import Genie.Renderer.Html: HTMLString, normal_element, register_normal_element

export icon

register_normal_element("q__icon", context = @__MODULE__)

function icon(name::Union{String,Symbol},
              args...;
              content::Union{String,Vector,Function} = "",
              wrap::Function = StippleUI.DEFAULT_WRAPPER,
              kwargs...)

  wrap() do
    q__icon([isa(content, Function) ? content() : join(content)], args...; attributes([:name => name, kwargs...])...)
  end
end

icon( content::Union{Vector,Function},
      args...;
      wrap::Function = StippleUI.DEFAULT_WRAPPER,
      name::Union{Symbol,String} = "",
      kwargs...) = icon(name, args...; content, wrap, kwargs...)

end


text:
using LinearAlgebra

mutable struct Broyden{R <: Real, C <: Union{R, Complex{R}}, T <: AbstractArray{C}}
    H
    theta_bar::R
    function Broyden{R, C, T}(x::T, H, theta_bar) where {R, C, T}
        new(H, theta_bar)
    end
end

Broyden(x::T; H=I, theta_bar=R(0.2)) where {
    R <: Real, C <: Union{R, Complex{R}}, T <: AbstractArray{C}
} = Broyden{R, C, T}(x, H, theta_bar)

_sign(x::R) where R = x == 0 ? R(1) : sign(x)

function update!(L::Broyden{R, C, T}, s, y) where {R, C, T}
    Hy = L.H * y
    sH = s' * L.H
    delta = dot(Hy, s)/norm(s)^2
    theta = if abs(delta) >= L.theta_bar
        R(1)
    else
        (1 - _sign(delta) * L.theta_bar)/(1 - delta)
    end
    L.H += (s - Hy)/dot(s, (1/theta - 1) * s + Hy) * sH
end

import Base: *

function (*)(L::Broyden, v)
    w = similar(v)
    mul!(w, L, v)
end

import LinearAlgebra: mul!

mul!(d::T, L::Broyden, v::T) where {T} = mul!(d, L.H, v)