Using EMhub Client#
The EMhub REST API is a powerful way for external programs/scripts to
interact with the application and extend its functionalities. In the following section,
there are some examples of how to use the API from Python (via the DataClient
class)
and from JavaScript.
Python#
Interacting with the EMhub REST API basically involves sending requests
to the remote server and processing the returned response. This can be done with
standard Python libraries such as requests
. To facilitate communication, EMhub
provides the emhub.client module to communicate with the server.
Below are some examples of its usage.
Getting Bookings within a time range#
A simple example:
from emhub.client import open_client
with open_client() as dc:
r = dc.request('get_bookings_range',
jsonData={'start': '2023-07-01', 'end': '2023-10-01'})
for b in r.json():
print(b)
Backing-up Forms into a JSON file#
We can fetch all forms from the EMhub server and store them in a JSON file. Similarly, we can read a JSON file and restore the forms into another instance. For example, let’s assume we want to retrieve forms from a remote server and set their values in a development environment.
from emhub.client import DataClient, open_client
# Connect to the remote server and login using some user/password
dc1 = DataClient(server_url='https://emhub.org')
dc.login(user, password)
# Fetch all forms
forms = dc.request('get_forms', jsonData=None).json()
# Dump forms into a JSON file
with open('forms.json', 'w') as f:
formList = [{'id': f['id'],
'name': f['name'],
'definition': f['definition']
}
for f in forms
]
json.dump(formList, f, indent=4)
dc.logout()
# Now connect to another server and load info from JSON file
# Assuming that by default the config are set for the development server:
with open('forms.json') as f:
formList = json.load(f)
with open_client() as dc2:
for form in formList:
print(f">>> Updating form ID={form['id']}\t {form['name']}")
dc.request('update_form', jsonData={'attrs': form})
Disguising the Database#
In this example, imagine that we want to present a running instance of EMhub, but we don’t want to reveal real users’ identities, projects, or session names. We can run a development instance and modify the database to hide the real information.
from emhub.client import DataClient, open_client
from faker import Faker
with open_client() as dc:
# Update user's name and email with fake values
users = dc.request('get_users', jsonData=None).json()
f = Faker()
for u in users:
name = ' '.join(f.name().split(' ')[-2:])
email = name.lower().replace(' ', '.') + '@emhub.org'
attrs = {'id': u['id'], 'name': name, 'email': email}
dc.request('update_user', jsonData={'attrs': attrs})
# Modify sessions to hide real name
sessions = dc.request('get_sessions', jsonData=None).json()
for s in sessions:
dc.update_session({'id': s['id'], 'name': f"S{s['id']:05d}"})
# Hide project's title and make all 'confidential'
projects = dc.request('get_projects', jsonData=None).json()
for p in projects:
# read 'extra' property where 'is_confidential' is stored
extra = dict(p['extra'])
extra['is_confidential'] = True
attrs = {'id': p['id'], 'extra': extra, 'title': 'Project Title'}
dc.request('update_project', jsonData={'attrs': attrs})
Updating Sessions’ Acquisition Info#
In this example, we want to update the Acquisition Info
for sessions where
this information is missing. To do that, we will read the acquisition from the configuration
for each microscope, based on its name. Then, we will need to map the microscope names to
their IDs by reading the resources
from EMhub. Finally, we will iterate over each session
and update the acquisition if necessary.
from emhub.client import open_client
with open_client() as dc:
# Let's get the resources and create a dict mapping resourceId -> resourceName
resources = dc.request('get_resources', jsonData=None).json()
rDict = {r['id']: r['name'] for r in resources}
# Let's get bookings since the resource id comes from the booking
# associated with the session
bookings = dc.request('get_bookings', jsonData=None).json()
# Create a mapping from booking to the resource name: bookingId -> resourceName
brDict = {b['id']: rDict[b['resource_id']] for b in bookings}
# Get sessions and the config related to sessions
sessions = dc.request('get_sessions', jsonData=None).json()
sconfig = dc.get_config('sessions')
for s in sessions:
# Get the resourceName for this session, based on its corresponding booking
rName = brDict[s['booking_id']]
# Get pixel size from the session's acquisition
acq = s['acquisition']
ps = acq.get('pixel_size', None)
# Fix the acquisition if there is no pixel_size (wrong acquisition info)
if ps:
print(f"Session {s['id'] is OK"})
else:
# Let's get the proper acquisition from the config and update the session
newAcq = sconfig['acquisition'][rName]
dc.update_session({'id': s['id'], 'acquisition': newAcq})
Javascript#
The EMhub’s UI also makes use of the REST API from JavaScript code. The JQuery library is used for sending AJAX requests, and there are some helper functions in the EMhub’s JavaScript to make it easier to request data and render HTML based on that.
For example, one can easily display the resulting HTML from a content-query to EMhub in a modal using the following code:
function showRegisterUser() {
var content = get_ajax_content("register_user_form", {});
show_modal_from_ajax('user-modal', content);
} // function showUser
In the previous example, one makes a request with the get_ajax_content
function
and displays a modal with the resulting HTML. In this case, it is a dialog to register
a new user. One can link an action in that modal (usually an HTML form coming from the
server) and send another request with that action to the server. In this case, the action
will be to register the user in the database. This is done in the following function:
function onRegisterUser() {
var roles = [];
// Update user's roles base on checkboxes
$(".user-role:checked").each(function(){
roles.push(this.name.replace('role-', ''));
});
// Create a user's data
var user = {
email: $('#user-email').val(),
name: $('#user-name').val(),
roles: roles,
pi_id: $('#user-pi-select').selectpicker('val')
};
// Send a request to register that user
send_ajax_json(Api.urls.user.register, user, handleUserAjaxDone);
} // function onRegisterUser