text:
#=
---------------------------------------------------------------------
This function computes the integer arrays FACE, mapL, and mapR, which
allows us to loop through the faces of the grid in order to perform flux integrals.

Written by F.X. Giraldo on July 14, 2021
           Department of Applied Mathematics
           Naval Postgraduate School
           Monterey; CA 93943-5216
---------------------------------------------------------------------
=#

function create_face_periodicity!(face,iside,coord,Nface,Nboun)

    #Constant
    tol=DFloat(1e-6)

    #Local arrays
    Nhull=Int(Nboun/4)
    ileft=zeros(Int64,Nhull,1)
    iright=zeros(Int64,Nhull,1)
    itop=zeros(Int64,Nhull,1)
    ibot=zeros(Int64,Nhull,1)

    #initialize
    nleft=0
    nright=0
    ntop=0
    nbot=0

    #Find Extrema of Domain
    xmax=maximum(coord[1,:])
    xmin=minimum(coord[1,:])
    ymax=maximum(coord[2,:])
    ymin=minimum(coord[2,:])

    #loop thru sides and extract Left; Right; Bot; & Top
    for s=1:Nface

        #Check for Periodicity Edges
        ier=face[4,s]
        if (ier == -6)

            i1=iside[1,s]
            i2=iside[2,s]
            xm=0.5*( coord[1,i1] + coord[1,i2] )
            ym=0.5*( coord[2,i1] + coord[2,i2] )

            #check Grid Point
            if ( abs(xm - xmin) < tol ) #left boundary
               nleft=nleft + 1
               ileft[nleft]=s
            elseif ( abs(xm - xmax) < tol ) #right boundary
               nright=nright + 1
               iright[nright]=s
            elseif ( abs(ym - ymin) < tol ) #bottom boundary
               nbot=nbot + 1
               ibot[nbot]=s
            elseif ( abs(ym - ymax) < tol ) #top boundary
               ntop=ntop + 1
               itop[ntop]=s
            else
               println("Error in CREATE_FACE_PERIODICITY. No match in PERIODIC_BCS for: s = ",s," ier = ",ier)
                exit
            end #if
        end #ier
    end #s

    #-----Loop through Periodic BCs

    #First: Do Left & Right
    for i=1:nleft
        sl=ileft[i]
        i1=iside[1,sl]
        yl1=coord[2,i1]

        #Search for Corresponding Right Edge
        for j=1:nright
            sr=iright[j]
            i2=iside[2,sr]
            yr2=coord[2,i2]
            if ( abs(yl1-yr2) < tol ) #they match
               face[2,sl]=face[1,sr]
               face[4,sl]=face[3,sr]
               face[1,sr]=sl #store the face number that this face replicates on the Left side
               face[3,sr]=-6; #means skip it due to Periodicity
               iside[4,sl]=iside[3,sr]
               iside[3,sr]=-6
               break
            end #if
        end #j
    end #i

    #Second: Do Top & Bottom
    for i=1:nbot
        sl=ibot[i]
        i1=iside[1,sl]
        xl1=coord[1,i1]

        #Search for Corresponding Top Edge
        for j=1:ntop
            sr=itop[j]
            i2=iside[2,sr]
            xr2=coord[1,i2]
            if ( abs(xl1-xr2) < tol ) #they match
               face[2,sl]=face[1,sr]
               face[4,sl]=face[3,sr]
               face[1,sr]=sl #store the face number that this face replicates on the Left side
               face[3,sr]=-6; #means skip it due to Periodicity
               iside[4,sl]=iside[3,sr]
               iside[3,sr]=-6
               break
            end #if
         end #j
    end #i

    return(face,iside)
end


text:
# ------------------------------------
# calculate Residuals
# ------------------------------------
function set_res(res, Delta_Qcon_hat, Delta_Qcon_hat_temp, cellxmax, cellymax, cellzmax, nval, icell)
    for l in 1:nval
        for k in 1+icell:cellzmax-icell
            for j in 1+icell:cellymax-icell
                for i in 1+icell:cellxmax-icell
                    res[i,j,k,l] = abs(Delta_Qcon_hat[i,j,k,l]-Delta_Qcon_hat_temp[i,j,k,l])
                end
            end
        end
    end
    return res
end

# ------------------------------------
# calculate Residuals by norm-2
# ------------------------------------
function check_converge(res, RHS, cellxmax, cellymax, cellzmax, init_small, nval, icell)
    norm2 = zeros(nval)

    tempAxb = zeros(nval)
    tempb = zeros(nval)
    for l in 1:nval
        for k in 1+icell:cellzmax-icell
            for j in 1+icell:cellymax-icell
                for i in 1+icell:cellxmax-icell
                    tempAxb[l] = tempAxb[l] + res[i,j,k,l]^2
                    tempb[l] = tempb[l] + RHS[i,j,k,l]^2
                end
            end
        end
    end
    for l in 1:nval
        norm2[l] = (tempAxb[l]/(tempb[l]+init_small)) ^ 0.5
    end
    return norm2
end

ext: jl


text:
"""
Creates lossy converter model between AC and DC grid
```
pconv_ac[i] + pconv_dc[i] == a + bI + cI^2
```
"""
function constraint_converter_losses(pm::_PM.AbstractACPModel, n::Int, i::Int, a, b, c, plmax)
    pconv_ac = _PM.var(pm, n, :pconv_ac, i)
    pconv_dc = _PM.var(pm, n, :pconv_dc, i)
    iconv = _PM.var(pm, n, :iconv_ac, i)

    JuMP.@NLconstraint(pm.model, pconv_ac + pconv_dc == a + b*iconv + c*iconv^2)
end
"""
Links converter power & current
```
pconv_ac[i]^2 + pconv_dc[i]^2 == vmc[i]^2 * iconv_ac[i]^2
```
"""
function constraint_converter_current(pm::_PM.AbstractACPModel, n::Int, i::Int, Umax, Imax)
    vmc = _PM.var(pm, n, :vmc, i)
    pconv_ac = _PM.var(pm, n, :pconv_ac, i)
    qconv_ac = _PM.var(pm, n, :qconv_ac, i)
    iconv = _PM.var(pm, n, :iconv_ac, i)

    JuMP.@NLconstraint(pm.model, pconv_ac^2 + qconv_ac^2 == vmc^2 * iconv^2)
end
"""
Converter transformer constraints
```
p_tf_fr ==  g/(tm^2)*vm_fr^2 + -g/(tm)*vm_fr*vm_to * cos(va_fr-va_to) + -b/(tm)*vm_fr*vm_to*sin(va_fr-va_to)
q_tf_fr == -b/(tm^2)*vm_fr^2 +  b/(tm)*vm_fr*vm_to * cos(va_fr-va_to) + -g/(tm)*vm_fr*vm_to*sin(va_fr-va_to)
p_tf_to ==  g*vm_to^2 + -g/(tm)*vm_to*vm_fr  *    cos(va_to - va_fr)     + -b/(tm)*vm_to*vm_fr    *sin(va_to - va_fr)
q_tf_to == -b*vm_to^2 +  b/(tm)*vm_to*vm_fr  *    cos(va_to - va_fr)     + -g/(tm)*vm_to*vm_fr    *sin(va_to - va_fr)
```
"""
function constraint_conv_transformer(pm::_PM.AbstractACPModel, n::Int, i::Int, rtf, xtf, acbus, tm, transformer)
    ptf_fr = _PM.var(pm, n, :pconv_tf_fr, i)
    qtf_fr = _PM.var(pm, n, :qconv_tf_fr, i)
    ptf_to = _PM.var(pm, n, :pconv_tf_to, i)
    qtf_to = _PM.var(pm, n, :qconv_tf_to, i)

    vm = _PM.var(pm, n, :vm, acbus)
    va = _PM.var(pm, n, :va, acbus)
    vmf = _PM.var(pm, n, :vmf, i)
    vaf = _PM.var(pm, n, :vaf, i)

    ztf = rtf + im*xtf
    if transformer
        ytf = 1/(rtf + im*xtf)
        gtf = real(ytf)
        btf = imag(ytf)
        gtf_sh = 0
        c1, c2, c3, c4 = ac_power_flow_constraints(pm.model, gtf, btf, gtf_sh, vm, vmf, va, vaf, ptf_fr, ptf_to, qtf_fr, qtf_to, tm)
    else
        JuMP.@constraint(pm.model, ptf_fr + ptf_to == 0)
        JuMP.@constraint(pm.model, qtf_fr + qtf_to == 0)
        JuMP.@constraint(pm.model, va == vaf)
        JuMP.@constraint(pm.model, vm == vmf)
    end
end
"constraints for a voltage magnitude transformer + series impedance"
function ac_power_flow_constraints(model, g, b, gsh_fr, vm_fr, vm_to, va_fr, va_to, p_fr, p_to, q_fr, q_to, tm)
    c1 = JuMP.@NLconstraint(model, p_fr ==  g/(tm^2)*vm_fr^2 + -g/(tm)*vm_fr*vm_to * cos(va_fr-va_to) + -b/(tm)*vm_fr*vm_to*sin(va_fr-va_to))
    c2 = JuMP.@NLconstraint(model, q_fr == -b/(tm^2)*vm_fr^2 +  b/(tm)*vm_fr*vm_to * cos(va_fr-va_to) + -g/(tm)*vm_fr*vm_to*sin(va_fr-va_to))
    c3 = JuMP.@NLconstraint(model, p_to ==  g*vm_to^2 + -g/(tm)*vm_to*vm_fr  *    cos(va_to - va_fr)     + -b/(tm)*vm_to*vm_fr    *sin(va_to - va_fr))
    c4 = JuMP.@NLconstraint(model, q_to == -b*vm_to^2 +  b/(tm)*vm_to*vm_fr  *    cos(va_to - va_fr)     + -g/(tm)*vm_to*vm_fr    *sin(va_to - va_fr))
    return c1, c2, c3, c4
end
"""
Converter reactor constraints
```
-pconv_ac == gc*vmc^2 + -gc*vmc*vmf*cos(vac-vaf) + -bc*vmc*vmf*sin(vac-vaf)
-qconv_ac ==-bc*vmc^2 +  bc*vmc*vmf*cos(vac-vaf) + -gc*vmc*vmf*sin(vac-vaf)
p_pr_fr ==  gc *vmf^2 + -gc *vmf*vmc*cos(vaf - vac) + -bc *vmf*vmc*sin(vaf - vac)
q_pr_fr == -bc *vmf^2 +  bc *vmf*vmc*cos(vaf - vac) + -gc *vmf*vmc*sin(vaf - vac)
```
"""
function constraint_conv_reactor(pm::_PM.AbstractACPModel, n::Int, i::Int, rc, xc, reactor)
    pconv_ac = _PM.var(pm, n,  :pconv_ac, i)
    qconv_ac = _PM.var(pm, n,  :qconv_ac, i)
    ppr_to = - pconv_ac
    qpr_to = - qconv_ac
    ppr_fr = _PM.var(pm, n,  :pconv_pr_fr, i)
    qpr_fr = _PM.var(pm, n,  :qconv_pr_fr, i)

    vmf = _PM.var(pm, n, :vmf, i)
    vaf = _PM.var(pm, n, :vaf, i)
    vmc = _PM.var(pm, n, :vmc, i)
    vac = _PM.var(pm, n, :vac, i)

    zc = rc + im*xc
    if reactor
        yc = 1/(zc)
        gc = real(yc)
        bc = imag(yc)
        JuMP.@NLconstraint(pm.model, - pconv_ac == gc*vmc^2 + -gc*vmc*vmf*cos(vac-vaf) + -bc*vmc*vmf*sin(vac-vaf)) # JuMP doesn't allow affine expressions in NL constraints
        JuMP.@NLconstraint(pm.model, - qconv_ac ==-bc*vmc^2 +  bc*vmc*vmf*cos(vac-vaf) + -gc*vmc*vmf*sin(vac-vaf)) # JuMP doesn't allow affine expressions in NL constraints
        JuMP.@NLconstraint(pm.model, ppr_fr ==  gc *vmf^2 + -gc *vmf*vmc*cos(vaf - vac) + -bc *vmf*vmc*sin(vaf - vac))
        JuMP.@NLconstraint(pm.model, qpr_fr == -bc *vmf^2 +  bc *vmf*vmc*cos(vaf - vac) + -gc *vmf*vmc*sin(vaf - vac))
    else
        JuMP.@constraint(pm.model, ppr_fr + ppr_to == 0)
        JuMP.@constraint(pm.model, qpr_fr + qpr_to == 0)
        JuMP.@constraint(pm.model, vac == vaf)
        JuMP.@constraint(pm.model, vmc == vmf)
    end
