ras-commander 0.52.0__py3-none-any.whl → 0.54.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/Decorators.py +137 -127
- ras_commander/HdfBase.py +21 -6
- ras_commander/HdfFluvialPluvial.py +553 -553
- ras_commander/HdfResultsPlan.py +192 -84
- ras_commander/HdfStruc.py +1 -1
- ras_commander/HdfXsec.py +2 -2
- ras_commander/LoggingConfig.py +2 -1
- ras_commander/RasCmdr.py +45 -20
- ras_commander/RasPlan.py +74 -65
- ras_commander/RasPrj.py +934 -917
- ras_commander/RasUnsteady.py +38 -19
- {ras_commander-0.52.0.dist-info → ras_commander-0.54.0.dist-info}/METADATA +92 -49
- {ras_commander-0.52.0.dist-info → ras_commander-0.54.0.dist-info}/RECORD +16 -16
- {ras_commander-0.52.0.dist-info → ras_commander-0.54.0.dist-info}/WHEEL +1 -1
- {ras_commander-0.52.0.dist-info → ras_commander-0.54.0.dist-info}/LICENSE +0 -0
- {ras_commander-0.52.0.dist-info → ras_commander-0.54.0.dist-info}/top_level.txt +0 -0
    
        ras_commander/Decorators.py
    CHANGED
    
    | @@ -1,128 +1,138 @@ | |
| 1 | 
            -
            from functools import wraps
         | 
| 2 | 
            -
            from pathlib import Path
         | 
| 3 | 
            -
            from typing import Union
         | 
| 4 | 
            -
            import logging
         | 
| 5 | 
            -
            import h5py
         | 
| 6 | 
            -
            import inspect
         | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
            def log_call(func):
         | 
| 10 | 
            -
                @wraps(func)
         | 
| 11 | 
            -
                def wrapper(*args, **kwargs):
         | 
| 12 | 
            -
                    logger = logging.getLogger(func.__module__)
         | 
| 13 | 
            -
                    logger. | 
| 14 | 
            -
                    result = func(*args, **kwargs)
         | 
| 15 | 
            -
                    logger. | 
| 16 | 
            -
                    return result
         | 
| 17 | 
            -
                return wrapper
         | 
| 18 | 
            -
             | 
| 19 | 
            -
            def standardize_input(file_type: str = 'plan_hdf'):
         | 
| 20 | 
            -
                """
         | 
| 21 | 
            -
                Decorator to standardize input for HDF file operations.
         | 
| 22 | 
            -
                
         | 
| 23 | 
            -
                This decorator processes various input types and converts them to a Path object
         | 
| 24 | 
            -
                pointing to the correct HDF file. It handles the following input types:
         | 
| 25 | 
            -
                - h5py.File objects
         | 
| 26 | 
            -
                - pathlib.Path objects
         | 
| 27 | 
            -
                - Strings (file paths or plan/geom numbers)
         | 
| 28 | 
            -
                - Integers (interpreted as plan/geom numbers)
         | 
| 29 | 
            -
                
         | 
| 30 | 
            -
                The decorator also manages RAS object references and logging.
         | 
| 31 | 
            -
                
         | 
| 32 | 
            -
                Args:
         | 
| 33 | 
            -
                    file_type (str): Specifies whether to look for 'plan_hdf' or 'geom_hdf' files.
         | 
| 34 | 
            -
                
         | 
| 35 | 
            -
                Returns:
         | 
| 36 | 
            -
                    A decorator that wraps the function to standardize its input to a Path object.
         | 
| 37 | 
            -
                """
         | 
| 38 | 
            -
                def decorator(func):
         | 
| 39 | 
            -
                    @wraps(func)
         | 
| 40 | 
            -
                    def wrapper(*args, **kwargs):
         | 
| 41 | 
            -
                        logger = logging.getLogger(func.__module__)
         | 
| 42 | 
            -
                        
         | 
