Claude-skill-registry ebfe_organize_models
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/ebfe-organize-models-gpt-cmdr-ras-commander" ~/.claude/skills/majiayu000-claude-skill-registry-ebfe-organize-models-0e750c && rm -rf "$T"
skills/data/ebfe-organize-models-gpt-cmdr-ras-commander/SKILL.mdOrganizing eBFE Models
Purpose
Organize 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
The skill must 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:
- HEC-HMS project.hms
- Basin model file.basin
- Meteorology file.met
- Control specifications.control
- Run configuration.run
- HMS results.results
in.dss
pathHydrology/
,.log
in HMS folders.out
Path indicators:
Hydrology/, HMS/
RAS Model/ Folder
Include files with these extensions or patterns:
- HEC-RAS project (validate: contains "Proj Title=", "Geom File=").prj
- Geometry file.g##
- Plan file.p##
- Flow file.f##
- Unsteady flow file.u##
- Sediment file.c##
- Bridge/culvert file.b##
- Boundary condition override.bco##
- Initial conditions override.IC.O##
- Cross section index.x##
- RAS Mapper project.rasmap
- DSS catalog (if in RAS folder).dsc
(if in RAS folder, not HMS folder).dss
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:
- GeoTIFF raster.tif
- Terrain HDF (if NOT .g##.hdf or .p##.hdf).hdf
- Virtual raster.vrt
- File geodatabase.gdb/
,.shp
,.shx
,.dbf
- Shapefiles (in Features/, Shp/, gis/ folders).prj- Folder named
(entire folder)Terrain/ - 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:
- Reports, guides.pdf
,.xlsx
- Inventories, metadata spreadsheets.xls
- Metadata.xml- Files with "Inventory" in name
- Files with "metadata" in name
- Files with "Report" in name
filesREADME*
Agent Deliverables
REQUIRED for Every Organization:
- ✅ Organized model in 4-folder structure
- ✅
- Agent work logagent/model_log.md - ✅
- Organization manifestMANIFEST.md - ✅ NEW: Generated
function inorganize_{modelname}()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
# Inspect the downloaded archive # - List all files # - Identify nested zips # - Detect pattern (1-4) # - Count .prj files (RAS) and .hms files (HMS)
Step 2: Extract Recursively
# Extract Models.zip # Find nested .zip files (_Final.zip, RAS_Submittal.zip, etc.) # Extract nested zips in place # Preserve directory structure during extraction
Step 3: Classify and Organize
# Recursively walk extracted content # For each file: # - Determine classification (HMS/RAS/Spatial/Docs) # - Move to appropriate standardized folder # - For RAS models with multiple projects: # - Group files by .prj stem # - Create subfolder per model # CRITICAL INTEGRATIONS (to create runnable HEC-RAS models): # 1. Move Output/ folder INTO HEC-RAS project folder # eBFE separates Output/ (pre-run HDF files) from Input/ (project) # HEC-RAS expects HDF files in project folder for model_folder in ras_model.glob('**/Input'): output_folder = model_folder.parent / 'Output' if output_folder.exists(): # Move all Output/*.hdf and other files INTO Input/ for output_file in output_folder.rglob('*'): if output_file.is_file(): shutil.copy2(output_file, model_folder / output_file.name) # 2. Move Terrain/ INTO HEC-RAS project folder # eBFE places Terrain/ as sibling to Input/ (breaks .rasmap references) # HEC-RAS expects Terrain/ in project folder for model_folder in ras_model.glob('**/Input'): terrain_folder = model_folder.parent / 'Terrain' if terrain_folder.exists(): # Move Terrain/ INTO Input/Terrain/ shutil.copytree(terrain_folder, model_folder / 'Terrain', dirs_exist_ok=True)
Step 4: Validate Organization
# Verify each folder: # - HMS Model/: Check for .hms files # - RAS Model/: Verify .prj files are valid HEC-RAS projects # - Spatial Data/: Check for terrain files # - Documentation/: Ensure reports are present # # Report summary: # - X HMS projects found # - Y RAS projects found # - Z terrain files found # - N documents organized
Step 4: Correct DSS File Paths (CRITICAL - VALIDATE EXISTENCE)
# CRITICAL: Fix DSS file path references in HEC-RAS files AND verify files exist # eBFE models have: # - Absolute paths from original system: C:\eBFE\... (doesn't exist on user system) # - Wrong relative paths: DSS\Input\file.dss (file is actually in same folder) # These cause "DSS path needs correction" GUI popups that break automation import re # Step 1: Find all DSS files that ACTUALLY EXIST in organized structure dss_files = list(ras_model_folder.glob('**/*.dss')) dss_lookup = {dss.name: dss for dss in dss_files} # Lookup by filename print(f"Found {len(dss_files)} DSS file(s):") for dss in dss_files: print(f" - {dss.relative_to(ras_model_folder)}") # Step 2: Find HEC-RAS files that reference DSS (.u##, .prj, .p##) hecras_files = [] hecras_files.extend(ras_model_folder.glob('**/*.u[0-9]*')) # Unsteady flow files hecras_files.extend(ras_model_folder.glob('**/*.p[0-9][0-9]')) # Plan files hecras_files.extend(ras_model_folder.glob('**/*.prj')) # Project files # Step 3: For each HEC-RAS file, validate and correct DSS references for hecras_file in hecras_files: content = hecras_file.read_text(encoding='utf-8', errors='ignore') modified = False # Find all "DSS File=" lines 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 # Extract just the filename # Check if this DSS file exists in our organized structure if dss_filename in dss_lookup: actual_dss_path = dss_lookup[dss_filename] # CRITICAL: Verify the DSS file actually exists if actual_dss_path.exists(): # Calculate correct relative path from HEC-RAS file to actual DSS location rel_path = actual_dss_path.relative_to(hecras_file.parent) rel_path_str = str(rel_path).replace('\\', '/') # Only replace if current path is wrong 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') # Result: Model opens without GUI popups, all DSS paths verified # Handles cases like: # DSS\Input\UPG_precip.dss → UPG_precip.dss (if file is in same folder) # C:\eBFE\...\file.dss → ../DSS/file.dss (if file is in subdirectory)
Step 5: Validate DSS Files (If Present)
# Validate DSS pathname contents (not just file paths) from ras_commander.dss import RasDss # Find all .dss files in RAS Model/ dss_files = list(ras_model_folder.glob('**/*.dss')) for dss_file in dss_files: # Get catalog catalog = RasDss.get_catalog(dss_file) # Check each pathname for pathname in catalog['pathname']: result = RasDss.check_pathname(dss_file, pathname) if not result.is_valid: # Document invalid pathnames in model_log.md pass
Step 6: Suggest Compute Test (If RAS Model Present)
# If RAS model organized, suggest optional compute test to user # This validates terrain, land use, and DSS files are correct 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)
# After compute test completes (if user runs it), check results for errors from ras_commander.hdf import HdfResultsPlan # Launch haiku subagent to check results 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.
# Generate organize_{modelname}() function # Write to: feature_dev_notes/eBFE_Integration/generated_functions/{studyarea}_{huc8}.py 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}. """ # Specific organization steps discovered by agent # Include pattern detection, extraction, classification # Use lessons learned from this organization pass
Deliverable: Write generated function to
feature_dev_notes/eBFE_Integration/generated_functions/organize_{studyarea}_{huc8}.py
Step 9: Generate Manifest and Model Log
# Create organization manifest: MANIFEST.md (in project root) # Document: # - Original archive pattern detected # - Files organized by category # - RAS project inventory (model names, types, sizes) # - HMS project inventory (if any) # - Terrain files inventory # - Document inventory # - DSS validation results # - Suggested compute test command # Create agent work log: agent/model_log.md (in project root) # **REQUIRED**: Every organized model MUST have agent/model_log.md # Document: # - Agent actions taken # - Files classified and moved # - Decisions made during organization # - Issues encountered and resolutions # - DSS validation results # - Generated function location # - Timestamps for all operations
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
# Organize a downloaded study area from pathlib import Path # Input: Raw downloaded and extracted files source = Path("D:/eBFE/raw_downloads/12040102_Spring_Models_extracted/") # Output: Organized into 4 folders target = Path("D:/eBFE/organized/SpringCreek_12040102/") # Agent organizes the files # Result: target/ now has HMS Model/, RAS Model/, Spatial Data/, Documentation/
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:
in Features/, Shp/, gis/ → Spatial Data/.prj - HEC-RAS:
with "Proj Title=" content → RAS Model/.prj
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
Generated Function Template
Every organization must generate an
organize_{modelname}() function:
File Location:
feature_dev_notes/eBFE_Integration/generated_functions/organize_{studyarea}_{huc8}.py
Template:
""" Generated organization function for {StudyArea} ({HUC8}) Generated by: ebfe_organize_models agent Date: {YYYY-MM-DD} Pattern: {Pattern X} """ from pathlib import Path from typing import Optional import shutil import zipfile from ras_commander.dss import RasDss def organize_{clean_name}( downloaded_folder: Path, output_folder: Optional[Path] = None, validate_dss: bool = True ) -> Path: """ Organize {StudyArea} ({HUC8}) eBFE model. Pattern {X}: {Pattern description discovered by agent} Args: downloaded_folder: Path to extracted {HUC8}_Models folder output_folder: Output location (default: ./ebfe_organized/{StudyArea}_{HUC8}/) validate_dss: Run DSS validation checks Returns: Path to organized model with 4-folder structure + agent/model_log.md Generated: {date} by ebfe_organize_models agent """ # [Agent-discovered organization steps] # 1. Extract nested zips (if pattern requires) # 2. Find .prj files recursively # 3. Classify files to HMS/RAS/Spatial/Docs # 4. Create 4-folder structure # 5. Move files to organized locations # 6. Validate DSS files if present # 7. Create agent/model_log.md # 8. Generate MANIFEST.md if validate_dss: # DSS validation code pass return output_folder # Example usage in notebook if __name__ == '__main__': """ Example usage for {StudyArea}: >>> from pathlib import Path >>> organized = organize_{clean_name}( ... Path(r"D:/downloads/{HUC8}_Models_extracted") ... ) >>> from ras_commander import init_ras_project >>> init_ras_project(organized / "RAS Model", "{version}") """
DSS Validation Example
# After organizing RAS Model, validate DSS files from ras_commander.dss import RasDss from pathlib import Path ras_model_folder = Path(r"D:/Organized/Model/RAS Model") dss_files = list(ras_model_folder.glob('**/*.dss')) dss_validation_results = [] for dss_file in dss_files: print(f"\nValidating: {dss_file.name}") # Get catalog try: catalog = RasDss.get_catalog(dss_file) print(f" Found {len(catalog)} pathnames") # Validate each pathname for pathname in catalog['pathname']: result = RasDss.check_pathname(dss_file, pathname) if not result.is_valid: dss_validation_results.append({ 'file': dss_file.name, 'pathname': pathname, 'issues': result.message }) print(f" ✗ INVALID: {pathname}") print(f" Issue: {result.message}") else: print(f" ✓ Valid: {pathname}") except Exception as e: print(f" ✗ Error reading DSS: {e}") dss_validation_results.append({ 'file': dss_file.name, 'pathname': 'N/A', 'issues': f"Failed to read: {e}" }) # Document results in agent/model_log.md if dss_validation_results: print(f"\n⚠️ Found {len(dss_validation_results)} DSS validation issues") print(" See agent/model_log.md for details") else: print(f"\n✓ All DSS files valid")
Compute Test Validation Workflow
# After organization, suggest optional compute test print("\n" + "=" * 80) print("OPTIONAL: Compute Test Validation") print("=" * 80) print("\nTo verify terrain, land use, and DSS files are correct:") print() print("```python") print(f"from ras_commander import init_ras_project, RasCmdr") print(f"from pathlib import Path") print() print(f"project = Path(r'{organized_folder / 'RAS Model'}')") print(f"init_ras_project(project, '{version}')") print(f"RasCmdr.compute_plan('01', num_cores=2)") print("```") print() print("If plan executes successfully → terrain/DSS files are valid") print("If plan fails → check compute messages for specific errors") print("=" * 80) # After user runs compute test, check results with haiku # (See Step 7 in workflow above)
See Also
- Research:
- 5 patterns documentedfeature_dev_notes/eBFE_Integration/RESEARCH_FINDINGS.md - Implementation:
- Design guidancefeature_dev_notes/eBFE_Integration/IMPLEMENTATION_SUMMARY.md - Discovery API:
- Download helpersfeature_dev_notes/eBFE_Integration/prototype_discovery.py - Generated Functions:
- Agent-generated deterministic functionsfeature_dev_notes/eBFE_Integration/generated_functions/ - DSS Validation:
- DSS validation patterns.claude/rules/hec-ras/dss-files.md - Results Checking:
- Haiku results checker.claude/agents/notebook-output-auditor.md