---
title: Python Tutorial
slug: python-tutorial
docTags: 
createdAt: 2023-03-22T17:09:28.000Z
---

*Author(s): Clark Chen and Kyle Vessey, November 2022*

:::hint{type="warning"}
<u>**Developer Prerequisites:**</u>

- mTLS Certificate, Client ID and Client Secret Key [(tutorial)](docId\:HRo4LnNgI79gn1Ww2Y-Ma)
- Python v3.9+  ([https://www.python.org/downloads/](https://www.python.org/downloads/))
- Pip (Latest Version) [https://pypi.org/project/pip/](https://pypi.org/project/pip/)
- VS Code IDE ([https://code.visualstudio.com/](https://code.visualstudio.com/)) or equivalent IDE
- Internet connection
:::

:::hint{type="info"}
<u>**Data Schema:**</u>

Please read the [Data Schema Fundamentals](docId\:iRzm_O_CYHCgjw5aThv1_) document before using the API. **Database CRUD operations are performed via the API** and therefore it is important to think of each HTTP REST operation (POST/GET/DELETE) as SQL transaction (UPSERT/SELECT/DELETE)
:::

:::hint{type="info"}
<u>**Visualizing Data:**</u>

Data inserted or modified using this tutorial can be visualized using the web portal application(s) at https\://app.onxecta.com. The portal contains a [Model Quality](docId\:JxHsilA0EcXIFRjb4G-l6) tool where you can see what data is in the system, the validity of the data and when the data was last modified.
:::

# 1 Create Project and Connect

## 1.1 Project Creation

### Create New Project in VS Code

Create a new folder on your machine to begin building your project

Open the folder, and create a new Python file

### Open Existing Project in VS Code

## 1.2 Install Xecta.Data.APIClient

### Download latest Xecta.Data.API Client from PIP Package Manager

The Xecta Data API Client is hosted as a Python package in [PyPi](https://pypi.org/project/xecta-data-api-client)

To install the API Client, run the following command in your command prompt window:

:::CodeblockTabs
```python
pip install xecta-data-api-client
```

Python3

```python
# If you do not have Python 2.7 installed, or you are on MacOS
# You may need to use the Python3 syntax for pip
pip3 install xecta-data-api-client
```
:::

This will pull the compiled package from PyPi and install it on your machine.

### Install and Configure SDK

To initialize and configure you project to include the SDK, follow this code sample

:::CodeblockTabs
Python

```python
from xecta_data_client.xecta_api import XectaApi

# Root URL
root_url = "https://data-sandbox.onxecta.com"
# Path to Signed CSR Certificate .pem file
signed_cert = "{LOCAL_PATH_TO_PEM}/xecta-data-api.pem"
# Path to Private Key
private_key = "{LOCAL_PATH_TO_PRIVATE_KEY}/xecta-data-api.key"

# Client ID
client_id = '{YOUR_CLIENT_ID}'
# Client Secret
client_secret = '{YOUR_CLIENT_SECRET}'

# Initialize the xecta api with the root url, certificate and key
xecta_api = XectaApi(root_url, signed_cert, private_key)

# Authenticating will return you a xecta api client.
api_client = xecta_api.authenticate(client_id, client_secret)
```
:::

:::hint{type="warning"}
<u>**Error Initializing Certificate and Key:**</u>
When calling the xecta\_api.authenticate method, you must pass in the environment URL, signed certificate (**xecta-data-api.pem**), and your private key (**xecta-data-api.key**)

If you get an error message stating: \[SSL: CERTIFICATE\_VERIFY\_FAILED], try the following fix:

**MacOS:** Navigate to Macintosh HD > Applications > PythonX.X folder (where X is the version of Python you are using) > then double click on "Install Certificates.command" file


![](https://api.archbee.com/api/optimize/-kIqrMCOJgmgBmRpzgKo2/mxi1oCbL7N7uDmNG47_RM_image.png "Install Certificates")
:::

## 1.3 Pre-requisite - Dependent Python Libraries Installation

a) Required Python libraries - Pandas and Numpy

```python
pip install pandas
pip install numpy
```

b) Optional Python libraries - tqdm (For displaying progress bar of data processing)

```python
pip install tqdm
```

## 1.4 Import required Python Libraries and API Client

```python
## Import required Python libraries
import pandas as pd
import numpy as np
## Import optional Python libraries
from tqdm import tqdm
## Import required API client and API endpoints
from openapi_client import ApiException, ApiClient
from openapi_client.model.daily_production_input import DailyProductionInput
from openapi_client.model.daily_production import DailyProduction
from openapi_client.model.well_input import WellInput
from xecta_data_client.xecta_api import XectaApi
from openapi_client import ApiClient, Configuration
from openapi_client.exceptions import ApiTypeError, ApiValueError, ApiException
from openapi_client.model.deviation_survey import DeviationSurvey
from openapi_client.model.deviation_survey_input import DeviationSurveyInput
from openapi_client.model.wellbore import Wellbore
from openapi_client.model.wellbore_input import WellboreInput
from openapi_client.model.casing import Casing
from openapi_client.model.casing_input import CasingInput
from openapi_client.model.tubing import Tubing
from openapi_client.model.tubing_input import TubingInput
from openapi_client.model.formation import Formation
from openapi_client.model.formation_input import FormationInput
```

# 2 Well Headers

## 2.1 Insert or Upsert a Well Header

a) Data Preparation - Import well header from source data (.xlsx data demonstrated in this tutorial)

```python
## Import wellheader from source data
well_header = pd.read_excel(r'...\exampledata.xlsx',sheet_name='well')
```

b) Create a function to convert field names in camel case to snake case

- This function will be used for other source data as well

```python
## Create a function to convert source data field names in camel case to snake case
def filed_name_conversion(str):
    return ''.join(['_'+i.lower() if i.isupper() else i for i in str]).lstrip('_')
```

c) Change field names and data type to be consistent with data schema

```python
## Convert source data field names in camel case to snake case
for name in well_header.columns:
    well_header.rename(columns={name : filed_name_conversion(name)},inplace=True)

## Convert NaN to Nonetype
well_header.replace({np.nan: None},inplace=True)

## Convert field 'uwi' and 'type' to str type
well_header['uwi'] = well_header['uwi'].apply(str)
well_header['type'] = well_header['type'].apply(str)

## Convert wellheader data to list form
well_header_input = well_header.to_dict(orient = 'records')

```

d) Upsert wellheader data to API client

```python
try:
    well_header_api = api_client.well_header_api()
    api_response = well_header_api.upsert_wells(well_header_input)
    ## Print API response when well header data was succesfully upserted
    print(api_response)
except ApiException as e:
  	## Print API response when error occured during upserting
    print("Exception when calling WellApi->upsert_wells: %s\n" % e)
```

:::hint{type="warning"}
Potential Error: Null values in non-nullable fields

Example: Null in field 'lat' will return error message when upserting
:::

::Image[]{src="https://files.readme.io/07e451f-image.png" size="50" isUploading="false" showCaption="false"}

## 2.2 Get a Well Header Record

```python
## Specify Source ID to be queried
source_id = 'SPECIFY_YOUR_SOURCE_ID'
## Get Wellheader by Source ID
try:
    well_header_api = api_client.well_header_api()
    api_response = well_header_api.get_well_by_source(source_id)
		## Print API response when well header data was fetched
    print(api_response)
except ApiException as e:
		## Print API response when error occured during fetching
    print("Exception when calling WellApi->get_well_by_source: %s\n" % e)
```

## 2.3 Get All Well Header Records

```python
## Get all Wellheaders
try:
    well_header_api = api_client.well_header_api()
    api_response = well_header_api.get_wells()
		## Print API response when well header data was fetched
    print(api_response)
except ApiException as e:
		## Print API response when error occured during fetching
    print("Exception when calling WellApi->get_wells(): %s\n" % e)
```

## 2.4 Delete a Well Header Record

```python
## Specify Source ID to be deleted
source_id = 'SPECIFY_YOUR_SOURCE_ID'
## Delete Wellheader by Source ID
try:
    well_header_api = api_client.well_header_api()
    api_response = well_header_api.delete_well_by_source('source_id')
    ## Print API response when well header data was successfully deleted
    print(api_response)
except ApiException as e:
  	## Print API response when error occured during deleting
    print("Exception when calling WellApi->delete_well_by_source: %s\n" % e)
```

# 3 Daily Production

## 3.1 Insert or Upsert single Daily Production record

a) Create daily production input (Example data demonstrated)

