text:
using Oceananigans.Fields: XFaceField, YFaceField, ZFaceField, CenterField
using Oceananigans.BuoyancyModels: BuoyancyField

has_buoyancy_tracer(model) = :b ∈ keys(model.tracers)

"""
    horizontally_averaged_velocities(model)

Returns a dictionary in which `:u` represents the horizontal average of
`model.velocities.u` and `:v` represents the horizontal average of
`model.velocities.v`.
"""
function horizontally_averaged_velocities(model)

    u, v, w = model.velocities

    averages = Dict(
                    :u => Field(Average(u, dims=(1, 2))),
                    :v => Field(Average(v, dims=(1, 2)))
                   )

    return averages
end

"""
    horizontally_averaged_tracers(model)

Returns a dictionary containing horizontal averages of
every tracer in `model.tracers`. The dictionary keys
correspond to the names of the tracer.
"""
function horizontally_averaged_tracers(model)

    averages = Dict()

    for tracer in keys(model.tracers)
        c = getproperty(model.tracers, tracer)
        averages[tracer] = Field(Average(c, dims=(1, 2)))
    end

    return averages
end

"""
    velocity_covariances(model; u_scratch = XFaceField(model.grid),
                                v_scratch = YFaceField(model.grid),
                                w_scratch = ZFaceField(model.grid),
                                c_scratch = CenterField(model.grid))

Returns a dictionary containing horizontal averages of the velocity covariances uᵢuⱼ.

The scratch fields `u_scratch`, `v_scratch`, `w_scratch` and `c_scratch` specify
scratch space for computations at `u`, `v`, `w`, and tracer ("`c`") locations, respectively.
"""
function velocity_covariances(model; u_scratch = XFaceField(model.grid),
                                     v_scratch = YFaceField(model.grid),
                                     w_scratch = ZFaceField(model.grid),
                                     c_scratch = CenterField(model.grid))

    u, v, w = model.velocities

    covariances = Dict(
                       :uu => Field(Average(u * u, dims=(1, 2))),
                       :vv => Field(Average(v * v, dims=(1, 2))),
                       :ww => Field(Average(w * w, dims=(1, 2))),
                       :uv => Field(Average(u * v, dims=(1, 2))),
                       :wv => Field(Average(w * v, dims=(1, 2))),
                       :wu => Field(Average(w * u, dims=(1, 2)))
                       )

    return covariances
end

"""
    tracer_covariances(model; b = BuoyancyField(model),
                              u_scratch = XFaceField(model.grid),
                              v_scratch = YFaceField(model.grid),
                              w_scratch = ZFaceField(model.grid),
                              c_scratch = CenterField(model.grid))

Returns a dictionary containing horizontal averages of
tracer variance, tracer-velocity covariances, and tracer-buoyancy covariance.

The scratch fields `u_scratch`, `v_scratch`, `w_scratch` and `c_scratch` specify
scratch space for computations at `u`, `v`, `w`, and tracer ("`c`") locations, respectively.

`b` is the `BuoyancyField(model)` for model. If `b` is not specified, new memory is allocated to
store the computation of buoyancy in three-dimensions over `model.grid`.
"""
function tracer_covariances(model; b = BuoyancyField(model),
                                   u_scratch = XFaceField(model.grid),
                                   v_scratch = YFaceField(model.grid),
                                   w_scratch = ZFaceField(model.grid),
                                   c_scratch = CenterField(model.grid))

    u, v, w = model.velocities

    covariances = Dict()

    for tracer in keys(model.tracers)
        c = getproperty(model.tracers, tracer)

        # Keys
        cc = Symbol(tracer, tracer)
        uc = Symbol(:u, tracer)
        vc = Symbol(:v, tracer)
        wc = Symbol(:w, tracer)

        covariances[cc] = Field(Average(c * c, dims=(1, 2)))
        covariances[uc] = Field(Average(u * c, dims=(1, 2)))
        covariances[vc] = Field(Average(v * c, dims=(1, 2)))
        covariances[wc] = Field(Average(w * c, dims=(1, 2)))

        # Add covariance of tracer with buoyancy
        if tracer != :b && !has_buoyancy_tracer(model)
            bc = Symbol(:b, tracer)
            covariances[bc] = Field(Average(b * c, dims=(1, 2)))
        end
    end

    return covariances
end

