well-log-toolkit 0.1.123__py3-none-any.whl → 0.1.125__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/manager.py +157 -8
- {well_log_toolkit-0.1.123.dist-info → well_log_toolkit-0.1.125.dist-info}/METADATA +1 -1
- {well_log_toolkit-0.1.123.dist-info → well_log_toolkit-0.1.125.dist-info}/RECORD +5 -5
- {well_log_toolkit-0.1.123.dist-info → well_log_toolkit-0.1.125.dist-info}/WHEEL +0 -0
- {well_log_toolkit-0.1.123.dist-info → well_log_toolkit-0.1.125.dist-info}/top_level.txt +0 -0
well_log_toolkit/manager.py
CHANGED
|
@@ -1507,7 +1507,10 @@ class WellDataManager:
|
|
|
1507
1507
|
def load_las(
|
|
1508
1508
|
self,
|
|
1509
1509
|
filepath: Union[str, Path, list[Union[str, Path]]],
|
|
1510
|
-
|
|
1510
|
+
path: Optional[Union[str, Path]] = None,
|
|
1511
|
+
sampled: bool = False,
|
|
1512
|
+
combine: Optional[str] = None,
|
|
1513
|
+
source_name: Optional[str] = None
|
|
1511
1514
|
) -> 'WellDataManager':
|
|
1512
1515
|
"""
|
|
1513
1516
|
Load LAS file(s), auto-create well if needed.
|
|
@@ -1515,10 +1518,26 @@ class WellDataManager:
|
|
|
1515
1518
|
Parameters
|
|
1516
1519
|
----------
|
|
1517
1520
|
filepath : Union[str, Path, list[Union[str, Path]]]
|
|
1518
|
-
Path to LAS file or list of paths to LAS files
|
|
1521
|
+
Path to LAS file or list of paths to LAS files.
|
|
1522
|
+
When providing a list, filenames can be relative to the path parameter.
|
|
1523
|
+
path : Union[str, Path], optional
|
|
1524
|
+
Directory path to prepend to all filenames. Useful when loading multiple
|
|
1525
|
+
files from the same directory. If None, filenames are used as-is.
|
|
1519
1526
|
sampled : bool, default False
|
|
1520
1527
|
If True, mark all properties from the LAS file(s) as 'sampled' type.
|
|
1521
1528
|
Use this for core plug data or other point measurements.
|
|
1529
|
+
combine : str, optional
|
|
1530
|
+
When loading multiple files, combine files from the same well into a single source:
|
|
1531
|
+
- None (default): Load files as separate sources, no combining
|
|
1532
|
+
- 'match': Combine using match method (safest, errors on mismatch)
|
|
1533
|
+
- 'resample': Combine using resample method (interpolates to first file)
|
|
1534
|
+
- 'concat': Combine using concat method (merges all unique depths)
|
|
1535
|
+
Files are automatically grouped by well name. If 4 files from 2 wells are loaded,
|
|
1536
|
+
2 combined sources are created (one per well).
|
|
1537
|
+
source_name : str, optional
|
|
1538
|
+
Name for combined source when combine is specified. If not specified,
|
|
1539
|
+
uses 'combined_match', 'combined_resample', or 'combined_concat'.
|
|
1540
|
+
When files span multiple wells, the well name is prepended automatically.
|
|
1522
1541
|
|
|
1523
1542
|
Returns
|
|
1524
1543
|
-------
|
|
@@ -1535,23 +1554,140 @@ class WellDataManager:
|
|
|
1535
1554
|
>>> manager = WellDataManager()
|
|
1536
1555
|
>>> manager.load_las("well1.las")
|
|
1537
1556
|
>>> manager.load_las(["well2.las", "well3.las"])
|
|
1557
|
+
|
|
1538
1558
|
>>> # Load core plug data
|
|
1539
1559
|
>>> manager.load_las("core_data.las", sampled=True)
|
|
1540
|
-
|
|
1560
|
+
|
|
1561
|
+
>>> # Load multiple files from same directory
|
|
1562
|
+
>>> manager.load_las(
|
|
1563
|
+
... ["file1.las", "file2.las", "file3.las"],
|
|
1564
|
+
... path="data/well_logs"
|
|
1565
|
+
... )
|
|
1566
|
+
|
|
1567
|
+
>>> # Load and combine files (automatically groups by well)
|
|
1568
|
+
>>> manager.load_las(
|
|
1569
|
+
... ["36_7-5_B_CorePerm.las", "36_7-5_B_CorePor.las",
|
|
1570
|
+
... "36_7-4_CorePerm.las", "36_7-4_CorePor.las"],
|
|
1571
|
+
... path="data/",
|
|
1572
|
+
... combine="match",
|
|
1573
|
+
... source_name="CorePlugs"
|
|
1574
|
+
... )
|
|
1575
|
+
Loaded sources:
|
|
1576
|
+
- Well 36/7-5 B: CorePlugs (2 files combined)
|
|
1577
|
+
- Well 36/7-4: CorePlugs (2 files combined)
|
|
1541
1578
|
"""
|
|
1542
1579
|
# Handle list of files
|
|
1543
1580
|
if isinstance(filepath, list):
|
|
1544
|
-
|
|
1545
|
-
|
|
1581
|
+
# Prepend path to all filenames if provided
|
|
1582
|
+
if path is not None:
|
|
1583
|
+
base_path = Path(path)
|
|
1584
|
+
file_paths = [base_path / file for file in filepath]
|
|
1585
|
+
else:
|
|
1586
|
+
file_paths = filepath
|
|
1587
|
+
|
|
1588
|
+
# If combine is specified, group files by well and combine each group
|
|
1589
|
+
if combine is not None:
|
|
1590
|
+
# Group files by well name
|
|
1591
|
+
from collections import defaultdict
|
|
1592
|
+
well_groups = defaultdict(list)
|
|
1593
|
+
|
|
1594
|
+
for file_path in file_paths:
|
|
1595
|
+
las = LasFile(file_path)
|
|
1596
|
+
if las.well_name is None:
|
|
1597
|
+
raise LasFileError(
|
|
1598
|
+
f"LAS file {file_path} has no WELL name in header. "
|
|
1599
|
+
"Cannot determine which well to load into."
|
|
1600
|
+
)
|
|
1601
|
+
well_groups[las.well_name].append(file_path)
|
|
1602
|
+
|
|
1603
|
+
# Track loaded sources for debug output
|
|
1604
|
+
loaded_sources = []
|
|
1605
|
+
|
|
1606
|
+
# Process each well group
|
|
1607
|
+
for well_name, files_for_well in well_groups.items():
|
|
1608
|
+
sanitized_name = sanitize_well_name(well_name)
|
|
1609
|
+
well_key = f"well_{sanitized_name}"
|
|
1610
|
+
|
|
1611
|
+
# Ensure well exists
|
|
1612
|
+
if well_key not in self._wells:
|
|
1613
|
+
self._wells[well_key] = Well(
|
|
1614
|
+
name=well_name,
|
|
1615
|
+
sanitized_name=sanitized_name,
|
|
1616
|
+
parent_manager=self
|
|
1617
|
+
)
|
|
1618
|
+
self._name_mapping[well_name] = well_key
|
|
1619
|
+
|
|
1620
|
+
# Load files into well with combine
|
|
1621
|
+
self._wells[well_key].load_las(
|
|
1622
|
+
files_for_well,
|
|
1623
|
+
path=None, # Path already prepended
|
|
1624
|
+
sampled=sampled,
|
|
1625
|
+
combine=combine,
|
|
1626
|
+
source_name=source_name
|
|
1627
|
+
)
|
|
1628
|
+
|
|
1629
|
+
# Track what was loaded
|
|
1630
|
+
actual_source_name = source_name if source_name else f"combined_{combine}"
|
|
1631
|
+
loaded_sources.append(
|
|
1632
|
+
(well_name, actual_source_name, len(files_for_well))
|
|
1633
|
+
)
|
|
1634
|
+
|
|
1635
|
+
# Print debug output
|
|
1636
|
+
print("Loaded sources:")
|
|
1637
|
+
for well_name, src_name, file_count in loaded_sources:
|
|
1638
|
+
print(f" - Well {well_name}: {src_name} ({file_count} file{'s' if file_count > 1 else ''} combined)")
|
|
1639
|
+
|
|
1640
|
+
return self
|
|
1641
|
+
|
|
1642
|
+
# No combine - load each file separately
|
|
1643
|
+
loaded_sources = []
|
|
1644
|
+
for file_path in file_paths:
|
|
1645
|
+
# Read well name before loading
|
|
1646
|
+
las = LasFile(file_path)
|
|
1647
|
+
if las.well_name is None:
|
|
1648
|
+
raise LasFileError(
|
|
1649
|
+
f"LAS file {file_path} has no WELL name in header. "
|
|
1650
|
+
"Cannot determine which well to load into."
|
|
1651
|
+
)
|
|
1652
|
+
well_name = las.well_name
|
|
1653
|
+
sanitized_name = sanitize_well_name(well_name)
|
|
1654
|
+
well_key = f"well_{sanitized_name}"
|
|
1655
|
+
|
|
1656
|
+
# Track existing sources before loading
|
|
1657
|
+
existing_sources = set()
|
|
1658
|
+
if well_key in self._wells:
|
|
1659
|
+
existing_sources = set(self._wells[well_key].sources)
|
|
1660
|
+
|
|
1661
|
+
# Load the file
|
|
1662
|
+
self.load_las(file_path, path=None, sampled=sampled, combine=None, source_name=None)
|
|
1663
|
+
|
|
1664
|
+
# Find new sources that were added
|
|
1665
|
+
if well_key in self._wells:
|
|
1666
|
+
new_sources = set(self._wells[well_key].sources) - existing_sources
|
|
1667
|
+
for src_name in new_sources:
|
|
1668
|
+
loaded_sources.append((well_name, src_name))
|
|
1669
|
+
|
|
1670
|
+
# Print debug output
|
|
1671
|
+
if loaded_sources:
|
|
1672
|
+
print("Loaded sources:")
|
|
1673
|
+
for well_name, src_name in loaded_sources:
|
|
1674
|
+
print(f" - Well {well_name}: {src_name}")
|
|
1675
|
+
|
|
1546
1676
|
return self
|
|
1547
1677
|
|
|
1548
1678
|
# Handle single file
|
|
1549
|
-
|
|
1679
|
+
# Prepend path if provided
|
|
1680
|
+
if path is not None:
|
|
1681
|
+
file_path = Path(path) / filepath
|
|
1682
|
+
else:
|
|
1683
|
+
file_path = filepath
|
|
1684
|
+
|
|
1685
|
+
las = LasFile(file_path)
|
|
1550
1686
|
well_name = las.well_name
|
|
1551
1687
|
|
|
1552
1688
|
if well_name is None:
|
|
1553
1689
|
raise LasFileError(
|
|
1554
|
-
f"LAS file {
|
|
1690
|
+
f"LAS file {file_path} has no WELL name in header. "
|
|
1555
1691
|
"Cannot determine which well to load into."
|
|
1556
1692
|
)
|
|
1557
1693
|
|
|
@@ -1559,7 +1695,11 @@ class WellDataManager:
|
|
|
1559
1695
|
# Use well_ prefix for dictionary key (attribute access)
|
|
1560
1696
|
well_key = f"well_{sanitized_name}"
|
|
1561
1697
|
|
|
1562
|
-
|
|
1698
|
+
# Track existing sources before loading
|
|
1699
|
+
existing_sources = set()
|
|
1700
|
+
if well_key in self._wells:
|
|
1701
|
+
existing_sources = set(self._wells[well_key].sources)
|
|
1702
|
+
else:
|
|
1563
1703
|
# Create new well
|
|
1564
1704
|
self._wells[well_key] = Well(
|
|
1565
1705
|
name=well_name,
|
|
@@ -1571,6 +1711,15 @@ class WellDataManager:
|
|
|
1571
1711
|
# Load into well
|
|
1572
1712
|
self._wells[well_key].load_las(las, sampled=sampled)
|
|
1573
1713
|
|
|
1714
|
+
# Find new sources that were added
|
|
1715
|
+
new_sources = set(self._wells[well_key].sources) - existing_sources
|
|
1716
|
+
|
|
1717
|
+
# Print debug output
|
|
1718
|
+
if new_sources:
|
|
1719
|
+
print("Loaded sources:")
|
|
1720
|
+
for src_name in new_sources:
|
|
1721
|
+
print(f" - Well {well_name}: {src_name}")
|
|
1722
|
+
|
|
1574
1723
|
return self # Enable chaining
|
|
1575
1724
|
|
|
1576
1725
|
def load_tops(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
well_log_toolkit/__init__.py,sha256=ilJAIIhh68pYfD9I3V53juTEJpoMN8oHpcpEFNpuXAQ,3793
|
|
2
2
|
well_log_toolkit/exceptions.py,sha256=X_fzC7d4yaBFO9Vx74dEIB6xmI9Agi6_bTU3MPxn6ko,985
|
|
3
3
|
well_log_toolkit/las_file.py,sha256=Tj0mRfX1aX2s6uug7BBlY1m_mu3G50EGxHGzD0eEedE,53876
|
|
4
|
-
well_log_toolkit/manager.py,sha256=
|
|
4
|
+
well_log_toolkit/manager.py,sha256=7v2zzdkUc_WFCdjZwn4DFHW5pkowtC85LS3o4lvZ9bI,109002
|
|
5
5
|
well_log_toolkit/operations.py,sha256=z8j8fGBOwoJGUQFy-Vawjq9nm3OD_dUt0oaNh8yuG7o,18515
|
|
6
6
|
well_log_toolkit/property.py,sha256=WOzoNQcmHCQ8moIKsnSyLgVC8s4LBu2x5IBXtFzmMe8,76236
|
|
7
7
|
well_log_toolkit/regression.py,sha256=7D3oI-1XVlFb-mOoHTxTTtUHERFyvQSBAzJzAGVoZnk,25192
|
|
@@ -9,7 +9,7 @@ well_log_toolkit/statistics.py,sha256=_huPMbv2H3o9ezunjEM94mJknX5wPK8V4nDv2lIZZR
|
|
|
9
9
|
well_log_toolkit/utils.py,sha256=O2KPq4htIoUlL74V2zKftdqqTjRfezU9M-568zPLme0,6866
|
|
10
10
|
well_log_toolkit/visualization.py,sha256=xb870FG5FghU2gEkqdn1b2NbWNu07oDmFDN1Cx1HIi0,157280
|
|
11
11
|
well_log_toolkit/well.py,sha256=kIN3Zr0sI3Zt3DeHbxDXADbQfWnVxXCQrHZ4UEMyeqI,103343
|
|
12
|
-
well_log_toolkit-0.1.
|
|
13
|
-
well_log_toolkit-0.1.
|
|
14
|
-
well_log_toolkit-0.1.
|
|
15
|
-
well_log_toolkit-0.1.
|
|
12
|
+
well_log_toolkit-0.1.125.dist-info/METADATA,sha256=I3JrySR3JycP7qOsp4gCCOKme-hcasI-VkhbaArGsRg,59810
|
|
13
|
+
well_log_toolkit-0.1.125.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
14
|
+
well_log_toolkit-0.1.125.dist-info/top_level.txt,sha256=BMOo7OKLcZEnjo0wOLMclwzwTbYKYh31I8RGDOGSBdE,17
|
|
15
|
+
well_log_toolkit-0.1.125.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|