ras-commander 0.51.0__py3-none-any.whl → 0.52.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ras_commander/HdfBase.py +344 -307
 - ras_commander/HdfFluvialPluvial.py +554 -309
 - ras_commander/HdfMesh.py +461 -461
 - ras_commander/HdfUtils.py +434 -434
 - ras_commander/HdfXsec.py +56 -38
 - ras_commander/RasPrj.py +93 -55
 - {ras_commander-0.51.0.dist-info → ras_commander-0.52.0.dist-info}/METADATA +11 -8
 - {ras_commander-0.51.0.dist-info → ras_commander-0.52.0.dist-info}/RECORD +11 -11
 - {ras_commander-0.51.0.dist-info → ras_commander-0.52.0.dist-info}/WHEEL +1 -1
 - {ras_commander-0.51.0.dist-info → ras_commander-0.52.0.dist-info}/LICENSE +0 -0
 - {ras_commander-0.51.0.dist-info → ras_commander-0.52.0.dist-info}/top_level.txt +0 -0
 
    
        ras_commander/HdfXsec.py
    CHANGED
    
    | 
         @@ -99,7 +99,7 @@ class HdfXsec: 
     | 
|
| 
       99 
99 
     | 
    
         
             
                    """
         
     | 
| 
       100 
100 
     | 
    
         
             
                    try:
         
     | 
| 
       101 
101 
     | 
    
         
             
                        with h5py.File(hdf_path, 'r') as hdf:
         
     | 
| 
       102 
     | 
    
         
            -
                            # Extract datasets
         
     | 
| 
      
 102 
     | 
    
         
            +
                            # Extract required datasets
         
     | 
| 
       103 
103 
     | 
    
         
             
                            poly_info = hdf['/Geometry/Cross Sections/Polyline Info'][:]
         
     | 
| 
       104 
104 
     | 
    
         
             
                            poly_parts = hdf['/Geometry/Cross Sections/Polyline Parts'][:]
         
     | 
| 
       105 
105 
     | 
    
         
             
                            poly_points = hdf['/Geometry/Cross Sections/Polyline Points'][:]
         
     | 
| 
         @@ -182,43 +182,61 @@ class HdfXsec: 
     | 
|
| 
       182 
182 
     | 
    
         
             
                                    else:
         
     | 
| 
       183 
183 
     | 
    
         
             
                                        ineffective_blocks.append([])
         
     | 
| 
       184 
184 
     | 
    
         | 
| 
       185 
     | 
    
         
            -
                            # Create  
     | 
| 
       186 
     | 
    
         
            -
                             
     | 
| 
       187 
     | 
    
         
            -
                                 
     | 
| 
       188 
     | 
    
         
            -
                                 
     | 
| 
       189 
     | 
    
         
            -
             
     | 
| 
       190 
     | 
    
         
            -
             
     | 
| 
       191 
     | 
    
         
            -
             
     | 
| 
       192 
     | 
    
         
            -
             
     | 
| 
       193 
     | 
    
         
            -
             
     | 
| 
       194 
     | 
    
         
            -
             
     | 
| 
       195 
     | 
    
         
            -
             
     | 
| 
       196 
     | 
    
         
            -
             
     | 
| 
       197 
     | 
    
         
            -
             
     | 
| 
       198 
     | 
    
         
            -
             
     | 
| 
       199 
     | 
    
         
            -
             
     | 
| 
       200 
     | 
    
         
            -
             
     | 
| 
       201 
     | 
    
         
            -
             
     | 
| 
       202 
     | 
    
         
            -
             
     | 
| 
       203 
     | 
    
         
            -
             
     | 
| 
       204 
     | 
    
         
            -
             
     | 
| 
       205 
     | 
    
         
            -
             
     | 
| 
       206 
     | 
    
         
            -
             
     | 
| 
       207 
     | 
    
         
            -
             
     | 
| 
       208 
     | 
    
         
            -
             
     | 
| 
       209 
     | 
    
         
            -
             
     | 
| 
       210 
     | 
    
         
            -
             
     | 
| 
       211 
     | 
    
         
            -
             
     | 
| 
       212 
     | 
    
         
            -
             
     | 
| 
       213 
     | 
    
         
            -
             
     | 
| 
       214 
     | 
    
         
            -
             
     | 
| 
       215 
     | 
    
         
            -
             
     | 
| 
       216 
     | 
    
         
            -
             
     | 
| 
       217 
     | 
    
         
            -
             
     | 
| 
       218 
     | 
    
         
            -
             
     | 
| 
       219 
     | 
    
         
            -
             
     | 
| 
       220 
     | 
    
         
            -
                                 
     | 
| 
      
 185 
     | 
    
         
            +
                            # Create base dictionary with required fields
         
     | 
| 
      
 186 
     | 
    
         
            +
                            data = {
         
     | 
| 
      
 187 
     | 
    
         
            +
                                'geometry': geometries,
         
     | 
| 
      
 188 
     | 
    
         
            +
                                'station_elevation': station_elevations,
         
     | 
| 
      
 189 
     | 
    
         
            +
                                'mannings_n': mannings_n,
         
     | 
| 
      
 190 
     | 
    
         
            +
                                'ineffective_blocks': ineffective_blocks,
         
     | 
| 
      
 191 
     | 
    
         
            +
                            }
         
     | 
| 
      
 192 
     | 
    
         
            +
                            
         
     | 
| 
      
 193 
     | 
    
         
            +
                            # Define field mappings with default values
         
     | 
| 
      
 194 
     | 
    
         
            +
                            field_mappings = {
         
     | 
| 
      
 195 
     | 
    
         
            +
                                'River': ('River', ''),
         
     | 
| 
      
 196 
     | 
    
         
            +
                                'Reach': ('Reach', ''),
         
     | 
| 
      
 197 
     | 
    
         
            +
                                'RS': ('RS', ''),
         
     | 
| 
      
 198 
     | 
    
         
            +
                                'Name': ('Name', ''),
         
     | 
| 
      
 199 
     | 
    
         
            +
                                'Description': ('Description', ''),
         
     | 
| 
      
 200 
     | 
    
         
            +
                                'Len Left': ('Len Left', 0.0),
         
     | 
| 
      
 201 
     | 
    
         
            +
                                'Len Channel': ('Len Channel', 0.0),
         
     | 
| 
      
 202 
     | 
    
         
            +
                                'Len Right': ('Len Right', 0.0),
         
     | 
| 
      
 203 
     | 
    
         
            +
                                'Left Bank': ('Left Bank', 0.0),
         
     | 
| 
      
 204 
     | 
    
         
            +
                                'Right Bank': ('Right Bank', 0.0),
         
     | 
| 
      
 205 
     | 
    
         
            +
                                'Friction Mode': ('Friction Mode', ''),
         
     | 
| 
      
 206 
     | 
    
         
            +
                                'Contr': ('Contr', 0.0),
         
     | 
| 
      
 207 
     | 
    
         
            +
                                'Expan': ('Expan', 0.0),
         
     | 
| 
      
 208 
     | 
    
         
            +
                                'Left Levee Sta': ('Left Levee Sta', None),
         
     | 
| 
      
 209 
     | 
    
         
            +
                                'Left Levee Elev': ('Left Levee Elev', None),
         
     | 
| 
      
 210 
     | 
    
         
            +
                                'Right Levee Sta': ('Right Levee Sta', None),
         
     | 
| 
      
 211 
     | 
    
         
            +
                                'Right Levee Elev': ('Right Levee Elev', None),
         
     | 
| 
      
 212 
     | 
    
         
            +
                                'HP Count': ('HP Count', 0),
         
     | 
| 
      
 213 
     | 
    
         
            +
                                'HP Start Elev': ('HP Start Elev', 0.0),
         
     | 
| 
      
 214 
     | 
    
         
            +
                                'HP Vert Incr': ('HP Vert Incr', 0.0),
         
     | 
| 
      
 215 
     | 
    
         
            +
                                'HP LOB Slices': ('HP LOB Slices', 0),
         
     | 
| 
      
 216 
     | 
    
         
            +
                                'HP Chan Slices': ('HP Chan Slices', 0),
         
     | 
| 
      
 217 
     | 
    
         
            +
                                'HP ROB Slices': ('HP ROB Slices', 0),
         
     | 
| 
      
 218 
     | 
    
         
            +
                                'Ineff Block Mode': ('Ineff Block Mode', 0),
         
     | 
| 
      
 219 
     | 
    
         
            +
                                'Obstr Block Mode': ('Obstr Block Mode', 0),
         
     | 
| 
      
 220 
     | 
    
         
            +
                                'Default Centerline': ('Default Centerline', 0),
         
     | 
| 
      
 221 
     | 
    
         
            +
                                'Last Edited': ('Last Edited', '')
         
     | 
| 
      
 222 
     | 
    
         
            +
                            }
         
     | 
| 
       221 
223 
     | 
    
         | 
| 
      
 224 
     | 
    
         
            +
                            # Add fields that exist in xs_attrs
         
     | 
| 
      
 225 
     | 
    
         
            +
                            for field_name, (attr_name, default_value) in field_mappings.items():
         
     | 
| 
      
 226 
     | 
    
         
            +
                                if attr_name in xs_attrs.dtype.names:
         
     | 
| 
      
 227 
     | 
    
         
            +
                                    if xs_attrs[attr_name].dtype.kind == 'S':
         
     | 
| 
      
 228 
     | 
    
         
            +
                                        # Handle string fields
         
     | 
| 
      
 229 
     | 
    
         
            +
                                        data[field_name] = [x[attr_name].decode('utf-8').strip() 
         
     | 
| 
      
 230 
     | 
    
         
            +
                                                          for x in xs_attrs]
         
     | 
| 
      
 231 
     | 
    
         
            +
                                    else:
         
     | 
| 
      
 232 
     | 
    
         
            +
                                        # Handle numeric fields
         
     | 
| 
      
 233 
     | 
    
         
            +
                                        data[field_name] = xs_attrs[attr_name]
         
     | 
| 
      
 234 
     | 
    
         
            +
                                else:
         
     | 
| 
      
 235 
     | 
    
         
            +
                                    # Use default value if field doesn't exist
         
     | 
| 
      
 236 
     | 
    
         
            +
                                    data[field_name] = [default_value] * len(geometries)
         
     | 
| 
      
 237 
     | 
    
         
            +
                                    logger.debug(f"Field {attr_name} not found in attributes, using default value")
         
     | 
| 
      
 238 
     | 
    
         
            +
                            
         
     | 
| 
      
 239 
     | 
    
         
            +
                            if geometries:
         
     | 
| 
       222 
240 
     | 
    
         
             
                                gdf = gpd.GeoDataFrame(data)
         
     | 
| 
       223 
241 
     | 
    
         | 
| 
       224 
242 
     | 
    
         
             
                                # Set CRS if available
         
     | 
| 
         @@ -233,7 +251,7 @@ class HdfXsec: 
     | 
|
| 
       233 
251 
     | 
    
         
             
                            return gpd.GeoDataFrame()
         
     | 
| 
       234 
252 
     | 
    
         | 
| 
       235 
253 
     | 
    
         
             
                    except Exception as e:
         
     | 
| 
       236 
     | 
    
         
            -
                         
     | 
| 
      
 254 
     | 
    
         
            +
                        logger.error(f"Error processing cross-section data: {str(e)}")
         
     | 
| 
       237 
255 
     | 
    
         
             
                        return gpd.GeoDataFrame()
         
     | 
| 
       238 
256 
     | 
    
         | 
| 
       239 
257 
     | 
    
         
             
                @staticmethod
         
     | 
    
        ras_commander/RasPrj.py
    CHANGED
    
    | 
         @@ -83,6 +83,31 @@ from ras_commander.Decorators import log_call 
     | 
|
| 
       83 
83 
     | 
    
         | 
| 
       84 
84 
     | 
    
         
             
            logger = get_logger(__name__)
         
     | 
| 
       85 
85 
     | 
    
         | 
| 
      
 86 
     | 
    
         
            +
            def read_file_with_fallback_encoding(file_path, encodings=['utf-8', 'latin1', 'cp1252', 'iso-8859-1']):
         
     | 
| 
      
 87 
     | 
    
         
            +
                """
         
     | 
