Skip to content

Julia Examples

Complete Julia examples demonstrating FastLOWESS with native Julia integration.

Batch Smoothing

Process complete datasets with confidence intervals and diagnostics.

#!/usr/bin/env julia
"""
FastLOWESS Batch Smoothing Example

This example demonstrates batch LOWESS smoothing features:
- Basic smoothing with different parameters
- Robustness iterations for outlier handling
- Confidence and prediction intervals
- Diagnostics and cross-validation

The Lowess class is the primary interface for
processing complete datasets that fit in memory.
"""

using Random
using Printf

# Handle package loading - check if we're already in the FastLOWESS project
using Pkg
project_name = Pkg.project().name
if project_name != "FastLOWESS"
    # Not in the FastLOWESS project, need to develop it
    script_dir = @__DIR__
    julia_pkg_dir = joinpath(dirname(script_dir), "julia")
    if !haskey(Pkg.project().dependencies, "FastLOWESS")
        Pkg.develop(path = julia_pkg_dir)
    end
end

using FastLOWESS

function generate_sample_data(n_points = 1000)
    """
    Generate complex sample data with a trend, seasonality, and outliers.
    """
    Random.seed!(42)
    x = collect(range(0, 50, length = n_points))

    # Trend + Seasonality
    y_true = 0.5 .* x .+ 5 .* sin.(x .* 0.5)

    # Gaussian noise
    y = y_true .+ randn(n_points) .* 1.5

    # Add significant outliers (10% of data)
    n_outliers = Int(round(n_points * 0.1))
    outlier_indices = randperm(n_points)[1:n_outliers]
    for i in outlier_indices
        y[i] += rand(10:20) * rand([-1, 1])
    end

    return x, y, y_true
end

function main()
    println("=== FastLOWESS Batch Smoothing Example ===")

    # 1. Generate Data
    x, y, y_true = generate_sample_data(1000)
    println("Generated $(length(x)) data points with outliers.")

    # 2. Basic Smoothing (Default parameters)
    println("Running basic smoothing...")
    # 2. Basic Smoothing (Default parameters)
    println("Running basic smoothing...")
    # Use a smaller fraction (0.05) to capture the sine wave seasonality
    l_basic = Lowess(iterations = 0, fraction = 0.05)
    res_basic = fit(l_basic, x, y)

    # 3. Robust Smoothing (IRLS)
    println("Running robust smoothing (3 iterations)...")
    l_robust = Lowess(
        fraction = 0.05,
        iterations = 3,
        robustness_method = "bisquare",
        return_robustness_weights = true,
    )
    res_robust = fit(l_robust, x, y)

    # 4. Uncertainty Quantification
    println("Computing confidence and prediction intervals...")
    l_intervals = Lowess(
        fraction = 0.05,
        confidence_intervals = 0.95,
        prediction_intervals = 0.95,
        return_diagnostics = true,
    )
    res_intervals = fit(l_intervals, x, y)

    # 5. Cross-Validation for optimal fraction
    println("Running cross-validation to find optimal fraction...")
    cv_fractions = [0.05, 0.1, 0.2, 0.4]
    l_cv = Lowess(cv_fractions = cv_fractions, cv_method = "kfold", cv_k = 5)
    res_cv = fit(l_cv, x, y)
    println("Optimal fraction found: $(res_cv.fraction_used)")

    # Diagnostics Printout
    if res_intervals.diagnostics !== nothing
        diag = res_intervals.diagnostics
        println("\nFit Statistics (Intervals Model):")
        @printf(" - R²:   %.4f\n", diag.r_squared)
        @printf(" - RMSE: %.4f\n", diag.rmse)
        @printf(" - MAE:  %.4f\n", diag.mae)
    end

    # 6. Boundary Policy Comparison
    println("\nDemonstrating boundary policy effects on linear data...")
    xl = collect(range(0, 10, length = 50))
    yl = 2 .* xl .+ 1

    # Compare policies
    r_ext = fit(Lowess(fraction = 0.6, boundary_policy = "extend"), xl, yl)
    r_ref = fit(Lowess(fraction = 0.6, boundary_policy = "reflect"), xl, yl)
    r_zr = fit(Lowess(fraction = 0.6, boundary_policy = "zero"), xl, yl)

    println("Boundary policy comparison:")
    println(
        " - Extend (Default): first=$(round(r_ext.y[1], digits=2)), last=$(round(r_ext.y[end], digits=2))",
    )
    println(
        " - Reflect:          first=$(round(r_ref.y[1], digits=2)), last=$(round(r_ref.y[end], digits=2))",
    )
    println(
        " - Zero:             first=$(round(r_zr.y[1], digits=2)), last=$(round(r_zr.y[end], digits=2))",
    )

    println("\n=== Batch Smoothing Example Complete ===")
