Files
eXParser-PLD/src/main.py

146 lines
6.7 KiB
Python

import os, json, requests
from getpass import getpass
from APIHandler import APIHandler
from classes import *
def call_entrypoint_from_elabid(elabid):
'''
Calls an entrypoint sample from eLabFTW using its elabid, then returns an object of the Entrypoint class.
If the entry is not a sample (category_title not matching exactly "Sample") returns ValueError.
'''
try:
sample_data = APIHandler(apikey).get_entry_from_elabid(elabid, entryType="items")
if not sample_data.get("category_title") == "Sample":
raise ValueError("The resource you selected is not a sample, therefore it can't be used as an entrypoint.")
sample_object = Entrypoint(sample_data)
except ConnectionError as e:
raise ConnectionError(e)
return sample_object # Entrypoint-class object
def call_material_from_elabid(elabid):
'''
Calls a material from eLabFTW using its elabid, then returns an object of the Material class.
If the entry is neither a PLD Target or a Substrate batch returns ValueError. Such entries always have a category_title key with its value either being "PLD Target" or "Substrate batch".
Because of an old typo, the value "Subtrate batch" (second 's' is missing) is also accepted.
'''
try:
material_data = APIHandler(apikey).get_entry_from_elabid(elabid, entryType="items")
# TO-DO: correct this typo on elabftw: Subtrate → Substrate.
if not sample_data.get("category_title") in ["PLD Target", "Substrate batch", "Subtrate batch"]:
raise ValueError(f"The referenced resource (elabid = {elabid}) is not a material.")
material_object = Material(material_data)
except ConnectionError as e:
raise ConnectionError(e)
return material_object # Material-class object
def call_layers_from_list(elabid_list):
'''
Calls a list of (PLD deposition) experiments from eLabFTW using their elabid - which means the input must be a list of integers instead of a single one - then returns a list of Layer-class objects.
If one of the entries is not related to a deposition layer (category_title not matching exactly "PLD Deposition") that entry is skipped, with no error raised.
'''
list_of_layers = []
for elabid in elabid_list:
try:
layer_data = APIHandler(apikey).get_entry_from_elabid(elabid, entryType="experiments")
if not layer_data.get("category_title") == "PLD Deposition":
continue
layer_object = Layer(layer_data)
list_of_layers.append(layer_object)
except ConnectionError as e:
nums = [ layer.layer_number for layer in list_of_layers ]
nums.sort()
print(f"LIST OF THE LAYERS PROCESSED (unordered):\n" + str(nums))
raise ConnectionError(f"An error occurred while fetching the experiment with elabid = {elabid}:\n" +
str(e) + f"\nPlease solve the problem before retrying." + "\n\n" +
f"Last resource attempted to call: {ELABFTW_API_URL}/experiments/{elabid}"
)
return list_of_layers # list of Layer-class objects
def chain_entrypoint_to_batch(sample_object):
'''
Takes an Entrypoint-class object, looks at its .batch_elabid attribute and returns a Material-class object containing data on the substrate batch associated to the starting sample.
Dependency: call_material_from_elabid.
'''
material_elabid = sample_object.batch_elabid
material_object = call_material_from_elabid(material_elabid)
return material_object
def chain_entrypoint_to_layers(sample_object):
'''
Takes an Entrypoint-class object, looks at its .linked_experiments_elabid attribute (list) and returns a list of Layer-class objects containing data on the deposition layers associated to the starting sample - using the function call_layers_from_list.
The list is sorted by progressive layer number (layer_number attribute).
Dependency: call_layers_from_list.
'''
linked_experiments_elabid = sample_object.linked_experiments_elabid # list of elabid
layer_object_list = call_layers_from_list(linked_experiments_elabid)
layer_object_list.sort(key=lambda x: x.layer_number)
return layer_object_list
#sample_object = call_entrypoint_from_elabid(elabid)
#from_entrypoint_to_material(sample_object)
if __name__=="__main__":
print(f"=======================\n===== DEBUG MODE! =====\n=======================\n")
ELABFTW_API_URL = "https://elabftw.fisica.unina.it/api/v2"
apikey = getpass("Paste API key here: ")
elabid = input("Enter elabid of your starting sample [default= 1111]: ") or 1111
data = APIHandler(apikey).get_entry_from_elabid(elabid)
sample = Entrypoint(data)
layers = chain_entrypoint_to_layers(sample)
print(f"Sample name:\n{sample.name}\n")
print(f"Layers data:")
for layer in layers:
ld = layer.__dict__
ld.pop("extra")
print(ld)
# entryType = None
# while entryType not in ["items", "experiments"]:
# eT = input("Enter a valid entry type [items, experiments]: ")
# # This allows for a shortcut: instead of prompting the type before and the elabid after I can just prompt both at the same time - e.g. e51 is exp. 51, i1108 is item 1108...
# if eT[0] in ["e", "i"] and eT[-1].isnumeric():
# try:
# elabid = int(eT[1:])
# eT = eT[0]
# except Exception:
# print("Usage: i|item|items|i[ELABID] for items, e|experiment|experiments|e[ELABID] for experiments.")
# continue
# match eT:
# case "items" | "i" | "item":
# entryType = "items"
# case "experiments" | "e" | "exp" | "experiment":
# entryType = "experiments"
# case _:
# continue
# # This will probably be reworked in production
# try:
# elabid = elabid
# except NameError:
# elabid = input("Input elabid here [default = 1111]: ") or 1111
# data = APIHandler(apikey).get_entry_from_elabid(elabid, entryType)
# if entryType == "experiments":
# layer = Layer(data)
# result = layer.__dict__
# result.pop("extra")
# print(result)
# elif entryType == "items":
# if data.get("category_title") == "Sample":
# item = Entrypoint(data)
# elif data.get("category_title") in ["PLD Target", "Substrate"]:
# item = Material(data)
# print(item.get_compound_formula(apikey))
# else:
# raise Exception("The selected item or experiment is not in one of the following categories: [Sample, PLD Target, Substrate, PLD Deposition].")
# result = item.__dict__
# result.pop("extra")
# print(result)