def test_HDC(reference_coordinates_HDC):
    def _power3(x, a=0.1000, b=1.489, c=0.1901):
        return a + b * x**c

    # A 3-parameter exponential function (a dependence function).
    def _exp3(x, a=0.0400, b=0.1748, c=-0.2243):
        return a + b * np.exp(c * x)

    bounds = [(0, None), (0, None), (None, None)]
    power3 = DependenceFunction(_power3, bounds)
    exp3 = DependenceFunction(_exp3, bounds)

    dist_description_0 = {
        "distribution": WeibullDistribution(alpha=2.776,
                                            beta=1.471,
                                            gamma=0.8888),
    }
    dist_description_1 = {
        "distribution": LogNormalDistribution(),
        "conditional_on": 0,
        "parameters": {
            "mu": power3,
            "sigma": exp3
        },
    }
    ghm = GlobalHierarchicalModel([dist_description_0, dist_description_1])

    alpha = calculate_alpha(3, 50)
    limits = [(0, 20), (0, 18)]
    deltas = [0.1, 0.1]
    my_contour = HighestDensityContour(ghm, alpha, limits, deltas)

    my_coordinates = my_contour.coordinates

    np.testing.assert_allclose(my_coordinates, reference_coordinates_HDC)
def test_IFORMContour(seastate_model):
    """
    Compare the coordinates of an IFORM contour with the results from Haselsteiner 
    et al. (2017; DOI: 10.1016/j.coastaleng.2017.03.002)
    """
    alpha = calculate_alpha(3, 25)
    my_contour = IFORMContour(seastate_model, alpha)

    my_coordinates = my_contour.coordinates
    np.testing.assert_allclose(max(my_coordinates[:, 0]), 15.23, atol=0.05)
    np.testing.assert_allclose(max(my_coordinates[:, 1]), 13.96, atol=0.05)
def test_ISORMContour(seastate_model):
    """
    Compare the coordinates of an ISORM contour with the results from Haselsteiner 
    et al. (2017; DOI: 10.1016/j.coastaleng.2017.03.002, Fig. 8). The shown
    308.8-year IFORM contour is the same as an 25-year IFORM contour.
    """
    alpha = calculate_alpha(3, 25)
    my_contour = ISORMContour(seastate_model, alpha)

    my_coordinates = my_contour.coordinates
    np.testing.assert_allclose(max(my_coordinates[:, 0]), 17.4, atol=0.1)
    np.testing.assert_allclose(max(my_coordinates[:, 1]), 14.9, atol=0.1)
def test_HighestDensityContour(seastate_model):
    """
    Compare the coordinates of a HD contour with the results from Haselsteiner 
    et al. (2017; DOI: 10.1016/j.coastaleng.2017.03.002, Fig. 5)
    """
    alpha = calculate_alpha(3, 25)
    limits = [(0, 20), (0, 18)]
    deltas = [0.05, 0.05]
    my_contour = HighestDensityContour(seastate_model, alpha, limits, deltas)

    my_coordinates = my_contour.coordinates
    np.testing.assert_allclose(max(my_coordinates[:, 0]), 16.79, atol=0.05)
    np.testing.assert_allclose(max(my_coordinates[:, 1]), 14.64, atol=0.05)
def test_ISORM(reference_coordinates_ISORM):

    # Logarithmic square function.
    def _lnsquare2(x, a=3.62, b=5.77):
        return np.log(a + b * np.sqrt(x / 9.81))

    # 3-parameter function that asymptotically decreases (a dependence function).
    def _asymdecrease3(x, a=0, b=0.324, c=0.404):
        return a + b / (1 + c * x)

    lnsquare2 = DependenceFunction(_lnsquare2)
    asymdecrease3 = DependenceFunction(_asymdecrease3)

    dist_description_0 = {
        "distribution":
        ExponentiatedWeibullDistribution(alpha=0.207, beta=0.684, delta=7.79),
    }

    dist_description_1 = {
        "distribution": LogNormalDistribution(),
        "conditional_on": 0,
        "parameters": {
            "mu": lnsquare2,
            "sigma": asymdecrease3
        },
    }

    ghm = GlobalHierarchicalModel([dist_description_0, dist_description_1])

    state_duration = 3
    return_period = 20
    alpha = calculate_alpha(state_duration, return_period)
    my_isorm = ISORMContour(ghm, alpha)

    my_coordinates = my_isorm.coordinates

    np.testing.assert_allclose(my_coordinates, reference_coordinates_ISORM)
