text:
import Combinatorics
using Random
using DataFrames
import CSV
using Printf
#import PyPlot

using JuMP
#using GLPK
using Gurobi

using PyPlot, PyCall
#@pyimport mpl_toolkits.axes_grid1 as axes_grid1
axes_grid1 = pyimport("mpl_toolkits.axes_grid1")

include("DataLog.jl")
include("Agents/ScenarioTree.jl")

include("Agents/Parameters.jl")
include("Agents/PowerFlow.jl")
include("Agents/EnergyProducer.jl")

include("Agents/System.jl")

#include("RepresentativeDays_ABM/RepresentativeDays.jl")
include("RepresentativeDays_ABM/RepresentativeData.jl")

#GUROBI_ENV = Gurobi.Env()
#setparams!(GUROBI_ENV, OutputFlag = 0,Method = 1)

Random.seed!(12)

#Initialize global parameters
investmentModelSelection = :GEP # :EMCAS, :EMLab, :GEP
investmentSequence = :sequential
simulationSettings = SimulationSettings(day2hour,year2day,segmentNumbers,downpaymentRatio,representativeData,investmentSequence,investmentModelSelection)
systemSettings = SystemSettings(GenCoNumbers,totalHorizon,milestoneYear,interestRate,simulationSettings)

function InitSystem(systemSettings::SystemSettings,genCoHorizon::Real; kwargs...)
    V = Dict(kwargs)
    if haskey(V,:gapCoverPercentage) && haskey(V,:divisionTypeShare)
        gapCoverPercentage = V[:gapCoverPercentage]
        divisionTypeShare = V[:divisionTypeShare]
    end
##########################################################################################################
    #Initialize technology pool
    technologyPool = Array{Technology,1}(undef,0)
    initialTechnologyHistory = TechnologyHistory(systemSettings)

    for i in 1:length(technologyType)
        thisDesignProperty = DesignProperty(availability[i], constructionTimeStamp[i],constructionTime[i],deconstructionTime[i],efficiency[i],emission_ton_perMWh[i],lifeTime[i],unitCapacity[i])
        thisEconomicProperty = EconomicProperty(unitConstructionCost[i], unitDeconstructionCost[i], unitVOMCost[i],unitFOMCost[i],systemSettings)

        if technologyType[i] in [:Base,:Mid,:Peak]
            thisTechnology = ConventionalPlants(technologyType[i],thisDesignProperty, thisEconomicProperty,systemSettings)
            thisTechnology.UpdateCost(emissionPrice,fuelPrice[i])
        end

        #if technologyType[i] in [:OnShoreWind,:OffShoreWind,:Solar]
        #    thisTechnology = RenewablePlants(technologyType[i],thisDesignProperty, thisEconomicProperty, capacityFactorImproveRate,[:offline,:subsidized],systemSettings)
        #end

        thisTechnology.MultipleUnits(1,systemSettings)
        println(thisTechnology.economicProperties.constructionCost)
        push!(technologyPool, thisTechnology)
    end

    ##########################################################################################################
    initial_ExistingCapacity_TimeStamp = [11 11 11 11;
                                          11 11 11 11;
                                          11 11 11 11]
    initial_Capacity = Array{Technology,1}(undef,0)

    for pre_TimeStamp in 1:size(initial_ExistingCapacity_TimeStamp)[2]
        for techCount in 1:length(technologyPool)
            thisInitialPlant = deepcopy(technologyPool[techCount])
            for techNum in 1:initial_ExistingCapacity_TimeStamp[techCount,pre_TimeStamp]
                thisInitialPlant.designProperties.constructionTimeStamp = (pre_TimeStamp-4) * systemSettings.milestoneYear
                push!(initial_Capacity,deepcopy(thisInitialPlant))
            end
        end
    end

    ##########################################################################################################
    #Initialize GenCos and ownerships

    systemCapacityMix = Array{Array{Technology,1},1}(undef,0)
    systemHistory = SystemHistory()
    allGenerators = Array{Technology,1}(undef,0)
    allOwnerShips = Array{GenCoPortfolioOwnership,1}(undef,0)
    allGenCos = Array{GenCo,1}(undef,0)
    for i in 1:systemSettings.GenCoNumbers
        thisName = string("GenCo", i)
        thisTechnologies = Array{Technology,1}(undef,0)
        thisTechnologyPortfolio = TechnologyPortfolio(Array{Technology,1}(undef,0))
        thisCompetitorExpansion = Array{CapacityExpansionEdge,1}(undef,0)
        thisCompetitorDivision=Array{CapacityDivisionEdge,1}(undef,0)

        if haskey(V,:gapCoverPercentage) && haskey(V,:divisionTypeShare)
            for m in 1:length(gapCoverProbability[i])
                push!(thisCompetitorExpansion, CapacityExpansionEdge(gapCoverProbability[i][m],gapCoverPercentage[i][m]))
            end
            for k in 1:length(divisionProbability[i])
                push!(thisCompetitorDivision, CapacityDivisionEdge(divisionProbability[i][k],divisionTypeShare[i][k]))
            end
        end

        thisGenCo = GenCo(thisName, genCoHorizon,thisTechnologyPortfolio,deepcopy(technologyPool);competitorExpansion = thisCompetitorExpansion,competitorDivision=thisCompetitorDivision)
        thisOwnerShip = GenCoPortfolioOwnership(thisGenCo, thisTechnologyPortfolio)
        for thisType in technologyType
            thisGenCo.history.investmentYearByType[thisType] = zeros(totalHorizon)
        end
        push!(allOwnerShips,thisOwnerShip)
        push!(allGenCos,thisGenCo)
    end

    #Randomly distribute initial capacities
    for n in 1:length(initial_Capacity)
        luckyGenCo = allGenCos[rand(1:GenCoNumbers)]
        push!(luckyGenCo.technologyPortfolio.technologies, initial_Capacity[n])
        push!(allGenerators, initial_Capacity[n])
    end

    #push!(systemHistory.systemCapacityMix, deepcopy(allGenerators))
    println("Generator numbers: ", length(allGenerators))

    println("OwnerShips: ", length(allOwnerShips))

    ##########################################################################################################
    #Initialize consumers
    #priceCap = 200.0 #€/MWh
    #averageLoad = 10000 #MWh
    systemLoad = Load(priceCap,0.0,representativeData[:Load])

    systemState = SystemState(1,allGenerators)
    ##########################################################################################################
    #Initialize market operators
    MO = MarketOperator("MarketOperator")

    ##########################################################################################################
    #Initialize powerflows
    allPowerFlows = Array{PowerFlow,1}(undef,0)
    for generator in allGenerators
        #if typeof(generator) != VirtualPlants
        thisPowerFlow = PowerFlow(generator, MO, 0,0)
        push!(allPowerFlows, thisPowerFlow)
        #end
    end

    return MO,allGenCos,systemLoad,allPowerFlows,technologyPool,systemState,systemHistory
end


text:
# =================================================================================================
# =                                         Hyland83a.jl                                          =
# =================================================================================================

#=
Testing the virial coefficients. Table 1 from reference [2].
=#
@testset "Hyland83a" begin
@testset "Virial Coeffients" begin

@testset "Baa" begin
@test -55.94 ≈ MoistAir.Baa(173.15)*1e6 atol=0.01
@test -13.15 ≈ MoistAir.Baa(273.15)*1e6 atol=0.01
@test 3.72 ≈ MoistAir.Baa(373.15)*1e6 atol=0.01
@test 12.31 ≈ MoistAir.Baa(473.15)*1e6 atol=0.01
end

@testset "dBaa/dT" begin
@test 0.7240 ≈ MoistAir.dBaa(173.15)*1e6 atol=0.0001
@test 0.2460 ≈ MoistAir.dBaa(273.15)*1e6 atol=0.0001
@test 0.1146 ≈ MoistAir.dBaa(373.15)*1e6 atol=0.0001
@test 0.0640 ≈ MoistAir.dBaa(473.15)*1e6 atol=0.0001
end

@testset "Caaa" begin
@test 2267.0 ≈ MoistAir.Caaa(173.15)*1e12 atol=1.0
@test 1409.0 ≈ MoistAir.Caaa(273.15)*1e12 atol=1.0
@test 1202.0 ≈ MoistAir.Caaa(373.15)*1e12 atol=1.0
@test 1139.0 ≈ MoistAir.Caaa(473.15)*1e12 atol=1.0
end

@testset "dCaaa/dT" begin
@test -18.00 ≈ MoistAir.dCaaa(173.15)*1e12 atol=0.01
@test -3.65 ≈ MoistAir.dCaaa(273.15)*1e12 atol=0.01
@test -1.06 ≈ MoistAir.dCaaa(373.15)*1e12 atol=0.01
@test -0.34 ≈ MoistAir.dCaaa(473.15)*1e12 atol=0.01
end

@testset "Baw" begin
@test -93.3 ≈ MoistAir.Baw(173.15)*1e6 atol=0.1
@test -36.4 ≈ MoistAir.Baw(273.15)*1e6 atol=0.1
@test -14.5 ≈ MoistAir.Baw(373.15)*1e6 atol=0.1
@test -3.1 ≈ MoistAir.Baw(473.15)*1e6 atol=0.1
end

@testset "dBaw/dT" begin
@test 1.01 ≈ MoistAir.dBaw(173.15)*1e6 atol=0.01
@test 0.318 ≈ MoistAir.dBaw(273.15)*1e6 atol=0.001
@test 0.151 ≈ MoistAir.dBaw(373.15)*1e6 atol=0.001
@test 0.0869 ≈ MoistAir.dBaw(473.15)*1e6 atol=0.0001
end

@testset "Caaw" begin
@test 1023 ≈ MoistAir.Caaw(173.15)*1e12 atol=1.0
@test 861 ≈ MoistAir.Caaw(273.15)*1e12 atol=1.0
@test 696 ≈ MoistAir.Caaw(373.15)*1e12 atol=1.0
@test 627 ≈ MoistAir.Caaw(473.15)*1e12 atol=1.0
end

@testset "dCaaw/dT" begin
@test  5.56 ≈ MoistAir.dCaaw(173.15)*1e12 atol=0.01
@test -2.44 ≈ MoistAir.dCaaw(273.15)*1e12 atol=0.01
@test -1.02 ≈ MoistAir.dCaaw(373.15)*1e12 atol=0.01
@test -0.457 ≈ MoistAir.dCaaw(473.15)*1e12 atol=0.001
end

@testset "Caww" begin
@test -2.0e7 ≈ MoistAir.Caww(173.15)*1e12 atol=0.1e7
@test -2.2e5 ≈ MoistAir.Caww(273.15)*1e12 atol=0.1e5
@test -3.0e4 ≈ MoistAir.Caww(373.15)*1e12 atol=0.1e4
@test -8.4e3 ≈ MoistAir.Caww(473.15)*1e12 atol=0.1e3
end

@testset "dCaww/dT" begin
@test 1.61e6 ≈ MoistAir.dCaww(173.15)*1e12 atol=0.01e6
@test 6.05e3 ≈ MoistAir.dCaww(273.15)*1e12 atol=0.01e3
@test    456 ≈ MoistAir.dCaww(373.15)*1e12 atol=1.0
@test   86.9 ≈ MoistAir.dCaww(473.15)*1e12 atol=0.1
# Note that on table 1, the last line is 8.69 instead of 86.9. Probably a typo in the paper.
end
end

@testset "Specific volume of dry air" begin
# Table 3
P = 0.1e6
@test 0.49510 ≈ MoistAir.volumeair(173.15, P) atol=0.00003
@test 0.78364 ≈ MoistAir.volumeair(273.15, P) atol=0.0001
@test 1.0713 ≈ MoistAir.volumeair(373.15, P) atol=0.0001
@test 1.3586 ≈ MoistAir.volumeair(473.15, P) atol=0.0001

P = 0.5e6
@test 0.09747 ≈ MoistAir.volumeair(173.15, P) atol=0.00003
@test 0.15637 ≈ MoistAir.volumeair(273.15, P) atol=0.00003
@test 0.21436 ≈ MoistAir.volumeair(373.15, P) atol=0.00003
@test 0.27207 ≈ MoistAir.volumeair(473.15, P) atol=0.00003

P = 1e6
@test 0.04775 ≈ MoistAir.volumeair(173.15, P) atol=0.00003
@test 0.07797 ≈ MoistAir.volumeair(273.15, P) atol=0.00003
@test 0.10725 ≈ MoistAir.volumeair(373.15, P) atol=0.00003
@test 0.13625 ≈ MoistAir.volumeair(473.15, P) atol=0.00003

P = 5e6
@test 0.00795 ≈ MoistAir.volumeair(173.15, P) atol=0.00003
@test 0.01533 ≈ MoistAir.volumeair(273.15, P) atol=0.00003
@test 0.02162 ≈ MoistAir.volumeair(373.15, P) atol=0.00003
@test 0.02763 ≈ MoistAir.volumeair(473.15, P) atol=0.00003
end

@testset "Specific enthalpy of dry air" begin
# Table 3
P = 0.1e6
@test -100.63 ≈ MoistAir.enthalpyair(173.15, P)/1000 atol=0.01
@test    0.004≈ MoistAir.enthalpyair(273.15, P)/1000 atol=0.01
@test  100.79 ≈ MoistAir.enthalpyair(373.15, P)/1000 atol=0.01
@test  202.55 ≈ MoistAir.enthalpyair(473.15, P)/1000 atol=0.01