| 43 | 
            -
                        # Check if the function expects an hdf_path parameter
         | 
| 44 | 
            -
                        sig = inspect.signature(func)
         | 
| 45 | 
            -
                        param_names = list(sig.parameters.keys())
         | 
| 46 | 
            -
                        
         | 
| 47 | 
            -
                        # If first parameter is 'hdf_file', skip path processing
         | 
| 48 | 
            -
                        if param_names and param_names[0] == 'hdf_file':
         | 
| 49 | 
            -
                            return func(*args, **kwargs)
         | 
| 50 | 
            -
                            
         | 
| 51 | 
            -
                        # Handle both static method calls and regular function calls
         | 
| 52 | 
            -
                        if args and isinstance(args[0], type):
         | 
| 53 | 
            -
                            # Static method call, remove the class argument
         | 
| 54 | 
            -
                            args = args[1:]
         | 
| 55 | 
            -
                        
         | 
| 56 | 
            -
                        hdf_input = kwargs.pop('hdf_path', None) or kwargs.pop('hdf_input', None) or (args[0] if args else None)
         | 
| 57 | 
            -
                         | 
| 58 | 
            -
             | 
| 59 | 
            -
                         | 
| 60 | 
            -
                        if  | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
                        #  | 
| 64 | 
            -
                        if  | 
| 65 | 
            -
                             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
                         | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
                        # Handle  | 