| 
      
 88 
     | 
    
         
            +
                Attempt to read a file using multiple encodings.
         
     | 
| 
      
 89 
     | 
    
         
            +
                
         
     | 
| 
      
 90 
     | 
    
         
            +
                Args:
         
     | 
| 
      
 91 
     | 
    
         
            +
                    file_path (str or Path): Path to the file to read
         
     | 
| 
      
 92 
     | 
    
         
            +
                    encodings (list): List of encodings to try, in order of preference
         
     | 
| 
      
 93 
     | 
    
         
            +
                
         
     | 
| 
      
 94 
     | 
    
         
            +
                Returns:
         
     | 
| 
      
 95 
     | 
    
         
            +
                    tuple: (content, encoding_used) or (None, None) if all encodings fail
         
     | 
| 
      
 96 
     | 
    
         
            +
                """
         
     | 
| 
      
 97 
     | 
    
         
            +
                for encoding in encodings:
         
     | 
| 
      
 98 
     | 
    
         
            +
                    try:
         
     | 
| 
      
 99 
     | 
    
         
            +
                        with open(file_path, 'r', encoding=encoding) as file:
         
     | 
| 
      
 100 
     | 
    
         
            +
                            content = file.read()
         
     | 
| 
      
 101 
     | 
    
         
            +
                            return content, encoding
         
     | 
| 
      
 102 
     | 
    
         
            +
                    except UnicodeDecodeError:
         
     | 
| 
      
 103 
     | 
    
         
            +
                        continue
         
     | 
| 
      
 104 
     | 
    
         
            +
                    except Exception as e:
         
     | 
| 
      
 105 
     | 
    
         
            +
                        logger.error(f"Error reading file {file_path} with {encoding} encoding: {e}")
         
     | 
| 
      
 106 
     | 
    
         
            +
                        continue
         
     | 
| 
      
 107 
     | 
    
         
            +
                
         
     | 
| 
      
 108 
     | 
    
         
            +
                logger.error(f"Failed to read file {file_path} with any of the attempted encodings: {encodings}")
         
     | 
| 
      
 109 
     | 
    
         
            +
                return None, None
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
       86 
111 
     | 
    
         
             
            class RasPrj:
         
     | 
| 
       87 
112 
     | 
    
         | 
| 
       88 
113 
     | 
    
         
             
                def __init__(self):
         
     | 
| 
         @@ -153,16 +178,20 @@ class RasPrj: 
     | 
|
| 
       153 
178 
     | 
    
         
             
                        str: The full path to the geometry HDF file, or None if not found.
         
     | 
| 
       154 
179 
     | 
    
         
             
                    """
         
     | 