def test_DirectSamplingContour(reference_data_DSContour):

    sample = reference_data_DSContour["sample"]
    ref_coordinates = reference_data_DSContour["ref_coordinates"]

    def _power3(x, a=0.1000, b=1.489, c=0.1901):
        return a + b * x**c

    # A 3-parameter exponential function (a dependence function).
    def _exp3(x, a=0.0400, b=0.1748, c=-0.2243):
        return a + b * np.exp(c * x)

    bounds = [(0, None), (0, None), (None, None)]
    power3 = DependenceFunction(_power3, bounds)
    exp3 = DependenceFunction(_exp3, bounds)

    dist_description_0 = {
        "distribution": WeibullDistribution(alpha=2.776,
                                            beta=1.471,
                                            gamma=0.8888),
    }
    dist_description_1 = {
        "distribution": LogNormalDistribution(),
        "conditional_on": 0,
        "parameters": {
            "mu": power3,
            "sigma": exp3
        },
    }
    ghm = GlobalHierarchicalModel([dist_description_0, dist_description_1])

    alpha = calculate_alpha(3, 50)
    my_ds_contour = DirectSamplingContour(ghm, alpha, sample=sample)

    my_coordinates = my_ds_contour.coordinates

    np.testing.assert_allclose(my_coordinates, ref_coordinates)
    plot_2D_isodensity,
    plot_dependence_functions,
    plot_marginal_quantiles,
)

# %% load data, prepare common variables

data = pd.read_csv("datasets/NDBC_buoy_46025.csv", sep=",")[["Hs", "T"]]

dist_descriptions, fit_descriptions, semantics = get_DNVGL_Hs_Tz()
ghm = GlobalHierarchicalModel(dist_descriptions)
ghm.fit(data, fit_descriptions=fit_descriptions)

state_duration = 3
return_period = 50
alpha = calculate_alpha(state_duration, return_period)
iform_contour = IFORMContour(ghm, alpha)

plt.close("all")
# %% plot_qq

axes = plot_marginal_quantiles(ghm, data, semantics=semantics)

# plt.show()

# %% plot_dependence_functions

par_rename = {"mu": r"$\mu$", "sigma": r"$\sigma$"}
axes = plot_dependence_functions(ghm,
                                 semantics=semantics,
                                 par_rename=par_rename)
def test_v_hs_hd_contour():
    """
    Use a wind speed - wave height dataset, fit the joint 
    distribution that was proposed by Haselsteiner et al. (2020)
    and compute a highest density contour. This test reproduces
    the results presented in Haselestiner et al. (2020). The
    coorindates are availble at https://github.com/ec-benchmark-organizers/
    ec-benchmark/blob/master/results/exercise-1/contribution-4/haselsteiner_
    andreas_dataset_d_50.txt

    Such a work flow is for example typical when generationg 
    a 50-year contour for DLC 1.6 in the offshore wind standard
    IEC 61400-3-1.

    Haselsteiner, A. F., Sander, A., Ohlendorf, J.-H., & Thoben, K.-D. (2020). 
    Global hierarchical models for wind and wave contours: Physical 
    interpretations of the dependence functions. Proc. 39th International 
    Conference on Ocean, Offshore and Arctic Engineering (OMAE 2020). 
    https://doi.org/10.1115/OMAE2020-18668

    International Electrotechnical Commission. (2019). Wind energy 
    generation systems - Part 3-1: Design requirements for fixed 
    offshore wind turbines (IEC 61400-3-1).
    """

    data = read_ec_benchmark_dataset("datasets/ec-benchmark_dataset_D.txt")

    def _logistics4(x, a=1, b=1, c=-1, d=1):
        return a + b / (1 + np.exp(c * (x - d)))

    def _alpha3(x, a, b, c, d_of_x):
        return (a + b * x**c) / 2.0445**(1 / d_of_x(x))

    logistics_bounds = [(0, None), (0, None), (None, 0), (0, None)]

    alpha_bounds = [(0, None), (0, None), (None, None)]

    beta_dep = DependenceFunction(_logistics4,
                                  logistics_bounds,
                                  weights=lambda x, y: y)
    alpha_dep = DependenceFunction(_alpha3,
                                   alpha_bounds,
                                   d_of_x=beta_dep,
                                   weights=lambda x, y: y)

    dist_description_v = {
        "distribution": ExponentiatedWeibullDistribution(),
        "intervals": WidthOfIntervalSlicer(width=2),
    }

    dist_description_hs = {
        "distribution": ExponentiatedWeibullDistribution(f_delta=5),
        "conditional_on": 0,
        "parameters": {
            "alpha": alpha_dep,
            "beta": beta_dep,
        },
    }

    model = GlobalHierarchicalModel([dist_description_v, dist_description_hs])

    fit_description_vs = {"method": "wlsq", "weights": "quadratic"}
    fit_description_hs = {"method": "wlsq", "weights": "quadratic"}

    model.fit(data, [fit_description_vs, fit_description_hs])

    axs = plot_marginal_quantiles(model, data)
    axs = plot_dependence_functions(model)
    ax = plot_2D_isodensity(model, data)

    alpha = calculate_alpha(1, 50)
    limits = [(0, 35), (0, 20)]
    contour = HighestDensityContour(model,
                                    alpha,
                                    limits=limits,
                                    deltas=[0.2, 0.2])

    coordinates = contour.coordinates
    np.testing.assert_allclose(max(coordinates[:, 0]), 29.9, atol=0.2)
    np.testing.assert_allclose(max(coordinates[:, 1]), 15.5, atol=0.2)
    np.testing.assert_allclose(min(coordinates[:, 0]), 0, atol=0.1)
    np.testing.assert_allclose(min(coordinates[:, 1]), 0, atol=0.1)

    ax = plot_2D_contour(contour, sample=data)
