I/O: LasFile

class logsuite.io.las_file.LasFile(filepath, _from_dataframe=False)[source]

Bases: object

Fast LAS file reader with lazy data loading.

Workflow: 1. Instantiate and parse headers (fast) 2. Inspect metadata (well name, curves, units) 3. Update curve metadata if needed 4. Load data when ready

When loading LAS files created by this toolkit, discrete properties and their label mappings are automatically detected and loaded.

Parameters:
  • filepath (Union[str, Path]) – Path to LAS file

  • _from_dataframe (bool)

filepath

Path to LAS file

Type:

Path

version_info

Version section data (VERS, WRAP)

Type:

dict

well_info

Well section data (WELL, STRT, STOP, NULL, etc.)

Type:

dict

parameter_info

Parameter section data (includes discrete property markers and labels)

Type:

dict

curves

Curve metadata: {name: {unit, description, type, alias, multiplier}}

Type:

dict

discrete_properties

List of properties marked as discrete in ~Parameter section. (Read-only property.)

Type:

list[str]

See also

get_discrete_labels

Extract label mappings for a discrete property.

Examples

>>> las = LasFile("well.las")
>>> print(las.well_name)
'12/3-2 B'
>>> print(las.curves.keys())
dict_keys(['DEPT', 'PHIE_2025', 'PERM_Lam_2025', ...])
>>> las.update_curve('PHIE_2025', type='continuous', alias='PHIE')
>>> df = las.data()  # Lazy load
>>> # Check for discrete properties
>>> print(las.discrete_properties)
['Zone', 'NTG_Flag']
>>> labels = las.get_discrete_labels('Zone')
>>> print(labels)
{0: 'NonReservoir', 1: 'Reservoir'}
SUPPORTED_VERSIONS = {'2', '2.0', '3', '3.0'}
classmethod open(filepath)[source]

Open a LAS file, auto-detecting version (2.0 or 3.0).

This is a convenience alias for LasFile(filepath).

Parameters:

filepath (Union[str, Path]) – Path to LAS file

Returns:

Parsed LAS file with headers loaded

Return type:

LasFile

Examples

>>> las = LasFile.open("well.las")
>>> print(las.well_name)
classmethod from_dataframe(df, well_name, source_name='external_df', unit_mappings=None, type_mappings=None, label_mappings=None, color_mappings=None, style_mappings=None, thickness_mappings=None)[source]

Create a LasFile object from a DataFrame.

Parameters:
  • df (pd.DataFrame) – DataFrame with DEPT column and property columns

  • well_name (str) – Well name for this data

  • source_name (str, default 'external_df') – Name for this data source (e.g., ‘external_df’, ‘external_df1’)

  • unit_mappings (dict[str, str], optional) – Mapping of column names to units

  • type_mappings (dict[str, str], optional) – Mapping of column names to ‘continuous’ or ‘discrete’

  • label_mappings (dict[str, dict[int, str]], optional) – Label mappings for discrete properties

  • color_mappings (dict[str, dict[int, str]], optional) – Color mappings for discrete property values

  • style_mappings (dict[str, dict[int, str]], optional) – Style mappings for discrete property values

  • thickness_mappings (dict[str, dict[int, float]], optional) – Thickness mappings for discrete property values

Returns:

LasFile object populated with DataFrame data

Return type:

LasFile

Examples

>>> df = pd.DataFrame({'DEPT': [2800, 2801], 'PHIE': [0.2, 0.22]})
>>> las = LasFile.from_dataframe(
...     df,
...     well_name='12/3-2 B',
...     source_name='external_df',
...     unit_mappings={'DEPT': 'm', 'PHIE': 'v/v'}
... )
property well_name: str | None

Extract well name from well info.

property depth_column: str | None

First curve (typically DEPT/DEPTH).

property null_value: float

NULL value from well section, default -999.25.

property discrete_properties: list[str]

List of properties marked as discrete in ~Parameter section.

Returns:

List of discrete property names from DISCRETE_PROPS parameter

Return type:

list[str]

get_discrete_labels(property_name)[source]

Extract label mappings for a discrete property from ~Parameter section.

Parameters:

property_name (str) – Name of the discrete property

Returns:

Label mapping {0: ‘Label0’, 1: ‘Label1’} or None if no labels found

Return type:

dict[int, str] | None

Examples

>>> las = LasFile("well.las")
>>> labels = las.get_discrete_labels('Zone')
>>> # Returns: {0: 'NonReservoir', 1: 'Reservoir'}