| 
       155 
180 
     | 
    
         
             
                    plan_file_path = self.project_folder / f"{self.project_name}.p{plan_number}"
         
     | 
| 
      
 181 
     | 
    
         
            +
                    content, encoding = read_file_with_fallback_encoding(plan_file_path)
         
     | 
| 
      
 182 
     | 
    
         
            +
                    
         
     | 
| 
      
 183 
     | 
    
         
            +
                    if content is None:
         
     | 
| 
      
 184 
     | 
    
         
            +
                        return None
         
     | 
| 
      
 185 
     | 
    
         
            +
                    
         
     | 
| 
       156 
186 
     | 
    
         
             
                    try:
         
     | 
| 
       157 
     | 
    
         
            -
                         
     | 
| 
       158 
     | 
    
         
            -
                             
     | 
| 
       159 
     | 
    
         
            -
                                 
     | 
| 
       160 
     | 
    
         
            -
             
     | 
| 
       161 
     | 
    
         
            -
             
     | 
| 
       162 
     | 
    
         
            -
                                     
     | 
| 
       163 
     | 
    
         
            -
             
     | 
| 
       164 
     | 
    
         
            -
                                     
     | 
| 
       165 
     | 
    
         
            -
                                        return None
         
     | 
| 
      
 187 
     | 
    
         
            +
                        for line in content.splitlines():
         
     | 
