ras-commander 0.45.0__py3-none-any.whl → 0.46.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/HdfFluvialPluvial.py +317 -0
- ras_commander/HdfMesh.py +62 -15
- ras_commander/HdfPipe.py +587 -78
- ras_commander/HdfPlan.py +5 -0
- ras_commander/HdfPump.py +25 -11
- ras_commander/HdfResultsMesh.py +135 -62
- ras_commander/HdfResultsXsec.py +126 -297
- ras_commander/HdfStruc.py +148 -50
- ras_commander/HdfUtils.py +51 -0
- ras_commander/HdfXsec.py +467 -136
- ras_commander/RasPlan.py +298 -45
- ras_commander/RasToGo.py +21 -0
- ras_commander/RasUnsteady.py +615 -14
- ras_commander/__init__.py +3 -1
- {ras_commander-0.45.0.dist-info → ras_commander-0.46.0.dist-info}/METADATA +1 -1
- ras_commander-0.46.0.dist-info/RECORD +30 -0
- {ras_commander-0.45.0.dist-info → ras_commander-0.46.0.dist-info}/WHEEL +1 -1
- ras_commander-0.45.0.dist-info/RECORD +0 -28
- {ras_commander-0.45.0.dist-info → ras_commander-0.46.0.dist-info}/LICENSE +0 -0
- {ras_commander-0.45.0.dist-info → ras_commander-0.46.0.dist-info}/top_level.txt +0 -0
    
        ras_commander/HdfResultsXsec.py
    CHANGED
    
    | @@ -9,7 +9,7 @@ The file has been forked and modified for use in RAS Commander. | |
| 9 9 | 
             
            """
         | 
| 10 10 |  | 
| 11 11 | 
             
            from pathlib import Path
         | 
| 12 | 
            -
            from typing import Union, Optional, List
         | 
| 12 | 
            +
            from typing import Union, Optional, List, Dict, Tuple
         | 
| 13 13 |  | 
| 14 14 | 
             
            import h5py
         | 
| 15 15 | 
             
            import numpy as np
         | 
| @@ -37,251 +37,90 @@ class HdfResultsXsec: | |
| 37 37 | 
             
                Attributes:
         | 
| 38 38 | 
             
                    None
         | 
| 39 39 |  | 
| 40 | 
            -
                 | 
| 41 | 
            -
                    steady_profile_xs_output: Extract steady profile cross-section output for a specified variable.
         | 
| 42 | 
            -
                    cross_sections_wsel: Get water surface elevation data for cross-sections.
         | 
| 43 | 
            -
                    cross_sections_flow: Get flow data for cross-sections.
         | 
| 44 | 
            -
                    cross_sections_energy_grade: Get energy grade data for cross-sections.
         | 
| 45 | 
            -
                    cross_sections_additional_enc_station_left: Get left encroachment station data for cross-sections.
         | 
| 46 | 
            -
                    cross_sections_additional_enc_station_right: Get right encroachment station data for cross-sections.
         | 
| 47 | 
            -
                    cross_sections_additional_area_total: Get total ineffective area data for cross-sections.
         | 
| 48 | 
            -
                    cross_sections_additional_velocity_total: Get total velocity data for cross-sections.
         | 
| 40 | 
            +
                
         | 
| 49 41 | 
             
                """
         | 
| 50 42 |  | 
| 51 | 
            -
                @staticmethod
         | 
| 52 | 
            -
                @standardize_input(file_type='plan_hdf')
         | 
| 53 | 
            -
                def steady_profile_xs_output(hdf_path: Path, var: str, round_to: int = 2) -> pd.DataFrame:
         | 
| 54 | 
            -
                    """
         | 
| 55 | 
            -
                    Create a DataFrame from steady cross section results based on the specified variable.
         | 
| 56 43 |  | 
| 57 | 
            -
                    Parameters:
         | 
| 58 | 
            -
                    ----------
         | 
| 59 | 
            -
                    hdf_path : Path
         | 
| 60 | 
            -
                        Path to the HEC-RAS plan HDF file.
         | 
| 61 | 
            -
                    var : str
         | 
| 62 | 
            -
                        The variable to extract from the steady cross section results.
         | 
| 63 | 
            -
                    round_to : int, optional
         | 
| 64 | 
            -
                        Number of decimal places to round the results to (default is 2).
         | 
| 65 44 |  | 
| 66 | 
            -
                    Returns:
         | 
| 67 | 
            -
                    -------
         | 
| 68 | 
            -
                    pd.DataFrame
         | 
| 69 | 
            -
                        DataFrame containing the steady cross section results for the specified variable.
         | 
| 70 | 
            -
                    """
         | 
