Processes NetCDF climate output files to extract and analyze scientific data.

Install

mkdir -p .claude/skills/glm-output && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/5084" && unzip -o skill.zip -d .claude/skills/glm-output && rm skill.zip

Installs to .claude/skills/glm-output

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Read and process GLM output files. Use when you need to extract temperature data from NetCDF output, convert depth coordinates, or calculate RMSE against observations.
167 chars✓ has a “when” trigger
Intermediate

Key capabilities

  • Extract temperature data from NetCDF
  • Convert depth coordinates
  • Calculate RMSE against observations
  • Process GLM simulation output

How it works

It parses NetCDF files to normalize depth coordinates and compute RMSE metrics by comparing simulated water temperature profiles against observational data.

Inputs & outputs

You give it
GLM output.nc file
You get back
RMSE metric and processed dataframe

When to use glm-output

  • Extract temperature from NetCDF files
  • Convert model depth data
  • Calculate RMSE against observations

About this skill

GLM Output Guide

Overview

GLM produces NetCDF output containing simulated water temperature profiles. Processing this output requires understanding the coordinate system and matching with observations.

Output File

After running GLM, results are in output/output.nc:

VariableDescriptionShape
timeHours since simulation start(n_times,)
zHeight from lake bottom (not depth!)(n_times, n_layers, 1, 1)
tempWater temperature (°C)(n_times, n_layers, 1, 1)

Reading Output with Python

from netCDF4 import Dataset
import numpy as np
import pandas as pd
from datetime import datetime

nc = Dataset('output/output.nc', 'r')
time = nc.variables['time'][:]
z = nc.variables['z'][:]
temp = nc.variables['temp'][:]
nc.close()

Coordinate Conversion

Important: GLM z is height from lake bottom, not depth from surface.

# Convert to depth from surface
# Set LAKE_DEPTH based on lake_depth in &init_profiles section of glm3.nml
LAKE_DEPTH = <lake_depth_from_nml>
depth_from_surface = LAKE_DEPTH - z

Complete Output Processing

from netCDF4 import Dataset
import numpy as np
import pandas as pd
from datetime import datetime

def read_glm_output(nc_path, lake_depth):
    nc = Dataset(nc_path, 'r')
    time = nc.variables['time'][:]
    z = nc.variables['z'][:]
    temp = nc.variables['temp'][:]
    start_date = datetime(2009, 1, 1, 12, 0, 0)

    records = []
    for t_idx in range(len(time)):
        hours = float(time[t_idx])
        date = pd.Timestamp(start_date) + pd.Timedelta(hours=hours)
        heights = z[t_idx, :, 0, 0]
        temps = temp[t_idx, :, 0, 0]

        for d_idx in range(len(heights)):
            h_val = heights[d_idx]
            t_val = temps[d_idx]
            if not np.ma.is_masked(h_val) and not np.ma.is_masked(t_val):
                depth = lake_depth - float(h_val)
                if 0 <= depth <= lake_depth:
                    records.append({
                        'datetime': date,
                        'depth': round(depth),
                        'temp_sim': float(t_val)
                    })
    nc.close()

    df = pd.DataFrame(records)
    df = df.groupby(['datetime', 'depth']).agg({'temp_sim': 'mean'}).reset_index()
    return df

Reading Observations

def read_observations(obs_path):
    df = pd.read_csv(obs_path)
    df['datetime'] = pd.to_datetime(df['datetime'])
    df['depth'] = df['depth'].round().astype(int)
    df = df.rename(columns={'temp': 'temp_obs'})
    return df[['datetime', 'depth', 'temp_obs']]

Calculating RMSE

def calculate_rmse(sim_df, obs_df):
    merged = pd.merge(obs_df, sim_df, on=['datetime', 'depth'], how='inner')
    if len(merged) == 0:
        return 999.0
    rmse = np.sqrt(np.mean((merged['temp_sim'] - merged['temp_obs'])**2))
    return rmse

# Usage: get lake_depth from glm3.nml &init_profiles section
sim_df = read_glm_output('output/output.nc', lake_depth=25)
obs_df = read_observations('field_temp_oxy.csv')
rmse = calculate_rmse(sim_df, obs_df)
print(f"RMSE: {rmse:.2f}C")

Common Issues

IssueCauseSolution
RMSE very highWrong depth conversionUse lake_depth - z, not z directly
No matched observationsDatetime mismatchCheck datetime format consistency
Empty merged dataframeDepth rounding issuesRound depths to integers

Best Practices

  • Check lake_depth in &init_profiles section of glm3.nml
  • Always convert z to depth from surface before comparing with observations
  • Round depths to integers for matching
  • Group by datetime and depth to handle duplicate records
  • Check number of matched observations after merge

When not to use it

  • Non-NetCDF output formats
  • Non-GLM simulation data

Prerequisites

netCDF4numpypandas

Limitations

  • Requires correct lake_depth from glm3.nml
  • Requires matching datetime formats

How it compares

It automates the coordinate conversion and metric calculation process which is prone to error when done manually.

Compared to similar skills

glm-output side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
glm-output (this skill)16moNo flagsIntermediate
exploratory-data-analysis152moReviewIntermediate
model-compare77moReviewAdvanced
astropy67moReviewAdvanced

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

exploratory-data-analysis

K-Dense-AI

Perform comprehensive exploratory data analysis on scientific data files across 200+ file formats. This skill should be used when analyzing any scientific data file to understand its structure, content, quality, and characteristics. Automatically detects file type and generates detailed markdown reports with format-specific analysis, quality metrics, and downstream analysis recommendations. Covers chemistry, bioinformatics, microscopy, spectroscopy, proteomics, metabolomics, and general scientific data formats.

15114

model-compare

rawwerks

Compare 3D CAD models using boolean operations (IoU, Dice, precision/recall). Use when evaluating generated models against gold references, diffing CAD revisions, or computing similarity metrics for ML training. Triggers on: model diff, compare models, IoU, intersection over union, model similarity, CAD comparison, STEP diff, 3D evaluation, gold reference, generated model, precision recall 3D.

783

astropy

davila7

Comprehensive Python library for astronomy and astrophysics. This skill should be used when working with astronomical data including celestial coordinates, physical units, FITS files, cosmological calculations, time systems, tables, world coordinate systems (WCS), and astronomical data analysis. Use when tasks involve coordinate transformations, unit conversions, FITS file manipulation, cosmological distance calculations, time scale conversions, or astronomical data processing.

682

statistical-analysis

anthropics

Apply statistical methods including descriptive stats, trend analysis, outlier detection, and hypothesis testing. Use when analyzing distributions, testing for significance, detecting anomalies, computing correlations, or interpreting statistical results.

848

datacommons-client

davila7

Work with Data Commons, a platform providing programmatic access to public statistical data from global sources. Use this skill when working with demographic data, economic indicators, health statistics, environmental data, or any public datasets available through Data Commons. Applicable for querying population statistics, GDP figures, unemployment rates, disease prevalence, geographic entity resolution, and exploring relationships between statistical entities.

637

analyzing-market-sentiment

jeremylongshore

Analyze cryptocurrency market sentiment using Fear & Greed Index, news analysis, and market momentum. Use when gauging overall market mood, checking if markets are fearful or greedy, or analyzing sentiment for specific coins. Trigger with phrases like "analyze crypto sentiment", "check market mood", "is the market fearful", "sentiment for Bitcoin", or "Fear and Greed index".

339

Search skills

Search the agent skills registry