ExamplesEmulator

Emulator Examples

Building a custom emulator

from biosnicar.emulator import Emulator
 
emu = Emulator.build(
    params={
        "rds": (100, 5000),
        "rho": (100, 917),
        "black_carbon": (0, 100000),
        "glacier_algae": (0, 500000),
    },
    n_samples=5000,
    layer_type=1,
    solzen=50,
    direct=1,
)
 
# Check accuracy
result = emu.verify(n_points=50)
print(result.summary())
 
# Save
emu.save("my_emulator.npz")

Emulator accuracy: predicted vs reference albedo

Predicting with the emulator

from biosnicar.emulator import Emulator
from biosnicar import run_emulator
 
# Load pre-built default emulator
emu = Emulator.load("data/emulators/glacier_ice_8_param_default.npz")
print(f"Parameters: {emu.param_names}")
print(f"Bounds: {emu.bounds}")
 
# Single prediction
albedo = emu.predict(
    rds=1000, rho=600, black_carbon=5000, snow_algae=0, dust=1000,
    glacier_algae=50000, direct=1, solzen=50,
)
print(f"Albedo shape: {albedo.shape}")

Batch prediction

import numpy as np
 
points = np.array([
    [1000, 600, 5000, 0, 1000, 50000, 1, 50],
    [500, 400, 0, 0, 0, 0, 1, 30],
    [2000, 800, 10000, 1000, 5000, 100000, 0, 60],
])
batch_albedo = emu.predict_batch(points)
print(f"Batch shape: {batch_albedo.shape}")  # (3, 480)

Full Outputs object

outputs = run_emulator(
    emu, rds=1000, rho=600, black_carbon=5000, snow_algae=0, dust=1000,
    glacier_algae=50000, direct=1, solzen=50,
)
print(f"BBA: {outputs.BBA:.4f}")
print(f"BBAVIS: {outputs.BBAVIS:.4f}")
print(f"BBANIR: {outputs.BBANIR:.4f}")
 
# Chain to satellite bands
s2 = outputs.to_platform("sentinel2")
print(f"S2 B3: {s2.B3:.3f}, NDSI: {s2.NDSI:.3f}")

Save and load roundtrip

emu.save("my_emulator.npz")
emu2 = Emulator.load("my_emulator.npz")
 
# Verify identical predictions
albedo1 = emu.predict(rds=1000, rho=600, black_carbon=0, snow_algae=0,
                      dust=0, glacier_algae=0, direct=1, solzen=50)
albedo2 = emu2.predict(rds=1000, rho=600, black_carbon=0, snow_algae=0,
                       dust=0, glacier_algae=0, direct=1, solzen=50)
print(f"Max difference: {np.max(np.abs(albedo1 - albedo2))}")

Speed comparison

import time
from biosnicar import run_model
 
# Forward model
start = time.perf_counter()
for _ in range(10):
    run_model(solzen=50, rds=1000)
fm_time = (time.perf_counter() - start) / 10
 
# Emulator
start = time.perf_counter()
for _ in range(10000):
    emu.predict(rds=1000, rho=600, black_carbon=0, snow_algae=0,
                dust=0, glacier_algae=0, direct=1, solzen=50)
emu_time = (time.perf_counter() - start) / 10000
 
print(f"Forward model: {fm_time*1000:.1f} ms")
print(f"Emulator:      {emu_time*1e6:.1f} µs")
print(f"Speedup:       {fm_time/emu_time:.0f}x")