The aim of Well Belo Log is to ease the workflow of dealing with large ammounts of files. It's quite common the need to restart your kernel while trying to acess some data in a closed file. Or maybe the boiler code is just too much, to merge the logical files, extract the frames... Anyway, enjoy...
- Well Belo Log
- Installation
- Usage
- Developing the project
- Academic Sponsors
You can install the package using pip directly from the github repository:
pip install git+https://github.com/MonumentoSoftware/wellbelog
or you can clone the repository and install it locally:
git clone https://github.com/MonumentoSoftware/wellbelog
cd webelog
pip install .
The main objective of WellBeLog is to ease the workflow when working with .dlis, .las and .dlis files. So, there are three main classes that you can use to work with these files. Also, we offer support to .tiff files, via the DlisReader and the LisReader classes.
- DlisReader: to read .dlis files
- LasReader: to read .las files
- LisReader: to read .lis files
All modules to deal with the files extensions, have a DataframeSchema class that can be generate pandas Dataframes.
- dlis has a FrameDataframe class
- las has a LasDataframe class
- lis has a CurveDataframe class
We intend to expand this feature, ut for now we have a generic funtion to plot all curves.
The plot_all_curves function receives a pandas dataframe, the depth column name, and the file name. It returns a plotly figure.
from webelog.plotters.general import plot_all_curves
from webelog.belolas import LasReader
# Acessing the data
reader = LasReader()
las_file = reader.process_las_file('path/to/your/file.las')
data = las_file.data
df = data.as_df()
figure = plot_all_curves(df, 'DEPT', las_file.file_name)
figure.show()
from webelog.plotters.general import plot_all_curves
from webelog.belolas import LisReader
# Acessing the data
reader = LisReader()
lis_file = reader.process_lis_file('path/to/your/file.lis')
curve_1 = file.logical_files[2].get_curve()
df = curve_1.as_df()
fig = plot_all_curves(df, 'DEPT', f'{file.file_name}-{file.logical_files[0].logical_id}.png')
fig.show()
In the Belodlis folder you can find all the tools to work with Dlis files. The DlisReader class reads the physical file and returns a PhysicalFileModel object, that contains all the information about the logical files, logical records, channels, frames, etc.
A simple way to search for Dlis files is to use the search_files method. It returns a list of all the Dlis files in the folder.
from webelog.belodlis import DlisReader
reader = DlisReader()
dlis_files = reader.search_files('path/to/your/folder')
The process_physical_file method returns a PhysicalFileModel object, that contains all the information about the logical files, logical records, channels, frames, etc.
from webelog.belodlis import DlisReader
reader = DlisReader()
dlis_file = reader.process_physical_file('path/to/your/file.dlis')
Prints a table with the file information.
from webelog.belodlis import DlisReader
reader = DlisReader()
dlis_file = reader.process_physical_file('path/to/your/file.dlis')
dlis_file.logical_files_table()
Will print something like this:
1PIR1AL_conv_ccl_canhoneio.dlis
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓
┃ File Name ┃ Curves ┃ Error ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━┩
│ 1PIR1AL_conv_ccl_canhoneio.dlis │ ['TDEP', 'MINMK', 'LSPD', 'LTEN', 'CCL'] │ False │
│ 1PIR1AL_conv_ccl_canhoneio.dlis │ ['TDEP', 'MINMK', 'LSPD', 'LTEN', 'CCL'] │ False │
│ 1PIR1AL_conv_ccl_canhoneio.dlis │ ['TDEP', 'MINMK', 'LSPD', 'LTEN', 'CCL'] │ False │
└─────────────────────────────────┴──────────────────────────────────────────┴───────┘
To convert the data to a pandas dataframe.
import pandas as pd
from webelog.belodlis import DlisReader
reader = DlisReader()
dlis_file = reader.process_physical_file('path/to/your/file.dlis')
frame = dlis_file.logical_files[0].get_frame()
df: pd.DataFrame = frame.data.as_df()
To save the data to a CSV file.
import pandas as pd
from webelog.belodlis import DlisReader
reader = DlisReader()
dlis_file = reader.process_physical_file('path/to/your/file.dlis')
frame = dlis_file.logical_files[0].get_frame()
frame.data.to_csv('path/to/your/file.csv')
# NOTE the function returns the path to the file.
path_to_csv = frame.data.to_csv('path/to/your/file.csv')
To save the data to an Excel file.
import pandas as pd
from webelog.belodlis import DlisReader
reader = DlisReader()
dlis_file = reader.process_physical_file('path/to/your/file.dlis')
frame = dlis_file.logical_files[0].get_frame()
frame.data.to_excel('path/to/your/file.xlsx')
# NOTE the function returns the path to the file.
path_to_excel = frame.data.to_excel('path/to/your/file.xlsx')
- Schemas Folder We make use of Pydantic to create the models. The PhysicalFileModel is the main model, but we have LogicalFileModel to represent the logical files, FrameModel to represent the frames. Here are the main models:
The main model, that contains all the information about the logical files, logical records, channels, frames, etc.
class PhysicalFileModel(TimeStampedModelSchema):
file_name: str = Field(..., description="The name of the file.")
error: bool = Field(False, description="If the file has any error during opening.")
error_message: Optional[str] = Field(None, description="The error exception if any.")
logical_files: Optional[list[LogicalFileModel]] = Field(default_factory=list, description="The logical files.")
error_files: Optional[list[LogicalFileModel]] = Field(default_factory=list, description="The error files.")
mnemonics: Optional[list[str]] = Field(default_factory=list, description="The mnemonics of the file.")
To represent the logical files.
class LogicalFileModel(TimeStampedModelSchema):
file_name: str = Field(..., description="The name of the file.")
logical_id: Any = Field(..., description="The id of the logical file.")
summary: LogicalFileSummary = Field(..., description="The summary of the file.")
frames: list[FrameModel] = Field(None, description="The frames of the file.")
error: bool = Field(False, description="If the file has any error during opening.")
error_message: Optional[str] = Field(None, description="The error exception if any.")
To represent the frames.
class FrameModel(TimeStampedModelSchema):
file_name: str = Field(..., description="The name of the file.")
logical_file_id: str = Field(..., description="The id of the logical file.")
description: Optional[str] = Field(None, description="The description of the file.")
channels: ChannelsList = Field(None, description="The channels of the file.")
error: bool = Field(False, description="If the file has any error during opening.")
error_message: Optional[str] = Field(None, description="The error exception if any.")
data: Optional[FrameDataframe] = Field(None, description="The dataframe of the file.")
To represent the Dataframe. The FrameDataframe class extends the DataframeSchema, that has a method to convert the data to a pandas DataFrame. And exports the data to a CSV file or to a Excel file.
class FrameDataframe(DataframeSchema):
file_name: str = Field(..., description="The name of the file.")
logical_file_id: str = Field(..., description="The id of the logical file.")
data: list[dict] = Field(None, description="The dataframe of the file.")
In the Belolas folder you can find all the tools to work with Las files. The .las extension is newer than the .dlis extension, and it's a lot simpler to work with. The LasReader class reads the physical file and returns a LasFileModel object, that contains all the information about the sections, curves, etc.
Use the search_files method to search for Las files in a folder. It returns a list of all the Las files in the folder.
from webelog.belolas import LasReader
reader = LasReader()
las_files = reader.search_files('path/to/your/folder')
The process_las_file method returns a LasFileModel object.
from webelog.belolas import LasReader
reader = LasReader()
las_file = reader.process_las_file('path/to/your/file.las')
Prints a table with the file information.
from webelog.belolas import LasReader
reader = LasReader()
las_file = reader.process_las_file('path/to/your/file.las')
las_file.table_view()
1-MPE-3-AL_hals-dslt-tdd-hgns-gr_resistividade_repetida.las
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓
┃ File Name ┃ Curves ┃ Error ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━┩
│ 1-MPE-3-AL_hals-dslt-tdd-hgns-gr_resistividade_repetida.las │ ['DEPT', 'DT', 'GR', 'HCAL', 'HDRA', 'HLLD', 'HLLS', 'HRM', 'HSO', 'HTEM', 'ITT', 'NPHI', │ False │
│ │ 'PEFZ', 'RHOZ'] │ │
└─────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────┴───────┘
To convert the data to a pandas dataframe.
import pandas as pd
from webelog.belolas import LasReader
reader = LasReader()
las_file = reader.process_las_file('path/to/your/file.las')
df: pd.DataFrame = las_file.data.as_df()
To save the data to a CSV file.
import pandas as pd
from webelog.belolas import LasReader
reader = LasReader()
las_file = reader.process_las_file('path/to/your/file.las')
las_file.data.to_csv('path/to/your/file.csv')
# NOTE the function returns the path to the file.
path_to_csv = las_file.data.to_csv('path/to/your/file.csv')
To save the data to an Excel file.
import pandas as pd
from webelog.belolas import LasReader
reader = LasReader()
las_file = reader.process_las_file('path/to/your/file.las')
las_file.data.to_excel('path/to/your/file.xlsx')
# NOTE the function returns the path to the file.
path_to_excel = las_file.data.to_excel('path/to/your/file.xlsx')
We make use of Pydantic to create the models. The LasFileModel is the main model, but we have SectionModel to represent the sections, CurveModel to represent the curves, etc.
A class to represent the Las file. It contains the file name, the folder name, the specs, the data, and some error handling.
class LasFileModel(TimeStampedModelSchema):
file_name: str = Field(..., description="The name of the file.")
folder_name: Optional[str] = Field(None, description="The name of the folder.")
specs: list[LasCurvesSpecs] = Field([], description="The curves specs.")
error: bool = Field(False, description="If the file has any error during opening.")
error_message: Optional[str] = Field(None, description="The error exception if any.")
data: Optional[LasDataframe] = Field(None, description="The data of the file.")
def column_search(self, column: str) -> Optional[LasCurvesSpecs]:
for spec in self.specs:
if spec.mnemonic == column:
return spec
return None
A class to represent the Dataframe. It extends the DataframeSchema, that has a method to convert the data to a pandas DataFrame. And exports the data to a CSV file or to a Excel file.
class LasDataframe(DataframeSchema):
file_name: str = Field(..., description="The name of the file.")
columns: list[str] = Field(..., description="The columns of the curve.")
shape: tuple = Field(..., description="The shape of the curve.")
Similar do the .Dlis file extension, the lis format is quite old and was the first of the three to be created. The BeloLis folder contains all the tools to work with Lis files. Nowadays, it's not so common to find .lis files, but we offer support to it as well. Also, there are some .Tiff files that uses the .lis extension.
A simple way to search for Lis files is to use the search_files method. It returns a list of all the Lis files in the folder.
from webelog.belolas import LisReader
reader = LisReader()
lis_files = reader.search_files('path/to/your/folder')
The process_lis_file method returns a LisFileModel object.
from webelog.belolas import LisReader
reader = LisReader()
lis_file = reader.process_physical_file('path/to/your/file.lis')
Prints a table with the file information.
from webelog.belolas import LisReader
reader = LisReader()
lis_file = reader.process_lis_file('path/to/your/file.lis')
lis_file.logical_files_table()
Will print something like this:
1-MPE-3-AL.lis
┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓
┃ File Name ┃ Curves ┃ Error ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━┩
│ 1-MPE-3-AL.lis │ [] │ False │
│ 1-MPE-3-AL.lis │ ['SP', 'SN', 'TBHV', 'DIR', 'ABHV', 'DEPT', 'DT', 'GR', 'ITT', 'TT4', 'TT1', 'YCAL', 'XCAL', 'TT3', 'TT2'] │ False │
└────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────┴───────┘
To convert the data to a pandas dataframe.
import pandas as pd
from webelog.belolas import LisReader
reader = LisReader()
lis_file = reader.process_lis_file('path/to/your/file.lis')
df: pd.DataFrame = lis_file.logical_files[0].curves_data[0].as_df()
To save the data to a CSV file.
import pandas as pd
from webelog.belolas import LisReader
reader = LisReader()
lis_file = reader.process_lis_file('path/to/your/file.lis')
lis_file.logical_files[0].curves_data[0].to_csv('path/to/your/file.csv')
# NOTE the function returns the path to the file.
path_to_csv = lis_file.logical_files[0].curves_data[0].to_csv('path/to/your/file.csv')
To save the data to an Excel file.
import pandas as pd
from webelog.belolas import LisReader
reader = LisReader()
lis_file = reader.process_lis_file('path/to/your/file.lis')
lis_file.logical_files[0].curves_data[0].to_excel('path/to/your/file.xlsx')
# NOTE the function returns the path to the file.
path_to_excel = lis_file.logical_files[0].curves_data[0].to_excel('path/to/your/file.xlsx')
To develop the project, you can clone the repository and install the requirements:
git clone https://github.com/MonumentoSoftware/wellbelog
cd wellbelog
poetry install
You can develop the project by creating new classes, methods, etc. Then you can run examples inside the poetry shell, let's say the dlis_example.py:
poetry shell
python examples/dlis_example.py
Then you can run the tests:
poetry run pytest
Thus project was developed to support the research of LAGESE - LaboratórioLaboratório de Geologia Sedimentar e Ambiental, da Universidade Federal de Pernambuco (UFPE) , located on the LITPEG - Instituto de Pesquisa em Petróleo e Energia.