| 71 | 
            -
                    XS_STEADY_OUTPUT_ADDITIONAL = [
         | 
| 72 | 
            -
                        "Additional Encroachment Station Left",
         | 
| 73 | 
            -
                        "Additional Encroachment Station Right",
         | 
| 74 | 
            -
                        "Additional Area Ineffective Total",
         | 
| 75 | 
            -
                        "Additional Velocity Total",
         | 
| 76 | 
            -
                    ]
         | 
| 77 | 
            -
                            
         | 
| 78 | 
            -
                    try:
         | 
| 79 | 
            -
                        with h5py.File(hdf_path, 'r') as hdf_file:
         | 
| 80 | 
            -
                            # Determine the correct path based on the variable
         | 
| 81 | 
            -
                            if var in XS_STEADY_OUTPUT_ADDITIONAL:
         | 
| 82 | 
            -
                                path = f"/Results/Steady/Cross Sections/Additional Output/{var}"
         | 
| 83 | 
            -
                            else:
         | 
| 84 | 
            -
                                path = f"/Results/Steady/Cross Sections/{var}"
         | 
| 85 | 
            -
                            
         | 
| 86 | 
            -
                            # Check if the path exists in the HDF file
         | 
| 87 | 
            -
                            if path not in hdf_file:
         | 
| 88 | 
            -
                                return pd.DataFrame()
         | 
| 89 45 |  | 
| 90 | 
            -
                            # Get the profile names
         | 
| 91 | 
            -
                            profiles = HdfBase.steady_flow_names(hdf_path)
         | 
| 92 | 
            -
                            
         | 
| 93 | 
            -
                            # Extract the steady data
         | 
| 94 | 
            -
                            steady_data = hdf_file[path]
         | 
| 95 | 
            -
                            
         | 
| 96 | 
            -
                            # Create a DataFrame with profiles as index
         | 
| 97 | 
            -
                            df = pd.DataFrame(steady_data, index=profiles)
         | 
| 98 | 
            -
                            
         | 
| 99 | 
            -
                            # Transpose the DataFrame and round values
         | 
| 100 | 
            -
                            df_t = df.T.copy()
         | 
| 101 | 
            -
                            for p in profiles:
         | 
| 102 | 
            -
                                df_t[p] = df_t[p].apply(lambda x: round(x, round_to))
         | 
| 103 46 |  | 
| 104 | 
            -
                            return df_t
         | 
| 105 | 
            -
                    except Exception as e:
         | 
| 106 | 
            -
                        HdfUtils.logger.error(f"Failed to get steady profile cross section output: {str(e)}")
         | 
| 107 | 
            -
                        return pd.DataFrame()
         | 
| 108 47 |  | 
| 109 | 
            -
                @staticmethod
         | 
| 110 | 
            -
                @standardize_input(file_type='plan_hdf')
         | 
| 111 | 
            -
                def cross_sections_wsel(hdf_path: Path) -> pd.DataFrame:
         | 
| 112 | 
            -
                    """
         | 
| 113 | 
            -
                    Return the water surface elevation information for each 1D Cross Section.
         | 
| 114 48 |  | 
| 115 | 
            -
                    Parameters:
         | 
| 116 | 
            -
                    ----------
         | 
| 117 | 
            -
                    hdf_path : Path
         | 
| 118 | 
            -
                        Path to the HEC-RAS plan HDF file.
         | 
| 119 49 |  | 
| 120 | 
            -
                    Returns:
         | 
| 121 | 
            -
                    -------
         | 
| 122 | 
            -
                    pd.DataFrame
         | 
| 123 | 
            -
                        A DataFrame containing the water surface elevations for each cross section and event.
         | 
| 124 | 
            -
                    """
         | 
| 125 | 
            -
                    return HdfResultsXsec.steady_profile_xs_output(hdf_path, "Water Surface")
         | 
| 126 50 |  | 
| 127 | 
            -
                @staticmethod
         | 
| 128 | 
            -
                @standardize_input(file_type='plan_hdf')
         | 