Notes

If a label contains a color specification (e.g., “NonNet|red”), only the label part is returned. Use get_discrete_colors() to retrieve colors.

get_discrete_colors(property_name)[source]

Extract color mappings for a discrete property from ~Parameter section.

Supports two formats: 1. Inline: Zone_0 = “NonNet|red” (color after pipe separator) 2. Separate: Zone_COLOR_0 = “red” (for backward compatibility)

Inline format takes precedence if both exist.

Parameters:

property_name (str) – Name of the discrete property

Returns:

Color mapping {0: ‘red’, 1: ‘green’} or None if no colors found

Return type:

dict[int, str] | None

Examples

>>> las = LasFile("well.las")
>>> colors = las.get_discrete_colors('Zone')
>>> # Returns: {0: 'red', 1: 'green'}
get_discrete_styles(property_name)[source]

Extract line style mappings for a discrete property from ~Parameter section.

Supports two formats: 1. Inline: Zone_0 = “NonNet|red|dashed” (style after second pipe separator) 2. Separate: Zone_STYLE_0 = “dashed” (for backward compatibility)

Inline format takes precedence if both exist.

Parameters:

property_name (str) – Name of the discrete property

Returns:

Style mapping {0: ‘solid’, 1: ‘dashed’} or None if no styles found

Return type:

dict[int, str] | None

Examples

>>> las = LasFile("well.las")
>>> styles = las.get_discrete_styles('Zone')
>>> # Returns: {0: 'solid', 1: 'dashed'}
get_discrete_thicknesses(property_name)[source]

Extract line thickness mappings for a discrete property from ~Parameter section.

Supports two formats: 1. Inline: Zone_0 = “NonNet|red|dashed|1.5” (thickness after third pipe separator) 2. Separate: Zone_THICKNESS_0 = “1.5” (for backward compatibility)

Inline format takes precedence if both exist.

Parameters:

property_name (str) – Name of the discrete property

Returns:

Thickness mapping {0: 1.5, 1: 2.0} or None if no thicknesses found

Return type:

dict[int, float] | None

Examples

>>> las = LasFile("well.las")
>>> thicknesses = las.get_discrete_thicknesses('Zone')
>>> # Returns: {0: 1.5, 1: 2.0}
check_depth_compatibility(other, well=None)[source]

Check if depth grids are compatible between two LAS files.

Checks if all depth values in this LAS file exist in the other LAS file (within tolerance), or if depths are identical.

Parameters:
  • other (LasFile or str) – Either a LasFile instance to compare with, or a string source name. If string, must provide well parameter to look up the source.

  • well (Well, optional) – Well object to look up source from if other is a string. Required when other is a string.

Returns:

Dictionary with compatibility information: - ‘compatible’ (bool): True if grids are compatible - ‘reason’ (str): Explanation of compatibility/incompatibility - ‘existing’ (dict): Info about existing depth grid - ‘new’ (dict): Info about new depth grid - ‘requires_resampling’ (bool): Whether resampling is needed

Return type:

dict

Raises:
  • ValueError – If other is a string but well is not provided

  • KeyError – If source name doesn’t exist in well

Examples

>>> # Compare two LasFile objects
>>> las1 = LasFile("well1.las")
>>> las2 = LasFile("well2.las")
>>> result = las2.check_depth_compatibility(las1)
>>> if result['compatible']:
...     print("Compatible!")
>>> else:
...     print(f"Incompatible: {result['reason']}")
>>> # Compare with a source by name
>>> result = new_las.check_depth_compatibility('Petrophysics', well=well)
data(include=None, exclude=None)[source]

Lazy-load and return data with optional column filtering.

Parameters:
  • include (str or list[str], optional) – Column name(s) to include. If None, includes all columns. Can be a single string or a list of strings.

  • exclude (str or list[str], optional) – Column name(s) to exclude. If both include and exclude are specified, exclude overrides (removes from include list). Can be a single string or a list of strings.

Returns:

Well log data with curves as columns

Return type:

pd.DataFrame

Examples

>>> df = las.data()
>>> df = las.data(include='PHIE')  # Single column
>>> df = las.data(include=['DEPT', 'PHIE', 'SW'])
>>> df = las.data(exclude='QC_Flag')  # Exclude single column
>>> df = las.data(include=['DEPT', 'PHIE', 'SW', 'Zone'], exclude='Zone')
set_data(df)[source]

Set data DataFrame.

Parameters:

df (pd.DataFrame) – Well log data with curves as columns

