This article discusses how to integrate with ZoneVu using the ZoneVu Web API and Python SDK, with the goal of displaying and updating in an external system a geosteering interpretation being worked on in ZoneVu during the drilling of a horizontal well.
ZoneVu's Web API and Web API Python SDK (Software Development Kit) make it easy to integrate external applications and data stores to ZoneVu. Note that logged in ZoneVu users can access the Swagger documentation for the ZoneVu Web API at https://zonevu.ubiterra.com/swagger. The ZoneVu Web API Python SDK is available at https://pypi.org/project/zonevu. It can be installed into your Python environment with the terminal command:
pip install zonevuAssumptions & Requirements:
In this article, we refer to the different system as the “external system”
Assume that the external system will use python and the ZoneVu Python SDK and will connect to it over the internet
Assume that the external system will display the “Starred” geosteering interpretation
The goal is to display the geosteering interpretation and to update it as drilling and geosteering continues
Information about who the interpreter who is doing the geosteering is desired
Assume the external system has the ancillary data related to the geosteering interpretation including wellbore trajectories and type well log data. If not, this information can easily be retrieved from ZoneVu, but that is not covered in this article.
The external system will poll the ZoneVu Web API on a regular cycle because ZoneVu currently does not support a web hook to publish notifications of changes to the geosteering interpretation. This may change in the future.
Assume the external system knows the UWI number of the active well
Fundamentals:
During drilling and geosteering, the geosteerer may decide to modify the interpretation behind the current measured depth (MD) of the drill bit. This means that when the external system detects a change to the geosteering interpretation, it must retrieve (and display) the whole geosteering interpretation again.
ZoneVu stores and exports geosteering interpretations in an efficient format (ZoneVu Geosteering Interpretation format, or ZGI). It is very easy and efficient to retrieve interpretations using the Python SDK.
The Python SDK includes utility functions to expand the exported interpretation into a more familiar format. For example, if the external system needs the interpretation in a per foot basis, the utility function “make_evenly_spaced_picks()” will do that.
The ZoneVu Python SDK requires Python version 3.11 or later.
Here is a survey of some Python coding to build the desired integration.
First, import ‘zonevu’ from pypi.org into your Python environment.
Go into ZoneVu and generate a web API key. There are some pre-requisites:
The ZoneVu account in question must have the Web API enabled. Ubiterra Support can enable this for you.
You must be an authenticated user in that ZoneVu account in order to be able to generate a Web API key.
Since ZoneVu is an enterprise class system, all users are assigned rights by the ZoneVu company administrator user. The user must have been assigned certain rights for this scenario to work. Specifically, the user must have the Web API right and the right to download well data.
Note that ZoneVu Web API the ZoneVu company administrator user or Ubiterra Support can assign these rights.
Note that ZoneVu Web API keys have a maximum “time to live” of 30 days. You will need to get another key when a particular key expires.
How to create a ZoneVu client:
from zonevu.Zonevu import Zonevu
from zonevu.DataModels.Geosteering.Calcs import make_evenly_spaced_picks, create_extended_picks, create_pseudo_welllog
# Get zonevu client and apply api_key
# Note that by default, the zonevu client returns all depths and distances in US units
api_key = 'my api key'
zonevu = Zonevu.init_from_apikey(api_key)
How to find a well and its well bore using UWI number. Note that ZoneVu currently supports one well bore per well:
# Find the target well by UWI number
uwi = 'target well UWI number'
well_svc = zonevu.well_service
well = well_svc.find_by_uwi(uwi)
wellbore = well.primary_wellbore
How to identify and retrieve the starred geosteering interpretation:
# Get the starred or first geosteering interpretation
geosteer_svc = zonevu.geosteering_service
interp_entries = geosteer_svc.get_interpretations(wellbore.id)
interp_entry = next((g for g in interp_entries if g.starred), interp_entries[0])
interpretation_version = interp_entry.row_version # Save to use when checking for updates
interpretation = geosteer_svc.get_interpretation(interp_entry.id)
interpretation_id = interpretation.id # Save to use when checking for updatesNote that the external system should store the system id of the preferred geosteering interpretation to utilize when checking for updates on it.
How to check if a geosteering interpretation has changed:
# Check if geosteering interpretation changed
polled_interp_entry = geosteer_svc.get_interpretation_entry(interpretation_id)
changed = interpretation_version != polled_interp_entry.row_version
if changed:
changed_datetime = polled_interp_entry.last_modified_date
changed_by = polled_interp_entry.last_modified_by_name
changed_interp = geosteer_svc.get_interpretation(interpretation_id) # Must retrieve whole interp again
How to convert the compact ZGI (ZoneVu Geosteering Interpretation) format to regularly spaced picks with a list of horizon depths for each pick. See the KB article "Retrieving Geosteering Interpretations" for information on the ZGI format.
# How to convert the compact ZGI (ZoneVu Geosteering Interpretation) format to regularly spaced picks w/horizons
# Note that 'create_extended_picks' needs the strat column for the well
strat_col = zonevu.strat_service.find_stratcolumn(well.strat_column.id)
interval = 1 # 1 Foot interval
evenly_spaced_picks = make_evenly_spaced_picks(interpretation, interval)
extended_picks = create_extended_picks(interpretation, strat_col, evenly_spaced_picks)
# extended_picks should have all the information needed for easy integration with the external system
It might be easier for some applications to process the geosteering interpretation in the form of blocks and faults. See the KB article "Retrieving Geosteering Interpretations" for information on the Blocks and Faults format. You can do this as follows:
blocks, faults = make_blocks_and_faults(interpretation)
Yet another alternative approach is to use ZoneVu's Well log data structure. It might be easier in some applications to process the horizons from a geosteering interpretation in the form of well log data:
# Alternative approach using ZoneVu's Well log data structure
strat_col = zonevu.strat_service.find_stratcolumn(well.strat_column.id)
interval = 1 # 1 Foot interval
pseudo_well_log = create_pseudo_welllog(zonevu, interpretation, strat_col, interval)