/install glm-lake-mendota-glm-output
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:
| Variable | Description | Shape |
|---|---|---|
time |
Hours since simulation start | (n_times,) |
z |
Height from lake bottom (not depth!) | (n_times, n_layers, 1, 1) |
temp |
Water 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 = \x3Clake_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 \x3C= depth \x3C= 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
| Issue | Cause | Solution |
|---|---|---|
| RMSE very high | Wrong depth conversion | Use lake_depth - z, not z directly |
| No matched observations | Datetime mismatch | Check datetime format consistency |
| Empty merged dataframe | Depth rounding issues | Round depths to integers |
Best Practices
- Check
lake_depthin&init_profilessection ofglm3.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
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install glm-lake-mendota-glm-output - After installation, invoke the skill by name or use
/glm-lake-mendota-glm-output - Provide required inputs per the skill's parameter spec and get structured output
What is glm-output?
Read and process GLM output files. Use when you need to extract temperature data from NetCDF output, convert depth coordinates, or calculate RMSE against obs... It is an AI Agent Skill for Claude Code / OpenClaw, with 81 downloads so far.
How do I install glm-output?
Run "/install glm-lake-mendota-glm-output" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is glm-output free?
Yes, glm-output is completely free, licensed under MIT-0. You can download, install and use it at no cost.
Which platforms does glm-output support?
glm-output is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created glm-output?
It is built and maintained by wu-uk (@wu-uk); the current version is v0.1.0.