Compare commits

..

3 Commits

Author SHA256 Message Date
fd903f025b adds compound definition to glossary 2026-01-28 15:43:38 +01:00
f51b0d8615 adds asyncio to requirements
will probably start using it, if not I'll roll back
2026-01-28 15:42:28 +01:00
7245c757c3 reworks chained_requests
classes for parsing, functions for requests
also in general I shouldn't put error handling inside a class
2026-01-28 15:41:20 +01:00
3 changed files with 66 additions and 27 deletions

View File

@@ -5,6 +5,7 @@
* Sample: what is being produced by a deposition. A sample is made up of different stacked layers of material (target) deposited upon another material (substrate). * Sample: what is being produced by a deposition. A sample is made up of different stacked layers of material (target) deposited upon another material (substrate).
* Target: material "consumed" during the deposition. * Target: material "consumed" during the deposition.
* Substrate: material on which the target is deposited. * Substrate: material on which the target is deposited.
* Compound: which material is a target or a substrate made of; substrates of the same batch are made of the same compound.
* Layer: one of the layers of material of which a sample is composed; every layer can have different properties, both in the physical sense (i.e. shape, thickness...) and regarding their manufacturing process (i.e. frequency of pulses, deposition temperature and pressure...). * Layer: one of the layers of material of which a sample is composed; every layer can have different properties, both in the physical sense (i.e. shape, thickness...) and regarding their manufacturing process (i.e. frequency of pulses, deposition temperature and pressure...).
## eLabFTW glossary ## eLabFTW glossary
@@ -19,7 +20,7 @@
* JSON: fancy dictionaries with important data. * JSON: fancy dictionaries with important data.
### Endpoints ### Endpoints
Base url: https://{ELAB_BASE_URL}:{PORT}/api/v2 API URL: `https://{ELAB_BASE_URL}:{PORT}/api/v2`
#### GET, PATCH, DELETE #### GET, PATCH, DELETE
* `/items/{elabid}`: data on a resource identified by its elabid. * `/items/{elabid}`: data on a resource identified by its elabid.

View File

@@ -1 +1,2 @@
requests requests
asyncio

View File

@@ -2,42 +2,79 @@ import os, json, requests
from getpass import getpass from getpass import getpass
from classes import Header from classes import Header
''' class Layers:
Starting from the sample's page we'll use this code to pull and return all data from the entries related to the sample and its fabrication. def __init__(self, layer_data):
''' try:
self.extra = layer_data["metadata_decoded"]["extra_fields"]
except KeyError as k:
raise KeyError(f"The provided dictionary lacks a \"{k}\" key.")
self.target_elabid = self.extra["Target"]["value"]
self.start_time = layer_data.get("created_at")
self.operator = layer_data.get("fullname")
self.description = layer_data.get("body")
self.deposition_time = self.extra["Duration"]["value"]
self.repetition_rate = self.extra["Repetition rate"]["value"]
self.number_of_pulses = float(self.deposition_time) * float(self.repetition_rate)
self.temperature = self.extra["Heater temperature "]["value"]
self.heating_method = self.extra["Heating Method"]["value"]
class Entrypoint: class Entrypoint:
''' '''
Use: Entrypoint(elabid) Entrypoint(sample_data) - where sample_data is a Python dictionary.
The entrypoint is the starting point of the process of resolving the data chain. The entrypoint must be a sample. The entrypoint is the starting point of the process of resolving the data chain. The entrypoint must be a dictionary containing the data of a sample, created directly from the JSON of the item endpoint on eLabFTW - which can be done through the function get_entry_from_elabid.
Currently, the elabid of the sample must be provided. In the future a different method will eventually be implemented.
''' '''
def __init__(self, elabid): def __init__(self, sample_data):
''' '''
Constructor method. Attributes:
self.sample_data is a dictionary of all data on the sample's eLab entry. - self.linked_experiments is a sub-dictionary which only includes links to related experiments.
self.linked_experiments is a sub-dictionary which only includes links to related experiments. - self.linked_items is a sub-dictionary which only includes links to related items.
self.batch_elabid is an integer (or NoneType if there's an error) containing the elabid of the associated substrate batch entry. - self.batch_elabid is an integer (or NoneType if there's an error) containing the elabid of the associated substrate batch entry.
''' '''
header = Header(apikey).dump
self.sample_data = requests.get(
headers = header,
url = f"https://elabftw.fisica.unina.it/api/v2/items/{elabid}",
verify=True
).json()
self.linked_experiments = self.sample_data.get("related_experiments_links") or None
try: try:
self.batch_elabid = self.sample_data["metadata_decoded"]["extra_fields"]["Substrate batch"]["value"] self.extra = sample_data["metadata_decoded"]["extra_fields"]
except KeyError as k: # if no metadata exists - which means there's a problem with the entry except KeyError as k:
self.batch_elabid = None raise KeyError(f"The provided dictionary lacks a \"{k}\" key.")
self.linked_experiments = sample_data.get("related_experiments_links") or None
self.linked_items = sample_data.get("items_links") or None
self.batch_elabid = self.extra["Substrate batch"]["value"]
def get_entry_from_elabid(elabid, entryType="items"):
'''
Function which returns entrypoint data (as dictionary) from its elabid.
'''
header = Header(apikey).dump
response = requests.get(
headers = header,
url = f"{ELABFTW_API_URL}/{entryType}/{elabid}",
verify=True
)
if response.status_code // 100 in [2,3]:
entry_data = response.json()
return entry_data
else:
raise ConnectionError(f"HTTP request failed with status code: {response.status_code}.")
if __name__=="__main__": if __name__=="__main__":
print("===== DEBUG MODE! =====") print("===== DEBUG MODE! =====")
ELABFTW_API_URL = "https://elabftw.fisica.unina.it/api/v2"
apikey = getpass("Paste API key here: ") apikey = getpass("Paste API key here: ")
entryType = None
while entryType not in ["items", "experiments"]:
eT = input("Enter a valid entry type [items, experiments]: ")
match eT:
case "items" | "i" | "item":
entryType = "items"
case "experiments" | "e" | "exp" | "experiment":
entryType = "experiments"
case _:
pass
elabid = input("Input elabid here [default = 1108]: ") or 1108 elabid = input("Input elabid here [default = 1108]: ") or 1108
chain = Entrypoint(elabid) data = get_entry_from_elabid(elabid, entryType)
print(json.dumps(chain.sample_data)) if entryType == "experiments":
print(json.dumps(chain.linked_experiments)) layer = Layers(data)
print(chain.batch_elabid) print(layer.__dict__)
# print(json.dumps(chain.sample_data))
# print(json.dumps(chain.linked_experiments))
# print(chain.batch_elabid)