"""
    third_order_velocity_statistics(model, u_scratch = XFaceField(model.grid),
                                           v_scratch = YFaceField(model.grid),
                                           w_scratch = ZFaceField(model.grid),
                                           c_scratch = CenterField(model.grid),
                                           p = model.pressures.pHY′ + model.pressures.pNHS)

Returns a dictionary of functions that calculate horizontally-averaged third-order statistics
that involve the velocity field. Includes statistics associated with pressure.

The scratch fields `u_scratch`, `v_scratch`, `w_scratch` and `c_scratch` specify
scratch space for computations at `u`, `v`, `w`, and tracer ("`c`") locations, respectively.
"""
function third_order_velocity_statistics(model; u_scratch = XFaceField(model.grid),
                                                v_scratch = YFaceField(model.grid),
                                                w_scratch = ZFaceField(model.grid),
                                                c_scratch = CenterField(model.grid),
                                                p = model.pressures.pHY′ + model.pressures.pNHS)

    u, v, w = model.velocities

    # Pressure-strain terms
    Σˣʸ = 0.5 * (∂y(u) + ∂x(v)) # FFC
    Σˣᶻ = 0.5 * (∂z(u) + ∂x(w)) # FCF
    Σʸᶻ = 0.5 * (∂z(v) + ∂y(w)) # CFF

    third_order_statistics = Dict(
                                  :uuu => Field(Average(u * u * u, dims=(1, 2))),
                                  :uuv => Field(Average(u * u * v, dims=(1, 2))),
                                  :uuw => Field(Average(u * u * w, dims=(1, 2))),
                                  :uvv => Field(Average(u * v * v, dims=(1, 2))),
                                  :uww => Field(Average(u * w * w, dims=(1, 2))),

                                  :vvv => Field(Average(v * v * v, dims=(1, 2))),
                                  :vvw => Field(Average(v * v * w, dims=(1, 2))),
                                  :vww => Field(Average(v * w * w, dims=(1, 2))),

                                  :www => Field(Average(w * w * w, dims=(1, 2))),
                                  :wvu => Field(Average(w * v * u, dims=(1, 2))),

                                   :up => Field(Average(u * p,     dims=(1, 2))),
                                   :vp => Field(Average(v * p,     dims=(1, 2))),
                                   :wp => Field(Average(w * p,     dims=(1, 2))),

                                  :pux => Field(Average(p * ∂x(u), dims=(1, 2))),
                                  :puy => Field(Average(p * ∂y(u), dims=(1, 2))),
                                  :puz => Field(Average(p * ∂z(u), dims=(1, 2))),

                                  :pvx => Field(Average(p * ∂x(v), dims=(1, 2))),
                                  :pvy => Field(Average(p * ∂y(v), dims=(1, 2))),
                                  :pvz => Field(Average(p * ∂z(v), dims=(1, 2))),

                                  :pwx => Field(Average(p * ∂x(w), dims=(1, 2))),
                                  :pwy => Field(Average(p * ∂y(w), dims=(1, 2))),
                                  :pwz => Field(Average(p * ∂z(w), dims=(1, 2))),
                                 )

    return third_order_statistics
end

"""
    third_order_tracer_statistics(model; u_scratch = XFaceField(model.grid),
                                         v_scratch = YFaceField(model.grid),
                                         w_scratch = ZFaceField(model.grid),
                                         c_scratch = CenterField(model.grid))

Returns a dictionary of functions that calculate horizontally-averaged third-order statistics
that involve tracers.

The scratch fields `u_scratch`, `v_scratch`, `w_scratch` and `c_scratch` specify
scratch space for computations at `u`, `v`, `w`, and tracer ("`c`") locations, respectively.
"""
function third_order_tracer_statistics(model; u_scratch = XFaceField(model.grid),
                                              v_scratch = YFaceField(model.grid),
                                              w_scratch = ZFaceField(model.grid),
                                              c_scratch = CenterField(model.grid),
                                              p = model.pressures.pHY′ + model.pressures.pNHS)

    u, v, w = model.velocities

    third_order_statistics = Dict()

    for tracer in keys(model.tracers)
        c = getproperty(model.tracers, tracer)

        # Keys
        wcc = Symbol(:w, tracer, tracer)
        cwu = Symbol(tracer, :wu)
        cpx = Symbol(tracer, :px)
        cpy = Symbol(tracer, :py)
        cpz = Symbol(tracer, :pz)

        third_order_statistics[wcc] = Field(Average(w * c * c, dims=(1, 2)))
        third_order_statistics[cwu] = Field(Average(c * w * u, dims=(1, 2)))
        third_order_statistics[cpx] = Field(Average(c * ∂x(p), dims=(1, 2)))
        third_order_statistics[cpy] = Field(Average(c * ∂y(p), dims=(1, 2)))
        third_order_statistics[cpz] = Field(Average(c * ∂z(p), dims=(1, 2)))
    end

    return third_order_statistics
end

function first_order_statistics(model; b = BuoyancyField(model),
                                       u_scratch = XFaceField(model.grid),
                                       v_scratch = YFaceField(model.grid),
                                       w_scratch = ZFaceField(model.grid),
                                       c_scratch = CenterField(model.grid),
                                       p = model.pressures.pHY′ + model.pressures.pNHS)

    output = merge(
                   horizontally_averaged_velocities(model),
                   horizontally_averaged_tracers(model),
                   )

    output[:p] = Field(Average(p, dims=(1, 2)))

    if !has_buoyancy_tracer(model)
        output[:b] = Field(Average(b, dims=(1, 2)))
    end

    return output
end

