Setup¶
Install the Signal Ocean SDK:
pip install signal-ocean
Set your subscription key acquired here: https://apis.signalocean.com/profile
pip install signal-ocean
signal_ocean_api_key = '' #replace with your subscription key
Call the Voyages API¶
The Voyages API retrieves information about vessel voyages.
from signal_ocean import Connection
from signal_ocean.voyages import VoyagesAPI
from signal_ocean.voyages import Vessel, VesselFilter
from signal_ocean.voyages import VesselType, VesselTypeFilter
from signal_ocean.voyages import VesselClass, VesselClassFilter
import pandas as pd
from datetime import date, timedelta
connection = Connection(signal_ocean_api_key)
api = VoyagesAPI(connection)
Get voyages for vessel¶
# get the imo by using the vessel name
vessel = api.get_imos(VesselFilter('Gold Pearl'))[0]
vessel
Vessel(imo=9292187, vessel_name='Gold Pearl')
vessel_voyages = api.get_voyages(imo=vessel.imo)
vessel_voyages_df = pd.DataFrame([v.__dict__ for v in vessel_voyages])
vessel_voyages_df.tail(5)
imo | voyage_number | vessel_type_id | vessel_class_id | vessel_status_id | commercial_operator_id | deleted | events | id | horizon_id | ... | is_implied_by_ais | has_manual_entries | ballast_distance | predicted_ballast_distance | laden_distance | predicted_laden_distance | suez_crossing | panama_crossing | canakkale_crossing | bosporus_crossing | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
63 | 9292187 | 64 | 1 | 84 | 1 | 1684.0 | False | (VoyageEvent(id='I8DC99BSEDABEEE00', port_id=3... | I8DC99BVEDABEEE00 | 1 | ... | None | None | 3831.88 | NaN | 4588.66 | None | None | None | None | None |
64 | 9292187 | 65 | 1 | 84 | 1 | 1684.0 | False | (VoyageEvent(id='I8DC99BSEDB0E0800', port_id=7... | I8DC99BVEDB0E0800 | 1 | ... | None | None | 4612.85 | NaN | 5273.31 | None | None | None | None | None |
65 | 9292187 | 66 | 1 | 84 | 1 | 1684.0 | False | (VoyageEvent(id='I8DC99BSEDB359500', port_id=3... | I8DC99BVEDB359500 | 1 | ... | None | None | 5422.68 | NaN | 4631.81 | None | None | None | None | None |
66 | 9292187 | 67 | 1 | 84 | 1 | NaN | False | (VoyageEvent(id='I8DC99BSEDB5D2200', port_id=7... | I8DC99BVEDB5D2200 | 1 | ... | None | None | 10166.69 | NaN | 8065.06 | None | None | None | None | None |
67 | 9292187 | 68 | 1 | 84 | 1 | NaN | False | (VoyageEvent(id='I8DC99BSEDC4A7000', port_id=3... | I8DC99BVEDC4A7000 | 2 | ... | None | None | 4517.18 | 2439.95 | NaN | None | None | None | None | None |
5 rows × 55 columns
vessel_events_df = pd.DataFrame(e.__dict__ for voyage_events in vessel_voyages_df['events'] for e in voyage_events)
vessel_events_df.tail(5)
id | port_id | voyage_id | event_type | event_horizon | purpose | event_date | arrival_date | sailing_date | latitude | ... | area_idlevel0 | area_name_level0 | area_idlevel1 | area_name_level1 | area_idlevel2 | area_name_level2 | area_idlevel3 | area_name_level3 | low_ais_density | event_details | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
396 | I8DC99BSEDC4A7000 | 3794 | None | VoyageStart | Historical | Start | 2023-08-01 15:40:25+00:00 | NaT | NaT | 2.0407 | ... | 24655 | Singapore / Malaysia | 23 | South East Asia | 99 | Far East | 84 | East | None | None |
397 | I8DC99BTEDC579F00 | 3794 | None | Stop | Historical | Stop | NaT | 2023-08-01 19:45:50+00:00 | 2023-08-04 15:38:45+00:00 | 2.0904 | ... | 24655 | Singapore / Malaysia | 23 | South East Asia | 99 | Far East | 84 | East | None | (VoyageEventDetail(id='I8DC99BLEDC5A4200', eve... |
398 | I8DC99BTEDC5E3680 | 9099 | None | Stop | Historical | Stop | NaT | 2023-08-06 07:52:49+00:00 | 2023-08-07 23:55:12+00:00 | 10.2290 | ... | 24770 | Thailand / Vietnam | 23 | South East Asia | 99 | Far East | 84 | East | None | (VoyageEventDetail(id='I8DC99BLEDC5E3680', eve... |
399 | I8DC99BTEDC64CE00 | 3669 | None | PortCall | Historical | Dry dock | NaT | 2023-08-10 07:58:02+00:00 | 2023-08-27 03:58:36+00:00 | 1.4543 | ... | 24655 | Singapore / Malaysia | 23 | South East Asia | 99 | Far East | 84 | East | None | (VoyageEventDetail(id='I8DC99BLEDC64CE00', eve... |
400 | I8DC99BTEDC71FD00 | 3913 | None | Stop | Future | Stop | NaT | 2023-09-14 02:18:49.611000+00:00 | 2023-09-14 02:18:49.611000+00:00 | -33.9135 | ... | 24776 | South Africa | 25015 | South East Africa | 25018 | Africa | 25027 | Africa | None | () |
5 rows × 26 columns
vessel_event_details_df = pd.DataFrame(e.__dict__ for event_details in vessel_events_df['event_details'] for e in event_details or [])
vessel_event_details_df.tail(5)
id | event_id | event_detail_type | arrival_date | sailing_date | start_time_of_operation | end_time_of_operation | sts_id | geo_asset_id | geo_asset_name | latitude | longitude | other_vessel_imo | other_vessel_name | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
362 | I8DC99BLEDC4A7000 | None | StS | 2023-07-27 23:54:38+00:00 | 2023-08-01 03:46:27+00:00 | 2023-07-29 11:36:58+00:00 | 2023-07-30 06:04:14+00:00 | 8CDA208DC99B8DB90281E082900 | 4195 | Singapore Anchorage | 2.0407 | 104.7849 | 9230880.0 | Timimus |
363 | I8DC99BLEDC579F00 | None | StS | 2023-08-01 03:55:27+00:00 | 2023-08-01 15:40:25+00:00 | 2023-08-01 03:55:27+00:00 | 2023-08-01 06:19:15+00:00 | 8CDA208DC99B8DB924324262180 | 4195 | Singapore Anchorage | 2.0876 | 104.7946 | 9230880.0 | Timimus |
364 | I8DC99BLEDC5A4200 | None | Stop | 2023-08-01 19:45:50+00:00 | 2023-08-04 15:38:45+00:00 | NaT | NaT | None | 4195 | Singapore Anchorage | 2.0904 | 104.7968 | NaN | None |
365 | I8DC99BLEDC5E3680 | None | Stop | 2023-08-06 07:52:49+00:00 | 2023-08-07 23:55:12+00:00 | NaT | NaT | None | 16890 | Ba Son Shipyard | 10.2290 | 107.0480 | NaN | None |
366 | I8DC99BLEDC64CE00 | None | Stop | 2023-08-10 07:58:02+00:00 | 2023-08-27 03:58:36+00:00 | NaT | NaT | None | 5320 | Mmhe Shipyard | 1.4543 | 103.8767 | NaN | None |
Get voyages for vessel class¶
#get vessel class id for vlcc
vc = api.get_vessel_classes(VesselClassFilter('vlcc'))[0]
vlcc_id = vc.vessel_class_id
vlcc_id
84
date_from = date.today() - timedelta(days=30)
recent_vlcc_voyages = api.get_voyages(vessel_class_id=vlcc_id, date_from=date_from)
recent_vlcc_voyages = pd.DataFrame([v.__dict__ for v in recent_vlcc_voyages])
recent_vlcc_voyages.tail(5)
imo | voyage_number | vessel_type_id | vessel_class_id | vessel_status_id | commercial_operator_id | deleted | events | id | horizon_id | ... | is_implied_by_ais | has_manual_entries | ballast_distance | predicted_ballast_distance | laden_distance | predicted_laden_distance | suez_crossing | panama_crossing | canakkale_crossing | bosporus_crossing | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
396 | 9933676 | 6 | 1 | 84 | 1 | 558.0 | False | (VoyageEvent(id='I97936C54SEDC7F2C00', port_id... | I97936C54VEDC7F2C00 | 2 | ... | None | None | 1189.17 | NaN | NaN | NaN | None | None | None | None |
397 | 9937103 | 4 | 1 | 84 | 1 | 1645.0 | False | (VoyageEvent(id='I97A0CF54SEDC4A7000', port_id... | I97A0CF54VEDC4A7000 | 2 | ... | None | None | 6710.89 | NaN | 5.57 | 11604.67 | None | None | None | None |
398 | 9941661 | 6 | 1 | 84 | 1 | 2236.0 | False | (VoyageEvent(id='I97B29D54SEDC71FD00', port_id... | I97B29D54VEDC71FD00 | 2 | ... | True | None | 523.75 | 4578.63 | NaN | 15532.25 | None | None | None | None |
399 | 9941673 | 5 | 1 | 84 | 1 | 2236.0 | False | (VoyageEvent(id='I97B2A954SEDC71FD00', port_id... | I97B2A954VEDC71FD00 | 2 | ... | None | None | 1549.48 | 1077.10 | NaN | NaN | None | None | None | None |
400 | 9943748 | 2 | 1 | 84 | 1 | 1645.0 | False | (VoyageEvent(id='I97BAC454SEDC71FD00', port_id... | I97BAC454VEDC71FD00 | 2 | ... | None | None | 3943.35 | 1486.83 | NaN | 12221.66 | None | None | None | None |
5 rows × 55 columns
Get voyages for vessel in flat format¶
# get the imo by using the vessel name
vessel = api.get_imos(VesselFilter('Gold Pearl'))[0]
vessel
Vessel(imo=9292187, vessel_name='Gold Pearl')
vessel_voyages_flat = api.get_voyages_flat(imo=vessel.imo)
vessel_voyages_df = pd.DataFrame(v.__dict__ for v in vessel_voyages_flat.voyages)
vessel_voyages_df.tail(5)
imo | voyage_number | vessel_type_id | vessel_class_id | vessel_status_id | commercial_operator_id | deleted | events | id | horizon_id | ... | is_implied_by_ais | has_manual_entries | ballast_distance | predicted_ballast_distance | laden_distance | predicted_laden_distance | suez_crossing | panama_crossing | canakkale_crossing | bosporus_crossing | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
63 | 9292187 | 64 | 1 | 84 | 1 | 1684.0 | False | None | I8DC99BVEDABEEE00 | 1 | ... | None | None | 3831.88 | NaN | 4588.66 | None | None | None | None | None |
64 | 9292187 | 65 | 1 | 84 | 1 | 1684.0 | False | None | I8DC99BVEDB0E0800 | 1 | ... | None | None | 4612.85 | NaN | 5273.31 | None | None | None | None | None |
65 | 9292187 | 66 | 1 | 84 | 1 | 1684.0 | False | None | I8DC99BVEDB359500 | 1 | ... | None | None | 5422.68 | NaN | 4631.81 | None | None | None | None | None |
66 | 9292187 | 67 | 1 | 84 | 1 | NaN | False | None | I8DC99BVEDB5D2200 | 1 | ... | None | None | 10166.69 | NaN | 8065.06 | None | None | None | None | None |
67 | 9292187 | 68 | 1 | 84 | 1 | NaN | False | None | I8DC99BVEDC4A7000 | 2 | ... | None | None | 4517.18 | 2439.95 | NaN | None | None | None | None | None |
5 rows × 55 columns
vessel_events_df = pd.DataFrame(v.__dict__ for v in vessel_voyages_flat.events)
vessel_events_df.tail(5)
id | port_id | voyage_id | event_type | event_horizon | purpose | event_date | arrival_date | sailing_date | latitude | ... | area_idlevel0 | area_name_level0 | area_idlevel1 | area_name_level1 | area_idlevel2 | area_name_level2 | area_idlevel3 | area_name_level3 | low_ais_density | event_details | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
396 | I8DC99BSEDC4A7000 | 3794 | I8DC99BVEDC4A7000 | VoyageStart | Historical | Start | 2023-08-01 15:40:25+00:00 | NaT | NaT | 2.0407 | ... | None | None | None | None | None | None | None | None | None | None |
397 | I8DC99BTEDC579F00 | 3794 | I8DC99BVEDC4A7000 | Stop | Historical | Stop | NaT | 2023-08-01 19:45:50+00:00 | 2023-08-04 15:38:45+00:00 | 2.0904 | ... | None | None | None | None | None | None | None | None | None | None |
398 | I8DC99BTEDC5E3680 | 9099 | I8DC99BVEDC4A7000 | Stop | Historical | Stop | NaT | 2023-08-06 07:52:49+00:00 | 2023-08-07 23:55:12+00:00 | 10.2290 | ... | None | None | None | None | None | None | None | None | None | None |
399 | I8DC99BTEDC64CE00 | 3669 | I8DC99BVEDC4A7000 | PortCall | Historical | Dry dock | NaT | 2023-08-10 07:58:02+00:00 | 2023-08-27 03:58:36+00:00 | 1.4543 | ... | None | None | None | None | None | None | None | None | None | None |
400 | I8DC99BTEDC71FD00 | 3913 | I8DC99BVEDC4A7000 | Stop | Future | Stop | NaT | 2023-09-14 02:18:49.611000+00:00 | 2023-09-14 02:18:49.611000+00:00 | -33.9135 | ... | None | None | None | None | None | None | None | None | None | None |
5 rows × 26 columns
vessel_event_details_df = pd.DataFrame(v.__dict__ for v in vessel_voyages_flat.event_details)
vessel_event_details_df.tail(5)
id | event_id | event_detail_type | arrival_date | sailing_date | start_time_of_operation | end_time_of_operation | sts_id | geo_asset_id | geo_asset_name | latitude | longitude | other_vessel_imo | other_vessel_name | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
362 | I8DC99BLEDC4A7000 | I8DC99BTEDC4A7000 | StS | 2023-07-27 23:54:38+00:00 | 2023-08-01 03:46:27+00:00 | 2023-07-29 11:36:58+00:00 | 2023-07-30 06:04:14+00:00 | 8CDA208DC99B8DB90281E082900 | 4195 | Singapore Anchorage | 2.0407 | 104.7849 | 9230880.0 | Timimus |
363 | I8DC99BLEDC579F00 | I8DC99BTEDC4A7000 | StS | 2023-08-01 03:55:27+00:00 | 2023-08-01 15:40:25+00:00 | 2023-08-01 03:55:27+00:00 | 2023-08-01 06:19:15+00:00 | 8CDA208DC99B8DB924324262180 | 4195 | Singapore Anchorage | 2.0876 | 104.7946 | 9230880.0 | Timimus |
364 | I8DC99BLEDC5A4200 | I8DC99BTEDC579F00 | Stop | 2023-08-01 19:45:50+00:00 | 2023-08-04 15:38:45+00:00 | NaT | NaT | None | 4195 | Singapore Anchorage | 2.0904 | 104.7968 | NaN | None |
365 | I8DC99BLEDC5E3680 | I8DC99BTEDC5E3680 | Stop | 2023-08-06 07:52:49+00:00 | 2023-08-07 23:55:12+00:00 | NaT | NaT | None | 16890 | Ba Son Shipyard | 10.2290 | 107.0480 | NaN | None |
366 | I8DC99BLEDC64CE00 | I8DC99BTEDC64CE00 | Stop | 2023-08-10 07:58:02+00:00 | 2023-08-27 03:58:36+00:00 | NaT | NaT | None | 5320 | Mmhe Shipyard | 1.4543 | 103.8767 | NaN | None |
vessel_voyages_geos_df = pd.DataFrame(v.__dict__ for v in vessel_voyages_flat.geos)
vessel_voyages_geos_df.tail(5)
id | name | port_id | port_name | country_id | country | area_idlevel0 | area_name_level0 | area_idlevel1 | area_name_level1 | area_idlevel2 | area_name_level2 | area_idlevel3 | area_name_level3 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
241 | 6163 | Vopak Terminal Europoort | 3689 | Rotterdam | 173 | Netherlands | 24758 | Continent | 25016 | UK Continent | 25025 | Mediterranean / UK Continent | 25028 | West |
242 | 5744 | Euro Tank Terminal B.v. | 3689 | Rotterdam | 173 | Netherlands | 24758 | Continent | 25016 | UK Continent | 25025 | Mediterranean / UK Continent | 25028 | West |
243 | 6361 | Aruba Lightering Zone | 3214 | San Nicolaas | 21 | Aruba | 24746 | Caribs | 9 | Caribs | 25019 | Atlantic America | 25028 | West |
244 | 5745 | Maatschap Europoort Terminal | 3689 | Rotterdam | 173 | Netherlands | 24758 | Continent | 25016 | UK Continent | 25025 | Mediterranean / UK Continent | 25028 | West |
245 | 4177 | Assaluyeh Anchorage | 3538 | Bandar Assaluyeh | 115 | Iran, Islamic Republic of | 24777 | Arabian Gulf | 2 | Arabian Gulf | 89 | Arabian Gulf | 84 | East |
Get voyages for vessel class in the flat format¶
#get vessel class id for vlcc
vc = api.get_vessel_classes(VesselClassFilter('vlcc'))[0]
vlcc_id = vc.vessel_class_id
date_from = date.today() - timedelta(days=30)
recent_vlcc_voyages_flat = api.get_voyages_flat(vessel_class_id=vlcc_id, date_from=date_from)
print('Voyages:', len(recent_vlcc_voyages_flat.voyages))
print('Events:', len(recent_vlcc_voyages_flat.events))
print('EventDetails:', len(recent_vlcc_voyages_flat.event_details))
print('Geos:', len(recent_vlcc_voyages_flat.geos))
Voyages: 401 Events: 1453 EventDetails: 504 Geos: 280
Get voyages for vessel incrementally¶
Initial requests retrieves voyages mathcing the query criteria and a query token that can be used in the subsequent request.
# get the imo by using the vessel name
vessel = api.get_imos(VesselFilter('XIN YONG YANG'))[0]
vessel
Vessel(imo=9416642, vessel_name='Xin Yong Yang')
vessel_voyages, next_request_token = api.get_incremental_voyages(imo=vessel.imo)
len(vessel_voyages)
81
Provided the token retrieved for the previous request, the subsequent request retrieves only voyages that have been updated since the previous request.
incremental_voyages, next_request_token = api.get_incremental_voyages(imo=9416642, incremental_token=next_request_token)
len(incremental_voyages)
0
The retrieved information is used to replace any modify voyages from the dataset. Note that returned voyages marked as deleted are only used to filter out voyages.
updated_voyage_ids = set(v.id for v in incremental_voyages)
vessel_voyages = [v for v in vessel_voyages if v.id not in updated_voyage_ids]
new_vessel_voyages = [v for v in incremental_voyages if not v.deleted]
vessel_voyages = sorted(vessel_voyages + new_vessel_voyages, key= lambda v: v.voyage_number)
len(vessel_voyages)
81
Get voyages for vessel class incrementally¶
Voyages for vessel class are retieved and updated in the same way incrementally.
#get vessel class id for vlcc
vc = api.get_vessel_classes(VesselClassFilter('vlcc'))[0]
vessel_class_id = vc.vessel_class_id
vessel_class_id
84
date_from = date.today() - timedelta(days=30)
voyages, next_request_token = api.get_incremental_voyages(vessel_class_id=vessel_class_id, date_from=date_from)
len(voyages)
401
incremental_voyages, next_request_token = api.get_incremental_voyages(vessel_class_id=vessel_class_id, date_from=date_from, incremental_token=next_request_token)
len(incremental_voyages)
0
updated_voyage_ids = set(v.id for v in incremental_voyages)
voyages = [v for v in voyages if v.id not in updated_voyage_ids and not v.deleted]
new_voyages = [v for v in incremental_voyages if not v.deleted]
voyages = sorted(voyages + new_voyages, key= lambda v: (v.imo, v.voyage_number))
len(voyages)
401
Get voyages for vessel class incrementally in the flat format¶
Voyages may be retrieved and updated incrementally in the flat format.
#get vessel class id for vlcc
vc = api.get_vessel_classes(VesselClassFilter('vlcc'))[0]
vessel_class_id = vc.vessel_class_id
vessel_class_id
84
date_from = date.today() - timedelta(days=30)
voyages_flat, next_request_token = api.get_incremental_voyages_flat(vessel_class_id=vessel_class_id, date_from=date_from)
voyages = voyages_flat.voyages
events = voyages_flat.events
event_details = voyages_flat.event_details
geos = voyages_flat.geos
len(voyages), len(events), len(event_details), len(geos)
(401, 1453, 504, 280)
incremental_voyages_flat, next_request_token = api.get_incremental_voyages_flat(vessel_class_id=vessel_class_id, date_from=date_from, incremental_token=next_request_token)
len(incremental_voyages_flat.voyages)
0
In this case the update step is applied to voyages, events, event details and geos datasets.
updated_voyage_ids = set(v.id for v in incremental_voyages_flat.voyages)
voyages = [v for v in voyages if v.id not in updated_voyage_ids and not v.deleted]
new_voyages = [v for v in incremental_voyages_flat.voyages if not v.deleted]
voyages = sorted(voyages + new_voyages, key= lambda v: (v.imo, v.voyage_number))
len(voyages)
401
updated_event_ids = set(e.id for e in events if e.voyage_id in updated_voyage_ids)
events = [e for e in events if e.id not in updated_event_ids]
events = sorted(events + list(incremental_voyages_flat.events), key= lambda e: e.id)
len(events)
1453
event_details = [e for e in event_details if e.id not in updated_event_ids]
event_details = sorted(event_details + list(incremental_voyages_flat.event_details), key= lambda e: e.id)
len(event_details)
504
updated_geo_ids = set(g.id for g in incremental_voyages_flat.geos)
geos = [g for g in geos if g.id not in updated_geo_ids] + list(incremental_voyages_flat.geos)
len(geos)
280