Examples
First, get an instance of the ThreediApi
:
from threedi_api_client import ThreediApi
env_file = "<path>/.env"
api = ThreediApi(env_file)
Now you can easily make use of the api models generated by the openapi
client. Let us create a simulation. We will use a Simulation
model
instance to pass data to the API. Some fields are optional but we do
need to specify:
the unique organisation ID we want to run the simulation for
the model schema to use for the simulation by referring to the id of the threedimodel resource
datetime (in ISO 8601 (UTC) format) for the simulation start
either a end datetime (also in ISO 8601 (UTC) format) or the duration parameter in seconds
If you do not know the unique ID for your organisation you can make use of the API to request it.
api.organisations_list(name__istartswith="nelen")
{'count': 2,
'next': None,
'previous': None,
'results': [{'name': 'Nelen & Schuurmans',
'unique_id': 'b8f91de705774fe8a4e7cb2d9413bf5c',
'url': 'https://api.3di.live/v3.0/organisations/61f5a464c35044c19bc7d4b42d7f58cb/'},
{'name': 'Nelen & Schuurmans alleen werknemers',
'unique_id': 'e82c74c4fb5846b3ae990c0cc69130c6',
'url': 'https://api.3di.live/v3.0/organisations/cde64bc165644be9af023fc4fa18d098/'}]}
Now we can create the Simulation
model instance.
from threedi_api_client.openapi import Simulation
# start date will be a datetime object
from datetime import datetime
my_extreme_event_simulation = Simulation(
name="my extreme event", # (optional)
threedimodel=1, # The model schema to use for the simulation by referring to the id of the threedimodel resource
organisation='b8f91de705774fe8a4e7cb2d9413bf5c',
start_datetime=datetime.utcnow(), # accepts datetime instance
duration=7200 # in secs ==> 2 hours
)
The simulations_create
method allows you to create a new Simulation resource.
api.simulations_create(my_extreme_event_simulation)
{'created': 'now',
'duration': 7200,
'duration_humanized': '2 hours, 0 minutes, 0 seconds',
'end_datetime': '2019-11-04T16:19:46Z',
'id': 631,
'name': 'my extreme event',
'organisation': 'b8f91de705774fe8a4e7cb2d9413bf5c',
'organisation_name': 'Nelen & Schuurmans',
'slug': 'my-extreme-event-378f55a5-06df-4021-8fb6-65bbb70519dc',
'start_datetime': '2019-11-04T14:19:46Z',
'threedimodel': 'https://api.3di.live/v3.0/threedimodels/1/',
'threedimodel_id': '1',
'url': 'https://api.3di.live/v3.0/simulations/631/',
'user': 'lars.claussen',
'uuid': '378f55a5-06df-4021-8fb6-65bbb70519dc'}
Simulations allow for adding an arbitrary number of events to them like
rain events
sources and sinks
initial conditions
laterals
saved states
structure controls
All of them have their own openapi client model. To add a constant rain event to the simulation you would do the following.
from threedi_api_client.openapi import ConstantRain
const_rain = ConstantRain(
simulation=631, # the ID we got from our create call above
offset=60, # let the rain start after one minute
duration=5000, # let the rain last for 5000 secs
value=0.0006, # not too extreme after all...;-)
units="m/s" # the only unit supported for now
)
api.simulations_events_rain_constant_create(631, const_rain)
{'duration': 5000,
'offset': 60,
'simulation': 'https://api.3di.live/v3.0/simulations/631/',
'units': 'm/s',
'url': 'https://api.3di.live/v3.0/simulations/631/events/rain/constant/17/',
'value': 0.0006}
If you want to see which events are defined on a given simulation
api.simulations_events(631)
{'boundaries': None,
'breach': [],
'filerasterrain': [],
'filerastersourcessinks': [],
'filetimeseriesrain': [],
'filetimeseriessourcessinks': [],
'initial_groundwaterlevel': None,
'initial_onedwaterlevel': None,
'initial_onedwaterlevelpredefined': None,
'initial_savedstate': None,
'initial_twodwaterlevel': None,
'laterals': [],
'lizardrasterrain': [],
'lizardrastersourcessinks': [],
'lizardtimeseriesrain': [],
'lizardtimeseriessourcessinks': [],
'savedstates': [],
'timedstructurecontrol': [],
'timeseriesrain': [{'constant': True,
'duration': 5000,
'interpolate': False,
'offset': 60,
'simulation': 'https://api.3di.live/v3.0/simulations/631/',
'units': 'm/s',
'url': 'https://api.3di.live/v3.0/simulations/631/events/rain/timeseries/17/',
'values': [[0.0, 0.0006], [5000.0, 0.0]]}],
'timeseriessourcessinks': []}
Advanced usage
See below for an example of uploading a rain raster.
from pathlib import Path
from threedi_api_client.files import upload_file
simulation_pk = 1
filename = 'bergermeer_rasters_from_geotiffs.nc'
local_file_path = Path('./data/bergermeer_rasters_from_geotiffs.nc')
# Create rain raster upload resource in API
# returns a 'file_upload' instance containing a
# put_url property which is the URL to the object
# storage object to be uploaded with an HTTP PUT requests.
file_upload = api.simulations_events_rain_rasters_upload(
filename, simulation_pk)
# Upload the file
upload_file(file_upload.put_url, local_file_path)
Async client
This project also provides an asynchronous api client. To use
the async-client make sure you install the optional dependencies using
pip install threedi-api-client[aio]
and then import from the aio
submodule. The async-client works the same as the synchronous client,
except all api calls are coroutines.
For example, to asynchronously request files from the api:
import asyncio
from threedi_api_client.api import ThreediApi
from threedi_api_client.openapi.api.v3_api import V3Api
config = {
"THREEDI_API_HOST": "https://api.3di.live",
"THREEDI_API_PERSONAL_API_TOKEN": "your_personal_api_token_here"
}
async def main():
async with ThreediApi(config=config) as api_client:
api_client: V3Api
print(await api_client.files_list())
if __name__ == '__main__':
asyncio.run(main())