function second_order_statistics(model; b = BuoyancyField(model),
                                        u_scratch = XFaceField(model.grid),
                                        v_scratch = YFaceField(model.grid),
                                        w_scratch = ZFaceField(model.grid),
                                        c_scratch = CenterField(model.grid))

    output = merge(
                   velocity_covariances(model, u_scratch = u_scratch,
                                               v_scratch = v_scratch,
                                               w_scratch = w_scratch,
                                               c_scratch = c_scratch),

                   tracer_covariances(model, b = b,
                                             u_scratch = u_scratch,
                                             v_scratch = v_scratch,
                                             w_scratch = w_scratch,
                                             c_scratch = c_scratch)

                  )

    if !has_buoyancy_tracer(model)
        u, v, w = model.velocities

        output[:ub] = Field(Average(u * b, dims=(1, 2)))
        output[:vb] = Field(Average(v * b, dims=(1, 2)))
        output[:wb] = Field(Average(w * b, dims=(1, 2)))
    end

    return output
end

function third_order_statistics(model; u_scratch = XFaceField(model.grid),
                                       v_scratch = YFaceField(model.grid),
                                       w_scratch = ZFaceField(model.grid),
                                       c_scratch = CenterField(model.grid),
                                       p = model.pressures.pHY′ + model.pressures.pNHS)

    output = merge(
                   third_order_velocity_statistics(model, p = p,
                                                   u_scratch = u_scratch,
                                                   v_scratch = v_scratch,
                                                   w_scratch = w_scratch,
                                                   c_scratch = c_scratch),

                   third_order_tracer_statistics(model, p = p,
                                                 u_scratch = u_scratch,
                                                 v_scratch = v_scratch,
                                                 w_scratch = w_scratch,
                                                 c_scratch = c_scratch)
                   )

    return output
end

function first_through_second_order(model; b = BuoyancyField(model),
                                           u_scratch = XFaceField(model.grid),
                                           v_scratch = YFaceField(model.grid),
                                           w_scratch = ZFaceField(model.grid),
                                           c_scratch = CenterField(model.grid),
                                           p = model.pressures.pHY′ + model.pressures.pNHS)

    output = merge(
                   first_order_statistics(model, b = b, p = p,
                                          u_scratch = u_scratch,
                                          v_scratch = v_scratch,
                                          w_scratch = w_scratch,
                                          c_scratch = c_scratch),

                   second_order_statistics(model,
                                           u_scratch = u_scratch,
                                           v_scratch = v_scratch,
                                           w_scratch = w_scratch,
                                           c_scratch = c_scratch,
                                                   b = b),

                  )

    return output
end

function first_through_third_order(model; b = BuoyancyField(model),
                                          u_scratch = XFaceField(model.grid),
                                          v_scratch = YFaceField(model.grid),
                                          w_scratch = ZFaceField(model.grid),
                                          c_scratch = CenterField(model.grid),
                                          p = model.pressures.pHY′ + model.pressures.pNHS)

    output = merge(
                   first_order_statistics(model, b = b, p = p,
                                          u_scratch = u_scratch,
                                          v_scratch = v_scratch,
                                          w_scratch = w_scratch,
                                          c_scratch = c_scratch),

                   second_order_statistics(model,
                                           u_scratch = u_scratch,
                                           v_scratch = v_scratch,
                                           w_scratch = w_scratch,
                                           c_scratch = c_scratch,
                                                   b = b),

                   third_order_statistics(model, p = p,
                                          u_scratch = u_scratch,
                                          v_scratch = v_scratch,
                                          w_scratch = w_scratch,
                                          c_scratch = c_scratch)

                  )

    return output
end

max_stars_repo_name: ali-ramadhan/LESbrary

max_issues_repo_name: ali-ramadhan/LESbrary

max_forks_repo_name: ali-ramadhan/LESbrary


text:
__precompile__
module TestPackage

# package code goes here

global const val = 42

function myfunc0()
  println("a = ", 42)
end

function myfunc(a::Int)
  println("a = ", a)
end

function myfunc2(a::Int, b::Int)
  return a + b
end

function myfunc3(a, b)
  return a + b
end

function myfunc4{Tsol}(a::AbstractArray, b::AbstractArray{Tsol})
  println("a = \n", a)
  println("b = \n", b)

  return nothing
end

end # module

ext: jl


text:
"""
    module Simulate_FallingBall1

Models and simulates a sphere that is falling downwards along the y-axis (constrained via
a prismatic joint), without collision handling.

See also models [`Simulate_FallingBall2`](@ref) (falling ball with collision handling).
"""
module Test_Prismatic_yAxis

using  Modia3D
import Modia3D.ModiaMath

@assembly FallingBall(;h=1.0) begin
   world  = Object3D()
   sphere = Object3D( Modia3D.Solid(Modia3D.SolidSphere(0.1), "Aluminium") )

   # Constrain sphere movement (initial placement at position [0,h,0])
   prismatic = Modia3D.Prismatic(world, sphere, axis=2, s_start=h)
end