```python
## Create example daily production record
daily_production = [
    DailyProductionInput(
        uwi = "well_uwi",
        date=datetime.datetime(2022, 9, 21, 20, 33, 4, 303441, tzinfo=tzutc()),
        oil_rate=12.33,
        gas_rate=12.33,
        water_rate=12.33,
        tubing_pressure=12.33,
        choke=1,
        gauge_pressure=12.33,
        wellhead_temperature=12.33,
        gauge_temperature=12.33,
        casing_pressure=12.33,
        gas_lift_injection_rate=12.33,
        esp_frequency=12.33,
        esp_intake_pressure=12.33,
        esp_amps=12.33,
        esp_volts=12.33,
        esp_discharge_pressure=12.33,
        esp_motor_temperature=12.33,
        esp_vibration=12.33,
        srp_strokes_per_min=12.33,
        downtime_hours=12.33,
        downtime_code="ST_1",
        water_injection_rate=12.33,
        gas_injection_rate=12.33,
    )]
```

b) Upsert daily production to API client

```python
try:
    daily_production_api = api_client.daily_production_api()
    response = daily_production_api.upsert_daily(daily_production)
    ## Print API response when daily production was successfully upserted
    print(response)
except ApiException as e:
  	## Print API response when error occurred during upserting
    print("Exception when calling DailyProductionApi->upsert_daily: %s\n" % e)
```