end

main()

Download batch_smoothing.jl


Streaming Smoothing

Process large datasets in memory-efficient chunks.

#!/usr/bin/env julia
"""
FastLOWESS Streaming Smoothing Example

This example demonstrates streaming LOWESS smoothing for large datasets:
- Basic chunked processing
- Handling datasets that don't fit in memory
- Parallel execution for extreme speed
"""

using Random
using Printf

# Handle package loading - check if we're already in the FastLOWESS project
using Pkg
project_name = Pkg.project().name
if project_name != "FastLOWESS"
    # Not in the FastLOWESS project, need to develop it
    script_dir = @__DIR__
    julia_pkg_dir = joinpath(dirname(script_dir), "julia")
    if !haskey(Pkg.project().dependencies, "FastLOWESS")
        Pkg.develop(path = julia_pkg_dir)
    end
end

using FastLOWESS

function main()
    println("=== FastLOWESS Streaming Mode Example ===")

    # 1. Generate Very Large Dataset
    # 100,000 points
    n_points = 100_000
    println("Generating large dataset: $n_points points...")
    Random.seed!(42)
    x = collect(range(0, 100, length = n_points))
    y = cos.(x .* 0.1) .+ randn(n_points) .* 0.5

    # 2. Regular Batch Smoothing (for comparison)
    println("Running Batch LOWESS (Parallel)...")
    batch_start = time()
    res_batch = fit(Lowess(fraction = 0.01), x, y)
    batch_time = time() - batch_start
    @printf("Batch took: %.4f seconds\n", batch_time)

    # 3. Streaming Mode
    # Divide the data into chunks of 2,000 for low memory usage
    println("Running Streaming LOWESS (Chunked)...")
    stream_start = time()
    model =
        StreamingLowess(fraction = 0.01, chunk_size = 2000, overlap = 200, parallel = true)
    res_stream = process_chunk(model, x, y)
    append!(res_stream, finalize(model))
    stream_time = time() - stream_start
    @printf("Streaming took: %.4f seconds\n", stream_time)

    # 4. Verify Accuracy
    mse = sum((res_batch.y .- res_stream.y) .^ 2) / length(res_batch.y)
    @printf("Mean Squared Difference (Batch vs Stream): %.2e\n", mse)

    # Show sample of results
    println("\nSample comparison (indices 1000-1005):")
    println("Index\tBatch\t\tStreaming\tDiff")
    for i  1000:1005
        diff = abs(res_batch.y[i] - res_stream.y[i])
        @printf("%d\t%.6f\t%.6f\t%.6f\n", i, res_batch.y[i], res_stream.y[i], diff)
    end

    println("\n=== Streaming Smoothing Example Complete ===")
end

main()

Download streaming_smoothing.jl


Online Smoothing

Real-time smoothing with sliding window for streaming data.

#!/usr/bin/env julia
"""
FastLOWESS Online Smoothing Example

This example demonstrates online LOWESS smoothing for real-time data:
- Basic incremental processing with streaming data
- Real-time sensor data smoothing
- Different update modes (Full vs Incremental)
- Memory-bounded processing with sliding window

The OnlineLowess class is designed for:
- Real-time data streams
- Sensors and monitoring
- Low-latency applications
"""