| 
      
 188 
     | 
    
         
            +
                            if line.startswith("Geom File="):
         
     | 
| 
      
 189 
     | 
    
         
            +
                                geom_file = line.strip().split('=')[1]
         
     | 
| 
      
 190 
     | 
    
         
            +
                                geom_hdf_path = self.project_folder / f"{self.project_name}.{geom_file}.hdf"
         
     | 
| 
      
 191 
     | 
    
         
            +
                                if geom_hdf_path.exists():
         
     | 
| 
      
 192 
     | 
    
         
            +
                                    return str(geom_hdf_path)
         
     | 
| 
      
 193 
     | 
    
         
            +
                                else:
         
     | 
| 
      
 194 
     | 
    
         
            +
                                    return None
         
     | 
| 
       166 
195 
     | 
    
         
             
                    except Exception as e:
         
     | 
| 
       167 
196 
     | 
    
         
             
                        logger.error(f"Error reading plan file for geometry: {e}")
         
     | 
| 
       168 
197 
     | 
    
         
             
                    return None
         
     | 
| 
         @@ -179,51 +208,54 @@ class RasPrj: 
     | 
|
| 
       179 
208 
     | 
    
         
             
                        dict: Dictionary containing extracted plan information.
         
     | 
| 
       180 
209 
     | 
    
         
             
                    """
         
     | 
| 
       181 
210 
     | 
    
         
             
                    plan_info = {}
         
     | 
| 
      
 211 
     | 
    
         
            +
                    content, encoding = read_file_with_fallback_encoding(plan_file_path)
         
     | 
| 
      
 212 
     | 
    
         
            +
                    
         
     | 
| 
      
 213 
     | 
    
         
            +
                    if content is None:
         
     | 
| 
      
 214 
     | 
    
         
            +
                        logger.error(f"Could not read plan file {plan_file_path} with any supported encoding")
         
     | 
| 
      
 215 
     | 
    
         
            +
                        return plan_info
         
     | 
| 
      
 216 
     | 
    
         
            +
                    
         
     | 
| 
       182 
217 
     | 
    
         
             
                    try:
         
     | 
| 
       183 
     | 
    
         
            -
                         
     | 
| 
       184 
     | 
    
         
            -
             
     | 
| 
       185 
     | 
    
         
            -
             
     | 
| 
       186 
     | 
    
         
            -
                             
     | 
| 
       187 
     | 
    
         
            -
             
     | 
| 
       188 
     | 
    
         
            -
             
     | 
| 
       189 
     | 
    
         
            -
             
     | 
| 
       190 
     | 
    
         
            -
             
     | 
| 
       191 
     | 
    
         
            -
             
     | 
| 
       192 
     | 
    
         
            -
                            
         
     | 
| 
       193 
     | 
    
         
            -
                             
     | 
| 
       194 
     | 
    
         
            -
                             
     | 
| 
       195 
     | 
    
         
            -
             
     | 
| 
       196 
     | 
    
         
            -
             
     | 
| 
       197 
     | 
    
         
            -
             
     | 
| 
       198 
     | 
    
         
            -
             
     | 
| 
       199 
     | 
    
         
            -
             
     | 
| 
       200 
     | 
    
         
            -
             
     | 
| 
       201 
     | 
    
         
            -
             
     | 
| 
       202 
     | 
    
         
            -
             
     | 
| 
       203 
     | 
    
         
            -
             
     | 
| 
       204 
     | 
    
         
            -
             
     | 
| 
       205 
     | 
    
         
            -
             
     | 
| 
       206 
     | 
    
         
            -
             
     | 
| 
       207 
     | 
    
         
            -
             
     | 
| 
       208 
     | 
    
         
            -
             
     | 
| 
       209 
     | 
    
         
            -
             
     | 
| 
       210 
     | 
    
         
            -
             
     | 
| 
       211 
     | 
    
         
            -
             
     | 
| 
       212 
     | 
    
         
            -
             
     | 
| 
       213 
     | 
    
         
            -
             
     | 
| 
       214 
     | 
    
         
            -
             
     | 
| 
       215 
     | 
    
         
            -
             
     | 
| 
       216 
     | 
    
         
            -
             
     | 
| 
       217 
     | 
    
         
            -
                             
     | 
| 
       218 
     | 
    
         
            -
                            
         
     | 
| 
       219 
     | 
    
         
            -
             
     | 
| 
       220 
     | 
    
         
            -
                                match = re.search(pattern, content)
         
     | 
| 
       221 
     | 
    
         
            -
                                if match:
         
     | 
| 
       222 
     | 
    
         
            -
                                    plan_info[key] = match.group(1).strip()
         
     | 
| 
      
 218 
     | 
    
         
            +
                        # Extract description
         
     | 
| 
      
 219 
     | 
    
         
            +
                        description_match = re.search(r'Begin DESCRIPTION(.*?)END DESCRIPTION', content, re.DOTALL)
         
     | 
| 
      
 220 
     | 
    
         
            +
                        if description_match:
         
     | 
| 
      
 221 
     | 
    
         
            +
                            plan_info['description'] = description_match.group(1).strip()
         
     | 
| 
      
 222 
     | 
    
         
            +
                        
         
     | 
| 
      
 223 
     | 
    
         
            +
                        # BEGIN Exception to Style Guide, this is needed to keep the key names consistent with the plan file keys.
         
     | 
| 
      
 224 
     | 
    
         
            +
                        
         
     | 
| 
      
 225 
     | 
    
         
            +
                        # Extract other critical information
         
     | 
| 
      
 226 
     | 
    
         
            +
                        supported_plan_keys = {
         
     | 
| 
      
 227 
     | 
    
         
            +
                            'Computation Interval': r'Computation Interval=(.+)',
         
     | 
| 
      
 228 
     | 
    
         
            +
                            'DSS File': r'DSS File=(.+)',
         
     | 
| 
      
 229 
     | 
    
         
            +
                            'Flow File': r'Flow File=(.+)',
         
     | 
| 
      
 230 
     | 
    
         
            +
                            'Friction Slope Method': r'Friction Slope Method=(.+)',
         
     | 
| 
      
 231 
     | 
    
         
            +
                            'Geom File': r'Geom File=(.+)',
         
     | 
| 
      
 232 
     | 
    
         
            +
                            'Mapping Interval': r'Mapping Interval=(.+)',
         
     | 
| 
      
 233 
     | 
    
         
            +
                            'Plan Title': r'Plan Title=(.+)',
         
     | 
| 
      
 234 
     | 
    
         
            +
                            'Program Version': r'Program Version=(.+)',
         
     | 
| 
      
 235 
     | 
    
         
            +
                            'Run HTab': r'Run HTab=(.+)',
         
     | 
| 
      
 236 
     | 
    
         
            +
                            'Run PostProcess': r'Run PostProcess=(.+)',
         
     | 
| 
      
 237 
     | 
    
         
            +
                            'Run Sediment': r'Run Sediment=(.+)',
         
     | 
| 
      
 238 
     | 
    
         
            +
                            'Run UNet': r'Run UNet=(.+)',
         
     | 
| 
      
 239 
     | 
    
         
            +
                            'Run WQNet': r'Run WQNet=(.+)',
         
     | 
| 
      
 240 
     | 
    
         
            +
                            'Short Identifier': r'Short Identifier=(.+)',
         
     | 
| 
      
 241 
     | 
    
         
            +
                            'Simulation Date': r'Simulation Date=(.+)',
         
     | 
| 
      
 242 
     | 
    
         
            +
                            'UNET D1 Cores': r'UNET D1 Cores=(.+)',
         
     | 
| 
      
 243 
     | 
    
         
            +
                            'UNET Use Existing IB Tables': r'UNET Use Existing IB Tables=(.+)',
         
     | 
| 
      
 244 
     | 
    
         
            +
                            'UNET 1D Methodology': r'UNET 1D Methodology=(.+)',
         
     | 
| 
      
 245 
     | 
    
         
            +
                            'UNET D2 SolverType': r'UNET D2 SolverType=(.+)',
         
     | 
| 
      
 246 
     | 
    
         
            +
                            'UNET D2 Name': r'UNET D2 Name=(.+)'
         
     | 
| 
      
 247 
     | 
    
         
            +
                        }
         
     | 
| 
      
 248 
     | 
    
         
            +
                        
         
     | 
| 
      
 249 
     | 
    
         
            +
                        # END Exception to Style Guide
         
     | 
| 
      
 250 
     | 
    
         
            +
                        
         
     | 
| 
      
 251 
     | 
    
         
            +
                        for key, pattern in supported_plan_keys.items():
         
     | 
| 
      
 252 
     | 
    
         
            +
                            match = re.search(pattern, content)
         
     | 
| 
      
 253 
     | 
    
         
            +
                            if match:
         
     | 
| 
      
 254 
     | 
    
         
            +
                                plan_info[key] = match.group(1).strip()
         
     | 
| 
       223 
255 
     | 
    
         | 
| 
       224 
     | 
    
         
            -
                        logger.debug(f"Parsed plan file: {plan_file_path}")
         
     | 
| 
      
 256 
     | 
    
         
            +
                        logger.debug(f"Parsed plan file: {plan_file_path} using {encoding} encoding")
         
     | 
| 
       225 
257 
     | 
    
         
             
                    except Exception as e:
         
     | 
| 
       226 
     | 
    
         
            -
                        logger. 
     | 
| 
      
 258 
     | 
    
         
            +
                        logger.error(f"Error parsing plan file {plan_file_path}: {e}")
         
     | 
| 
       227 
259 
     | 
    
         | 
| 
       228 
260 
     | 
    
         
             
                    return plan_info
         
     | 
| 
       229 
261 
     | 
    
         | 
| 
         @@ -284,11 +316,14 @@ class RasPrj: 
     | 
|
| 
       284 
316 
     | 
    
         
             
                        dict: Dictionary containing extracted unsteady flow information.
         
     | 
| 
       285 
317 
     | 
    
         
             
                    """
         
     | 