:::hint{type="success"}
**API response when upserted successfully**



::Image[]{src="https://api.archbee.com/api/optimize/-kIqrMCOJgmgBmRpzgKo2/FW54_bcuC14BnlbgT4NYd_image.png" size="62" width="582" height="527" position="center" showCaption="false"}
:::

:::hint{type="danger"}
<font color="#eb144c">**API response when error occurred (Example\: uwi of upserted daily production doesn't exist in wellheader)**</font>



![](https://api.archbee.com/api/optimize/-kIqrMCOJgmgBmRpzgKo2/DKukdrYbo7_7ziSw9VO7n_image.png)
:::

## 3.2 Insert a History of Daily Production (Multiple Records)

### 3.2.1 Daily Production Input Preparation

a)  Import daily production from source data (.xlsx data demonstrated in this tutorial)

```python
## Import daily production from source data
dailyproduction = pd.read_excel(r'...\ExampleData.xlsx',sheet_name='dailyProduction')
```

b) Input data preparation - change field names and data type to be consistent with data schema

```python
## Convert NaN to Nonetype
dailyproduction.replace({np.nan: None},inplace=True) 

## Maximum 30 characters allowed for 'downtimecode'
dailyproduction['downtimeCode'] = dailyproduction['downtimeCode'].str[:30]

## Convert datetime to UTC
dailyproduction['date'] = pd.to_datetime(dailyproduction['date'],utc=True)

## Convert 'uwi' to str type
dailyproduction['uwi'] = dailyproduction['uwi'].apply(str)

## Convert source data field names in camel case to snake case
for name in dailyproduction.columns:
    dailyproduction.rename(columns={name : filed_name_conversion(name)},inplace=True)

## Convert input data to list form
daily_production = dailyproduction.to_dict(orient = 'records')
```

### 3.2.2 Basic Method of upserting multiple records

:::hint{type="info"}
<u>**Batch Processing:**</u>

In order to reduce the payload, it is recommended to upsert the daily production of each well in batches
:::

```python
## Create a function to divide the daily production into batches for each well
def batch_file(df,batch_size):
  df_len = len(df)
  batches = [
  df[ix:ix+batch_size]
  for ix in range(0, df_len, batch_size)]
  return batches
```

```python
for uwi in tqdm(dailyproduction['uwi'].unique()):
    uwi_production = list(filter(lambda daily_production: daily_production['uwi'] == uwi, daily_production))
    batches = batch_file(uwi_production,1500)
    for batch in batches:
        try:
            daily_production_api = api_client.daily_production_api()
            response = daily_production_api.upsert_daily(batch)
        except ApiException as e:
            print("Exception when calling DailyProductionApi->upsert_daily: %s\n" % e)
```

