Validating DSS File Paths and Data Availability¶
Overview¶
This notebook demonstrates validation of DSS pathnames and boundary data before use in HEC-RAS. Validation catches issues early, preventing simulation failures.
What You'll Learn¶
- Use the validation framework for DSS pathnames
- Interpret ValidationReport severity levels
- Implement pre-flight checks for boundary conditions
- Handle validation failures gracefully
LLM Forward Approach¶
- Early Validation: Catch issues before running expensive simulations
- Clear Diagnostics: ValidationReports provide actionable error messages
- Audit Trail: Document which validations passed/failed
Reference Documentation¶
- See
.claude/rules/validation/validation-patterns.mdin ras-commander repo - HEC-DSS User's Manual
Understanding Validation Framework¶
The ras_commander.RasValidation module provides structured validation with severity levels:
ValidationSeverity Levels: - INFO: Informational (file size, metadata) - WARNING: Non-critical issue (large file, empty pathname parts) - ERROR: Critical issue (file not found, invalid format) - CRITICAL: Blocking issue (corrupted file, incompatible format)
Validation Methods:
- Detailed (check_*): Returns ValidationResult with full diagnostics
- Boolean (is_valid_*): Returns True/False for quick checks
When to Use Each: - Use detailed when you need diagnostic information - Use boolean for simple pass/fail decisions
Example: Pre-Flight Check¶
from ras_commander.dss import RasDss
from ras_commander.RasValidation import ValidationSeverity
# Comprehensive validation before running model
report = RasDss.check_pathname(
dss_file="boundary.dss",
pathname="//BASIN/LOCATION/FLOW/01JAN2020/1HOUR/OBS/"
)
# Check severity
if not report.is_valid:
print("Validation Failed - Cannot Run Model")
report.print_report(show_passed=False)
raise ValueError("Fix validation errors before running")
elif report.has_warnings:
print("Warnings Detected - Proceeding with Caution")
else:
print("All Validations Passed - Safe to Run")
# Proceed with model execution
RasCmdr.compute_plan("01")
Handling Validation Results¶
Strategy 1: Early Exit
if not report.is_valid:
logger.error("Validation failed - cannot proceed")
report.print_report(show_passed=False)
raise ValueError("Fix errors before running")
Strategy 2: Collect All Issues
all_valid = True
reports = {}
for bc_name, pathname in boundary_conditions.items():
report = RasDss.check_pathname(dss_file, pathname)
reports[bc_name] = report
if not report.is_valid:
all_valid = False
if not all_valid:
# Print all validation failures
for bc_name, report in reports.items():
if not report.is_valid:
print(f"{bc_name}:")
report.print_report(show_passed=False)
raise ValueError("Fix all errors")
Strategy 3: Graceful Degradation
# Try to use DSS boundary, fall back to default if invalid
if RasDss.is_pathname_available(dss_file, pathname):
bc_data = RasDss.get_timeseries(dss_file, pathname)
else:
logger.warning("Pathname not available - using default BC")
bc_data = get_default_boundary_condition()
# =============================================================================
# DEVELOPMENT MODE TOGGLE
# =============================================================================
# Set USE_LOCAL_SOURCE based on your setup:
# True = Use local source code (for developers editing ras-commander)
# False = Use pip-installed package (for users)
# =============================================================================
USE_LOCAL_SOURCE = True # <-- TOGGLE THIS
# -----------------------------------------------------------------------------
if USE_LOCAL_SOURCE:
import sys
from pathlib import Path
local_path = str(Path.cwd().parent) # Parent of examples/ = repo root
if local_path not in sys.path:
sys.path.insert(0, local_path) # Insert at position 0 = highest priority
print(f"📁 LOCAL SOURCE MODE: Loading from {local_path}/ras_commander")
else:
print("📦 PIP PACKAGE MODE: Loading installed ras-commander")
# Import ras-commander (will use local or pip based on toggle above)
from ras_commander import RasDss, RasExamples, ValidationSeverity
# Verify which version loaded
import ras_commander
print(f"✓ Loaded: {ras_commander.__file__}")
Parameters¶
Configure these values to customize the notebook for your project.
# =============================================================================
# PARAMETERS - Edit these to customize the notebook
# =============================================================================
from pathlib import Path
# Project Configuration
PROJECT_NAME = "BaldEagleCrkMulti2D" # Example project with DSS boundary files
RAS_VERSION = "7.0" # HEC-RAS version (6.3, 6.5, 6.6, etc.)
Overview¶
This notebook demonstrates the DSS pathname validation framework in ras-commander. DSS (Data Storage System) files are commonly used to store boundary conditions for HEC-RAS models. Validating pathnames and data availability is critical for ensuring model runs will succeed.
The validation framework provides: - Format validation (pathname structure) - File existence checks - Pathname catalog verification - Time series data availability checks - Comprehensive validation reports
We'll use the BaldEagleCrkMulti2D example project which includes DSS boundary conditions.
Extract Example Project¶
# Extract BaldEagleCrkMulti2D project (contains DSS boundary files)
project_path = RasExamples.extract_project(PROJECT_NAME, suffix="311")
print(f"\nProject extracted to: {project_path}")
2026-01-12 00:17:16 - ras_commander.RasExamples - INFO - Found zip file: C:\GH\ras-commander\examples\Example_Projects_6_6.zip
2026-01-12 00:17:16 - ras_commander.RasExamples - INFO - Loading project data from CSV...
2026-01-12 00:17:16 - ras_commander.RasExamples - INFO - Loaded 68 projects from CSV.
2026-01-12 00:17:16 - ras_commander.RasExamples - INFO - ----- RasExamples Extracting Project -----
2026-01-12 00:17:16 - ras_commander.RasExamples - INFO - Extracting project 'BaldEagleCrkMulti2D' as 'BaldEagleCrkMulti2D_311'
2026-01-12 00:17:16 - ras_commander.RasExamples - INFO - Folder 'BaldEagleCrkMulti2D_311' already exists. Deleting existing folder...
2026-01-12 00:17:16 - ras_commander.RasExamples - INFO - Existing folder 'BaldEagleCrkMulti2D_311' has been deleted.
2026-01-12 00:17:17 - ras_commander.RasExamples - INFO - Successfully extracted project 'BaldEagleCrkMulti2D' to C:\GH\ras-commander\examples\example_projects\BaldEagleCrkMulti2D_311
Project extracted to: C:\GH\ras-commander\examples\example_projects\BaldEagleCrkMulti2D_311
# Find DSS files in the project
from pathlib import Path
dss_files = list(project_path.glob("*.dss"))
print(f"Found {len(dss_files)} DSS file(s):")
for dss_file in dss_files:
print(f" - {dss_file.name} ({dss_file.stat().st_size / 1024:.2f} KB)")
Found 2 DSS file(s):
- BaldEagleDamBrk.dss (726.09 KB)
- Bald_Eagle_Creek.dss (29973.50 KB)
# Use first DSS file for validation examples
if dss_files:
test_dss_file = dss_files[0]
print(f"Using DSS file: {test_dss_file.name}")
# Get catalog to see available pathnames (returns DataFrame with 'pathname' column)
catalog_df = RasDss.get_catalog(test_dss_file)
catalog = catalog_df['pathname'].tolist() # Convert to list for easier iteration
print(f"\nDSS file contains {len(catalog)} pathname(s):")
for i, pathname in enumerate(catalog[:10], 1): # Show first 10
print(f" {i}. {pathname}")
if len(catalog) > 10:
print(f" ... and {len(catalog) - 10} more")
else:
print("⚠️ No DSS files found in project - will use synthetic examples")
test_dss_file = project_path / "boundary.dss" # For examples
catalog = [] # Empty list for synthetic examples
Using DSS file: BaldEagleDamBrk.dss
Configuring Java VM for DSS operations...
Found Java: C:\Program Files\Java\jre1.8.0_471
[OK] Java VM configured
DSS file contains 102 pathname(s):
1. /SA CONNECTION/Sayers Dam/FLOW-TOTAL/08Sep2018/1Minute/Grid Precip Infiltration/
2. /SA CONNECTION/Sayers Dam/FLOW-TOTAL/09Sep2018/1Minute/Grid Precip Infiltration/
3. /BCLINE/BaldEagleCr: DSNormalDepth/FLOW/10Sep2018/1Minute/Grid Precip Infiltration/
4. /SA CONNECTION/Sayers Dam/FLOW-TOTAL/10Sep2018/1Minute/Grid Precip Infiltration/
5. /SA CONNECTION/Sayers Dam/FLOW-TOTAL/11Sep2018/1Minute/Grid Precip Infiltration/
6. /SA CONNECTION/Sayers Dam/FLOW-TOTAL/12Sep2018/1Minute/Grid Precip Infiltration/
7. /SA CONNECTION/Sayers Dam/FLOW-TOTAL/13Sep2018/1Minute/Grid Precip Infiltration/
8. /SA CONNECTION/Sayers Dam/FLOW-WEIR/08Sep2018/1Minute/Grid Precip Infiltration/
9. /SA CONNECTION/Sayers Dam/FLOW-WEIR/09Sep2018/1Minute/Grid Precip Infiltration/
10. /SA CONNECTION/Sayers Dam/FLOW-WEIR/10Sep2018/1Minute/Grid Precip Infiltration/
... and 92 more
1. Format Validation: check_pathname_format()¶
DSS pathnames must follow the format: //A/B/C/D/E/F/
Where: - A = Basin/Project - B = Location - C = Parameter (e.g., FLOW, STAGE) - D = Date - E = Interval (e.g., 1HOUR, 15MIN) - F = Scenario/Version
# Example 1: Valid pathname format
valid_pathname = "//BASIN/LOCATION/FLOW/01JAN2020/1HOUR/OBS/"
result = RasDss.check_pathname_format(valid_pathname)
print(f"Pathname: {valid_pathname}")
print(f"Result: {result}")
print(f"\nDetails:")
for key, value in result.details.items():
print(f" {key}: {value}")
Pathname: //BASIN/LOCATION/FLOW/01JAN2020/1HOUR/OBS/
Result: [INFO] [PASS] path_format: DSS path format is valid
Details:
parts: {'basin': 'BASIN', 'location': 'LOCATION', 'parameter': 'FLOW', 'date': '01JAN2020', 'interval': '1HOUR', 'scenario': 'OBS'}
# Example 2: Invalid pathname - missing leading //
invalid_pathname1 = "/BASIN/LOCATION/FLOW/01JAN2020/1HOUR/OBS/"
result = RasDss.check_pathname_format(invalid_pathname1)
print(f"Pathname: {invalid_pathname1}")
print(f"Result: {result}")
print(f"Passed: {result.passed}")
print(f"Severity: {result.severity.value}")
Pathname: /BASIN/LOCATION/FLOW/01JAN2020/1HOUR/OBS/
Result: [INFO] [PASS] path_format: DSS path format is valid
Passed: True
Severity: info
# Example 3: Invalid pathname - wrong number of parts
invalid_pathname2 = "//BASIN/LOCATION/FLOW/01JAN2020/" # Missing parts
result = RasDss.check_pathname_format(invalid_pathname2)
print(f"Pathname: {invalid_pathname2}")
print(f"Result: {result}")
print(f"\nDetails:")
for key, value in result.details.items():
print(f" {key}: {value}")
Pathname: //BASIN/LOCATION/FLOW/01JAN2020/
Result: [ERROR] [FAIL] path_format: DSS path must have 6 parts (/A/B/C/D/E/F/), got 4: //BASIN/LOCATION/FLOW/01JAN2020/
Details:
pathname: //BASIN/LOCATION/FLOW/01JAN2020/
expected_parts: 6
actual_parts: 4
# Example 4: Valid but with empty parts (warning)
pathname_with_empty = "//BASIN/LOCATION/FLOW//1HOUR/OBS/" # Empty date part
result = RasDss.check_pathname_format(pathname_with_empty)
print(f"Pathname: {pathname_with_empty}")
print(f"Result: {result}")
print(f"Passed: {result.passed} (with warnings)")
print(f"Severity: {result.severity.value}")
Pathname: //BASIN/LOCATION/FLOW//1HOUR/OBS/
Result: [WARNING] [PASS] path_format: DSS path has empty parts: date (part 4)
Passed: True (with warnings)
Severity: warning
2. File Existence: check_file_exists()¶
Validates that the DSS file exists and is accessible.
# Example 1: Valid file (exists)
if dss_files:
result = RasDss.check_file_exists(test_dss_file)
print(f"File: {test_dss_file.name}")
print(f"Result: {result}")
print(f"\nDetails:")
for key, value in result.details.items():
print(f" {key}: {value}")
File: BaldEagleDamBrk.dss
Result: [INFO] [PASS] file_existence: DSS file exists and is readable
Details:
dss_file: C:\GH\ras-commander\examples\example_projects\BaldEagleCrkMulti2D_311\BaldEagleDamBrk.dss
file_size_mb: 0.71
# Example 2: Invalid file (doesn't exist)
nonexistent_file = project_path / "nonexistent.dss"
result = RasDss.check_file_exists(nonexistent_file)
print(f"File: {nonexistent_file.name}")
print(f"Result: {result}")
print(f"Passed: {result.passed}")
print(f"Severity: {result.severity.value} (CRITICAL - blocks all further checks)")
File: nonexistent.dss
Result: [CRITICAL] [FAIL] file_existence: DSS file not found: C:\GH\ras-commander\examples\example_projects\BaldEagleCrkMulti2D_311\nonexistent.dss
Passed: False
Severity: critical (CRITICAL - blocks all further checks)
3. Pathname Existence: check_pathname_exists()¶
Validates that a specific pathname exists in the DSS file catalog.
# Example 1: Pathname exists (use actual pathname from catalog)
if dss_files and len(catalog) > 0:
existing_pathname = catalog[0] # First pathname in catalog
result = RasDss.check_pathname_exists(test_dss_file, existing_pathname)
print(f"Pathname: {existing_pathname}")
print(f"Result: {result}")
print(f"\nDetails:")
for key, value in result.details.items():
print(f" {key}: {value}")
Pathname: /SA CONNECTION/Sayers Dam/FLOW-TOTAL/08Sep2018/1Minute/Grid Precip Infiltration/
Result: [INFO] [PASS] pathname_existence: Pathname exists in DSS file
Details:
total_paths: 102
# Example 2: Pathname doesn't exist
if dss_files:
missing_pathname = "//BASIN/NOWHERE/FLOW/01JAN2020/1HOUR/MISSING/"
result = RasDss.check_pathname_exists(test_dss_file, missing_pathname)
print(f"Pathname: {missing_pathname}")
print(f"Result: {result}")
print(f"\nDetails:")
for key, value in result.details.items():
if key == 'similar_paths':
print(f" {key}:")
for path in value:
print(f" - {path}")
else:
print(f" {key}: {value}")
Pathname: //BASIN/NOWHERE/FLOW/01JAN2020/1HOUR/MISSING/
Result: [ERROR] [FAIL] pathname_existence: Pathname not found in DSS file
Details:
pathname: //BASIN/NOWHERE/FLOW/01JAN2020/1HOUR/MISSING/
total_paths: 102
similar_paths:
4. Data Availability: check_data_availability()¶
Validates that time series data exists and optionally checks date range coverage.
# Example 1: Check data availability (without date range)
if dss_files and len(catalog) > 0:
data_pathname = catalog[0]
result = RasDss.check_data_availability(test_dss_file, data_pathname)
print(f"Pathname: {data_pathname}")
print(f"Result: {result}")
print(f"\nDetails:")
for key, value in result.details.items():
print(f" {key}: {value}")
Pathname: /SA CONNECTION/Sayers Dam/FLOW-TOTAL/08Sep2018/1Minute/Grid Precip Infiltration/
Result: [INFO] [PASS] data_availability: Time series data available (7201 points from 2018-09-09 to 2018-09-14)
Details:
data_points: 7201
actual_start: 2018-09-09 00:00:00
actual_end: 2018-09-14 00:00:00
units: cfs
interval: 1
# Example 2: Check data availability with expected date range
if dss_files and len(catalog) > 0:
from datetime import datetime
data_pathname = catalog[0]
# Get actual date range from data
df = RasDss.read_timeseries(test_dss_file, data_pathname)
actual_start = df.index.min()
actual_end = df.index.max()
print(f"Actual data range: {actual_start} to {actual_end}")
# Check with expected range that matches actual (should pass)
result = RasDss.check_data_availability(
test_dss_file,
data_pathname,
expected_start=actual_start,
expected_end=actual_end
)
print(f"\nValidation with matching range:")
print(f"Result: {result}")
Actual data range: 2018-09-09 00:00:00 to 2018-09-14 00:00:00
Validation with matching range:
Result: [INFO] [PASS] data_availability: Time series data available (7201 points from 2018-09-09 to 2018-09-14)
# Example 3: Check with expected range beyond actual data (warning)
if dss_files and len(catalog) > 0:
from datetime import datetime, timedelta
data_pathname = catalog[0]
df = RasDss.read_timeseries(test_dss_file, data_pathname)
actual_end = df.index.max()
# Request data extending beyond what's available
extended_end = actual_end + timedelta(days=365)
result = RasDss.check_data_availability(
test_dss_file,
data_pathname,
expected_end=extended_end
)
print(f"Validation with extended range:")
print(f"Result: {result}")
print(f"Severity: {result.severity.value} (WARNING - data incomplete)")
Validation with extended range:
Result: [INFO] [PASS] data_availability: Time series data available (7201 points from 2018-09-09 to 2018-09-14)
Severity: info (WARNING - data incomplete)
5. Comprehensive Validation: check_pathname()¶
Performs all validation checks in sequence and returns a comprehensive report.
# Example 1: Comprehensive validation - valid pathname
if dss_files and len(catalog) > 0:
valid_pathname = catalog[0]
report = RasDss.check_pathname(
dss_file=test_dss_file,
pathname=valid_pathname
)
print(f"Comprehensive validation for: {valid_pathname}")
print(f"\nReport: {report}")
print(f"Is valid: {report.is_valid}")
print(f"Has warnings: {report.has_warnings}")
# Print formatted report
report.print_report(show_passed=True)
Comprehensive validation for: /SA CONNECTION/Sayers Dam/FLOW-TOTAL/08Sep2018/1Minute/Grid Precip Infiltration/
Report: ValidationReport(target=DSS Pathname: /SA CONNECTION/Sayers Dam/FLOW-TOTAL/08Sep2018/1Minute/Grid Precip Infiltration/, 3 info, 0 warnings, 0 errors, 0 critical)
Is valid: True
Has warnings: False
================================================================================
Validation Report: DSS Pathname: /SA CONNECTION/Sayers Dam/FLOW-TOTAL/08Sep2018/1Minute/Grid Precip Infiltration/
Timestamp: 2026-01-12T00:17:18.362257
================================================================================
Summary: 3 info, 0 warnings, 0 errors, 0 critical
Overall Status: VALID
================================================================================
Detailed Results:
================================================================================
[INFO] [PASS] path_format: DSS path format is valid
parts: {'basin': 'SA CONNECTION', 'location': 'Sayers Dam', 'parameter': 'FLOW-TOTAL', 'date': '08Sep2018', 'interval': '1Minute', 'scenario': 'Grid Precip Infiltration'}
[INFO] [PASS] file_existence: DSS file exists and is readable
dss_file: C:\GH\ras-commander\examples\example_projects\BaldEagleCrkMulti2D_311\BaldEagleDamBrk.dss
file_size_mb: 0.71
[INFO] [PASS] pathname_existence: Pathname exists in DSS file
total_paths: 102
================================================================================
# Example 2: Comprehensive validation - invalid pathname
if dss_files:
invalid_pathname = "//BASIN/MISSING/FLOW/01JAN2020/1HOUR/NONE/"
report = RasDss.check_pathname(
dss_file=test_dss_file,
pathname=invalid_pathname
)
print(f"Comprehensive validation for: {invalid_pathname}")
print(f"\nIs valid: {report.is_valid}")
# Print only failures (default behavior)
report.print_report(show_passed=False)
Comprehensive validation for: //BASIN/MISSING/FLOW/01JAN2020/1HOUR/NONE/
Is valid: False
================================================================================
Validation Report: DSS Pathname: //BASIN/MISSING/FLOW/01JAN2020/1HOUR/NONE/
Timestamp: 2026-01-12T00:17:18.374050
================================================================================
Summary: 2 info, 0 warnings, 1 errors, 0 critical
Overall Status: INVALID
================================================================================
Detailed Results:
================================================================================
[ERROR] [FAIL] pathname_existence: Pathname not found in DSS file
pathname: //BASIN/MISSING/FLOW/01JAN2020/1HOUR/NONE/
total_paths: 102
similar_paths: []
================================================================================
# Example 3: Filter results by severity
if dss_files and len(catalog) > 0:
pathname = catalog[0]
report = RasDss.check_pathname(test_dss_file, pathname)
# Get only errors
errors = report.get_results_by_severity(ValidationSeverity.ERROR)
print(f"Errors found: {len(errors)}")
for error in errors:
print(f" - {error}")
# Get only warnings
warnings = report.get_results_by_severity(ValidationSeverity.WARNING)
print(f"\nWarnings found: {len(warnings)}")
for warning in warnings:
print(f" - {warning}")
# Get all failed checks
failed = report.get_failed_checks()
print(f"\nFailed checks: {len(failed)}")
Errors found: 0
Warnings found: 0
Failed checks: 0
Component-Level Validation¶
Validate individual DSS path components (A-F parts) for format correctness.
# Component-level validation of DSS path parts
print("DSS Path Component Validation:")
print("=" * 80)
# Parse pathnames from catalog to analyze components
if dss_files and len(catalog) > 0:
import re
# Parse DSS pathnames into components (A-F parts)
# Format: /A/B/C/D/E/F/ where:
# A = Basin, B = Location, C = Parameter, D = Date, E = Interval, F = Scenario
def parse_dss_pathname(pathname):
"""Parse DSS pathname into A-F parts."""
parts = pathname.strip('/').split('/')
if len(parts) >= 6:
return {
'A': parts[0], # Basin/Location
'B': parts[1], # Location/Sublocation
'C': parts[2], # Parameter (FLOW, STAGE, etc.)
'D': parts[3], # Date (DDMmmYYYY)
'E': parts[4], # Interval (1Minute, 1HOUR, etc.)
'F': parts[5] # Scenario/Version
}
return None
# Parse all pathnames
parsed_paths = [parse_dss_pathname(p) for p in catalog if parse_dss_pathname(p)]
# Validate D-part (Date format: DDMmmYYYY like 08Sep2018)
print("\nD-Part (Date) Validation:")
d_parts = list(set([p['D'] for p in parsed_paths]))
for d_part in d_parts[:10]: # Show first 10
if re.match(r'\d{2}[A-Za-z]{3}\d{4}', str(d_part)):
print(f" [OK] {d_part}")
elif d_part == '':
print(f" [INFO] '' - empty date (block data)")
else:
print(f" [WARN] '{d_part}' - non-standard date format")
if len(d_parts) > 10:
print(f" ... and {len(d_parts) - 10} more")
# Validate E-part (Interval)
print("\nE-Part (Interval) Validation:")
valid_intervals = ['1MIN', '5MIN', '15MIN', '30MIN', '1HOUR', '6HOUR', '1DAY',
'1MINUTE', '5MINUTE', '15MINUTE', '30MINUTE',
'IR-YEAR', 'IR-CENTURY', '1MINUTE', '1Minute']
e_parts = list(set([p['E'] for p in parsed_paths]))
for e_part in e_parts:
if str(e_part).upper() in [v.upper() for v in valid_intervals]:
print(f" [OK] {e_part}")
else:
print(f" [INFO] '{e_part}' - non-standard interval (may still be valid)")
# Summary of A-parts (Basin/Location identifiers)
print("\nA-Part (Basin/Location) Summary:")
a_parts = list(set([p['A'] for p in parsed_paths]))
print(f" Found {len(a_parts)} unique basin/location identifier(s)")
for a_part in a_parts[:5]: # Show first 5
print(f" - {a_part}")
if len(a_parts) > 5:
print(f" ... and {len(a_parts) - 5} more")
# Summary of C-parts (Parameters)
print("\nC-Part (Parameter) Summary:")
c_parts = list(set([p['C'] for p in parsed_paths]))
print(f" Found {len(c_parts)} unique parameter type(s)")
for c_part in c_parts[:5]: # Show first 5
print(f" - {c_part}")
if len(c_parts) > 5:
print(f" ... and {len(c_parts) - 5} more")
else:
print("No DSS pathnames found to validate")
6. Boolean Convenience Methods¶
For quick checks without detailed reports.
# Example 1: Quick pathname format check
pathnames_to_check = [
"//BASIN/LOC/FLOW/01JAN2020/1HOUR/OBS/", # Valid
"/BASIN/LOC/FLOW/01JAN2020/1HOUR/OBS/", # Invalid - missing //
"//BASIN/LOC/FLOW/01JAN2020/", # Invalid - too few parts
]
for pathname in pathnames_to_check:
is_valid = RasDss.is_valid_pathname(pathname)
status = "✓ VALID" if is_valid else "✗ INVALID"
print(f"{status}: {pathname}")
✓ VALID: //BASIN/LOC/FLOW/01JAN2020/1HOUR/OBS/
✓ VALID: /BASIN/LOC/FLOW/01JAN2020/1HOUR/OBS/
✗ INVALID: //BASIN/LOC/FLOW/01JAN2020/
# Example 2: Quick pathname availability check
if dss_files and len(catalog) > 0:
# Check if pathname is available (file exists, pathname exists, has data)
existing_pathname = catalog[0]
missing_pathname = "//BASIN/NOWHERE/FLOW/01JAN2020/1HOUR/NONE/"
print(f"Checking pathname availability:\n")
is_available1 = RasDss.is_pathname_available(test_dss_file, existing_pathname)
print(f"{'✓' if is_available1 else '✗'} {existing_pathname}")
print(f" Available: {is_available1}\n")
is_available2 = RasDss.is_pathname_available(test_dss_file, missing_pathname)
print(f"{'✓' if is_available2 else '✗'} {missing_pathname}")
print(f" Available: {is_available2}")
Checking pathname availability:
✓ /SA CONNECTION/Sayers Dam/FLOW-TOTAL/08Sep2018/1Minute/Grid Precip Infiltration/
Available: True
✗ //BASIN/NOWHERE/FLOW/01JAN2020/1HOUR/NONE/
Available: False
7. Practical Use Case: Pre-Flight Check for Model Run¶
Validate all boundary condition pathnames before executing a HEC-RAS plan.
# Simulate pre-flight check for multiple boundary conditions
if dss_files and len(catalog) > 0:
print("=" * 80)
print("PRE-FLIGHT CHECK: Boundary Condition Validation")
print("=" * 80)
# Use all pathnames from catalog (or subset if many)
pathnames_to_validate = catalog[:3] if len(catalog) > 3 else catalog
all_valid = True
for i, pathname in enumerate(pathnames_to_validate, 1):
print(f"\n[{i}/{len(pathnames_to_validate)}] Validating: {pathname}")
# Quick check
is_available = RasDss.is_pathname_available(test_dss_file, pathname)
if is_available:
print(f" ✓ PASS")
else:
print(f" ✗ FAIL - running detailed diagnostics...")
report = RasDss.check_pathname(test_dss_file, pathname)
report.print_report(show_passed=False)
all_valid = False
print("\n" + "=" * 80)
if all_valid:
print("✓ PRE-FLIGHT CHECK PASSED - All boundary conditions valid")
print(" Ready to execute HEC-RAS plan")
else:
print("✗ PRE-FLIGHT CHECK FAILED - Fix boundary conditions before running")
print("=" * 80)
================================================================================
PRE-FLIGHT CHECK: Boundary Condition Validation
================================================================================
[1/3] Validating: /SA CONNECTION/Sayers Dam/FLOW-TOTAL/08Sep2018/1Minute/Grid Precip Infiltration/
✓ PASS
[2/3] Validating: /SA CONNECTION/Sayers Dam/FLOW-TOTAL/09Sep2018/1Minute/Grid Precip Infiltration/
✓ PASS
[3/3] Validating: /BCLINE/BaldEagleCr: DSNormalDepth/FLOW/10Sep2018/1Minute/Grid Precip Infiltration/
✓ PASS
================================================================================
✓ PRE-FLIGHT CHECK PASSED - All boundary conditions valid
Ready to execute HEC-RAS plan
================================================================================
Cleanup¶
# Clean up extracted project
import shutil
if project_path.parent.name == "example_projects":
shutil.rmtree(project_path.parent, ignore_errors=True)
print("✓ Cleaned up example projects")
✓ Cleaned up example projects
Summary¶
This notebook demonstrated the DSS validation framework:
Individual Validation Methods:
- check_pathname_format() - Validates DSS pathname structure
- check_file_exists() - Verifies file accessibility
- check_pathname_exists() - Confirms pathname in catalog
- check_data_availability() - Validates time series coverage
Comprehensive Validation:
- check_pathname() - Runs all checks, returns ValidationReport
Boolean Conveniences:
- is_valid_pathname() - Quick format check
- is_pathname_available() - Quick availability check
Validation Reports: - Filter by severity (INFO, WARNING, ERROR, CRITICAL) - Get failed checks - Print formatted reports
Use these tools to ensure DSS boundary conditions are valid before running HEC-RAS models!