| 129 | 
            -
                def cross_sections_flow(hdf_path: Path) -> pd.DataFrame:
         | 
| 130 | 
            -
                    """
         | 
| 131 | 
            -
                    Return the Flow information for each 1D Cross Section.
         | 
| 132 51 |  | 
| 133 | 
            -
                    Parameters:
         | 
| 134 | 
            -
                    ----------
         | 
| 135 | 
            -
                    hdf_path : Path
         | 
| 136 | 
            -
                        Path to the HEC-RAS plan HDF file.
         | 
| 137 52 |  | 
| 138 | 
            -
                    Returns:
         | 
| 139 | 
            -
                    -------
         | 
| 140 | 
            -
                    pd.DataFrame
         | 
| 141 | 
            -
                        A DataFrame containing the flow for each cross section and event.
         | 
| 142 | 
            -
                    """
         | 
| 143 | 
            -
                    return HdfResultsXsec.steady_profile_xs_output(hdf_path, "Flow")
         | 
| 144 53 |  | 
| 145 54 | 
             
                @staticmethod
         | 
| 55 | 
            +
                @log_call
         | 
| 146 56 | 
             
                @standardize_input(file_type='plan_hdf')
         | 
| 147 | 
            -
                def  | 
| 57 | 
            +
                def get_pump_station_profile_output(hdf_path: Path) -> pd.DataFrame:
         | 
| 148 58 | 
             
                    """
         | 
| 149 | 
            -
                     | 
| 59 | 
            +
                    Extract pump station profile output data from the HDF file.
         | 
| 150 60 |  | 
| 151 | 
            -
                     | 
| 152 | 
            -
             | 
| 153 | 
            -
                    hdf_path : Path
         | 
| 154 | 
            -
                        Path to the HEC-RAS plan HDF file.
         | 
| 61 | 
            +
                    Args:
         | 
| 62 | 
            +
                        hdf_path (Path): Path to the HDF file.
         | 
| 155 63 |  | 
| 156 64 | 
             
                    Returns:
         | 
| 157 | 
            -
             | 
| 158 | 
            -
                    pd.DataFrame
         | 
| 159 | 
            -
                        A DataFrame containing the energy grade for each cross section and event.
         | 
| 160 | 
            -
                    """
         | 
| 161 | 
            -
                    return HdfResultsXsec.steady_profile_xs_output(hdf_path, "Energy Grade")
         | 
| 65 | 
            +
                        pd.DataFrame: DataFrame containing pump station profile output data.
         | 
| 162 66 |  | 
| 163 | 
            -
             | 
| 164 | 
            -
             | 
| 165 | 
            -
                def cross_sections_additional_enc_station_left(hdf_path: Path) -> pd.DataFrame:
         | 
| 67 | 
            +
                    Raises:
         | 
| 68 | 
            +
                        KeyError: If the required datasets are not found in the HDF file.
         | 
| 166 69 | 
             
                    """
         | 
| 167 | 
            -
                     | 
| 70 | 
            +
                    try:
         | 
| 71 | 
            +
                        with h5py.File(hdf_path, 'r') as hdf:
         | 
| 72 | 
            +
                            # Extract profile output data
         | 
| 73 | 
            +
                            profile_path = "/Results/Unsteady/Output/Output Blocks/DSS Profile Output/Unsteady Time Series/Pumping Stations"
         | 
| 74 | 
            +
                            if profile_path not in hdf:
         | 
| 75 | 
            +
                                logger.warning("Pump Station profile output data not found in HDF file")
         | 
| 76 | 
            +
                                return pd.DataFrame()
         | 
| 168 77 |  | 
| 169 | 
            -
             | 
| 170 | 
            -
             | 
| 171 | 
            -
                    hdf_path : Path
         | 
| 172 | 
            -
                        Path to the HEC-RAS plan HDF file.
         | 
| 78 | 
            +
                            # Initialize an empty list to store data from all pump stations
         | 
| 79 | 
            +
                            all_data = []
         | 
| 173 80 |  | 
| 174 | 
            -
             | 
| 175 | 
            -
             | 
| 176 | 
            -
             | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
             | 
| 81 | 
            +
                            # Iterate through all pump stations
         | 
| 82 | 
            +
                            for station in hdf[profile_path].keys():
         | 
| 83 | 
            +
                                station_path = f"{profile_path}/{station}/Structure Variables"
         | 
| 84 | 
            +
                                
         | 
| 85 | 
            +
                                data = hdf[station_path][()]
         | 
| 86 | 
            +
                                
         | 
| 87 | 
            +
                                # Create a DataFrame for this pump station
         | 
| 88 | 
            +
                                df = pd.DataFrame(data, columns=['Flow', 'Stage HW', 'Stage TW', 'Pump Station', 'Pumps on'])
         | 
| 89 | 
            +
                                df['Station'] = station
         | 
| 90 | 
            +
                                
         | 
| 91 | 
            +
                                all_data.append(df)
         | 
| 182 92 |  | 
| 183 | 
            -
             | 
| 184 | 
            -
             | 
| 185 | 
            -
                def cross_sections_additional_enc_station_right(hdf_path: Path) -> pd.DataFrame:
         | 
| 186 | 
            -
                    """
         | 