fallBall = FallingBall(h=3.5, sceneOptions=Modia3D.SceneOptions(visualizeFrames=true, defaultFrameLength=0.3))
simulationModel = Modia3D.SimulationModel( fallBall, stopTime=1.0 )
result          = ModiaMath.simulate!(simulationModel)
ModiaMath.plot(result, ("prismatic.s", "prismatic.v"))

println("... success of Test_Prismatic_yAxis.jl!")

end


text:
# ---
# title: 1537. Get the Maximum Score
# id: problem1537
# author: Tian Jun
# date: 2020-10-31
# difficulty: Hard
# categories: Dynamic Programming
# link: <https://leetcode.com/problems/get-the-maximum-score/description/>
# hidden: true
# ---
#
# You are given two **sorted** arrays of distinct integers `nums1` and `nums2.`
#
# A **valid ** __** path** is defined as follows:
#
#   * Choose array nums1 or nums2 to traverse (from index-0).
#   * Traverse the current array from left to right.
#   * If you are reading any value that is present in `nums1` and `nums2` you are allowed to change your path to the other array. (Only one repeated value is considered in the valid path).
#
# _Score_ is defined as the sum of uniques values in a valid path.
#
# Return the maximum _score_ you can obtain of all possible  **valid  paths**.
#
# Since the answer may be too large, return it modulo 10^9 + 7.
#
#
#
# **Example 1:**
#
# **![](https://assets.leetcode.com/uploads/2020/07/16/sample_1_1893.png)**
#
#
#
#     Input: nums1 = [2,4,5,8,10], nums2 = [4,6,8,9]
#     Output: 30
#     Explanation:  Valid paths:
#     [2,4,5,8,10], [2,4,5,8,9], [2,4,6,8,9], [2,4,6,8,10],  (starting from nums1)
#     [4,6,8,9], [4,5,8,10], [4,5,8,9], [4,6,8,10]    (starting from nums2)
#     The maximum is obtained with the path in green **[2,4,6,8,10]**.
#
#
# **Example 2:**
#
#
#
#     Input: nums1 = [1,3,5,7,9], nums2 = [3,5,100]
#     Output: 109
#     Explanation:  Maximum sum is obtained with the path **[1,3,5,100]**.
#
#
# **Example 3:**
#
#
#
#     Input: nums1 = [1,2,3,4,5], nums2 = [6,7,8,9,10]
#     Output: 40
#     Explanation:  There are no common elements between nums1 and nums2.
#     Maximum sum is obtained with the path [6,7,8,9,10].
#
#
# **Example 4:**
#
#
#
#     Input: nums1 = [1,4,5,8,9,11,19], nums2 = [2,3,4,11,12]
#     Output: 61
#
#
#
#
# **Constraints:**
#
#   * `1 <= nums1.length <= 10^5`
#   * `1 <= nums2.length <= 10^5`
#   * `1 <= nums1[i], nums2[i] <= 10^7`
#   * `nums1` and `nums2` are strictly increasing.
#
#
## @lc code=start
using LeetCode

## add your code here:
## @lc code=end


text:
export instruct!

"""
    instruct!(state, operator[, locs, control_locs, control_configs, theta])

instruction implementation for applying an operator to a quantum state.

This operator will be overloaded for different operator or state with
different types.
"""
function instruct! end

# empty gates
YaoBase.instruct!(state::AbstractVecOrMat, ::Any,
    locs::Tuple{}, control_locs::NTuple{N1, Int}=(),
    control_configs::NTuple{N2, Int}=()) where {N1, N2} = state


text:
module SpatialDatasets

    """
    SpatialDatasets
    A Julia package containing popular spatial datasets for spatial data analysis.
    [SpatialDatasets repository](https://github.com/javierbarbero/SpatialDatasets.jl).
    """

    using LazyArtifacts
    using DataFrames
    using Shapefile

    export sdataset

    include("sdataset.jl")

end


text:
 rk001,ck001=kpsimpleprover("kpdata/kp001.cnf",3,5)
 rk002,ck002=kpsimpleprover("kpdata/kp002.cnf",2,2)
 rk003,ck003=kpsimpleprover("kpdata/kp003.cnf",5,5)
 rk004,ck004=kpsimpleprover("kpdata/kp004.cnf",5,5)
 rk005,ck005=kpsimpleprover("kpdata/kp005.cnf",5,5)
 rk006,ck006=kpsimpleprover("kpdata/kp006.cnf",5,5)

 rkj001,ckj001=kpsimpleprover("kpdata/kpjp001.cnf",3,5)
 rkj002,ckj002=kpsimpleprover("kpdata/kpjp002.cnf",3,5)

max_stars_repo_name: sazare/cheapViews

max_issues_repo_name: sazare/cheapViews

max_forks_repo_name: sazare/cheapViews


text:
#md ---
#md layout: post
#md title: "Numerize me!"
#md date: 2019-01-01 00:00:00 +0000
#md categories: blog
#md mathjax: true
#md ---

# # Numerize me!