| 79 | 
            -
                        elif isinstance(hdf_input,  | 
| 80 | 
            -
                             | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
                             | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
                                 | 
| 90 | 
            -
                                     | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
                                     | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
                                 | 
| 112 | 
            -
             | 
| 113 | 
            -
                             | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
                             | 
| 120 | 
            -
             | 
| 121 | 
            -
             | 
| 122 | 
            -
             | 
| 123 | 
            -
             | 
| 124 | 
            -
             | 
| 125 | 
            -
             | 
| 126 | 
            -
             | 
| 127 | 
            -
             | 
| 1 | 
            +
            from functools import wraps
         | 
| 2 | 
            +
            from pathlib import Path
         | 
| 3 | 
            +
            from typing import Union
         | 
| 4 | 
            +
            import logging
         | 
| 5 | 
            +
            import h5py
         | 
| 6 | 
            +
            import inspect
         | 
| 7 | 
            +
             | 
| 8 | 
            +
             | 
| 9 | 
            +
            def log_call(func):
         | 
| 10 | 
            +
                @wraps(func)
         | 
| 11 | 
            +
                def wrapper(*args, **kwargs):
         | 
| 12 | 
            +
                    logger = logging.getLogger(func.__module__)
         | 
| 13 | 
            +
                    logger.debug(f"Calling {func.__name__}")
         | 
| 14 | 
            +
                    result = func(*args, **kwargs)
         | 
| 15 | 
            +
                    logger.debug(f"Finished {func.__name__}")
         | 
| 16 | 
            +
                    return result
         | 
| 17 | 
            +
                return wrapper
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            def standardize_input(file_type: str = 'plan_hdf'):
         | 
| 20 | 
            +
                """
         | 
| 21 | 
            +
                Decorator to standardize input for HDF file operations.
         | 
| 22 | 
            +
                
         | 
| 23 | 
            +
                This decorator processes various input types and converts them to a Path object
         | 
| 24 | 
            +
                pointing to the correct HDF file. It handles the following input types:
         | 
| 25 | 
            +
                - h5py.File objects
         | 
| 26 | 
            +
                - pathlib.Path objects
         | 
| 27 | 
            +
                - Strings (file paths or plan/geom numbers)
         | 
| 28 | 
            +
                - Integers (interpreted as plan/geom numbers)
         | 
| 29 | 
            +
                
         | 
| 30 | 
            +
                The decorator also manages RAS object references and logging.
         | 
| 31 | 
            +
                
         | 
| 32 | 
            +
                Args:
         | 
| 33 | 
            +
                    file_type (str): Specifies whether to look for 'plan_hdf' or 'geom_hdf' files.
         | 
| 34 | 
            +
                
         | 
| 35 | 
            +
                Returns:
         | 
| 36 | 
            +
                    A decorator that wraps the function to standardize its input to a Path object.
         | 
| 37 | 
            +
                """
         | 
| 38 | 
            +
                def decorator(func):
         | 
| 39 | 
            +
                    @wraps(func)
         | 
| 40 | 
            +
                    def wrapper(*args, **kwargs):
         | 
| 41 | 
            +
                        logger = logging.getLogger(func.__module__)
         | 
| 42 | 
            +
                        
         | 
| 43 | 
            +
                        # Check if the function expects an hdf_path parameter
         | 
| 44 | 
            +
                        sig = inspect.signature(func)
         | 
| 45 | 
            +
                        param_names = list(sig.parameters.keys())
         | 
| 46 | 
            +
                        
         | 
| 47 | 
            +
                        # If first parameter is 'hdf_file', skip path processing
         | 
| 48 | 
            +
                        if param_names and param_names[0] == 'hdf_file':
         | 
| 49 | 
            +
                            return func(*args, **kwargs)
         | 
| 50 | 
            +
                            
         | 
| 51 | 
            +
                        # Handle both static method calls and regular function calls
         | 
| 52 | 
            +
                        if args and isinstance(args[0], type):
         | 
| 53 | 
            +
                            # Static method call, remove the class argument
         | 
| 54 | 
            +
                            args = args[1:]
         | 
| 55 | 
            +
                        
         | 
| 56 | 
            +
                        hdf_input = kwargs.pop('hdf_path', None) or kwargs.pop('hdf_input', None) or (args[0] if args else None)
         | 
| 57 | 
            +
                        
         | 
| 58 | 
            +
                        # Import ras here to ensure we get the most current instance
         | 
| 59 | 
            +
                        from .RasPrj import ras as ras
         | 
| 60 | 
            +
                        ras_object = kwargs.pop('ras_object', None) or (args[1] if len(args) > 1 else None)
         | 
| 61 | 
            +
                        ras_obj = ras_object or ras
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                        # If no hdf_input provided, return the function unmodified
         | 
| 64 | 
            +
                        if hdf_input is None:
         | 
| 65 | 
            +
                            return func(*args, **kwargs)
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                        # NEW: If input is already a Path and exists, use it directly regardless of file_type
         | 
| 68 | 
            +
                        if isinstance(hdf_input, Path) and hdf_input.is_file():
         | 
| 69 | 
            +
                            logger.info(f"Using existing HDF file: {hdf_input}")
         | 
| 70 | 
            +
                            new_args = (hdf_input,) + args[1:]
         | 
| 71 | 
            +
                            return func(*new_args, **kwargs)
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                        hdf_path = None
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                        # If hdf_input is already an h5py.File object, use its filename
         | 
| 76 | 
            +
                        if isinstance(hdf_input, h5py.File):
         | 
| 77 | 
            +
                            hdf_path = Path(hdf_input.filename)
         | 
| 78 | 
            +
                        # Handle Path objects
         | 
| 79 | 
            +
                        elif isinstance(hdf_input, Path):
         | 
| 80 | 
            +
                            if hdf_input.is_file():
         | 
| 81 | 
            +
                                hdf_path = hdf_input
         | 
| 82 | 
            +
                        # Handle string inputs
         | 
| 83 | 
            +
                        elif isinstance(hdf_input, str):
         | 
| 84 | 
            +
                            # Check if it's a file path
         | 
| 85 | 
            +
                            if Path(hdf_input).is_file():
         | 
| 86 | 
            +
                                hdf_path = Path(hdf_input)
         | 
| 87 | 
            +
                            # Check if it's a number (with or without 'p' prefix)
         | 
| 88 | 
            +
                            elif hdf_input.isdigit() or (len(hdf_input) == 3 and hdf_input[0] == 'p' and hdf_input[1:].isdigit()):
         | 
| 89 | 
            +
                                try:
         | 
| 90 | 
            +
                                    ras_obj.check_initialized()
         | 
| 91 | 
            +
                                except Exception as e:
         | 
| 92 | 
            +
                                    raise ValueError(f"RAS object is not initialized: {str(e)}")
         | 
| 93 | 
            +
                                    
         | 
| 94 | 
            +
                                number = hdf_input if hdf_input.isdigit() else hdf_input[1:]
         | 
| 95 | 
            +
                                
         | 
| 96 | 
            +
                                if file_type == 'plan_hdf':
         | 
| 97 | 
            +
                                    plan_info = ras_obj.plan_df[ras_obj.plan_df['plan_number'] == number]
         | 
| 98 | 
            +
                                    if not plan_info.empty:
         | 
| 99 | 
            +
                                        hdf_path = Path(plan_info.iloc[0]['HDF_Results_Path'])
         | 
| 100 | 
            +
                                elif file_type == 'geom_hdf':
         | 
| 101 | 
            +
                                    geom_info = ras_obj.geom_df[ras_obj.geom_df['geom_number'] == number]
         | 
| 102 | 
            +
                                    if not geom_info.empty:
         | 
| 103 | 
            +
                                        hdf_path = Path(geom_info.iloc[0]['HDF_Path'])
         | 
| 104 | 
            +
                                else:
         | 
| 105 | 
            +
                                    raise ValueError(f"Invalid file type: {file_type}")
         | 
| 106 | 
            +
                        # Handle integer inputs (assuming they're plan or geom numbers)
         | 
| 107 | 
            +
                        elif isinstance(hdf_input, int):
         | 
| 108 | 
            +
                            try:
         | 
| 109 | 
            +
                                ras_obj.check_initialized()
         | 
| 110 | 
            +
                            except Exception as e:
         | 
| 111 | 
            +
                                raise ValueError(f"RAS object is not initialized: {str(e)}")
         | 
| 112 | 
            +
                                
         | 
| 113 | 
            +
                            number = f"{hdf_input:02d}"
         | 
| 114 | 
            +
                            
         | 
| 115 | 
            +
                            if file_type == 'plan_hdf':
         | 
| 116 | 
            +
                                plan_info = ras_obj.plan_df[ras_obj.plan_df['plan_number'] == number]
         | 
| 117 | 
            +
                                if not plan_info.empty:
         | 
| 118 | 
            +
                                    hdf_path = Path(plan_info.iloc[0]['HDF_Results_Path'])
         | 
| 119 | 
            +
                            elif file_type == 'geom_hdf':
         | 
| 120 | 
            +
                                geom_info = ras_obj.geom_df[ras_obj.geom_df['geom_number'] == number]
         | 
| 121 | 
            +
                                if not geom_info.empty:
         | 
| 122 | 
            +
                                    hdf_path = Path(geom_info.iloc[0]['HDF_Path'])
         | 
| 123 | 
            +
                            else:
         | 
| 124 | 
            +
                                raise ValueError(f"Invalid file type: {file_type}")
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                        if hdf_path is None or not hdf_path.is_file():
         | 
| 127 | 
            +
                            error_msg = f"HDF file not found: {hdf_input}"
         | 
| 128 | 
            +
                            logger.error(error_msg)
         | 
| 129 | 
            +
                            raise FileNotFoundError(error_msg)
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                        logger.info(f"Using HDF file: {hdf_path}")
         | 
| 132 | 
            +
                        
         | 
| 133 | 
            +
                        # Pass all original arguments and keywords, replacing hdf_input with standardized hdf_path
         | 
| 134 | 
            +
                        new_args = (hdf_path,) + args[1:]
         | 
| 135 | 
            +
                        return func(*new_args, **kwargs)
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                    return wrapper
         | 
| 128 138 | 
             
                return decorator
         | 
    
        ras_commander/HdfBase.py
    CHANGED
    
    | @@ -158,6 +158,7 @@ class HdfBase: | |
| 158 158 |  | 
| 159 159 | 
             
                    project_folder = hdf_path.parent
         | 
| 160 160 | 
             
                    wkt = None
         | 
| 161 | 
            +
                    proj_file = None  # Initialize proj_file variable
         | 
| 161 162 |  | 
| 162 163 | 
             
                    # Try HDF file
         | 
| 163 164 | 
             
                    try:
         | 
| @@ -170,6 +171,7 @@ class HdfBase: | |
| 170 171 | 
             
                                    return wkt
         | 
| 171 172 | 
             
                    except Exception as e:
         | 
| 172 173 | 
             
                        logger.error(f"Error reading projection from HDF file {hdf_path}: {str(e)}")
         | 
| 174 | 
            +
             | 
| 173 175 | 
             
                    # Try RASMapper file if no HDF projection
         | 
| 174 176 | 
             
                    if not wkt:
         | 
| 175 177 | 
             
                        try:
         | 
| @@ -189,16 +191,29 @@ class HdfBase: | |
| 189 191 | 
             
                        except Exception as e:
         | 
| 190 192 | 
             
                            logger.error(f"Error reading RASMapper projection file: {str(e)}")
         | 
| 191 193 |  | 
| 192 | 
            -
                     | 
| 193 | 
            -
             | 
| 194 | 
            -
                         | 
| 195 | 
            -
             | 
| 196 | 
            -
             | 
| 194 | 
            +
                    # Customize error message based on whether proj_file was found
         | 
| 195 | 
            +
                    if proj_file:
         | 
| 196 | 
            +
                        error_msg = (
         | 
| 197 | 
            +
                            "No valid projection found. Checked:\n"
         | 
| 198 | 
            +
                            f"1. HDF file projection attribute: {hdf_path}\n"
         | 
| 199 | 
            +
                            f"2. RASMapper projection file {proj_file} found in RASMapper file, but was invalid"
         | 
| 200 | 
            +
                        )
         | 
| 201 | 
            +
                    else:
         | 
| 202 | 
            +
                        error_msg = (
         | 
| 203 | 
            +
                            "No valid projection found. Checked:\n"
         | 
| 204 | 
            +
                            f"1. HDF file projection attribute: {hdf_path}\n was checked and no projection attribute found"
         | 
| 205 | 
            +
                            "2. No RASMapper projection file found"
         | 
| 206 | 
            +
                        )
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                    error_msg += (
         | 
| 209 | 
            +
                        "\nTo fix this:\n"
         | 
| 197 210 | 
             
                        "1. Open RASMapper\n"
         | 
| 198 211 | 
             
                        "2. Click Map > Set Projection\n" 
         | 
| 199 212 | 
             
                        "3. Select an appropriate projection file or coordinate system\n"
         | 
| 200 213 | 
             
                        "4. Save the RASMapper project"
         | 
| 201 214 | 
             
                    )
         | 
| 215 | 
            +
                    
         | 
| 216 | 
            +
                    logger.critical(error_msg)
         | 
| 202 217 | 
             
                    return None
         | 
| 203 218 |  | 
| 204 219 | 
             
                @staticmethod
         | 
| @@ -219,7 +234,7 @@ class HdfBase: | |
| 219 234 | 
             
                            logger.warning(f"Path {attr_path} not found in HDF file")
         | 
| 220 235 | 
             
                            return {}
         | 
| 221 236 |  | 
| 222 | 
            -
                        return HdfUtils. | 
| 237 | 
            +
                        return HdfUtils.convert_hdf5_attrs_to_dict(hdf_file[attr_path].attrs)
         | 
| 223 238 | 
             
                    except Exception as e:
         | 
| 224 239 | 
             
                        logger.error(f"Error getting attributes from {attr_path}: {str(e)}")
         | 
| 225 240 | 
             
                        return {}
         |