def test_hs_tz_iform_contour():
    """
    Use a sea state dataset with the variables Hs and Tz,
    fit the join distribution recommended in DNVGL-RP-C203 to 
    it and compute an IFORM contour. This tests reproduces
    the results published in Haseltseiner et al. (2019).

    Such a work flow is for example typical in ship design.

    Haselsteiner, A. F., Coe, R. G., Manuel, L., Nguyen, P. T. T., 
    Martin, N., & Eckert-Gallup, A. (2019). A benchmarking exercise 
    on estimating extreme environmental conditions: Methodology & 
    baseline results. Proc. 38th International Conference on Ocean, 
    Offshore and Arctic Engineering (OMAE 2019). 
    https://doi.org/10.1115/OMAE2019-96523
    
    DNV GL. (2017). Recommended practice DNVGL-RP-C205: 
    Environmental conditions and environmental loads.
    """

    data = read_ec_benchmark_dataset("datasets/ec-benchmark_dataset_A.txt")

    # A 3-parameter power function (a dependence function).
    def _power3(x, a, b, c):
        return a + b * x**c

    # A 3-parameter exponential function (a dependence function).
    def _exp3(x, a, b, c):
        return a + b * np.exp(c * x)

    bounds = [(0, None), (0, None), (None, None)]
    power3 = DependenceFunction(_power3, bounds)
    exp3 = DependenceFunction(_exp3, bounds)

    dist_description_0 = {
        "distribution": WeibullDistribution(),
        "intervals": WidthOfIntervalSlicer(width=0.5),
    }
    dist_description_1 = {
        "distribution": LogNormalDistribution(),
        "conditional_on": 0,
        "parameters": {
            "mu": power3,
            "sigma": exp3
        },
    }
    model = GlobalHierarchicalModel([dist_description_0, dist_description_1])
    model.fit(data)

    axs = plot_marginal_quantiles(model, data)
    axs = plot_dependence_functions(model)
    ax = plot_2D_isodensity(model, data)

    alpha = calculate_alpha(1, 20)
    contour = IFORMContour(model, alpha)

    coordinates = contour.coordinates
    np.testing.assert_allclose(max(coordinates[:, 0]), 5.0, atol=0.5)
    np.testing.assert_allclose(max(coordinates[:, 1]), 16.1, atol=0.5)

    ax = plot_2D_contour(contour, sample=data)
def test_DirectSamplingContour(seastate_model):
    """
    Computes a direct sampling contour and compares it with results
    from Huseby et al. (2013; DOI: 10.1016/j.oceaneng.2012.12.034, Tab. 5).
    """
    ref_contour_hs_1 = [
        9.99,
        10.65,
        10.99,
        11.25,
        11.25,
        11.41,
        11.42,
        11.46,
        11.48,
        11.54,
        11.57,
        11.56,
        11.58,
        11.59,
        11.59,
        11.60,
        11.60,
        11.59,
        11.59,
        11.56,
        11.53,
        11.46,
        11.26,
        10.88,
        7.44,
        2.05,
    ]
    ref_contour_tz_1 = [
        12.34,
        12.34,
        12.31,
        12.25,
        12.25,
        12.18,
        12.17,
        12.15,
        12.13,
        12.06,
        12.02,
        12.03,
        12.00,
        11.96,
        11.95,
        11.86,
        11.84,
        11.77,
        11.76,
        11.67,
        11.60,
        11.47,
        11.20,
        10.77,
        7.68,
        3.76,
    ]

    alpha = calculate_alpha(6, 1)

    prng = np.random.RandomState(42)  # Fix the random seed for consistency.
    # Because a random sample is drawn (and fixing the random seed with
    # .np.random.RandomState) does not work, results will be different each
    # time the test is run. Sometimes the test might fail.
    my_ds_contour = DirectSamplingContour(seastate_model, alpha, deg_step=6)

    my_coordinates = my_ds_contour.coordinates

    np.testing.assert_allclose(my_coordinates[0:26, 0],
                               ref_contour_hs_1,
                               atol=0.75)
    np.testing.assert_allclose(my_coordinates[0:26, 1],
                               ref_contour_tz_1,
                               atol=0.75)
exp3 = DependenceFunction(_exp3, bounds)

dist_description_0 = {
    "distribution": WeibullDistribution(alpha=2.776, beta=1.471, gamma=0.8888),
}
dist_description_1 = {
    "distribution": LogNormalDistribution(),
    "conditional_on": 0,
    "parameters": {
        "mu": power3,
        "sigma": exp3
    },
}
ghm = GlobalHierarchicalModel([dist_description_0, dist_description_1])

alpha = calculate_alpha(3, 50)
n = 10000
sample = ghm.draw_sample(n)
my_ds_contour = DirectSamplingContour(ghm, alpha, sample=sample)

my_coordinates = my_ds_contour.coordinates

# %% viroconcom v1
import sys

sys.path.append("../viroconcom")
from viroconcom.distributions import (
    WeibullDistribution,
    LognormalDistribution,
    MultivariateDistribution,
)