Last updated

Wellbore DDMS Reference APIs

Introduction

The Wellbore DDMS Reference APIs let the user get the data of the given WellLog in the targeted reference.
The targeted reference can be chosen between TVD and TVDSS.
The targeted reference is computed using the data of the definitive trajectory of the Wellbore associated to this WellLog.
If the targeted reference is not present in the definitive trajectory of the parent wellbore, a 404 error message is returned in the response.

APIs

The module provide two APIs, one to get the data of the given WellLog in the targeted reference for the latest version and the other for a specific version of the WellLog.

    /reference/v1/welllogs/{record_id}/data
    /reference/v1/welllogs/{record_id}/version/{version}/data

API Parameters

  • {record_id}: The WellLog id
  • {version}: The version of the WellLog (only for the /version API)
  • targeted_reference: The reference for which the WellLog data have to be returned. Supported values are TVD and TVDSS. Columns with the correct type (TrajectoryStationPropertyTypeID set to a TrajectoryStationPropertyType TVD or TVDSS) should be present in the associated definitive trajectory
  • offset: The number of rows that are to be skipped and not included in the result
  • limit: The maximum number of rows to be returned
  • curves: Filters curves. List of curves to be returned (in addition to MD and targeted_reference). If not set or set to None, only MD and targeted_reference are returned. The default value is set to None to maximize performances with large data.
  • orient: format for JSON only.

Best practice

When retrieving large data (huge number of variables, columns and/or rows) it is a good practice to call this API only for reference (MD) and targeted reference (TVD). This can be achieved by letting the curves parameter empty. It prevents unnecessary network calls and huge size of data transit between Wellbore DMS and Delfi-wdms services.

Example use case: display big data using TVD Good workflow:

  • call Wellbore DMS WellLog bulk api to get curves data (preferably by chunk)
  • call Delfi-Wdms reference api to get MD and associated TVD (preferably by chunk) and append the TVD column to the result of Wellbore DMS call.

Code example

If needed install required modules
# If needed install required modules
import sys
!{sys.executable} -m pip install httpx
!{sys.executable} -m pip install pandas
Setup targeted environment and http client
# Setup targeted environment and http client

import httpx
import json
import pandas as pd

#Authentication token
token = 'your Bearer token'

#evt
data_partition = 'opendes'
OSDU_URL = "https://evt.api.enterprisedata.cloud.slb-ds.com"
acl_domain = "enterprisedata.cloud.slb-ds.com"
legal_tag = "opendes-default-legal"

delfi_wdms_host = OSDU_URL + "/api/delfi-wdms"
wdms_host = OSDU_URL + "/api/os-wellbore-ddms"
accept_type = "application/json" # Can be changed to "application/x-parquet" to get result in parquet format

headers = {
    'Content-Type': 'application/json', 
    'Accept': accept_type, 
    'data-partition-id':data_partition,
    'Authorization': token
}