| 187 | 
            -
                    Return the right side encroachment information for a floodway plan hdf.
         | 
| 93 | 
            +
                            # Concatenate all DataFrames
         | 
| 94 | 
            +
                            result_df = pd.concat(all_data, ignore_index=True)
         | 
| 188 95 |  | 
| 189 | 
            -
             | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 192 | 
            -
                        Path to the HEC-RAS plan HDF file.
         | 
| 96 | 
            +
                            # Add time information
         | 
| 97 | 
            +
                            time = HdfBase._get_unsteady_datetimes(hdf)
         | 
| 98 | 
            +
                            result_df['Time'] = [time[i] for i in result_df.index]
         | 
| 193 99 |  | 
| 194 | 
            -
             | 
| 195 | 
            -
             | 
| 196 | 
            -
                     | 
| 197 | 
            -
                         | 
| 198 | 
            -
             | 
| 199 | 
            -
                     | 
| 200 | 
            -
                         | 
| 201 | 
            -
             | 
| 100 | 
            +
                            return result_df
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                    except KeyError as e:
         | 
| 103 | 
            +
                        logger.error(f"Required dataset not found in HDF file: {e}")
         | 
| 104 | 
            +
                        raise
         | 
| 105 | 
            +
                    except Exception as e:
         | 
| 106 | 
            +
                        logger.error(f"Error extracting pump station profile output data: {e}")
         | 
| 107 | 
            +
                        raise
         | 
| 202 108 |  | 
| 203 | 
            -
                @staticmethod
         | 
| 204 | 
            -
                @standardize_input(file_type='plan_hdf')
         | 
| 205 | 
            -
                def cross_sections_additional_area_total(hdf_path: Path) -> pd.DataFrame:
         | 
| 206 | 
            -
                    """
         | 
| 207 | 
            -
                    Return the 1D cross section area for each profile.
         | 
| 208 109 |  | 
| 209 | 
            -
                    Parameters:
         | 
| 210 | 
            -
                    ----------
         | 
| 211 | 
            -
                    hdf_path : Path
         | 
| 212 | 
            -
                        Path to the HEC-RAS plan HDF file.
         | 
| 213 110 |  | 
| 214 | 
            -
                    Returns:
         | 
| 215 | 
            -
                    -------
         | 
| 216 | 
            -
                    pd.DataFrame
         | 
| 217 | 
            -
                        A DataFrame containing the wet area inside the cross sections.
         | 
| 218 | 
            -
                    """
         | 
| 219 | 
            -
                    return HdfResultsXsec.steady_profile_xs_output(hdf_path, "Area Ineffective Total")
         | 
| 220 111 |  | 
| 221 | 
            -
                @staticmethod
         | 
| 222 | 
            -
                @standardize_input(file_type='plan_hdf')
         | 
| 223 | 
            -
                def cross_sections_additional_velocity_total(hdf_path: Path) -> pd.DataFrame:
         | 
| 224 | 
            -
                    """
         | 
| 225 | 
            -
                    Return the 1D cross section velocity for each profile.
         | 
| 226 112 |  | 
| 227 | 
            -
                    Parameters:
         | 
| 228 | 
            -
                    ----------
         | 
| 229 | 
            -
                    hdf_path : Path
         | 
| 230 | 
            -
                        Path to the HEC-RAS plan HDF file.
         | 
| 231 113 |  | 
| 232 | 
            -
                    Returns:
         | 
| 233 | 
            -
                    -------
         | 
| 234 | 
            -
                    pd.DataFrame
         | 
| 235 | 
            -
                        A DataFrame containing the velocity inside the cross sections.
         | 
| 236 | 
            -
                    """
         | 
