diff --git a/ifes_apt_tc_data_modeling/ato/ato_reader.py b/ifes_apt_tc_data_modeling/ato/ato_reader.py new file mode 100644 index 0000000..6e635d2 --- /dev/null +++ b/ifes_apt_tc_data_modeling/ato/ato_reader.py @@ -0,0 +1,117 @@ +# POS file format reader used by atom probe microscopists. +# +# Copyright The NOMAD Authors. +# +# This file is part of NOMAD. See https://nomad-lab.eu for further info. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# pylint: disable=no-member,duplicate-code + +import os + +import numpy as np + +from ifes_apt_tc_data_modeling.nexus.nx_field import NxField + +from ifes_apt_tc_data_modeling.utils.mmapped_io import get_memory_mapped_data + + +class ReadAtoFileFormat(): + """Read Rouen group *.ato file format.""" + + def __init__(self, filename: str): + assert len(filename) > 4, "ATO file incorrect filename ending!" + assert filename.lower().endswith(".ato"), \ + "ATO file incorrect file type!" + self.filename = filename + + self.filesize = os.path.getsize(self.filename) + self.number_of_events = None + self.version = None + retval = self.get_ato_version() + if retval in [3, 4, 5]: + self.version = retval + print(f"ATO file is in a supported version {self.version}") + if self.version == 3: + assert (self.filesize - 2 * 4) % 14 * 4 == 0, \ + "ATO v3 filesize not integer multiple of 14*4B!" + self.number_of_events = np.uint32((self.filesize - 2 * 4) / (14 * 4)) + print(f"ATO file contains {self.number_of_events} entries") + if self.version == 5: + assert (self.filesize - 5000) % 40 == 0, \ + "ATO v5 filesize not integer multiple of 40B!" + self.number_of_events = np.uint32((self.filesize - 5000) / 40) + print(f"ATO file contains {self.number_of_events} entries") + else: + raise ValueError("ATO file unsupported version!") + # https://zenodo.org/records/8382828 + # details three versions of the Rouen/GPM ato format v3, v4, v5 + # Cameca/AMETEK's runrootl/FileConvert utility know two ATO flavours: + # CamecaRoot v18.46.533g built Marc, 21, 2022 against ROOT 5.34/36 + # v3 LAWATOP and v5 current GPM + + def get_ato_version(self): + header = get_memory_mapped_data(self.filename, " x + xyz.typed_value[:, 1] = \ + get_memory_mapped_data(self.filename, " y + xyz.typed_value[:, 2] = \ + get_memory_mapped_data(self.filename, " z + if self.version == 5: + xyz.typed_value[:, 0] = \ + np.float32(get_memory_mapped_data(self.filename, " x + xyz.typed_value[:, 1] = \ + np.float32(get_memory_mapped_data(self.filename, " y + xyz.typed_value[:, 2] = \ + get_memory_mapped_data(self.filename, " z + return xyz + + def get_mass_to_charge_state_ratio(self): + """Read mass-to-charge-state-ratio column.""" + + m_n = NxField() + m_n.typed_value = np.zeros( + [self.number_of_events, 1], np.float32) + m_n.unit = "Da" + + if self.version == 3: + m_n.typed_value[:, 0] = \ + get_memory_mapped_data(self.filename, "