well-log-toolkit 0.1.123__py3-none-any.whl → 0.1.124__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.
@@ -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
- sampled: bool = False
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,26 +1554,134 @@ 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
- >>> well = manager.well_12_3_2_B
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
- for file in filepath:
1545
- self.load_las(file, sampled=sampled)
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 and source 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
+ source_name_from_file = las.source_name
1654
+
1655
+ # Load the file
1656
+ self.load_las(file_path, path=None, sampled=sampled, combine=None, source_name=None)
1657
+
1658
+ # Track what was loaded
1659
+ loaded_sources.append((well_name, source_name_from_file))
1660
+
1661
+ # Print debug output
1662
+ print("Loaded sources:")
1663
+ for well_name, src_name in loaded_sources:
1664
+ print(f" - Well {well_name}: {src_name}")
1665
+
1546
1666
  return self
1547
1667
 
1548
1668
  # Handle single file
1549
- las = LasFile(filepath)
1669
+ # Prepend path if provided
1670
+ if path is not None:
1671
+ file_path = Path(path) / filepath
1672
+ else:
1673
+ file_path = filepath
1674
+
1675
+ las = LasFile(file_path)
1550
1676
  well_name = las.well_name
1551
1677
 
1552
1678
  if well_name is None:
1553
1679
  raise LasFileError(
1554
- f"LAS file {filepath} has no WELL name in header. "
1680
+ f"LAS file {file_path} has no WELL name in header. "
1555
1681
  "Cannot determine which well to load into."
1556
1682
  )
1557
1683
 
1684
+ source_name_from_file = las.source_name
1558
1685
  sanitized_name = sanitize_well_name(well_name)
1559
1686
  # Use well_ prefix for dictionary key (attribute access)
1560
1687
  well_key = f"well_{sanitized_name}"
@@ -1571,6 +1698,10 @@ class WellDataManager:
1571
1698
  # Load into well
1572
1699
  self._wells[well_key].load_las(las, sampled=sampled)
1573
1700
 
1701
+ # Print debug output
1702
+ print("Loaded sources:")
1703
+ print(f" - Well {well_name}: {source_name_from_file}")
1704
+
1574
1705
  return self # Enable chaining
1575
1706
 
1576
1707
  def load_tops(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: well-log-toolkit
3
- Version: 0.1.123
3
+ Version: 0.1.124
4
4
  Summary: Fast LAS file processing with lazy loading and filtering for well log analysis
5
5
  Author-email: Kristian dF Kollsgård <kkollsg@gmail.com>
6
6
  License: MIT
@@ -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=Mc_zgC9pgbYq82msiAc0KMVmPFbCX90SZK5JfwGY4H4,102422
4
+ well_log_toolkit/manager.py,sha256=oz67-IZvMEP7T_JEY7JMzeXWAvG1FmFSk8NKBif7yFI,108220
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.123.dist-info/METADATA,sha256=gI89Dn-k1W6yy9ODs-5Roj1wiZ2GpMlc7deaBcpq3KA,59810
13
- well_log_toolkit-0.1.123.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
- well_log_toolkit-0.1.123.dist-info/top_level.txt,sha256=BMOo7OKLcZEnjo0wOLMclwzwTbYKYh31I8RGDOGSBdE,17
15
- well_log_toolkit-0.1.123.dist-info/RECORD,,
12
+ well_log_toolkit-0.1.124.dist-info/METADATA,sha256=CfWF9CRjoyY3ZmsZ1CkKOSsuVUMg3yY3_XZE3B_lwf4,59810
13
+ well_log_toolkit-0.1.124.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
+ well_log_toolkit-0.1.124.dist-info/top_level.txt,sha256=BMOo7OKLcZEnjo0wOLMclwzwTbYKYh31I8RGDOGSBdE,17
15
+ well_log_toolkit-0.1.124.dist-info/RECORD,,