end
"""
Converter filter constraints
```
ppr_fr + ptf_to == 0
qpr_fr + qtf_to +  (-bv) * filter *vmf^2 == 0
```
"""
function constraint_conv_filter(pm::_PM.AbstractACPModel, n::Int, i::Int, bv, filter)
    ppr_fr = _PM.var(pm, n, :pconv_pr_fr, i)
    qpr_fr = _PM.var(pm, n, :qconv_pr_fr, i)
    ptf_to = _PM.var(pm, n, :pconv_tf_to, i)
    qtf_to = _PM.var(pm, n, :qconv_tf_to, i)

    vmf = _PM.var(pm, n, :vmf, i)

    JuMP.@constraint(pm.model,   ppr_fr + ptf_to == 0 )
    JuMP.@NLconstraint(pm.model, qpr_fr + qtf_to +  (-bv) * filter *vmf^2 == 0)
end
"""
LCC firing angle constraints
```
pconv_ac == cos(phi) * Srated
qconv_ac == sin(phi) * Srated
```
"""
function constraint_conv_firing_angle(pm::_PM.AbstractACPModel, n::Int, i::Int, S, P1, Q1, P2, Q2)
    p = _PM.var(pm, n, :pconv_ac, i)
    q = _PM.var(pm, n, :qconv_ac, i)
    phi = _PM.var(pm, n, :phiconv, i)

    JuMP.@NLconstraint(pm.model,   p == cos(phi) * S)
    JuMP.@NLconstraint(pm.model,   q == sin(phi) * S)
end

function constraint_dc_droop_control(pm::_PM.AbstractACPModel, n::Int, i::Int, busdc_i, vref_dc, pref_dc, k_droop)
    pconv_dc = _PM.var(pm, n, :pconv_dc, i)
    vdc = _PM.var(pm, n, :vdcm, busdc_i)

    JuMP.@constraint(pm.model, pconv_dc == pref_dc - sign(pref_dc) * 1 / k_droop * (vdc - vref_dc))
end

#################### TNEP Constraints #########################
"""
Creates lossy converter model between AC and DC grid

```
pconv_ac[i] + pconv_dc[i] == a + bI + cI^2
```
"""
function constraint_converter_losses_ne(pm::_PM.AbstractACPModel, n::Int, i::Int, a, b, c, plmax)
    pconv_ac = _PM.var(pm, n, :pconv_ac_ne, i)
    pconv_dc = _PM.var(pm, n, :pconv_dc_ne, i)
    iconv = _PM.var(pm, n, :iconv_ac_ne, i)
    z = _PM.var(pm, n, :conv_ne, i)

    JuMP.@NLconstraint(pm.model, pconv_ac + pconv_dc == a*z + b*iconv + c*iconv^2)
end

"""
Links converter power & current

```
pconv_ac[i]^2 + pconv_dc[i]^2 == vmc[i]^2 * iconv_ac[i]^2
```
"""
function constraint_converter_current_ne(pm::_PM.AbstractACPModel, n::Int, i::Int, Umax, Imax)
    vmc = _PM.var(pm, n, :vmc_ne, i)
    pconv_ac = _PM.var(pm, n, :pconv_ac_ne, i)
    qconv_ac = _PM.var(pm, n, :qconv_ac_ne, i)
    iconv = _PM.var(pm, n, :iconv_ac_ne, i)

    JuMP.@NLconstraint(pm.model, pconv_ac^2 + qconv_ac^2 == vmc^2 * iconv^2)
end

"""
Converter transformer constraints

```
p_tf_fr ==  g/(tm^2)*vm_fr^2 + -g/(tm)*vm_fr*vm_to * cos(va_fr-va_to) + -b/(tm)*vm_fr*vm_to*sin(va_fr-va_to)
q_tf_fr == -b/(tm^2)*vm_fr^2 +  b/(tm)*vm_fr*vm_to * cos(va_fr-va_to) + -g/(tm)*vm_fr*vm_to*sin(va_fr-va_to)
p_tf_to ==  g*vm_to^2 + -g/(tm)*vm_to*vm_fr  *    cos(va_to - va_fr)     + -b/(tm)*vm_to*vm_fr    *sin(va_to - va_fr)
q_tf_to == -b*vm_to^2 +  b/(tm)*vm_to*vm_fr  *    cos(va_to - va_fr)     + -g/(tm)*vm_to*vm_fr    *sin(va_to - va_fr)
```
"""
function constraint_conv_transformer_ne(pm::_PM.AbstractACPModel, n::Int, i::Int, rtf, xtf, acbus, tm, transformer)

    ptf_fr = _PM.var(pm, n, :pconv_tf_fr_ne, i)
    qtf_fr = _PM.var(pm, n, :qconv_tf_fr_ne, i)
    ptf_to = _PM.var(pm, n, :pconv_tf_to_ne, i)
    qtf_to = _PM.var(pm, n, :qconv_tf_to_ne, i)

    vm = _PM.var(pm, n, :vm, acbus)
    va = _PM.var(pm, n, :va, acbus)
    vmf = _PM.var(pm, n, :vmf_ne, i)
    vaf = _PM.var(pm, n, :vaf_ne, i)
    z = _PM.var(pm, n, :conv_ne)[i]
    ztf = rtf + im*xtf
    if transformer
        ytf = 1/(rtf + im*xtf)
        gtf = real(ytf)
        btf = imag(ytf)
        gtf_sh = 0
        c1, c2, c3, c4 = ac_power_flow_constraints(pm.model, gtf, btf, gtf_sh, vm, vmf, va, vaf, ptf_fr, ptf_to, qtf_fr, qtf_to, tm, z)
    else
        JuMP.@constraint(pm.model, ptf_fr + ptf_to == 0)
        JuMP.@constraint(pm.model, qtf_fr + qtf_to == 0)
        JuMP.@constraint(pm.model, va == vaf)
        JuMP.@constraint(pm.model, vm/(tm) == vmf)
    end
end

"constraints for a voltage magnitude transformer + series impedance"
function ac_power_flow_constraints(model, g, b, gsh_fr, vm_fr, vm_to, va_fr, va_to, p_fr, p_to, q_fr, q_to, tm, z)
    c1 = JuMP.@NLconstraint(model, p_fr ==  z* (g/(tm^2)*vm_fr^2 + -g/(tm)*vm_fr*vm_to * cos(va_fr-va_to) + -b/(tm)*vm_fr*vm_to*sin(va_fr-va_to)))
    c2 = JuMP.@NLconstraint(model, q_fr == z* (-b/(tm^2)*vm_fr^2 +  b/(tm)*vm_fr*vm_to * cos(va_fr-va_to) + -g/(tm)*vm_fr*vm_to*sin(va_fr-va_to)))
    c3 = JuMP.@NLconstraint(model, p_to == z* (g*vm_to^2 + -g/(tm)*vm_to*vm_fr  *    cos(va_to - va_fr)     + -b/(tm)*vm_to*vm_fr    *sin(va_to - va_fr)))
    c4 = JuMP.@NLconstraint(model, q_to == z* (-b*vm_to^2 +  b/(tm)*vm_to*vm_fr  *    cos(va_to - va_fr)     + -g/(tm)*vm_to*vm_fr    *sin(va_to - va_fr)))
    return c1, c2, c3, c4
end

"""
Converter reactor constraints

```
-pconv_ac == gc*vmc^2 + -gc*vmc*vmf*cos(vac-vaf) + -bc*vmc*vmf*sin(vac-vaf)
-qconv_ac ==-bc*vmc^2 +  bc*vmc*vmf*cos(vac-vaf) + -gc*vmc*vmf*sin(vac-vaf)
p_pr_fr ==  gc *vmf^2 + -gc *vmf*vmc*cos(vaf - vac) + -bc *vmf*vmc*sin(vaf - vac)
q_pr_fr == -bc *vmf^2 +  bc *vmf*vmc*cos(vaf - vac) + -gc *vmf*vmc*sin(vaf - vac)
```
"""
function constraint_conv_reactor_ne(pm::_PM.AbstractACPModel, n::Int, i::Int, rc, xc, reactor)
    pconv_ac = _PM.var(pm, n,  :pconv_ac_ne, i)
    qconv_ac = _PM.var(pm, n,  :qconv_ac_ne, i)
    ppr_to = - pconv_ac
    qpr_to = - qconv_ac
    ppr_fr = _PM.var(pm, n,  :pconv_pr_fr_ne, i)
    qpr_fr = _PM.var(pm, n,  :qconv_pr_fr_ne, i)

    vmf = _PM.var(pm, n, :vmf_ne, i)
    vaf = _PM.var(pm, n, :vaf_ne, i)
    vmc = _PM.var(pm, n, :vmc_ne, i)
    vac = _PM.var(pm, n, :vac_ne, i)
    zc = rc + im*xc
    z = _PM.var(pm, n, :conv_ne)[i]

    if reactor
        yc = 1/(zc)
        gc = real(yc)
        bc = imag(yc)
        JuMP.@NLconstraint(pm.model, - pconv_ac == z*(gc*vmc^2 + -gc*vmc*vmf*cos(vac-vaf) + -bc*vmc*vmf*sin(vac-vaf))) # JuMP doesn't allow affine expressions in NL constraints
        JuMP.@NLconstraint(pm.model, - qconv_ac == z*(-bc*vmc^2 +  bc*vmc*vmf*cos(vac-vaf) + -gc*vmc*vmf*sin(vac-vaf))) # JuMP doesn't allow affine expressions in NL constraints
        JuMP.@NLconstraint(pm.model, ppr_fr ==  z*(gc *vmf^2 + -gc *vmf*vmc*cos(vaf - vac) + -bc *vmf*vmc*sin(vaf - vac)))
        JuMP.@NLconstraint(pm.model, qpr_fr ==  z*(-bc *vmf^2 +  bc *vmf*vmc*cos(vaf - vac) + -gc *vmf*vmc*sin(vaf - vac)))
    else
        JuMP.@constraint(pm.model, ppr_fr + ppr_to == 0)
        JuMP.@constraint(pm.model, qpr_fr + qpr_to == 0)
        JuMP.@constraint(pm.model, vac == vaf)
        JuMP.@constraint(pm.model, vmc == vmf)

    end
end

"""
Converter filter constraints

```
ppr_fr + ptf_to == 0
qpr_fr + qtf_to +  (-bv) * filter *vmf^2 == 0
```
"""
function constraint_conv_filter_ne(pm::_PM.AbstractACPModel, n::Int, i::Int, bv, filter)
    ppr_fr = _PM.var(pm, n, :pconv_pr_fr_ne, i)
    qpr_fr = _PM.var(pm, n, :qconv_pr_fr_ne, i)
    ptf_to = _PM.var(pm, n, :pconv_tf_to_ne, i)
    qtf_to = _PM.var(pm, n, :qconv_tf_to_ne, i)

    vmf = _PM.var(pm, n, :vmf_ne, i)
    z = _PM.var(pm, n, :conv_ne)[i]

    JuMP.@constraint(pm.model,   ppr_fr + ptf_to == 0 )
    JuMP.@NLconstraint(pm.model, qpr_fr + qtf_to +  z*(-bv) * filter *vmf^2 == 0)
end

"""
LCC firing angle constraints

```
pconv_ac == cos(phi) * Srated
qconv_ac == sin(phi) * Srated
```
"""
function constraint_conv_firing_angle_ne(pm::_PM.AbstractACPModel, n::Int, i::Int, S, P1, Q1, P2, Q2)
    p = _PM.var(pm, n, :pconv_ac_ne, i)
    q = _PM.var(pm, n, :qconv_ac_ne, i)
    phi = _PM.var(pm, n, :phiconv_ne, i)

    JuMP.@NLconstraint(pm.model,   p == cos(phi) * S)
    JuMP.@NLconstraint(pm.model,   q == sin(phi) * S)
