eaebec39创建于 2024年10月24日历史提交
package scientific.matplot


import std.unittest.*
import std.unittest.testmacro.*

import scientific.numbers.*
import scientific.linear.*
import scientific.stats.random.*
import scientific.stats.normal.*

/* Type for x and y: Float64 */
foreign func c_binscatter(
    x: CPointer<Unit>, x_len: Int64, y: CPointer<Unit>, y_len: Int64): CPointer<Unit>
foreign func c_binscatter_algo_style(
    x: CPointer<Unit>, x_len: Int64, y: CPointer<Unit>, y_len: Int64, 
    binning_algorithm: CString, bin_scatter_style: CString, 
    normalization: CString): CPointer<Unit>
foreign func c_binscatter_bins_style(
    x: CPointer<Unit>, x_len: Int64, y: CPointer<Unit>, y_len: Int64, 
    nbins_x: Int64, nbins_y: Int64,
    bin_scatter_style: CString, normalization: CString): CPointer<Unit>

public func binscatter(
    x: Vector<Float64>, y: Vector<Float64>,
    binning_algorithm!: BinningAlgorithm = Automatic,
    bin_scatter_style!: BinScatterStyle = Automatic,
    normalization_alg!: Normalization = Count): AxesObject
{
    let size = x.size()
    var cstr_binning_algorithm = unsafe { LibC.mallocCString(binning_algorithm.toString()) }
    var cstr_bin_scatter_style = unsafe { LibC.mallocCString(bin_scatter_style.toString()) }
    var cstr_normalization = unsafe { LibC.mallocCString(normalization_alg.toString()) }
    let handle = unsafe {
        c_binscatter_algo_style(x.ptr, size, y.ptr, size, 
            cstr_binning_algorithm, cstr_bin_scatter_style, cstr_normalization)
    }
    unsafe { LibC.free(cstr_binning_algorithm) }
    unsafe { LibC.free(cstr_bin_scatter_style) }
    unsafe { LibC.free(cstr_normalization) }
    return AxesObject(handle)
}

public func binscatter(
    x: Vector<Float64>, y: Vector<Float64>,
    nbins_x: Int64, nbins_y: Int64,
    bin_scatter_style!: BinScatterStyle = Automatic,
    normalization_alg!: Normalization = Count): AxesObject
{
    let size = x.size()
    var cstr_normalization = unsafe { LibC.mallocCString(normalization_alg.toString()) }
    var cstr_bin_scatter_style = unsafe { LibC.mallocCString(bin_scatter_style.toString()) }
    let handle = unsafe {
        c_binscatter_bins_style(x.ptr, size, y.ptr, size, 
            nbins_x, nbins_y, cstr_bin_scatter_style, cstr_normalization)
    }
    unsafe { LibC.free(cstr_normalization) }
    unsafe { LibC.free(cstr_bin_scatter_style) }
    return AxesObject(handle)
}

public enum BinScatterStyle {
    | Automatic
    | Point_size
    | Point_alpha
    | Jitter
    | Point_colormap
    | Heatmap

    func toString(): String {
        return match (this) {
            case Automatic => "automatic"
            case Point_size => "point_size"
            case Point_alpha => "point_alpha"
            case Jitter => "jitter"
            case Point_colormap => "point_colormap"
            case Heatmap => "heatmap"
        }
    }
}

public func testBinScatter1() {
    let f = gcf()
    f.width(f.width() * 2)
    var r: Random = Random(0)

    let x_reduced = randn(r, 1000, 0.0, 1.0)
    let y_reduced = x_reduced * 2.0 + rand(r, 1000)
    subplot(1, 2, 0)
    scatter(x_reduced, y_reduced)
    title("Scatter plot (n=1000)")

    let x = randn(r, 1000000, 0.0, 1.0)
    let y = x * 2.0 + rand(r, 1000000)
    subplot(1, 2, 1)
    binscatter(x, y)
    axis(Tight)
    title("Binned Scatter plot (n=1000000)")

    save("./tests/imgs/bin_scatter/bin_scatter_1.svg", "svg")
    clear()
}

public func testBinScatter2() {
    var r: Random = Random(0)
    let x: Vector<Float64> = randn(r, 100000, 0.0, 1.0)
    let y: Vector<Float64> = x * 2.0 + rand(r, 100000)

    let x_line = x[0..1000]
    let y_line = y[0..1000]

    subplot(2,3,0)
    scatter(x_line, y_line)
    title("Scatter")

    subplot(2,3,1)
    binscatter(x, y, bin_scatter_style:Point_size)
    title("Bin Scatter: Point Size")

    subplot(2,3,2)
    binscatter(x, y, bin_scatter_style:Point_alpha)
    title("Bin Scatter: Point Alpha")

    subplot(2,3,3)
    binscatter(x, y, bin_scatter_style:Point_colormap)
    title("Bin Scatter: Point Colormap")

    subplot(2,3,4)
    binscatter(x, y, bin_scatter_style:Heatmap)
    title("Bin Scatter: Heatmap")

    subplot(2,3,5)
    binscatter(x, y, bin_scatter_style:Jitter)
    title("Bin Scatter: Jitter")

    save("./tests/imgs/bin_scatter/bin_scatter_2.svg", "svg")
    clear()
}