P = 0.5e6
@test -103.17 ≈ MoistAir.enthalpyair(173.15, P)/1000 atol=0.01
@test   -1.10 ≈ MoistAir.enthalpyair(273.15, P)/1000 atol=0.01
@test  100.26 ≈ MoistAir.enthalpyair(373.15, P)/1000 atol=0.01
@test  202.30 ≈ MoistAir.enthalpyair(473.15, P)/1000 atol=0.01

P = 1e6
@test -106.42 ≈ MoistAir.enthalpyair(173.15, P)/1000 atol=0.01
@test   -2.48 ≈ MoistAir.enthalpyair(273.15, P)/1000 atol=0.01
@test   99.60 ≈ MoistAir.enthalpyair(373.15, P)/1000 atol=0.01
@test  202.00 ≈ MoistAir.enthalpyair(473.15, P)/1000 atol=0.01

P = 5e6
@test -135.55 ≈ MoistAir.enthalpyair(173.15, P)/1000 atol=0.01
@test  -13.15 ≈ MoistAir.enthalpyair(273.15, P)/1000 atol=0.01
@test   94.63 ≈ MoistAir.enthalpyair(373.15, P)/1000 atol=0.01
@test  199.8 ≈ MoistAir.enthalpyair(473.15, P)/1000 atol=0.1
end

@testset "Specific entropy of dry air" begin
P = 0.1e6
@test -0.4550 ≈ MoistAir.entropyair(173.15, P)/1000 atol=0.0001
@test  0.0038 ≈ MoistAir.entropyair(273.15, P)/1000 atol=0.0001
@test  0.3182 ≈ MoistAir.entropyair(373.15, P)/1000 atol=0.0001
@test  0.5597 ≈ MoistAir.entropyair(473.15, P)/1000 atol=0.0001
end

# Table 4, appendix of reference [2]
@testset "Volume of saturated moist air" begin
volmoist(Tk, P) = MoistAir.volumemoist(Tk, P, MoistAir.efactor(Tk,P)*MoistAir.Pws(Tk)/P)
P = 0.1e6
@test 0.49510 ≈ volmoist(173.15, P) atol=0.00005
@test 0.78846 ≈ volmoist(273.15, P) atol=0.00005
@test 3.4974 ≈ volmoist(363.15, P) atol=0.0002 #fail
P = 0.5e6
@test 0.097466 ≈ volmoist(173.15, P) atol=0.000006
@test 0.15657 ≈ volmoist(273.15, P) atol=0.00005
@test 0.24273 ≈ volmoist(363.15, P) atol=0.00003
@test 0.26904 ≈ volmoist(373.15, P) atol=0.00003
P=1e6
@test 0.047752 ≈ volmoist(173.15, P) atol=0.000006
@test 0.078022 ≈ volmoist(273.15, P) atol=0.000005
@test 0.11226 ≈ volmoist(363.15, P) atol=0.00001
@test 0.11942 ≈ volmoist(373.15, P) atol=0.00001
@test 0.23281 ≈ volmoist(423.15, P) atol=0.00002 #fail
@test 0.32711 ≈ volmoist(433.15, P) atol=0.00002
@test 0.61489 ≈ volmoist(443.15, P) atol=0.00005 #fail

P=5e6
@test 0.007951 ≈ volmoist(173.15, P) atol=0.000006
@test 0.015331 ≈ volmoist(273.15, P) atol=0.000005
@test 0.021310 ≈ volmoist(363.15, P) atol=0.00001
@test 0.022073 ≈ volmoist(373.15, P) atol=0.00001
@test 0.02727  ≈ volmoist(423.15, P) atol=0.00001
@test 0.02885  ≈ volmoist(433.15, P) atol=0.00001
@test 0.03077  ≈ volmoist(443.15, P) atol=0.00001
@test 0.03315  ≈ volmoist(453.15, P) atol=0.00001
@test 0.0402  ≈ volmoist(473.15, P) atol=0.0001
end

@testset "enthalpy of saturated moist air" begin
hmoist(Tk, P) = MoistAir.enthalpymoist(Tk, P, MoistAir.efactor(Tk,P)*MoistAir.Pws(Tk)/P)/1000
P = 0.1e6
@test -100.627 ≈ hmoist(173.15, P) atol=0.005
@test    9.602 ≈ hmoist(273.15, P) atol=0.005
@test   4035.0 ≈ hmoist(363.15, P) atol=0.3 # In the paper the number is 4305! #fail

P = 0.5e6
@test -103.168 ≈ hmoist(173.15, P) atol=0.005
@test    0.831 ≈ hmoist(273.15, P) atol=0.005
@test   365.55 ≈ hmoist(363.15, P) atol=0.03
@test   533.27 ≈ hmoist(373.15, P) atol=0.03
@test   35957 ≈ hmoist(423.15, P) atol=2.0 #fail

P = 1e6
@test -106.415 ≈ hmoist(173.15, P) atol=0.005
@test   -1.498 ≈ hmoist(273.15, P) atol=0.005
@test   217.77 ≈ hmoist(363.15, P) atol=0.03
@test   293.17 ≈ hmoist(373.15, P) atol=0.03
@test   1788.8 ≈ hmoist(423.15, P) atol=0.5 #fail
@test   3113.3 ≈ hmoist(433.15, P) atol=0.5
@test   7206.0 ≈ hmoist(443.15, P) atol=2.0 #fail

P = 5e6
@test -135.547 ≈ hmoist(173.15, P) atol=0.005
@test  -12.929 ≈ hmoist(273.15, P) atol=0.005
@test   109.89 ≈ hmoist(363.15, P) atol=0.03
@test   132.42 ≈ hmoist(373.15, P) atol=0.03
@test   347.3 ≈ hmoist(423.15, P) atol=0.5
@test   428.8 ≈ hmoist(433.15, P) atol=0.5
@test   534.1 ≈ hmoist(443.15, P) atol=0.5
@test   672.0 ≈ hmoist(453.15, P) atol=1.0
@test   1113.0 ≈ hmoist(473.15, P) atol=1.0
end

@testset "Entropy of saturated moist air" begin
# Table 4 in the appendix of reference [2].
smoist(Tk, P) = MoistAir.entropymoist(Tk, P, MoistAir.efactor(Tk,P)*MoistAir.Pws(Tk)/P)/1000
P = 0.1e6
@test  -0.45499 ≈ smoist(173.15, P) atol=0.00003
@test   0.04070 ≈ smoist(273.15, P) atol=0.00003
@test  11.7287 ≈ smoist(363.15, P) atol=0.0005 #fail

P = 0.5e6
@test  -0.92718 ≈ smoist(173.15, P) atol=0.00005
@test  -0.45417 ≈ smoist(273.15, P) atol=0.00005
@test   0.64517 ≈ smoist(363.15, P) atol=0.0005
@test   1.1102 ≈ smoist(373.15, P) atol=0.0005
@test  90.01 ≈ smoist(423.15, P) atol=0.05 #fail

P = 1e6
@test  -1.13929 ≈ smoist(173.15, P) atol=0.00005 # In the table the signal is +
@test  -0.66104 ≈ smoist(273.15, P) atol=0.00005
@test   0.00805 ≈ smoist(363.15, P) atol=0.00005
@test   0.21676 ≈ smoist(373.15, P) atol=0.0005
@test   4.0478  ≈ smoist(423.15, P) atol=0.0005 #fail
@test   7.3103  ≈ smoist(433.15, P) atol=0.0005
@test   17.221  ≈ smoist(443.15, P) atol=0.005 #fail

P = 5e6
@test  -1.72380 ≈ smoist(173.15, P) atol=0.0001 # In the table the signal is +
@test  -1.15924 ≈ smoist(273.15, P) atol=0.00005
@test  -0.77519 ≈ smoist(363.15, P) atol=0.00005
@test  -0.71331 ≈ smoist(373.15, P) atol=0.00005
@test  -0.1629  ≈ smoist(423.15, P) atol=0.0002
@test   0.0364  ≈ smoist(433.15, P) atol=0.0002
@test   0.2901  ≈ smoist(443.15, P) atol=0.0002
@test   0.6185  ≈ smoist(453.15, P) atol=0.0002
@test   1.642  ≈ smoist(473.15, P) atol=0.002
end
end

ext: jl


text:
using Plots,ApproxFun

x=Fun(identity)
D=Derivative()

u=[dirichlet();
   1/70*D^2-x*D+I] \ [1.,2.]

plot(u)

max_stars_repo_path: examples/Lee & Greengard equation.jl

max_issues_repo_path: examples/Lee & Greengard equation.jl

max_forks_repo_path: examples/Lee & Greengard equation.jl


text:
#structs & enums

# consts
const forward="forward"
const down="down"
const up="up"

mutable struct INSTRUCTION
  X::Int
  Z::Int
  INSTRUCTION() = new(0, 0)
end
function parseInstruction(instruction::INSTRUCTION, direction::String, svalue::String)

  instruction.X = 0
  instruction.Z = 0

  value = parse(Int,svalue)
  if direction == forward
    instruction.X = value
  elseif direction == down
    instruction.Z = value
  elseif direction == up
    instruction.Z = (-1)*value
  end
end

mutable struct SUBMARINE
  X::Int
  Z::Int
  AIM::Int
  DEPTH::Int
  SUBMARINE() = new(0,0,0,0)
end
function updateSub(sub::SUBMARINE, iX::Int64, iZ::Int64)
  sub.X += iX
  sub.Z += iZ
  sub.AIM += iZ
  if iX > 0
    sub.DEPTH += ( sub.AIM * iX )
  end
end

println("#######################")
println("### AoC2021 - Day 2 ###")
println("#######################")

println(">> @arg1 : Input file")
println()

if ( size(ARGS)[1] != 1 )
  println("FATAL ERROR : Invalid number of args. Input file is required as @arg1.")
  quit()
end

# open input file
fd = open(ARGS[1], "r")
vals = readlines(ARGS[1])
if (size(vals)[1] <= 1)
  println("INVALID INPUT : Not enough data for meaningful answer.")
  quit()
end
n = size(vals)[1]

# interpret lines
# > DIRECTION : VAL
submarine   = SUBMARINE()
instruction = INSTRUCTION()

for i=1:n
  line = vals[i]
  splitted = split(line, " ")
  if (size(splitted)[1] != 2 )
    println("INVALID INPUT : Bad line length in input data for line : $splitted")
  end
  parseInstruction(instruction, String(splitted[1]), String(splitted[2]))
  updateSub( submarine, instruction.X, instruction.Z)
end

subx = submarine.X
subz = submarine.Z
println("SUBMARINE : $subx:$subz")

submul = subx * subz
println("PART 1 RESULT : $submul")

submul2 = subx * submarine.DEPTH
println("PART 2 RESULT : $submul2")

# close file
close(fd)


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

using Markdown
using InteractiveUtils

# ╔═╡ bb6cae46-4108-11eb-2309-3d11f13a19fa
begin
	using Pkg
	Pkg.activate(mktempdir())
end

# ╔═╡ d8b334ae-4108-11eb-2546-99e75efc18d6
begin
	Pkg.add(["Plots", "PlutoUI","StatsBase", "DataStructures", "Unitful", "PhysicalConstants", "UnitfulEquivalences"])

	using Plots
	plotly()
	using PlutoUI
	using StatsBase
	using DataStructures
	using Unitful
	using PhysicalConstants.CODATA2018: c_0, h, ħ
	using UnitfulEquivalences
end

# ╔═╡ a78b9c3a-4109-11eb-26ca-1556cfeb2b8c
quantum_energy2 = uconvert(u"eV", 500u"THz", PhotonEnergy())

# ╔═╡ 5aa7ff98-410a-11eb-3848-895e37363b3c
period2 = 1/500u"THz"

# ╔═╡ 5990a14a-410b-11eb-086a-f129b7fdf82c
refracted_speed2 = uconvert(u"Mm/s", c_0 / 1.5)

# ╔═╡ 6209ea56-410c-11eb-0bb3-ff80947cdcb0
wavelength2 = uconvert(u"nm", refracted_speed2*period2)

# ╔═╡ 84c21a6c-4109-11eb-166e-151c460d28c8
md"""
## E2

Light, which possesses in vacuum the frequency of 500 THz and quantum energy of $quantum_energy2, passes through
sheet of glass with the refractive index of 1.5. The speed of such light in glass is $refracted_speed2, the frequency is
500 THz, the wavelength is $wavelength2 and quantum energy is 2.07 eV.
"""

# ╔═╡ fdae38fe-410c-11eb-18dd-9bae51fb4e00
freq3 = uconvert(u"THz", (1E13)u"Hz")

# ╔═╡ fdbe0894-410c-11eb-0ace-3d269b2942aa
n = 9

# ╔═╡ 220ec448-410d-11eb-17c3-d1682a1588c9
refractive3 = sqrt(n)

# ╔═╡ 74fa7748-410c-11eb-0688-a37608618c96
md"""
## E3.1

The electric field strength that oscillates with the frequency of **$freq3** is reduced **$n** times in some substance
with respect to the vacuum. The refractive index of this substance is **$refractive3**
"""

# ╔═╡ 31bce1b8-410d-11eb-008b-bf04b66bf555
slit_length4 = 0.03u"mm"

# ╔═╡ 2e0551ea-410d-11eb-176c-650b9c498d25
distance_from_slit = 2u"m"

# ╔═╡ 0aaf6748-410e-11eb-035a-8be0950091d6
minima_distance = 8u"cm"

# ╔═╡ 0aa8bb82-410e-11eb-163c-6de6eda9e616
minima_angle = uconvert(u"rad", atan(minima_distance/2, distance_from_slit))