| 
       286 
318 
     | 
    
         
             
                    unsteady_info = {}
         
     | 
| 
       287 
     | 
    
         
            -
                     
     | 
| 
       288 
     | 
    
         
            -
             
     | 
| 
       289 
     | 
    
         
            -
             
     | 
| 
      
 319 
     | 
    
         
            +
                    content, encoding = read_file_with_fallback_encoding(unsteady_file_path)
         
     | 
| 
      
 320 
     | 
    
         
            +
                    
         
     | 
| 
      
 321 
     | 
    
         
            +
                    if content is None:
         
     | 
| 
      
 322 
     | 
    
         
            +
                        return unsteady_info
         
     | 
| 
      
 323 
     | 
    
         
            +
                    
         
     | 
| 
      
 324 
     | 
    
         
            +
                    try:
         
     | 
| 
       290 
325 
     | 
    
         
             
                        # BEGIN Exception to Style Guide, this is needed to keep the key names consistent with the unsteady file keys.
         
     | 
| 
       291 
     | 
    
         
            -
             
     | 
| 
      
 326 
     | 
    
         
            +
                        
         
     | 
| 
       292 
327 
     | 
    
         
             
                        supported_unsteady_keys = {
         
     | 
| 
       293 
328 
     | 
    
         
             
                            'Flow Title': r'Flow Title=(.+)',
         
     | 
| 
       294 
329 
     | 
    
         
             
                            'Program Version': r'Program Version=(.+)',
         
     | 
| 
         @@ -309,6 +344,9 @@ class RasPrj: 
     | 
|
| 
       309 
344 
     | 
    
         
             
                            if match:
         
     | 
| 
       310 
345 
     | 
    
         
             
                                unsteady_info[key] = match.group(1).strip()
         
     | 
| 
       311 
346 
     | 
    
         | 
| 
      
 347 
     | 
    
         
            +
                    except Exception as e:
         
     | 
| 
      
 348 
     | 
    
         
            +
                        logger.error(f"Error parsing unsteady file {unsteady_file_path}: {e}")
         
     | 
| 
      
 349 
     | 
    
         
            +
                    
         
     | 
| 
       312 
350 
     | 
    
         
             
                    return unsteady_info
         
     | 
| 
       313 
351 
     | 
    
         | 
| 
       314 
352 
     | 
    
         
             
                @property
         
     | 
| 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            Metadata-Version: 2. 
     | 
| 
      
 1 
     | 
    
         
            +
            Metadata-Version: 2.2
         
     | 
| 
       2 
2 
     | 
    
         
             
            Name: ras-commander
         
     | 
| 
       3 
     | 
    
         
            -
            Version: 0. 
     | 
| 
      
 3 
     | 
    
         
            +
            Version: 0.52.0
         
     | 
| 
       4 
4 
     | 
    
         
             
            Summary: A Python library for automating HEC-RAS operations
         
     | 
| 
       5 
5 
     | 
    
         
             
            Home-page: https://github.com/billk-FM/ras-commander
         
     | 
| 
       6 
6 
     | 
    
         
             
            Author: William M. Katzenmeyer
         
     | 
| 
         @@ -8,6 +8,13 @@ Author-email: billk@fenstermaker.com 
     | 
|
| 
       8 
8 
     | 
    
         
             
            Requires-Python: >=3.10
         
     | 
| 
       9 
9 
     | 
    
         
             
            Description-Content-Type: text/markdown
         
     | 
| 
       10 
10 
     | 
    
         
             
            License-File: LICENSE
         
     | 
| 
      
 11 
     | 
    
         
            +
            Dynamic: author
         
     | 
| 
      
 12 
     | 
    
         
            +
            Dynamic: author-email
         
     | 
| 
      
 13 
     | 
    
         
            +
            Dynamic: description
         
     | 
| 
      
 14 
     | 
    
         
            +
            Dynamic: description-content-type
         
     | 
| 
      
 15 
     | 
    
         
            +
            Dynamic: home-page
         
     | 
| 
      
 16 
     | 
    
         
            +
            Dynamic: requires-python
         
     | 
| 
      
 17 
     | 
    
         
            +
            Dynamic: summary
         
     | 
| 
       11 
18 
     | 
    
         | 
| 
       12 
19 
     | 
    
         
             
            # RAS Commander (ras-commander)
         
     | 
| 
       13 
20 
     | 
    
         | 
| 
         @@ -24,11 +31,8 @@ Aaron Nichols, P.E., C.F.M. 
     | 
|
| 
       24 
31 
     | 
    
         | 
| 
       25 
32 
     | 
    
         
             
            ## Don't Ask Me, Ask ChatGPT!
         
     | 
| 
       26 
33 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
            Before you read any further, you can [chat directly with ChatGPT 
     | 
| 
      
 34 
     | 
    
         
            +
            Before you read any further, you can [chat directly with ChatGPT.](https://chatgpt.com/g/g-TZRPR3oAO-ras-commander-library-assistant) about the library.  Ask it anything, and it will use its tools to answer your questions and help you learn.  You can even upload your own plan, unsteady and HDF files to inspect and help determine how to automate your workflows or visualize your results, although this ability is still limited in comparison to the provided library assistant. 
         
     | 
| 
       28 
35 
     | 
    
         | 
| 
       29 
     | 
    
         
            -
            There are also [AI Assistant Knowledge Bases](https://github.com/billk-FM/ras-commander/tree/main/ai_tools/assistant_knowledge_bases) with various versions available to directly use with large context LLM models such as Anthropic's Claude, Google Gemini and OpenAI's GPT4o and o1 models.  
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
            FUTURE:  TEMPLATES are available to use with AI Assistant Notebooks to build your own automation tools.  When used with large context models, these templates allow you to ask GPT to build a workflow from scratch to automate your projects. 
         
     | 
| 
       32 
36 
     | 
    
         | 
| 
       33 
37 
     | 
    
         
             
            ## Background
         
     | 
| 
       34 
38 
     | 
    
         
             
            The ras-commander library emerged from the initial test-bed of AI-driven coding represented by the HEC-Commander tools Python notebooks. These notebooks served as a proof of concept, demonstrating the value proposition of automating HEC-RAS operations. The transition from notebooks to a structured library aims to provide a more robust, maintainable, and extensible solution for water resources engineers.
         
     | 
| 
         @@ -51,9 +55,8 @@ ras-commander provides several AI-powered tools to enhance the coding experience 
     | 
|
| 
       51 
55 
     | 
    
         
             
            2. **[Purpose-Built Knowledge Base Summaries](https://github.com/billk-FM/ras-commander/tree/main/ai_tools/assistant_knowledge_bases)**: Up-to-date compilations of the documentation and codebase for use with large language models like Claude or GPT-4. Look in 'ai_tools/assistant_knowledge_bases/' in the repo.
         
     | 
| 
       52 
56 
     | 
    
         | 
| 
       53 
57 
     | 
    
         
             
            3. **[Cursor IDE Integration](https://github.com/billk-FM/ras-commander/blob/main/.cursorrules)**: Custom rules for the Cursor IDE to provide context-aware suggestions and documentation.  Just open the repository folder in Cursor.  You can create your own folders "/workspace/, "/projects/", or "my_projects/" as these are already in the .gitignore, and place your custom scripts there for your projects.  This will allow easy referencing of the ras-commander documents and individual repo files, the automatic loading of the .cursorrules file.  Alternatvely, download the github repo into your projects folder to easily load documents and use cursor rules files.  
         
     | 
| 
       54 
     | 
    
         
            -
            4. **[ 
     | 
| 
      
 58 
     | 
    
         
            +
            4. **[RAS-Commander Library Assistant](https://github.com/billk-FM/ras-commander/blob/main/library_assistant)**: A full-featured interface for multi-turn conversations, using your own API keys and the ras-commander library for context.  The library assistant allows you to load your own scripts and chat with specific examples and/or function classes in the RAS-Commander library to effectively utilize the library's functions in your workflow.
         
     | 
| 
       55 
59 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
            These tools aim to streamline development and provide intelligent assistance when modeling with, and working with and revising the ras-commander library.
         
     | 
| 
       57 
60 
     | 
    
         | 
| 
       58 
61 
     | 
    
         
             
            ## Installation
         
     | 
| 
       59 
62 
     | 
    
         | 
| 
         @@ -1,9 +1,9 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ras_commander/Decorators.py,sha256=M5r5cHz_yy9YTHNEoytO9uwWbv_S-YYUk2QHNamJJJs,5848
         
     | 
| 
       2 
     | 
    
         
            -
            ras_commander/HdfBase.py,sha256= 
     | 
| 
      
 2 
     | 
    
         
            +
            ras_commander/HdfBase.py,sha256=Bmj5mR9Ubr8gsthmjgDzlZk4Dh2tReE-zUgjXoNUsRM,13671
         
     | 
| 
       3 
3 
     | 
    
         
             
            ras_commander/HdfBndry.py,sha256=m81NdCu_ER-AAZpEkQPQka7pYv3sm7vEZevq3SIt2pw,12545
         
     | 
| 
       4 
     | 
    
         
            -
            ras_commander/HdfFluvialPluvial.py,sha256= 
     | 
| 
      
 4 
     | 
    
         
            +
            ras_commander/HdfFluvialPluvial.py,sha256=dK79kqP9cQi4JmUj8420TkEDXoYFv_hVRxuuLDJhZYA,25380
         
     | 
| 
       5 
5 
     | 
    
         
             
            ras_commander/HdfInfiltration.py,sha256=QVigQJjYeQNutbazGHhbTmEuIVCb9gIb2f4yM-wyUtQ,15269
         
     | 
| 
       6 
     | 
    
         
            -
            ras_commander/HdfMesh.py,sha256= 
     | 
| 
      
 6 
     | 
    
         
            +
            ras_commander/HdfMesh.py,sha256=zI_4AqxDxb2_31G9RUmWibyld6KDMGhDpI3F8qwzVAw,19139
         
     | 
| 
       7 
7 
     | 
    
         
             
            ras_commander/HdfPipe.py,sha256=m-yvPL2GIP23NKt2tcwzOlS7khvgcDPGAshlTPMUAeI,32154
         
     | 
| 
       8 
8 
     | 
    
         
             
            ras_commander/HdfPlan.py,sha256=NW6g2kS74y44Ci1P9iMo7IKUfR0eYOaJn1QbzsRM1co,10415
         
     | 
| 
       9 
9 
     | 
    
         
             
            ras_commander/HdfPlot.py,sha256=7MNI5T9qIz-Ava1RdlnB6O9oJElE5BEB29QVF5Y2Xuc,3401
         
     | 
| 
         @@ -13,8 +13,8 @@ ras_commander/HdfResultsPlan.py,sha256=HoN3wvhj1wtkW-M20UHH9skntDqEvJEgeYeO_QBLF 
     | 
|
| 
       13 
13 
     | 
    
         
             
            ras_commander/HdfResultsPlot.py,sha256=ylzfT78CfgoDO0XAlRwlgMNRzvNQYBMn9eyXyBfjv_w,7660
         
     | 
| 
       14 
14 
     | 
    
         
             
            ras_commander/HdfResultsXsec.py,sha256=-P7nXnbjOLAeUnrdSC_lJQSfzrlWKmDF9Z5gEjmxbJY,13031
         
     | 
| 
       15 
15 
     | 
    
         
             
            ras_commander/HdfStruc.py,sha256=yzD4_eZLgwZDS3GdYVWqd85jRpdlRdVdbHHfPYTmwjA,12703
         
     | 
| 
       16 
     | 
    
         
            -
            ras_commander/HdfUtils.py,sha256= 
     | 
| 
       17 
     | 
    
         
            -
            ras_commander/HdfXsec.py,sha256= 
     | 
| 
      
 16 
     | 
    
         
            +
            ras_commander/HdfUtils.py,sha256=VkIKAXBrLwTlk2VtXSO-W3RU-NHpfHbE1QcZUZgl-t8,15248
         
     | 
| 
      
 17 
     | 
    
         
            +
            ras_commander/HdfXsec.py,sha256=R3lrRZ42L80n6nwrtihvHtit-Y2jI9cdDGzekAyoJ-s,27348
         
     | 
| 
       18 
18 
     | 
    
         
             
            ras_commander/LoggingConfig.py,sha256=p1OJkQj5dsDdyBQqF0HWsvbsU88n9cYOc3YB2MMBYiw,2666
         
     | 
| 
       19 
19 
     | 
    
         
             
            ras_commander/RasCmdr.py,sha256=N2PI5n0P3ClLUPOPNcONJHGJYF-fIU5o0GXwHv4VATE,25271
         
     | 
| 
       20 
20 
     | 
    
         
             
            ras_commander/RasExamples.py,sha256=eYlRKryCG88FN5p23TnA1-E2Bxuaz3OxjdHPHJSqdB8,17006
         
     | 
| 
         @@ -22,13 +22,13 @@ ras_commander/RasGeo.py,sha256=M0sVNKlWmmbve8iMXLWq25WgbxqLWBo7_1oDg_rALzU,5607 
     | 
|
| 
       22 
22 
     | 
    
         
             
            ras_commander/RasGpt.py,sha256=N_7p2nucWrBBXdB2k2ZKvOeOdXNmFD9dIY3W7_5i5nw,1206
         
     | 
| 
       23 
23 
     | 
    
         
             
            ras_commander/RasMapper.py,sha256=A7xupixCmgXFiSfQs3oWBMBstrO8XcxieMeZWKTcbPQ,3271
         
     | 
| 
       24 
24 
     | 
    
         
             
            ras_commander/RasPlan.py,sha256=jt0adLtwGjrKC90uuBXYgHpVyV3cKgD1Q_zkKiI04fc,52742
         
     | 
| 
       25 
     | 
    
         
            -
            ras_commander/RasPrj.py,sha256= 
     | 
| 
      
 25 
     | 
    
         
            +
            ras_commander/RasPrj.py,sha256=a1Rju4G0vZqD8RY7Qj35f_oyXXF-csgXO7hHJ8TfIV8,38103
         
     | 
| 
       26 
26 
     | 
    
         
             
            ras_commander/RasToGo.py,sha256=TKujfaV1xQhFaOddF4g2ogGy6ky-CLlfelSMPD2J3Nk,1223
         
     | 
| 
       27 
27 
     | 
    
         
             
            ras_commander/RasUnsteady.py,sha256=NWZbmB3-HT0W00K4-zxFN9OF8H_HlOY64nM72sHicWg,31154
         
     | 
| 
       28 
28 
     | 
    
         
             
            ras_commander/RasUtils.py,sha256=P2-aBL61kdRINsjnBpstZVD6VVc7hI_D3RUXqr6ldmc,34863
         
     | 
| 
       29 
29 
     | 
    
         
             
            ras_commander/__init__.py,sha256=vhnZQaejmyFVFP5fcYxAc4A562o8KFcnZNkcY6J5xwY,2068
         
     | 
| 
       30 
     | 
    
         
            -
            ras_commander-0. 
     | 
| 
       31 
     | 
    
         
            -
            ras_commander-0. 
     | 
| 
       32 
     | 
    
         
            -
            ras_commander-0. 
     | 
| 
       33 
     | 
    
         
            -
            ras_commander-0. 
     | 
| 
       34 
     | 
    
         
            -
            ras_commander-0. 
     | 
| 
      
 30 
     | 
    
         
            +
            ras_commander-0.52.0.dist-info/LICENSE,sha256=_pbd6qHnlsz1iQ-ozDW_49r86BZT6CRwO2iBtw0iN6M,457
         
     | 
| 
      
 31 
     | 
    
         
            +
            ras_commander-0.52.0.dist-info/METADATA,sha256=wg9l08JoU1IX27wMf32hpzXQp1PPYQe5DAyYENRShi4,17813
         
     | 
| 
      
 32 
     | 
    
         
            +
            ras_commander-0.52.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
         
     | 
| 
      
 33 
     | 
    
         
            +
            ras_commander-0.52.0.dist-info/top_level.txt,sha256=i76S7eKLFC8doKcXDl3aiOr9RwT06G8adI6YuKbQDaA,14
         
     | 
| 
      
 34 
     | 
    
         
            +
            ras_commander-0.52.0.dist-info/RECORD,,
         
     | 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     |