I/O: LasFile¶
- class logsuite.io.las_file.LasFile(filepath, _from_dataframe=False)[source]
Bases:
objectFast 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.
- filepath
Path to LAS file
- Type:
Path
- version_info
Version section data (VERS, WRAP)
- Type:
- well_info
Well section data (WELL, STRT, STOP, NULL, etc.)
- Type:
- parameter_info
Parameter section data (includes discrete property markers and labels)
- Type:
- curves
Curve metadata: {name: {unit, description, type, alias, multiplier}}
- Type:
- discrete_properties
List of properties marked as discrete in
~Parametersection. (Read-only property.)
See also
get_discrete_labelsExtract 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 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.
- 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:
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:
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:
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:
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:
- 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:
KeyError – If curve not found
ValueError – If invalid attribute or type value
- 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.
- Raises:
ValueError – If DEPT column not found in DataFrame
LasFileError – If file write fails
- 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~Curvesections.- Parameters:
- Return type:
None
Examples
>>> las = LasFile('input.las') >>> las.export('output.las')
>>> las.export('output_v3.las', version='3.0')