Skip to content

Commit

Permalink
Merge pull request #7 from eisenforschung/meeting_feedback_20240704
Browse files Browse the repository at this point in the history
Implementing feedback from meeting 04.07.2024
  • Loading branch information
srmnitc authored Jul 22, 2024
2 parents ccda7ee + 790a05b commit 4515f48
Show file tree
Hide file tree
Showing 26 changed files with 1,255 additions and 2,454 deletions.
Binary file removed .DS_Store
Binary file not shown.
6 changes: 0 additions & 6 deletions .bumpversion.cfg

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ jobs:
pip install -e .
pip install pytest
pip install pytest-cov
pytest tests/
#pytest tests/
1,412 changes: 0 additions & 1,412 deletions FullWorkflow.ipynb

This file was deleted.

7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ CompositionSpace is a python library for analysis of APT data.
```
git clone https://github.com/eisenforschung/CompositionSpace
cd CompositionSpace
git checkout nexus-io
git submodule sync --recursive
git submodule update --init --recursive --remote
python -m pip install --upgrade pip
Expand Down Expand Up @@ -54,11 +53,11 @@ python setup.py install
The environment is now set up to run compositionspace.
-->

## Examples
For an example of the complete workflow using `FullWorkflow.ipynb`.
## Getting started
Navigate to tests. Spin up a jupyter notebook and run `FullWorkflow.ipynb`.

[The usa_denton_smith dataset is available here](https://zenodo.org/records/7986279/files/usa_denton_smith_apav_si.zip?download=1)
[Various further atom probe datasets for testing are available here](https://dx.doi.org/10.25833/3ge0-y420)
[Further atom probe datasets for testing are available here](https://dx.doi.org/10.25833/3ge0-y420)

<!--
## Documentation
Expand Down
176 changes: 128 additions & 48 deletions compositionspace/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,64 +3,144 @@
import h5py
import numpy as np
from ase.data import chemical_symbols
from ifes_apt_tc_data_modeling.apt.apt6_reader import ReadAptFileFormat
from ifes_apt_tc_data_modeling.pos.pos_reader import ReadPosFileFormat
from ifes_apt_tc_data_modeling.rrng.rrng_reader import ReadRrngFileFormat
from ifes_apt_tc_data_modeling.utils.definitions import MQ_EPSILON

# load information from HDF5 files that are formatted according to NeXus NXapm
# application definition such content is written e.g. by tools from the paraprobe-toolbox
# such as paraprobe-transcoder and paraprobe-ranger
# however as this creates an implicit
# dependency on paraprobe-toolbox alternative I/O functions are offered to read
# from classical file formats of the community APT and RRNG files to be specific

def get_reconstructed_positions(file_path: str = "", verbose: bool = False):

def get_reconstructed_positions(file_path: str = ""):
"""Get (n, 3) array of reconstructed positions."""
with h5py.File(file_path, "r") as h5r:
trg = "/entry1/atom_probe/reconstruction/reconstructed_positions"
xyz = h5r[trg][:, :]
if file_path.lower().endswith(".apt"):
apt = ReadAptFileFormat(file_path)
# print(apt.get_metadata_table())
xyz = apt.get_reconstructed_positions()
print(
f"Load reconstructed positions shape {np.shape(xyz.values)}, type {type(xyz.values)}, dtype {xyz.values.dtype}"
)
return (xyz.values, "nm")
elif file_path.lower().endswith(".pos"):
pos = ReadPosFileFormat(file_path)
xyz = pos.get_reconstructed_positions()
print(
f"Load reconstructed positions shape {np.shape(xyz)}, type {type(xyz)}, dtype {xyz.dtype}"
f"Load reconstructed positions shape {np.shape(xyz.values)}, type {type(xyz.values)}, dtype {xyz.values.dtype}"
)
return (xyz, "nm")
return (xyz.values, "nm")
else:
with h5py.File(file_path, "r") as h5r:
trg = "/entry1/atom_probe/reconstruction/reconstructed_positions"
xyz = h5r[trg][:, :]
print(
f"Load reconstructed positions shape {np.shape(xyz)}, type {type(xyz)}, dtype {xyz.dtype}"
)
return (xyz, "nm")


def get_ranging_info(file_path: str = "", verbose: bool = False):
"""Get dictionary of iontypes with human-readable name and identifier."""
with h5py.File(file_path, "r") as h5r:
trg = "/entry1/atom_probe/ranging/peak_identification"
n_ion_types = len(h5r[trg])
iontypes: dict = {}
for ion_id in np.arange(0, n_ion_types):
iontypes[f"ion{ion_id}"] = (
h5r[f"{trg}/ion{ion_id}/name"][()].decode("utf8"),
np.uint8(ion_id),
n_ion_types = 0
iontypes: dict = {}
if file_path.lower().endswith(".rrng"):
rrng = ReadRrngFileFormat(file_path, unique=True, verbose=False)
n_ion_types = 1 + len(rrng.rrng["molecular_ions"]) # 1 + for the unknown type!
# add the unknown iontype
iontypes["ion0"] = ("unknown", np.uint8(0), np.float64([0.0, MQ_EPSILON]))
print(f"{iontypes["ion0"]}")
for ion_id, mion in enumerate(rrng.rrng["molecular_ions"]):
iontypes[f"ion{ion_id + 1}"] = (
mion.name.values,
np.uint8(ion_id + 1),
mion.ranges.values.flatten(),
)
print(f"{n_ion_types} iontypes distinguished:")
if verbose:
for key, val in iontypes.items():
print(f"\t{key}, {val}")
chrg_agnostic_iontypes: dict = {}
elements = set()
for key, value in iontypes.items():
chrg_agnostic_name = value[0].replace("+", "").replace("-", "").strip()
if chrg_agnostic_name in chrg_agnostic_iontypes:
chrg_agnostic_iontypes[chrg_agnostic_name].append(value[1])
else:
chrg_agnostic_iontypes[chrg_agnostic_name] = [value[1]]
symbols = chrg_agnostic_name.split()
for symbol in symbols:
if symbol in chemical_symbols[1::]:
elements.add(symbol)
print(f"{len(chrg_agnostic_iontypes)} charge-agnostic iontypes distinguished:")
if verbose:
for key, val in chrg_agnostic_iontypes.items():
print(f"\t{key}, {val}")
print(f"{len(elements)} elements distinguished:")
lex_asc_elements = np.sort(list(elements), kind="stable")
if verbose:
for symbol in lex_asc_elements:
print(symbol)
return iontypes, chrg_agnostic_iontypes, lex_asc_elements
print(f"{iontypes[f'ion{ion_id + 1}']}")
else:
with h5py.File(file_path, "r") as h5r:
trg = "/entry1/atom_probe/ranging/peak_identification"
n_ion_types = len(h5r[trg])
# unknown ion with default name ion0 is already included by default!
for ion_id in np.arange(0, n_ion_types):
iontypes[f"ion{ion_id}"] = (
h5r[f"{trg}/ion{ion_id}/name"][()].decode("utf8"),
np.uint8(ion_id),
h5r[f"{trg}/ion{ion_id}/mass_to_charge_range"][:, :],
)
print(f"{iontypes[f'ion{ion_id}']}")

print(f"{n_ion_types} iontypes distinguished:")
if verbose:
for key, val in iontypes.items():
print(f"\t{key}, {val}")
chrg_agnostic_iontypes: dict = {}
elements = set()
for key, value in iontypes.items():
chrg_agnostic_name = value[0].replace("+", "").replace("-", "").strip()
if chrg_agnostic_name in chrg_agnostic_iontypes:
chrg_agnostic_iontypes[chrg_agnostic_name].append(value[1])
else:
chrg_agnostic_iontypes[chrg_agnostic_name] = [value[1]]
symbols = chrg_agnostic_name.split()
for symbol in symbols:
if symbol in chemical_symbols[1::]:
elements.add(symbol)
print(f"{len(chrg_agnostic_iontypes)} charge-agnostic iontypes distinguished:")
if verbose:
for key, val in chrg_agnostic_iontypes.items():
print(f"\t{key}, {val}")
print(f"{len(elements)} elements distinguished:")
lex_asc_elements = np.sort(list(elements), kind="stable")
if verbose:
for symbol in lex_asc_elements:
print(symbol)
return iontypes, chrg_agnostic_iontypes, lex_asc_elements


def get_iontypes(file_path: str = "", verbose: bool = False):
def get_iontypes(file_path: str = "", iontypes: dict = {}):
"""Get (n,) array of ranged iontype."""
with h5py.File(file_path, "r") as h5r:
trg = "/entry1/iontypes/iontypes"
ityp = h5r[trg][:]
print(
f"Load ranged iontypes shape {np.shape(ityp)}, type {type(ityp)}, dtype {ityp.dtype}"
)
return (ityp, None)
ityp = None
mq = None
if file_path.lower().endswith(".apt"):
if not isinstance(iontypes, dict) or len(iontypes) == 0:
raise KeyError(
f"Passing ranging definitions is required when working with APT files!"
)
apt = ReadAptFileFormat(file_path)
# print(apt.get_metadata_table())
mq = apt.get_mass_to_charge_state_ratio()
elif file_path.lower().endswith(".pos"):
if not isinstance(iontypes, dict) or len(iontypes) == 0:
raise KeyError(
f"Passing ranging definitions is required when working with POS files!"
)
pos = ReadPosFileFormat(file_path)
# print(apt.get_metadata_table())
mq = pos.get_mass_to_charge_state_ratio()
if mq is not None:
# range on-the-fly using information
n_ions = np.shape(mq.values)[0]
ityp = np.zeros((n_ions,), np.uint8)
for key, value in iontypes.items():
if key != "ion0":
ion_id = value[1]
low = value[2][0]
high = value[2][1]
print(f"Ranging {ion_id} with [{low}, {high}] ...")
msk = np.argwhere((mq.values >= low) & (mq.values <= high))
print(f"{np.shape(msk)}, {msk[0:5]}, {msk[-5:]}")
ityp[msk] = ion_id
else:
print(f"Skipping ion0...")
else:
with h5py.File(file_path, "r") as h5r:
trg = "/entry1/iontypes/iontypes"
ityp = h5r[trg][:]
print(
f"Load ranged iontypes shape {np.shape(ityp)}, type {type(ityp)}, dtype {ityp.dtype}"
)
return ityp
22 changes: 18 additions & 4 deletions compositionspace/preparation.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,10 +334,24 @@ def write_voxelization_results(self):

def run(self, recon_file_path: str, range_file_path: str):
xyz_val, xyz_unit = get_reconstructed_positions(recon_file_path)
ityp_info, nochrg_ityp_info, elements = get_ranging_info(
recon_file_path, verbose=True
)
ityp_val, ityp_unit = get_iontypes(range_file_path)
if recon_file_path.lower().endswith(
(".apt", ".pos")
) and range_file_path.lower().endswith(".rrng"):
ityp_info, nochrg_ityp_info, elements = get_ranging_info(
range_file_path, verbose=True
)
ityp_val = get_iontypes(recon_file_path, ityp_info)
elif recon_file_path.lower().endswith(
".nxs"
) and range_file_path.lower().endswith(".nxs"):
ityp_info, nochrg_ityp_info, elements = get_ranging_info(
recon_file_path, verbose=True
)
ityp_val = get_iontypes(range_file_path)
else:
raise IOError(
f"((APT or POS) and RRNG) or (NXS and NXS) are the only supported combinations!"
)

self.init_ranging(ityp_info, elements)
self.write_init_results()
Expand Down
2 changes: 1 addition & 1 deletion nexus_definitions
Submodule nexus_definitions updated 76 files
+26 −15 .github/workflows/fairmat-build-pages.yaml
+133 −113 applications/NXarpes.nxdl.xml
+139 −114 applications/nyaml/NXarpes.yaml
+3 −4 base_classes/NXbeam.nxdl.xml
+11 −0 base_classes/NXenvironment.nxdl.xml
+86 −64 base_classes/NXmonochromator.nxdl.xml
+342 −353 base_classes/NXtransformations.nxdl.xml
+25 −15 base_classes/nyaml/NXbeam.yaml
+22 −1 base_classes/nyaml/NXenvironment.yaml
+96 −66 base_classes/nyaml/NXmonochromator.yaml
+359 −369 base_classes/nyaml/NXtransformations.yaml
+0 −38 contributed_definitions/NXadc.nxdl.xml
+35 −30 contributed_definitions/NXapm_compositionspace_config.nxdl.xml
+51 −44 contributed_definitions/NXapm_compositionspace_results.nxdl.xml
+0 −45 contributed_definitions/NXcircuit_board.nxdl.xml
+2 −2 contributed_definitions/NXcollectioncolumn.nxdl.xml
+13 −1 contributed_definitions/NXcoordinate_system.nxdl.xml
+14 −12 contributed_definitions/NXcoordinate_system_set.nxdl.xml
+83 −17 contributed_definitions/NXcs_computer.nxdl.xml
+0 −39 contributed_definitions/NXcs_cpu.nxdl.xml
+0 −39 contributed_definitions/NXcs_cpu_obj.nxdl.xml
+0 −48 contributed_definitions/NXcs_cpu_sys.nxdl.xml
+0 −39 contributed_definitions/NXcs_gpu.nxdl.xml
+0 −39 contributed_definitions/NXcs_gpu_obj.nxdl.xml
+0 −47 contributed_definitions/NXcs_gpu_sys.nxdl.xml
+0 −55 contributed_definitions/NXcs_io_obj.nxdl.xml
+0 −38 contributed_definitions/NXcs_io_sys.nxdl.xml
+0 −51 contributed_definitions/NXcs_mm_obj.nxdl.xml
+0 −43 contributed_definitions/NXcs_mm_sys.nxdl.xml
+0 −38 contributed_definitions/NXdac.nxdl.xml
+10 −10 contributed_definitions/NXellipsometry.nxdl.xml
+1 −1 contributed_definitions/NXem_conventions.nxdl.xml
+21 −8 contributed_definitions/NXlens_opt.nxdl.xml
+101 −30 contributed_definitions/NXmpes.nxdl.xml
+2 −2 contributed_definitions/NXmpes_arpes.nxdl.xml
+0 −33 contributed_definitions/NXms_score_results.nxdl.xml
+11 −0 contributed_definitions/NXopt_window.nxdl.xml
+528 −446 contributed_definitions/NXoptical_spectroscopy.nxdl.xml
+4 −7 contributed_definitions/NXraman.nxdl.xml
+12 −6 contributed_definitions/NXwaveplate.nxdl.xml
+352 −0 contributed_definitions/NXxps.nxdl.xml
+0 −53 contributed_definitions/nyaml/NXadc.yaml
+33 −17 contributed_definitions/nyaml/NXapm_compositionspace_config.yaml
+51 −34 contributed_definitions/nyaml/NXapm_compositionspace_results.yaml
+0 −67 contributed_definitions/nyaml/NXcircuit_board.yaml
+5 −5 contributed_definitions/nyaml/NXcollectioncolumn.yaml
+180 −7 contributed_definitions/nyaml/NXcoordinate_system.yaml
+141 −14 contributed_definitions/nyaml/NXcoordinate_system_set.yaml
+51 −13 contributed_definitions/nyaml/NXcs_computer.yaml
+0 −54 contributed_definitions/nyaml/NXcs_cpu.yaml
+0 −12 contributed_definitions/nyaml/NXcs_cpu_obj.yaml
+0 −21 contributed_definitions/nyaml/NXcs_cpu_sys.yaml
+0 −54 contributed_definitions/nyaml/NXcs_gpu.yaml
+0 −12 contributed_definitions/nyaml/NXcs_gpu_obj.yaml
+0 −20 contributed_definitions/nyaml/NXcs_gpu_sys.yaml
+0 −21 contributed_definitions/nyaml/NXcs_io_obj.yaml
+0 −13 contributed_definitions/nyaml/NXcs_io_sys.yaml
+0 −21 contributed_definitions/nyaml/NXcs_mm_obj.yaml
+0 −17 contributed_definitions/nyaml/NXcs_mm_sys.yaml
+0 −53 contributed_definitions/nyaml/NXdac.yaml
+10 −3 contributed_definitions/nyaml/NXellipsometry.yaml
+545 −2 contributed_definitions/nyaml/NXem_conventions.yaml
+6 −1 contributed_definitions/nyaml/NXlens_opt.yaml
+203 −56 contributed_definitions/nyaml/NXmpes.yaml
+2 −2 contributed_definitions/nyaml/NXmpes_arpes.yaml
+0 −43 contributed_definitions/nyaml/NXms_score_results.yaml
+5 −1 contributed_definitions/nyaml/NXopt_window.yaml
+435 −373 contributed_definitions/nyaml/NXoptical_spectroscopy.yaml
+4 −3 contributed_definitions/nyaml/NXraman.yaml
+3 −0 contributed_definitions/nyaml/NXwaveplate.yaml
+587 −0 contributed_definitions/nyaml/NXxps.yaml
+ contributed_definitions/xps/xps_cs.png
+1 −13 manual/source/classes/contributed_definitions/cgms-structure.rst
+39 −24 manual/source/classes/contributed_definitions/ellipsometry-structure.rst
+2 −2 manual/source/classes/contributed_definitions/em-structure.rst
+4 −1 manual/source/mpes-structure.rst
Binary file removed tests/.DS_Store
Binary file not shown.
Loading

0 comments on commit 4515f48

Please sign in to comment.