Service API¶
This section describes the interaction with AmbraHealth service API .
At the footer of this document, the current version of the AmbraHealth API is specified. Make sure that the current version of ambra-sdk is not lower.
>>> from ambra_sdk import API_VERSION
>>> print(API_VERSION)
LBL0022 v47.0 2021-06-30
In ambra-sdk all service api methods have the form api.CommandNamespace.command.{get(),all() or first()}.
You can find a description of all existing methods in the Service API reference.
Query objects¶
All Service methods returns Query object for preparing data request. For example:
>>> query_object = api.Study.list()
>>> print(type(query_object))
<class 'ambra_sdk.service.query.query.QueryOPSF'>
OSF in query type name means that you can use only, sort_by, and filter_by methods. P means that this is a query for results with pagination. So you can use all or first method on this object.
Inspect your query object to get information about request:
query_object.url
query_object.full_url
query_object.request_args
Execute this query using first() or all() method (api.Study.list() is query for request multiple results):
some_study = query_object.first()
for study in query_object.all():
do_somethingwith(study)
Another example is a query for requesting one result:
study_get_query = api \
.Study \
.get(uuid=uuid)
For requesting study data using this query, we use get() method:
some_study = study_get_query.get()
Only¶
All ambra-sdk service api methods support the only method to limit the set of requested fields. Using this method is slightly different for different types of requests.
For example, let’s imagine that we are using a method for requesting only one Field in the result.
In this case, we pass to the query.only()
function to specify the required field or list of required fields:
user_query = api.User.get().only(['email', 'name'])
# for request only one field
user_query = api.User.get().only('email')
user = user_query.get()
assert list(user.keys()) == ['email']
Another use case: When preparing a request to get multiple results, pass a dict in the query.only()
function where the key is the request object name and the value is a list of requested fields. For example:
account_request = api.Account \
.list() \
.only({'account': ['name', 'uuid']})
account = account_request.first()
assert set(account.keys()) == set(['name', 'uuid'])
An easier way to do this is using models:
from ambra_sdk.models import Account
account_request = api.Account \
.list() \
.only([Account.name, Account.uuid])
account = account_request.first()
Pagination¶
When querying methods that return multiple results, ambra-sdk supports an automatic pagination of server requests.
Suppose we have a study list query:
study_list_query = api.Study.list()
Then let’s create study list iterator using the all() method:
study_list_iterator = study_list_query.all()
In code:
for study in study_list_iterator:
do_something_with(study)
study_list_iterator requests the 100 studies from AmbraHalth API, yields the results in the loop, and then requests the next 100 results.
In the query level, one can change the number of rows in one pagination page:
study_list_query = api.Study.list().set_rows_in_page(20)
Set a range of requested results: For example, to skip the first 5 results and take the next 10 items:
for study in study_list_iterator \
.set_range(min_row=5, max_row=15):
do_something_with(study)
Slices can also be used to achieve the same result:
for study in study_list_iterator[5:15]:
do_something_with(study)
Note
At this moment, ambra-sdk does not support stepping or reverse stepping through multiple results:
# This code is invalid
for study in study_list_iterator[5:15:2]:
do_something_with(study)
Sorting¶
Some service api methods in ambra-sdk support sorting: To top sort, pass Sorter object to sort_by query method:
from ambra_sdk.service.sorting import Sorter, SortingOrder
sorter = Sorter(
field_name='patient_name',
order=SortingOrder.ascending,
)
study_query = api \
.Study \
.list() \
.sort_by(sorter)
Using models:
from ambra_sdk.models import Study
study_query = api \
.Study \
.list() \
.sort_by(Study.patient_name.asc())
Filtering¶
Some service api methods in ambra-sdk support filtering. To filter results, pass Filter object to filter_by query method:
from ambra_sdk.service.filtering import Filter
from ambra_sdk.service.filtering import FilterCondition
account_name = 'SOME_ACCOUNT_NAME'
account = api.Account \
.list() \
.filter_by(
Filter(
'name',
FilterCondition.equals,
account_name,
)
).first()
assert account.name == account_name
Using models:
from ambra_sdk.models import Account
account = api.Account \
.list() \
.filter_by(Account.name==account_name) \
.first()
Special arguments (customfields)¶
Some of AmbraHealth API methods accept special parameters.
For example, add a method in the study namespace has a customfield-{UUID} argument. To use this argument, execute Study.add() method with customfield_param argument, where customfield_param is a dict of {UUID: value}:
api.Study.add(
...,
customfield_param={
customfield_uid1: customfield_value1,
customfield_uid2: customfield_value2,
},
)
Study customfields filtering¶
api.Study.get()
and api.Study.list()
methods return study data.
If a given study has customfields attributes, one can use filtering to retrieve specific fields. For example:
study = api \
.Study \
.get(uuid=uuid) \
.get()
# Or
study = api \
.Study \
.list() \
.first()
filtered_customfields = study \
.customfields \
.filter_by({'name': 'some_name'})
for customfield in filtered_customfields:
print(customfield)
Use get_by_name or get_by_uuid functions to get only the first filtered result:
customfield = study.customfields.get_by_name('some_name')
customfield = study.customfields.get_by_uuid('some_uuid')
Retries¶
SDK service namespace supports a retry mechanism. By default, ambra-sdk sets specific retry settings. In some cases, one can define custom settings for specific methods. The example below shows how to do this:
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util import Retry
max_retries = Retry(
total=10,
backoff_factor=0.2,
method_whitelist=['GET', 'POST'],
)
adapter = HTTPAdapter(max_retries=max_retries)
some_method_url = api.Study.list().full_url
api.service_session.mount(some_method_url, adapter)
Headers¶
You can setup some default headers for service session (using service_default_headers property) or for both service and storage sessions (using default_headers property):
api.default_headers['Golbal-header'] = 'value'
api.service_default_headers['Service-pecific-header'] = 'value'
You can setup headers for some special requests:
query = api.User.get()
query.request_args.headers = {'Special-request-header': 'value'}
user = query.get()
For setup headers for login call (get new sid) you can use special_headers_for_login:
api = Api.with_creds(
url,
username,
password,
special_headers_for_login = {
'Special-header-for-login': 'value',
},
)