# ╔═╡ 70a82a76-410e-11eb-2f0e-295b06d5d8fb
wavelength4 = uconvert(u"nm", sin(minima_angle) * slit_length4)

# ╔═╡ 3bb15c6c-410d-11eb-1b1b-4b13708ceb70
md"""
## E4.1

The monochromatic light is penetrating a single **$slit_length4** wide vertical slit. On the screen positioned perpendicular to the light propagating direction at the distance of **$distance_from_slit** behind the slit, a diffraction pattern appears in which the two first minima are located at the distance of **$minima_distance** from each other. The first minimum is located at the angle of **$minima_angle** with respect to the diffraction pattern centre. The wavelength of the light used was **$wavelength4**
"""

# ╔═╡ c08c3f10-4117-11eb-059e-1fa7c75e4240
absorption_coef_blue = 5u"cm^-1"

# ╔═╡ ffd6d630-4117-11eb-2200-a147d74af92f
absorbtion_coef_green = 3u"cm^-1"

# ╔═╡ 38b97e80-4118-11eb-34c5-65de18666aed
absorption_coef_red = 0.3u"cm^-1"

# ╔═╡ 45bb6c38-4118-11eb-0ba5-f55cde355ccd
blue_layer_thickness = uconvert(u"cm", 1/absorption_coef_blue)

# ╔═╡ 40d8a62c-4118-11eb-15c3-e9e0c5d87609
n_intensity_reduced = 3

# ╔═╡ 793b338a-4119-11eb-1916-6513f6eed696
ℯ

# ╔═╡ afcc4710-4119-11eb-28db-fdf5aa042d8e
substance_color1 = "red"

# ╔═╡ d0340d2e-4119-11eb-209d-7dcf7fa4c2e7
substance_color2 = "black"

# ╔═╡ c094cb3a-4117-11eb-168a-df762ad5739e
md"""
## E5
For some substance, the absorption coefficient for the blue light is **$absorption_coef_blue**. For the green light, it is **$absorbtion_coef_green** and for the red light **$absorption_coef_red**. This means that the intensity of the blue light will be reduced Euler number (e = 2.7183..) times by passing through the **$blue_layer_thickness** thick layer of the substance. The layer with the thickness of 1 cm reduces the intensity of green light e **$n_intensity_reduced** times. If we illuminate this substance with the white light, the colour of the substance will be **$substance_color1**. If we illuminate the substance with the blue light, the colour of the substance will be **$substance_color2**.

"""

# ╔═╡ 80572be0-411b-11eb-3f15-fbf4e6ed7cf3
electron_speed = 729u"km/s"

# ╔═╡ 5788010a-411e-11eb-2c69-bd73c5cd6d3f
ground_speed = 2188u"km/s"

# ╔═╡ 7fe77a98-411b-11eb-1835-75b0687dedfd
n6 = round(ground_speed / electron_speed)

# ╔═╡ 7fc27112-411b-11eb-3b4b-97599735cd31
angular_momentum = uconvert(u"kg*m^2*s^-1", 1.05E-34u"kg*m^2*s^-1" * n6)

# ╔═╡ 224bba9e-411f-11eb-2901-87f766e95a56
ground_frequency = 6580u"THz"

# ╔═╡ 3ed8da6c-411e-11eb-3a35-4164dfd2aa54
imagined_rotation_frequency = uconvert(u"THz", ground_frequency / n6 ^3)

# ╔═╡ 91b1a86c-411f-11eb-0700-a30281bd1f40
ground_energy = -13.60u"eV"

# ╔═╡ 8a2e2e76-411f-11eb-0da9-ed7c9382599f
net_energy = ground_energy / n6^2

# ╔═╡ 0396e5f2-4120-11eb-1502-f358ec34acd9
ground_radius = 0.529u"Å"

# ╔═╡ 03d6d638-4120-11eb-20d0-0fa5cffc6d3d
mean_distance = ground_radius * n6^2

# ╔═╡ 296b84ce-4121-11eb-2c07-1b1ff4cac46c
emitted_photon_wavelength = 656u"nm"

# ╔═╡ f74d6ff0-4120-11eb-2de1-9d7c40c9354c
quantum_energy6 = uconvert(u"eV", emitted_photon_wavelength, PhotonEnergy())

# ╔═╡ 66942310-4121-11eb-063c-37022902216f
energy_after_photon = net_energy - quantum_energy6

# ╔═╡ 81bc1422-4121-11eb-0cb5-215e6fb5c308
qn = round(sqrt(ground_energy/energy_after_photon))

# ╔═╡ 8238f47e-4121-11eb-06a7-a3f1bf8887cb
imag_rot_freq2 = uconvert(u"THz", ground_frequency / qn ^3)

# ╔═╡ 0e7c4e68-4122-11eb-3b1a-8f9808df6829
mean_distance2 = ground_radius * qn^2

# ╔═╡ 7fec90b4-411b-11eb-04db-a913940a9f22
md"""
## E6
In the atom of hydrogen, the electron moves according to the Bohr model. Its speed is **$electron_speed**. The angular momentum of this electron is **$angular_momentum**, the frequency of imagined rotation is **$imagined_rotation_frequency**, the net energy is **$net_energy** and the mean distance from the nucleus is **$mean_distance**. The electron comes closer to the nucleus and a photon with the wavelength of **$emitted_photon_wavelength** is emitted. The quantum energy of this radiation is **$quantum_energy6**. At the end of the transition, the frequency of the imagined rotation of the electron is **$imag_rot_freq2** and its mean distance from the nucleus is **$mean_distance2**.
"""

# ╔═╡ 46652b7e-4122-11eb-1576-29e34caf1b03
mass = 4E-25u"kg"

# ╔═╡ 78e0e354-4122-11eb-1a11-0b1d36a38b70
diam = 5E-10u"m"

# ╔═╡ 46798970-4122-11eb-31a8-ab967162b1ae
h_bar = 1E-34u"J*s"

# ╔═╡ 4691ff34-4122-11eb-1614-b5df5b328525
speed_increase = uconvert(u"m/s", h_bar / (mass * diam))

# ╔═╡ c9767010-4125-11eb-3529-43e03fc0ed7b
time_for_diam = diam / speed_increase

# ╔═╡ c9680bce-4125-11eb-1a30-93e346ab5ef8
time2 = uconvert(u"ns", time_for_diam)

# ╔═╡ 451edba2-4122-11eb-0ea9-b3e5a7021bd1
md"""
# E7

The uranium atom (a microscopic object) with the mass of **$mass** and diameter of **$diam** moves in a certain direction. The location of the atom is fixed by its passing through the slit possessing the width almost equal to the atom diameter. The screen containing this slit is positioned perpendicular to the velocity of the atom. As a result of penetrating this slit, the speed of the atom receives some unpredictable increase perpendicular to the direction of previous motion. Using the reduced Planck constant 10–34 J*s as a typical value of impact uncertainty, we can conclude that the increase of the speed is **$speed_increase**. After **$time_for_diam** seconds, the atom deviates from its classical straight trajectory by its own diameter. This result means that we can predict the motion of uranium atom in a classical way for maximally **$time2** nanoseconds.

"""

# ╔═╡ aa066c66-4126-11eb-1909-713aeda74edc
mass8 = 9E-31u"kg"

# ╔═╡ c4375a50-4126-11eb-2667-7b693682e9a8
well_width = 3u"Å"

# ╔═╡ aa323b5c-4126-11eb-18fa-a5aa100d0678
qn8 = 3

# ╔═╡ aa487444-4126-11eb-306c-1d98f391cfc6
planck8 = 6.6E-34u"J*s"

# ╔═╡ aa708326-4126-11eb-2129-df2f5666aa93
wavelength = 2*well_width / qn8

# ╔═╡ aa9ab420-4126-11eb-206b-2bd429f38b13
lin_momentum = uconvert(u"kg*m/s", planck8 / wavelength)

# ╔═╡ aa805792-4126-11eb-20eb-b127d6ae2898
energy8 = uconvert(u"eV", lin_momentum^2/(2*mass8))

# ╔═╡ c98691d4-4125-11eb-3e71-d1ffa4fc0f3a
md"""
## E8

An electron with the mass of **$mass8** is located in a single-dimensional potential well with the width of **$well_width** (approximate diameter of the atom). Let us describe this electron according to the laws of quantum mechanics as a standing wave in the string, whereas the length of the string is equal to the width of the potential well. In the state described by the quantum number **$qn8**, the wavelength of the electron is **$wavelength**, its
linear momentum is **$lin_momentum** and its energy is **$energy8**.

"""

# ╔═╡ aa5f27d4-4126-11eb-19db-9b02f89cf0f0

# ╔═╡ aa1d3ab8-4126-11eb-11d9-ab8a72c7e68f

# ╔═╡ Cell order:
# ╠═bb6cae46-4108-11eb-2309-3d11f13a19fa
# ╠═d8b334ae-4108-11eb-2546-99e75efc18d6
# ╟─84c21a6c-4109-11eb-166e-151c460d28c8
# ╠═a78b9c3a-4109-11eb-26ca-1556cfeb2b8c
# ╠═5aa7ff98-410a-11eb-3848-895e37363b3c
# ╠═5990a14a-410b-11eb-086a-f129b7fdf82c
# ╠═6209ea56-410c-11eb-0bb3-ff80947cdcb0
# ╟─74fa7748-410c-11eb-0688-a37608618c96
# ╠═fdae38fe-410c-11eb-18dd-9bae51fb4e00
# ╠═fdbe0894-410c-11eb-0ace-3d269b2942aa
# ╠═220ec448-410d-11eb-17c3-d1682a1588c9
# ╠═3bb15c6c-410d-11eb-1b1b-4b13708ceb70
# ╠═31bce1b8-410d-11eb-008b-bf04b66bf555
# ╠═2e0551ea-410d-11eb-176c-650b9c498d25
# ╠═0aaf6748-410e-11eb-035a-8be0950091d6
# ╠═0aa8bb82-410e-11eb-163c-6de6eda9e616
# ╠═70a82a76-410e-11eb-2f0e-295b06d5d8fb
# ╠═c094cb3a-4117-11eb-168a-df762ad5739e
# ╠═c08c3f10-4117-11eb-059e-1fa7c75e4240
# ╠═ffd6d630-4117-11eb-2200-a147d74af92f
# ╠═38b97e80-4118-11eb-34c5-65de18666aed
# ╠═45bb6c38-4118-11eb-0ba5-f55cde355ccd
# ╠═40d8a62c-4118-11eb-15c3-e9e0c5d87609
# ╠═793b338a-4119-11eb-1916-6513f6eed696
# ╠═afcc4710-4119-11eb-28db-fdf5aa042d8e
# ╠═d0340d2e-4119-11eb-209d-7dcf7fa4c2e7
# ╟─7fec90b4-411b-11eb-04db-a913940a9f22
# ╠═80572be0-411b-11eb-3f15-fbf4e6ed7cf3
# ╠═5788010a-411e-11eb-2c69-bd73c5cd6d3f
# ╠═7fe77a98-411b-11eb-1835-75b0687dedfd
# ╠═7fc27112-411b-11eb-3b4b-97599735cd31
# ╠═224bba9e-411f-11eb-2901-87f766e95a56
# ╠═3ed8da6c-411e-11eb-3a35-4164dfd2aa54
# ╠═91b1a86c-411f-11eb-0700-a30281bd1f40
# ╠═8a2e2e76-411f-11eb-0da9-ed7c9382599f
# ╠═0396e5f2-4120-11eb-1502-f358ec34acd9
# ╠═03d6d638-4120-11eb-20d0-0fa5cffc6d3d
# ╠═296b84ce-4121-11eb-2c07-1b1ff4cac46c
# ╠═f74d6ff0-4120-11eb-2de1-9d7c40c9354c
# ╠═66942310-4121-11eb-063c-37022902216f
# ╠═81bc1422-4121-11eb-0cb5-215e6fb5c308
# ╠═8238f47e-4121-11eb-06a7-a3f1bf8887cb
# ╠═0e7c4e68-4122-11eb-3b1a-8f9808df6829
# ╟─451edba2-4122-11eb-0ea9-b3e5a7021bd1
# ╠═46652b7e-4122-11eb-1576-29e34caf1b03
# ╠═78e0e354-4122-11eb-1a11-0b1d36a38b70
# ╠═46798970-4122-11eb-31a8-ab967162b1ae
# ╠═4691ff34-4122-11eb-1614-b5df5b328525
# ╠═c9767010-4125-11eb-3529-43e03fc0ed7b
# ╠═c9680bce-4125-11eb-1a30-93e346ab5ef8
# ╠═c98691d4-4125-11eb-3e71-d1ffa4fc0f3a
# ╠═aa066c66-4126-11eb-1909-713aeda74edc
# ╠═c4375a50-4126-11eb-2667-7b693682e9a8
# ╠═aa323b5c-4126-11eb-18fa-a5aa100d0678
# ╠═aa487444-4126-11eb-306c-1d98f391cfc6
# ╠═aa708326-4126-11eb-2129-df2f5666aa93
# ╠═aa9ab420-4126-11eb-206b-2bd429f38b13
# ╠═aa805792-4126-11eb-20eb-b127d6ae2898
# ╠═aa5f27d4-4126-11eb-19db-9b02f89cf0f0
# ╠═aa1d3ab8-4126-11eb-11d9-ab8a72c7e68f


text:
# Use baremodule to shave off a few KB from the serialized `.ji` file
baremodule AprilTags_jll
using Base
using Base: UUID
import JLLWrappers