# >This post is the first tentative post on programming with Julia language. The focus is not on programming, or coding, instead it is on the *mathematical modelling* that drastically leverage nowadays on computer resources.

# A typical problem in *data science* is **identifying correlations**.

# To find an example to understand the importance of pseudo-causality (correlation) we can use the case study *when it rains shops sell more*. Clearly you cannot control weather but at least by knowling the such a correlation you know how much to buy in rain seasons.
# Sometimes variables are stored in the computer with a human readable approach, e.g. for weather conditions we can use the strings *rain* *sun* *cloudy*, while a more cryptic approach would be to use integer numbers such as 0 1 2. Strings are the best choice when dealing with data-frames with lots of variables since we do not have to memorize the meaning of integer numbers for different columns. However, computers cannot handle strings and for most commands require to have data-frames of numbers only. It is thus left to the user to adjust data to be handled by analysis functions.

# In this blog post I'd like to show you how to replace a *strings column* with *numeric values* in a *Julia data-frame*.

# Let's create a very simple, examplar example, data-frame to play with,
using DataFrames

df = DataFrame(weather=String[],selling=Float64[])
push!(df,["rain",100.])
push!(df,["rain",200.])
push!(df,["sun",300.])

# The created data-frame looks like \
# index | `weather` | `selling` |
# --- | --- | --- |
# 1 | rain | 100 |
# 2 | rain | 200 |
# 3 | sun | 300 |

# this data-frame contains only two columns `weather` and `selling`, the first column is a string-column that cannot be accepted for example by the Julia **corrplot** stats plot.
# We want simply to substitute rain=1 and sun=2, while this is a simple operation with the simple data-frame created the operation become more cumbersome when playing with big-data.
# In order to solve this code requirements we proceed as follow,

# step | `action`|
#  --- | --- |
# 1    | list the values that appear in column `weather` |
# ->   | listing=[rain,sun], cardinality=2 |
# 2    | assign 1 to rain, 2 to sun |
# ->   | creating a vector **v** of integer values from 1 to the length of the vector [rain,sun], v=[1,2] |
# 3    | loop over each `weather` column entry, for each value find the corresponding position in listing and substitute the listing argument position value |
# ->   | v=[1,1,2] |
# 4    | include the new vector to the data-frame, or create a new data-frame with the new numeric column |

# The above procedure is summarised in these few Julia lines,
listing = unique(df[:weather])              # listing = ["rain","sun"]
value   = collect(1:length(listing))        # value   = [1,2]
v       = Float64[]                         # v       = [ ]
for element in df[:weather]
    p=findall(x -> x==element,listing)      # sun  > p = 2
    append!(v,value[p])                     # value[p] = 2
    println(p,element)                      # printing---
end
df[:weather_num] = v                        # add the column to data-frame

# The new dataframe now looks like,
# index | `weather` | `selling` | `weather_num` |
# --- | --- | --- | --- |
# 1 | rain | 100 | 1 |
# 2 | rain | 200 | 1 |
# 3 | sun | 300 | 2 |

# With the new numerical column we can use the corrplot command,
using StatPlots
@df correlation_plot = df corrplot([:weather_num :selling], grid = false)
cd("C:\\Users\\a.marocchino\\Documents\\codes\\github.io\\_img\\001_dataframe_string_removal")
savefig(".\\001_dataframe_string_removal_01.png")
# that for the given data-set is pretty pretty meanigless
# ![Julia corrplot](IMAGEFOLDER/001_dataframe_string_removal_01.png)

cd("C:\\Users\\a.marocchino\\Documents\\codes\\github.io")                                                                #src
using Literate                                                                                #src
# preprocess for notebooks                                                                                #src
function setimagefolder(content)                                                                                #src
    content = replace(content, "IMAGEFOLDER" => "$IMAGEFOLDER")                                                           #src
    return content                                                                                #src
end                                                                                #src
# for Jupyter notebook, put images in subfolder                                                                           #src
IMAGEFOLDER = "_img\\001_dataframe_string_removal"                                                                        #src
Literate.notebook("_source\\001_dataframe_string_removal.jl", "notebooks", preprocess = setimagefolder)                   #src
# for Markdown/Jekyll notebook, put images in "/images"                                                                   #src
IMAGEFOLDER = "/_img/001_dataframe_string_removal"                                                                         #src
Literate.markdown("_source\\001_dataframe_string_removal.jl", ".", name="_posts\\dataframe_string_removal",               #src
 preprocess = setimagefolder,                                                                                #src
 documenter=false)                                                                                #src


text:
module LESUtils

import NCDatasets
import ..ReferenceModels: ReferenceModel
import TurbulenceConvection
const TC = TurbulenceConvection
using ..HelperFuncs

export get_les_names, get_cfsite_les_dir, find_alias, get_path_to_artifact