:::hint{type="danger"}
<font color="#eb144c">**Potential Error\: API response will return 400 error code when uwi of daily production doesn't exist in database**
</font>

![](https://api.archbee.com/api/optimize/-kIqrMCOJgmgBmRpzgKo2/0lqzoCBWvrCIE2kJLN7Wj_image.png)
:::

## 3.3 Get a Daily Production History

```python
## Get daily production 
try:
    daily_production_api = api_client.daily_production_api()
    ## Query daily production of uwi: 'well_uwi'
    response = daily_production_api.get_daily('well_uwi')
    print(response) 
except ApiException as e:
    print("Exception when calling DailyProductionApi->get_daily: %s\n" % e)
```

## 3.4 Remove a Daily Production Record

```python
## Delete daily production 
try:
    daily_production_api = api_client.daily_production_api()
    ## Define datetime range for daily production (optional)
    start_date = datetime.datetime(1900, 9, 21, 20, 33, 4, 303441, tzinfo=tzutc()) 
    end_date = datetime.datetime(2022, 9, 21, 20, 33, 4, 303441, tzinfo=tzutc())
    response = daily_production_api.delete_daily(uwi,start_date = start_date,end_date = end_date)
    print(response)
except ApiException as e:
    print("Exception when calling DailyProductionApi->delete_daily: %s\n" % e)
```

:::hint{type="success"}
**If daily production has been successfully deleted, API response will return number of records which was just deleted.**


(In this example 658 records were deleted)

![](https://api.archbee.com/api/optimize/-kIqrMCOJgmgBmRpzgKo2/BiV_UavZIyThC00zytyX2_image.png)
:::



:::hint{type="danger"}
<font color="#eb144c">**If uwi doesn't exist in database, API response will return 400 error code.**</font>



![](https://api.archbee.com/api/optimize/-kIqrMCOJgmgBmRpzgKo2/o0sdIKPNgdnlTIjXMFff5_image.png)
:::

# 4. Wellbore

## 4.1 Upsert a wellbore record

a) Data Preparation (Data import and format conversion)

```python
## Import wellbore data
wellbore = pd.read_excel(r'...\DataPlatformAPITemplate_By_SourceId.xlsx',sheet_name='wellbore')

## Convert source data field names in camel case to snake case
for name in wellbore.columns:
    wellbore.rename(columns={name : filed_name_conversion(name)},inplace=True)

## Replace Nan with None
wellbore.replace({np.nan: None},inplace=True) 

## Convert wellbore data to list format
wellbore_input = wellbore.to_dict(orient='records')
```

b) Upsert wellbore record

```python
# Batch Upsert
batches = batch_file(wellbore,100)

for batch in tqdm(batches):
    wellbore_input = batch.to_dict(orient='records')
    try:
        wellbore_api = api_client.wellbore_api()
        response = wellbore_api.upsert_wellbores(wellbore_input)
        #print(response)
    except ApiException as e:
        print("Exception when calling WellboreApi->upsert_wellbores: %s\n" % e)
```

## 4.2 Get a wellbore record

### 4.2.1 Get Wellbore Record by Source Well ID

```python
## Define Source Well ID to be queried 
source_well_id = 'testSourceWellId'
## Get Wellbore By Well
try:
    wellbore_api = api_client.wellbore_api()
    response = wellbore_api.get_wellbores_by_source_well(source_well_id)
    print(response)
except ApiException as e:
    print("Exception when calling WellboreApi->get_wellbores_by_source_well: %s\n" % e)
```

### 4.2.2 Get Wellbore Record by Source Well ID and Source Wellbore ID

```python
## Define Source Well ID and Source Wellbore ID to be queried
source_well_id = 'testSourceWellId'
source_wellbore_id = 'testSourceWellboreId'
## Get Wellbore By Source
try:
    wellbore_api = api_client.wellbore_api()
    response = wellbore_api.get_wellbor_by_source(source_well_id,source_wellbore_id)
    print(response)
except ApiException as e:
    print("Exception when calling WellboreApi->get_wellbore_by_source: %s\n" % e)
```

### 4.3 Delete a wellbore record by Source Well ID

```python
## Define Source ID to be queried
source_well_id = 'testSourceWellId'
## Delete Wellbore
try:
    wellbore_api = api_client.wellbore_api()
    response = wellbore_api.delete_wellbore_by_source_well(source_well_id)
    print(response)
except ApiException as e:
    print("Exception when calling WellboreApi->delete_wellbore_by_source_well: %s\n" % e)
```

### 4.4 Delete a wellbore record by Source Well ID and Source Wellbore ID

```python
## Define Source Well ID and Source Wellbore ID to be queried
source_well_id = 'testSourceWellId'
source_wellbore_id = 'testSourceWellboreId'
## Delete Wellbore
try:
    wellbore_api = api_client.wellbore_api()
    response = wellbore_api.delete_wellbore_by_source(source_well_id,source_wellbore_id)
    print(response)
except ApiException as e:
    print("Exception when calling WellboreApi->delete_wellbore_by_source: %s\n" % e)
```

# 5 Deviation Survey

## 5.1 Upsert deviation survey

a) Data preparation (Data import and formation conversion)