public func testBinScatter3() {
    let f = gcf()
    f.width(f.width() * 2)
    f.height(f.height() * 2)
    f.x_position(200)
    f.y_position(100)

    var r: Random = Random(0)
    let x: Vector<Float64> = randn(r, 100000, 0.0, 1.0)
    let y: Vector<Float64> = x * 2.0 + rand(r, 100000)

    var b = BinScatterStyle.Automatic

    subplot(2,3,0)
    binscatter(x, y, binning_algorithm: BinningAlgorithm.Automatic, bin_scatter_style: b)
    title("Automatic")

    subplot(2,3,1)
    binscatter(x, y, binning_algorithm: BinningAlgorithm.Integers, bin_scatter_style: b)
    axis(Tight)
    title("Integers")

    subplot(2,3,2)
    binscatter(x, y, binning_algorithm: BinningAlgorithm.Scott, bin_scatter_style: b)
    axis(Tight)
    title("Scott's rule")

    subplot(2,3,3)
    binscatter(x, y, binning_algorithm: BinningAlgorithm.FD, bin_scatter_style: b)
    axis(Tight)
    title("Freedman-Diaconis rule")

    subplot(2,3,4)
    binscatter(x, y, binning_algorithm: BinningAlgorithm.Sqrt, bin_scatter_style: b)
    axis(Tight)
    title("Square root rule")

    subplot(2,3,5)
    binscatter(x, y, binning_algorithm: BinningAlgorithm.Sturges, bin_scatter_style: b)
    axis(Tight)
    title("Sturges' rule")

    save("./tests/imgs/bin_scatter/bin_scatter_3.png", "png")
    clear()
}

public func testBinScatter4() {
    let f = gcf()
    f.width(f.width() * 2)
    f.height(f.height() * 2)
    f.x_position(200)
    f.y_position(100)

    var r: Random = Random(0)
    let x: Vector<Float64> = randn(r, 100000, 0.0, 1.0)
    let y: Vector<Float64> = x * 2.0 + rand(r, 100000)

    var b = BinScatterStyle.Heatmap
    var a = BinningAlgorithm.Automatic

    subplot(2,3,0)
    binscatter(x, y, binning_algorithm: a, bin_scatter_style: b, 
                normalization_alg: Normalization.Count)
    axis(Tight)
    title("Normalization: Count")

    subplot(2,3,1)
    binscatter(x, y, binning_algorithm: a, bin_scatter_style: b, 
                normalization_alg: Normalization.Probability)
    axis(Tight)
    title("Normalization: Probability")

    subplot(2,3,2)
    binscatter(x, y, binning_algorithm: a, bin_scatter_style: b, 
                normalization_alg: Normalization.CumulativeCount)
    axis(Tight)
    title("Normalization: Cumulative count")

    subplot(2,3,3)
    binscatter(x, y, binning_algorithm: a, bin_scatter_style: b, 
                normalization_alg: Normalization.CountDensity)
    axis(Tight)
    title("Normalization: Count density")

    subplot(2,3,4)
    binscatter(x, y, binning_algorithm: a, bin_scatter_style: b, 
                normalization_alg: Normalization.Pdf)
    axis(Tight)
    title("Normalization: PDF")

    subplot(2,3,5)
    binscatter(x, y, binning_algorithm: a, bin_scatter_style: b, 
                normalization_alg: Normalization.Cdf)
    axis(Tight)
    title("Normalization: CDF")

    save("./tests/imgs/bin_scatter/bin_scatter_4.svg", "svg")
    clear()
}

public func testBinScatter5() {
    let f = gcf()
    f.width(f.width() * 2)
    f.height(f.height() * 2)
    f.x_position(200)
    f.y_position(100)
    f.quiet_mode(true)

    var r: Random = Random(0)
    let x: Vector<Float64> = randn(r, 10000, 0.0, 1.0)
    let y: Vector<Float64> = randn(r, 10000, 0.0, 1.0)

    subplot(2,3,0)
    scatter(x, y)
    title("Scatter plot")

    subplot(2,3,1)
    binscatter(x, y, 30, 10, bin_scatter_style: Point_size)
    title("Binned scatter plot: Point size")

    subplot(2, 3, 2)
    binscatter(x, y, 30, 10, bin_scatter_style: Point_alpha)
    title("Binned scatter plot: Point alpha")

    subplot(2, 3, 3)
    binscatter(x, y, 30, 10, bin_scatter_style: Jitter)
    title("Binned scatter plot: Jitter")

    subplot(2, 3, 4)
    binscatter(x, y, 30, 10, bin_scatter_style: Point_colormap)
    title("Binned scatter plot: Colormap")

    subplot(2, 3, 5)
    binscatter(x, y, 30, 10, bin_scatter_style: Heatmap)
    title("Binned scatter plot: Heatmap")
    axis(Tight)

    save("./tests/imgs/bin_scatter/bin_scatter_5.svg", "svg")
    clear()
}

public func testBinScatter6() {
    var r: Random = Random(0)
    let x: Vector<Float64> = randn(r, 100000, 0.0, 1.0)
    let y: Vector<Float64> = randn(r, 100000, 0.0, 1.0)

    binscatter(x, y, bin_scatter_style: Point_colormap)

    save("./tests/imgs/bin_scatter/bin_scatter_6.svg", "svg")
    clear()
}

public func testBinScatter7() {
    var r: Random = Random(0)
    let x: Vector<Float64> = randn(r, 100000, 0.0, 1.0)
    let y: Vector<Float64> = randn(r, 100000, 0.0, 1.0)

    binscatter(x, y, 20, 30, bin_scatter_style: Heatmap)
    axis(Tight)

    save("./tests/imgs/bin_scatter/bin_scatter_7.svg", "svg")
    clear()
}

public func testBinnedScatter() {
    print("  + testBinnedScatter\n")
    testBinScatter1()
    testBinScatter2()
    testBinScatter3()
    testBinScatter4()
    testBinScatter5()
    testBinScatter6()
    testBinScatter7()
}