"""
    get_LES_library

Hierarchical dictionary of available LES simulations described in [Shen2022](@cite).
The following cfsites are available across listed models, months,
and experiments.
"""
function get_LES_library()
    LES_library = Dict("HadGEM2-A" => Dict(), "CNRM-CM5" => Dict(), "CNRM-CM6-1" => Dict())
    Shen_et_al_sites = collect(2:15)
    append!(Shen_et_al_sites, collect(17:23))
    Shen_et_al_deep_convection_sites = (collect(30:33)..., collect(66:70)..., 82, 92, 94, 96, 99, 100)
    append!(Shen_et_al_sites, Shen_et_al_deep_convection_sites)

    LES_library["HadGEM2-A"]["10"] = Dict()
    LES_library["HadGEM2-A"]["10"]["cfsite_numbers"] = setdiff(Shen_et_al_sites, [94, 100])
    LES_library["HadGEM2-A"]["07"] = Dict()
    LES_library["HadGEM2-A"]["07"]["cfsite_numbers"] = Shen_et_al_sites
    LES_library["HadGEM2-A"]["04"] = Dict()
    LES_library["HadGEM2-A"]["04"]["cfsite_numbers"] = setdiff(Shen_et_al_sites, [15, 17, 18, 32, 92, 94])
    LES_library["HadGEM2-A"]["01"] = Dict()
    LES_library["HadGEM2-A"]["01"]["cfsite_numbers"] = setdiff(Shen_et_al_sites, [15, 17, 18, 19, 20])

    for month in ["01", "04", "07", "10"]
        LES_library["HadGEM2-A"][month]["experiments"] = ["amip", "amip4K"]
    end
    return LES_library
end

"""
    get_les_names(y_names::Vector{String}, filename::String)
    get_les_names(m::ReferenceModel, filename::String)

Returns the aliases of the variables actually present in the nc
file (`filename`) corresponding to SCM variables `y_names`.
"""
get_les_names(m::ReferenceModel, filename::String)::Vector{String} = get_les_names(m.y_names, filename)
function get_les_names(y_names::Vector{String}, filename::String)::Vector{String}
    dict = TC.name_aliases()
    y_alias_groups = [haskey(dict, var) ? (dict[var]..., var) : (var,) for var in y_names]
    return [find_alias(aliases, filename) for aliases in y_alias_groups]
end

"""
    find_alias(aliases::Tuple{Vararg{String}}, filename::String)

Finds the alias present in an NCDataset from a list of possible aliases.
"""
function find_alias(aliases::Tuple{Vararg{String}}, filename::String)
    NCDatasets.NCDataset(filename) do ds
        for alias in aliases
            if haskey(ds, alias)
                return alias
            else
                for group_option in ["profiles", "reference", "timeseries"]
                    haskey(ds.group, group_option) || continue
                    if haskey(ds.group[group_option], alias)
                        return alias
                    end
                end
            end
        end
        error("None of the aliases $aliases found in the dataset $filename.")
    end
end

"""
    get_cfsite_les_dir(
        cfsite_number::Integer;
        forcing_model::String = "HadGEM2-A",
        month::Integer = 7,
        experiment::String = "amip",)

Given information about an LES run from [Shen2022](@cite),
fetch LES directory on central cluster.

Inputs:

 - cfsite_number  :: cfsite number
 - forcing_model :: {"HadGEM2-A", "CNRM-CM5", "CNRM-CM6-1", "IPSL-CM6A-LR"} - name of climate model used for forcing. Currently, only "HadGEM2-A" simulations are available reliably.
 - month :: {1, 4, 7, 10} - month of simulation.
 - experiment :: {"amip", "amip4K"} - experiment from which LES was forced.

Outputs:

 - les_dir - path to les simulation containing stats folder
"""
function get_cfsite_les_dir(
    cfsite_number::Integer;
    forcing_model::String = "HadGEM2-A",
    month::Integer = 7,
    experiment::String = "amip",
)
    month = string(month, pad = 2)
    try
        LES_library = get_LES_library()
        @assert forcing_model in keys(LES_library)
        @assert String(month) in keys(LES_library[forcing_model])
        @assert cfsite_number in LES_library[forcing_model][month]["cfsite_numbers"]
        @assert experiment in LES_library[forcing_model][month]["experiments"]
    catch e
        @error "The requested cfsite LES does not exist."
        throw(e)
    end
    cfsite_number = string(cfsite_number)
    root_dir = "/central/groups/esm/zhaoyi/GCMForcedLES/cfsite/$month/$forcing_model/$experiment/"
    rel_dir = join(["Output.cfsite$cfsite_number", forcing_model, experiment, "2004-2008.$month.4x"], "_")
    return joinpath(root_dir, rel_dir)
end

include("artifact_funcs.jl")

end # module


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