```python
## Import deviation survey data
deviationsurvey = pd.read_excel(r'...\DataPlatformAPITemplate_By_SourceId.xlsx',sheet_name='wellboreDeviationSurvey')  

## Convert source data field names in camel case to snake case
for name in deviationsurvey.columns:
    deviationsurvey.rename(columns={name : filed_name_conversion(name)},inplace=True)

## Replace NaN with None
deviationsurvey.replace({np.nan: None},inplace=True) 

## Convert survey data to list
deviationsurveyinput = deviationsurvey.to_dict(orient='records')
```

b) Upsert deviation survey

```python
## Upsert Survey
try:
    deviation_survey_api = api_client.deviation_survey_api()
    response = deviation_survey_api.upsert_deviation_surveys(deviationsurveyinput)
    print(response)
except ApiException as e:
    print("Exception when calling DeviationSurveyApi->upsert_deviation_surveys: %s\n" % e)
```

## 5.2 Get Deviation Survey

### 5.2.1 Get Deviation Survey by Source Well ID

```python
## Define Source ID to be queried
source_well_id = 'testSourceSurveySourceWellID'
## Get Survey
try:
    deviation_survey_api = api_client.deviation_survey_api()
    response = deviation_survey_api.get_deviation_survey_by_source_well(source_well_id)
    print(response)
except ApiException as e:
    print("Exception when calling DeviationDurveyApi->get_deviation_survey_by_source_well: %s\n" % e)
```

### 5.2.2 Get Deviation Survey by Source Well ID and Source Wellbore ID

```python
## Define Source Well ID and Source Wellbore ID to be queried
source_well_id = 'testSourceSurveySourceWellID'
source_wellbore_id = 'testSourceSurveySourceWellboreID'
## Get Survey
try:
    deviation_survey_api = api_client.deviation_survey_api()
    response = deviation_survey_api.get_deviation_survey_by_source_wellbore(source_well_id,source_wellbore_id)
    print(response)
except ApiException as e:
    print("Exception when calling DeviationDurveyApi->get_deviation_survey_by_source_wellbore: %s\n" % e)
```

### 5.2.3 Get Deviation Survey by Source

```python
## Define Source Wellbore ID to be queried
source_well_id = 'testSourceSurveySourceWellID'
source_wellbore_id = 'testSourceSurveySourceWellboreID'
source_id = 'testSourceSurveySourceID'
## Get Survey
try:
    deviation_survey_api = api_client.deviation_survey_api()
    response = deviation_survey_api.get_deviation_survey_by_source(source_well_id,source_wellbore_id,source_id)
    print(response)
except ApiException as e:
    print("Exception when calling DeviationDurveyApi->get_deviation_survey_by_source: %s\n" % e)
```

## 5.3 Delete Deviation Survey

### 5.3.1 Delete Deviation Survey by Source Well ID

```python
## Define source well id to be queried
source_well_id = 'testSourceSurveySourceWellID'
## Delete Survey
try:
    deviation_survey_api = api_client.deviation_survey_api()
    response = deviation_survey_api.delete_deviation_surveys_by_source_well(source_well_id)
    print(response)
except ApiException as e:
    print("Exception when calling DeviationDurveyApi->delete_deviation_surveys_by_source_well: %s\n" % e)
```