end

function variable_voltage_slack(pm::_PM.AbstractACPModel; nw::Int=pm.cnw, bounded::Bool = true, report::Bool=false)
end


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

"""
    AddAttributesToFindings()

Assigns attributes (key and value pairs) to the findings that are specified by the ARNs of the findings.

# Required Parameters
- `attributes`: The array of attributes that you want to assign to specified findings.
- `findingArns`: The ARNs that specify the findings that you want to assign attributes to.

"""
add_attributes_to_findings(attributes, findingArns; aws_config::AWSConfig=global_aws_config()) = inspector("AddAttributesToFindings", Dict{String, Any}("attributes"=>attributes, "findingArns"=>findingArns); aws_config=aws_config)
add_attributes_to_findings(attributes, findingArns, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("AddAttributesToFindings", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("attributes"=>attributes, "findingArns"=>findingArns), args)); aws_config=aws_config)

"""
    CreateAssessmentTarget()

Creates a new assessment target using the ARN of the resource group that is generated by CreateResourceGroup. If resourceGroupArn is not specified, all EC2 instances in the current AWS account and region are included in the assessment target. If the service-linked role isn’t already registered, this action also creates and registers a service-linked role to grant Amazon Inspector access to AWS Services needed to perform security assessments. You can create up to 50 assessment targets per AWS account. You can run up to 500 concurrent agents per AWS account. For more information, see  Amazon Inspector Assessment Targets.

# Required Parameters
- `assessmentTargetName`: The user-defined name that identifies the assessment target that you want to create. The name must be unique within the AWS account.

# Optional Parameters
- `resourceGroupArn`: The ARN that specifies the resource group that is used to create the assessment target. If resourceGroupArn is not specified, all EC2 instances in the current AWS account and region are included in the assessment target.
"""
create_assessment_target(assessmentTargetName; aws_config::AWSConfig=global_aws_config()) = inspector("CreateAssessmentTarget", Dict{String, Any}("assessmentTargetName"=>assessmentTargetName); aws_config=aws_config)
create_assessment_target(assessmentTargetName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("CreateAssessmentTarget", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentTargetName"=>assessmentTargetName), args)); aws_config=aws_config)

"""
    CreateAssessmentTemplate()

Creates an assessment template for the assessment target that is specified by the ARN of the assessment target. If the service-linked role isn’t already registered, this action also creates and registers a service-linked role to grant Amazon Inspector access to AWS Services needed to perform security assessments.

# Required Parameters
- `assessmentTargetArn`: The ARN that specifies the assessment target for which you want to create the assessment template.
- `assessmentTemplateName`: The user-defined name that identifies the assessment template that you want to create. You can create several assessment templates for an assessment target. The names of the assessment templates that correspond to a particular assessment target must be unique.
- `durationInSeconds`: The duration of the assessment run in seconds.
- `rulesPackageArns`: The ARNs that specify the rules packages that you want to attach to the assessment template.

# Optional Parameters
- `userAttributesForFindings`: The user-defined attributes that are assigned to every finding that is generated by the assessment run that uses this assessment template. An attribute is a key and value pair (an Attribute object). Within an assessment template, each key must be unique.
"""
create_assessment_template(assessmentTargetArn, assessmentTemplateName, durationInSeconds, rulesPackageArns; aws_config::AWSConfig=global_aws_config()) = inspector("CreateAssessmentTemplate", Dict{String, Any}("assessmentTargetArn"=>assessmentTargetArn, "assessmentTemplateName"=>assessmentTemplateName, "durationInSeconds"=>durationInSeconds, "rulesPackageArns"=>rulesPackageArns); aws_config=aws_config)
create_assessment_template(assessmentTargetArn, assessmentTemplateName, durationInSeconds, rulesPackageArns, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("CreateAssessmentTemplate", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentTargetArn"=>assessmentTargetArn, "assessmentTemplateName"=>assessmentTemplateName, "durationInSeconds"=>durationInSeconds, "rulesPackageArns"=>rulesPackageArns), args)); aws_config=aws_config)

"""
    CreateExclusionsPreview()

Starts the generation of an exclusions preview for the specified assessment template. The exclusions preview lists the potential exclusions (ExclusionPreview) that Inspector can detect before it runs the assessment.

# Required Parameters
- `assessmentTemplateArn`: The ARN that specifies the assessment template for which you want to create an exclusions preview.

"""
create_exclusions_preview(assessmentTemplateArn; aws_config::AWSConfig=global_aws_config()) = inspector("CreateExclusionsPreview", Dict{String, Any}("assessmentTemplateArn"=>assessmentTemplateArn); aws_config=aws_config)
create_exclusions_preview(assessmentTemplateArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("CreateExclusionsPreview", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentTemplateArn"=>assessmentTemplateArn), args)); aws_config=aws_config)

"""
    CreateResourceGroup()

Creates a resource group using the specified set of tags (key and value pairs) that are used to select the EC2 instances to be included in an Amazon Inspector assessment target. The created resource group is then used to create an Amazon Inspector assessment target. For more information, see CreateAssessmentTarget.

# Required Parameters
- `resourceGroupTags`: A collection of keys and an array of possible values, '[{\"key\":\"key1\",\"values\":[\"Value1\",\"Value2\"]},{\"key\":\"Key2\",\"values\":[\"Value3\"]}]'. For example,'[{\"key\":\"Name\",\"values\":[\"TestEC2Instance\"]}]'.

"""
create_resource_group(resourceGroupTags; aws_config::AWSConfig=global_aws_config()) = inspector("CreateResourceGroup", Dict{String, Any}("resourceGroupTags"=>resourceGroupTags); aws_config=aws_config)
create_resource_group(resourceGroupTags, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("CreateResourceGroup", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("resourceGroupTags"=>resourceGroupTags), args)); aws_config=aws_config)

"""
    DeleteAssessmentRun()

Deletes the assessment run that is specified by the ARN of the assessment run.

# Required Parameters
- `assessmentRunArn`: The ARN that specifies the assessment run that you want to delete.

"""
delete_assessment_run(assessmentRunArn; aws_config::AWSConfig=global_aws_config()) = inspector("DeleteAssessmentRun", Dict{String, Any}("assessmentRunArn"=>assessmentRunArn); aws_config=aws_config)
delete_assessment_run(assessmentRunArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("DeleteAssessmentRun", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentRunArn"=>assessmentRunArn), args)); aws_config=aws_config)

"""
    DeleteAssessmentTarget()

Deletes the assessment target that is specified by the ARN of the assessment target.

# Required Parameters
- `assessmentTargetArn`: The ARN that specifies the assessment target that you want to delete.

"""
delete_assessment_target(assessmentTargetArn; aws_config::AWSConfig=global_aws_config()) = inspector("DeleteAssessmentTarget", Dict{String, Any}("assessmentTargetArn"=>assessmentTargetArn); aws_config=aws_config)
delete_assessment_target(assessmentTargetArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("DeleteAssessmentTarget", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentTargetArn"=>assessmentTargetArn), args)); aws_config=aws_config)

"""
    DeleteAssessmentTemplate()

Deletes the assessment template that is specified by the ARN of the assessment template.

# Required Parameters
- `assessmentTemplateArn`: The ARN that specifies the assessment template that you want to delete.

"""
delete_assessment_template(assessmentTemplateArn; aws_config::AWSConfig=global_aws_config()) = inspector("DeleteAssessmentTemplate", Dict{String, Any}("assessmentTemplateArn"=>assessmentTemplateArn); aws_config=aws_config)
delete_assessment_template(assessmentTemplateArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("DeleteAssessmentTemplate", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentTemplateArn"=>assessmentTemplateArn), args)); aws_config=aws_config)

"""
    DescribeAssessmentRuns()

Describes the assessment runs that are specified by the ARNs of the assessment runs.

# Required Parameters
- `assessmentRunArns`: The ARN that specifies the assessment run that you want to describe.

"""
describe_assessment_runs(assessmentRunArns; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeAssessmentRuns", Dict{String, Any}("assessmentRunArns"=>assessmentRunArns); aws_config=aws_config)
describe_assessment_runs(assessmentRunArns, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeAssessmentRuns", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentRunArns"=>assessmentRunArns), args)); aws_config=aws_config)

"""
    DescribeAssessmentTargets()

Describes the assessment targets that are specified by the ARNs of the assessment targets.

# Required Parameters
- `assessmentTargetArns`: The ARNs that specifies the assessment targets that you want to describe.

"""
describe_assessment_targets(assessmentTargetArns; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeAssessmentTargets", Dict{String, Any}("assessmentTargetArns"=>assessmentTargetArns); aws_config=aws_config)
describe_assessment_targets(assessmentTargetArns, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeAssessmentTargets", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentTargetArns"=>assessmentTargetArns), args)); aws_config=aws_config)

"""
    DescribeAssessmentTemplates()

Describes the assessment templates that are specified by the ARNs of the assessment templates.

# Required Parameters
- `assessmentTemplateArns`:

"""
describe_assessment_templates(assessmentTemplateArns; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeAssessmentTemplates", Dict{String, Any}("assessmentTemplateArns"=>assessmentTemplateArns); aws_config=aws_config)
describe_assessment_templates(assessmentTemplateArns, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeAssessmentTemplates", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentTemplateArns"=>assessmentTemplateArns), args)); aws_config=aws_config)

"""
    DescribeCrossAccountAccessRole()

Describes the IAM role that enables Amazon Inspector to access your AWS account.

"""
describe_cross_account_access_role(; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeCrossAccountAccessRole"; aws_config=aws_config)
describe_cross_account_access_role(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeCrossAccountAccessRole", args; aws_config=aws_config)

"""
    DescribeExclusions()

Describes the exclusions that are specified by the exclusions' ARNs.

# Required Parameters
- `exclusionArns`: The list of ARNs that specify the exclusions that you want to describe.

# Optional Parameters
- `locale`: The locale into which you want to translate the exclusion's title, description, and recommendation.
"""
describe_exclusions(exclusionArns; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeExclusions", Dict{String, Any}("exclusionArns"=>exclusionArns); aws_config=aws_config)
describe_exclusions(exclusionArns, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeExclusions", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("exclusionArns"=>exclusionArns), args)); aws_config=aws_config)

"""
    DescribeFindings()

Describes the findings that are specified by the ARNs of the findings.

# Required Parameters
- `findingArns`: The ARN that specifies the finding that you want to describe.

# Optional Parameters
- `locale`: The locale into which you want to translate a finding description, recommendation, and the short description that identifies the finding.
"""
describe_findings(findingArns; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeFindings", Dict{String, Any}("findingArns"=>findingArns); aws_config=aws_config)
describe_findings(findingArns, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeFindings", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("findingArns"=>findingArns), args)); aws_config=aws_config)

"""
    DescribeResourceGroups()

Describes the resource groups that are specified by the ARNs of the resource groups.

# Required Parameters
- `resourceGroupArns`: The ARN that specifies the resource group that you want to describe.

"""
describe_resource_groups(resourceGroupArns; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeResourceGroups", Dict{String, Any}("resourceGroupArns"=>resourceGroupArns); aws_config=aws_config)
describe_resource_groups(resourceGroupArns, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeResourceGroups", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("resourceGroupArns"=>resourceGroupArns), args)); aws_config=aws_config)

"""
    DescribeRulesPackages()

Describes the rules packages that are specified by the ARNs of the rules packages.

# Required Parameters
- `rulesPackageArns`: The ARN that specifies the rules package that you want to describe.

# Optional Parameters
- `locale`: The locale that you want to translate a rules package description into.
"""
describe_rules_packages(rulesPackageArns; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeRulesPackages", Dict{String, Any}("rulesPackageArns"=>rulesPackageArns); aws_config=aws_config)
describe_rules_packages(rulesPackageArns, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("DescribeRulesPackages", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("rulesPackageArns"=>rulesPackageArns), args)); aws_config=aws_config)

"""
    GetAssessmentReport()

Produces an assessment report that includes detailed and comprehensive results of a specified assessment run.

# Required Parameters
- `assessmentRunArn`: The ARN that specifies the assessment run for which you want to generate a report.
- `reportFileFormat`: Specifies the file format (html or pdf) of the assessment report that you want to generate.
- `reportType`: Specifies the type of the assessment report that you want to generate. There are two types of assessment reports: a finding report and a full report. For more information, see Assessment Reports.

"""
get_assessment_report(assessmentRunArn, reportFileFormat, reportType; aws_config::AWSConfig=global_aws_config()) = inspector("GetAssessmentReport", Dict{String, Any}("assessmentRunArn"=>assessmentRunArn, "reportFileFormat"=>reportFileFormat, "reportType"=>reportType); aws_config=aws_config)
get_assessment_report(assessmentRunArn, reportFileFormat, reportType, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("GetAssessmentReport", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentRunArn"=>assessmentRunArn, "reportFileFormat"=>reportFileFormat, "reportType"=>reportType), args)); aws_config=aws_config)

"""
    GetExclusionsPreview()

Retrieves the exclusions preview (a list of ExclusionPreview objects) specified by the preview token. You can obtain the preview token by running the CreateExclusionsPreview API.

# Required Parameters
- `assessmentTemplateArn`: The ARN that specifies the assessment template for which the exclusions preview was requested.
- `previewToken`: The unique identifier associated of the exclusions preview.

# Optional Parameters
- `locale`: The locale into which you want to translate the exclusion's title, description, and recommendation.
- `maxResults`: You can use this parameter to indicate the maximum number of items you want in the response. The default value is 100. The maximum value is 500.
- `nextToken`: You can use this parameter when paginating results. Set the value of this parameter to null on your first call to the GetExclusionsPreviewRequest action. Subsequent calls to the action fill nextToken in the request with the value of nextToken from the previous response to continue listing data.
"""
get_exclusions_preview(assessmentTemplateArn, previewToken; aws_config::AWSConfig=global_aws_config()) = inspector("GetExclusionsPreview", Dict{String, Any}("assessmentTemplateArn"=>assessmentTemplateArn, "previewToken"=>previewToken); aws_config=aws_config)
get_exclusions_preview(assessmentTemplateArn, previewToken, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("GetExclusionsPreview", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentTemplateArn"=>assessmentTemplateArn, "previewToken"=>previewToken), args)); aws_config=aws_config)

"""
    GetTelemetryMetadata()

Information about the data that is collected for the specified assessment run.

# Required Parameters
- `assessmentRunArn`: The ARN that specifies the assessment run that has the telemetry data that you want to obtain.

"""
get_telemetry_metadata(assessmentRunArn; aws_config::AWSConfig=global_aws_config()) = inspector("GetTelemetryMetadata", Dict{String, Any}("assessmentRunArn"=>assessmentRunArn); aws_config=aws_config)
get_telemetry_metadata(assessmentRunArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("GetTelemetryMetadata", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentRunArn"=>assessmentRunArn), args)); aws_config=aws_config)

"""
    ListAssessmentRunAgents()

Lists the agents of the assessment runs that are specified by the ARNs of the assessment runs.

# Required Parameters
- `assessmentRunArn`: The ARN that specifies the assessment run whose agents you want to list.

# Optional Parameters
- `filter`: You can use this parameter to specify a subset of data to be included in the action's response. For a record to match a filter, all specified filter attributes must match. When multiple values are specified for a filter attribute, any of the values can match.
- `maxResults`: You can use this parameter to indicate the maximum number of items that you want in the response. The default value is 10. The maximum value is 500.
- `nextToken`: You can use this parameter when paginating results. Set the value of this parameter to null on your first call to the ListAssessmentRunAgents action. Subsequent calls to the action fill nextToken in the request with the value of NextToken from the previous response to continue listing data.
"""
list_assessment_run_agents(assessmentRunArn; aws_config::AWSConfig=global_aws_config()) = inspector("ListAssessmentRunAgents", Dict{String, Any}("assessmentRunArn"=>assessmentRunArn); aws_config=aws_config)
list_assessment_run_agents(assessmentRunArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("ListAssessmentRunAgents", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentRunArn"=>assessmentRunArn), args)); aws_config=aws_config)

"""
    ListAssessmentRuns()

Lists the assessment runs that correspond to the assessment templates that are specified by the ARNs of the assessment templates.

# Optional Parameters
- `assessmentTemplateArns`: The ARNs that specify the assessment templates whose assessment runs you want to list.
- `filter`: You can use this parameter to specify a subset of data to be included in the action's response. For a record to match a filter, all specified filter attributes must match. When multiple values are specified for a filter attribute, any of the values can match.
- `maxResults`: You can use this parameter to indicate the maximum number of items that you want in the response. The default value is 10. The maximum value is 500.
- `nextToken`: You can use this parameter when paginating results. Set the value of this parameter to null on your first call to the ListAssessmentRuns action. Subsequent calls to the action fill nextToken in the request with the value of NextToken from the previous response to continue listing data.
"""
list_assessment_runs(; aws_config::AWSConfig=global_aws_config()) = inspector("ListAssessmentRuns"; aws_config=aws_config)
list_assessment_runs(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("ListAssessmentRuns", args; aws_config=aws_config)

"""
    ListAssessmentTargets()

Lists the ARNs of the assessment targets within this AWS account. For more information about assessment targets, see Amazon Inspector Assessment Targets.

# Optional Parameters
- `filter`: You can use this parameter to specify a subset of data to be included in the action's response. For a record to match a filter, all specified filter attributes must match. When multiple values are specified for a filter attribute, any of the values can match.
- `maxResults`: You can use this parameter to indicate the maximum number of items you want in the response. The default value is 10. The maximum value is 500.
- `nextToken`: You can use this parameter when paginating results. Set the value of this parameter to null on your first call to the ListAssessmentTargets action. Subsequent calls to the action fill nextToken in the request with the value of NextToken from the previous response to continue listing data.
"""
list_assessment_targets(; aws_config::AWSConfig=global_aws_config()) = inspector("ListAssessmentTargets"; aws_config=aws_config)
list_assessment_targets(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("ListAssessmentTargets", args; aws_config=aws_config)

"""
    ListAssessmentTemplates()

Lists the assessment templates that correspond to the assessment targets that are specified by the ARNs of the assessment targets.

# Optional Parameters
- `assessmentTargetArns`: A list of ARNs that specifies the assessment targets whose assessment templates you want to list.
- `filter`: You can use this parameter to specify a subset of data to be included in the action's response. For a record to match a filter, all specified filter attributes must match. When multiple values are specified for a filter attribute, any of the values can match.
- `maxResults`: You can use this parameter to indicate the maximum number of items you want in the response. The default value is 10. The maximum value is 500.
- `nextToken`: You can use this parameter when paginating results. Set the value of this parameter to null on your first call to the ListAssessmentTemplates action. Subsequent calls to the action fill nextToken in the request with the value of NextToken from the previous response to continue listing data.
"""
list_assessment_templates(; aws_config::AWSConfig=global_aws_config()) = inspector("ListAssessmentTemplates"; aws_config=aws_config)
list_assessment_templates(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("ListAssessmentTemplates", args; aws_config=aws_config)

"""
    ListEventSubscriptions()

Lists all the event subscriptions for the assessment template that is specified by the ARN of the assessment template. For more information, see SubscribeToEvent and UnsubscribeFromEvent.

# Optional Parameters
- `maxResults`: You can use this parameter to indicate the maximum number of items you want in the response. The default value is 10. The maximum value is 500.
- `nextToken`: You can use this parameter when paginating results. Set the value of this parameter to null on your first call to the ListEventSubscriptions action. Subsequent calls to the action fill nextToken in the request with the value of NextToken from the previous response to continue listing data.
- `resourceArn`: The ARN of the assessment template for which you want to list the existing event subscriptions.
"""
list_event_subscriptions(; aws_config::AWSConfig=global_aws_config()) = inspector("ListEventSubscriptions"; aws_config=aws_config)
list_event_subscriptions(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("ListEventSubscriptions", args; aws_config=aws_config)

"""
    ListExclusions()

List exclusions that are generated by the assessment run.

# Required Parameters
- `assessmentRunArn`: The ARN of the assessment run that generated the exclusions that you want to list.

# Optional Parameters
- `maxResults`: You can use this parameter to indicate the maximum number of items you want in the response. The default value is 100. The maximum value is 500.
- `nextToken`: You can use this parameter when paginating results. Set the value of this parameter to null on your first call to the ListExclusionsRequest action. Subsequent calls to the action fill nextToken in the request with the value of nextToken from the previous response to continue listing data.
"""
list_exclusions(assessmentRunArn; aws_config::AWSConfig=global_aws_config()) = inspector("ListExclusions", Dict{String, Any}("assessmentRunArn"=>assessmentRunArn); aws_config=aws_config)
list_exclusions(assessmentRunArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("ListExclusions", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentRunArn"=>assessmentRunArn), args)); aws_config=aws_config)

"""
    ListFindings()

Lists findings that are generated by the assessment runs that are specified by the ARNs of the assessment runs.

# Optional Parameters
- `assessmentRunArns`: The ARNs of the assessment runs that generate the findings that you want to list.
- `filter`: You can use this parameter to specify a subset of data to be included in the action's response. For a record to match a filter, all specified filter attributes must match. When multiple values are specified for a filter attribute, any of the values can match.
- `maxResults`: You can use this parameter to indicate the maximum number of items you want in the response. The default value is 10. The maximum value is 500.
- `nextToken`: You can use this parameter when paginating results. Set the value of this parameter to null on your first call to the ListFindings action. Subsequent calls to the action fill nextToken in the request with the value of NextToken from the previous response to continue listing data.
"""
list_findings(; aws_config::AWSConfig=global_aws_config()) = inspector("ListFindings"; aws_config=aws_config)
list_findings(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("ListFindings", args; aws_config=aws_config)

"""
    ListRulesPackages()

Lists all available Amazon Inspector rules packages.

# Optional Parameters
- `maxResults`: You can use this parameter to indicate the maximum number of items you want in the response. The default value is 10. The maximum value is 500.
- `nextToken`: You can use this parameter when paginating results. Set the value of this parameter to null on your first call to the ListRulesPackages action. Subsequent calls to the action fill nextToken in the request with the value of NextToken from the previous response to continue listing data.
"""
list_rules_packages(; aws_config::AWSConfig=global_aws_config()) = inspector("ListRulesPackages"; aws_config=aws_config)
list_rules_packages(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("ListRulesPackages", args; aws_config=aws_config)

"""
    ListTagsForResource()

Lists all tags associated with an assessment template.

# Required Parameters
- `resourceArn`: The ARN that specifies the assessment template whose tags you want to list.

"""
list_tags_for_resource(resourceArn; aws_config::AWSConfig=global_aws_config()) = inspector("ListTagsForResource", Dict{String, Any}("resourceArn"=>resourceArn); aws_config=aws_config)
list_tags_for_resource(resourceArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("ListTagsForResource", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("resourceArn"=>resourceArn), args)); aws_config=aws_config)

"""
    PreviewAgents()

Previews the agents installed on the EC2 instances that are part of the specified assessment target.

# Required Parameters
- `previewAgentsArn`: The ARN of the assessment target whose agents you want to preview.

# Optional Parameters
- `maxResults`: You can use this parameter to indicate the maximum number of items you want in the response. The default value is 10. The maximum value is 500.
- `nextToken`: You can use this parameter when paginating results. Set the value of this parameter to null on your first call to the PreviewAgents action. Subsequent calls to the action fill nextToken in the request with the value of NextToken from the previous response to continue listing data.
"""
preview_agents(previewAgentsArn; aws_config::AWSConfig=global_aws_config()) = inspector("PreviewAgents", Dict{String, Any}("previewAgentsArn"=>previewAgentsArn); aws_config=aws_config)
preview_agents(previewAgentsArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("PreviewAgents", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("previewAgentsArn"=>previewAgentsArn), args)); aws_config=aws_config)

"""
    RegisterCrossAccountAccessRole()

Registers the IAM role that grants Amazon Inspector access to AWS Services needed to perform security assessments.

# Required Parameters
- `roleArn`: The ARN of the IAM role that grants Amazon Inspector access to AWS Services needed to perform security assessments.

"""
register_cross_account_access_role(roleArn; aws_config::AWSConfig=global_aws_config()) = inspector("RegisterCrossAccountAccessRole", Dict{String, Any}("roleArn"=>roleArn); aws_config=aws_config)
register_cross_account_access_role(roleArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("RegisterCrossAccountAccessRole", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("roleArn"=>roleArn), args)); aws_config=aws_config)

"""
    RemoveAttributesFromFindings()

Removes entire attributes (key and value pairs) from the findings that are specified by the ARNs of the findings where an attribute with the specified key exists.

# Required Parameters
- `attributeKeys`: The array of attribute keys that you want to remove from specified findings.
- `findingArns`: The ARNs that specify the findings that you want to remove attributes from.

"""
remove_attributes_from_findings(attributeKeys, findingArns; aws_config::AWSConfig=global_aws_config()) = inspector("RemoveAttributesFromFindings", Dict{String, Any}("attributeKeys"=>attributeKeys, "findingArns"=>findingArns); aws_config=aws_config)
remove_attributes_from_findings(attributeKeys, findingArns, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("RemoveAttributesFromFindings", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("attributeKeys"=>attributeKeys, "findingArns"=>findingArns), args)); aws_config=aws_config)

"""
    SetTagsForResource()

Sets tags (key and value pairs) to the assessment template that is specified by the ARN of the assessment template.

# Required Parameters
- `resourceArn`: The ARN of the assessment template that you want to set tags to.

# Optional Parameters
- `tags`: A collection of key and value pairs that you want to set to the assessment template.
"""
set_tags_for_resource(resourceArn; aws_config::AWSConfig=global_aws_config()) = inspector("SetTagsForResource", Dict{String, Any}("resourceArn"=>resourceArn); aws_config=aws_config)
set_tags_for_resource(resourceArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("SetTagsForResource", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("resourceArn"=>resourceArn), args)); aws_config=aws_config)

"""
    StartAssessmentRun()

Starts the assessment run specified by the ARN of the assessment template. For this API to function properly, you must not exceed the limit of running up to 500 concurrent agents per AWS account.

# Required Parameters
- `assessmentTemplateArn`: The ARN of the assessment template of the assessment run that you want to start.

# Optional Parameters
- `assessmentRunName`: You can specify the name for the assessment run. The name must be unique for the assessment template whose ARN is used to start the assessment run.
"""
start_assessment_run(assessmentTemplateArn; aws_config::AWSConfig=global_aws_config()) = inspector("StartAssessmentRun", Dict{String, Any}("assessmentTemplateArn"=>assessmentTemplateArn); aws_config=aws_config)
start_assessment_run(assessmentTemplateArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("StartAssessmentRun", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentTemplateArn"=>assessmentTemplateArn), args)); aws_config=aws_config)

"""
    StopAssessmentRun()

Stops the assessment run that is specified by the ARN of the assessment run.

# Required Parameters
- `assessmentRunArn`: The ARN of the assessment run that you want to stop.

# Optional Parameters
- `stopAction`: An input option that can be set to either START_EVALUATION or SKIP_EVALUATION. START_EVALUATION (the default value), stops the AWS agent from collecting data and begins the results evaluation and the findings generation process. SKIP_EVALUATION cancels the assessment run immediately, after which no findings are generated.
"""
stop_assessment_run(assessmentRunArn; aws_config::AWSConfig=global_aws_config()) = inspector("StopAssessmentRun", Dict{String, Any}("assessmentRunArn"=>assessmentRunArn); aws_config=aws_config)
stop_assessment_run(assessmentRunArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("StopAssessmentRun", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentRunArn"=>assessmentRunArn), args)); aws_config=aws_config)

"""
    SubscribeToEvent()

Enables the process of sending Amazon Simple Notification Service (SNS) notifications about a specified event to a specified SNS topic.

# Required Parameters
- `event`: The event for which you want to receive SNS notifications.
- `resourceArn`: The ARN of the assessment template that is used during the event for which you want to receive SNS notifications.
- `topicArn`: The ARN of the SNS topic to which the SNS notifications are sent.

"""
subscribe_to_event(event, resourceArn, topicArn; aws_config::AWSConfig=global_aws_config()) = inspector("SubscribeToEvent", Dict{String, Any}("event"=>event, "resourceArn"=>resourceArn, "topicArn"=>topicArn); aws_config=aws_config)
subscribe_to_event(event, resourceArn, topicArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("SubscribeToEvent", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("event"=>event, "resourceArn"=>resourceArn, "topicArn"=>topicArn), args)); aws_config=aws_config)

"""
    UnsubscribeFromEvent()

Disables the process of sending Amazon Simple Notification Service (SNS) notifications about a specified event to a specified SNS topic.

# Required Parameters
- `event`: The event for which you want to stop receiving SNS notifications.
- `resourceArn`: The ARN of the assessment template that is used during the event for which you want to stop receiving SNS notifications.
- `topicArn`: The ARN of the SNS topic to which SNS notifications are sent.

"""
unsubscribe_from_event(event, resourceArn, topicArn; aws_config::AWSConfig=global_aws_config()) = inspector("UnsubscribeFromEvent", Dict{String, Any}("event"=>event, "resourceArn"=>resourceArn, "topicArn"=>topicArn); aws_config=aws_config)
unsubscribe_from_event(event, resourceArn, topicArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("UnsubscribeFromEvent", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("event"=>event, "resourceArn"=>resourceArn, "topicArn"=>topicArn), args)); aws_config=aws_config)

"""
    UpdateAssessmentTarget()

Updates the assessment target that is specified by the ARN of the assessment target. If resourceGroupArn is not specified, all EC2 instances in the current AWS account and region are included in the assessment target.

# Required Parameters
- `assessmentTargetArn`: The ARN of the assessment target that you want to update.
- `assessmentTargetName`: The name of the assessment target that you want to update.

# Optional Parameters
- `resourceGroupArn`: The ARN of the resource group that is used to specify the new resource group to associate with the assessment target.
"""
update_assessment_target(assessmentTargetArn, assessmentTargetName; aws_config::AWSConfig=global_aws_config()) = inspector("UpdateAssessmentTarget", Dict{String, Any}("assessmentTargetArn"=>assessmentTargetArn, "assessmentTargetName"=>assessmentTargetName); aws_config=aws_config)
update_assessment_target(assessmentTargetArn, assessmentTargetName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = inspector("UpdateAssessmentTarget", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("assessmentTargetArn"=>assessmentTargetArn, "assessmentTargetName"=>assessmentTargetName), args)); aws_config=aws_config)


text:
import Base: getindex, show, convert, sum, prod, mean, var, std, maximum, minimum, merge

abstract AbstractTimeSeries

immutable TimeVector{T<:Float64,D<:TimeType} <: AbstractTimeSeries
    timestamp::PersistentVector{D}
    values::PersistentVector{T}
end

function timevector{T<:Float64, D<:TimeType}(tstamp::Vector{D}, vals::Vector{T})
    TimeVector(pvec(tstamp), pvec(vals))
end

function timevector{T<:Float64, D<:TimeType}(tstamp::Vector{D}, vals::Matrix{T})
    TimeVector(pvec(tstamp), pvec(vals))
end

function timevector{T<:Float64,N,D<:TimeType}(ta::TimeArray{T,N,D})
    TimeVector(pvec(ta.timestamp), pvec(ta.values))
end

function Base.show(io::IO, tv::TimeVector)

    nrow = size(tv.values, 1)

  # timestamp and values line
    if nrow > 7
        for i in 1:4
            print(io, tv.timestamp[i], " | ", tv.values[i])
            println(io, "")
        end

        println(io, '\u22EE')

        for i in nrow-3:nrow
            print(io, tv.timestamp[i], " | ", tv.values[i])
            println(io, "")
        end

    elseif nrow > 0

        for i in 1:nrow
            print(io, tv.timestamp[i], " | ", tv.values[i])
            println(io, "")
        end
    end
end


text:
@testset "Solve: acrobot" begin
    # horizon
    T = 101

    # acrobot
    nx = 4
    nu = 1
    nw = 0
    w_dim = [nw for t = 1:T]

    function acrobot(x, u, w)
        # dimensions
        n = 4
        m = 1
        d = 0

        # link 1
        mass1 = 1.0
        inertia1 = 0.33
        length1 = 1.0
        lengthcom1 = 0.5

        # link 2
        mass2 = 1.0
        inertia2 = 0.33
        length2 = 1.0
        lengthcom2 = 0.5

        gravity = 9.81
        friction1 = 0.1
        friction2 = 0.1

        # mass matrix
        function M(x, w)
            a = (inertia1 + inertia2 + mass2 * length1 * length1
                + 2.0 * mass2 * length1 * lengthcom2 * cos(x[2]))

            b = inertia2 + mass2 * length1 * lengthcom2 * cos(x[2])

            c = inertia2

        return [a b; b c]
        end

        # dynamics bias
        function τ(x, w)
            a = (-1.0 * mass1 * gravity * lengthcom1 * sin(x[1])
                - mass2 * gravity * (length1 * sin(x[1])
                + lengthcom2 * sin(x[1] + x[2])))

            b = -1.0 * mass2 * gravity * lengthcom2 * sin(x[1] + x[2])

            return [a; b]
        end

        function C(x, w)
            a = -2.0 * mass2 * length1 * lengthcom2 * sin(x[2]) * x[4]
            b = -1.0 * mass2 * length1 * lengthcom2 * sin(x[2]) * x[4]
            c = mass2 * length1 * lengthcom2 * sin(x[2]) * x[3]
            d = 0.0

            return [a b; c d]
        end

        # input Jacobian
        function B(x, w)
            [0.0; 1.0]
        end

        # dynamics
        q = view(x, 1:2)
        v = view(x, 3:4)

        qdd = M(q, w) \ (-1.0 * C(x, w) * v
                + τ(q, w) + B(q, w) * u[1] - [friction1; friction2] .* v)

        return [x[3]; x[4]; qdd[1]; qdd[2]]
    end

    function midpoint_implicit(y, x, u, w)
        h = 0.05 # timestep
        y - (x + h * acrobot(0.5 * (x + y), u, w))
    end

    dt = Dynamics(midpoint_implicit, nx, nx, nu, nw=nw)
    dyn = [dt for t = 1:T-1]
    model = DynamicsModel(dyn, w_dim=w_dim)

    # initial state
    x1 = [0.0; 0.0; 0.0; 0.0]

    # goal state
    xT = [0.0; π; 0.0; 0.0]

    # interpolation
    x_interpolation = linear_interpolation(x1, xT, T)

    # objective
    ot = (x, u, w) -> 0.1 * dot(x[3:4], x[3:4]) + 0.1 * dot(u, u)
    oT = (x, u, w) -> 0.1 * dot(x[3:4], x[3:4])
    ct = Cost(ot, nx, nu, nw, [t for t = 1:T-1])
    cT = Cost(oT, nx, 0, nw, [T])
    obj = [ct, cT]

    # constraints
    x_init = Bound(nx, nu, [1], xl=x1, xu=x1)
    x_goal = Bound(nx, 0, [T], xl=xT, xu=xT)
    # u_limits = Bound(nx, nu, [t for t = 1:T-1], ul=-5.0 * ones(nu), uu=5.0 * ones(nu))
    cons = ConstraintSet([x_init, x_goal,
    # u_limits
    ], [StageConstraint()])

    # problem
    trajopt = TrajectoryOptimizationProblem(obj, model, cons)
    s = Solver(trajopt)

    # initialize
    z0 = 0.001 * randn(s.p.num_var)
    for (t, idx) in enumerate(s.p.trajopt.model.idx.x)
        z0[idx] = x_interpolation[t]
    end
    initialize!(s, z0)

    # solve
    @time solve!(s)

    @test norm(trajopt.x[1] - x1) < 1.0e-3
    @test norm(trajopt.x[T] - xT) < 1.0e-3
end


text:
@testset "expand_poly" begin
    xi = 1:6
    xf = 1f0:6f0
    @test_throws MethodError expand_poly(xi, obsdim = 3)
    @test_throws MethodError expand_poly(xf, 5, ObsDim.Constant{3}())

    @testset "ObsDim.Last()" begin
        for x in [xi, xf]
            X = expand_poly(x, degree = 5)
            @test eltype(x) == eltype(X)
            @test @inferred(expand_poly(x)) == X
            @test @inferred(expand_poly(x, 5)) == X
            @test @inferred(expand_poly(x, 5, ObsDim.Last())) == X
            @test @inferred(expand_poly(x, 5, ObsDim.Constant{2}())) == X
            @test size(X) == (5, 6)
            for i in 1:6, k in 1:5
                @test X[k, i] === x[i]^k
            end
        end
    end

    @testset "ObsDim.First()" begin
        for x in [xi, xf]
            X = expand_poly(x, degree = 5, obsdim = 1)
            @test eltype(x) == eltype(X)
            @test expand_poly(x, obsdim = 1) == X
            @test @inferred(expand_poly(x, 5, ObsDim.First())) == X
            @test size(X) == (6, 5)
            for k in 1:5, i in 1:6
                @test X[i, k] === x[i]^k
            end
        end
    end

    @testset "Missing" begin
        xm = [1., 2., missing, 4., 5., 6.]
        @test_throws MethodError expand_poly(xm, obsdim = 3)
        @test_throws MethodError expand_poly(xm, 5, ObsDim.Constant{3}())
        X = @inferred(expand_poly(xm, 5))
        @test eltype(xm) == eltype(X)
        @test size(X) == (5, 6)
        for i in 1:6, k in 1:5
            if i != 3
                @test X[k, i] === xm[i]^k
            else
                @test ismissing(X[k, i])
            end
        end
    end
end


text:
# This file is a part of AstroLib.jl. License is MIT "Expat".
# Copyright (C) 2016 Mosè Giordano.

function _flux2mag{T<:AbstractFloat}(flux::T, zero_point::T, ABwave::T)
    if isnan(ABwave)
        return -2.5*log10(flux) - zero_point
    else
        return -2.5*log10(flux) - 5.0*log10(float(ABwave)) - 2.406
    end
end

"""
    flux2mag(flux[, zero_point, ABwave=number]) -> magnitude

### Purpose ###

Convert from flux expressed in erg/(s cm² Å) to magnitudes.

### Explanation ###

This is the reverse of `mag2flux`.

### Arguments ###

* `flux`: the flux to be converted in magnitude, expressed in
  erg/(s cm² Å).  It can be either a scalar or an array.
* `zero_point`: scalar giving the zero point level of the magnitude.  If not
 supplied then defaults to 21.1 (Code et al 1976).  Ignored if the `ABwave`
 keyword is supplied
* `ABwave` (optional numeric keyword): wavelength scalar or vector in Angstroms.
 If supplied, then returns Oke AB magnitudes (Oke & Gunn 1983, ApJ, 266, 713;
 http://adsabs.harvard.edu/abs/1983ApJ...266..713O).

### Output ###

The magnitude.  It is of the same type, scalar or array, as `flux`.

If the `ABwave` keyword is set then magnitude is given by the expression

\$\$\\text{ABmag} = -2.5\\log_{10}(f) - 5\\log_{10}(\\text{ABwave}) - 2.406\$\$

Otherwise, magnitude is given by the expression

\$\$\\text{mag} = -2.5\\log_{10}(\\text{flux}) - \\text{zero point}\$\$

### Example ###

``` julia
flux2mag(5.2e-15)
# => 14.609991640913002
flux2mag(5.2e-15, 15)
# => 20.709991640913003
flux2mag(5.2e-15, ABwave=15)
# => 27.423535345634598
```

### Notes ###

Code of this function is based on IDL Astronomy User's Library.
"""
flux2mag(flux::Real, zero_point::Real=21.1; ABwave::Real=NaN) =
    _flux2mag(promote(float(flux), float(zero_point), float(ABwave))...)

function flux2mag{N<:Real}(flux::AbstractArray{N}, zero_point::Real=21.1;
                           ABwave::Real=NaN)
    mag = similar(flux, typeof(float(one(N))))
    for i in eachindex(flux)
        mag[i] = flux2mag(flux[i], zero_point, ABwave=ABwave)
    end
    return mag
end


text:
"""
Functions for estimating covariance matrices to use when fitting CCFs

Author: Eric Ford
Created: October 2020
"""

default_kmax_calc_ccf_sample_covar_reduced_rank = 6  # TODO:  pick more thoughtfully than just using values from Scapels paper

""" `calc_ccf_sample_covar_reduced_rank( ccfs, ccf_vars ; kmax)`
Calculate a reduced rank approximation to the sample covariance matrix for the CCF
"""
function calc_ccf_sample_covar_reduced_rank( ccfs::A2, ccf_vars::A3 ; kmax::Integer = default_kmax_calc_ccf_sample_covar_reduced_rank, assume_normalized::Bool = false, verbose::Bool = false ) where {T2<:Real, A2<:AbstractArray{T2,2}, T3<:Real, A3<:AbstractArray{T3,2}  }
    num_obs = size(ccfs,2)
    (ccfs_norm, ccf_vars_norm) = assume_normalized ? (ccfs, ccf_vars) : calc_normalized_ccfs(ccfs, ccf_vars)
    ccf_template = calc_ccf_template(ccfs_norm, ccf_vars_norm, assume_normalized=true )
    return calc_ccf_sample_covar_reduced_rank_helper(ccfs_norm, template=ccf_template, kmax=kmax)
end

#=
function calc_ccf_sample_covar_reduced_rank( ccfs::A2; kmax::Integer = default_kmax_calc_ccf_sample_covar_reduced_rank, assume_normalized::Bool = false ) where {T2<:Real, A2<:AbstractArray{T2,2} }
    ccfs_norm = assume_normalized ? ccfs : calc_normalized_ccfs(ccfs)
    ccf_template = calc_ccf_template(ccfs_norm, assume_normalized=true )
    #ccf_sample_covar = (ccfs_norm .- template) * (ccfs_norm .- template)'
    return calc_ccf_sample_covar_reduced_rank_helper(ccfs_norm, template=ccf_template, kmax=kmax)
end
=#

function calc_ccf_sample_covar_reduced_rank_helper( ccfs_norm::A2; template::A1, kmax::Integer = default_kmax_calc_ccf_sample_covar_reduced_rank, verbose::Bool = false ) where {T1<:Real, A1<:AbstractArray{T1,1}, T2<:Real, A2<:AbstractArray{T2,2} }
    num_obs = size(ccfs_norm,2)
    @assert 2 <= num_obs <= 10000  # Arbitrary upper limit
    sample_covar_svd = svd((ccfs_norm .- template)')
    R_kmax = sample_covar_svd.U[1:kmax,:]'*(diagm(sample_covar_svd.S[1:kmax])*sample_covar_svd.Vt[1:kmax,:])
    #ccf_sample_covar = (max.(R_kmax'*R_kmax,0)) / num_obs
    ccf_sample_covar = (R_kmax'*R_kmax)  / (num_obs-1)
    return (covar=ccf_sample_covar, R_kmax=R_kmax)
end

""" `est_covar_for_obs(covar_reduced_rank, diag_model, diag_norm)`
Returns estimate of the CCF covariance based using
`covar_reduced_rank + diag_norm * diag_model`
`diag_model` is typically not diagonal, but rather terms near the diagonal
"""
function est_covar_for_obs(covar_reduced_rank::A2, diag_model::A3, diag_norm::Real) where {T1<:Real, A1<:AbstractArray{T1,1}, T2<:Real, A2<:AbstractArray{T2,2}, T3<:Real, A3<:AbstractArray{T3,2}  }
    @assert size(covar_reduced_rank) == size(diag_model)
    return covar_reduced_rank + diag_norm * diag_model
end

function est_covar_for_obs(covar_reduced_rank::A2, shape_model::A3, row_norms::A1, obs_idx::Integer) where {T1<:Real, A1<:AbstractArray{T1,1}, T2<:Real, A2<:AbstractArray{T2,2}, T3<:Real, A3<:AbstractArray{T3,2}  }
    @assert 1 <= obs_idx <= length(row_norms)
    est_covar_for_obs(covar_reduced_rank, shape_model, row_norms[obs_idx])
end

@. triangle_helper(x, p) = p[1]*max(1-abs(x)/p[2], 0)

function triangular_shape_near_diagonal(n::Integer, width::Real; norm::Real = 1)
  shape_model = collect( triangle_helper(i-j,[norm,width]) for i in 1:n, j in 1:n )
end

#=
using LsqFit

# WARNING:  This function still needs major work
function calc_ccf_sample_covar_and_near_diag_model( ccfs::A2, ccf_vars::A3 ; kmax::Integer = default_kmax_calc_ccf_sample_covar_reduced_rank,
                                            num_diags_to_calc::Integer = floor(Int,size(ccfs,1)//2), verbose::Bool = false ) where {T2<:Real, A2<:AbstractArray{T2,2}, T3<:Real, A3<:AbstractArray{T3,2}  }
    num_vels, num_obs = size(ccfs)
    @assert size(ccfs) == size(ccf_vars)
    @assert 5 <= num_diags_to_calc <= num_vels
    @assert kmax <= num_obs
    (ccfs_norm, ccf_vars_norm) = #= assume_normalized ? (ccfs, ccf_vars) : =# calc_normalized_ccfs(ccfs, ccf_vars)
    ccf_template = calc_ccf_template(ccfs_norm, ccf_vars_norm, assume_normalized=true )
    obs_weights = calc_ccf_weights_formal(ccfs, ccf_vars, ccf_template)
    ccf_sample_covar = Array{eltype(ccfs),2}(undef, num_vels, num_vels)
    calc_ccf_sample_covar_helper!(ccf_sample_covar, ccfs_norm, obs_weights, template=ccf_template, assume_normalized=true )

    (ccf_sample_covar_reduced_rank, R_kmax) = calc_ccf_sample_covar_reduced_rank_helper( ccfs_norm, template = ccf_template, kmax=kmax) #, assume_normalized=true )
    residR = ccf_sample_covar - ccf_sample_covar_reduced_rank
    return residR
    if verbose
        flush(stdout)
        println("# extrema(ccf_sample_covar) = ",extrema(ccf_sample_covar))
        println("# extrema(ccf_sample_covar_reduced_rank) = ",extrema(ccf_sample_covar_reduced_rank))
        println("# extrema(residR) = ",extrema(residR))
    end
    #=
    mean_zero_lag = compute_mean_off_diag(residR,0)
    mean_offset_diag = map(i->compute_mean_off_diag(residR,i)./mean_zero_lag, -num_diags_to_calc:num_diags_to_calc)
    =#
    # TODO: fit triangle away from CCF peak
    residR_away_from_peak_1 = view(residR,1:ceil(Int,num_vels//4),1:ceil(Int,num_vels//4))
    residR_away_from_peak_2 = view(residR,floor(Int,num_vels*3//4):num_vels,floor(Int,num_vels*3//4):num_vels)
    mean_zero_lag = (compute_mean_off_diag(residR_away_from_peak_1,0)+compute_mean_off_diag(residR_away_from_peak_2,0))/2
    println("mean_zero_lag = ",mean_zero_lag)
    num_diags_to_calc_tmp_1 = min(num_diags_to_calc,size(residR_away_from_peak_1,1)-1)
    num_diags_to_calc_tmp_2 = min(num_diags_to_calc,size(residR_away_from_peak_2,1)-1)
    num_diags_to_calc_tmp = min(num_diags_to_calc_tmp_1,num_diags_to_calc_tmp_2)
    println("num_diags_to_calc_tmp = ",num_diags_to_calc_tmp)
    mean_offset_diag   = map(i->compute_mean_off_diag(residR_away_from_peak_1,i)./mean_zero_lag, -num_diags_to_calc_tmp:num_diags_to_calc_tmp)
    println("mean_offset_diag = ",extrema(mean_offset_diag) )
    mean_offset_diag .+= map(i->compute_mean_off_diag(residR_away_from_peak_2,i)./mean_zero_lag, -num_diags_to_calc_tmp:num_diags_to_calc_tmp)
    mean_offset_diag ./= 2
    println("mean_offset_diag = ",extrema(mean_offset_diag) )
    return mean_offset_diag
    # Find idx around CCF peak
    #mid_offset = findmin(ccf_template)[2]
    half_width = est_full_width(1:num_vels,ccf_template)
    width_guess = 2*half_width
    result = curve_fit(triangle_helper, -num_diags_to_calc_tmp:num_diags_to_calc_tmp, mean_offset_diag, [1.0, width_guess] )
    #=
    max_offset = min(num_vels,mid_offset+num_diags_to_calc)
    min_offset = max(1,mid_offset-num_diags_to_calc)
    epsilon = 0.1 * mean_zero_lag
    idx_hi = findfirst(x->x<=epsilon,view(mean_offset_diag,mid_offset:max_offset))
    idx_lo = findfirst(x->x<=epsilon,view(mean_offset_diag,mid_offset:-1:min_offset))
    if idx_hi == nothing || idx_lo == nothing
        #flush(stdout)
        #println("mean_offset_diag = ",view(mean_offset_diag,mid_offset:max_offset))
        idx_hi = min(num_vels,mid_offset + 2*half_width)
        idx_lo = max(1,mid_offset - 2*half_width)
    else
        idx_hi = min(num_vels, idx_hi+ (mid_offset-1) )
        idx_lo = max(1, -idx_lo + (mid_offset+1) )
    end
    width_guess = idx_hi-idx_lo
    if verbose   println("# idx_lo = ", idx_lo, " idx_hi = ", idx_hi, " width_guess = ", width_guess )   end
    result = curve_fit(triangle_helper, view(-num_diags_to_calc:num_diags_to_calc,idx_lo:idx_hi), view(mean_offset_diag,idx_lo:idx_hi), [1.0, width_guess] )
    =#
    A = coef(result)[1]
    δv = coef(result)[2]
    if true || verbose   println("# A = ", A, " δv = ", δv, "  mean_lag_zero = ", mean_zero_lag, " converged = ", result.converged )   end
    #shape_model = ( triangle_helper(i-j,[A,δv]) for i in 1:num_vels, j in 1:num_vels )
    shape_model = triangular_shape_near_diagonal(num_vels, δv; norm=A)
    row_norms = vec(var( (ccfs_norm .- ccf_template)' .-  R_kmax, dims=2))
    #return (covar_reduced_rank=ccf_sample_covar_reduced_rank / num_obs, shape_model=shape_model, row_norms=row_norms)
    return (covar_reduced_rank=ccf_sample_covar_reduced_rank , shape_model=shape_model, row_norms=row_norms)
end
=#

""" ` compute_mean_off_diag(matrix, offset)`
Compute mean value of entries with given offset from the diagonal.
Note: offset may be positive or negative
"""
function compute_mean_off_diag(m::AbstractArray{T,2}, offset::Integer) where {T<:Real}
  n = size(m,1)
  @assert size(m,1) == size(m,2)
  @assert -n <= offset <= n
  sum = 0
  count = 0
  for i in 1:n
      if 1<= i+offset <= n
        sum += m[i,i+offset]
        count += 1
      end
  end
  return sum/count
end

max_stars_repo_name: RvSpectML/EchelleCCFs

max_issues_repo_name: RvSpectML/EchelleCCFs

max_forks_repo_name: RvSpectML/EchelleCCFs


text:
using LinearAlgebra
"""
    function read_gt_n_frq(gt, frq)
---
Read genotypes and their frequencies from file `gt` and `frq`.
Note gt can be prepared like below:
```
plink --species --bfile source --recode A --out target
cat target.raw | pathto/raw2gt target.frq > target.gt
```
See also the function `prepare_gt_from_plink_files`.
"""
function read_gt_n_frq(gt, frq)
    subtitle("Read genotypes and frequencies")
    item("Frequency related")
    # Frequency related
    p = Float64[]
    for x in eachline(frq)
        push!(p, parse(Float64, x))
    end
    twop = p.*2.
    done()

    item("Genotypes")
    nlc = length(readline(gt))
    fsz = stat(gt).size
    lsz = nlc + 1               # assuming Unix text format
    nid = Int(fsz/lsz)
    if(nid*lsz ≠ fsz)
        warning("Not a square file")
        return
    end
    message("NID: $nid;\tN_loci: $nlc")
    z = Array{Float64, 2}(undef, nlc, nid) # one column per ID
    fgt = open(gt, "r")
    for j in 1:nid
        t = read(fgt, lsz)
        for i in 1:nlc
            z[i, j] = Float64(t[i] - 0x30) # 0x30 == '0'
        end
    end
    close(fgt)
    done()
    return p, twop, z
end

"""
    vanRaden(Z, twop, d = 0.)
---
This function calculate **`G`** with van Raden 2008 on genotype **`Z`**.
method I.  Note **`Z`** here is ID column majored.

`G = Z'Z/2Σp_i(1-p_i)`

where **`Z`** contains the marker genotypes of value 0, 1 or 2 for all animals
at all loci.  It is then corrected by the passed `twop`,
the allele frequency per locus, and `p_i` is the frequency of the allele at locus
*i* coded with `1`.

One may pass `copy(Z)` to this function to avoid GT matrix modification.

The diaganols will be added `d`, which is by default `0`.
"""
function vanRaden(Z, twop, d = 0.)
    subtitle("Calculate G with vanRaden method I")
    Z .-= twop
    s2pq = (1 .- .5 .* twop)'twop
    r2pq = 1. / s2pq
    G = Z'Z .* r2pq + I(size(Z)[2]) .* d
end

"""
    vanRaden2(W::Array{Float64, 2})
---
Calculate **`G`** with van Raden method II.
"""
function vanRadenII(W::Array{Float64, 2})
    subtitle("Calculate G with van Raden method II")
    twop = mean(W, dims=2)
    topq = sqrt.(twop .* (1 .- .5 .* twop))
    W .-= twop
    W ./= topq
    G  = W'W ./ length(twop)
end

"""
    yangG(W::Array{Float64, 2})
---
Calculate **`G`** with Yang Jian's method.
"""
function yangG(W::Array{Float64, 2})
    subtitle("Calculate G with Yang's method")

    message("Will address this later")
    # twop = mean(W, dims=2)
    # topq = sqrt.(twop .* (1 .- .5 .* twop))
    # nid = size(gt)[2]
    # for i in 1:nid
    #
    #
    # # Calculate the diagonals first
    # for i in 1:lengt
    # W .-= twop
    # W ./= topq
    # # Above is just like van Raden method II
    # for i in 1:length(twop)
end

"""
    D_matrix(M::Array{Float64, 2})
---
Calculate **`D`** (dominance relationship) matrix with genotypes given.
"""
function D_matrix(M::Array{Float64, 2})
    subtitle("Dominance relationship matrix")
    p = mean(M, dims=2).* .5
    q = 1 .- p
    op = [vec(-2 .* p .* p) vec(2 .*p .* q)  vec(-2 .*q .* q)]
    for j in 1:size(M)[2]
        for i in 1:size(M)[1]
            k = Int(M[i, j]) + 1
            M[i, j] = op[i, k]
        end
    end
    s2pq = sum((p .* q .* 2) .^2)
    D = M'M ./s2pq
end

"""
    function plink_2_vr_I(file::AbstractString)
---
Given the file stem name `file`, this funciton calculate `G` with vanRaden method I.
Note, data are stored in `file.ped`, `file.bim`, `file.fam`.
"""
function plink_2_vr_I(file::AbstractString, species::AbstractString="cow")
    subtitle("Calculate G from plink data with vanRaden method I")
    message("   data: $file.{bed,bim,fam}\nSpecies: $species")
    if Sys.which("plink") == Nothing
        warning("Command plink can't be find in default paths")
        return
    end
    isfile(joinpath(abgBin, "raw2gt")) || make()
    tmp = joinpath(workdir, "tmp")
    isdir(tmp) || mkdir(tmp)
    plink_012(file, joinpath(tmp, "plink"), species)
    _ = run(pipeline(joinpath(tmp, "plink.raw"), `$abgBin/raw2gt $tmp/plk.frq`, "$tmp/plk.gt"))
    _, twop, z = read_gt_n_frq(joinpath(tmp, "plk.gt"), joinpath(tmp, "plk.frq"))
    G = vanRaden(z, vec(twop))
    done()
    return G
end

"""
Note: function names start with a `_` is just for testing.
"""
function _test_grm()
    nlc = 1000
    nid = 10
    M = rand(0:2, nlc, nid)
    p = mean(M, dims=2) .* .5
    twop = 2p
    s2pq = sum((1 .- p) .* twop)
    r2pq = 1. / s2pq
    Z = M .- twop
    if Sys.which("calc_grm") ≠ Nothing
        inp = ["$nlc", "genotypes.txt", "genotypes", "1", "vanraden",
               "giv 0.00", "G ASReml", "print_giv=asc", "print_geno=no genotypes.dat",
               "1", ""]
        write("tmp/calc_grm.inp", join(inp, '\n'))
        gt = open("tmp/genotypes.txt", "w")
        for i in 1:nid
            print(gt, i, ' ', join(M[:, i]), '\n')
        end
        close(gt)
    end
    G = Z'Z.*r2pq
    return p, G
end

"""
    inv_3c_G(file, out)
---
Invert a G-matrix stored in file `file`, and put the results to `out`.
"""
function inv_3c_G(file, out)
    nid, G = begin
        tmp = Float64[]
        for line in eachline(file)
            t = parse(Float64, split(line)[3])
            push!(tmp, t)
        end
        l = length(tmp)
        nid = Int(floor((sqrt(8l+1)-1)/2))
        g = zeros(nid, nid)
        k = 1
        for i in 1:nid
            for j in 1:i
                g[i, j] = g[j, i] = tmp[k]
                k += 1
            end
        end
        nid, g
    end
    giv = inv(G)
    open(out, "w") do io
        for i in 1:nid
            for j in 1:i
                println(io, "$i $j ", giv[i,j])
            end
        end
    end
end


text:
using Dates

println("Building package MyPkg")
open("time.txt", "w") do io
    t = now()
    println(io, "$t")
end

max_stars_repo_name: glennmoy/MyPkg

max_issues_repo_name: glennmoy/MyPkg

max_forks_repo_name: glennmoy/MyPkg


text:
# sum_n
@tensordiff (Z[i,j] = Espresso.sum_1(X[:,j])) (dZ[i,j]/dX[m,n] = 1.0 * (j == n))
@tensordiff (Z[i,j] = Espresso.sum_2(X[i,:])) (dZ[i,j]/dX[m,n] = 1.0 * (i == m))

# sum_n + sum
@tensordiff (Z = Espresso.sum_1(X[:,j])) (dZ[i,j]/dX[m,n] = 1.0)
@tensordiff (Z = Espresso.sum_2(X[i,:])) (dZ[i,j]/dX[m,n] = 1.0)

# matrix-by-matrix product
@tensordiff (Z[i,j] = X[i,k] * Y[k,j]) (dZ[i,j]/dX[m,n] = Y[n,j] * (i == m))
@tensordiff (Z[i,j] = X[i,k] * Y[k,j]) (dZ[i,j]/dY[m,n] = X[i,m] * (n == j))

# matrix-by-vector product
@tensordiff (Z[i] = X[i,k] * Y[k]) (dZ[i]/dX[m,n] = Y[n] * (i == m))
@tensordiff (Z[i] = X[i,k] * Y[k]) (dZ[i]/dY[m] = X[i,m])

# inner product of 2 vectors
@tensordiff (Z = X[i] * Y[i]) (dZ/dX[i] = Y[i])
@tensordiff (Z = X[i] * Y[i]) (dZ/dY[i] = X[i])

# outer product of 2 vectors
@tensordiff (Z[i,j] = X[i] * Y[j]) (dZ[i,j]/dX[m] = Y[j] * (i == m))
@tensordiff (Z[i,j] = X[i] * Y[j]) (dZ[i,j]/dY[m] = X[i] * (j == m))

# inner product of 2 matrices
@tensordiff (Z = X[i,j] * Y[i,j]) (dZ/dX[i,j] = Y[i,j])
@tensordiff (Z = X[i,j] * Y[i,j]) (dZ/dY[i,j] = X[i,j])

# index permutation (broken)
# @tensordiff (Z[i,j] = X[j,i]) (dZ[i,j]/dX[m,n] = 1 * (i == n) * (j == m))

# length
@tensordiff (Z = length(X[:])) (dZ/dX[i] = 0.0)

# convolution
@tensordiff (Z[i,j] = X[i+m-1, j+n-1] * W[m,n]) (dZ[i,j] / dW[m,n] = X[i+m-1, j+n-1])
@tensordiff (Z[i,j] = X[i+m-1, j+n-1] * W[m,n]) (dZ[i,j] / dX[p,q] = W[p-i+1, q-j+1])

@tensordiff (Z = X[i+m-1, j+n-1] * W[m,n]) (dZ / dW[m,n] = X[i+m-1, j+n-1])
@tensordiff (Z = X[i+m-1, j+n-1] * W[m,n]) (dZ / dX[p,q] = W[p-i+1, q-j+1])


text:
function construct( e::ProjectionMatrix,
                   𝐊::AbstractArray,
                   𝐑::AbstractArray,
                    𝐭::AbstractArray )

    if size(𝐊) != (3,3) || size(𝐑) != (3,3)
        throw(ArgumentError("Expect 3 x 3 calibration and rotation matrices."))
    end
    if length(𝐭) != 3
        throw(ArgumentError("Expect length-3 translation vectors."))
    end
    # TODO: Reconcile this change in convention with the rest of the code.
    𝐏 = 𝐊*[𝐑' -𝐑'*𝐭]
    SMatrix{3,4,Float64,3*4}(𝐏)
end

function construct(e::ProjectionMatrix, 𝐅::AbstractArray)
    𝐞 = epipole(𝐅')
    𝐏₁ = Matrix{Float64}(I,3,4)
    𝐏₂ = [vec2antisym(𝐞) * 𝐅  𝐞]

    SMatrix{3,4,Float64,3*4}(𝐏₁), SMatrix{3,4,Float64,3*4}(𝐏₂)

end

function construct(e::ProjectionMatrix, 𝐄::AbstractArray, 𝒟::Tuple{AbstractArray, Vararg{AbstractArray}})
    𝐖 = SMatrix{3,3,Float64,3*3}([0 -1 0; 1 0 0; 0 0 1])
    𝐙 = SMatrix{3,3,Float64,3*3}([0 1 0; -1 0 0; 0 0 0])
    𝐔,𝐒,𝐕 = svd(𝐄)
    𝐭 = 𝐔[:,3]
    𝐏₁ = SMatrix{3,4,Float64,3*4}(1.0I)
    𝐏₂₁ = SMatrix{3,4,Float64,3*4}([𝐔*𝐖*𝐕'  𝐭])
    𝐏₂₂ = SMatrix{3,4,Float64,3*4}([𝐔*𝐖'*𝐕' 𝐭])
    𝐏₂₃ = SMatrix{3,4,Float64,3*4}([𝐔*𝐖*𝐕' -𝐭])
    𝐏₂₄ = SMatrix{3,4,Float64,3*4}([𝐔*𝐖'*𝐕' -𝐭])

    𝒳₁ = triangulate(DirectLinearTransform(), 𝐏₁, 𝐏₂₁, 𝒟)
    𝒳₂ = triangulate(DirectLinearTransform(), 𝐏₁, 𝐏₂₂, 𝒟)
    𝒳₃ = triangulate(DirectLinearTransform(), 𝐏₁, 𝐏₂₃, 𝒟)
    𝒳₄ = triangulate(DirectLinearTransform(), 𝐏₁, 𝐏₂₄, 𝒟)

    # Determine which projection matrix in the second view triangulated
    # the majority of points in front of the cameras.
    ℳ₁ = map(𝒳₁) do 𝐗
        𝐦 = 𝐏₂₁ * 𝐗
        𝐦[3] > 0
    end

    ℳ₂ = map(𝒳₂) do 𝐗
        𝐦 = 𝐏₂₂ * 𝐗
        𝐦[3] > 0
    end

    ℳ₃ = map(𝒳₃) do 𝐗
        𝐦 = 𝐏₂₃ * 𝐗
        𝐦[3] > 0
    end

    ℳ₄ = map(𝒳₄) do 𝐗
        𝐦 = 𝐏₂₄ * 𝐗
        𝐦[3] > 0
    end

    total, index = findmax((sum(ℳ₁), sum(ℳ₂), sum(ℳ₃), sum(ℳ₄)))

    if index == 1
        return 𝐏₁,  𝐏₂₁
    elseif index == 2
        return 𝐏₁,  𝐏₂₂
    elseif index == 3
        return 𝐏₁,  𝐏₂₃
    else
        return 𝐏₁,  𝐏₂₄
    end
end

function construct(e::ProjectionMatrices, ℋ::Tuple{AbstractArray, Vararg{AbstractArray}})
    construct(LatentVariables(HomographyMatrices()), ℋ)
end

function construct(lv::LatentVariables, ℋ::Tuple{AbstractArray, Vararg{AbstractArray}})
        N = length(ℋ)
        if N < 2
            throw(ArgumentError("Please supply at least two homography matrices."))
        end
        𝐗₁ = ℋ[1]
        𝛍 = zeros(N)
        𝐉 = Array{Float64}(undef,(3,(N-1)*6))
        i₁ = range(1, step = 6, length = N - 1)
        i₂ = range(6, step = 6, length = N - 1)
        for n = 2:N
            𝐗ₙ = ℋ[n]
            e₁, e₂ = find_nearest_eigenvalues(eigvals(Array(𝐗₁), Array(𝐗ₙ)))
            𝐘 = hcat(e₁ * 𝐗ₙ - 𝐗₁, e₂ * 𝐗ₙ - 𝐗₁)
            μ = (e₁ + e₂) / 2
            𝛍[n] = real(μ)
            𝐉[:,i₁[n-1]:i₂[n-1]] .= 𝐘
        end
        𝛈 = initialisation_procedure(𝐉, 𝛍, ℋ)
        𝐚  = @view 𝛈[1:9]
        𝐀 = reshape(𝐚, (3,3))
        𝐛 = @view 𝛈[10:12]
        𝐏₁ = SMatrix{3,4}(1.0I)
        𝐏₂ = SMatrix{3,4}(hcat(𝐀, 𝐛))
        𝐏₁, 𝐏₂
end

function initialisation_procedure(𝐉::AbstractArray, 𝛍::AbstractArray, ℋ::Tuple{AbstractArray, Vararg{AbstractArray}})
    N = length(ℋ)
    if N < 2
        throw(ArgumentError("Please supply at least two homography matrices."))
    end
    F = svd(𝐉)
    𝛈 = zeros(9 + 3 + (N*3) + N)
    𝐛 = real(F.U[:,1])
    𝐗₁ = ℋ[1]
    𝐀 = 𝐗₁
    𝐯₁ = SVector(0,0,0)
    wₙ = 1
    # pack 𝛈 = [𝐚,𝐛, 𝐯₁,...,𝐯ₙ, w₁, ..., wₙ]
    𝛈[1:9] .= vec(𝐀)
    𝛈[10:12] .= 𝐛
    for (n,i) in enumerate(range(13, step = 3, length = N))
        if n == 1
            𝛈[i:i+2] .= 𝐯₁
        else
            𝐗ₙ = ℋ[n]
            𝛈[i:i+2] .= 𝐯₁ +  (𝛍[n] * 𝐗ₙ - 𝐗₁)' * 𝐛 / (norm(𝐛)^2)
        end
    end
    𝛈[end-(N-1):end] .= wₙ
    𝛈
end

function find_nearest_eigenvalues(e::AbstractArray)
    dist = SVector(abs(e[1]-e[2]), abs(e[1]-e[3]), abs(e[2]-e[3]))
    minval, index = findmin(dist)
    if index == 3
        i₁ = 2
        i₂ = 3
    elseif index == 2
        i₁ = 1
        i₂ = 3
    else
        i₁ = 1
        i₂ = 2
    end
    e[i₁], e[i₂]
end

function unpack(e::LatentVariables, 𝛈::AbstractArray)
    N = div(length(𝛈) - 12,  4)
    𝐚  = @view 𝛈[1:9]
    𝐀 = reshape(𝐚, (3,3))
    𝐛 = @view 𝛈[10:12]
    𝐰 = @view 𝛈[end-(N-1):end]
    r = range(13, step = 3, length = N+1)
    @show first(r), last(r), N
    𝐯 = reshape(view(𝛈,first(r):last(r)-1), (3,N))
    𝒫 = Array{Array{Float64,2},1}(undef,(N,))
    for n = 1:N
        𝒫[n] = 𝐰[n]*𝐀 + 𝐛*𝐯[:,n]'
    end
    𝒫
end


text:
module TestDAGcntr

using Compat
using Compat.Test
using IntervalArithmetic
using EAGODomainReduction

single_expr = :(x[1]+x[2]^2-exp(x[1]))
tape_out = Generate_Tape(single_expr,2,-2,4)
dag_out = getDAG(single_expr,[1,2])
@test dag_out[1] == Int64[1; 2; 3; 4; 5; 6; 7]
@test dag_out[3][4] == Int64[4; 5]

#=
generates the tape list for the constraints -1 <= (x[1]+x[2]^2-exp(x[1]) <= 2
and 2 <= :(x[1]*x[2]-x[5]) <= 4 and runs the contractor 6 times in place on the
variable box X = [1,20]^5
=#
mult_expr = [:(x[1]+x[2]^2)
             :(x[1]+x[5])
            ]
X = [Interval(-10.0,20.0) for i=1:5]
ftapelist_out = Generate_Fixed_TapeList(mult_expr,4,[-8.0,0.5],[2.0,4.5],[[5.0]])
DAGContractor!(X,ftapelist_out,6)
@test -10-1E-4 <= X[1].lo <= -10+1E-4
@test 0-1E-4 <= X[2].lo <= 0+1E-4
@test -10-1E-4 <= X[3].lo <= -10+1E-4
@test -10-1E-4 <= X[4].lo <= -10+1E-4
@test 5-1E-4 <= X[5].lo <= 5+1E-4
@test 20-1E-4 <= X[1].hi <= 20+1E-4
@test 20-1E-4 <= X[2].hi <= 20+1E-4
@test 20-1E-4 <= X[3].hi <= 20+1E-4
@test 20-1E-4 <= X[4].hi <= 20+1E-4
@test 5-1E-4 <= X[5].hi <= 5+1E-4

end


text:
module MyModel

using Mimi

include("region_parameters.jl")
include("gross_economy.jl")
include("emissions.jl")

export construct_MyModel

function construct_MyModel()

	m = Model()

	set_dimension!(m, :time, collect(2015:5:2110))
	set_dimension!(m, :regions, [:Region1, :Region2, :Region3])	 # Note that the regions of your model must be specified here

	add_comp!(m, grosseconomy)
	add_comp!(m, emissions)

	# set parameters for grosseconomy component
	update_param!(m, :grosseconomy, :l, l)
	update_param!(m, :grosseconomy, :tfp, tfp)
	update_param!(m, :grosseconomy, :s, s)
	update_param!(m, :grosseconomy, :depk,depk)
	update_param!(m, :grosseconomy, :k0, k0)
	update_param!(m, :grosseconomy, :share, 0.3)

	# set and connect parameters for emissions component
	update_param!(m, :emissions, :sigma, sigma)
	connect_param!(m, :emissions, :YGROSS, :grosseconomy, :YGROSS)

    return m

end

end #module