mutable struct ImageProperties <: SwaggerModel
    sourceVirtualMachine::Any # spec type: Union{ Nothing, SubResource } # spec name: sourceVirtualMachine
    storageProfile::Any # spec type: Union{ Nothing, ImageStorageProfile } # spec name: storageProfile
    provisioningState::Any # spec type: Union{ Nothing, String } # spec name: provisioningState
    hyperVGeneration::Any # spec type: Union{ Nothing, HyperVGenerationType } # spec name: hyperVGeneration

    function ImageProperties(;sourceVirtualMachine=nothing, storageProfile=nothing, provisioningState=nothing, hyperVGeneration=nothing)
        o = new()
        validate_property(ImageProperties, Symbol("sourceVirtualMachine"), sourceVirtualMachine)
        setfield!(o, Symbol("sourceVirtualMachine"), sourceVirtualMachine)
        validate_property(ImageProperties, Symbol("storageProfile"), storageProfile)
        setfield!(o, Symbol("storageProfile"), storageProfile)
        validate_property(ImageProperties, Symbol("provisioningState"), provisioningState)
        setfield!(o, Symbol("provisioningState"), provisioningState)
        validate_property(ImageProperties, Symbol("hyperVGeneration"), hyperVGeneration)
        setfield!(o, Symbol("hyperVGeneration"), hyperVGeneration)
        o
    end
end # type ImageProperties

const _property_map_ImageProperties = Dict{Symbol,Symbol}(Symbol("sourceVirtualMachine")=>Symbol("sourceVirtualMachine"), Symbol("storageProfile")=>Symbol("storageProfile"), Symbol("provisioningState")=>Symbol("provisioningState"), Symbol("hyperVGeneration")=>Symbol("hyperVGeneration"))
const _property_types_ImageProperties = Dict{Symbol,String}(Symbol("sourceVirtualMachine")=>"SubResource", Symbol("storageProfile")=>"ImageStorageProfile", Symbol("provisioningState")=>"String", Symbol("hyperVGeneration")=>"HyperVGenerationType")
Base.propertynames(::Type{ ImageProperties }) = collect(keys(_property_map_ImageProperties))
Swagger.property_type(::Type{ ImageProperties }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_ImageProperties[name]))}
Swagger.field_name(::Type{ ImageProperties }, property_name::Symbol) =  _property_map_ImageProperties[property_name]

function check_required(o::ImageProperties)
    true
end

function validate_property(::Type{ ImageProperties }, name::Symbol, val)
end


text:
#   Copyright 2022 Velexi Corporation
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

"""
Unit tests for the methods in `jlcoverage/cli.jl`.
"""

# --- Imports

# Standard library
using Logging: Logging
using Test

# External packages
using Coverage: Coverage
using Suppressor

# Local modules
using TestTools.jlcoverage: cli
using TestTools.jltest: EnhancedTestSet

# --- Tests

@testset EnhancedTestSet "jlcoverage.cli.parse_args()" begin

    # --- Default arguments

    raw_args = Vector{String}()
    args = cli.parse_args(; raw_args=raw_args)
    expected_args = Dict(
        "verbose" => false, "version" => false, "paths" => Vector{String}()
    )
    @test args == expected_args

    # --- verbose

    # Case: raw_args = "--verbose"
    raw_args = ["--verbose"]
    args = cli.parse_args(; raw_args=raw_args)
    expected_args = Dict("verbose" => true, "version" => false, "paths" => Vector{String}())
    @test args == expected_args

    # Case: raw_args = "-v"
    raw_args = ["-v"]
    args = cli.parse_args(; raw_args=raw_args)
    expected_args = Dict("verbose" => true, "version" => false, "paths" => Vector{String}())
    @test args == expected_args

    # --- version

    # Case: raw_args = "--version"
    raw_args = ["--version"]
    args = cli.parse_args(; raw_args=raw_args)
    expected_args = Dict("verbose" => false, "version" => true, "paths" => Vector{String}())
    @test args == expected_args

    # Case: raw_args = "-V"
    raw_args = ["-V"]
    args = cli.parse_args(; raw_args=raw_args)
    expected_args = Dict("verbose" => false, "version" => true, "paths" => Vector{String}())
    @test args == expected_args

    # --- paths

    # Case: normal usage
    raw_args = ["/path/to/file-1.jl", "/path/to/dir"]
    args = cli.parse_args(; raw_args=raw_args)
    expected_args = Dict("verbose" => false, "version" => false, "paths" => raw_args)
    @test args == expected_args

    # Case: `paths` contains "."
    raw_args = ["."]
    args = cli.parse_args(; raw_args=raw_args)
    expected_args = Dict("verbose" => false, "version" => false, "paths" => raw_args)
    @test args == expected_args

    # --- Mixed arguments

    # Case: normal usage
    raw_args = ["-v", "/path/to/file-1.jl", "/path/to/dir"]
    args = cli.parse_args(; raw_args=raw_args)
    expected_args = Dict("verbose" => true, "version" => false, "paths" => raw_args[2:3])
    @test args == expected_args
end