### 5.3.2 Delete Deviation Survey by Source Well ID and Source Wellbore ID

```python
## Define source well ID and source wellbore ID to be queried
source_well_id = 'testSourceSurveySourceWellID'
source_wellbore_id = 'testSourceSurveySourceWellboreID'
## Delete Survey
try:
    deviation_survey_api = api_client.deviation_survey_api()
    response = deviation_survey_api.delete_deviation_surveys_by_source_wellbore(source_well_id,source_wellbore_id)
    print(response)
except ApiException as e:
    print("Exception when calling DeviationDurveyApi->delete_deviation_surveys_by_source_wellbore: %s\n" % e)
```

### 5.3.3 Delete Deviation Survey by Source

```python
## Define source well ID and source wellbore ID to be queried
source_well_id = 'testSourceSurveySourceWellID'
source_wellbore_id = 'testSourceSurveySourceWellboreID'
source_id = 'testSourceSurveySourceID'
## Delete Survey
try:
    deviation_survey_api = api_client.deviation_survey_api()
    response = deviation_survey_api.delete_deviation_survey_by_source(source_well_id,source_wellbore_id,source_id)
    print(response)
except ApiException as e:
    print("Exception when calling DeviationDurveyApi->delete_deviation_survey_by_source: %s\n" % e)
```

# 6 Casing

## 6.1 Upsert Casing Records

a) Data Preparation (Data import and data format conversion)

```python
## Import casing data from local excel file
casing = pd.read_excel(r'...\DataPlatformAPITemplate_By_SourceId.xlsx',sheet_name='wellboreCasing') 

## Convert source data field names in camel case to snake case
for name in casing.columns:
    casing.rename(columns={name : filed_name_conversion(name)},inplace=True)

## Replace NaN with None
casing.replace({np.nan: None},inplace=True) 

## Convert Run Date data type
casing['run_date'] = pd.to_datetime(casing['run_date'],utc=True)

## Convert casing data to list
casing_input = casing.to_dict(orient='records')
```

b) Upsert casing data

```python
## Upsert Casing
try:
    casing_api = api_client.wellbore_casing_api()
    response = casing_api.upsert_casing(casing_input)
    print(response)
except ApiException as e:
    print("Exception when calling CasginApi->upsert_casing: %s\n" % e)
```

## 6.2 Get casing record

### 6.2.1 Get Casing Record by Source Well ID

```python
## Define the source well ID to be queried
source_well_id = 'sourceWellID'
## Get Casing Record by Source ID
try:
    casing_api = api_client.wellbore_casing_api()
    response = casing_api.get_casing_by_source_well(source_well_id)
    print(response)
except ApiException as e:
    print("Exception when calling CasingApi->get_casing_by_source_well: %s\n" % e)
```

### 6.2.2 Get Casing Record by Source Well ID and Source Wellbore ID

```python
## Define the source ID to be queried
source_well_id = 'sourceWellID'
source_wellbore_id = 'sourceWellboreID'
## Get Casing
try:
    casing_api = api_client.wellbore_casing_api()
    response = casing_api.get_casing_by_source_wellbore(source_well_id,source_wellbore_id)
    print(response)
except ApiException as e:
    print("Exception when calling CasingApi->get_casing_by_source_wellbore: %s\n" % e)
```

### 6.2.3 Get Casing Record by Source

```python
## Define the source ID to be queried
source_well_id = 'sourceWellID'
source_wellbore_id = 'sourceWellboreID'
source_id = 'sourceID'
## Get Casing
try:
    casing_api = api_client.wellbore_casing_api()
    response = casing_api.get_casing_by_source(source_well_id,source_wellbore_id,source_id)
    print(response)
except ApiException as e:
    print("Exception when calling CasingApi->get_casing_by_source: %s\n" % e)
```

## 6.3 Delete Casing Records

### 6.3.1 Delete Casing Records by Source Well ID

```python
## Define source ID to be deleted
source_well_id = 'sourceWellID'
## Delete Casing
try:
    casing_api = api_client.wellbore_casing_api()
    response = casing_api.delete_casing_by_source_well(source_well_id)
    print(response)
except ApiException as e:
    print("Exception when calling CasingApi->delete_casing_by_source_well: %s\n" % e)
```

