Compare commits

...

4 Commits

Author SHA256 Message Date
6f618b2340 adds comments 2026-02-13 01:05:32 +01:00
38940995b5 completes the dataset with instruments_used (in a way...)
only lacks units of measurement, then I'll be ready for conversion
2026-02-13 00:59:22 +01:00
f686ea65b1 adds get_instruments method to Layer class
get_instruments returns a dictionary with the names of every system used
during the deposition
unfortunately, NeXus standard allows for a single value of all three
keys per every sample - not every layer
this means that every layer has its own data for laser, rheed system and
depo chamber which IDEALLY is the same for every layer, but in practice
they COULD be different and I still don't know how to deal with this
2026-02-13 00:32:31 +01:00
23bfdefd30 adds all the remaining layer data
only lacks the instrument_used data and units of measurement
NOTE: units of measurement are hard to collect, but could be assumed
considering our instruments are standard
2026-02-13 00:18:07 +01:00
2 changed files with 77 additions and 2 deletions

View File

@@ -16,8 +16,9 @@ class Layer:
self.extra = layer_data["metadata_decoded"]["extra_fields"]
self.layer_number = self.extra["Layer Progressive Number"]["value"] # integer
self.target_elabid = self.extra["Target"]["value"] # elabid
self.rheed_system_elabid = self.extra["RHEED System"]["value"] # elabid
self.laser_system_elabid = self.extra["Laser System"]["value"] # elabid
self.chamber_elabid = self.extra["Chamber"]["value"] # elabid
self.rheed_system_elabid = self.extra["RHEED System"]["value"] # elabid
self.start_time = layer_data.get("created_at")
self.operator = layer_data.get("fullname")
self.description = layer_data.get("body")
@@ -71,6 +72,16 @@ class Layer:
# Some keys are not required and can be called through the .get() method - which is permissive and allows null values;
# Other keys are required so if they can't be called (invalid or null) raise error and stop execution of the program:
raise KeyError(f"The provided dictionary lacks a \"{k}\" key. Check the deposition layer entry on eLabFTW and make sure you used the correct Experiment template.")
def get_instruments(self, apikey):
raw_lasersys_data = APIHandler(apikey).get_entry_from_elabid(self.laser_system_elabid, entryType="items")
raw_chamber_data = APIHandler(apikey).get_entry_from_elabid(self.chamber_elabid, entryType="items")
raw_rheedsys_data = APIHandler(apikey).get_entry_from_elabid(self.rheed_system_elabid, entryType="items")
instruments_used = {
"laser_system": raw_lasersys_data.get("title") or None,
"deposition_chamber": raw_chamber_data.get("title") or None,
"rheed_system": raw_rheedsys_data.get("title") or None,
}
return instruments_used
class Entrypoint:
'''

View File

@@ -98,7 +98,37 @@ def chain_layer_to_target(layer_object):
material_object = call_material_from_elabid(target_elabid)
return material_object
def deduplicate_instruments_from_layers(layers):
'''
Takes a list of Layer-class objects and for each layer gets the instruments used (laser, depo chamber and RHEED), returns deduplicated list. Ideally, the lists should only contain one element.
'''
lasers = []
chambers = []
rheeds = []
for lyr in layers:
instruments = lyr.get_instruments(apikey)
lasers.append(instruments["laser_system"])
chambers.append(instruments["deposition_chamber"])
rheeds.append(instruments["rheed_system"])
instruments_used_dict = {
"laser_system": list( set( lasers ) ),
"deposition_chamber": list( set( chambers ) ),
"rheed_system" : list( set( rheeds ) ),
}
# lasers = { f"layer_{lyr.layer_number}": lyr.laser_system for lyr in layers }
# chambers = { f"layer_{lyr.layer_number}": lyr.deposition_chamber for lyr in layers }
# rheeds = { f"layer_{lyr.layer_number}": lyr.rheed_system for lyr in layers }
# instruments_used_dict = {
# "laser_system": lasers,
# "deposition_chamber": chambers,
# "rheed_system": rheeds,
# }
return instruments_used_dict
def make_nexus_schema_dictionary(substrate_object, layers):
'''
Main function, takes all the other functions to reconstruct the full dataset. Takes a Substrate-class object (output of the chain_entrypoint_to_batch() function) and a list of Layer-class objects (output of the chain_entrypoint_to_layers() function), returns dictionary with the same schema as the NeXus standard for PLD fabrications.
'''
pld_fabrication = {
"sample": {
"substrate": {
@@ -115,6 +145,7 @@ def make_nexus_schema_dictionary(substrate_object, layers):
},
"multilayer": {},
},
"instruments_used": deduplicate_instruments_from_layers(layers),
}
multilayer = pld_fabrication["sample"]["multilayer"]
for layer in layers:
@@ -133,7 +164,39 @@ def make_nexus_schema_dictionary(substrate_object, layers):
# "batch_id" : target_object.batch_id,
}
multilayer[name] = {
"target": target_dict
"target": target_dict,
"start_time": layer.start_time,
"operator": layer.operator,
"description": layer.description,
"number_of_pulses": layer.number_of_pulses,
"deposition_time": layer.deposition_time,
"temperature": layer.temperature,
"heating_method": layer.heating_method,
"layer_thickness": layer.layer_thickness,
"buffer_gas": layer.buffer_gas,
"process_pressure": layer.process_pressure,
"heater_target_distance": layer.heater_target_distance,
"repetition_rate": layer.repetition_rate,
"laser_fluence": layer.laser_fluence,
"laser_spot_area": layer.laser_spot_area,
"laser_energy": layer.laser_energy,
"laser_rastering": {
"geometry": layer.laser_rastering_geometry,
"positions": layer.laser_rastering_positions,
"velocities": layer.laser_rastering_velocities,
},
"pre_annealing": {
"ambient_gas": layer.pre_annealing_ambient_gas,
"pressure": layer.pre_annealing_pressure,
"temperature": layer.pre_annealing_temperature,
"duration": layer.pre_annealing_duration,
},
"post_annealing": {
"ambient_gas": layer.post_annealing_ambient_gas,
"pressure": layer.post_annealing_pressure,
"temperature": layer.post_annealing_temperature,
"duration": layer.post_annealing_duration,
},
}
return json.dumps(pld_fabrication, indent=2)
@@ -147,3 +210,4 @@ if __name__=="__main__":
substrate_object = chain_entrypoint_to_batch(sample) # Substrate-class object
layers = chain_entrypoint_to_layers(sample) # list of Layer-class objects
print(make_nexus_schema_dictionary(substrate_object, layers)) # debug