Logging 📄#
This notebook introduces the concept of logging using Python’s built-in logging module. Logging is essential for tracking events that happen when some software runs. The module provides a way to configure different log handlers and severity levels.
This notebook can be downloaded from the source code here.
The logging levels available in gwrefpy are:
DEBUG: Detailed information, typically of interest only when diagnosing problems.INFO: Confirmation that things are working as expected. This is the default logging level.WARNING: An indication that something unexpected happened, or indicative of some problem in the near futureERROR: Due to a more serious problem, the software has not been able to perform some function. Typically, these are issues will also raise exceptions.
Let’s start by importing the necessary libraries and setting the logging level to DEBUG using the set_logging_level function.
import gwrefpy as gr
import numpy as np
import pandas as pd
gr.set_log_level("DEBUG") # Set logging level to DEBUG
Log level set to DEBUG
We can now create some well objects and a model to see the logging in action.
# Creat the observed and reference wells
obs1 = gr.Well(name="Obs. well", is_reference=False)
obs1.add_timeseries(values_obs1) # <-- Here we will see logging messages
ref1 = gr.Well(name="Ref. well", is_reference=True)
ref1.add_timeseries(values_ref1) # <-- Here we will see logging messages
# Create the model and add the wells
model1 = gr.Model(name="Logging Example Model")
model1.add_well(obs1) # <-- Here we will see logging messages
model1.add_well(ref1) # <-- Here we will see logging messages
Added timeseries to well Obs. well
Added timeseries to well Ref. well
Well 'Obs. well' added to model 'Logging Example Model'.
Well 'Ref. well' added to model 'Logging Example Model'.
As you can see, we got logging messages in the console when adding the wells to the model. Now let’s fit the model to see more logging messages.
# Fit the model
model1.fit(
obs1,
ref1,
offset="0D",
tmin=dates[0],
tmax=dates[-21],
)
Using linear regression method for fitting.
Fit completed for model 'Logging Example Model' with RMSE 0.14269974740731517.
Fitting model 'Logging Example Model' using reference well 'Ref. well' and observation well 'Obs. well'.
Fit Results: Obs. well ~ Ref. well
==================================
Statistic Value Description
--------------------------------------------------
RMSE 0.1427 Root Mean Square Error
R² 0.9043 Coefficient of Determination
R-value 0.9510 Correlation Coefficient
Slope 1.9834 Linear Regression Slope
Intercept -11.3871 Linear Regression Intercept
P-value 0.0000 Statistical Significance
N 80 Number of Data Points
Std Error 0.1445 Standard Error
Confidence 95.0 % Confidence Level
Calibration Period: 2020-01-01 00:00:00 to 2020-03-20 00:00:00
Time Offset: 0D
Aggregation Method: mean
| Statistic | Value | Description |
|---|---|---|
| RMSE | 0.1427 | Root Mean Square Error |
| R² | 0.9043 | Coefficient of Determination |
| R-value | 0.9510 | Correlation Coefficient |
| Slope | 1.9834 | Linear Regression Slope |
| Intercept | -11.3871 | Linear Regression Intercept |
| P-value | 0.0000 | Statistical Significance |
| N | 80 | Number of Data Points |
| Std Error | 0.1445 | Standard Error |
| Confidence | 95.0% | Confidence Level |
Calibration Period: 2020-01-01 00:00:00 to 2020-03-20 00:00:00
Time Offset: 0D
Aggregation Method: mean
As you can see both the progress and the results of the fitting are logged to the console.
Usually, we do not want that much information printed to the console. For many practivale applications, the INFO logging level is sufficient. Let’s change the logging level and see how it affects the output. We will also enable logging to a file with the enable_file_logging function, here we can set the logging level to DEBUG to capture all messages in the file.
Tip
If you want to log your own messages in your code, you can use the get_logger function to get a logger object and then use its methods to log messages at different levels (e.g., logger.debug(), logger.info(), etc.).
In the example below, we will use the logging module directly to demonstrate this. The info and debug messages will be logged according to the logging level we set.
import logging
logger = logging.getLogger(__name__)
# Set logging level to INFO (default)
gr.set_log_level("INFO")
# Enable logging to a file with DEBUG level
gr.enable_file_logging("gwrefpy_debug.log", loglevel="DEBUG")
Log level set to INFO
Let’s create a new model and fit it again to see the detailed logging in the file.
# Creat the observed and reference wells
logger.info("Creating wells with timeseries data")
obs2 = gr.Well(name="Obs. well 1", is_reference=False)
obs2.add_timeseries(values_obs2)
ref2 = gr.Well(name="Ref. well 1", is_reference=True)
ref2.add_timeseries(values_ref2)
logger.debug("Timeseries data added to wells") # <-- This will be logged to the file only
# Create the model and add the wells
logger.info("Creating a new model")
model2 = gr.Model(name="Logging Example Model DEBUG")
model2.add_well(obs2)
model2.add_well(ref2)
logger.debug("The wells have been added to the model") # <-- This will be logged to the file only
Creating wells with timeseries data
Creating a new model
Now, when we add the wells to the model, we will not see any logging messages in the console, but they will be logged to the file.
We can now fit the model again.
# Fit the model
logger.info("Running the fit method on the model")
model2.fit(
obs2,
ref2,
offset="0D",
tmin=dates[0],
tmax=dates[-21],
)
Running the fit method on the model
Fitting model 'Logging Example Model DEBUG' using reference well 'Ref. well 1' and observation well 'Obs. well 1'.
| Statistic | Value | Description |
|---|---|---|
| RMSE | 0.1670 | Root Mean Square Error |
| R² | 0.8712 | Coefficient of Determination |
| R-value | 0.9334 | Correlation Coefficient |
| Slope | 2.1444 | Linear Regression Slope |
| Intercept | -14.4441 | Linear Regression Intercept |
| P-value | 0.0000 | Statistical Significance |
| N | 80 | Number of Data Points |
| Std Error | 0.1692 | Standard Error |
| Confidence | 95.0% | Confidence Level |
Calibration Period: 2020-01-01 00:00:00 to 2020-03-20 00:00:00
Time Offset: 0D
Aggregation Method: mean
As you can see, not as much will be printed to the console. But if we instead open gwrefpy_debug.log file we can see all the detailed logging information.
# Print the log file content
with open("gwrefpy_debug.log", "r") as log_file:
log_content = log_file.read()
print(log_content)
2025-09-26 12:03:05,620 [INFO] __main__: Creating wells with timeseries data
2025-09-26 12:03:05,620 [DEBUG] gwrefpy.well: Added timeseries to well Obs. well 1
2025-09-26 12:03:05,621 [DEBUG] gwrefpy.well: Added timeseries to well Ref. well 1
2025-09-26 12:03:05,621 [DEBUG] __main__: Timeseries data added to wells
2025-09-26 12:03:05,621 [INFO] __main__: Creating a new model
2025-09-26 12:03:05,621 [DEBUG] gwrefpy.model: Well 'Obs. well 1' added to model 'Logging Example Model DEBUG'.
2025-09-26 12:03:05,621 [DEBUG] gwrefpy.model: Well 'Ref. well 1' added to model 'Logging Example Model DEBUG'.
2025-09-26 12:03:05,621 [DEBUG] __main__: The wells have been added to the model
2025-09-26 12:03:05,625 [INFO] __main__: Running the fit method on the model
2025-09-26 12:03:05,626 [DEBUG] gwrefpy.fitbase: Using linear regression method for fitting.
2025-09-26 12:03:05,630 [DEBUG] gwrefpy.fitbase: Fit completed for model 'Logging Example Model DEBUG' with RMSE 0.1670235627371146.
2025-09-26 12:03:05,630 [INFO] gwrefpy.fitbase: Fitting model 'Logging Example Model DEBUG' using reference well 'Ref. well 1' and observation well 'Obs. well 1'.
2025-09-26 12:03:05,631 [DEBUG] gwrefpy.model: Fit Results: Obs. well 1 ~ Ref. well 1
======================================
Statistic Value Description
--------------------------------------------------
RMSE 0.1670 Root Mean Square Error
R² 0.8712 Coefficient of Determination
R-value 0.9334 Correlation Coefficient
Slope 2.1444 Linear Regression Slope
Intercept -14.4441 Linear Regression Intercept
P-value 0.0000 Statistical Significance
N 80 Number of Data Points
Std Error 0.1692 Standard Error
Confidence 95.0 % Confidence Level
Calibration Period: 2020-01-01 00:00:00 to 2020-03-20 00:00:00
Time Offset: 0D
Aggregation Method: mean
As you can see, the log file contains detailed information about the program’s execution, module, time, and log level, including messages that are not necessarily printed to the console.
This concludes this notebook on logging in gwrefpy. For more information on logging, please refer to the logging documentation and the API for gwrefpy’s logging functions here.