ras-commander 0.76.0__py3-none-any.whl → 0.78.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 +256 -256
- ras_commander/HdfInfiltration.py +1529 -1529
- ras_commander/HdfResultsPlan.py +380 -380
- ras_commander/RasExamples.py +543 -424
- ras_commander/RasGeo.py +3 -3
- ras_commander/RasMap.py +467 -252
- ras_commander/RasPlan.py +1536 -1536
- ras_commander/RasPrj.py +1479 -1474
- ras_commander/__init__.py +1 -1
- {ras_commander-0.76.0.dist-info → ras_commander-0.78.0.dist-info}/METADATA +17 -12
- {ras_commander-0.76.0.dist-info → ras_commander-0.78.0.dist-info}/RECORD +14 -14
- {ras_commander-0.76.0.dist-info → ras_commander-0.78.0.dist-info}/WHEEL +1 -1
- {ras_commander-0.76.0.dist-info → ras_commander-0.78.0.dist-info}/licenses/LICENSE +0 -0
- {ras_commander-0.76.0.dist-info → ras_commander-0.78.0.dist-info}/top_level.txt +0 -0
ras_commander/Decorators.py
CHANGED
@@ -1,257 +1,257 @@
|
|
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
|
-
import pandas as pd
|
8
|
-
|
9
|
-
|
10
|
-
def log_call(func):
|
11
|
-
@wraps(func)
|
12
|
-
def wrapper(*args, **kwargs):
|
13
|
-
logger = logging.getLogger(func.__module__)
|
14
|
-
logger.debug(f"Calling {func.__name__}")
|
15
|
-
result = func(*args, **kwargs)
|
16
|
-
logger.debug(f"Finished {func.__name__}")
|
17
|
-
return result
|
18
|
-
return wrapper
|
19
|
-
|
20
|
-
def standardize_input(file_type: str = 'plan_hdf'):
|
21
|
-
"""
|
22
|
-
Decorator to standardize input for HDF file operations.
|
23
|
-
|
24
|
-
This decorator processes various input types and converts them to a Path object
|
25
|
-
pointing to the correct HDF file. It handles the following input types:
|
26
|
-
- h5py.File objects
|
27
|
-
- pathlib.Path objects
|
28
|
-
- Strings (file paths or plan/geom numbers)
|
29
|
-
- Integers (interpreted as plan/geom numbers)
|
30
|
-
|
31
|
-
The decorator also manages RAS object references and logging.
|
32
|
-
|
33
|
-
Args:
|
34
|
-
file_type (str): Specifies whether to look for 'plan_hdf' or 'geom_hdf' files.
|
35
|
-
|
36
|
-
Returns:
|
37
|
-
A decorator that wraps the function to standardize its input to a Path object.
|
38
|
-
"""
|
39
|
-
def decorator(func):
|
40
|
-
@wraps(func)
|
41
|
-
def wrapper(*args, **kwargs):
|
42
|
-
logger = logging.getLogger(func.__module__)
|
43
|
-
|
44
|
-
# Check if the function expects an hdf_path parameter
|
45
|
-
sig = inspect.signature(func)
|
46
|
-
param_names = list(sig.parameters.keys())
|
47
|
-
|
48
|
-
# If first parameter is 'hdf_file', pass an h5py object
|
49
|
-
if param_names and param_names[0] == 'hdf_file':
|
50
|
-
if isinstance(args[0], h5py.File):
|
51
|
-
return func(*args, **kwargs)
|
52
|
-
elif isinstance(args[0], (str, Path)):
|
53
|
-
with h5py.File(args[0], 'r') as hdf:
|
54
|
-
return func(hdf, *args[1:], **kwargs)
|
55
|
-
else:
|
56
|
-
raise ValueError(f"Expected h5py.File or path, got {type(args[0])}")
|
57
|
-
|
58
|
-
# Handle both static method calls and regular function calls
|
59
|
-
if args and isinstance(args[0], type):
|
60
|
-
# Static method call, remove the class argument
|
61
|
-
args = args[1:]
|
62
|
-
|
63
|
-
# Get hdf_input from kwargs if provided with hdf_path key, or take first positional arg
|
64
|
-
hdf_input = kwargs.pop('hdf_path', None) if 'hdf_path' in kwargs else (args[0] if args else None)
|
65
|
-
|
66
|
-
# Import ras here to ensure we get the most current instance
|
67
|
-
from .RasPrj import ras as ras
|
68
|
-
ras_object = kwargs.pop('ras_object', None) or (args[1] if len(args) > 1 else None)
|
69
|
-
ras_obj = ras_object or ras
|
70
|
-
|
71
|
-
# If no hdf_input provided, return the function unmodified
|
72
|
-
if hdf_input is None:
|
73
|
-
return func(*args, **kwargs)
|
74
|
-
|
75
|
-
hdf_path = None
|
76
|
-
|
77
|
-
# Clean and normalize string inputs
|
78
|
-
if isinstance(hdf_input, str):
|
79
|
-
# Clean the string (remove extra whitespace, normalize path separators)
|
80
|
-
hdf_input = hdf_input.strip()
|
81
|
-
|
82
|
-
# Check if it's a raw file path that exists
|
83
|
-
try:
|
84
|
-
test_path = Path(hdf_input)
|
85
|
-
if test_path.is_file():
|
86
|
-
hdf_path = test_path
|
87
|
-
logger.info(f"Using HDF file from direct string path: {hdf_path}")
|
88
|
-
except Exception as e:
|
89
|
-
logger.debug(f"Error converting string to path: {str(e)}")
|
90
|
-
|
91
|
-
# If a valid path wasn't created from string processing, continue with normal flow
|
92
|
-
if hdf_path is None:
|
93
|
-
# If hdf_input is already a Path and exists, use it directly
|
94
|
-
if isinstance(hdf_input, Path) and hdf_input.is_file():
|
95
|
-
hdf_path = hdf_input
|
96
|
-
logger.info(f"Using existing Path object HDF file: {hdf_path}")
|
97
|
-
# If hdf_input is an h5py.File object, use its filename
|
98
|
-
elif isinstance(hdf_input, h5py.File):
|
99
|
-
hdf_path = Path(hdf_input.filename)
|
100
|
-
logger.info(f"Using HDF file from h5py.File object: {hdf_path}")
|
101
|
-
# Handle Path objects that might not be verified yet
|
102
|
-
elif isinstance(hdf_input, Path):
|
103
|
-
if hdf_input.is_file():
|
104
|
-
hdf_path = hdf_input
|
105
|
-
logger.info(f"Using verified Path object HDF file: {hdf_path}")
|
106
|
-
# Handle string inputs that are plan/geom numbers
|
107
|
-
elif isinstance(hdf_input, str) and (hdf_input.isdigit() or (len(hdf_input) > 1 and hdf_input[0] == 'p' and hdf_input[1:].isdigit())):
|
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
|
-
# Extract the number part and strip leading zeros
|
114
|
-
number_str = hdf_input if hdf_input.isdigit() else hdf_input[1:]
|
115
|
-
stripped_number = number_str.lstrip('0')
|
116
|
-
if stripped_number == '': # Handle case where input was '0' or '00'
|
117
|
-
stripped_number = '0'
|
118
|
-
number_int = int(stripped_number)
|
119
|
-
|
120
|
-
if file_type == 'plan_hdf':
|
121
|
-
try:
|
122
|
-
# Convert plan_number column to integers for comparison after stripping zeros
|
123
|
-
plan_info = ras_obj.plan_df[ras_obj.plan_df['plan_number'].str.lstrip('0').astype(int) == number_int]
|
124
|
-
if not plan_info.empty:
|
125
|
-
# Make sure HDF_Results_Path is a string and not None
|
126
|
-
hdf_path_str = plan_info.iloc[0]['HDF_Results_Path']
|
127
|
-
if pd.notna(hdf_path_str):
|
128
|
-
hdf_path = Path(str(hdf_path_str))
|
129
|
-
except Exception as e:
|
130
|
-
logger.warning(f"Error retrieving plan HDF path: {str(e)}")
|
131
|
-
|
132
|
-
|
133
|
-
elif file_type == 'geom_hdf':
|
134
|
-
try:
|
135
|
-
# First try to get the geometry number from the plan
|
136
|
-
from ras_commander import RasPlan
|
137
|
-
plan_info = ras_obj.plan_df[ras_obj.plan_df['plan_number'].astype(int) == number_int]
|
138
|
-
if not plan_info.empty:
|
139
|
-
# Extract the geometry number from the plan
|
140
|
-
geom_number = plan_info.iloc[0]['geometry_number']
|
141
|
-
if pd.notna(geom_number) and geom_number is not None:
|
142
|
-
# Handle different types of geom_number (string or int)
|
143
|
-
try:
|
144
|
-
# Get the geometry path using RasPlan
|
145
|
-
geom_path = RasPlan.get_geom_path(str(geom_number), ras_obj)
|
146
|
-
|
147
|
-
if geom_path is not None:
|
148
|
-
# Create the HDF path by adding .hdf to the geometry path
|
149
|
-
hdf_path = Path(str(geom_path) + ".hdf")
|
150
|
-
if hdf_path.exists():
|
151
|
-
logger.info(f"Found geometry HDF file for plan {number_int}: {hdf_path}")
|
152
|
-
else:
|
153
|
-
# Try to find it in the geom_df if direct path doesn't exist
|
154
|
-
geom_info = ras_obj.geom_df[ras_obj.geom_df['full_path'] == str(geom_path)]
|
155
|
-
if not geom_info.empty and 'hdf_path' in geom_info.columns:
|
156
|
-
hdf_path_str = geom_info.iloc[0]['hdf_path']
|
157
|
-
if pd.notna(hdf_path_str):
|
158
|
-
hdf_path = Path(str(hdf_path_str))
|
159
|
-
logger.info(f"Found geometry HDF file from geom_df for plan {number_int}: {hdf_path}")
|
160
|
-
except (TypeError, ValueError) as e:
|
161
|
-
logger.warning(f"Error processing geometry number {geom_number}: {str(e)}")
|
162
|
-
else:
|
163
|
-
logger.warning(f"No valid geometry number found for plan {number_int}")
|
164
|
-
except Exception as e:
|
165
|
-
logger.warning(f"Error retrieving geometry HDF path: {str(e)}")
|
166
|
-
else:
|
167
|
-
raise ValueError(f"Invalid file type: {file_type}")
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
# Handle integer inputs (assuming they're plan or geom numbers)
|
173
|
-
elif isinstance(hdf_input, int):
|
174
|
-
try:
|
175
|
-
ras_obj.check_initialized()
|
176
|
-
except Exception as e:
|
177
|
-
raise ValueError(f"RAS object is not initialized: {str(e)}")
|
178
|
-
|
179
|
-
number_int = hdf_input
|
180
|
-
|
181
|
-
if file_type == 'plan_hdf':
|
182
|
-
try:
|
183
|
-
# Convert plan_number column to integers for comparison after stripping zeros
|
184
|
-
plan_info = ras_obj.plan_df[ras_obj.plan_df['plan_number'].str.lstrip('0').astype(int) == number_int]
|
185
|
-
if not plan_info.empty:
|
186
|
-
# Make sure HDF_Results_Path is a string and not None
|
187
|
-
hdf_path_str = plan_info.iloc[0]['HDF_Results_Path']
|
188
|
-
if pd.notna(hdf_path_str):
|
189
|
-
hdf_path = Path(str(hdf_path_str))
|
190
|
-
except Exception as e:
|
191
|
-
logger.warning(f"Error retrieving plan HDF path: {str(e)}")
|
192
|
-
|
193
|
-
elif file_type == 'geom_hdf':
|
194
|
-
try:
|
195
|
-
# First try finding plan info to get geometry number
|
196
|
-
plan_info = ras_obj.plan_df[ras_obj.plan_df['plan_number'].astype(int) == number_int]
|
197
|
-
if not plan_info.empty:
|
198
|
-
# Extract the geometry number from the plan
|
199
|
-
geom_number = plan_info.iloc[0]['geometry_number']
|
200
|
-
if pd.notna(geom_number) and geom_number is not None:
|
201
|
-
# Handle different types of geom_number (string or int)
|
202
|
-
try:
|
203
|
-
# Get the geometry path using RasPlan
|
204
|
-
from ras_commander import RasPlan
|
205
|
-
geom_path = RasPlan.get_geom_path(str(geom_number), ras_obj)
|
206
|
-
|
207
|
-
if geom_path is not None:
|
208
|
-
# Create the HDF path by adding .hdf to the geometry path
|
209
|
-
hdf_path = Path(str(geom_path) + ".hdf")
|
210
|
-
if hdf_path.exists():
|
211
|
-
logger.info(f"Found geometry HDF file for plan {number_int}: {hdf_path}")
|
212
|
-
else:
|
213
|
-
# Try to find it in the geom_df if direct path doesn't exist
|
214
|
-
geom_info = ras_obj.geom_df[ras_obj.geom_df['full_path'] == str(geom_path)]
|
215
|
-
if not geom_info.empty and 'hdf_path' in geom_info.columns:
|
216
|
-
hdf_path_str = geom_info.iloc[0]['hdf_path']
|
217
|
-
if pd.notna(hdf_path_str):
|
218
|
-
hdf_path = Path(str(hdf_path_str))
|
219
|
-
logger.info(f"Found geometry HDF file from geom_df for plan {number_int}: {hdf_path}")
|
220
|
-
except (TypeError, ValueError) as e:
|
221
|
-
logger.warning(f"Error processing geometry number {geom_number}: {str(e)}")
|
222
|
-
else:
|
223
|
-
logger.warning(f"No valid geometry number found for plan {number_int}")
|
224
|
-
except Exception as e:
|
225
|
-
logger.warning(f"Error retrieving geometry HDF path: {str(e)}")
|
226
|
-
else:
|
227
|
-
raise ValueError(f"Invalid file type: {file_type}")
|
228
|
-
|
229
|
-
# Final verification that the path exists
|
230
|
-
if hdf_path is None or not hdf_path.exists():
|
231
|
-
error_msg = f"HDF file not found: {hdf_input}"
|
232
|
-
logger.error(error_msg)
|
233
|
-
raise FileNotFoundError(error_msg)
|
234
|
-
|
235
|
-
logger.info(f"Final validated HDF file path: {hdf_path}")
|
236
|
-
|
237
|
-
# Now try to validate the HDF file structure (but don't fail if validation fails)
|
238
|
-
try:
|
239
|
-
with h5py.File(hdf_path, 'r') as test_file:
|
240
|
-
# Just open to verify it's a valid HDF5 file
|
241
|
-
logger.debug(f"Successfully opened HDF file for validation: {hdf_path}")
|
242
|
-
except Exception as e:
|
243
|
-
logger.warning(f"Warning: Could not validate HDF file: {str(e)}")
|
244
|
-
# Continue anyway, let the function handle detailed validation
|
245
|
-
|
246
|
-
# Pass all original arguments and keywords, replacing hdf_input with standardized hdf_path
|
247
|
-
# If the original input was positional, replace the first argument
|
248
|
-
if args and 'hdf_path' not in kwargs:
|
249
|
-
new_args = (hdf_path,) + args[1:]
|
250
|
-
else:
|
251
|
-
new_args = args
|
252
|
-
kwargs['hdf_path'] = hdf_path
|
253
|
-
|
254
|
-
return func(*new_args, **kwargs)
|
255
|
-
|
256
|
-
return wrapper
|
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
|
+
import pandas as pd
|
8
|
+
|
9
|
+
|
10
|
+
def log_call(func):
|
11
|
+
@wraps(func)
|
12
|
+
def wrapper(*args, **kwargs):
|
13
|
+
logger = logging.getLogger(func.__module__)
|
14
|
+
logger.debug(f"Calling {func.__name__}")
|
15
|
+
result = func(*args, **kwargs)
|
16
|
+
logger.debug(f"Finished {func.__name__}")
|
17
|
+
return result
|
18
|
+
return wrapper
|
19
|
+
|
20
|
+
def standardize_input(file_type: str = 'plan_hdf'):
|
21
|
+
"""
|
22
|
+
Decorator to standardize input for HDF file operations.
|
23
|
+
|
24
|
+
This decorator processes various input types and converts them to a Path object
|
25
|
+
pointing to the correct HDF file. It handles the following input types:
|
26
|
+
- h5py.File objects
|
27
|
+
- pathlib.Path objects
|
28
|
+
- Strings (file paths or plan/geom numbers)
|
29
|
+
- Integers (interpreted as plan/geom numbers)
|
30
|
+
|
31
|
+
The decorator also manages RAS object references and logging.
|
32
|
+
|
33
|
+
Args:
|
34
|
+
file_type (str): Specifies whether to look for 'plan_hdf' or 'geom_hdf' files.
|
35
|
+
|
36
|
+
Returns:
|
37
|
+
A decorator that wraps the function to standardize its input to a Path object.
|
38
|
+
"""
|
39
|
+
def decorator(func):
|
40
|
+
@wraps(func)
|
41
|
+
def wrapper(*args, **kwargs):
|
42
|
+
logger = logging.getLogger(func.__module__)
|
43
|
+
|
44
|
+
# Check if the function expects an hdf_path parameter
|
45
|
+
sig = inspect.signature(func)
|
46
|
+
param_names = list(sig.parameters.keys())
|
47
|
+
|
48
|
+
# If first parameter is 'hdf_file', pass an h5py object
|
49
|
+
if param_names and param_names[0] == 'hdf_file':
|
50
|
+
if isinstance(args[0], h5py.File):
|
51
|
+
return func(*args, **kwargs)
|
52
|
+
elif isinstance(args[0], (str, Path)):
|
53
|
+
with h5py.File(args[0], 'r') as hdf:
|
54
|
+
return func(hdf, *args[1:], **kwargs)
|
55
|
+
else:
|
56
|
+
raise ValueError(f"Expected h5py.File or path, got {type(args[0])}")
|
57
|
+
|
58
|
+
# Handle both static method calls and regular function calls
|
59
|
+
if args and isinstance(args[0], type):
|
60
|
+
# Static method call, remove the class argument
|
61
|
+
args = args[1:]
|
62
|
+
|
63
|
+
# Get hdf_input from kwargs if provided with hdf_path key, or take first positional arg
|
64
|
+
hdf_input = kwargs.pop('hdf_path', None) if 'hdf_path' in kwargs else (args[0] if args else None)
|
65
|
+
|
66
|
+
# Import ras here to ensure we get the most current instance
|
67
|
+
from .RasPrj import ras as ras
|
68
|
+
ras_object = kwargs.pop('ras_object', None) or (args[1] if len(args) > 1 else None)
|
69
|
+
ras_obj = ras_object or ras
|
70
|
+
|
71
|
+
# If no hdf_input provided, return the function unmodified
|
72
|
+
if hdf_input is None:
|
73
|
+
return func(*args, **kwargs)
|
74
|
+
|
75
|
+
hdf_path = None
|
76
|
+
|
77
|
+
# Clean and normalize string inputs
|
78
|
+
if isinstance(hdf_input, str):
|
79
|
+
# Clean the string (remove extra whitespace, normalize path separators)
|
80
|
+
hdf_input = hdf_input.strip()
|
81
|
+
|
82
|
+
# Check if it's a raw file path that exists
|
83
|
+
try:
|
84
|
+
test_path = Path(hdf_input)
|
85
|
+
if test_path.is_file():
|
86
|
+
hdf_path = test_path
|
87
|
+
logger.info(f"Using HDF file from direct string path: {hdf_path}")
|
88
|
+
except Exception as e:
|
89
|
+
logger.debug(f"Error converting string to path: {str(e)}")
|
90
|
+
|
91
|
+
# If a valid path wasn't created from string processing, continue with normal flow
|
92
|
+
if hdf_path is None:
|
93
|
+
# If hdf_input is already a Path and exists, use it directly
|
94
|
+
if isinstance(hdf_input, Path) and hdf_input.is_file():
|
95
|
+
hdf_path = hdf_input
|
96
|
+
logger.info(f"Using existing Path object HDF file: {hdf_path}")
|
97
|
+
# If hdf_input is an h5py.File object, use its filename
|
98
|
+
elif isinstance(hdf_input, h5py.File):
|
99
|
+
hdf_path = Path(hdf_input.filename)
|
100
|
+
logger.info(f"Using HDF file from h5py.File object: {hdf_path}")
|
101
|
+
# Handle Path objects that might not be verified yet
|
102
|
+
elif isinstance(hdf_input, Path):
|
103
|
+
if hdf_input.is_file():
|
104
|
+
hdf_path = hdf_input
|
105
|
+
logger.info(f"Using verified Path object HDF file: {hdf_path}")
|
106
|
+
# Handle string inputs that are plan/geom numbers
|
107
|
+
elif isinstance(hdf_input, str) and (hdf_input.isdigit() or (len(hdf_input) > 1 and hdf_input[0] == 'p' and hdf_input[1:].isdigit())):
|
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
|
+
# Extract the number part and strip leading zeros
|
114
|
+
number_str = hdf_input if hdf_input.isdigit() else hdf_input[1:]
|
115
|
+
stripped_number = number_str.lstrip('0')
|
116
|
+
if stripped_number == '': # Handle case where input was '0' or '00'
|
117
|
+
stripped_number = '0'
|
118
|
+
number_int = int(stripped_number)
|
119
|
+
|
120
|
+
if file_type == 'plan_hdf':
|
121
|
+
try:
|
122
|
+
# Convert plan_number column to integers for comparison after stripping zeros
|
123
|
+
plan_info = ras_obj.plan_df[ras_obj.plan_df['plan_number'].str.lstrip('0').astype(int) == number_int]
|
124
|
+
if not plan_info.empty:
|
125
|
+
# Make sure HDF_Results_Path is a string and not None
|
126
|
+
hdf_path_str = plan_info.iloc[0]['HDF_Results_Path']
|
127
|
+
if pd.notna(hdf_path_str):
|
128
|
+
hdf_path = Path(str(hdf_path_str))
|
129
|
+
except Exception as e:
|
130
|
+
logger.warning(f"Error retrieving plan HDF path: {str(e)}")
|
131
|
+
|
132
|
+
|
133
|
+
elif file_type == 'geom_hdf':
|
134
|
+
try:
|
135
|
+
# First try to get the geometry number from the plan
|
136
|
+
from ras_commander import RasPlan
|
137
|
+
plan_info = ras_obj.plan_df[ras_obj.plan_df['plan_number'].astype(int) == number_int]
|
138
|
+
if not plan_info.empty:
|
139
|
+
# Extract the geometry number from the plan
|
140
|
+
geom_number = plan_info.iloc[0]['geometry_number']
|
141
|
+
if pd.notna(geom_number) and geom_number is not None:
|
142
|
+
# Handle different types of geom_number (string or int)
|
143
|
+
try:
|
144
|
+
# Get the geometry path using RasPlan
|
145
|
+
geom_path = RasPlan.get_geom_path(str(geom_number), ras_obj)
|
146
|
+
|
147
|
+
if geom_path is not None:
|
148
|
+
# Create the HDF path by adding .hdf to the geometry path
|
149
|
+
hdf_path = Path(str(geom_path) + ".hdf")
|
150
|
+
if hdf_path.exists():
|
151
|
+
logger.info(f"Found geometry HDF file for plan {number_int}: {hdf_path}")
|
152
|
+
else:
|
153
|
+
# Try to find it in the geom_df if direct path doesn't exist
|
154
|
+
geom_info = ras_obj.geom_df[ras_obj.geom_df['full_path'] == str(geom_path)]
|
155
|
+
if not geom_info.empty and 'hdf_path' in geom_info.columns:
|
156
|
+
hdf_path_str = geom_info.iloc[0]['hdf_path']
|
157
|
+
if pd.notna(hdf_path_str):
|
158
|
+
hdf_path = Path(str(hdf_path_str))
|
159
|
+
logger.info(f"Found geometry HDF file from geom_df for plan {number_int}: {hdf_path}")
|
160
|
+
except (TypeError, ValueError) as e:
|
161
|
+
logger.warning(f"Error processing geometry number {geom_number}: {str(e)}")
|
162
|
+
else:
|
163
|
+
logger.warning(f"No valid geometry number found for plan {number_int}")
|
164
|
+
except Exception as e:
|
165
|
+
logger.warning(f"Error retrieving geometry HDF path: {str(e)}")
|
166
|
+
else:
|
167
|
+
raise ValueError(f"Invalid file type: {file_type}")
|
168
|
+
|
169
|
+
|
170
|
+
|
171
|
+
|
172
|
+
# Handle integer inputs (assuming they're plan or geom numbers)
|
173
|
+
elif isinstance(hdf_input, int):
|
174
|
+
try:
|
175
|
+
ras_obj.check_initialized()
|
176
|
+
except Exception as e:
|
177
|
+
raise ValueError(f"RAS object is not initialized: {str(e)}")
|
178
|
+
|
179
|
+
number_int = hdf_input
|
180
|
+
|
181
|
+
if file_type == 'plan_hdf':
|
182
|
+
try:
|
183
|
+
# Convert plan_number column to integers for comparison after stripping zeros
|
184
|
+
plan_info = ras_obj.plan_df[ras_obj.plan_df['plan_number'].str.lstrip('0').astype(int) == number_int]
|
185
|
+
if not plan_info.empty:
|
186
|
+
# Make sure HDF_Results_Path is a string and not None
|
187
|
+
hdf_path_str = plan_info.iloc[0]['HDF_Results_Path']
|
188
|
+
if pd.notna(hdf_path_str):
|
189
|
+
hdf_path = Path(str(hdf_path_str))
|
190
|
+
except Exception as e:
|
191
|
+
logger.warning(f"Error retrieving plan HDF path: {str(e)}")
|
192
|
+
|
193
|
+
elif file_type == 'geom_hdf':
|
194
|
+
try:
|
195
|
+
# First try finding plan info to get geometry number
|
196
|
+
plan_info = ras_obj.plan_df[ras_obj.plan_df['plan_number'].astype(int) == number_int]
|
197
|
+
if not plan_info.empty:
|
198
|
+
# Extract the geometry number from the plan
|
199
|
+
geom_number = plan_info.iloc[0]['geometry_number']
|
200
|
+
if pd.notna(geom_number) and geom_number is not None:
|
201
|
+
# Handle different types of geom_number (string or int)
|
202
|
+
try:
|
203
|
+
# Get the geometry path using RasPlan
|
204
|
+
from ras_commander import RasPlan
|
205
|
+
geom_path = RasPlan.get_geom_path(str(geom_number), ras_obj)
|
206
|
+
|
207
|
+
if geom_path is not None:
|
208
|
+
# Create the HDF path by adding .hdf to the geometry path
|
209
|
+
hdf_path = Path(str(geom_path) + ".hdf")
|
210
|
+
if hdf_path.exists():
|
211
|
+
logger.info(f"Found geometry HDF file for plan {number_int}: {hdf_path}")
|
212
|
+
else:
|
213
|
+
# Try to find it in the geom_df if direct path doesn't exist
|
214
|
+
geom_info = ras_obj.geom_df[ras_obj.geom_df['full_path'] == str(geom_path)]
|
215
|
+
if not geom_info.empty and 'hdf_path' in geom_info.columns:
|
216
|
+
hdf_path_str = geom_info.iloc[0]['hdf_path']
|
217
|
+
if pd.notna(hdf_path_str):
|
218
|
+
hdf_path = Path(str(hdf_path_str))
|
219
|
+
logger.info(f"Found geometry HDF file from geom_df for plan {number_int}: {hdf_path}")
|
220
|
+
except (TypeError, ValueError) as e:
|
221
|
+
logger.warning(f"Error processing geometry number {geom_number}: {str(e)}")
|
222
|
+
else:
|
223
|
+
logger.warning(f"No valid geometry number found for plan {number_int}")
|
224
|
+
except Exception as e:
|
225
|
+
logger.warning(f"Error retrieving geometry HDF path: {str(e)}")
|
226
|
+
else:
|
227
|
+
raise ValueError(f"Invalid file type: {file_type}")
|
228
|
+
|
229
|
+
# Final verification that the path exists
|
230
|
+
if hdf_path is None or not hdf_path.exists():
|
231
|
+
error_msg = f"HDF file not found: {hdf_input}"
|
232
|
+
logger.error(error_msg)
|
233
|
+
raise FileNotFoundError(error_msg)
|
234
|
+
|
235
|
+
logger.info(f"Final validated HDF file path: {hdf_path}")
|
236
|
+
|
237
|
+
# Now try to validate the HDF file structure (but don't fail if validation fails)
|
238
|
+
try:
|
239
|
+
with h5py.File(hdf_path, 'r') as test_file:
|
240
|
+
# Just open to verify it's a valid HDF5 file
|
241
|
+
logger.debug(f"Successfully opened HDF file for validation: {hdf_path}")
|
242
|
+
except Exception as e:
|
243
|
+
logger.warning(f"Warning: Could not validate HDF file: {str(e)}")
|
244
|
+
# Continue anyway, let the function handle detailed validation
|
245
|
+
|
246
|
+
# Pass all original arguments and keywords, replacing hdf_input with standardized hdf_path
|
247
|
+
# If the original input was positional, replace the first argument
|
248
|
+
if args and 'hdf_path' not in kwargs:
|
249
|
+
new_args = (hdf_path,) + args[1:]
|
250
|
+
else:
|
251
|
+
new_args = args
|
252
|
+
kwargs['hdf_path'] = hdf_path
|
253
|
+
|
254
|
+
return func(*new_args, **kwargs)
|
255
|
+
|
256
|
+
return wrapper
|
257
257
|
return decorator
|