Skip to content

Commit

Permalink
Using refactored NXapm, possibly BREAKING CHANGE, next through testin…
Browse files Browse the repository at this point in the history
…g with run-throughs
  • Loading branch information
atomprobe-tc committed Jan 31, 2025
1 parent ffea6b0 commit 63f7eb5
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 25 deletions.
12 changes: 6 additions & 6 deletions src/pynxtools_apm/configurations/cameca_cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@
("measurement/instrument/fabrication/model", "fLeapModel"),
("measurement/instrument/fabrication/serial_number", "fSerialNumber"),
(
"measurement/instrument/pulser/SOURCE[source*]/fabrication/model",
"measurement/instrument/pulser/sourceID[source*]/fabrication/model",
"fLaserModelString",
),
(
"measurement/instrument/pulser/SOURCE[source*]/fabrication/serial_number",
"measurement/instrument/pulser/sourceID[source*]/fabrication/serial_number",
"fLaserSerialNumber",
),
(
Expand Down Expand Up @@ -73,18 +73,18 @@
("atom_probe/reconstruction/tip_radius_zero", ureg.nanometer, "fTipRadius0"),
("atom_probe/reconstruction/voltage_zero", ureg.volt, "fVoltage0"),
(
"measurement/instrument/analysis_chamber/pressure",
"measurement/events/eventID[event*]/instrument/analysis_chamber/pressure",
ureg.torr,
"fAnalysisPressure",
),
(
"measurement/instrument/local_electrode/voltage",
"measurement/events/eventID[event*]/instrument/local_electrode/voltage",
ureg.volt,
"fAnodeAccelVoltage",
),
("elapsed_time", ureg.second, "fElapsedTime"),
(
"measurement/instrument/pulser/pulse_frequency",
"measurement/events/eventID[event*]/instrument/pulser/pulse_frequency",
ureg.kilohertz,
"fInitialPulserFreq",
),
Expand All @@ -96,7 +96,7 @@
"fMaximumFlightPathMm",
),
(
"measurement/instrument/stage/specimen_temperature",
"measurement/events/eventID[event*]/instrument/stage/specimen_temperature",
ureg.kelvin,
"fSpecimenTemperature",
),
Expand Down
27 changes: 13 additions & 14 deletions src/pynxtools_apm/configurations/eln_cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,21 @@
APM_ENTRY_TO_NEXUS = {
"prefix_trg": "/ENTRY[entry*]",
"prefix_src": "entry/",
"map": [
"run_number",
"map_to_str": [
"operation_mode",
"start_time",
"end_time",
"experiment_description",
("experiment_alias", "run_number"),
],
"map_to_u4": ["run_number"],
}


APM_SAMPLE_TO_NEXUS = {
"prefix_trg": "/ENTRY[entry*]/sample",
"prefix_src": "sample/",
"map": [
"map_to_str": [
"alias",
"description",
("type", "method"),
Expand Down Expand Up @@ -88,7 +88,7 @@
APM_SPECIMEN_TO_NEXUS = {
"prefix_trg": "/ENTRY[entry*]/specimen",
"prefix_src": "specimen/",
"map": [
"map_to_str": [
"alias",
"preparation_date",
"description",
Expand Down Expand Up @@ -116,16 +116,15 @@
APM_INSTRUMENT_STATIC_TO_NEXUS = {
"prefix_trg": "/ENTRY[entry*]/measurement/instrument",
"prefix_src": "instrument/",
"map": [
"status",
("name", "instrument_name"),
"map_to_str": [
# "status",
"location",
("name", "instrument_name"),
("fabrication/vendor", "fabrication_vendor"),
("fabrication/model", "fabrication_model"),
("fabrication/identifier/identifier", "fabrication_identifier"),
("reflectron/status", "reflectron_status"),
("local_electrode/name", "local_electrode_name"),
("pulser/pulse_mode", "pulser/pulse_mode"),
],
"map_to_f8": [
(
Expand All @@ -139,11 +138,11 @@


APM_INSTRUMENT_DYNAMIC_TO_NEXUS = {
"prefix_trg": "/ENTRY[entry*]/measurement/event_data_apm_set/event_data_apm/instrument",
"prefix_trg": "/ENTRY[entry*]/measurement/events/eventID[event*]/instrument",
"prefix_src": "instrument/",
"use": [("control/target_detection_rate/@units", "ions/pulse")],
"map": [
"pulser_pulse_mode",
"map_to_str": [
("pulser/pulse_mode", "pulser/pulse_mode"),
("control/evaporation_control", "evaporation_control"),
],
"map_to_f8": [
Expand All @@ -156,7 +155,7 @@
),
("pulser/pulse_fraction", "pulser/pulse_fraction"),
(
"analysis_chamber/chamber_pressure",
"analysis_chamber/pressure",
ureg.bar,
"chamber_pressure/value",
"chamber_pressure/unit",
Expand All @@ -174,7 +173,7 @@
APM_RANGE_TO_NEXUS = {
"prefix_trg": "/ENTRY[entry*]/atom_probe/ranging",
"prefix_src": "ranging/",
"map": [
"map_to_str": [
("programID[program1]/program", "program"),
("programID[program1]/program/@version", "program_version"),
],
Expand All @@ -184,7 +183,7 @@
APM_RECON_TO_NEXUS = {
"prefix_trg": "/ENTRY[entry*]/atom_probe/reconstruction",
"prefix_src": "reconstruction/",
"map": [
"map_to_str": [
"protocol_name",
"crystallographic_calibration",
"parameter",
Expand Down
4 changes: 2 additions & 2 deletions src/pynxtools_apm/configurations/oasis_cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
f"{dt.datetime.now(dt.timezone.utc).isoformat().replace('+00:00', 'Z')}",
),
],
"map": ["operation_mode"],
"map_to_str": ["operation_mode"],
}


Expand Down Expand Up @@ -89,5 +89,5 @@
APM_EXAMPLE_TO_NEXUS = {
"prefix_trg": "/ENTRY[entry*]/CITE[cite*]",
"prefix_src": "",
"map": ["authors", "doi", "description", "url"],
"map_to_str": ["authors", "doi", "description", "url"],
}
22 changes: 22 additions & 0 deletions src/pynxtools_apm/utils/generate_synthetic_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class ApmCreateExampleData:
"""A synthesized dataset meant to be used for development purposes only!."""

def __init__(self, synthesis_id):
"""Construct class."""
raise NotImplementedError()
# assure deterministic behaviour of the PRNG
np.random.seed(seed=synthesis_id)

Expand Down Expand Up @@ -106,6 +108,7 @@ def create_reconstructed_positions(self):

# assumptions:
# identity orientation, no periodic boundary conditions
raise NotImplementedError()
print(f"Using the following version of ase {ase.__version__}")
xyz = np.asarray(
FaceCenteredCubic(
Expand Down Expand Up @@ -159,6 +162,7 @@ def place_atoms_from_periodic_table(self):
create (hypothetical) charged molecular ions from them
and evaluate their mass-to-charge-state ratio to be used
as values in the example dataset."""
raise NotImplementedError()

# uniform random model for how many different ions
# !! warning: for real world datasets this depends on real specimen composition
Expand Down Expand Up @@ -268,6 +272,7 @@ def place_atoms_from_periodic_table(self):

def composition_to_ranging_definitions(self, template: dict) -> dict:
"""Create ranging definitions based on composition."""
raise NotImplementedError()
assert len(self.nrm_composition) > 0, "Composition is not defined!"
trg = f"/ENTRY[entry{self.entry_id}]/atom_probe/ranging/"
template[f"{trg}programID[program1]/program"] = NX_APM_EXEC_NAME
Expand Down Expand Up @@ -303,6 +308,7 @@ def composition_to_ranging_definitions(self, template: dict) -> dict:

def emulate_entry(self, template: dict) -> dict:
"""Copy data in entry section."""
raise NotImplementedError()
# check if required fields exists and are valid
# print("Parsing entry...")
trg = f"/ENTRY[entry{self.entry_id}]/"
Expand All @@ -328,6 +334,7 @@ def emulate_entry(self, template: dict) -> dict:

def emulate_user(self, template: dict) -> dict:
"""Copy data in user section."""
raise NotImplementedError()
# check if required fields exists and are valid
# print("Parsing user...")
prefix = f"/ENTRY[entry{self.entry_id}]/"
Expand Down Expand Up @@ -367,6 +374,7 @@ def emulate_user(self, template: dict) -> dict:

def emulate_specimen(self, template: dict) -> dict:
"""Copy data in specimen section."""
raise NotImplementedError()
# check if required fields exists and are valid
# print("Parsing specimen...")
trg = f"/ENTRY[entry{self.entry_id}]/specimen/"
Expand Down Expand Up @@ -397,6 +405,7 @@ def emulate_specimen(self, template: dict) -> dict:

def emulate_control_software(self, template: dict) -> dict:
"""Copy data in control software section."""
raise NotImplementedError()
# print("Parsing control software...")
trg = f"/ENTRY[entry{self.entry_id}]/atom_probe/control_software/"
template[f"{trg}programID[program1]/program"] = "IVAS"
Expand All @@ -407,6 +416,7 @@ def emulate_control_software(self, template: dict) -> dict:

def emulate_instrument_header(self, template: dict) -> dict:
"""Copy data in instrument_header section."""
raise NotImplementedError()
# check if required fields exists and are valid
# print("Parsing instrument header...")
trg = f"/ENTRY[entry{self.entry_id}]/atom_probe/"
Expand All @@ -419,6 +429,7 @@ def emulate_instrument_header(self, template: dict) -> dict:

def emulate_fabrication(self, template: dict) -> dict:
"""Copy data in fabrication section."""
raise NotImplementedError()
# print("Parsing fabrication...")
trg = f"/ENTRY[entry{self.entry_id}]/atom_probe/FABRICATION[fabrication]/"
template[f"{trg}vendor"] = str(
Expand Down Expand Up @@ -446,6 +457,7 @@ def emulate_fabrication(self, template: dict) -> dict:

def emulate_analysis_chamber(self, template: dict) -> dict:
"""Copy data in analysis_chamber section."""
raise NotImplementedError()
# print("Parsing analysis chamber...")
trg = f"/ENTRY[entry{self.entry_id}]/atom_probe/analysis_chamber/"
template[f"{trg}pressure"] = np.float64(
Expand All @@ -456,20 +468,23 @@ def emulate_analysis_chamber(self, template: dict) -> dict:

def emulate_reflectron(self, template: dict) -> dict:
"""Copy data in reflectron section."""
raise NotImplementedError()
# print("Parsing reflectron...")
trg = f"/ENTRY[entry{self.entry_id}]/atom_probe/REFLECTRON[reflectron]/"
template[f"{trg}applied"] = bool(np.random.choice([0, 1], 1)[0])
return template

def emulate_local_electrode(self, template: dict) -> dict:
"""Copy data in local_electrode section."""
raise NotImplementedError()
# print("Parsing local electrode...")
trg = f"/ENTRY[entry{self.entry_id}]/atom_probe/local_electrode/"
template[f"{trg}name"] = str(f"electrode {np.random.choice(1000, 1)[0]}")
return template

def emulate_detector(self, template: dict) -> dict:
"""Copy data in ion_detector section."""
raise NotImplementedError()
# print("Parsing detector...")
trg = f"/ENTRY[entry{self.entry_id}]/atom_probe/ion_detector/"
detector_model_type = str(np.random.choice(["cameca", "mcp", "custom"], 1)[0])
Expand All @@ -483,6 +498,7 @@ def emulate_detector(self, template: dict) -> dict:

def emulate_stage_lab(self, template: dict) -> dict:
"""Copy data in stage lab section."""
raise NotImplementedError()
# print("Parsing stage lab...")
trg = f"/ENTRY[entry{self.entry_id}]/atom_probe/stage_lab/"
template[f"{trg}base_temperature"] = np.float64(10 + np.random.choice(50, 1)[0])
Expand All @@ -491,6 +507,7 @@ def emulate_stage_lab(self, template: dict) -> dict:

def emulate_specimen_monitoring(self, template: dict) -> dict:
"""Copy data in specimen_monitoring section."""
raise NotImplementedError()
# print("Parsing specimen monitoring...")
trg = f"/ENTRY[entry{self.entry_id}]/atom_probe/specimen_monitoring/"
eta = np.min((np.random.normal(loc=0.6, scale=0.1), 1.0))
Expand All @@ -503,6 +520,7 @@ def emulate_specimen_monitoring(self, template: dict) -> dict:

def emulate_pulser(self, template: dict) -> dict:
"""Copy data in pulser section."""
raise NotImplementedError()
# print("Parsing pulser...")
trg = f"/ENTRY[entry{self.entry_id}]/atom_probe/pulser/"
pulse_mode = str(
Expand Down Expand Up @@ -537,6 +555,7 @@ def emulate_pulser(self, template: dict) -> dict:

def emulate_reconstruction(self, template: dict) -> dict:
"""Copy data in reconstruction section."""
raise NotImplementedError()
# print("Parsing reconstruction...")
trg = f"/ENTRY[entry{self.entry_id}]/atom_probe/reconstruction/"
src = f"/ENTRY[entry{self.entry_id}]/atom_probe/control_software/"
Expand All @@ -555,6 +574,7 @@ def emulate_reconstruction(self, template: dict) -> dict:

def emulate_ranging(self, template: dict) -> dict:
"""Copy data in ranging section."""
raise NotImplementedError()
# print("Parsing ranging...")
trg = f"/ENTRY[entry{self.entry_id}]/atom_probe/ranging/"
src = f"/ENTRY[entry{self.entry_id}]/atom_probe/control_software/"
Expand All @@ -568,6 +588,7 @@ def emulate_ranging(self, template: dict) -> dict:

def emulate_random_input_from_eln(self, template: dict) -> dict:
"""Emulate random input as could come from an ELN."""
raise NotImplementedError()
self.emulate_entry(template)
self.emulate_user(template)
self.emulate_specimen(template)
Expand All @@ -594,6 +615,7 @@ def emulate_random_input_from_eln(self, template: dict) -> dict:

def synthesize(self, template: dict) -> dict:
"""Hand-over instantiated dataset to dataconverter template."""
raise NotImplementedError()
# heavy data, synthetic/mocked dataset
for entry_id in np.arange(1, self.n_entries + 1):
self.entry_id = entry_id
Expand Down
2 changes: 1 addition & 1 deletion src/pynxtools_apm/utils/oasis_apsuite_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def assume_pulse_mode(self, template: dict) -> dict:
else:
pulse_mode = "unknown"
template[
f"/ENTRY[entry{self.entry_id}]/measurement/instrument/pulser/pulse_mode"
f"/ENTRY[entry{self.entry_id}]/measurement/events/eventID[event1]/instrument/pulser/pulse_mode"
] = pulse_mode
return template

Expand Down
5 changes: 3 additions & 2 deletions src/pynxtools_apm/utils/oasis_eln_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ def parse_pulser_source(self, template: dict) -> dict:
for ldct in self.yml[src]:
trg_sta = (
f"/ENTRY[entry{self.entry_id}]/measurement/"
f"instrument/pulser/sourceID[source{laser_id}]"
f"events/eventID[event1]/instrument/"
f"pulser/sourceID[source{laser_id}]"
)
if "name" in ldct:
template[f"{trg_sta}/name"] = ldct["name"]
Expand All @@ -174,7 +175,7 @@ def parse_pulser_source(self, template: dict) -> dict:

trg_dyn = (
f"/ENTRY[entry{self.entry_id}]/measurement/"
f"event_data_apm_set/event_data_apm/instrument/"
f"events/eventID[event1]/instrument/"
f"pulser/sourceID[source{laser_id}]"
)
quantities = ["power", "pulse_energy"]
Expand Down

0 comments on commit 63f7eb5

Please sign in to comment.