well-log-toolkit 0.1.120__py3-none-any.whl → 0.1.122__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.
- well_log_toolkit/las_file.py +35 -2
- well_log_toolkit/well.py +81 -17
- {well_log_toolkit-0.1.120.dist-info → well_log_toolkit-0.1.122.dist-info}/METADATA +1 -1
- {well_log_toolkit-0.1.120.dist-info → well_log_toolkit-0.1.122.dist-info}/RECORD +6 -6
- {well_log_toolkit-0.1.120.dist-info → well_log_toolkit-0.1.122.dist-info}/WHEEL +0 -0
- {well_log_toolkit-0.1.120.dist-info → well_log_toolkit-0.1.122.dist-info}/top_level.txt +0 -0
well_log_toolkit/las_file.py
CHANGED
|
@@ -104,7 +104,10 @@ class LasFile:
|
|
|
104
104
|
source_name: str = 'external_df',
|
|
105
105
|
unit_mappings: Optional[dict[str, str]] = None,
|
|
106
106
|
type_mappings: Optional[dict[str, str]] = None,
|
|
107
|
-
label_mappings: Optional[dict[str, dict[int, str]]] = None
|
|
107
|
+
label_mappings: Optional[dict[str, dict[int, str]]] = None,
|
|
108
|
+
color_mappings: Optional[dict[str, dict[int, str]]] = None,
|
|
109
|
+
style_mappings: Optional[dict[str, dict[int, str]]] = None,
|
|
110
|
+
thickness_mappings: Optional[dict[str, dict[int, float]]] = None
|
|
108
111
|
) -> 'LasFile':
|
|
109
112
|
"""
|
|
110
113
|
Create a LasFile object from a DataFrame.
|
|
@@ -123,6 +126,12 @@ class LasFile:
|
|
|
123
126
|
Mapping of column names to 'continuous' or 'discrete'
|
|
124
127
|
label_mappings : dict[str, dict[int, str]], optional
|
|
125
128
|
Label mappings for discrete properties
|
|
129
|
+
color_mappings : dict[str, dict[int, str]], optional
|
|
130
|
+
Color mappings for discrete property values
|
|
131
|
+
style_mappings : dict[str, dict[int, str]], optional
|
|
132
|
+
Style mappings for discrete property values
|
|
133
|
+
thickness_mappings : dict[str, dict[int, float]], optional
|
|
134
|
+
Thickness mappings for discrete property values
|
|
126
135
|
|
|
127
136
|
Returns
|
|
128
137
|
-------
|
|
@@ -148,6 +157,9 @@ class LasFile:
|
|
|
148
157
|
unit_mappings = unit_mappings or {}
|
|
149
158
|
type_mappings = type_mappings or {}
|
|
150
159
|
label_mappings = label_mappings or {}
|
|
160
|
+
color_mappings = color_mappings or {}
|
|
161
|
+
style_mappings = style_mappings or {}
|
|
162
|
+
thickness_mappings = thickness_mappings or {}
|
|
151
163
|
|
|
152
164
|
# Create instance without parsing file
|
|
153
165
|
instance = cls(source_name, _from_dataframe=True)
|
|
@@ -176,7 +188,7 @@ class LasFile:
|
|
|
176
188
|
'multiplier': None
|
|
177
189
|
}
|
|
178
190
|
|
|
179
|
-
# Set parameter info (discrete labels)
|
|
191
|
+
# Set parameter info (discrete labels and metadata)
|
|
180
192
|
if label_mappings:
|
|
181
193
|
discrete_props = ','.join(sorted(label_mappings.keys()))
|
|
182
194
|
instance.parameter_info['DISCRETE_PROPS'] = discrete_props
|
|
@@ -186,6 +198,27 @@ class LasFile:
|
|
|
186
198
|
param_name = f"{prop_name}_{value}"
|
|
187
199
|
instance.parameter_info[param_name] = label
|
|
188
200
|
|
|
201
|
+
# Add color mappings to parameter section
|
|
202
|
+
if color_mappings:
|
|
203
|
+
for prop_name, colors in color_mappings.items():
|
|
204
|
+
for value, color in colors.items():
|
|
205
|
+
param_name = f"{prop_name}_{value}_COLOR"
|
|
206
|
+
instance.parameter_info[param_name] = color
|
|
207
|
+
|
|
208
|
+
# Add style mappings to parameter section
|
|
209
|
+
if style_mappings:
|
|
210
|
+
for prop_name, styles in style_mappings.items():
|
|
211
|
+
for value, style in styles.items():
|
|
212
|
+
param_name = f"{prop_name}_{value}_STYLE"
|
|
213
|
+
instance.parameter_info[param_name] = style
|
|
214
|
+
|
|
215
|
+
# Add thickness mappings to parameter section
|
|
216
|
+
if thickness_mappings:
|
|
217
|
+
for prop_name, thicknesses in thickness_mappings.items():
|
|
218
|
+
for value, thickness in thicknesses.items():
|
|
219
|
+
param_name = f"{prop_name}_{value}_THICKNESS"
|
|
220
|
+
instance.parameter_info[param_name] = str(thickness)
|
|
221
|
+
|
|
189
222
|
# Set data directly
|
|
190
223
|
instance._data = df.copy()
|
|
191
224
|
|
well_log_toolkit/well.py
CHANGED
|
@@ -335,9 +335,17 @@ class Well:
|
|
|
335
335
|
# Mark source as modified
|
|
336
336
|
self._sources[source_name]['modified'] = True
|
|
337
337
|
|
|
338
|
-
def load_las(
|
|
338
|
+
def load_las(
|
|
339
|
+
self,
|
|
340
|
+
las: Union[LasFile, str, Path, list[Union[str, Path]]],
|
|
341
|
+
sampled: bool = False,
|
|
342
|
+
resample_method: Optional[str] = None,
|
|
343
|
+
merge: bool = False,
|
|
344
|
+
combine: Optional[str] = None,
|
|
345
|
+
source_name: Optional[str] = None
|
|
346
|
+
) -> 'Well':
|
|
339
347
|
"""
|
|
340
|
-
Load LAS file into this well, organized by source.
|
|
348
|
+
Load LAS file(s) into this well, organized by source.
|
|
341
349
|
|
|
342
350
|
Properties are grouped by source (LAS file). The source name is derived
|
|
343
351
|
from the filename stem (without extension), sanitized for Python attribute
|
|
@@ -346,8 +354,8 @@ class Well:
|
|
|
346
354
|
|
|
347
355
|
Parameters
|
|
348
356
|
----------
|
|
349
|
-
las : Union[LasFile, str, Path]
|
|
350
|
-
Either a LasFile instance
|
|
357
|
+
las : Union[LasFile, str, Path, list[Union[str, Path]]]
|
|
358
|
+
Either a LasFile instance, path to LAS file, or list of LAS file paths
|
|
351
359
|
sampled : bool, default False
|
|
352
360
|
If True, mark all properties from this source as 'sampled' type.
|
|
353
361
|
Use this for core plug data or other point measurements where
|
|
@@ -365,6 +373,15 @@ class Well:
|
|
|
365
373
|
properties into the existing source instead of overwriting it.
|
|
366
374
|
When merging with incompatible depth grids, resample_method must be specified.
|
|
367
375
|
If False (default), existing source is overwritten with warning.
|
|
376
|
+
combine : str, optional
|
|
377
|
+
When loading multiple files (list), combine them into a single source:
|
|
378
|
+
- None (default): Load files as separate sources, no combining
|
|
379
|
+
- 'match': Combine using match method (safest, errors on mismatch)
|
|
380
|
+
- 'resample': Combine using resample method (interpolates to first file)
|
|
381
|
+
- 'concat': Combine using concat method (merges all unique depths)
|
|
382
|
+
source_name : str, optional
|
|
383
|
+
Name for combined source when combine is specified. If not specified,
|
|
384
|
+
uses 'combined_match', 'combined_resample', or 'combined_concat'
|
|
368
385
|
|
|
369
386
|
Returns
|
|
370
387
|
-------
|
|
@@ -381,23 +398,70 @@ class Well:
|
|
|
381
398
|
|
|
382
399
|
Examples
|
|
383
400
|
--------
|
|
384
|
-
>>>
|
|
401
|
+
>>> # Load single file
|
|
385
402
|
>>> well.load_las("36_7-5_B_CorePor.las") # Source name: "CorePor"
|
|
386
|
-
|
|
387
|
-
>>>
|
|
403
|
+
|
|
404
|
+
>>> # Load multiple files as separate sources
|
|
405
|
+
>>> well.load_las(["file1.las", "file2.las", "file3.las"])
|
|
406
|
+
>>> print(well.sources) # ['file1', 'file2', 'file3']
|
|
407
|
+
|
|
408
|
+
>>> # Load and combine multiple files
|
|
409
|
+
>>> well.load_las(
|
|
410
|
+
... ["file1.las", "file2.las", "file3.las"],
|
|
411
|
+
... combine="match",
|
|
412
|
+
... source_name="CombinedLogs"
|
|
413
|
+
... )
|
|
414
|
+
>>> print(well.sources) # ['CombinedLogs']
|
|
415
|
+
|
|
388
416
|
>>> # Load core plug data as sampled
|
|
389
417
|
>>> well.load_las("36_7-5_B_Core.las", sampled=True)
|
|
390
|
-
|
|
391
|
-
>>>
|
|
392
|
-
>>>
|
|
418
|
+
|
|
419
|
+
>>> # Load with resample combining
|
|
420
|
+
>>> well.load_las(
|
|
421
|
+
... ["log1.las", "log2.las"],
|
|
422
|
+
... combine="resample",
|
|
423
|
+
... source_name="CombinedLogs"
|
|
424
|
+
... )
|
|
425
|
+
|
|
426
|
+
>>> # Merge into existing source (legacy behavior)
|
|
393
427
|
>>> well.load_las("CorePor.las") # Load initial properties
|
|
394
|
-
>>> well.load_las("CorePor_Extra.las", merge=True) # Merge new properties
|
|
395
|
-
>>> # Access by source
|
|
396
|
-
>>> well.CorePor.PHIE
|
|
397
|
-
>>> well.Log.GR
|
|
398
|
-
>>> # Access directly if unique
|
|
399
|
-
>>> well.PHIE # Error if both CorePor and Log have PHIE
|
|
428
|
+
>>> well.load_las("CorePor_Extra.las", merge=True) # Merge new properties
|
|
400
429
|
"""
|
|
430
|
+
# Handle list of files
|
|
431
|
+
if isinstance(las, list):
|
|
432
|
+
# Load all files as separate sources
|
|
433
|
+
loaded_sources = []
|
|
434
|
+
for las_file in las:
|
|
435
|
+
# Recursively call load_las for each file (without merge or combine)
|
|
436
|
+
self.load_las(las_file, sampled=sampled, resample_method=resample_method, merge=False, combine=None)
|
|
437
|
+
# Get the source name that was just created
|
|
438
|
+
loaded_sources.append(self.sources[-1])
|
|
439
|
+
|
|
440
|
+
# Combine if requested
|
|
441
|
+
if combine in {'match', 'resample', 'concat'}:
|
|
442
|
+
# Determine combined source name
|
|
443
|
+
combined_source_name = source_name or f'combined_{combine}'
|
|
444
|
+
|
|
445
|
+
# Merge all loaded sources
|
|
446
|
+
self.merge(
|
|
447
|
+
method=combine,
|
|
448
|
+
sources=loaded_sources,
|
|
449
|
+
source_name=combined_source_name
|
|
450
|
+
)
|
|
451
|
+
|
|
452
|
+
# Remove original sources
|
|
453
|
+
self.remove_source(loaded_sources)
|
|
454
|
+
|
|
455
|
+
return self
|
|
456
|
+
|
|
457
|
+
# Single file logic below
|
|
458
|
+
# Validate combine parameter for single file
|
|
459
|
+
if combine is not None:
|
|
460
|
+
raise ValueError(
|
|
461
|
+
f"combine='{combine}' is only valid when loading multiple files (list). "
|
|
462
|
+
f"For single file loading, use merge=True to merge into existing source."
|
|
463
|
+
)
|
|
464
|
+
|
|
401
465
|
# Parse if path provided
|
|
402
466
|
filepath = None
|
|
403
467
|
if isinstance(las, (str, Path)):
|
|
@@ -2247,7 +2311,7 @@ class Well:
|
|
|
2247
2311
|
|
|
2248
2312
|
df = pd.DataFrame(data)
|
|
2249
2313
|
|
|
2250
|
-
# Create LasFile from DataFrame
|
|
2314
|
+
# Create LasFile from DataFrame with all metadata
|
|
2251
2315
|
las = LasFile.from_dataframe(
|
|
2252
2316
|
df=df,
|
|
2253
2317
|
well_name=self.name,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
well_log_toolkit/__init__.py,sha256=ilJAIIhh68pYfD9I3V53juTEJpoMN8oHpcpEFNpuXAQ,3793
|
|
2
2
|
well_log_toolkit/exceptions.py,sha256=X_fzC7d4yaBFO9Vx74dEIB6xmI9Agi6_bTU3MPxn6ko,985
|
|
3
|
-
well_log_toolkit/las_file.py,sha256=
|
|
3
|
+
well_log_toolkit/las_file.py,sha256=Tj0mRfX1aX2s6uug7BBlY1m_mu3G50EGxHGzD0eEedE,53876
|
|
4
4
|
well_log_toolkit/manager.py,sha256=Mc_zgC9pgbYq82msiAc0KMVmPFbCX90SZK5JfwGY4H4,102422
|
|
5
5
|
well_log_toolkit/operations.py,sha256=z8j8fGBOwoJGUQFy-Vawjq9nm3OD_dUt0oaNh8yuG7o,18515
|
|
6
6
|
well_log_toolkit/property.py,sha256=WOzoNQcmHCQ8moIKsnSyLgVC8s4LBu2x5IBXtFzmMe8,76236
|
|
@@ -8,8 +8,8 @@ well_log_toolkit/regression.py,sha256=7D3oI-1XVlFb-mOoHTxTTtUHERFyvQSBAzJzAGVoZn
|
|
|
8
8
|
well_log_toolkit/statistics.py,sha256=_huPMbv2H3o9ezunjEM94mJknX5wPK8V4nDv2lIZZRw,16814
|
|
9
9
|
well_log_toolkit/utils.py,sha256=O2KPq4htIoUlL74V2zKftdqqTjRfezU9M-568zPLme0,6866
|
|
10
10
|
well_log_toolkit/visualization.py,sha256=xb870FG5FghU2gEkqdn1b2NbWNu07oDmFDN1Cx1HIi0,157280
|
|
11
|
-
well_log_toolkit/well.py,sha256
|
|
12
|
-
well_log_toolkit-0.1.
|
|
13
|
-
well_log_toolkit-0.1.
|
|
14
|
-
well_log_toolkit-0.1.
|
|
15
|
-
well_log_toolkit-0.1.
|
|
11
|
+
well_log_toolkit/well.py,sha256=u2KhhMfXkMPIOKRgH3SB3k-2knotqWdBGY4Lup31Pxc,102017
|
|
12
|
+
well_log_toolkit-0.1.122.dist-info/METADATA,sha256=MxrNyJ2HeEdC6VUmRFSPdVT6te10N5Buy-iJLzwHEFY,59810
|
|
13
|
+
well_log_toolkit-0.1.122.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
14
|
+
well_log_toolkit-0.1.122.dist-info/top_level.txt,sha256=BMOo7OKLcZEnjo0wOLMclwzwTbYKYh31I8RGDOGSBdE,17
|
|
15
|
+
well_log_toolkit-0.1.122.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|