Return type:

None

update_curve(name, **kwargs)[source]

Update curve metadata.

Parameters:
  • name (str) – Curve name to update

  • **kwargs – unit : str - Unit string description : str - Description type : {‘continuous’, ‘discrete’} - Log type alias : str | None - Output column name multiplier : float | None - Unit conversion factor

Raises:
Return type:

None

Examples

>>> las.update_curve('PHIE_2025', type='continuous', alias='PHIE')
>>> las.update_curve('ResFlag_2025', type='discrete', alias='ResFlag')
>>> las.update_curve('PERM_Lam_2025', multiplier=0.001, alias='PERM_D')
bulk_update_curves(updates)[source]

Update multiple curves at once.

Parameters:

updates (dict[str, dict]) – Mapping of {curve_name: {attr: value, ...}, ...}.

Return type:

None

Examples

>>> las.bulk_update_curves({
...     'Cerisa_facies_LF': {'type': 'discrete', 'alias': 'Facies'},
...     'PHIE_2025': {'alias': 'PHIE'},
...     'PERM_Lam_2025': {'alias': 'PERM', 'multiplier': 0.001}
... })
static export_las(filepath, well_name, df, unit_mappings=None, null_value=-999.25, discrete_labels=None, discrete_colors=None, discrete_styles=None, discrete_thicknesses=None, template_las=None, version='2.0')[source]

Export DataFrame to LAS format file.

Parameters:
  • filepath (Union[str, Path]) – Output LAS file path

  • well_name (str) – Well name for the LAS file

  • df (pd.DataFrame) – DataFrame to export (must contain DEPT column)

  • unit_mappings (dict[str, str], optional) – Mapping of column names to units (e.g., {‘PHIE’: ‘v/v’, ‘DEPT’: ‘m’}) If not provided, uses empty units

  • null_value (float, default -999.25) – Value to use for missing data

  • discrete_labels (dict[str, dict[int, str]], optional) – Label mappings for discrete properties stored in ~Parameter section. Format: {‘PropertyName’: {0: ‘Label0’, 1: ‘Label1’}} Example: {‘Zone’: {0: ‘NonReservoir’, 1: ‘Reservoir’}}

  • discrete_colors (dict[str, dict[int, str]], optional) – Color mappings for discrete properties stored in ~Parameter section. Format: {‘PropertyName’: {0: ‘red’, 1: ‘green’}} Example: {‘Zone’: {0: ‘red’, 1: ‘green’}}

  • template_las (LasFile, optional) – Source LAS file to use as template. Preserves original ~Version info, ~Well parameters (excluding STRT/STOP/STEP/NULL), and ~Parameter entries not related to discrete labels and colors.

  • version (str, default "2.0") – LAS version to export (“2.0” or “3.0”). LAS 3.0 uses tab-separated data and different section names.

  • discrete_styles (dict[str, dict[int, str]] | None)

  • discrete_thicknesses (dict[str, dict[int, float]] | None)

Raises:
Return type:

None

Examples

>>> df = well.data()
>>> LasFile.export_las(
...     'output.las',
...     well_name='12/3-2 B',
...     df=df,
...     unit_mappings={'DEPT': 'm', 'PHIE': 'v/v', 'SW': 'v/v'}
... )
>>> # Export with discrete labels stored in parameter section
>>> LasFile.export_las(
...     'output.las',
...     well_name='12/3-2 B',
...     df=df,
...     unit_mappings={'DEPT': 'm', 'Zone': ''},
...     discrete_labels={'Zone': {0: 'NonReservoir', 1: 'Reservoir'}}
... )
>>> # Export using original LAS as template (preserves metadata)
>>> LasFile.export_las(
...     'updated.las',
...     well_name='12/3-2 B',
...     df=df,
...     unit_mappings={'DEPT': 'm', 'PHIE': 'v/v'},
...     template_las=original_las
... )
export(filepath, null_value=-999.25, version=None)[source]

Export this LasFile instance to a LAS file.

This is an instance method that exports the LasFile’s own data, including all metadata from the ~Version, ~Well, ~Parameter, and ~Curve sections.

Parameters:
  • filepath (Union[str, Path]) – Output LAS file path

  • null_value (float, default -999.25) – Value to use for missing data

  • version (str, optional) – LAS version to export as (“2.0” or “3.0”). If None, uses the version of the source file.

Return type:

None

Examples

>>> las = LasFile('input.las')
>>> las.export('output.las')
>>> las.export('output_v3.las', version='3.0')