| name | ebfe_organize_models |
| model | sonnet |
| shared_corpus | true |
| harness_scope | shared |
| source_owner | gpt-cmdr |
| security_review | internal |
| description | Organize downloaded FEMA eBFE/BLE model files into standardized 4-folder structure.
Use when working with eBFE downloads that need organization into:
- HMS Model/ (HEC-HMS hydrologic models)
- RAS Model/ (HEC-RAS hydraulic models)
- Spatial Data/ (GIS, terrain, geodatabases)
- Documentation/ (reports, PDFs, metadata)
Handles variable archive structures, nested zips, and mixed content through
intelligent file analysis and recursive extraction.
|
Organizing eBFE Models
Purpose
When the user asks to organize eBFE or BLE downloads, use this skill to transform downloaded FEMA eBFE/BLE study area files into a standardized 4-folder structure, regardless of the original archive organization patterns.
Standardized Output Structure
Every organized eBFE study area should have this structure:
{StudyAreaName}_{HUC8}/
├── HMS Model/ # HEC-HMS hydrologic models
│ ├── {ProjectName}.hms
│ ├── {ProjectName}.basin
│ ├── *.dss
│ └── ... (all HMS-related files)
├── RAS Model/ # HEC-RAS hydraulic models
│ ├── {Model1}/
│ │ ├── {Model1}.prj
│ │ ├── {Model1}.g##
│ │ ├── {Model1}.p##
│ │ └── ... (all RAS project files)
│ └── {Model2}/...
├── Spatial Data/ # GIS, terrain, geodatabases
│ ├── Terrain/
│ ├── *.tif, *.hdf
│ ├── *.gdb/
│ └── ... (all spatial data)
└── Documentation/ # Reports, metadata, inventories
├── *.pdf
├── *.xlsx (inventories)
├── *_metadata.xml
└── ... (all documentation)
Input Patterns
Handle these downloaded archive patterns:
Pattern 1: Multiple 1D models in variable wrapper folders (80-200 MB)
Pattern 2: ModelURLs.txt links file (1 KB)
Pattern 3: Single 2D model in nested zip (5-15 GB)
Pattern 4: Compound HMS + RAS in nested zips (8+ GB)
See feature_dev_notes/eBFE_Integration/RESEARCH_FINDINGS.md for complete pattern documentation.
File Classification Rules
HMS Model/ Folder
Include files with these extensions or patterns:
.hms - HEC-HMS project
.basin - Basin model file
.met - Meteorology file
.control - Control specifications
.run - Run configuration
.results - HMS results
.dss in Hydrology/ path
.log, .out in HMS folders
Path indicators: Hydrology/, HMS/
RAS Model/ Folder
Include files with these extensions or patterns:
.prj - HEC-RAS project (validate: contains "Proj Title=", "Geom File=")
.g## - Geometry file
.p## - Plan file
.f## - Flow file
.u## - Unsteady flow file
.c## - Sediment file
.b## - Bridge/culvert file
.bco## - Boundary condition override
.IC.O## - Initial conditions override
.x## - Cross section index
.rasmap - RAS Mapper project
.dsc - DSS catalog (if in RAS folder)
.dss (if in RAS folder, not HMS folder)
Exclude: .prj files in Features/, Shp/, gis/ (shapefiles, not HEC-RAS)
Organization within RAS Model/:
- If single model: Place files directly in RAS Model/
- If multiple models: Create subfolder per model (use .prj stem as folder name)
Spatial Data/ Folder
Include files with these extensions or patterns:
.tif - GeoTIFF raster
.hdf - Terrain HDF (if NOT .g##.hdf or .p##.hdf)
.vrt - Virtual raster
.gdb/ - File geodatabase
.shp, .shx, .dbf, .prj - Shapefiles (in Features/, Shp/, gis/ folders)
- Folder named
Terrain/ (entire folder)
- Folder named
Spatial/, GIS/, Shp/, Features/
Exception: .g##.hdf (geometry preprocessor) and .p##.hdf (results) stay with RAS Model/
Documentation/ Folder
Include files with these extensions or patterns:
.pdf - Reports, guides
.xlsx, .xls - Inventories, metadata spreadsheets
.xml - Metadata
- Files with "Inventory" in name
- Files with "metadata" in name
- Files with "Report" in name
README* files
Agent Deliverables
REQUIRED for Every Organization:
- ✅ Organized model in 4-folder structure
- ✅
agent/model_log.md - Agent work log
- ✅
MANIFEST.md - Organization manifest
- ✅ NEW: Generated
organize_{modelname}() function in feature_dev_notes/eBFE_Integration/generated_functions/
- ✅ NEW: DSS validation results (if DSS files present)
- ✅ NEW: Suggested compute test command for user
- ✅ NEW: Haiku subagent results check (if compute test run)
Workflow
Step 1: Analyze Archive Structure
Step 2: Extract Recursively
Step 3: Classify and Organize
for model_folder in ras_model.glob('**/Input'):
output_folder = model_folder.parent / 'Output'
if output_folder.exists():
for output_file in output_folder.rglob('*'):
if output_file.is_file():
shutil.copy2(output_file, model_folder / output_file.name)
for model_folder in ras_model.glob('**/Input'):
terrain_folder = model_folder.parent / 'Terrain'
if terrain_folder.exists():
shutil.copytree(terrain_folder, model_folder / 'Terrain', dirs_exist_ok=True)
Step 4: Validate Organization
Step 4: Correct DSS File Paths (CRITICAL - VALIDATE EXISTENCE)
import re
dss_files = list(ras_model_folder.glob('**/*.dss'))
dss_lookup = {dss.name: dss for dss in dss_files}
print(f"Found {len(dss_files)} DSS file(s):")
for dss in dss_files:
print(f" - {dss.relative_to(ras_model_folder)}")
hecras_files = []
hecras_files.extend(ras_model_folder.glob('**/*.u[0-9]*'))
hecras_files.extend(ras_model_folder.glob('**/*.p[0-9][0-9]'))
hecras_files.extend(ras_model_folder.glob('**/*.prj'))
for hecras_file in hecras_files:
content = hecras_file.read_text(encoding='utf-8', errors='ignore')
modified = False
dss_file_pattern = re.compile(r'DSS File=(.+?)(?:\n|$)', re.IGNORECASE)
for match in dss_file_pattern.finditer(content):
old_path = match.group(1).strip()
dss_filename = Path(old_path).name
if dss_filename in dss_lookup:
actual_dss_path = dss_lookup[dss_filename]
if actual_dss_path.exists():
rel_path = actual_dss_path.relative_to(hecras_file.parent)
rel_path_str = str(rel_path).replace('\\', '/')
if old_path != rel_path_str:
old_full = f"DSS File={old_path}"
new_full = f"DSS File={rel_path_str}"
content = content.replace(old_full, new_full)
modified = True
print(f" Corrected in {hecras_file.name}:")
print(f" Old: {old_path}")
print(f" New: {rel_path_str} (✓ verified exists)")
else:
print(f" ⚠️ WARNING: DSS not found: {dss_filename}")
else:
print(f" ⚠️ WARNING: DSS not in organized structure: {dss_filename}")
if modified:
hecras_file.write_text(content, encoding='utf-8')
Step 5: Validate DSS Files (If Present)
from ras_commander.dss import RasDss
dss_files = list(ras_model_folder.glob('**/*.dss'))
for dss_file in dss_files:
catalog = RasDss.get_catalog(dss_file)
for pathname in catalog['pathname']:
result = RasDss.check_pathname(dss_file, pathname)
if not result.is_valid:
pass
Step 6: Suggest Compute Test (If RAS Model Present)
print("=" * 80)
print("OPTIONAL VALIDATION: Compute Test")
print("=" * 80)
print("To verify terrain, land use, and DSS files are correct,")
print("run at least one plan:")
print()
print(" from ras_commander import init_ras_project, RasCmdr")
print(f" init_ras_project(r'{ras_model_folder}', '{version}')")
print(" RasCmdr.compute_plan('01', num_cores=2)")
print()
print("If the plan executes successfully, terrain/DSS files are valid.")
print("=" * 80)
Step 7: Check Results with Haiku Subagent (If Compute Test Run)
from ras_commander.hdf import HdfResultsPlan
Task(
subagent_type="notebook-output-auditor",
model="haiku",
description="Check HEC-RAS results for errors",
prompt=f"""
Check HEC-RAS results for errors in: {hdf_file}
Extract compute messages and check for:
- Error messages
- Warning messages
- Convergence issues
- Numerical instabilities
- Missing data
Write findings to: {agent_folder}/compute_test_results.md
"""
)
Step 8: Generate Deterministic Function
REQUIRED: After organizing each model, generate a Python function for future use.
def organize_{clean_name}(
downloaded_folder: Path,
output_folder: Optional[Path] = None
) -> Path:
"""
Organize {StudyArea} ({HUC8}) eBFE model.
Pattern {X}: {Pattern description}
Generated by ebfe_organize_models agent on {date}.
"""
pass
Deliverable: Write generated function to feature_dev_notes/eBFE_Integration/generated_functions/organize_{studyarea}_{huc8}.py
Step 9: Generate Manifest and Model Log
Output Format
REQUIRED: agent/model_log.md
CRITICAL: Every organized eBFE model MUST have agent/model_log.md documenting agent work.
Location: {StudyAreaName}_{HUC8}/agent/model_log.md
Template:
# Agent Work Log - {StudyAreaName}
**Agent**: ebfe_organize_models
**Date**: {YYYY-MM-DD HH:MM:SS}
**Study Area**: {Name} ({HUC8})
**Pattern**: {Pattern 1/2/3/4}
## Actions Taken
### Archive Extraction
- Extracted: {source_archive}
- Nested zips: {list any nested zips extracted}
- Total files extracted: {count}
### File Classification
{For each file category, list files moved}
#### HMS Model (X files, Y MB)
- {list key files}
#### RAS Model (X files, Y GB)
- {list models and key files}
#### Spatial Data (X files, Y MB)
- {list terrain, shapefiles, etc.}
#### Documentation (X files, Y MB)
- {list reports, inventories}
### Decisions Made
- {Document any classification decisions}
- {Document handling of ambiguous files}
- {Document terrain handling approach}
### Issues Encountered
- {List any problems}
- {Document resolutions}
### Validation Checks
- [x] All files classified
- [x] RAS .prj files validated (not shapefiles)
- [x] Terrain location documented
- [x] Manifest created
## Next Steps for User
{Provide clear next steps, e.g., testing with ras-commander}
MANIFEST.md Template
# eBFE Model Organization Manifest
**Study Area**: {Name}
**HUC8**: {HUC8}
**Original Pattern**: {Pattern 1/2/3/4}
**Organized Date**: {YYYY-MM-DD}
## HMS Model
{X} HEC-HMS projects found:
- {ProjectName}.hms - {StormFrequencies}
## RAS Model
{Y} HEC-RAS projects found:
### {ModelName1}
- Type: {1D/2D}
- Plans: {#}
- Size: {MB/GB}
- Terrain: {Self-contained/External/Not needed}
### {ModelName2}
...
## Spatial Data
{Z} terrain/spatial files:
- {TerrainFile1} - {Size}
- Geodatabase: {.gdb folders}
- Shapefiles: {count}
## Documentation
{N} documents:
- {Report1}.pdf - {Size}
- {Inventory}.xlsx
- {Metadata}.xml
## Notes
{Any special observations or issues encountered}
Example Usage
from pathlib import Path
source = Path("D:/eBFE/raw_downloads/12040102_Spring_Models_extracted/")
target = Path("D:/eBFE/organized/SpringCreek_12040102/")
Special Handling Notes
Nested Zips
- Recursively extract _Final.zip, RAS_Submittal.zip, etc.
- Delete intermediate zips after extraction (optional)
- Preserve meaningful folder names
Shapefile .prj vs HEC-RAS .prj
- Shapefiles:
.prj in Features/, Shp/, gis/ → Spatial Data/
- HEC-RAS:
.prj with "Proj Title=" content → RAS Model/
Self-Contained vs External Terrain
- If Terrain/ folder in model directory → stays with RAS Model/, copy to Spatial Data/
- If .rasmap references external terrain → document in manifest
Multiple RAS Projects
- Create subfolder per .prj file using stem name
- Group related files (.g##, .p##, .f##) with matching basename
- Keep directory hierarchy for watershed organization if meaningful
Templates and Validation
For generated function templates, DSS validation examples, and compute test workflows, see references/templates-and-validation.md.
Cross-References
Skills (related workflows):
ebfe_validate_models -- Use downstream to validate organized models
Agents (delegate when needed):
ebfe-organizer -- Delegate for complex multi-model eBFE organization
Primary sources:
ras_commander/ebfe_models.py -- RasEbfeModels implementation
docs/ebfe_models.md -- Complete eBFE documentation