| 237 | 
            -
                    return HdfResultsXsec.steady_profile_xs_output(hdf_path, "Velocity Total")
         | 
| 238 114 |  | 
| 239 115 |  | 
| 240 | 
            -
                @staticmethod
         | 
| 241 | 
            -
                @log_call
         | 
| 242 | 
            -
                @standardize_input(file_type='plan_hdf')
         | 
| 243 | 
            -
                def get_pipe_network_summary(hdf_path: Path) -> pd.DataFrame:
         | 
| 244 | 
            -
                    """
         | 
| 245 | 
            -
                    Extract summary data for pipe networks from the HDF file.
         | 
| 246 116 |  | 
| 247 | 
            -
                    Args:
         | 
| 248 | 
            -
                        hdf_path (Path): Path to the HDF file.
         | 
| 249 117 |  | 
| 250 | 
            -
                    Returns:
         | 
| 251 | 
            -
                        pd.DataFrame: DataFrame containing pipe network summary data.
         | 
| 252 118 |  | 
| 253 | 
            -
                    Raises:
         | 
| 254 | 
            -
                        KeyError: If the required datasets are not found in the HDF file.
         | 
| 255 | 
            -
                    """
         | 
| 256 | 
            -
                    try:
         | 
| 257 | 
            -
                        with h5py.File(hdf_path, 'r') as hdf:
         | 
| 258 | 
            -
                            # Extract summary data
         | 
| 259 | 
            -
                            summary_path = "/Results/Unsteady/Summary/Pipe Network"
         | 
| 260 | 
            -
                            if summary_path not in hdf:
         | 
| 261 | 
            -
                                logger.warning("Pipe Network summary data not found in HDF file")
         | 
| 262 | 
            -
                                return pd.DataFrame()
         | 
| 263 119 |  | 
| 264 | 
            -
                            summary_data = hdf[summary_path][()]
         | 
| 265 | 
            -
                            
         | 
| 266 | 
            -
                            # Create DataFrame
         | 
| 267 | 
            -
                            df = pd.DataFrame(summary_data)
         | 
| 268 120 |  | 
| 269 | 
            -
                            # Convert column names
         | 
| 270 | 
            -
                            df.columns = [col.decode('utf-8') if isinstance(col, bytes) else col for col in df.columns]
         | 
| 271 121 |  | 
| 272 | 
            -
                            # Convert byte string values to regular strings
         | 
| 273 | 
            -
                            for col in df.columns:
         | 
| 274 | 
            -
                                if df[col].dtype == object:
         | 
| 275 | 
            -
                                    df[col] = df[col].apply(lambda x: x.decode('utf-8') if isinstance(x, bytes) else x)
         | 
| 276 122 |  | 
| 277 | 
            -
                            return df
         | 
| 278 123 |  | 
| 279 | 
            -
                    except KeyError as e:
         | 
| 280 | 
            -
                        logger.error(f"Required dataset not found in HDF file: {e}")
         | 
| 281 | 
            -
                        raise
         | 
| 282 | 
            -
                    except Exception as e:
         | 
| 283 | 
            -
                        logger.error(f"Error extracting pipe network summary data: {e}")
         | 
| 284 | 
            -
                        raise
         | 
| 285 124 |  | 
| 286 125 | 
             
                @staticmethod
         | 
| 287 126 | 
             
                @log_call
         | 
| @@ -329,115 +168,105 @@ class HdfResultsXsec: | |
| 329 168 | 
             
                        logger.error(f"Error extracting pump station summary data: {e}")
         | 
| 330 169 | 
             
                        raise
         | 
| 331 170 |  | 
| 332 | 
            -
                @staticmethod
         | 
| 333 | 
            -
                @log_call
         | 
| 334 | 
            -
                @standardize_input(file_type='plan_hdf')
         | 
| 335 | 
            -
                def get_pipe_network_profile_output(hdf_path: Path) -> pd.DataFrame:
         | 
