|
| 1 | +#!/usr/bin/env python |
| 2 | + |
| 3 | +############### |
| 4 | +# DESCRIPTION # |
| 5 | +############## |
| 6 | +# In this script, we will work with date-time data by doing statistics with experiments. Date-time information returned |
| 7 | +# by elabapi-python are in string formats, and we would like to convert the strings to a workable format, |
| 8 | +# so we can programmatically manipulate them for later use. |
| 9 | +############## |
| 10 | + |
| 11 | +# necessary imports for this example |
| 12 | +# datetime module for converting strings to datetime instances |
| 13 | +from datetime import datetime |
| 14 | + |
| 15 | +# the python library for elabftw |
| 16 | +import elabapi_python |
| 17 | + |
| 18 | +# matplot to finally open the plot as an image |
| 19 | +import matplotlib.pyplot as plt |
| 20 | + |
| 21 | +# Pandas library for converting dictionary to dataframe (plotting tools like seaborn knows how to plot dataframes) |
| 22 | +import pandas as pd |
| 23 | + |
| 24 | +# Seaborn to plot the dataframe from pandas |
| 25 | +import seaborn as sns |
| 26 | + |
| 27 | +######################### |
| 28 | +# CONFIG # |
| 29 | +######################### |
| 30 | +# replace with the URL of your instance |
| 31 | +API_HOST_URL = 'https://elab.local:3148/api/v2' |
| 32 | +# replace with your api key |
| 33 | +API_KEY = 'apiKey4Test' |
| 34 | +######################### |
| 35 | +# END CONFIG # |
| 36 | +######################### |
| 37 | + |
| 38 | +# Configure the api client |
| 39 | +configuration = elabapi_python.Configuration() |
| 40 | +configuration.api_key['api_key'] = API_KEY |
| 41 | +configuration.api_key_prefix['api_key'] = 'Authorization' |
| 42 | +configuration.host = API_HOST_URL |
| 43 | +configuration.debug = False |
| 44 | +configuration.verify_ssl = False |
| 45 | + |
| 46 | +# create an instance of the API class |
| 47 | +api_client = elabapi_python.ApiClient(configuration) |
| 48 | +# fix issue with Authorization header not being properly set by the generated lib |
| 49 | +api_client.set_default_header(header_name='Authorization', header_value=API_KEY) |
| 50 | + |
| 51 | +#### SCRIPT START ################## |
| 52 | + |
| 53 | +# Load the experiments api |
| 54 | +experiments = elabapi_python.ExperimentsApi(api_client) |
| 55 | + |
| 56 | +# We would like to see the frequency of experiment creation over the past years. First we need to be able to parse the |
| 57 | +# date-time value from "created_at" field. For that we structure the data first. |
| 58 | +data = experiments.read_experiments() |
| 59 | + |
| 60 | +# We can try looking at one of the dates to see if it worked. |
| 61 | +print(data[0].created_at) |
| 62 | +# The datetime is in string format (ISO 8601). Though some libraries already know how to handle date-time data that are |
| 63 | +# in string format by implicitly converting them to Python datetime objects. Here we will do the conversion ourselves. |
| 64 | +# Let's take a look at how that would look like. |
| 65 | +print(datetime.fromisoformat(data[0].created_at)) # strips date-time in ISO 8601. |
| 66 | +# For working with date-time **programmatically** you want to work with this datetime instance |
| 67 | +# instead of the string format everywhere. |
| 68 | +print( |
| 69 | + datetime.fromisoformat(data[0].created_at).strftime("%Y") |
| 70 | +) # only gives the year value |
| 71 | +# Now we collect all the "created_at" dates. |
| 72 | +created_at = [datetime.fromisoformat(time.created_at).strftime("%Y") for time in data] |
| 73 | +# An alternative of fromisoformat() would be strptime("%m-%d-%Y %H:%M:%S", time.created_at). If we wanted to get months |
| 74 | +# instead of years we would use strftime("%m"). Have a look at this wonderful reference site for all sorts |
| 75 | +# date-time formats: https://strftime.org/. |
| 76 | +# For things like parsing timezones and other date-time paring related information, |
| 77 | +# please refer to the official documentation of datetime: https://docs.python.org/3/library/datetime.html |
| 78 | + |
| 79 | +# So far we have been using the data in its original structure as returned by the elabapi-python. |
| 80 | +# You might notice data[0] is an elabapi-python object, not a built-in data container. If you want more flexibility |
| 81 | +# with the data, you can convert it to dictionary with the built-in ast module the following way: |
| 82 | +# import ast |
| 83 | +# structured_data = ast. literal_eval(str(data)) |
| 84 | +# Here structured_data will be a full-fledged dictionary. |
| 85 | + |
| 86 | +# To make our final plot interesting we would like to see how the frequency looks like when it is color encoded (hue) |
| 87 | +# with "status". I.e., we would expect the older an experiment is the more likely its status is set to "Success". |
| 88 | +# Status by default is assigned "Running". |
| 89 | +status = [s.category for s in data] # In the API response "status" is named "category" |
| 90 | + |
| 91 | +# Though we won't plot the experiments IDs, just for future reference we collect the IDs as well. |
| 92 | +ids = [i.id for i in data] |
| 93 | + |
| 94 | +# Now we create the Pandas dataframe for plotting |
| 95 | +plot_data = { |
| 96 | + "Experiment IDs": created_at, |
| 97 | + "Creation Year": created_at, |
| 98 | + "Status": status, |
| 99 | +} |
| 100 | +df = pd.DataFrame.from_dict(plot_data) |
| 101 | +# Now we plot. |
| 102 | +sns.countplot(data=df, x="Creation Year", hue="Status") |
| 103 | +plt.show() |
| 104 | +# And that should give us an interesting discrete time series plot! |
0 commit comments