using Random
using Printf

# Handle package loading - check if we're already in the FastLOWESS project
using Pkg
project_name = Pkg.project().name
if project_name != "FastLOWESS"
    # Not in the FastLOWESS project, need to develop it
    script_dir = @__DIR__
    julia_pkg_dir = joinpath(dirname(script_dir), "julia")
    if !haskey(Pkg.project().dependencies, "FastLOWESS")
        Pkg.develop(path = julia_pkg_dir)
    end
end

using FastLOWESS

function main()
    println("=== FastLOWESS Online Smoothing Example ===")

    # 1. Simulate a real-time signal
    # A sine wave with changing frequency and random noise
    n_points = 1000
    Random.seed!(42)
    x = collect(Float64, 0:(n_points-1))
    y_true = 20.0 .+ 5.0 .* sin.(x .* 0.1) .+ 2.0 .* sin.(x .* 0.02)
    y = y_true .+ randn(n_points) .* 1.2

    # Add some sudden spikes (sensor glitches)
    y[201:205] .+= 15.0
    y[601:610] .-= 10.0

    println("Simulating $n_points real-time data points...")

    # 2. Sequential Online Processing
    # Full Update Mode (higher accuracy)
    println("Processing with 'full' update mode...")
    model_full = OnlineLowess(
        fraction = 0.3,
        window_capacity = 50,
        iterations = 3,
        update_mode = "full",
    )
    res_full = add_points(model_full, x, y)

    # Incremental Update Mode (faster for large windows)
    println("Processing with 'incremental' update mode...")
    model_inc = OnlineLowess(
        fraction = 0.3,
        window_capacity = 50,
        iterations = 3,
        update_mode = "incremental",
    )
    res_inc = add_points(model_inc, x, y)

    # Compare results
    println("\nResults Comparison:")

    # Show sample around spike area
    println("\nSample around spike (indices 198-208):")
    println("Index\tRaw\t\tTrue\t\tFull\t\tIncremental")
    for i  198:208
        @printf(
            "%d\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f\n",
            i,
            y[i],
            y_true[i],
            res_full.y[i],
            res_inc.y[i]
        )
    end

    # Calculate overall statistics
    mse_full = sum((res_full.y .- y_true) .^ 2) / n_points
    mse_inc = sum((res_inc.y .- y_true) .^ 2) / n_points

    println("\nMean Squared Error vs True Signal:")
    @printf(" - Full Update:        %.4f\n", mse_full)
    @printf(" - Incremental Update: %.4f\n", mse_inc)

    println("\n=== Online Smoothing Example Complete ===")
end

main()

Download online_smoothing.jl


Installation

using Pkg
Pkg.develop(path="bindings/julia/julia")

Running the Examples

julia --project=bindings/julia/julia examples/julia/batch_smoothing.jl
julia --project=bindings/julia/julia examples/julia/streaming_smoothing.jl
julia --project=bindings/julia/julia examples/julia/online_smoothing.jl

Quick Start

using FastLOWESS

# Generate sample data
x = collect(0.0:0.1:10.0)
y = sin.(x) .+ 0.3 .* randn(length(x))

# Basic smoothing
result = smooth(x, y; fraction=0.3)
println("Smoothed values: ", result.y[1:5])

# With options
result = smooth(x, y;
    fraction=0.3,
    iterations=3,
    confidence_intervals=0.95,
    return_diagnostics=true
)

println("R²: ", result.diagnostics.r_squared)

# Access confidence intervals
lower = result.confidence_lower
upper = result.confidence_upper

Features

The Julia bindings provide:

  • Native Julia types - Uses Julia arrays directly
  • C FFI integration - Efficient bindings via ccall
  • Multiple dispatch - Works with Float32 and Float64
  • Full parameter access - All LOWESS options available