### 6.3.2 Delete Casing Records by Source Wellbore ID

```python
## Define source ID to be deleted
source_well_id = 'sourceWellID'
source_wellbore_id = 'sourceWellboreID'
## Delete Casing
try:
    casing_api = api_client.wellbore_casing_api()
    response = casing_api.delete_casing_by_source_wellbore(source_well_id,source_wellbore_id)
    print(response)
except ApiException as e:
    print("Exception when calling CasingApi->delete_casing_by_source_wellbore: %s\n" % e)
```

### 6.3.2 Delete Casing Records by Source

```python
## Define source ID to be deleted
source_well_id = 'sourceWellID'
source_wellbore_id = 'sourceWellboreID'
source_id = 'sourceID'
## Delete Casing
try:
    casing_api = api_client.wellbore_casing_api()
    response = casing_api.delete_casing_by_source(source_well_id,source_wellbore_id,source_id)
    print(response)
except ApiException as e:
    print("Exception when calling CasingApi->delete_casing_by_source: %s\n" % e)
```

# 7 Tubing

## 7.1 Upsert Tubing Records

a) Data preparation (Data import and data format conversion)

```python
## Import tubing data from local excel file
tubing = pd.read_excel(r'...\DataPlatformAPITemplate_By_SourceId.xlsx',sheet_name='wellboreTubing') 

## Convert source data field names in camel case to snake case
for name in tubing.columns:
    tubing.rename(columns={name : filed_name_conversion(name)},inplace=True)

## Replace NaN with None
tubing.replace({np.nan: None},inplace=True) 

## Convert tubing data to list
tubing_input = tubing.to_dict(orient='records')
```

b) Upsert tubing records

```python
## Upsert Tubing
try:
    tubing_api = api_client.wellbore_tubing_api()
    response = tubing_api.upsert_tubing(tubing_input)
    print(response)
except ApiException as e:
    print("Exception when calling TubingApi->upsert_tubing: %s\n" % e)
```

## 7.2 Get Tubing Records

### 7.2.1 Get Tubing Records by Source Well ID

```python
## Define the source ID to be queried
source_well_id = 'sourceWellID'
## Get Tubing Record by Source ID
try:
    tubing_api = api_client.wellbore_tubing_api()
    response = tubing_api.get_tubing_for_source_well(source_well_id)
    print(response)
except ApiException as e:
    print("Exception when calling TubingApi->get_tubing_for_source_well: %s\n" % e)
```

### 7.2.2 Get Tubing Records by Source Well ID and Source Wellbore ID

```python
## Define the source well ID to be queried
source_well_id = 'sourceWellID'
source_wellbore_id = 'sourceWellboreID'
## Get Tubing Record by source well ID
try:
    tubing_api = api_client.wellbore_tubing_api()
    response = tubing_api.get_tubing_for_source_wellbore(source_well_id,source_wellbore_id)
    print(response)
except ApiException as e:
    print("Exception when calling TubingApi->get_tubing_for_source_wellbore: %s\n" % e)
```

### 7.2.3 Get Tubing Records by Source

```python
## Define the source well ID to be queried
source_well_id = 'sourceWellID'
source_wellbore_id = 'sourceWellboreID'
source_id = 'sourceID'
## Get Tubing Record by Source Wellbore ID
try:
    tubing_api = api_client.wellbore_tubing_api()
    response = tubing_api.get_tubing_by_source(source_well_id,source_wellbore_id,source_id)
    print(response)
except ApiException as e:
    print("Exception when calling TubingApi->get_tubing_by_source: %s\n" % e)
```

## 7.3 Delete Tubing Records

### 7.3.1 Delete Tubing Records by Source Well ID

```python
## Specify source ID to be deleted
source_well_id = 'sourceWellID'
## Delete Tubing
try:
    wellbore_tubing_api = api_client.wellbore_tubing_api()
    response = wellbore_tubing_api.delete_tubing_by_source_well(source_well_id)
(source_well_id)
    print(response)
except ApiException as e:
    print("Exception when calling DailyProductionApi->delete_tubing_by_source_well: %s\n" % e)
```