transport = httpx.HTTPTransport(retries=3)
client = httpx.Client(transport=transport)
Data creation for testing - Wellbore
# Data creation for testing
wellbore = {
    "id": f"{data_partition}:master-data--Wellbore:delfiwdms-nb123456gw",
    "kind": "osdu:wks:master-data--Wellbore:1.0.0",
    "acl": {
      "viewers": [
        f"data.default.viewers@{data_partition}.{acl_domain}"
      ],
      "owners": [
        f"data.default.owners@{data_partition}.{acl_domain}"
      ]
    },
    "legal": {
      "legaltags": [
        f"{legal_tag}"
      ],
      "otherRelevantDataCountries": [
        "FR",
        "US"
      ]
    },
    "data": {
      "Source": "delfiwdms",
      "DefinitiveTrajectoryID": f"{data_partition}:work-product-component--WellboreTrajectory:delfiwdms-nb123456gt:",
      "VerticalMeasurements": [
            {
                "VerticalMeasurement": 12155.0,
                "VerticalMeasurementID": "Total Depth MD",
                "VerticalMeasurementPathID": f"{data_partition}:reference-data--VerticalMeasurementPath:MeasuredDepth:",
                "VerticalMeasurementUnitOfMeasureID": f"{data_partition}:reference-data--UnitOfMeasure:ft:"
            },            
            {
                "VerticalMeasurement": 128.0,
                "VerticalMeasurementID": "Well Head Elevation",
                "VerticalMeasurementPathID": f"{data_partition}:reference-data--VerticalMeasurementPath:TrueVerticalHeight:",
                "VerticalMeasurementUnitOfMeasureID": f"{data_partition}:reference-data--UnitOfMeasure:ft:"
            }
        ],
        "DefaultVerticalMeasurementID": "Well Head Elevation"
    }
}
r = client.post(wdms_host + f"/ddms/v3/wellbores", headers=headers, json=[wellbore])
assert r.status_code==200
print('Wellbore created')
Data creation for testing - WellLog
# Data creation for testing
welllog = {
    "id": f"{data_partition}:work-product-component--WellLog:delfiwdms-nb123456gw",
    "kind": "osdu:wks:work-product-component--WellLog:1.1.0",
    "acl": {
      "viewers": [
        f"data.default.viewers@{data_partition}.{acl_domain}"
      ],
      "owners": [
        f"data.default.owners@{data_partition}.{acl_domain}"
      ]
    },
    "legal": {
      "legaltags": [
        f"{legal_tag}"
      ],
      "otherRelevantDataCountries": [
        "FR",
        "US"
      ]
    },    "tags": {
      "QualityScore": "Low",
      "QCCompleteness": "High",
      "QCValidity": "Low"
    },
    "data": {
      "Name": "delfiwdms test wellLog",
      "Source": "delfiwdms",
      "TechnicalAssuranceID": f"{data_partition}:reference-data--TechnicalAssuranceType:Unsuitable:",
      "WellboreID": f"{data_partition}:master-data--Wellbore:delfiwdms-nb123456gw:",
      "TopMeasuredDepth": 808.0,
      "BottomMeasuredDepth": 812.5,
      "Curves": [
        {
          "CurveID": "DEPTH",
          "CurveUnit": f"{data_partition}:reference-data--UnitOfMeasure:m:",
          "Mnemonic": "DEPTH",
          "LogCurveFamilyID": f"{data_partition}:reference-data--LogCurveFamily:Measured%20Depth:",
          "NumberOfColumns": 1
        },
        {
          "CurveID": "GR",
          "CurveUnit": f"{data_partition}:reference-data--UnitOfMeasure:gAPI:",
          "Mnemonic": "GR",
          "LogCurveFamilyID": f"{data_partition}:reference-data--LogCurveFamily:Gamma%20Ray:",
          "NumberOfColumns": 1
        }
      ],
      "SamplingInterval": 0.5,
      "ReferenceCurveID": "DEPTH",
      "SamplingStart": 808.0,
      "SamplingStop": 812.5,
      "SamplingDomainTypeID": f"{data_partition}:reference-data--WellLogSamplingDomainType:Depth:",
      "ExtensionProperties": {}
    }
}
r = client.post(wdms_host + f"/ddms/v3/welllogs", headers=headers, json=[welllog])
# assert r.status_code==200 <-- it can fail if entity already created

welllog_bulks = {"columns":["DEPTH","GR"],
                 "index":[0,1,2,3,4,5,6,7,8,9],
                 "data":[[808.0,808.0],
                         [808.5,808.5],
                         [809.0,809.0],
                         [809.5,809.5],
                         [810.0,810.0],
                         [810.5,810.5],
                         [811.0,811.0],
                         [811.5,811.5],
                         [812.0,812.0],
                         [812.5,812.5]]}