JLLWrappers.@generate_main_file_header("AprilTags")
JLLWrappers.@generate_main_file("AprilTags", UUID("49f4e9a8-0306-5d58-91df-e9c3c0e42747"))
end  # module AprilTags_jll


text:
using DrWatson
@quickactivate :FractalDimension # uses DynamicalSystems, PyPlot
include(srcdir("style.jl"))
using BenchmarkTools

X = Data.henon_chaotic(N = 10_000)
es = estimate_boxsizes(X)
qC = 2

for qC in (2, 3, 4)
    @show qC
    bmark = @benchmark correlationsum($X, $es; q = qC)
    bmark_boxed = @benchmark boxed_correlationsum($X, $es; q = qC)

    @show median(bmark).time
    @show median(bmark_boxed).time
    @show median(bmark).allocs
    @show median(bmark_boxed).allocs
    println()
end

max_stars_repo_name: Datseris/FractalDimension

max_issues_repo_name: Datseris/FractalDimension

max_forks_repo_name: Datseris/FractalDimension


text:
module LDJ

# include("Content.jl")
# using .Content

using JSON
using Dates: Date, now, year, DateTime
using URIs: URI

const DATE_FORMAT = "mm/dd/yyyy"
const EMPTY_DATE = Date("0001-01-01")

export wrap_ldj, website, search, place, author, publisher, languages, webpage, translation, breadcrumbs, Book, book,
    bookfeed, event_status, online_event, license, orgschema, coverage, place_schema, dataset, faqschema, image,
    howtoitem, howto, logo, ratingprop, movie, itemslist, review, searchaction, speakable, pubevents, video

macro unimp(fname)
    quote
        function $(esc(fname))()
            throw("unimplemented")
        end
    end
end

@doc "Set properties (a (k, v) vector) to data (an dict)."
macro setprops!()
    quote
        pr = $(esc(:props))
        data = $(esc(:data))
        if !isempty(pr)
            for (p, v) in pr
	            data[p] = v
            end
        end
        data
    end
end

function setargs!(data, args...)
    for (k, v) in args
        if !isnothing(v) && !isempty(v)
            data[k] = v
        end
    end
    data
end

## LD+JSON functions
@inline function schema()
    "@context" => "https://schema.org"
end

@inline function wrap_ldj(data::IdDict, wrap=true, id="", class="")
    wrap && return "<script type=\"application/ld+json\" id=\"$(id)\" class=\"$(class)\">$(JSON.json(data))</script>"
    data
end

@doc "https://schema.org/WebSite"
function website(url, author, year; image="")
    IdDict(
        "@context" => "https://schema.org/",
        "@type" => "WebSite",
        "@id" => url,
        "url" => url,
        "image" => image,
        "copyrightHolder" => author,
        "copyrightYear" => year,
    )
end

@doc "https://schema.org/SearchAction
`parts` are url parts (scheme, host, port, path, query, fragment) to merge with the url string. It has
to contain a parameter which value is `{input}`."
function search(url::AbstractString; parts=NamedTuple(), maxlength=100)
    @assert "{input}" in values(parts.query)
    uri = URI(url)
    IdDict(
        "potentialAction" => IdDict(
            "@type" => "SearchAction",
            "target" => URI(uri; parts...),
            "query" => "required",
            "query-input" => "required maxlength=$(maxlength) name=input",
            "actionStatus" => "https://schema.org/PotentialActionStatus",
        ),
    )
end

@doc "https://schema.org/Place"
function place(place="homeLocation"; country="", region="", props=[])
    data = IdDict(
        place => IdDict(
            "@type" => "https://schema.org/Place",
            "addressCountry" => locvar(:country),
            "addressRegion" => locvar(:region),
        ),
    )
    if !isempty(country)
        data["addressCountry"] = country
    end
    if !isempty(region)
        data["addressRegion"] = region
    end
    @setprops!
    data
end

@doc "Convenience function for authors.
Requires at least `name` and `email`."
function author(entity="Person"; name, email="", description="", image="", sameAs="")
    data = IdDict{String, Any}(
        "@type" => "https://schema.org/$(entity)",
        "name" => name,
        "email" => email
    )
    setargs!(data, "image" => image, "description" => description, "sameAs" => sameAs)
end

@doc "Currently same as `author`. NOTE: a publisher should not be a person."
function publisher(args...; kwargs...)
	author(args; kwargs...)
end

@doc "Create a list of Language types"
function languages(langs)
    [IdDict("@type" => "Language", "name" => l) for l in langs]
end

@doc "convert VAL to TO if equal to WHAT, otherwise return VAL."
@inline function coerce(val; what=nothing, to="")
    val === what && return to
    val
end
@doc "convert VAL to TO if FN returns true, otherwise return VAL."
@inline function coercf(val; fn=isempty, to="")
    fn(val) && return to
    val
end

function ensure_time(modified, created, default=string(now()))
    if isempty(modified)
        isempty(created) && return default
        return created
    end
    modified
end

function webpage(;id, title, url, mtime, selector, description, keywords, name="", headline="",
                 image="", entity="Article", status="Published",lang="english", mentions=[],
                 access_mode=["textual", "visual"], access_sufficient=[], access_summary="",
                 created="", published="", props=[])
    d_mtime = coerce(mtime)
    s_created = string(created)
    description = coerce(description; to=title)
	data = IdDict(
        "@context" => "https://schema.org",
        "@type" => "https://schema.org/WebPage",
        "@id" => id,
        "url" => url,
        "lastReviewed" => coerce(mtime),
        "mainEntityOfPage" => IdDict(
            "@type" => entity,
            "@id" => url
        ),
        "mainContentOfPage" =>
            IdDict("@type" => "WebPageElement", "cssSelector" => selector),
        "accessMode" => access_mode,
        "accessModeSufficient" => IdDict(
            "@type" => "itemList",
            "itemListElement" => coercf(access_sufficient; to=access_mode),
        ),
        "creativeWorkStatus" => status,
        # NOTE: datePublished should always be provided
        "datePublished" => ensure_time(string(d_mtime), s_created),
        "dateModified" => d_mtime,
        "dateCreated" => coerce(s_created; to=d_mtime),
        "name" => coerce(name; to=title),
        "description" => coerce(description),
        "keywords" => coerce(keywords; to=[])
    )
    setargs!(data, "inLanguage" => lang, "accessibilitySummary" => access_summary,
             "headline" => coerce(headline; to=description), "image" => image,
             "mentions" => mentions)
    @setprops!
end

@doc "file path must be relative to the project directory, assumes the published website is under '__site/'"
function translation(;src_url, trg_url, lang, title, mtime, selector, description, keywords,
                     image="", headline="", props=[],
                     translator_name="Google", translator_url="https://translate.google.com/")

    data = webpage(;id=trg_url, title, url=trg_url, mtime, selector, description,
                   keywords, image, headline, lang, props)
    data["translator" ] = IdDict("@type" => "https://schema.org/Organization",
                               "name" => translator_name,
                               "url" => translator_url)
    data["translationOfWork"] = IdDict("@id" => src_url)
    data
end

@doc """Take a list of (name, link) tuples and returns a breadcrumb
definition with hierarchy from top to bottom"""
function breadcrumbs(items)
    IdDict(
        "@type" => "BreadcrumbList",
        "itemListElement" => [
            IdDict(
                "@type" => "ListItem",
                "position" => n,
                "name" => name,
                "item" => item
            ) for (n, (name, item)) in enumerate(items)
                ]
    )
end

Book = @NamedTuple begin
	name::String
    author::String
    url::String
    sameas::String
    tags::Vector{String}
    comments::String
end

function book(name, author, url, tags, sameas)
    book = IdDict(                schema(),
                                  "@type" => "Book",
                                  "@id" => url,
                                  "url" => url,
                                  "urlTemplate" => url,
                                  "name" => name,
                                  "author" => IdDict(
                                      "@type" => "Person",
                                      "name" => author
                                  ),
                                  "sameAs" => sameas )
    !isempty(url) && begin
	    book["url"] = url
        book["@id"] = url
        book["urlTemplate"] = url
    end
    book
end

function bookfeed(books; props=[])
    data = IdDict(
        schema(),
        "@type" => "DataFeed",
        "dataFeedElement" => [book(b...) for b in books],)
    @setprops!
end

function event_status(status)
    let schema = "https://schema.org/Event"
        if status === "cancelled"
            schema * "Cancelled"
        elseif status === "moved"
            schema * "MovedOnline"
        elseif status === "postponed"
            schema * "Postponed"
        elseif status === "rescheduled"
            schema * "Rescheduled"
        else
            schema * "Scheduled"
        end
    end
end

function online_event(;name, start_date, end_date, url, image=[], desc="",
                      status="EventScheduled", prev_date="",
                      perf=IdDict(), org=IdDict(), offers=IdDict())
	IdDict(
        schema(),
        "@type" => "Event",
        "name" => name,
        "startDate" => start_date,
        "endDate" => end_date,
        "previousStartDate" => prev_date,
        "eventStatus" => event_status(status),
        "eventAttendanceMode" => "https://schema.org/OnlineEventAttendanceMode",
        "location" => IdDict(
            "@type" => "VirtualLocation",
            "url" => url
        ),
        "image" => image,
        "description" => desc,
        "offers" => offers,
        "performer" => perf,
        "organizer" => org)
end

function license(name="")
	if name === "mit"
        "https://en.wikipedia.org/wiki/MIT_License"
    elseif name === "apache"
        "https://en.wikipedia.org/wiki/Apache_License"
    elseif name === "gpl" || name === "gplv3"
        "https://www.gnu.org/licenses/gpl-3.0.html"
    elseif name === "gplv2"
        "https://www.gnu.org/licenses/old-licenses/gpl-2.0.html"
    elseif name === "sol"
        "https://wiki.p2pfoundation.net/Copysol_License"
    elseif name === "crypto" || name === "cal"
        "https://raw.githubusercontent.com/holochain/cryptographic-autonomy-license/master/README.md"
    else
        "https://creativecommons.org/publicdomain/zero/1.0/"
    end
end

function orgschema(;name, url, contact="", tel="", email="", sameas="", logo="")
    IdDict(
        "@type" => "Organization",
        "name" => name,
        "url" => url,
        "logo" => logo,
        "sameAs" => sameas,
        "contactPoint" => IdDict(
            "@type" => "ContactPoint",
            "contactType" => contact,
            "telephone" => tel,
            "email" => email,))
end

function coverage(start_date, end_date="")
	start_date * "/" * (isempty(end_date) ? ".." : end_date)
end

function place_schema(coords="")
    IdDict(
        "@type" => "Place",
        "geo" => IdDict(
            "@type" => "GeoShape",
            "box" => coords
        )
    )
end

@doc "dist is a tuple of (format, url) for content format and download link"
function dataset(;name, url, desc="", sameas="", id="",
                 keywords=[], parts=[], license="", access=true,
                 creator=IdDict(), funder=IdDict(), catalog="", dist=[],
                 start_date="", end_date="", coords="")
    IdDict(
        schema(),
        "@type" => "Dataset",
        "name" => name,
        "url" => url,
        "description" => desc,
        "sameAs" => sameas,
        "identifier" => isempty(id) ? url : id,
        "keywords" => keywords,
        "hasPart" => parts,
        "license" => license,
        "isAccessibleForFree" => access,
        "creator" => creator,
        "funder" => funder,
        "includedInDataCatalog" => IdDict(
            "@type" => "DataCatalog",
            "name" => catalog
        ),
        "distribution" => [
            IdDict(
                "@type" => "DataDownload",
                "encodingFormat" => f,
                "contentUrl" => d
            ) for (f, d) in dist
                ],
        "temporalCoverage" => isempty(start_date) ? start_date : coverage(start_date, end_date),
        "spatialCoverage" => place_schema(coords)
    )
end

function faqschema(faqs)
    IdDict(
        schema(),
        "@type" => "FAQPage",
        "mainEntity" => [
            IdDict(
                "@type" => "Question",
                "name" => question,
                "acceptedAnswer" => IdDict(
                    "@type" => "Answer",
                    "text" => answer
                )
            ) for (question, answer) in faqs])
end

@doc "estimatedCost, MonetaryAmount (monetary) or Text"
function cost(type; currency="USD", value="0")
    if type === "monetary"
	    IdDict(
            "@type" => "MonetaryAmount",
            "currency" => currency,
            "value" => value
        )
    else
        type
    end
end

function image(url; width="", height="", license=(license="", acquire=""))
	IdDict(
        schema(),
        "@type" => "ImageObject",
        "url" => url,
        "width" => width,
        "height" => height,
        "license" => license.license,
        "acquireLicensePage" => license.acquire)
end

@doc "create an HowToSupply, HowToTool or HowToStep"
function howtoitem(name, type="supply"; props=[])
    if type === "supply"
        tp = "HowToSupply"
    elseif type === "item"
        tp = "HowToItem"
    elseif type === "direction"
        tp = "HowToDirection"
    elseif type === "tip"
        tp = "HowToTip"
    else
        tp = "HowToStep"
    end
    data = IdDict(
        "@type" => tp,
        "name" => name
    )
    @setprops!
end

function howto(;name, desc="", image=IdDict(),
               cost=(currency="USD", value=0), supply=[],
               tool=[], step=[], totaltime="")
	IdDict(
        schema(),
        "@type" => "HowTo",
        "name" => name,
        "description" => desc,
        "image" => image,
        "estimatedCost" => cost("monetary"; cost...),
        "supply" => supply,
        "tool" => tool,
        "step" => step,
        # https://en.wikipedia.org/wiki/ISO_8601#Durations
        "totalTime" => "")