| 336 | 
            -
                    """
         | 
| 337 | 
            -
                    Extract pipe network profile output data from the HDF file.
         | 
| 338 | 
            -
             | 
| 339 | 
            -
                    Args:
         | 
| 340 | 
            -
                        hdf_path (Path): Path to the HDF file.
         | 
| 341 171 |  | 
| 342 | 
            -
                    Returns:
         | 
| 343 | 
            -
                        pd.DataFrame: DataFrame containing pipe network profile output data.
         | 
| 344 172 |  | 
| 345 | 
            -
                    Raises:
         | 
| 346 | 
            -
                        KeyError: If the required datasets are not found in the HDF file.
         | 
| 347 | 
            -
                    """
         | 
| 348 | 
            -
                    try:
         | 
| 349 | 
            -
                        with h5py.File(hdf_path, 'r') as hdf:
         | 
| 350 | 
            -
                            # Extract profile output data
         | 
| 351 | 
            -
                            profile_path = "/Results/Unsteady/Output/Output Blocks/DSS Profile Output/Unsteady Time Series/Pipe Networks"
         | 
| 352 | 
            -
                            if profile_path not in hdf:
         | 
| 353 | 
            -
                                logger.warning("Pipe Network profile output data not found in HDF file")
         | 
| 354 | 
            -
                                return pd.DataFrame()
         | 
| 355 173 |  | 
| 356 | 
            -
             | 
| 357 | 
            -
             | 
| 174 | 
            +
            # Tested functions from AWS webinar where the code was developed
         | 
| 175 | 
            +
            # Need to add examples
         | 
| 358 176 |  | 
| 359 | 
            -
                            # Iterate through all pipe networks
         | 
| 360 | 
            -
                            for network in hdf[profile_path].keys():
         | 
| 361 | 
            -
                                network_path = f"{profile_path}/{network}"
         | 
| 362 | 
            -
                                
         | 
| 363 | 
            -
                                # Extract data for each variable
         | 
| 364 | 
            -
                                for var in hdf[network_path].keys():
         | 
| 365 | 
            -
                                    data = hdf[f"{network_path}/{var}"][()]
         | 
| 366 | 
            -
                                    
         | 
| 367 | 
            -
                                    # Create a DataFrame for this variable
         | 
| 368 | 
            -
                                    df = pd.DataFrame(data)
         | 
| 369 | 
            -
                                    df['Network'] = network
         | 
| 370 | 
            -
                                    df['Variable'] = var
         | 
| 371 | 
            -
                                    
         | 
| 372 | 
            -
                                    all_data.append(df)
         | 
| 373 | 
            -
             | 
| 374 | 
            -
                            # Concatenate all DataFrames
         | 
| 375 | 
            -
                            result_df = pd.concat(all_data, ignore_index=True)
         | 
| 376 | 
            -
             | 
| 377 | 
            -
                            # Add time information
         | 
| 378 | 
            -
                            time = HdfBase._get_unsteady_datetimes(hdf)
         | 
| 379 | 
            -
                            result_df['Time'] = [time[i] for i in result_df.index]
         | 
| 380 | 
            -
             | 
| 381 | 
            -
                            return result_df
         | 
| 382 | 
            -
             | 
| 383 | 
            -
                    except KeyError as e:
         | 
| 384 | 
            -
                        logger.error(f"Required dataset not found in HDF file: {e}")
         | 
| 385 | 
            -
                        raise
         | 
| 386 | 
            -
                    except Exception as e:
         | 
| 387 | 
            -
                        logger.error(f"Error extracting pipe network profile output data: {e}")
         | 
| 388 | 
            -
                        raise
         | 
| 389 177 |  | 
| 390 178 | 
             
                @staticmethod
         | 
| 391 179 | 
             
                @log_call
         | 
| 392 180 | 
             
                @standardize_input(file_type='plan_hdf')
         | 
| 393 | 
            -
                def  | 
| 181 | 
            +
                def extract_cross_section_results(hdf_path: Path) -> xr.Dataset:
         | 