### 7.3.2 Delete Tubing Records by Source Well ID and Source Wellbore ID

```python
## Specify source ID to be deleted
source_well_id = 'sourceWellID'
source_wellbore_id = 'sourceWellboreID'
## Delete Tubing
try:
    wellbore_tubing_api = api_client.wellbore_tubing_api()
    response = wellbore_tubing_api.delete_tubing_by_source_wellbore(source_well_id,source_wellbore_id)
    print(response)
except ApiException as e:
    print("Exception when calling DailyProductionApi->delete_tubing_by_source_wellbore: %s\n" % e)
```

### 7.3.3 Delete Tubing Records by Source

```python
## Specify source ID to be deleted
source_well_id = 'sourceWellID'
source_wellbore_id = 'sourceWellboreID'
source_id = 'sourceID'
## Delete Tubing
try:
    wellbore_tubing_api = api_client.wellbore_tubing_api()
    response = wellbore_tubing_api.delete_tubing_by_source(source_well_id,source_wellbore_id,source_id)
    print(response)
except ApiException as e:
    print("Exception when calling DailyProductionApi->delete_tubing_by_source: %s\n" % e)
```

# 8 Formation

## 8.1 Upsert Formation

a) Data Preparation (Data import and formation conversion)

```python
## Import Formation Data from excel file
formation = pd.read_excel(r'...\DataPlatformAPITemplate_By_SourceId.xlsx',sheet_name='wellboreFormation')

## Replace NaN with None
formation.replace({np.nan: None},inplace=True) 

## Convert source data field names in camel case to snake case
for name in formation.columns:
    formation.rename(columns={name : filed_name_conversion(name)},inplace=True)
    
## Change Attribute names
formation.rename(columns={"fluid_comingled_g_o_r":"fluid_comingled_gor","fluid_molar_frac_c_o2":"fluid_molar_frac_co2"},inplace = True)

## Convert formation data to list
formation_input = formation.to_dict(orient='records')

```

b) Upsert formation

```python
## Upsert Formation
try:
    formation_property_api = api_client.wellbore_formation_api()
    response = formation_property_api.upsert_formations(formation_input)
    print(response)
except ApiException as e:
    print("Exception when calling FormationApi->upsert_formations: %s\n" % e)
```

## 8.2 Get formation

### 8.2.1 Get formation by source well ID

```python
## Specify Source Wellbore ID
source_well_id = 'sourceWellID'
## Get Formation
try:
    formation_property_api = api_client.wellbore_formation_api()
    response = formation_property_api.get_formations_by_well(source_well_id)
    print(response)
except ApiException as e:
    print("Exception when calling FormationApi->get_formations_by_well: %s\n" % e)
```

### 8.2.2 Get formation by source wellbore ID

```python
## Specify Source Wellbore ID
source_well_id = 'sourceWellID'
source_wellbore_id = 'sourceWellboreID'
## Get Formation
try:
    formation_property_api = api_client.wellbore_formation_api()
    response = formation_property_api.get_formations_by_wellbore(source_well_id,source_wellbore_id)
    print(response)
except ApiException as e:
    print("Exception when calling FormationApi->get_formations_by_wellbore: %s\n" % e)
```

## 8.3 Delete formation

### 8.3.1 Delete formation by source well ID

```python
## Specify Source Wellbore ID
source_well_id = 'sourceWellID'
## Delete Formation
try:
    formation_property_api = api_client.wellbore_formation_api()
    response = formation_property_api.delete_formations_by_source_well(source_well_id)
    print(response)
except ApiException as e:
    print("Exception when calling FormationApi->delete_formations_by_source_well: %s\n" % e)
```

### 8.3.2 Delete formation by source wellbore ID

```python
## Specify Source Wellbore ID
source_well_id = 'sourceWellID'
source_wellbore_id = 'sourceWellboreID'
## Delete Formation
try:
    formation_property_api = api_client.wellbore_formation_api()
    response = formation_property_api.delete_formation_by_source_wellbore(source_well_id,source_wellbore_id)
    print(response)
except ApiException as e:
    print("Exception when calling FormationApi->delete_formation_by_source_wellbore: %s\n" % e)
```