r = client.post(wdms_host + f"/ddms/v3/welllogs/{welllog['id']}/data", headers=headers, json=welllog_bulks)
assert r.status_code==200
print('WellLog created')
Data creation for testing - Wellbore Trajectory
# Data creation for testing
wellbore_trajectory = {
    "id": f"{data_partition}:work-product-component--WellboreTrajectory:delfiwdms-nb123456gt",
    "kind": "osdu:wks:work-product-component--WellboreTrajectory:1.1.0",
    "acl": {
      "viewers": [
        f"data.default.viewers@{data_partition}.{acl_domain}"
      ],
      "owners": [
        f"data.default.owners@{data_partition}.{acl_domain}"
      ]
    },
    "legal": {
      "legaltags": [
        f"{legal_tag}"
      ],
      "otherRelevantDataCountries": [
        "FR",
        "US"
      ]
    },    "data": {
      "Source": "Techlog",
      "WellboreID": f"{data_partition}:master-data--Wellbore:delfiwdms-nb123456gw:",
      "TopDepthMeasuredDepth": 800.0,
      "BaseDepthMeasuredDepth": 809.75,
      "VerticalMeasurement": {
        "VerticalReferenceID": "Well Head Elevation"
      },
      "AvailableTrajectoryStationProperties": [
        {
          "TrajectoryStationPropertyTypeID": f"{data_partition}:reference-data--TrajectoryStationPropertyType:MD:",
          "StationPropertyUnitID": f"{data_partition}:reference-data--UnitOfMeasure:m:",
          "Name": "MD"
        },
        {
          "TrajectoryStationPropertyTypeID": f"{data_partition}:reference-data--TrajectoryStationPropertyType:TVD:",
          "StationPropertyUnitID": f"{data_partition}:reference-data--UnitOfMeasure:m:",
          "Name": "TVD"
        },
        {
          "TrajectoryStationPropertyTypeID": f"{data_partition}:reference-data--TrajectoryStationPropertyType:TVDSS:",
          "StationPropertyUnitID": f"{data_partition}:reference-data--UnitOfMeasure:m:",
          "Name": "TVDSS"
        }
      ],
      "ExtensionProperties": {}
    }
}
r = client.post(wdms_host + f"/ddms/v3/wellboretrajectories", headers=headers, json=[wellbore_trajectory])
# assert r.status_code==200 <-- it can fail if entity already created

wellbore_trajectory_bulks = {"columns":["TVD","TVDSS","MD"],
                             "index":[0.0,0.15,0.3,0.45,0.6,0.75,0.9,1.05,1.2,1.35,1.5,1.65,1.8,1.95,2.1,2.25,2.4,2.55,2.7,2.85,3.0,3.15,3.3,3.45,3.6,3.75,3.9,4.05,4.2,4.35,4.5,4.65,4.8,4.95,5.1,5.25,5.4,5.55,5.7,5.85,6.0,6.15,6.3,6.45,6.6,6.75,6.9,7.05,7.2,7.35,7.5,7.65,7.8,7.95,8.1,8.25,8.4,8.55,8.7,8.85,9.0,9.15,9.3,9.45,9.6,9.75],
                             "data":[[800.0,800.0,800.0],[800.15,800.15,800.15],[800.3,800.3,800.3],[800.45,800.45,800.45],[800.6,800.6,800.6],[800.75,800.75,800.75],[800.9,800.9,800.9],[801.05,801.05,801.05],[801.2,801.2,801.2],[801.35,801.35,801.35],[801.5,801.5,801.5],[801.65,801.65,801.65],[801.8,801.8,801.8],[801.95,801.95,801.95],[802.1,802.1,802.1],[802.25,802.25,802.25],[802.4,802.4,802.4],[802.55,802.55,802.55],[802.7,802.7,802.7],[802.85,802.85,802.85],[803.0,803.0,803.0],[803.15,803.15,803.15],[803.3,803.3,803.3],[803.45,803.45,803.45],[803.6,803.6,803.6],[803.75,803.75,803.75],[803.9,803.9,803.9],[804.05,804.05,804.05],[804.2,804.2,804.2],[804.35,804.35,804.35],[804.5,804.5,804.5],[804.65,804.65,804.65],[804.8,804.8,804.8],[804.95,804.95,804.95],[805.1,805.1,805.1],[805.25,805.25,805.25],[805.4,805.4,805.4],[805.55,805.55,805.55],[805.7,805.7,805.7],[805.85,805.85,805.85],[806.0,806.0,806.0],[806.15,806.15,806.15],[806.3,806.3,806.3],[806.45,806.45,806.45],[806.6,806.6,806.6],[806.75,806.75,806.75],[806.9,806.9,806.9],[807.05,807.05,807.05],[807.2,807.2,807.2],[807.35,807.35,807.35],[807.5,807.5,807.5],[807.65,807.65,807.65],[807.8,807.8,807.8],[807.95,807.95,807.95],[808.1,808.1,808.1],[808.25,808.25,808.25],[808.4,808.4,808.4],[808.55,808.55,808.55],[808.7,808.7,808.7],[808.85,808.85,808.85],[809.0,809.0,809.0],[809.15,809.15,809.15],[809.3,809.3,809.3],[809.45,809.45,809.45],[809.6,809.6,809.6],[809.75,809.75,809.75]]}
