Skip to content
Back to skills

Docs

ASecurity

Generate the hexagonal (or other polygonal) mesh with DEM-derived elevation values in the JSON format consumed by HexWatershed. This stage bridges raw geospatial data (GeoTIFF DEMs) to the model's cell-based representation.

  • 200 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 11, 2026
toolspythongobashgit

Security analysis

A100/100

Pro scans all 11 files and shows the line behind each finding

Scanned September 11, 2026

npx -y skills add lzwei196/KISS---Knowledge-Infrastructure-for-Scientific-Simulation --skill docs --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Docs?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Docs
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/lzwei196-docs-071743c2/badge)](https://www.skillsdirectory.com/skills/lzwei196-docs-071743c2)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Stage 1: Mesh Generation — Skill Document

## Purpose

Generate the hexagonal (or other polygonal) mesh with DEM-derived elevation values
in the JSON format consumed by HexWatershed. This stage bridges raw geospatial data
(GeoTIFF DEMs) to the model's cell-based representation.

The mesh JSON is the single most critical input to HexWatershed. Every subsequent
computation depends on correct cell geometry, neighbor relationships, and elevation values.

## Inputs

| Input              | Source              | Format   | Unit/Notes                          |
|-------------------|---------------------|----------|--------------------------------------|
| DEM raster        | SRTM / MERIT / NED  | GeoTIFF  | EPSG:4326, elevation in meters       |
| Mesh resolution   | Configuration        | float    | Cell edge length in meters           |
| Mesh type         | Configuration        | string   | hexagon, square, latlon, mpas, etc.  |
| Study area bounds | Configuration        | lat/lon  | west, south, east, north in degrees  |

## Outputs

| Output                        | Format | Description                               |
|-------------------------------|--------|-------------------------------------------|
| `{mesh_type}_mesh_info.json`  | JSON   | Complete mesh with cells, topology, elev  |

### Output JSON Structure

```json
{
  "sMesh_type": "hexagon",
  "nCell": 12345,
  "dResolution": 5000.0,
  "aCells": [
    {
      "lCellID": 1,
      "dLongitude_center_degree": -76.5,
      "dLatitude_center_degree": 39.2,
      "dElevation_mean": 152.3,
      "dElevation_raw": 152.3,
      "dArea": 21650000.0,
      "nVertex": 6,
      "vVertex": [{"dLongitude_degree": -76.48, "dLatitude_degree": 39.22}, ...],
      "aNeighbor": [2, 3, 4, 5, 6, 7],
      "aNeighbor_distance": [5000.0, 5000.0, 5000.0, 5000.0, 5000.0, 5000.0]
    }
  ]
}
```

## Procedure

1. **Obtain DEM** in GCS (EPSG:4326) with meters elevation:
   ```bash
   # Reproject if needed
   gdalwarp -t_srs EPSG:4326 -r bilinear input_utm.tif output_gcs.tif
   ```

2. **Verify DEM CRS and units**:
   ```bash
   gdalinfo dem.tif | grep -E "AUTHORITY|Unit|NoData"
   # Must show: EPSG:4326, degree units, elevation in meters
   ```

3. **Generate mesh** using PyFlowline (recommended):
   ```python
   from pyflowline.formats.convert_mesh import pyflowline_generate_mesh
   pyflowline_generate_mesh(
       sDEM='/data/dem.tif',
       sMesh_type='hexagon',
       dResolution=5000,
       sOutput='/data/mesh/'
   )
   ```

   Or use the KI mesh_converter tool:
   ```bash
   python mesh_converter.py --dem /data/dem.tif --resolution 5000 \
       --mesh-type hexagon --output /data/mesh/hexagon_mesh_info.json
   ```

4. **Validate mesh**:
   - Check all cells have valid elevation (not nodata)
   - Check neighbor relationships are symmetric (if A neighbors B, B neighbors A)
   - Check cell areas are physically reasonable for the resolution

## Verification

```bash
# Check mesh JSON is valid and has cells
python3 -c "
import json
mesh = json.load(open('hexagon_mesh_info.json'))
print(f'Cells: {mesh[\"nCell\"]}')
cells = mesh['aCells']
elev = [c['dElevation_mean'] for c in cells]
print(f'Elevation range: {min(elev):.1f} to {max(elev):.1f} m')
nodata = [c for c in cells if c['dElevation_mean'] <= -9999]
print(f'Nodata cells: {len(nodata)}')"

# Check coordinate system (values should be in degree range)
python3 -c "
import json
mesh = json.load(open('hexagon_mesh_info.json'))
lons = [c['dLongitude_center_degree'] for c in mesh['aCells']]
lats = [c['dLatitude_center_degree'] for c in mesh['aCells']]
print(f'Lon range: {min(lons):.4f} to {max(lons):.4f}')
print(f'Lat range: {min(lats):.4f} to {max(lats):.4f}')
assert max(abs(l) for l in lons) <= 180, 'PROJECTED CRS DETECTED'
assert max(abs(l) for l in lats) <= 90, 'PROJECTED CRS DETECTED'"
```

## Traps

### TRAP: DEM in projected CRS (dt_006)
If the DEM is in UTM or State Plane (coordinates in meters, not degrees), the mesh
will have coordinates like (500000, 4000000) instead of (-76.5, 39.2). The model
will compute nonsensical distances because it expects geographic degrees for its
internal spherical geometry calculations. **Always check bounds before proceeding.**

### TRAP: DEM elevation in feet (dt_013)
USGS NED tiles may have elevation in feet. Since all HexWatershed internal calculations
assume meters, slopes will be inflated by a factor of 3.28, and depression filling will
behave incorrectly. **Verify**: `gdalinfo dem.tif` should show meters or check max values.

### TRAP: Cell area units (dt_011)
Cell area (`dArea`) must be in m² (square meters). If a GIS tool exports area in km²,
the value will be 10⁶ times too small, causing drainage density and all area-based
metrics to be wildly wrong. A 5km hex cell should have area ~21.65 × 10⁶ m², not 21.65.

### TRAP: Neighbor distance units (dt_012)
`aNeighbor_distance` must be in meters. If distances are in km or degrees, slope
calculations (Δz / distance) will be off by orders of magnitude.

### TRAP: Mesh type mismatch (dt_005)
The `sMesh_type` in the config must match the structure of the mesh JSON. A hexagon
mesh has 6 neighbors per cell; an MPAS mesh has variable connectivity. Using the wrong
parser silently produces garbage topology.

## Example

For a 5km hexagonal mesh over the Chesapeake Bay watershed:

```bash
# DEM: MERIT Hydro, already in EPSG:4326, meters
python mesh_converter.py \
    --dem /data/merit_hydro_chesapeake.tif \
    --resolution 5000 \
    --mesh-type hexagon \
    --output /data/mesh/hexagon_mesh_info.json

# Expected: ~2000-5000 cells depending on watershed size
```

Files in this skill

  • REFERENCES.md1.4 KB
  • format_spec.yaml24.8 KB
  • papers.json5 KB
  • s0_configuration_skill.md5 KB
  • s1_mesh_generation_skill.md5.5 KB
  • s2_flowline_preparation_skill.md5.7 KB
  • s3_execution_skill.md6.5 KB
  • s4_output_analysis_skill.md6.2 KB
  • s5_validation_skill.md6.8 KB
  • validation_convention.yaml16.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…