agentsclimarketplace

Glm netcdf analysis

Skill cxcscmu/SkillLearnBench/skills/b1-one-shot-claude-sonnet-4-6/temperature-simulation/glm-netcdf-analysis

[COLM'26] SkillLearnBench is the first benchmark for evaluating continual learning methods that automatically generate agent skills.

Install
npx -y skills add cxcscmu/SkillLearnBench --skill glm-netcdf-analysis

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its author says it does

Copied from the file, not written here

Extracting and analyzing GLM NetCDF output to compute RMSE against field observations using exact datetime+depth matching.

SKILL.md

2.6 KB, 688 tokens by cl100k_base, as published. Nobody here has run it

GLM NetCDF Analysis Skill

Reading GLM NetCDF Output

import netCDF4 as nc
import numpy as np
import pandas as pd

ds = nc.Dataset('/root/output/output.nc')
# Key variables
time_raw = ds.variables['time'][:]       # days since some reference
temp = ds.variables['temp'][:]           # shape: (ntimes, nlayers)
z = ds.variables['z'][:]                 # layer heights (m above bottom), shape: (ntimes, nlayers)
NS = ds.variables['NS'][:]               # number of active layers per timestep

# Get time units and convert
time_units = ds.variables['time'].units  # e.g., "hours since 1900-01-01 00:00:00"
import cftime
times = nc.num2date(time_raw, time_units)

Converting Heights to Depths

# z is height above bottom; lake_depth converts to depth from surface
lake_depth = 25.0  # from glm3.nml init_profiles lake_depth
# depth from surface = lake_depth - height_above_bottom
depths = lake_depth - z  # array of depths for each layer, each timestep

Exact Datetime + Rounded Depth Merge

obs = pd.read_csv('/root/field_temp_oxy.csv', parse_dates=['datetime'])
obs['depth_round'] = obs['depth'].round(0).astype(int)

# Build simulation dataframe
sim_rows = []
for i, t in enumerate(times):
    n = int(NS[i])
    dt = pd.Timestamp(t.year, t.month, t.day, t.hour, t.minute, t.second)
    for j in range(n):
        h = float(z[i, j])
        d = lake_depth - h
        d_round = round(d)
        sim_rows.append({'datetime': dt, 'depth_round': d_round, 'sim_temp': float(temp[i, j])})

sim_df = pd.DataFrame(sim_rows)
# Keep one sim value per datetime+depth (if duplicates, take mean or last)
sim_df = sim_df.groupby(['datetime', 'depth_round'])['sim_temp'].mean().reset_index()

merged = obs.merge(sim_df, on=['datetime', 'depth_round'], how='inner')

Computing RMSE Metrics

import json

def rmse(df):
    return float(np.sqrt(np.mean((df['temp'] - df['sim_temp'])**2)))

overall_rmse = rmse(merged)

deep = merged[merged['depth_round'] >= 13]
annual_deep_rmse = rmse(deep)

summer_deep = deep[deep['datetime'].dt.month.isin([6, 7, 8, 9])]
summer_deep_rmse = rmse(summer_deep)

metrics = {
    'overall_rmse': overall_rmse,
    'annual_deep_rmse': annual_deep_rmse,
    'summer_deep_rmse': summer_deep_rmse,
    'overall_n_pairs': len(merged),
    'annual_deep_n_pairs': len(deep),
    'summer_deep_n_pairs': len(summer_deep)
}

with open('/root/metrics.json', 'w') as f:
    json.dump(metrics, f, indent=2)

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 327,132. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.