@testset EnhancedTestSet "jlcoverage.cli.run(): normal operation" begin

    # --- Preparations

    # Get current directory
    cwd = pwd()

    # Generate coverage data for TestPackage
    test_pkg_dir = joinpath(@__DIR__, "data", "TestPackage")
    cmd_options = `--startup-file=no --project=@. -O0`
    cmd = `julia $(cmd_options) -e 'import Pkg; Pkg.test(coverage=true)'`
    @suppress begin
        Base.run(Cmd(cmd; dir=test_pkg_dir); wait=true)
    end

    # --- Exercise functionality and check results

    # Case: `paths` contains a single directory, verbose=false
    cd(joinpath(test_pkg_dir))
    output = @capture_out begin
        cli.run([test_pkg_dir])
    end

    expected_output = """
-------------------------------------------------------------------------------
File                                  Lines of Code     Missed   Coverage
-------------------------------------------------------------------------------
$(joinpath("src", "TestPackage.jl"))                                1          0     100.0%
$(joinpath("src", "methods.jl"))                                    3          1      66.7%
$(joinpath("src", "more_methods.jl"))                               2          2       0.0%
$(joinpath("test", "runtests.jl"))                                  0          0        N/A
-------------------------------------------------------------------------------
TOTAL                                             6          3      50.0%
"""
    @test output == expected_output
    cd(cwd)  # Restore current directory

    # Case: `paths` contains a single directory, verbose=true
    # TODO: add test to check that log messages are generated
    cd(joinpath(test_pkg_dir))
    output = @capture_out begin
        cli.run([test_pkg_dir]; verbose=true)
    end

    expected_output = """
-------------------------------------------------------------------------------
File                                  Lines of Code     Missed   Coverage
-------------------------------------------------------------------------------
$(joinpath("src", "TestPackage.jl"))                                1          0     100.0%
$(joinpath("src", "methods.jl"))                                    3          1      66.7%
$(joinpath("src", "more_methods.jl"))                               2          2       0.0%
$(joinpath("test", "runtests.jl"))                                  0          0        N/A
-------------------------------------------------------------------------------
TOTAL                                             6          3      50.0%
"""
    @test output == expected_output
    cd(cwd)  # Restore current directory

    # Case: `paths` contains a file
    cd(joinpath(test_pkg_dir))
    src_file = joinpath(test_pkg_dir, "src", "methods.jl")
    output = @capture_out begin
        cli.run([src_file])
    end

    expected_output = """
-------------------------------------------------------------------------------
File                                  Lines of Code     Missed   Coverage
-------------------------------------------------------------------------------
$(joinpath("src", "methods.jl"))                                    3          1      66.7%
-------------------------------------------------------------------------------
TOTAL                                             3          1      66.7%
"""
    @test output == expected_output
    cd(cwd)  # Restore current directory

    # Case: `paths` is empty and current directory is a Julia package
    cd(test_pkg_dir)
    output = @capture_out begin
        cli.run([])
    end

    expected_output = """
-------------------------------------------------------------------------------
File                                  Lines of Code     Missed   Coverage
-------------------------------------------------------------------------------
$(joinpath("src", "TestPackage.jl"))                                1          0     100.0%
$(joinpath("src", "methods.jl"))                                    3          1      66.7%
$(joinpath("src", "more_methods.jl"))                               2          2       0.0%
-------------------------------------------------------------------------------
TOTAL                                             6          3      50.0%
"""
    @test output == expected_output
    cd(cwd)  # Restore current directory

    # Case: `paths` is empty and current directory is not a Julia package
    cd(joinpath(test_pkg_dir, "src"))
    output = @capture_out begin
        cli.run([])
    end
    expected_output = """
-------------------------------------------------------------------------------
File                                  Lines of Code     Missed   Coverage
-------------------------------------------------------------------------------
TestPackage.jl                                    1          0     100.0%
methods.jl                                        3          1      66.7%
more_methods.jl                                   2          2       0.0%
-------------------------------------------------------------------------------
TOTAL                                             6          3      50.0%
"""
    @test output == expected_output
    cd(cwd)  # Restore current directory

    # --- Clean up

    # Delete coverage data files
    @suppress begin
        Coverage.clean_folder(test_pkg_dir)
    end

    # Remove Manifest.toml
    rm(joinpath(test_pkg_dir, "Manifest.toml"); force=true)
end

@testset EnhancedTestSet "jlcoverage.cli.run(): error cases" begin

    # --- Exercise functionality and check results

    # Case: invalid `paths` argument
    @test_throws MethodError cli.run([1, 2, 3])

    # Case: `paths` contains an invalid path
    invalid_file = joinpath("path", "to", "invalid", "file")
    local output
    error = @capture_err begin
        output = @capture_out begin
            cli.run([invalid_file])
        end
    end
    expected_error = "┌ Warning: $(joinpath(pwd(), invalid_file)) not found. Skipping..."
    @test startswith(error, expected_error)

    expected_output = """
-------------------------------------------------------------------------------
File                                  Lines of Code     Missed   Coverage
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
TOTAL                                             0          0        N/A
"""
    @test output == expected_output
end

# Re-enable logging to avoid interfering with other unit tests.
#
# Note: setting the log level less than the log level for Logging.Debug ensures that
#       log messages at all levels are displayed
Logging.disable_logging(Logging.LogLevel(Logging.Debug.level - 1))