r = client.post(wdms_host + f"/ddms/v3/wellboretrajectories/{wellbore_trajectory['id']}/data", headers=headers, json=wellbore_trajectory_bulks)
assert r.status_code==200

print('Wellbore Trajectory created')
Call to reference api
# Call to reference api

params = {
    "targeted_reference": "TVD", # Can be TVD to get TVD or TVDSS to get the TVDSS
    "limit": 3, # (optional) retrieve only 3 rows
    "offset": 0, # (optional) starting at first row
    "curves": "GR", # (optional) Additional curves to retrieve, the format is a string curve ids seprated by ','
}

r = client.get(delfi_wdms_host + f"/reference/v1/welllogs/{welllog['id']}/data", headers=headers, params=params)
assert r.status_code==200
print(json.dumps(r.json(), indent=1)) 

df = pd.read_json(json.dumps(r.json()), orient='split')
print("Dataframe view")
display(df)
  Dataframe view
    {
     "columns": [
      "DEPTH",
      "GR",
      "TVD"
     ],
     "index": [
      808.0,
      808.5,
      809.0
     ],
     "data": [
      [
       808.0,
       808.0,
       808.0
      ],
      [
       808.5,
       808.5,
       808.5
      ],
      [
       809.0,
       809.0,
       809.0
      ]
     ]
    }
DEPTHGRTVD
808.0808.0808.0808.0
808.5808.5808.5808.5
809.0809.0809.0809.0
Best practice example
# Best practice example

# Call Wdms to get all columns
params = {
    "limit": 5, 
    "offset": 1, 
}
r = client.get(wdms_host + f"/ddms/v3/welllogs/{welllog['id']}/data", headers=headers, params=params)
assert r.status_code==200
df_from_wdms = pd.read_json(json.dumps(r.json()), orient='split')
print("Dataframe from Wdms")
display(df_from_wdms)

# Get TVD from reference module
params = {
    "targeted_reference": "TVD", # Can be TVD to get TVD or TVDSS to get the TVDSS
    "limit": 4, 
    "offset": 0, 
}

r = client.get(delfi_wdms_host + f"/reference/v1/welllogs/{welllog['id']}/data", headers=headers, params=params)
assert r.status_code==200

df_from_reference_module = pd.read_json(json.dumps(r.json()), orient='split')
print("Dataframe from Reference module")
display(df_from_reference_module)

# Merge results
# Drop Depth column before merging in df_from_reference_module
df_from_reference_module = df_from_reference_module[df_from_reference_module.columns[~df_from_reference_module.columns.isin([welllog['data']['ReferenceCurveID']])]]
# Merge dataframe from Wdms and one from reference module
dfres = pd.merge(df_from_wdms, df_from_reference_module, left_index=True, right_index=True)
print("Merged Dataframe")
display(dfres)
Dataframe from Wdms
DEPTHGR
808.5808.5808.5
809.0809.0809.0
809.5809.5809.5
810.0810.0810.0
810.5810.5810.5
Dataframe from Reference module
DEPTHTVD
808.0808.0808.0
808.5808.5808.5
809.0809.0809.0
809.5809.5809.5
Merged Dataframe
DEPTHGRTVD
808.5808.5808.5808.5
809.0809.0809.0809.0
809.5809.5809.5809.5
Clean up test data

# Clean up data
r = client.post(wdms_host + f"/ddms/v3/records/delete", headers=headers, json=[wellbore['id'], welllog['id'], wellbore_trajectory['id']])
assert r.status_code==204
print('Data removed')
Data removed