| 394 182 | 
             
                    """
         | 
| 395 | 
            -
                    Extract  | 
| 183 | 
            +
                    Extract Water Surface, Velocity Total, Velocity Channel, Flow Lateral, and Flow data from HEC-RAS HDF file.
         | 
| 184 | 
            +
                    Includes Cross Section Only and Cross Section Attributes as coordinates in the xarray.Dataset.
         | 
| 185 | 
            +
                    Also calculates maximum values for key parameters.
         | 
| 396 186 |  | 
| 397 | 
            -
                     | 
| 398 | 
            -
             | 
| 187 | 
            +
                    Parameters:
         | 
| 188 | 
            +
                    -----------
         | 
| 189 | 
            +
                    hdf_path : Path
         | 
| 190 | 
            +
                        Path to the HEC-RAS results HDF file
         | 
| 399 191 |  | 
| 400 192 | 
             
                    Returns:
         | 
| 401 | 
            -
             | 
| 402 | 
            -
             | 
| 403 | 
            -
             | 
| 404 | 
            -
                         | 
| 193 | 
            +
                    --------
         | 
| 194 | 
            +
                    xr.Dataset
         | 
| 195 | 
            +
                        Xarray Dataset containing the extracted cross-section results with appropriate coordinates and attributes.
         | 
| 196 | 
            +
                        Includes maximum values for Water Surface, Flow, Channel Velocity, Total Velocity, and Lateral Flow.
         | 
| 405 197 | 
             
                    """
         | 
| 406 198 | 
             
                    try:
         | 
| 407 | 
            -
                        with h5py.File(hdf_path, 'r') as  | 
| 408 | 
            -
                            #  | 
| 409 | 
            -
                             | 
| 410 | 
            -
                             | 
| 411 | 
            -
             | 
| 412 | 
            -
             | 
| 413 | 
            -
             | 
| 414 | 
            -
                             | 
| 415 | 
            -
                             | 
| 416 | 
            -
             | 
| 417 | 
            -
                             | 
| 418 | 
            -
                             | 
| 419 | 
            -
             | 
| 420 | 
            -
             | 
| 421 | 
            -
             | 
| 422 | 
            -
             | 
| 423 | 
            -
             | 
| 424 | 
            -
             | 
| 425 | 
            -
             | 
| 426 | 
            -
                                
         | 
| 427 | 
            -
             | 
| 428 | 
            -
             | 
| 429 | 
            -
                             | 
| 430 | 
            -
                             | 
| 431 | 
            -
             | 
| 432 | 
            -
                             | 
| 433 | 
            -
                             | 
| 434 | 
            -
                             | 
| 435 | 
            -
             | 
| 436 | 
            -
                             | 
| 199 | 
            +
                        with h5py.File(hdf_path, 'r') as hdf_file:
         | 
| 200 | 
            +
                            # Define base paths
         | 
| 201 | 
            +
                            base_output_path = "/Results/Unsteady/Output/Output Blocks/Base Output/Unsteady Time Series/Cross Sections/"
         | 
| 202 | 
            +
                            time_stamp_path = "/Results/Unsteady/Output/Output Blocks/Base Output/Unsteady Time Series/Time Date Stamp (ms)"
         | 
| 203 | 
            +
                            
         | 
| 204 | 
            +
                            # Extract Cross Section Attributes
         | 
| 205 | 
            +
                            attrs_dataset = hdf_file[f"{base_output_path}Cross Section Attributes"][:]
         | 
| 206 | 
            +
                            rivers = [attr['River'].decode('utf-8').strip() for attr in attrs_dataset]
         | 
| 207 | 
            +
                            reaches = [attr['Reach'].decode('utf-8').strip() for attr in attrs_dataset]
         | 
| 208 | 
            +
                            stations = [attr['Station'].decode('utf-8').strip() for attr in attrs_dataset]
         | 
| 209 | 
            +
                            names = [attr['Name'].decode('utf-8').strip() for attr in attrs_dataset]
         | 
| 210 | 
            +
                            
         | 
| 211 | 
            +
                            # Extract Cross Section Only (Unique Names)
         | 
| 212 | 
            +
                            cross_section_only_dataset = hdf_file[f"{base_output_path}Cross Section Only"][:]
         | 
| 213 | 
            +
                            cross_section_names = [cs.decode('utf-8').strip() for cs in cross_section_only_dataset]
         | 
| 214 | 
            +
                            
         | 
| 215 | 
            +
                            # Extract Time Stamps and convert to datetime
         | 
| 216 | 
            +
                            time_stamps = hdf_file[time_stamp_path][:]
         | 
| 217 | 
            +
                            if any(isinstance(ts, bytes) for ts in time_stamps):
         | 
| 218 | 
            +
                                time_stamps = [ts.decode('utf-8') for ts in time_stamps]
         | 
| 219 | 
            +
                            # Convert RAS format timestamps to datetime
         | 
| 220 | 
            +
                            times = pd.to_datetime(time_stamps, format='%d%b%Y %H:%M:%S:%f')
         | 
