<jupyter_start><jupyter_text>Oceanbolt Python SDK Lesson 6: Port Distances at ScaleFor certain maritime analyses, you will require a distance parameter. E.g. to calculate voyage times or estimate bunker consumption. It is often a tedious process to access many port to port distances or calculating the distance from a current position of a vessel to a port. We have made this easy by exposing our proprietary Oceanbolt Port Distance calculator. In this lesson, we will demonstrate how. This is Lesson 6 in our Python learning series. You can find past lessons on our blog: https://www.oceanbolt.com/blog/. You can find the full documentation on our distance calculator here: https://python-sdk.oceanbolt.com/distance_v3/distance.html<jupyter_code># Import the relevant libraries

from oceanbolt.sdk.client import APIClient
from oceanbolt.sdk.distance import DistanceCalculator
import pandas as pd
# Create the base API client using your token. Token can be created in the Oceanbolt App (app.oceanbolt.com)
base_client = APIClient("<token>")<jupyter_output><empty_output><jupyter_text>Port to Port DistanceYou can use the API to get simple port to port distances. You also have the option to include relevant way points for bunker stops etc.<jupyter_code># Connect to the relevant Oceanbolt data endpoints using the base client object, ie: Distance
distance = DistanceCalculator(base_client).distance(
    locations=[
        {"unlocode": "BRSSZ"},
        {"unlocode": "CNQDG"},
    ]
)
print("There are",round(distance),"nautical miles from Santos to Qingdao")<jupyter_output>There are 11211 nautical miles from Santos to Qingdao<jupyter_text>Vessel to Port DistanceSay you wanted instead to find the remaining distance from a particular vessel to a port. As an example, you can find the distance from the vessel MAGIC VELA (IMO: 9473327) to Santos.<jupyter_code>distance = DistanceCalculator(base_client).distance(
    locations=[
        {"imo": 9473327},
        {"unlocode": "BRSSZ"},
    ]
)
print("There are",round(distance),"nautical miles from MAGIC VELA to Santos")<jupyter_output>There are 545 nautical miles from MAGIC VELA to Santos<jupyter_text>This is what the query in our dashboard would look like.  Multiple Ports to PortsIf you have ever had to calculate the distance from multiple ports to multiple ports, you know how tedious this process can be. With our SDK, the process is easy. Simply create a csv file containing all the pairs you want to calculate and process it with the SDK. You can find the steps below. The example shows distances from Santos to 8 different Chinese ports.<jupyter_code># Load CSV into dataframe for easy manipulation
df = pd.read_csv('.../Port_Pairs.csv') #update file path
df
# Loop to add distances into dataframe
port_distances = []

for i in range(len(df['loadport'])):
    distance = DistanceCalculator(base_client).distance(
        locations=[
            {"unlocode": df['loadport'][i]},
            {"unlocode": df['disport'][i]},
        ]
    )
    port_distances.append(distance)

port_distances
# Appending new column to DataFrame
df2 = pd.DataFrame(port_distances)
df['Distance'] = df2
# Export to CSV
df.to_csv(path_or_buf='<path_to_file>') #update file path<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07595325953259532, 'fraction_numerical': 0.008610086100861008, 'mean_word_length': 4.7677304964539005, 'pattern_counts': {'":': 6, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 2, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '511345', 'license': 'MIT', 'n_tokens_mistral': 967, 'n_tokens_neox': 894, 'n_words': 389, 'path': 'docs/examples/21_port_distances.ipynb', 'repo_name': 'oceanbolt/oceanbolt-python-sdk', 'size': '3252'}