end

function logo(;type="Organization", url, logo, props=[])
    data = IdDict(
        schema(),
        "@type" => type,
        "url" => url,
        "logo" => logo
    )
    @setprops!
end

function ratingprop(value, best, count)
    "aggregateRating" => IdDict(
        "@type" => "AggregateRating",
        "ratingValue" => value,
        "bestRating" => best,
        "ratingCount" => count)
end

function movie(;url, name, image="", created="", director="", rating="", review_author="", review="", props=[])
    data = IdDict(
        "@type" => "Movie",
        "url" => url,
        "name" => name,
        "image" => image,
        "dateCreated" => created,
        "director" => IdDict(
            "@type" => "Person",
            "name" => director,),
        "review" => IdDict(
            "@type" => "Review",
            "reviewRating" => IdDict(
                "@type" => "Rating",
                "ratingValue" => rating,),
            "author" => IdDict(
                "type" => "Person",
                "name" => review_author
            ),
            "reviewBody" => review,))
    @setprops!
end

function itemslist(items)
    IdDict(
        schema(),
        "@type" => "ItemList",
        "itemListElement" => items
    )
end

function review(;name, rating="", author="", review="", org=[],
                item_props=[], props=[])
    data = IdDict(
        schema(),
        "@type" => "Review",
        "itemReviewed" => IdDict(p => v for (p, v) in item_props) ,
        "reviewRating" => IdDict(
            "@type" => "Rating",
            "ratingvalue" =>  rating,
        ),
        "name" => name,
        "author" => IdDict(
            "@type" => "Person",
            "name" => author
        ),
        "reviewBody" => review,
        "publisher" => orgschema(;org...)
    )
    @setprops!
end

function searchaction(;url, template, query, props=[])
    data = IdDict(
        schema(),
        "@type" => "WebSite",
        "url" => url,
        "potentialAction" => IdDict(
            "@type" => "SearchAction",
            "target" => IdDict(
                "@type" => "EntryPoint",
                "urlTemplate" => template,),
            "query-input" => "required " * query))
    @setprops!
end

function speakable(;name, url, css::AbstractVector)
    IdDict(
        schema(),
        "@type" => "WebPage",
        "name" => name,
        "speakable" => IdDict(
            "@type" => "SpeakableSpecification",
            "cssSelector" => css
        ),
        "url" => url
    )
end

function pubevents(events)
    [IdDict(
        "@type" => "BroadcastEvent",
        "isLiveBroadcast" => true,
        "startDate" => start_date,
        "endDate" => end_date) for (start_date, end_date) in events]
end

function video(;name, url, desc="", duration="", embed="",
               expire="", regions="", views, thumbnail="", date="", pubevents=[])
    IdDict(
        schema(),
        "@type" => "VideoObject",
        "contentURL" => url,
        "description" => desc,
        "duration" => duration,
        "embedURL" => embed,
        "expires" => expire,
        "regionsAllowed" => regions,
        "interactionStatistic" => IdDict(
            "@type" => "InteractionCounter",
            "interactionType" => IdDict("@type" => "WatchAction"),
            "userInteractionCount" => views,
        ),
        "name" => name,
        "thumbnailUrl" => thumbnail,
        "uploadDate" => date,
        "publication" => pubevents
    )
end

@unimp jobtraining

@unimp jobposting

@unimp business

@unimp factcheck

@unimp mathsolver

@unimp practiceproblems

@unimp product

@unimp qapage

@unimp recipe

@unimp softwareapp

@unimp subscription

function ldjfranklin()
    include(joinpath(dirname(@__FILE__), "LDJFranklin.jl"))
    @eval export LDJFranklin
end

end


text:
#const RETAINED_COLS_BB_SEO = []
const BB_DATE_FORMAT = dateformat"mm/dd/yyyy"
const BB_EVENT_NAMES = ["seo1", "seo2"]

function cleanbbnames!(bb::DataFrame; )
  bbnames::Vector{String} = (string).(names(bb))

  bbnames .= (lowercase).(bbnames)
  bbnames .= (s->replace(s, r"[^a-z0-9]"=>"")).(bbnames)
  names!(bb, (Symbol).(bbnames))

end

function filterbbeventdates!(bb::DataFrame)
  #WARNING: STUB -Need to acquire data and put in the filter for 10 days between filing and offer date
  return bb
end

function getidentifiersforbb(bb::DataFrame)
  local ccm::DataFrame = loadccm()
  ccm = preprocessccm!(ccm)

  bb.eid = collect(1:size(bb,1)) #assign an id to each event
  ccm.cusip = (Symbol).(ccm.cusip)
  bb.cusip = (Symbol).(bb.cusip)

  bb = join(bb, ccm, on=:cusip=>:cusip)
  filter!(r::DataFrameRow -> r.date ∈ r.linkeffdate:Day(1):r.linkenddate, bb)
  @assert allunique(bb.eid) #no dups

  rename!(bb, :lpermno=>:permno) #sanitize permno

  return bb
end

function readbbseo(fnames::Vector{String} = BB_EVENT_NAMES;
  path::String = EVENT_PATH,
  bbdateformat = BB_DATE_FORMAT)

  local bb::DataFrame = DataFrame()

  #read in the bloomberg files
  for (i, f) ∈ enumerate(fnames)
    bbin::DataFrame = CSV.read("$path\\$f.csv") |> DataFrame
    cleanbbnames!(bbin)
    bb = vcat(bb, bbin)
  end

  #println("got here")

  filterbbeventdates!(bb)
  bb[!, :date] = (s->Date(s, bbdateformat)).(bb.announceddate)
  bb = getidentifiersforbb(bb)
end

