Constrained water and energy balance algorithm for snow water equivalent (SWE) and precipitation, described in:
Dechow et al. (2025). Merging remote sensing observations and land surface models to improve estimates of the spatial and temporal dynamics of snow water equivalent and surface density. Water Resources Research. [Under review — revised submission]
Preprint DOI: https://essopenarchive.org/doi/10.22541/essoar.175915579.90649700/v1
PhD Dissertation (OSU, 2024):
Merging remote sensing observations and land surface models to improve estimates of the spatial and temporal dynamics of snow water equivalent and surface density http://rave.ohiolink.edu/etdc/view?acc_num=osu1723774509328696
The current version of Blender is a self-contained Julia Jupyter notebook (RunBlender.ipynb). It is the version used to generate results in the revised manuscript. Key improvements over V0:
- Reads gridded NetCDF inputs via
Rasters.jlinstead of per-pixel text files - Multithreaded pixel loop (
Threads.@threads) for substantially faster runtimes - Batched file writes outside the threaded loop for I/O efficiency
- Precipitation scalar support (
v0/v1/v2) for sensitivity experiments
- Julia ≥ 1.x with packages:
NCDatasets,JuMP,Ipopt,Rasters,DimensionalData,DelimitedFiles,Statistics,Distributed,Random - A Julia-compatible Jupyter environment (e.g., IJulia)
- Multithreading enabled before starting the notebook:
export JULIA_NUM_THREADS=auto - You can run without multithreading but it takes 2-4x as long!!
The notebook expects the following NetCDF files organized as <baseDir>/<model>/WY<year>/:
| File | Variable | Description |
|---|---|---|
SCF.nc |
SCF |
Snow-covered fraction |
Snowf_tavg.nc |
Snowf_tavg |
Precipitation (snowfall), σ=1 smoothed |
SWE_tavg.nc |
SWE_tavg |
Snow water equivalent, σ=1 smoothed |
Tair_f_tavg.nc |
Tair_f_tavg |
Air temperature |
Qg_tavg.nc |
Qg_tavg |
Ground heat flux |
precip_scalars/WY<year>/precip_scalar_<vN>.nc |
precip_scalar |
Precipitation scaling factor |
mask.nc |
mask |
Valid pixel mask — defines the spatial domain; included in this repository |
At the top of call_Blender_wshed, set baseDir to your local data directory:
baseDir = "/path/to/your/data"The function also uses a wshed_name string (pulled from an internal lookup) to name the output subdirectory — you will need to adapt that section of the notebook for your own domain.
Open RunBlender.ipynb and run all cells. To run a single domain:
WY = "WY2016"
model = "ERA5L"
vN = "v2"
call_Blender_wshed(WY, model, 1, vN)To loop over multiple water years, uncomment the loop at the bottom of the notebook.
Per-pixel output files are written to <baseDir>/<model>/WY<year>/<wshed_name>/<vN>/Pix_i_j.txt, with two columns: SWE [m] and Precip [m]. Pixel file names are assigned from their position in the ij loop, and need to be accounted for when reading them back into an array. If there are fully nan rows/columns in your area of interest, that needs to be accounted for when reading in files.
The original version of Blender (used for the PhD dissertation and initial preprint) is preserved in the V0/ subdirectory. It consists of a standalone Julia script (Blender_Algorithm_v5.0.jl) designed for HPC environments, operating on one pixel at a time via per-pixel text file inputs. See V0/ for the call script and sample job submission script.
Data for this algorithm are available at https://zenodo.org/records/17093963