| 221 | 
            +
                            
         | 
| 222 | 
            +
                            # Extract Required Datasets
         | 
| 223 | 
            +
                            water_surface = hdf_file[f"{base_output_path}Water Surface"][:]
         | 
| 224 | 
            +
                            velocity_total = hdf_file[f"{base_output_path}Velocity Total"][:]
         | 
| 225 | 
            +
                            velocity_channel = hdf_file[f"{base_output_path}Velocity Channel"][:]
         | 
| 226 | 
            +
                            flow_lateral = hdf_file[f"{base_output_path}Flow Lateral"][:]
         | 
| 227 | 
            +
                            flow = hdf_file[f"{base_output_path}Flow"][:]
         | 
| 228 | 
            +
                            
         | 
| 229 | 
            +
                            # Calculate maximum values along time axis
         | 
| 230 | 
            +
                            max_water_surface = np.max(water_surface, axis=0)
         | 
| 231 | 
            +
                            max_flow = np.max(flow, axis=0)
         | 
| 232 | 
            +
                            max_velocity_channel = np.max(velocity_channel, axis=0)
         | 
| 233 | 
            +
                            max_velocity_total = np.max(velocity_total, axis=0)
         | 
| 234 | 
            +
                            max_flow_lateral = np.max(flow_lateral, axis=0)
         | 
| 235 | 
            +
                            
         | 
| 236 | 
            +
                            # Create Xarray Dataset
         | 
| 237 | 
            +
                            ds = xr.Dataset(
         | 
| 238 | 
            +
                                {
         | 
| 239 | 
            +
                                    'Water_Surface': (['time', 'cross_section'], water_surface),
         | 
| 240 | 
            +
                                    'Velocity_Total': (['time', 'cross_section'], velocity_total),
         | 
| 241 | 
            +
                                    'Velocity_Channel': (['time', 'cross_section'], velocity_channel),
         | 
| 242 | 
            +
                                    'Flow_Lateral': (['time', 'cross_section'], flow_lateral),
         | 
| 243 | 
            +
                                    'Flow': (['time', 'cross_section'], flow),
         | 
| 244 | 
            +
                                },
         | 
| 245 | 
            +
                                coords={
         | 
| 246 | 
            +
                                    'time': times,
         | 
| 247 | 
            +
                                    'cross_section': cross_section_names,
         | 
| 248 | 
            +
                                    'River': ('cross_section', rivers),
         | 
| 249 | 
            +
                                    'Reach': ('cross_section', reaches),
         | 
| 250 | 
            +
                                    'Station': ('cross_section', stations),
         | 
| 251 | 
            +
                                    'Name': ('cross_section', names),
         | 
| 252 | 
            +
                                    'Maximum_Water_Surface': ('cross_section', max_water_surface),
         | 
| 253 | 
            +
                                    'Maximum_Flow': ('cross_section', max_flow),
         | 
| 254 | 
            +
                                    'Maximum_Channel_Velocity': ('cross_section', max_velocity_channel),
         | 
| 255 | 
            +
                                    'Maximum_Velocity_Total': ('cross_section', max_velocity_total),
         | 
| 256 | 
            +
                                    'Maximum_Flow_Lateral': ('cross_section', max_flow_lateral)
         | 
| 257 | 
            +
                                },
         | 
| 258 | 
            +
                                attrs={
         | 
| 259 | 
            +
                                    'description': 'Cross-section results extracted from HEC-RAS HDF file',
         | 
| 260 | 
            +
                                    'source_file': str(hdf_path)
         | 
| 261 | 
            +
                                }
         | 
| 262 | 
            +
                            )
         | 
| 263 | 
            +
                            
         | 
| 264 | 
            +
                            return ds
         | 
| 437 265 |  | 
| 438 266 | 
             
                    except KeyError as e:
         | 
| 439 267 | 
             
                        logger.error(f"Required dataset not found in HDF file: {e}")
         | 
| 440 268 | 
             
                        raise
         | 
| 441 269 | 
             
                    except Exception as e:
         | 
| 442 | 
            -
                        logger.error(f"Error extracting  | 
| 443 | 
            -
                        raise
         | 
| 270 | 
            +
                        logger.error(f"Error extracting cross section results: {e}")
         | 
| 271 | 
            +
                        raise
         | 
| 272 | 
            +
             |