function formeventwindows(event::DataFrame;
  days=7,
  refresheventcrsp::Bool = true)

  Nevent::Int = size(event,1)

  #create the fields that will hold the returns
  local dayfields::Vector{Symbol} = (d->d<0 ? Symbol("DM",abs(d)) : Symbol("D",d)).(collect((-1*days):days))
  for f::Symbol ∈ dayfields
    event[!, f] = Vector{MFloat64}(missing, Nevent)
  end

  validpermnos::Vector{Int} = unique(event[!, :permno])

  #load the crsp df
  local crsp::DataFrame = prepcrsp(
    crspcolumns = [:date, :permno, :ret, :net],
    crsptype = REPLICATION_TYPE[],
    refreshcrsp=refresheventcrsp,
    validpermnos = validpermnos,
    prefix = "event") do df::DataFrame
    computenetreturns!(df)
  end

  #make the appropriate sorts
  crspdates::Vector{Date} = sort(unique(crsp.date))
  sort!(crsp,[:permno,:date])
  sort!(event, [:permno, :date])

  validdateranges::Dict =Dict(crspdates[i]=> (crspdates[i-days], crspdates[i+days])
    for i ∈ (1+days):(length(crspdates)-days))

  #allocate space for the information we will get for the study
  event.begindate = Vector{Union{Missing,Date}}(missing, Nevent)
  event.enddate = Vector{Union{Missing,Date}}(missing, Nevent)
  event.tokeep=trues(Nevent)

  #index the dataframe rows
  eventidx::Dict{Int, SubDataFrame} = Dict{Int, SubDataFrame}(
    sevent.permno[1] => sevent for sevent ∈ groupby(event, :permno))

  scrsps::GroupedDataFrame = groupby(crsp, :permno)
  dateidx::Dict = Dict(d=>i for (i,d) ∈ enumerate(crspdates))

  #for each valid permno we have and each event for those permnos
  @mpar for i ∈ 1:length(scrsps)
    local scrsp::SubDataFrame = scrsps[i]
    for r::DataFrameRow ∈ eachrow(eventidx[scrsp.permno[1]])

      t₀::Date = r.date
      Nscrsp::Int = size(scrsp,1)

      #locate the appropriate entry, and beform first set of validity checks
      i₀::Int = searchsortedfirst(scrsp.date, t₀)
      #println("i₀: $i₀ Nscrsp: $Nscrsp")
      println("i₀: $i₀
        days: $days
        length(scrsp.date): $(length(scrsp.date))
        scrsp.date: $(scrsp.date[i₀])
        t₀: $t₀
      ")
      if ((i₀ - days < 1) || #also takes care of certain "not found" cases
        (i₀ + days > Nscrsp) ||
        (scrsp.date[i₀] ≠ t₀) ||
        (!haskey(validdateranges, t₀)))

        r.tokeep = false
        error("break")
        continue
      end

      #check that the range is complete
      (tₗ::Date,tₕ::Date) = validdateranges[t₀]
      if (tₗ ≠ scrsp.date[i₀-days]) || (tₗ ≠ scrsp.date[i₀+days])
        r.tokeep = false
        continue
      end

      #now copy the return info
      for (i::Int, f::Symbol) ∈ enumerate(dayfields)
        iₜ::Int = i₀ + (i - days)
        r[f] = scrsp.net[iₜ]
      end

    end
  end

  #drop the rows that missed the prior check
  event = event[event.tokeep, :]

  #drop row with incomplete returns
  event = event[completecases(event[:, dayfields]), :]

  return event
end

function formevent(;refresheventcrsp::Bool = true)
  bb::DataFrame = readbbseo()
  bb |> CSV.write("output\\cleanevent.csv")
  bb = formeventwindows(bb)
  println(size(bb))

end

max_stars_repo_name: clintonTE/CCA

max_issues_repo_name: clintonTE/CCA

max_forks_repo_name: clintonTE/CCA


text:
n = rand(1:5)

A = matrixdepot("rando", Int, n, 1)
B = matrixdepot("rando", Int, n, 2)
C = matrixdepot("rando", Int, n, 3)

for i in length(A)
    @test A[i] == 0 || A[i] == 1
end

for i in length(B)
    @test B[i] == -1 || B[i] == 1
end

for i in length(C)
    @test C[i] == -1 || C[i] == 0 || C[i] == 1
end

try
    matridepot("rando", 3, 3, 5)
catch ArgumentError
    println("rando: invalid k value")
end

θ = matrixdepot("rando", n)

println("'rando' passed test...")


text:
using Pkg
Pkg.status()

using Documenter
using ProgressiveHedging

makedocs(modules=[ProgressiveHedging],
         format=Documenter.HTML(prettyurls=haskey(ENV,"GITHUB_ACTIONS")),
         sitename="ProgressiveHedging.jl",
         authors="Jonathan Maack",
         pages=["Overview" => "index.md",
                "Examples" => map(s -> "examples/$(s)",
                                  sort(readdir(joinpath(@__DIR__, "src", "examples")))
                                  ),
                "Reference" => map(s -> "api/$(s)",
                                   sort(readdir(joinpath(@__DIR__, "src", "api")))
                                   ),
                ]
         )

deploydocs(repo = "github.com/NREL/ProgressiveHedging.jl.git")


text:
#=
Transforms.jl:

Author: Satyabrata pal (satyabrata.pal1@gmail.com)

Acknowledgements-
Original source -
    https://github.com/fastai/fastai2/blob/master/fastai2/data/transforms.py

Original documentation-
    https://github.com/fastai/fastai2/blob/master/nbs/05_data.transforms.ipynb

Helper functions for processing data and basic transforms
    Functions for getting, splitting, and labeling data,
    as well as generic transforms

Get, split, and label
    For most data source creation we need functions to get
    a list of items, split them in to train/valid sets, and
    label them.
=#
using Random
using MLDataUtils
using DataStructures
using DataFrames

include("transform.jl")

#TODO: ignore case while checking extesnions
function process_files(path::AbstractString,
                       files::AbstractArray,
                        extensions=nothing)
    #gets file as per an extension
      res = []
      extensions === nothing ? res = [joinpath(path, file)
                                    for file in files] :
                                      res = [joinpath(path, file) for file in files
                                                if any(map(extension->occursin(extension,file),extensions))]
      res
end

#todo: figure out what is teh role of the "folders" parameter in the original code
function get_files(path::AbstractString,
    extensions=nothing,
    recurse::Bool=true)

    if length(path) == 0
        error("A path must be provided")
    end

    #Get all the files in path with optional extensions, optionally with recurse, only in folders, if specified.
    res = AbstractString[]
    file_names = []

    if recurse
       for (root, dirs, files) in walkdir(path)
           for file in files
               push!(file_names, joinpath(root,file))
           end
       end
       res = process_files("", file_names, extensions)
    else
       files = [file for file in readdir(path, join=true) if isfile(file)]
       res = process_files(path, files, extensions)
    end
    res
end

#=
Curry function that will provide the arguments first and then
wait for the pathsuffix later

Example from - https://riptutorial.com/julia-lang/example/20261/implementing-currying

It's often useful to be able to create functions with customized behavior. fastai.
data generally uses functions named as CamelCase verbs ending in er to create these
functions. FileGetter is a simple example of such a function creator.
e.g. const filegetter= FileGetter("path",".csv")
filegetter("/test")
=#

function FileGetter(path, extensions=nothing, recurse=true)
    #Create `get_files` partial function that searches path suffix `suf`,
    #only in `folders`, if specified, and passes along args
     pathsuffix -> get_files(joinpath(path, pathsuffix),extensions, recurse)
end

#=
"Get image files in `path` recursively, only in `folders`, if specified."
Convienience function to get images with standard image extension
=#
function get_image_files(path, recurse=true, folders=nothing)
    res = []
    image_extensions=["tiff", "jpeg", "png", "gif", "jpg"]
    res = [file for file in get_files(path, image_extensions, recurse)]
    res
end

#=
Curry function that will provide the arguments first and then
wait for the pathsuffix later

Example from - https://riptutorial.com/julia-lang/example/20261/implementing-currying

e.g. const imagegetter= ImageGetter("path",".csv")
filegetter("/test")
=#
function ImageGetter(path, recurse=true, folders=nothing)
    "Create `get_image_files` partial function that searches path suffix `suf`
     and passes along `kwargs`, only in `folders`, if specified."
     pathsuffix -> get_image_files(joinpath(path, pathsuffix), recurse, folders)
end

#=
Helper for text files
=#
function get_text_files(path, recurse=true, folders=nothing)
    "Get text files in `path` recursively, only in `folders`, if specified."
    get_files(path, ".txt", recurse)
end

#=
Accessing items across tuples when a specific
index is provided.

Soft implementation of ItemGetter in the original source-
  https://github.com/fastai/fastai2/blob/master/fastai2/data/transforms.py

Helpful for collecting labels of inputs.
e.g. datatuple= [(5, 4), (4, 6)]
          ItemGetter(1)
          output-- (5,4)
=#
function ItemGetter(index::Integer, x)
   Tuple( (a->a[index]).(x))
end

#=Does it make sense to design somthing like this in Julia?
Accessing fields across tuples when a specific
index is provided.

implementation of AttrGetter in the original source-
  https://github.com/fastai/fastai2/blob/master/fastai2/data/transforms.py

=#
#=original code
class AttrGetter(ItemTransform):
    "Creates a proper transform that applies `attrgetter(nm)` (even on a tuple)"
    _retain = False
    def __init__(self, nm, default=None): store_attr(self, 'nm,default')
    def encodes(self, x): return getattr(x, self.nm, self.default)
=#

#=
Split
The next set of functions are used to split data into training and validation sets.
The functions return two lists - a list of indices or masks for each of training
and validation sets.

These APIs cloesly mimic the original code's APIs.

Functions from the MLDataUtils are leveraged here.
=#

#=Wrapper around the splitobs function from here -
http://mldatapatternjl.readthedocs.io/en/latest/documentation/datasubset.html#split

e.g. X = rand(2, 6)
     split = RandomSplitter()
     train, test = split(X)
     --julia> train
              2×4 SubArray{Float64,2,Array{Float64,2},Tuple{Colon,UnitRange{Int64}},true}:
               0.226582  0.933372  0.505208   0.0443222
               0.504629  0.522172  0.0997825  0.722906

       julia> test
       2×2 SubArray{Float64,2,Array{Float64,2},Tuple{Colon,UnitRange{Int64}},true}:
        0.812814  0.11202
        0.245457  0.000341996

=#
function RandomSplitter(valid_pct=0.2)
    datatable -> splitobs(datatable, at = valid_pct);
end

#=
Wrapper around stratifiedobs--
http://mldatapatternjl.readthedocs.io/en/latest/documentation/targets.html#stratified

Can be used for stratified partioning of data
=#

function TrainTestSplitter(data)
     (args...) -> stratifiedobs(data, args...)
end

function TrainTestSplitter(f,data)
    (args...) -> stratifiedobs(f,data, args...)
end

#=
Split `items` so that `val_idx` are in the validation set
and the others in the training set
=#
function IndexSplitter(items::AbstractArray, valid_idx::AbstractArray)
    train_idx= setdiff(SortedSet(items),SortedSet(valid_idx))
    collect(train_idx), collect(valid_idx)
end

#=
Return an array of indices of parent directories of files
e.g. grandparent_idxs(["/folder/train/test.png", "/folder/valid/test2.png"],
                      "train")
[1]
=#
#the bool array is exactly len of actual array * len of names
#have to find a way to find the true indices

#TODO: code can be much cleaner
function grandparent_idxs(items::AbstractArray, name::AbstractString)
    truthvalues = [occursin("$name", item) for item in items]
    idxs=findall(truthvalues)
    return [items[idx] for idx in idxs]
end
#TODO: code can be much cleaner
function grandparent_idxs(items::AbstractArray, names::Tuple)
    truths=[]
    for name in names
        truthvalues = []
        for item in items
            push!(truthvalues,occursin("/$name/", item))
        end
        push!(truths, truthvalues)
    end
    idxs=[idx for truth in truths for idx in findall(truth)]
    return [items[idx] for idx in idxs]
end

#=
Split `items` from the grand parent folder names (`train_name` and `valid_name`).
e.g. fnames -> GrandparentSplitter(train_name='train', valid_name='valid')
[]
=#
function GrandparentSplitter()
    train = items -> grandparent_idxs(items, "train")
    valid = items -> grandparent_idxs(items, "valid")
    train,valid
end

function GrandparentSplitter(train_name::AbstractString, valid_name::AbstractString)
    train = items -> grandparent_idxs(items, train_name)
    valid = items -> grandparent_idxs(items, valid_name)
    train,valid
end

function GrandparentSplitter(train_name::Tuple, valid_name::Tuple)
    train = items -> grandparent_idxs(items, train_name)
    valid = items -> grandparent_idxs(items, valid_name)
    train,valid
end

#=
do we need to port the below functions?
In juli acreating anonymous functions are easier than in python.
Keeping this in mind do we need a top level API to split indices
on basis of a fucntion output?

Similar question applies for the MaskSplitter function and FileSplitter.
=#
#= def FuncSplitter(func):
    "Split `items` by result of `func` (`True` for validation, `False` for training set)."
    def _inner(o, **kwargs):
        val_idx = mask2idxs(func(o_) for o_ in o)
        return IndexSplitter(val_idx)(o)
    return _inner

# export
def MaskSplitter(mask):
    "Split `items` depending on the value of `mask`."
    def _inner(o, **kwargs): return IndexSplitter(mask2idxs(mask))(o)
    return _inner

def FileSplitter(fname):
    "Split `items` depending on the value of `mask`."
    valid = Path(fname).read().split('\n')
    def _func(x): return x.name in valid
    def _inner(o, **kwargs): return FuncSplitter(_func)(o)
    return _inner
    =#

#=
"Split `items` (supposed to be a dataframe) by value in `col`"
e.g df = {'a': [0,1,2,3,4], 'b': [True,False,True,True,False]}
split = ColSplitter("b")
split(df)
[[2,5],[1,3,4]]
=#
function ColSplitter(;col=:is_valid)
    df -> IndexSplitter([DataFrames.row(collect(eachrow(df))[i])
                          for i in 1:size(df, 1)],
                          findall(df[col]))
end

function ColSplitter(col::Integer)
    df -> IndexSplitter([DataFrames.row(collect(eachrow(df))[i])
                            for i in 1:size(df, 1)],
                            findall(df[!, col]))
end

#= checking the bounds - =#
function assertBounds(num, lowerbound, upperbound)
    lowerbound<num<upperbound ? nothing : error("$num in
                                          $lowerbound:$upperbound")
end

#=
Take randoms subsets of `splits` with `train_sz` and `valid_sz`
e.g items= [1,2,3,4,5,6,7,8,9,10]
RandomSubsetSplitter(0.3,0.1)
=#

#= TODO: does anythng already exists in the ecosystem which does
something similar to this but in much more efficient way=#
function Splitter(items, train_sz, valid_sz)
    train_valid_len  = (convert(Int,round(length(items)*train_sz)),
                         convert(Int,round(length(items)*valid_sz)))
    idxs = shuffle!([i for i in 1:length(items)])
    idxs[1:train_valid_len[1]],idxs[train_valid_len[1]:train_valid_len[1]+
                       train_valid_len[2]]
end

function RandomSubsetSplitter(train_sz, valid_sz)
    assertBounds(train_sz, 0,1)
    assertBounds(valid_sz, 0,1)
    items -> Splitter(items, train_sz, valid_sz)
end

#=
Label -
 The final set of functions is used to label a single item of data.
=#

#=
"Label `item` with the parent folder name."
e.g. parent_label("fastai_dev/dev/data/mnist_tiny/train/3/9932.png"))
3
=#
function parent_label(path::AbstractString, args...)
    last(dirname(path))
end
#= Label `item` with regex `pat`.
e.g. pattern = RegexLabeller("fastai_dev/dev/data/mnist_tiny/train/3/9932.png")
     pattern("[0-9]+")
     '3'
=#
function RegexLabeller(pat)
    path -> strip(convert(String,(match(pat, "$path")).match), ['/', '/'])
end

#=
Read `cols` in `row` with potential `pref` and `suff`
cols can be a list of column names or a list of indices
(or a mix of both). If label_delim is passed, the result
 is split using it.
=#
function ColReader(col:: Symbol; pref:: AbstractString,
                                          suff:: AbstractString)
    prefix_infix = val -> pref*val*suff
    df -> prefix_infix.(df[!, col])
end

function ColReader(col:: Symbol, label_delim:: AbstractString)
    delim_split = val -> split(val, label_delim)
    df -> delim_split.(df[!, col])
end

function ColReader(cols:: Array; pref:: AbstractString,
                                     suff:: AbstractString)
    prefix_infix = val -> pref*val*suff
    df -> [[prefix_infix.(df[!, col][i])  for col in cols] for i in 1:nrow(df)]
end

function ColReader(col:: Integer; pref:: AbstractString,
                                       suff:: AbstractString)
    prefix_infix = val -> pref*val*suff
    df -> prefix_infix.(df[!, col])
end

function ColReader(col:: Symbol)
    df -> df[!, col]
end

function ColReader(col:: Integer)
    df -> df[!, col]
end

#=
Categorize-
  Collection of categories with the reverse mapping in `o2i`
  followthis to know more about this set of func--
  https://forums.fast.ai/t/fastai-v2-code-walk-thru-2/53978
  class CategoryMap(CollBase):
    def __init__(self, col, sort=True, add_na=False):
        if is_categorical_dtype(col): items = L(col.cat.categories)
        else:
            # `o==o` is the generalized definition of non-NaN used by Pandas
            items = L(o for o in L(col).unique() if o==o)
            if sort: items = items.sorted()
        self.items = '#na#' + items if add_na else items
        self.o2i = defaultdict(int, self.items.val2idx())
    def __eq__(self,b): return all_equal(b,self)
CategoryMap grabs all of the unique values in your column, optionally sort them,
and then optionally creates the object-to-int o2i.
=#
mutable struct CategoryMap
    items
    o2i
    CategoryMap(items, o2i)=new(items,o2i)
end

#=not sure at the moment how to preserve the order of CategoricalArray
as "levels" sorts the array and "levels!" requires the order of levels
tobe entered manually
TODO: need to preserve the order of o2i if add_na is true
=#
function CategoryMap(col; sort_Val=true, add_na=false, strict=false)
    if isa(col, CategoricalArray)
        if strict
            items = levels(droplevels!(col))
        else
            items = levels(col)
        end
    else
        if !allunique(col)
            items = skipmissing(unique!(col))
            if sort_Val
                items = sort!(col)
            end
        end
    end

    if add_na
        #items=(x -> "#na#"*x).(items)
        items=pushfirst!(items, "#na#")
    else
        items=items
    end

    o2i= Dict((item,findall(isequal(item),items)[1]) for item in items)
    CategoryMap(items,o2i)
end

#=
Categorize-
"Reversible transform of category string to `vocab` id"
original code - https://github.com/fastai/fastai2/blob/master/nbs/05_data.transforms.ipynb

Categorize derives from Transforms.
Following the explanation in this walkthrough
https://forums.fast.ai/t/fastai-v2-code-walk-thru-2/53978
A Transform implements the following methods -

setup(transform::T, items, train_setup)
encodesl(transform::T, func, values, split_idx, vargs...)
decodes(transform::T, func, x, vargs...)
=#
#=TODO: The categorize family of classes in the original code sets
a defaultloss_func,order,store_attrs. Iamnot sure what this does.
=#
mutable struct Categorize <:Transform
    vocab
    reverseMap
    Categorize(vocab, reverseMap) = new(vocab, reverseMap)
end

#user can use Categorize alone
#in such case both the transforms and
#mapped dict will be recieved
function Categorize(cols::Array{String};
            sort_Val=true,
            add_na=false,
            strict=false)
    map = CategoryMap(cols, sort_Val=sort_Val, add_na=add_na, strict=strict)
    Categorize(map.items, map.o2i)
end

#user can use only encode to access just transform
function encode(obj::Categorize)
    encode(obj.vocab)
end

function decode(obj::Categorize, item::String)
    map = obj.reverseMap
    decode(map[item])
end

function decode(obj::Categorize, item::Integer)
    map = obj.reverseMap
    category=""
    for (key,val) in map
        if val == item
            category=key
        end
    end
    decode(category)
end


text:
"""
Apply fourier operator v ← op * u
"""
function apply_operator!(op::Matrix{CT}, u::Union{Matrix{CT},SharedArray{CT,2}}, v::Union{Matrix{CT},SharedArray{CT,2}}) where {CT}
    v .= op .* u
end

"""
Apply fourier operator v[i] ← op[i] * u for i in 1:length(op)
"""
function apply_operator!(op::Vector{Matrix{CT}}, u::Union{Matrix{CT},SharedArray{CT,2}}, v::Union{Vector{Matrix{CT}},Vector{SharedArray{CT,2}}}) where {CT}
    for k in 1:length(op)
        v[k] .= op[k] .* u
    end
end

"""
Apply fourier operator v ← sum_i op[i] * u[i]
"""
function apply_operator!(op::Vector{Matrix{CT}}, u::Union{Vector{Matrix{CT}},Vector{SharedArray{CT,2}}}, v::Union{Matrix{CT},SharedArray{CT,2}}) where {CT}
    @assert length(op) == length(u)
    fill!(v, 0)
    for k in 1:length(op)
        v .+= op[k] .* u[k]
    end
end

"""
Returns gradient operator
"""
function get_gradient(ft::FourierTransform{ℳ,𝒩,RT,CT}) where {ℳ,𝒩,RT,CT}
    D₁ = zeros(CT, ℳ, 𝒩)
    D₂ = zeros(CT, ℳ, 𝒩)

    for s in 1:𝒩
        for r in 1:ℳ
            D₁[r,s] = 1im * ft.m[r]
            D₂[r,s] = 1im * ft.n[s]
        end
    end

    [D₁, D₂]
end

"""
Returns inverse Laplacian operator
"""
function get_inverse_laplacian(ft::FourierTransform{ℳ,𝒩,RT,CT}; sign=+1) where {ℳ,𝒩,RT,CT}
    Δ⁻¹ = zeros(CT, ℳ, 𝒩)

    for s in 1:𝒩
        for r in 1:ℳ
            if !(r == 1 && s == 1)
                Δ⁻¹[r,s] = - sign / (ft.m[r]^2 + ft.n[s]^2)
            end
        end
    end

    Δ⁻¹
end


text:
function Base.show(io::IO,c::CoTangent)
	show(io,c,0)
end
function Base.show{F,T}(io::IO,c::Call{F,T},n::Int)
	for i in 1:n
		print(io,"  ")
	end
	println(io,"Call $(F) $(val(c)|>with_size)")
	for a in c.args
		show(io,a,n+1)
	end
end
function Base.show{T}(io::IO,c::Lift{T},n::Int)
	for i in 1:n
		print(io,"  ")
	end
	println(io,"Lift $(val(c)|>with_size)")
	for a in c.args
		show(io,a,n+1)
	end
end
function Base.show{T}(io::IO,x::Variable{T},n::Int)
	for i in 1:n
		print(io,"  ")
	end
	println(io,"Variable $(val(x)|>with_size)")
end

function Base.show(io::IO,x,n::Int)
	for i in 1:n
		print(io,"  ")
	end
	println(io,"Constant $(x|>with_size)")
end

function with_size{T}(x::T)
	"$(T)"
end
function with_size(x::Real)
	"$(x)"
end
function with_size{T}(x::Array{T})
	"$(T)$(size(x))"
end


text:
module RGlasso

export glasso

function glasso(S::Matrix, rho::Float64; rcmd="R")
    writedlm("/tmp/RGlasso_tmp_matrix.txt", S)

    # start R and tell it to run glasso with a given rho value
    rcode = "library(glasso);" *
            "S = as.matrix(read.table('/tmp/RGlasso_tmp_matrix.txt', header=FALSE));" *
            "out = glasso(S, $rho);" *
            "write.table(out\$wi, '/tmp/RGlasso_tmp_matrix.txt', row.names=FALSE, col.names=FALSE)"
    run(pipeline(`$rcmd -q -e $rcode`, stdout=DevNull))

    w = readdlm("/tmp/RGlasso_tmp_matrix.txt")
    rm("/tmp/RGlasso_tmp_matrix.txt")
    w
end

end # module


text:
#  Copyright 2016, Iain Dunning, Joey Huchette, Miles Lubin, and contributors
#  This Source Code Form is subject to the terms of the Mozilla Public
#  License, v. 2.0. If a copy of the MPL was not distributed with this
#  file, You can obtain one at http://mozilla.org/MPL/2.0/.
#############################################################################
# JuMP
# An algebraic modelling langauge for Julia
# See http://github.com/JuliaOpt/JuMP.jl
#############################################################################
# test/solvers.jl
# Detect and load solvers
# Should be run as part of runtests.jl
#############################################################################

function try_import(name::Symbol)
    try
        @eval import $name
        return true
    catch e
        return false
    end
end

# Load available solvers
grb = try_import(:Gurobi)
cpx = try_import(:CPLEX)
mos = try_import(:Mosek)
cbc = try_import(:Cbc)
if cbc; import Clp; end
glp = try_import(:GLPKMathProgInterface)
ipt = try_import(:Ipopt)
nlo = try_import(:NLopt)
kni = try_import(:KNITRO)
eco = try_import(:ECOS)
osl = try_import(:CoinOptServices)
scs = try_import(:SCS)
nlw = try_import(:AmplNLWriter)

# Create solver lists
# LP solvers
lp_solvers = Any[]
grb && push!(lp_solvers, Gurobi.GurobiSolver(OutputFlag=0))
cpx && push!(lp_solvers, CPLEX.CplexSolver(CPX_PARAM_SCRIND=0))
mos && push!(lp_solvers, Mosek.MosekSolver(LOG=0))
cbc && push!(lp_solvers, Clp.ClpSolver())
glp && push!(lp_solvers, GLPKMathProgInterface.GLPKSolverLP())
ipt && push!(lp_solvers, Ipopt.IpoptSolver(print_level=0))
eco && push!(lp_solvers, ECOS.ECOSSolver(verbose=false))
osl && push!(lp_solvers, CoinOptServices.OsilSolver())
scs && push!(lp_solvers, SCS.SCSSolver(eps=1e-6,verbose=0))
# MILP solvers
ip_solvers = Any[]
grb && push!(ip_solvers, Gurobi.GurobiSolver(OutputFlag=0))
cpx && push!(ip_solvers, CPLEX.CplexSolver(CPX_PARAM_SCRIND=0))
mos && push!(ip_solvers, Mosek.MosekSolver(LOG=0))
cbc && push!(ip_solvers, Cbc.CbcSolver(logLevel=0))
glp && push!(ip_solvers, GLPKMathProgInterface.GLPKSolverMIP())
osl && push!(ip_solvers, CoinOptServices.OsilSolver())
# Support semi-continuous, semi-integer solvers
semi_solvers = Any[]
grb && push!(semi_solvers, Gurobi.GurobiSolver(OutputFlag=0))
cpx && push!(semi_solvers, CPLEX.CplexSolver(CPX_PARAM_SCRIND=0))
# SOS solvers
sos_solvers = Any[]
grb && push!(sos_solvers, Gurobi.GurobiSolver(OutputFlag=0))
cpx && push!(sos_solvers, CPLEX.CplexSolver(CPX_PARAM_SCRIND=0))
cbc && push!(sos_solvers, Cbc.CbcSolver())
# Conic solvers with duals
conic_solvers_with_duals = Any[]
eco && push!(conic_solvers_with_duals, ECOS.ECOSSolver(verbose=false))
scs && push!(conic_solvers_with_duals, SCS.SCSSolver(eps=1e-6,verbose=0))
mos && push!(conic_solvers_with_duals, Mosek.MosekSolver(LOG=0))
# Callback solvers
lazy_solvers, lazylocal_solvers, cut_solvers, cutlocal_solvers, heur_solvers, info_solvers = Any[], Any[], Any[], Any[], Any[], Any[]
if grb
    push!(lazy_solvers, Gurobi.GurobiSolver(OutputFlag=0, Presolve=0))
    push!( cut_solvers, Gurobi.GurobiSolver(PreCrush=1, Cuts=0, Presolve=0, Heuristics=0.0, OutputFlag=0))
    push!(heur_solvers, Gurobi.GurobiSolver(Cuts=0, Presolve=0, Heuristics=0.0, OutputFlag=0))
    # push!(heur_solvers, Gurobi.GurobiSolver(Heuristics=0.0, OutputFlag=0))
    push!(info_solvers, Gurobi.GurobiSolver(OutputFlag=0))
end
if cpx
    push!(lazy_solvers, CPLEX.CplexSolver(CPX_PARAM_PRELINEAR=0, CPX_PARAM_PREIND=0, CPX_PARAM_ADVIND=0, CPX_PARAM_MIPSEARCH=1,CPX_PARAM_MIPCBREDLP=0,CPX_PARAM_SCRIND=0))
    push!(lazylocal_solvers, CPLEX.CplexSolver(CPX_PARAM_PRELINEAR=0, CPX_PARAM_PREIND=0, CPX_PARAM_ADVIND=0, CPX_PARAM_MIPSEARCH=1,CPX_PARAM_MIPCBREDLP=0,CPX_PARAM_SCRIND=0, CPX_PARAM_FRACCUTS=-1, CPX_PARAM_EACHCUTLIM=0, CPX_PARAM_HEURFREQ=-1))
    push!( cut_solvers, CPLEX.CplexSolver(CPX_PARAM_PRELINEAR=0, CPX_PARAM_PREIND=0, CPX_PARAM_ADVIND=0, CPX_PARAM_MIPSEARCH=1,CPX_PARAM_MIPCBREDLP=0,CPX_PARAM_SCRIND=0))
    push!(cutlocal_solvers, CPLEX.CplexSolver(CPX_PARAM_PRELINEAR=0, CPX_PARAM_PREIND=0, CPX_PARAM_ADVIND=0, CPX_PARAM_MIPSEARCH=1,CPX_PARAM_MIPCBREDLP=0,CPX_PARAM_SCRIND=0, CPX_PARAM_FRACCUTS=-1, CPX_PARAM_EACHCUTLIM=0, CPX_PARAM_HEURFREQ=-1))
    push!(heur_solvers, CPLEX.CplexSolver(CPX_PARAM_PRELINEAR=0, CPX_PARAM_PREIND=0, CPX_PARAM_ADVIND=0, CPX_PARAM_MIPSEARCH=1,CPX_PARAM_MIPCBREDLP=0,CPX_PARAM_SCRIND=0))
    push!(info_solvers, CPLEX.CplexSolver(CPX_PARAM_PRELINEAR=0, CPX_PARAM_PREIND=0, CPX_PARAM_ADVIND=0, CPX_PARAM_MIPSEARCH=1,CPX_PARAM_MIPCBREDLP=0,CPX_PARAM_SCRIND=0))
end
if glp
    push!(lazy_solvers, GLPKMathProgInterface.GLPKSolverMIP())
    push!( cut_solvers, GLPKMathProgInterface.GLPKSolverMIP())
    push!(heur_solvers, GLPKMathProgInterface.GLPKSolverMIP())
    push!(info_solvers, GLPKMathProgInterface.GLPKSolverMIP())
end
# Quadratic support
quad_solvers = Any[]
grb && push!(quad_solvers, Gurobi.GurobiSolver(QCPDual=1,OutputFlag=0))
cpx && push!(quad_solvers, CPLEX.CplexSolver(CPX_PARAM_SCRIND=0))
mos && push!(quad_solvers, Mosek.MosekSolver(LOG=0))
quad_mip_solvers = copy(quad_solvers)
osl && push!(quad_solvers, CoinOptServices.OsilSolver(CoinOptServices.OSOption("sb","yes",solver="ipopt")))
soc_solvers = copy(quad_solvers)
ipt && push!(quad_solvers, Ipopt.IpoptSolver(print_level=0))
eco && push!(soc_solvers, ECOS.ECOSSolver(verbose=false))
scs && push!(soc_solvers, SCS.SCSSolver(eps=1e-6,verbose=0))
osl && push!(quad_mip_solvers, CoinOptServices.OsilBonminSolver(CoinOptServices.OSOption("sb","yes",category="ipopt")))
osl && push!(quad_mip_solvers, CoinOptServices.OsilCouenneSolver())
rsoc_solvers = Any[]
mos && push!(rsoc_solvers, Mosek.MosekSolver(LOG=0))
grb && push!(rsoc_solvers, Gurobi.GurobiSolver(QCPDual=1,OutputFlag=0))
cpx && push!(rsoc_solvers, CPLEX.CplexSolver(CPX_PARAM_SCRIND=0))
# Nonlinear solvers
nlp_solvers = Any[]
ipt && push!(nlp_solvers, Ipopt.IpoptSolver(print_level=0))
nlo && push!(nlp_solvers, NLopt.NLoptSolver(algorithm=:LD_SLSQP))
kni && push!(nlp_solvers, KNITRO.KnitroSolver(objrange=1e16,outlev=0))
osl && push!(nlp_solvers, CoinOptServices.OsilSolver(CoinOptServices.OSOption("sb","yes",solver="ipopt")))
nlw && osl && push!(nlp_solvers, AmplNLWriter.BonminNLSolver(["bonmin.nlp_log_level=0"; "bonmin.bb_log_level=0"]))
convex_nlp_solvers = copy(nlp_solvers)
mos && push!(convex_nlp_solvers, Mosek.MosekSolver(LOG=0))
# Mixed-Integer Nonlinear solvers
minlp_solvers = Any[]
kni && push!(minlp_solvers, KNITRO.KnitroSolver(outlev=0))
osl && push!(minlp_solvers, CoinOptServices.OsilBonminSolver(CoinOptServices.OSOption("sb","yes",category="ipopt")))
osl && push!(minlp_solvers, CoinOptServices.OsilCouenneSolver())
nlw && osl && push!(minlp_solvers, AmplNLWriter.BonminNLSolver(["bonmin.nlp_log_level=0"; "bonmin.bb_log_level=0"]))
nlw && osl && push!(minlp_solvers, AmplNLWriter.CouenneNLSolver())
# Semidefinite solvers
sdp_solvers = Any[]
mos && push!(sdp_solvers, Mosek.MosekSolver(LOG=0))
scs && push!(sdp_solvers, SCS.SCSSolver(eps=1e-6,verbose=0))

const error_map = Dict()
grb && (error_map[Gurobi.GurobiSolver] = Gurobi.GurobiError)
cpx && (error_map[CPLEX.CplexSolver] = CPLEX.CplexError)


text:
# smc_plots.jl
#
# Creates plots for the sequential Monte-Carlo algorithm

import PWS
using PWS: ConditionalEnsemble, gene_expression_system, marginal_configuration, MarginalEnsemble, SMCEstimate, chemotaxis_system, generate_configuration
using Plots

system = gene_expression_system(dtimes=0:0.1:5.0)
conf = generate_configuration(system)

cond_ens = ConditionalEnsemble(system)
marg_ens = MarginalEnsemble(system)

algorithm = SMCEstimate(256)

particles = []
PWS.simulate(algorithm, conf, marg_ens; inspect=x -> push!(particles, x), new_particle=PWS.JumpParticleSlow)

function ancestors(particle)
    if particle.parent !== nothing
        list = ancestors(particle.parent)
        push!(list, particle)
        list
    else
        list = [particle]
    end
end

p = Plots.plot()
Plots.plot!(p, conf.s_traj.t, getindex.(conf.s_traj.u, 1), seriestype=:steppre)
# plot!(conf.r_traj.t, getindex.(conf.r_traj.u, 1) ./ 10000)
# plot!(conf.r_traj.t, getindex.(conf.r_traj.u, 2) ./ 10000)
Plots.plot!(conf.x_traj.t, getindex.(conf.x_traj.u, 1))
for ptcl in particles[1]
    # u_vals = hcat(Vector.(getfield.(ancestors(ptcl), :u))...)
    # u_vals ./= [40, 10000, 10000]
    u_vals = hcat(Vector.(getfield.(ancestors(ptcl), :u))...)
    Plots.plot!(p, system.dtimes[2:end], transpose(u_vals), color=:black, legend=false, linewidth=0.1)
end
plot!(p, ylim=(0.40, 0.60))
plot!(p, conf.x_traj)
p

plot()
for ptcl in particles[1]
    plot!(getfield.(ancestors(ptcl), :weight))
end
plot!()

getfield.(ancestors(particles[1][1]), :u)
getfield.(ancestors(particles[1][2]), :u)

system.dtimes


text:
module H5PLEXOS

import Dates: DateTime, DateFormat, format
import HDF5
import HDF5: attributes, create_group, create_dataset, datatype, h5open
import PLEXOSUtils: PLEXOSCollection, PLEXOSMembership, PLEXOSProperty,
                    PLEXOSSample, PLEXOSKeyIndex, PLEXOSSolutionDataset,
                    plexostables, open_plexoszip

export process

const H5PLEXOS_VERSION = "v0.6.2"

include("process.jl")
include("utils.jl")

end # module


text:
using NetCDF, Plots, Printf

sub_directory = "/Geostrophic_Start_20"
filename = pwd() * sub_directory * "_middepth.nc"
ncinfo(filename)
x = Array(NetCDF.open(filename, "xC"))
y = Array(NetCDF.open(filename, "yC"))
z = Array(NetCDF.open(filename, "zC"))
t = Array(NetCDF.open(filename, "time"))
sim_day = t ./ 86400
z = (z[2:end] + z[1:end-1]) / 2
b = NetCDF.open(filename, "b")
u = NetCDF.open(filename, "u")
v = NetCDF.open(filename, "v")
w = NetCDF.open(filename, "w")
##
sti = 150 # starting time index
cmax = maximum(Array(b[2:end-1,2:end-1, 1, sti:end]))
cmin = minimum(Array(b[:,:, 1, sti:end]))
clims = (cmin, cmax)
anim = @animate for i in sti:1:length(b[1, 1, 1, :])
    b_array = Array(b[:, :, 1, i])
    # p1 = contourf(y, z, b_array, fill = true, linewidth = 0, color = :ocean, clim = (-0.0013871555898403098, -3.3776441214941526e-6))
    day_label = @sprintf("%.2f ", sim_day[i])
    p1 = contourf(x, y, b_array',
    color = :ocean, title = "Buoyancy at Middepth at day " * day_label ,
     xlabel = "Meridional [m]", ylabel = "Depth [m]"
     , clims = clims)
end
gif(anim, filename *".gif", fps = 15)
##
filename = pwd() * sub_directory * "_zonal_average.nc"
ncinfo(filename)
y = Array(NetCDF.open(filename, "yC"))
z = Array(NetCDF.open(filename, "zC"))
b = NetCDF.open(filename, "Bz")
u = NetCDF.open(filename, "Uz")
t = Array(NetCDF.open(filename, "time"))
sim_day = t ./ 86400
cmax = maximum(Array(b[2:end-1, 2:end-1, 1:1:end]))
cmin = minimum(Array(b[2:end-1, 2:end-1, 1:1:end]))
clims = (cmin, cmax)
anim = @animate for i in 1:1:length(b[ 1, 1, :])
    b_array = Array(b[:, :, i])
    day_label = @sprintf("%.2f ", sim_day[i])
    p1 = contourf(y, z, b_array',
        color = :ocean, title = "Zonal Average Buoyancy at day " * day_label ,
        xlabel = "Meridional [m]", ylabel = "Depth [m]"
        , clims = clims)
end
gif(anim, filename * ".gif", fps = 15)
##
i = length(b[ 1, 1, :])
u_array = Array(u[:, :, i])
day_label = @sprintf("%.2f ", sim_day[i])
p1 = contourf(y, z, u_array',
color = :ocean, title = "Zonal Average Zonal Velocity at day " * day_label ,
        xlabel = "Meridional [m]", ylabel = "Depth [m]")

##
i = length(b[1, 1, :])
b_array = Array(b[:, :, i])
cmax = maximum(b_array)
cmin = minimum(b_array)
clims = (cmin, cmax)
day_label = @sprintf("%.2f ", sim_day[i])
p1 = contourf(y, z, b_array',
        color = :ocean, title = "Zonal Average Buoyancy at day " * day_label ,
        xlabel = "Meridional [m]", ylabel = "Depth [m]"
        , clims = clims)
plot(p1)
##
filename = pwd() * sub_directory * "_surface.nc"
ncinfo(filename)
y = Array(NetCDF.open(filename, "yC"))
x = Array(NetCDF.open(filename, "xC"))
b = NetCDF.open(filename, "b")
t = Array(NetCDF.open(filename, "time"))
sim_day = t ./ 86400
start_time = 1
skip = 1
end_time = 180
cmax = maximum(Array(b[2:end-1, 2:end-1, 1, start_time:skip:end_time]))
cmin = minimum(Array(b[2:end-1, 2:end-1, 1, start_time:skip:end_time]))
clims = (cmin, cmax)
anim = @animate for i in start_time:end_time
    b_array = Array(b[:, :,1, i])
    day_label = @sprintf("%.2f ", sim_day[i])
    p1 = contourf(x, y, b_array',
        color = :thermometer, title = "Buoyancy at 50 [m] on day " * day_label ,
        xlabel = "Zonal [m]", ylabel = "Meridional [m]"
        , clims = clims, linewidth = 0)
end
gif(anim, filename * ".gif", fps = 15)
##
filename = pwd() *  "/Windstress_Convection_4_meridional.nc"
ncinfo(filename)
x = Array(NetCDF.open(filename, "yC"))
y = Array(NetCDF.open(filename, "yC"))
z = Array(NetCDF.open(filename, "zC"))
t = Array(NetCDF.open(filename, "time"))
sim_day = t ./ 86400
# z = (z[2:end] + z[1:end-1]) / 2
b = NetCDF.open(filename, "b")
u = NetCDF.open(filename, "u")
v = NetCDF.open(filename, "v")
w = NetCDF.open(filename, "w")
Δz = z[2:end] - z[1:end-1]
Δx = x[2:end] - x[1:end-1]
Δy = y[2:end] - y[1:end-1]
a = abs.(w[1, 1, 2:end-1, 1] ./ (Δz))
a2 = abs.(w[1, 1:end-1, 16, 1] ./ (Δx))
b = abs.(u[1, 1:end-1, 1, 1] ./ (Δy))
c = abs.(v[1, 2:end-1, 1, 1] ./ (Δy))

##
filename = pwd() *  "/Windstress_Convection_4_checkpoint_iteration4851612.jld2"
ncinfo(filename)

max_stars_repo_name: sandreza/Mesoscale

max_issues_repo_name: sandreza/Mesoscale

max_forks_repo_name: sandreza/Mesoscale


text:
@testset "Continuous Linear" begin
    mock = MOIU.MockOptimizer(ModelForMock{Float64}())
    config = MOIT.TestConfig()
    config_no_lhs_modif = MOIT.TestConfig(modify_lhs = false)

    function set_mock_optimize_linear1Test!(mock)
         MOIU.set_mock_optimize!(mock,
             (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1, 0],
                  (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64})    => [-1]),
             (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1, 0],
                  (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64})    => [-1]),
             (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 0, 1],
                  (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64})    => [-2]),
             (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [-1, 0, 2]),
             (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1, 0, 0]),
             (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [2, 0, 0]),
             (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 2, 0]),
             (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1, 1, 0],
                  (MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64})     => [-1.5],
                  (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [0.5]))
    end
    set_mock_optimize_linear1Test!(mock)
    MOIT.linear1test(mock, config)
    set_mock_optimize_linear1Test!(mock)
    MOIT.linear1test(mock, config_no_lhs_modif)
    MOIU.set_mock_optimize!(mock,
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1, 0],
             (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64})    => [-1]))
    MOIT.linear2test(mock, config)
    MOIU.set_mock_optimize!(mock,
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [3]),
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0]))
    MOIT.linear3test(mock, config)
    MOIU.set_mock_optimize!(mock,
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 0]),
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, 0]),
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, -100]))
    MOIT.linear4test(mock, config)
    function set_mock_optimize_linear5Test!(mock)
         MOIU.set_mock_optimize!(mock,
             (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [4/3, 4/3]),
             (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [2, 0]),
             (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [4, 0]),
             (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [2]))
    end
    set_mock_optimize_linear5Test!(mock)
    MOIT.linear5test(mock, config)
    set_mock_optimize_linear5Test!(mock)
    MOIT.linear5test(mock, config_no_lhs_modif)
    MOIU.set_mock_optimize!(mock,
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 0]),
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, 0]),
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, -100]))
    MOIT.linear6test(mock, config)
    function set_mock_optimize_linear7Test!(mock)
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 0]),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, 0]),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, -100]))
    end
    set_mock_optimize_linear7Test!(mock)
    MOIT.linear7test(mock, config)
    set_mock_optimize_linear7Test!(mock)
    MOIT.linear7test(mock, config_no_lhs_modif)
    MOIU.set_mock_optimize!(mock,
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, tuple(),
             (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-1]))
    MOIT.linear8atest(mock, config)
    MOIU.set_mock_optimize!(mock,
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, MOI.InfeasibleNoResult))
    MOIT.linear8atest(mock, MOIT.TestConfig(infeas_certificates=false))
    MOIU.set_mock_optimize!(mock,
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, MOI.InfeasibilityCertificate))
    MOIT.linear8btest(mock, config)
    MOIU.set_mock_optimize!(mock,
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, MOI.UnboundedNoResult))
    MOIT.linear8btest(mock, MOIT.TestConfig(infeas_certificates=false))
    MOIU.set_mock_optimize!(mock,
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, (MOI.InfeasibilityCertificate, [1, 1])))
    MOIT.linear8ctest(mock, config)
    MOIU.set_mock_optimize!(mock,
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, MOI.UnboundedNoResult))
    MOIT.linear8ctest(mock, MOIT.TestConfig(infeas_certificates=false))
    MOIU.set_mock_optimize!(mock,
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [650/11, 400/11]))
    MOIT.linear9test(mock, config)
    MOIU.set_mock_optimize!(mock,
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [5.0, 5.0],
              (MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64})    => [-1]),
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [2.5, 2.5],
              (MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64})    => [1]),
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1.0, 1.0]),
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [6.0, 6.0]))
    MOIT.linear10test(mock, config)
    MOIU.set_mock_optimize!(mock,
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1.0, 1.0]),
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0.5, 0.5]))
    MOIT.linear11test(mock, config)
    MOIU.set_mock_optimize!(mock,
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, tuple(),
              (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64})    => [-1, -1]))
    MOIT.linear12test(mock, config)
    MOIU.set_mock_optimize!(mock,
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, MOI.InfeasibleNoResult))
    MOIT.linear12test(mock, MOIT.TestConfig(infeas_certificates=false))
    MOIU.set_mock_optimize!(mock,
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1/5, 1/5],
             (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [0],
             (MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64})     => [0]))
    MOIT.linear13test(mock, config)
    MOIU.set_mock_optimize!(mock,
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 1/2, 1],
             (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64})    => [-1],
             (MOI.SingleVariable, MOI.GreaterThan{Float64})                => [2, 0, 0],
             (MOI.SingleVariable, MOI.LessThan{Float64})                   => [-2]),
         (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1],
             (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64})    => [-1],
             (MOI.SingleVariable, MOI.GreaterThan{Float64})                => [0]))
    # linear14 has double variable bounds for the z variable
    mock.eval_variable_constraint_dual = false
    MOIT.linear14test(mock, config)
    mock.eval_variable_constraint_dual = true
    MOIU.set_mock_optimize!(mock,
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0.0],
             (MOI.VectorAffineFunction{Float64}, MOI.Zeros) => [0.0, 0.0]))
    MOIT.linear15test(mock, config)
end