From abf8519383f902750db4e720b35af7a61badd75d Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 28 Dec 2023 19:24:47 +0100 Subject: [PATCH 01/20] Added working example for reading ranging definitions from ENV files --- ifes_apt_tc_data_modeling/ato/ato_reader.py | 9 +- ifes_apt_tc_data_modeling/env/__init__.py | 0 ifes_apt_tc_data_modeling/env/env_reader.py | 167 ++++ ifes_apt_tc_data_modeling/rng/rng_reader.py | 7 +- tests/TestsForDevelopers.ipynb | 884 +++++++++++++++++- .../env/examples_without_provenance/ErMnO.env | 112 +++ 6 files changed, 1149 insertions(+), 30 deletions(-) create mode 100644 ifes_apt_tc_data_modeling/env/__init__.py create mode 100644 ifes_apt_tc_data_modeling/env/env_reader.py create mode 100755 tests/data/env/examples_without_provenance/ErMnO.env diff --git a/ifes_apt_tc_data_modeling/ato/ato_reader.py b/ifes_apt_tc_data_modeling/ato/ato_reader.py index a5ebce2..87b759f 100644 --- a/ifes_apt_tc_data_modeling/ato/ato_reader.py +++ b/ifes_apt_tc_data_modeling/ato/ato_reader.py @@ -31,9 +31,8 @@ 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!" + if (len(filename) <= 4) or (filename.lower().endswith(".ato") is False): + raise ImportError(f"WARNING::ATO file incorrect filename ending or file type!") self.filename = filename self.filesize = os.path.getsize(self.filename) @@ -53,9 +52,9 @@ def __init__(self, filename: str): 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") + print(f"ATO file contains {self.number_of_events} entries") else: - raise ValueError("ATO file unsupported version!") + raise ImportError("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: diff --git a/ifes_apt_tc_data_modeling/env/__init__.py b/ifes_apt_tc_data_modeling/env/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ifes_apt_tc_data_modeling/env/env_reader.py b/ifes_apt_tc_data_modeling/env/env_reader.py new file mode 100644 index 0000000..e8012ed --- /dev/null +++ b/ifes_apt_tc_data_modeling/env/env_reader.py @@ -0,0 +1,167 @@ +# Reader for GPM/Rouen ENV system configuration and range file +# +# 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. +# + + +import re +import numpy as np +from ifes_apt_tc_data_modeling.nexus.nx_ion import NxField, NxIon +from ifes_apt_tc_data_modeling.utils.utils import \ + create_isotope_vector, is_range_significant +from ifes_apt_tc_data_modeling.utils.definitions import MQ_EPSILON +from ifes_apt_tc_data_modeling.utils.molecular_ions import MolecularIonBuilder +from ifes_apt_tc_data_modeling.utils.molecular_ions import \ + PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ + PRACTICAL_MIN_HALF_LIFE, VERBOSE, SACRIFICE_ISOTOPIC_UNIQUENESS +from ase.data import atomic_numbers, atomic_masses, chemical_symbols + + +def get_smart_chemical_symbols(): + priority_queue = [] + for symbol in chemical_symbols: + if len(symbol) == 2: + priority_queue.append(symbol) + for symbol in chemical_symbols: + if symbol != "X" and len(symbol) == 1: + priority_queue.append(symbol) + return priority_queue + + +def evaluate_env_range_line(line: str) -> dict: + """Represent information content of a single range line.""" + # example line: ". 107.7240 108.0960 1 0 0 0 0 0 0 0 0 0 3 0 0 0" + info: dict = {} + info["identifier"] = None + info["range"] = np.asarray([0., MQ_EPSILON], np.float64) + info["atoms"] = [] + info["volume"] = np.float64(0.) + info["color"] = "" + info["name"] = "" + + tmp = line.split() + + # interpret zeroth token into a list of chemical symbols + # interpret first token as inclusive left of m/q interval + # interpret second token as inclusive right bound of m/q interval + if len(tmp) < 3: + print(f"WARNING::ENV file ranging definition {line} has insufficient information!") + return None + if is_range_significant(np.float64(tmp[1]), np.float64(tmp[2])) is True: + info["range"] = np.asarray([tmp[1], tmp[2]], np.float64) + else: + print(f"WARNING::ENV file ranging definition {line} has insignificant range!") + return None + + lst = [] + if tmp[0] == "Hyd": + lst = [] + elif tmp[0] in get_smart_chemical_symbols(): + lst.append(tmp[0]) + else: + tokens = re.split(r'(\d+)', tmp[0]) + for jdx in np.arange(0, len(tokens)): + kdx = 0 + for sym in get_smart_chemical_symbols(): + if tokens[jdx][kdx:].startswith(sym) is True: + mult = 1 + if jdx < len(tokens) - 1: + if (tokens[jdx][kdx:] == sym) and (tokens[jdx + 1].isdigit() is True): + mult = int(tokens[jdx + 1]) + kdx += len(tokens[jdx + 1]) + for cnt in np.arange(0, mult): + lst.append(sym) + kdx += len(sym) + info["atoms"] = lst + return info + + +class ReadEnvFileFormat(): + """Read GPM/Rouen *.env file format.""" + + def __init__(self, filename: str): + if (len(filename) <= 4) or (filename.lower().endswith(".env") is False): + raise ImportError(f"WARNING::ENV file incorrect filename ending or file type!") + self.filename = filename + self.env: dict = {} + self.env["ranges"] = {} + self.env["ions"] = {} + self.env["molecular_ions"] = [] + self.read_env() + + def read_env(self): + """Read ENV system configuration and ranging definitions.""" + # GPM/Rouen ENV file format is neither standardized nor uses magic number + with open(self.filename, mode="r", encoding="utf-8") as envf: + txt = envf.read() + txt = txt.replace("\r\n", "\n") # windows to unix EOL conversion + txt = txt.replace(",", ".") # use decimal dots instead of comma + txt_stripped = [line for line in txt.split("\n") if line.strip() != ""] + # search for ranging definitions "# Definition of" + rng_s = None + rng_e = None + for idx in np.arange(0, len(txt_stripped)): + if txt_stripped[idx].startswith("# Definition of") is False: + continue + else: + rng_s = idx + break + for idx in np.arange(rng_s + 1, len(txt_stripped)): + if txt_stripped[idx].startswith("# Atom probe definition") is False: + continue + else: + rng_e = idx + break + if rng_s is None or rng_e is None: + print("WARNING:: No ranging definitions were found!") + return + + for idx in np.arange(rng_s + 1, rng_e): + dct = evaluate_env_range_line(txt_stripped[idx]) + if dct is None: + continue + + m_ion = NxIon(isotope_vector=create_isotope_vector( + dct["atoms"]), charge_state=0) + m_ion.add_range(dct["range"][0], dct["range"][1]) + m_ion.comment = NxField(dct["name"], "") + m_ion.color = NxField(dct["color"], "") + m_ion.volume = NxField(dct["volume"], "") + # m_ion.report() + + crawler = MolecularIonBuilder( + min_abundance=PRACTICAL_ABUNDANCE, + min_abundance_product=PRACTICAL_ABUNDANCE_PRODUCT, + min_half_life=PRACTICAL_MIN_HALF_LIFE, + sacrifice_uniqueness=SACRIFICE_ISOTOPIC_UNIQUENESS, + verbose=VERBOSE) + recovered_charge_state, m_ion_candidates = crawler.combinatorics( + m_ion.isotope_vector.typed_value, + m_ion.ranges.typed_value[0, 0], + m_ion.ranges.typed_value[0, 1]) + # print(f"{recovered_charge_state}") + m_ion.charge_state = NxField(np.int8(recovered_charge_state), "") + m_ion.update_human_readable_name() + m_ion.add_charge_state_model( + {"min_abundance": PRACTICAL_ABUNDANCE, + "min_abundance_product": PRACTICAL_ABUNDANCE_PRODUCT, + "min_half_life": PRACTICAL_MIN_HALF_LIFE, + "sacrifice_isotopic_uniqueness": SACRIFICE_ISOTOPIC_UNIQUENESS}, + m_ion_candidates) + + self.env["molecular_ions"].append(m_ion) + print(f"{self.filename} parsed successfully") diff --git a/ifes_apt_tc_data_modeling/rng/rng_reader.py b/ifes_apt_tc_data_modeling/rng/rng_reader.py index 323c2cb..ad42bf5 100644 --- a/ifes_apt_tc_data_modeling/rng/rng_reader.py +++ b/ifes_apt_tc_data_modeling/rng/rng_reader.py @@ -159,8 +159,9 @@ def read_rng(self): i - current_line_id, txt_stripped[i], header["column_id_to_label"], n_element_symbols + 3) - assert dct is not None, \ - "Line " + txt_stripped[i] + " is corrupted!" + if dct is None: + print("WARNING::RNG line {txt_stripped[i]} is corrupted!") + continue m_ion = NxIon(isotope_vector=create_isotope_vector( dct["atoms"]), charge_state=0) @@ -191,7 +192,7 @@ def read_rng(self): m_ion_candidates) self.rng["molecular_ions"].append(m_ion) - print(self.filename + " parsed successfully") + print(f"{self.filename} parsed successfully") if __name__ == "main": pass diff --git a/tests/TestsForDevelopers.ipynb b/tests/TestsForDevelopers.ipynb index 67fb6ee..93da2a5 100644 --- a/tests/TestsForDevelopers.ipynb +++ b/tests/TestsForDevelopers.ipynb @@ -20,13 +20,14 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "fc6c2ca9-ba62-4580-8eed-223467c58b22", "metadata": { "tags": [] }, "outputs": [], "source": [ + "import re\n", "import os\n", "import numpy as np\n", "import h5py\n", @@ -42,6 +43,848 @@ "from ase.data import atomic_numbers, atomic_masses, chemical_symbols" ] }, + { + "cell_type": "markdown", + "id": "523ccf70-b115-4717-9007-bd13ff86a2a5", + "metadata": {}, + "source": [ + "## GPM Rouen ENV system" + ] + }, + { + "cell_type": "markdown", + "id": "ad2b00d4-99b6-4e1a-a7cc-e48e6de843e1", + "metadata": {}, + "source": [ + "
An ENV file has to be formatted using the UTF8 character encoding for this reader to function!
" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "d239daae-b751-4f18-96c9-1f1e87ffacb6", + "metadata": {}, + "outputs": [], + "source": [ + "prefix = f\"{os.getcwd()}/data/env/examples_without_provenance\"\n", + "fnm = [\"ErMnO.env\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "8203e807-847d-45bd-853a-3adfb7dcb1b1", + "metadata": {}, + "outputs": [], + "source": [ + "from ifes_apt_tc_data_modeling.env.env_reader import ReadEnvFileFormat" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "6b5b4e1f-847a-4579-bef1-15ba2fe0faf4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/home/kaiobach/Research/hu_hu_hu/sprint17/ifes/ifes_apt_tc_data_modeling/tests/data/env/examples_without_provenance/ErMnO.env parsed successfully\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", + " [8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "O +\n", + "charge_state\n", + "1\n", + "ranges\n", + "[[15.88 16.84]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Mn ++\n", + "charge_state\n", + "2\n", + "ranges\n", + "[[27.33 27.95]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er ++\n", + "charge_state\n", + "2\n", + "ranges\n", + "[[81.89 82.36]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er ++\n", + "charge_state\n", + "2\n", + "ranges\n", + "[[82.91 83.41]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er ++\n", + "charge_state\n", + "2\n", + "ranges\n", + "[[83.41 83.91]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er ++\n", + "charge_state\n", + "2\n", + "ranges\n", + "[[83.93 84.9 ]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er ++\n", + "charge_state\n", + "2\n", + "ranges\n", + "[[84.92 85.45]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er +++\n", + "charge_state\n", + "3\n", + "ranges\n", + "[[53.93 54.13]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er +++\n", + "charge_state\n", + "3\n", + "ranges\n", + "[[54.49 54.75]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er +++\n", + "charge_state\n", + "3\n", + "ranges\n", + "[[55.09 55.55]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er +++\n", + "charge_state\n", + "3\n", + "ranges\n", + "[[55.543 55.88 ]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er +++\n", + "charge_state\n", + "3\n", + "ranges\n", + "[[55.877 56.27 ]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er +++\n", + "charge_state\n", + "3\n", + "ranges\n", + "[[56.5 56.97]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Mn +\n", + "charge_state\n", + "1\n", + "ranges\n", + "[[54.77 55.02]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[25 25 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[25 25 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [25 25 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Mn Mn O ++\n", + "charge_state\n", + "2\n", + "ranges\n", + "[[62.85 63.13]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[25 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[25 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [25 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Mn O O ++\n", + "charge_state\n", + "2\n", + "ranges\n", + "[[43.38 43.65]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[25 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[25 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [25 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Mn O +\n", + "charge_state\n", + "1\n", + "ranges\n", + "[[70.59 72.81]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[25 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[25 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [25 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Mn O O +\n", + "charge_state\n", + "1\n", + "ranges\n", + "[[86.76 87.27]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er O ++\n", + "charge_state\n", + "2\n", + "ranges\n", + "[[89.81 93.86]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er O O ++\n", + "charge_state\n", + "2\n", + "ranges\n", + "[[ 98.8 101.36]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[25 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[25 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [25 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Mn O O O +\n", + "charge_state\n", + "1\n", + "ranges\n", + "[[102.77 103.53]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er O +\n", + "charge_state\n", + "1\n", + "ranges\n", + "[[180.33 187.3 ]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[68 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[68 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]\n", + " [68 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", + " 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "Er O O +\n", + "charge_state\n", + "1\n", + "ranges\n", + "[[197. 203.38]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", + " [8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "O O +\n", + "charge_state\n", + "1\n", + "ranges\n", + "[[31.72 34.3 ]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "unknown_iontype\n", + "charge_state\n", + "0\n", + "ranges\n", + "[[22.24 22.72]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n", + "ion_type\n", + "\n", + "isotope_vector\n", + "[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", + "nuclid_list\n", + "[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]\n", + "human-readable name\n", + "unknown_iontype\n", + "charge_state\n", + "0\n", + "ranges\n", + "[[0.93 3.18]]\n", + "comment\n", + "\n", + "color\n", + "\n", + "volume\n", + "0.0\n" + ] + } + ], + "source": [ + "env = ReadEnvFileFormat(f\"{prefix}/{fnm[0]}\")\n", + "for m_ion in env.env[\"molecular_ions\"]:\n", + " m_ion.report()" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "9dd0fa4d-650d-4978-982c-6f9b2253d614", + "metadata": { + "collapsed": true, + "jupyter": { + "outputs_hidden": true + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "#\n", + "#\n", + "#\t\tGerald Da Costa\t / Alain Bostel\n", + "#\n", + "#\t\tCopyright (C)\tGPM de Rouen\n", + "#\t\tUMR 6634 CNRS - Universite et Insa de Rouen\n", + "#\t\t76821 Mont Saint Aignan Cedex\n", + "#\n", + "#\t\tRev 2.0 : Environment file for 3D Atom Probe\n", + "#\n", + "#\n", + "# Version Id\n", + "Rev_2.0\n", + "# Alloy definition\n", + "# Number of elements / Number of mass ranges\n", + "12\t26\n", + "# List of Element and Color components ( Red / Green / Blue )\n", + "O\t0.0\t1.0\t0.0\n", + "Mn\t0.0\t0.5\t1.0\n", + "Er\t1.0\t0.0\t0.0\n", + "Mn2O\t0.0\t0.0\t0.0\n", + "MnO2\t0.5\t0.5\t0.5\n", + "MnO\t0.5\t0.5\t0.5\n", + "ErO\t1.0\t0.0\t0.0\n", + "ErO2\t1.0\t0.0\t0.0\n", + "MnO3\t0.5\t0.5\t0.5\n", + "O2\t0.0\t0.0\t1.0\n", + "X23\t0.3\t0.5\t0.5\n", + "Hyd\t0.0\t0.0\t0.0\n", + "# Definition of Mass ranges / Atomic volumes / Increment for concentration\n", + "O\t15.880\t16.840\t20.000\t1.000\n", + "Mn\t27.330\t27.950\t11.660\t1.000\n", + "Er\t81.890\t82.360\t11.660\t1.000\n", + "Er\t82.910\t83.410\t11.660\t1.000\n", + "Er\t83.410\t83.910\t11.660\t1.000\n", + "Er\t83.930\t84.900\t11.660\t1.000\n", + "Er\t84.920\t85.450\t11.660\t1.000\n", + "Er\t53.930\t54.130\t11.660\t1.000\n", + "Er\t54.490\t54.750\t11.660\t1.000\n", + "Er\t55.090\t55.550\t11.660\t1.000\n", + "Er\t55.543\t55.880\t11.660\t1.000\n", + "Er\t55.877\t56.270\t11.660\t1.000\n", + "Er\t56.500\t56.970\t11.660\t1.000\n", + "Mn\t54.770\t55.020\t11.660\t1.000\n", + "Mn2O\t62.850\t63.130\t11.660\t1.000\n", + "MnO2\t43.380\t43.650\t11.660\t1.000\n", + "MnO\t70.590\t72.810\t11.660\t1.000\n", + "MnO2\t86.760\t87.270\t11.660\t1.000\n", + "ErO\t89.810\t93.860\t11.660\t1.000\n", + "ErO2\t98.800\t101.360\t11.660\t1.000\n", + "MnO3\t102.770\t103.530\t11.660\t1.000\n", + "ErO\t180.330\t187.300\t11.660\t1.000\n", + "ErO2\t197.000\t203.380\t11.660\t1.000\n", + "O2\t31.720\t34.300\t11.660\t1.000\n", + "X23\t22.240\t22.720\t11.660\t1.000\n", + "Hyd\t0.930\t3.180\t11.660\t1.000\n", + "# Atom probe definition\n", + "# Flight length (m)\n", + "0.100500\n", + "# Pulse fraction (%)\n", + "0.000000\n", + "# Coupling factor (%)\n", + "100.000000\n", + "# Time added to the tof for mass calculation (ns)\n", + "-3.000000\n", + "# Reflectron factor\n", + "1.006500\n", + "# Input Voltage of the detection system (kV)\n", + "2.700000\n", + "# Distance between Grid and MCPin (m)\n", + "0.014000\n", + "# Space definition\n", + "# Ebeta value\n", + "24.000000\n", + "# Projection point value (m+1)\n", + "1.600000\n", + "# Surface of the detection system (m²)\n", + "0.004656\n", + "# Efficiency of the detection system\n", + "0.550000\n", + "# Angle used for the rotation of the tip\n", + "0.000000\n", + "# Angle used for the tilt of the tip\n", + "0.000000\n", + "---->['O', '15.880', '16.840', '20.000', '1.000']\n", + "['O']\n", + "---->['Mn', '27.330', '27.950', '11.660', '1.000']\n", + "['Mn']\n", + "---->['Er', '81.890', '82.360', '11.660', '1.000']\n", + "['Er']\n", + "---->['Er', '82.910', '83.410', '11.660', '1.000']\n", + "['Er']\n", + "---->['Er', '83.410', '83.910', '11.660', '1.000']\n", + "['Er']\n", + "---->['Er', '83.930', '84.900', '11.660', '1.000']\n", + "['Er']\n", + "---->['Er', '84.920', '85.450', '11.660', '1.000']\n", + "['Er']\n", + "---->['Er', '53.930', '54.130', '11.660', '1.000']\n", + "['Er']\n", + "---->['Er', '54.490', '54.750', '11.660', '1.000']\n", + "['Er']\n", + "---->['Er', '55.090', '55.550', '11.660', '1.000']\n", + "['Er']\n", + "---->['Er', '55.543', '55.880', '11.660', '1.000']\n", + "['Er']\n", + "---->['Er', '55.877', '56.270', '11.660', '1.000']\n", + "['Er']\n", + "---->['Er', '56.500', '56.970', '11.660', '1.000']\n", + "['Er']\n", + "---->['Mn', '54.770', '55.020', '11.660', '1.000']\n", + "['Mn']\n", + "---->['Mn2O', '62.850', '63.130', '11.660', '1.000']\n", + "['Mn', 'Mn', 'O']\n", + "---->['MnO2', '43.380', '43.650', '11.660', '1.000']\n", + "['Mn', 'O', 'O']\n", + "---->['MnO', '70.590', '72.810', '11.660', '1.000']\n", + "['Mn', 'O']\n", + "---->['MnO2', '86.760', '87.270', '11.660', '1.000']\n", + "['Mn', 'O', 'O']\n", + "---->['ErO', '89.810', '93.860', '11.660', '1.000']\n", + "['Er', 'O']\n", + "---->['ErO2', '98.800', '101.360', '11.660', '1.000']\n", + "['Er', 'O', 'O']\n", + "---->['MnO3', '102.770', '103.530', '11.660', '1.000']\n", + "['Mn', 'O', 'O', 'O']\n", + "---->['ErO', '180.330', '187.300', '11.660', '1.000']\n", + "['Er', 'O']\n", + "---->['ErO2', '197.000', '203.380', '11.660', '1.000']\n", + "['Er', 'O', 'O']\n", + "---->['O2', '31.720', '34.300', '11.660', '1.000']\n", + "['O', 'O']\n", + "---->['X23', '22.240', '22.720', '11.660', '1.000']\n", + "[]\n", + "---->['Hyd', '0.930', '3.180', '11.660', '1.000']\n", + "[]\n" + ] + } + ], + "source": [ + "def get_smart_chemical_symbols():\n", + " priority_queue = []\n", + " for symbol in chemical_symbols:\n", + " if len(symbol) == 2:\n", + " priority_queue.append(symbol)\n", + " for symbol in chemical_symbols:\n", + " if symbol != \"X\" and len(symbol) == 1:\n", + " priority_queue.append(symbol)\n", + " return priority_queue\n", + "\n", + "\n", + "with open(f\"{prefix}/{fnm[0]}\", mode=\"r\", encoding=\"utf-8\") as envf:\n", + " txt = envf.read()\n", + " txt = txt.replace(\"\\r\\n\", \"\\n\") # windows to unix EOL conversion\n", + " txt = txt.replace(\",\", \".\") # use decimal dots instead of comma\n", + " txt_stripped = [line for line in txt.split(\"\\n\") if line.strip() != \"\"] # and line.startswith(\"#\") is False\n", + " for line in txt_stripped:\n", + " print(line)\n", + " # search for ranging definitions \"# Definition of\"\n", + " rng_s = None\n", + " rng_e = None\n", + " for idx in np.arange(0, len(txt_stripped)):\n", + " if txt_stripped[idx].startswith(\"# Definition of\") is False:\n", + " continue\n", + " else:\n", + " rng_s = idx\n", + " break\n", + " for idx in np.arange(rng_s + 1, len(txt_stripped)):\n", + " if txt_stripped[idx].startswith(\"# Atom probe definition\") is False:\n", + " continue\n", + " else:\n", + " rng_e = idx\n", + " break\n", + " # print(f\"{txt_stripped[rng_s]}\\n{txt_stripped[rng_e]}\")\n", + " for idx in np.arange(rng_s + 1, rng_e):\n", + " tmp = txt_stripped[idx].split()\n", + " # interpret zeroth token into a list of chemical symbols\n", + " print(f\"---->{tmp}\")\n", + " lst = []\n", + " if tmp[0] == \"Hyd\":\n", + " lst = []\n", + " elif tmp[0] in get_smart_chemical_symbols():\n", + " lst.append(tmp[0])\n", + " else: \n", + " tokens = re.split(r'(\\d+)', tmp[0])\n", + " for jdx in np.arange(0, len(tokens)):\n", + " kdx = 0\n", + " for sym in get_smart_chemical_symbols():\n", + " if tokens[jdx][kdx:].startswith(sym) is True:\n", + " mult = 1\n", + " if jdx < len(tokens) - 1:\n", + " if (tokens[jdx][kdx:] == sym) and (tokens[jdx + 1].isdigit() is True):\n", + " mult = int(tokens[jdx + 1])\n", + " kdx += len(tokens[jdx + 1])\n", + " # else:\n", + " # print(\"jdx >\")\n", + " for cnt in np.arange(0, mult):\n", + " lst.append(sym)\n", + " kdx += len(sym)\n", + " print(lst)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "97ed82d1-26e7-46f2-ad4a-8b8625fb46c9", + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "id": "e680a9d0-4005-40b0-ab45-a8f5fb215273", @@ -59,10 +902,11 @@ }, "outputs": [], "source": [ + "# eventually change needed point to the location of the files to analyze\n", "prefix = f\"{os.getcwd()}/../../../../../paper_paper_paper/joss_nomad_apt/bb_analysis/data\"\n", - "fnm = [\"1748_Al.h5\",\n", - " \"1748_Al_range_.h5\",\n", - " \"1748_Nov-14-2023_13-31_Al.h5\"]\n", + "fnm = [\"1748_Nov-14-2023_13-31_Al.h5\",\n", + " \"1748_Al.h5\",\n", + " \"1748_Al_range_.h5\"]\n", "# df = pd.read_hdf(f\"{prefix}/ger_erlangen_pyccapt_format/{fnm[1]}\")\n", "# H5Web(f\"{prefix}/ger_erlangen_pyccapt_format/{fnm[1]}\")\n", "# df" @@ -78,16 +922,6 @@ "from ifes_apt_tc_data_modeling.pyccapt.pyccapt_reader import ReadPyccaptControlFileFormat, ReadPyccaptCalibrationFileFormat, ReadPyccaptRangingFileFormat" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "ac6b2e02-371b-47ff-9c68-b23b6e1b4b83", - "metadata": {}, - "outputs": [], - "source": [ - "pyc_r = ReadPyccaptRangingFileFormat(f\"{prefix}/ger_erlangen_pyccapt_format/{fnm[1]}\")" - ] - }, { "cell_type": "code", "execution_count": null, @@ -95,7 +929,18 @@ "metadata": {}, "outputs": [], "source": [ - "pyc_m = ReadPyccaptControlFileFormat(f\"{prefix}/ger_erlangen_pyccapt_format/{fnm[2]}\")" + "# the actual measurement (comparable to LEAP's STR/RRAW/RHIT/HITS)\n", + "pyc_m = ReadPyccaptControlFileFormat(f\"{prefix}/ger_erlangen_pyccapt_format/{fnm[0]}\")\n", + "\n", + "# the calibrations (voltage, bowl, m/q, comparable to LEAP's ROOT and POS/EPOS)\n", + "pyc_c = ReadPyccaptCalibrationFileFormat(f\"{prefix}/ger_erlangen_pyccapt_format/{fnm[1]}\")\n", + "xyz = pyc_c.get_reconstructed_positions()\n", + "print(xyz.typed_value)\n", + "m_q = pyc_c.get_mass_to_charge_state_ratio()\n", + "print(m_q.typed_value)\n", + "\n", + "# the ranging definitions (comparable to RNG/RRNG)\n", + "pyc_r = ReadPyccaptRangingFileFormat(f\"{prefix}/ger_erlangen_pyccapt_format/{fnm[2]}\")" ] }, { @@ -105,11 +950,7 @@ "metadata": {}, "outputs": [], "source": [ - "pyc_c = ReadPyccaptCalibrationFileFormat(f\"{prefix}/ger_erlangen_pyccapt_format/{fnm[0]}\")\n", - "xyz = pyc_c.get_reconstructed_positions()\n", - "print(xyz.typed_value)\n", - "m_q = pyc_c.get_mass_to_charge_state_ratio()\n", - "print(m_q.typed_value)" + "\n" ] }, { @@ -437,7 +1278,6 @@ "cell_type": "markdown", "id": "9ea7c00f-e3f4-4ac1-bfd5-449303a702a1", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -846,7 +1686,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.5" + "version": "3.10.13" } }, "nbformat": 4, diff --git a/tests/data/env/examples_without_provenance/ErMnO.env b/tests/data/env/examples_without_provenance/ErMnO.env new file mode 100755 index 0000000..db72e93 --- /dev/null +++ b/tests/data/env/examples_without_provenance/ErMnO.env @@ -0,0 +1,112 @@ +# +# +# Gerald Da Costa / Alain Bostel +# +# Copyright (C) GPM de Rouen +# UMR 6634 CNRS - Universite et Insa de Rouen +# 76821 Mont Saint Aignan Cedex +# +# Rev 2.0 : Environment file for 3D Atom Probe +# +# + + + +# Version Id +Rev_2.0 + + +# Alloy definition + +# Number of elements / Number of mass ranges +12 26 + +# List of Element and Color components ( Red / Green / Blue ) +O 0.0 1.0 0.0 +Mn 0.0 0.5 1.0 +Er 1.0 0.0 0.0 +Mn2O 0.0 0.0 0.0 +MnO2 0.5 0.5 0.5 +MnO 0.5 0.5 0.5 +ErO 1.0 0.0 0.0 +ErO2 1.0 0.0 0.0 +MnO3 0.5 0.5 0.5 +O2 0.0 0.0 1.0 +X23 0.3 0.5 0.5 +Hyd 0.0 0.0 0.0 + +# Definition of Mass ranges / Atomic volumes / Increment for concentration +O 15.880 16.840 20.000 1.000 +Mn 27.330 27.950 11.660 1.000 +Er 81.890 82.360 11.660 1.000 +Er 82.910 83.410 11.660 1.000 +Er 83.410 83.910 11.660 1.000 +Er 83.930 84.900 11.660 1.000 +Er 84.920 85.450 11.660 1.000 +Er 53.930 54.130 11.660 1.000 +Er 54.490 54.750 11.660 1.000 +Er 55.090 55.550 11.660 1.000 +Er 55.543 55.880 11.660 1.000 +Er 55.877 56.270 11.660 1.000 +Er 56.500 56.970 11.660 1.000 +Mn 54.770 55.020 11.660 1.000 +Mn2O 62.850 63.130 11.660 1.000 +MnO2 43.380 43.650 11.660 1.000 +MnO 70.590 72.810 11.660 1.000 +MnO2 86.760 87.270 11.660 1.000 +ErO 89.810 93.860 11.660 1.000 +ErO2 98.800 101.360 11.660 1.000 +MnO3 102.770 103.530 11.660 1.000 +ErO 180.330 187.300 11.660 1.000 +ErO2 197.000 203.380 11.660 1.000 +O2 31.720 34.300 11.660 1.000 +X23 22.240 22.720 11.660 1.000 +Hyd 0.930 3.180 11.660 1.000 + + + +# Atom probe definition + +# Flight length (m) +0.100500 + +# Pulse fraction (%) +0.000000 + +# Coupling factor (%) +100.000000 + +# Time added to the tof for mass calculation (ns) +-3.000000 + +# Reflectron factor +1.006500 + +# Input Voltage of the detection system (kV) +2.700000 + +# Distance between Grid and MCPin (m) +0.014000 + + + +# Space definition + +# Ebeta value +24.000000 + +# Projection point value (m+1) +1.600000 + +# Surface of the detection system (m²) +0.004656 + +# Efficiency of the detection system +0.550000 + +# Angle used for the rotation of the tip +0.000000 + +# Angle used for the tilt of the tip +0.000000 + From c896d2c2eea9e3ce70b4cde26a01b03b75797d34 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 28 Dec 2023 20:40:08 +0100 Subject: [PATCH 02/20] Added pycodestyle, pylinting, and mypy, but not all these code quality, cleaning refactoring has been performed yet and that new code needs testing --- dev-requirements.txt | 51 +- ifes_apt_tc_data_modeling/apt/apt6_reader.py | 28 +- .../apt/apt6_sections_branches.py | 4 +- ifes_apt_tc_data_modeling/apt/apt6_utils.py | 3 +- ifes_apt_tc_data_modeling/ato/ato_reader.py | 17 +- ifes_apt_tc_data_modeling/env/env_reader.py | 33 +- ifes_apt_tc_data_modeling/fig/fig_reader.py | 44 +- ifes_apt_tc_data_modeling/nexus/nx_field.py | 9 +- ifes_apt_tc_data_modeling/nexus/nx_ion.py | 14 +- ifes_apt_tc_data_modeling/pos/pos_reader.py | 11 +- .../pyccapt/pyccapt_reader.py | 19 +- ifes_apt_tc_data_modeling/rng/rng_reader.py | 30 +- ifes_apt_tc_data_modeling/rrng/rrng_reader.py | 22 +- ifes_apt_tc_data_modeling/utils/mmapped_io.py | 8 +- .../utils/molecular_ions.py | 108 +- .../utils/nist_isotope_data.py | 6702 ++++++++--------- .../utils/string_handling.py | 6 - ifes_apt_tc_data_modeling/utils/utils.py | 23 +- pyproject.toml | 5 +- tests/TestsForDevelopers.ipynb | 752 +- 20 files changed, 3576 insertions(+), 4313 deletions(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index c34a224..78aa550 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.11 +# This file is autogenerated by pip-compile with Python 3.10 # by the following command: # # pip-compile --extra=dev --output-file=dev-requirements.txt pyproject.toml @@ -14,7 +14,9 @@ argon2-cffi==21.3.0 argon2-cffi-bindings==21.2.0 # via argon2-cffi ase==3.19.0 - # via ifes-apt-tc-data-modeling (pyproject.toml) + # via ifes_apt_tc_data_modeling (pyproject.toml) +astroid==3.0.2 + # via pylint asttokens==2.2.1 # via stack-data attrs==23.1.0 @@ -53,6 +55,8 @@ decorator==5.1.1 # via ipython defusedxml==0.7.1 # via nbconvert +dill==0.3.7 + # via pylint docutils==0.19 # via readme-renderer executing==1.2.0 @@ -66,7 +70,7 @@ h5grove==1.3.0 h5py==3.8.0 # via # h5grove - # ifes-apt-tc-data-modeling (pyproject.toml) + # ifes_apt_tc_data_modeling (pyproject.toml) # jupyterlab-h5web idna==3.4 # via @@ -88,6 +92,8 @@ ipython-genutils==0.2.0 # via # nbclassic # notebook +isort==5.13.2 + # via pylint jaraco-classes==3.2.3 # via keyring jedi==0.18.2 @@ -136,9 +142,9 @@ jupyter-server==1.24.0 # nbclassic # notebook-shim jupyterlab==3.5.3 - # via ifes-apt-tc-data-modeling (pyproject.toml) + # via ifes_apt_tc_data_modeling (pyproject.toml) jupyterlab-h5web==7.1.1 - # via ifes-apt-tc-data-modeling (pyproject.toml) + # via ifes_apt_tc_data_modeling (pyproject.toml) jupyterlab-pygments==0.2.2 # via nbconvert jupyterlab-server==2.22.1 @@ -161,6 +167,8 @@ matplotlib-inline==0.1.6 # via # ipykernel # ipython +mccabe==0.7.0 + # via pylint mdurl==0.1.2 # via markdown-it-py mistune==2.0.5 @@ -171,6 +179,10 @@ mpmath==1.3.0 # via sympy msgpack==1.0.7 # via blosc2 +mypy==1.8.0 + # via ifes_apt_tc_data_modeling (pyproject.toml) +mypy-extensions==1.0.0 + # via mypy nbclassic==0.5.6 # via # jupyterlab @@ -211,7 +223,7 @@ numpy==1.24.3 # contourpy # h5grove # h5py - # ifes-apt-tc-data-modeling (pyproject.toml) + # ifes_apt_tc_data_modeling (pyproject.toml) # matplotlib # numexpr # pandas @@ -231,7 +243,7 @@ packaging==23.1 # nbconvert # tables pandas==2.0.1 - # via ifes-apt-tc-data-modeling (pyproject.toml) + # via ifes_apt_tc_data_modeling (pyproject.toml) pandocfilters==1.5.0 # via nbconvert parso==0.8.3 @@ -245,7 +257,9 @@ pillow==9.5.0 pkginfo==1.9.6 # via twine platformdirs==3.5.0 - # via jupyter-core + # via + # jupyter-core + # pylint prometheus-client==0.16.0 # via # jupyter-server @@ -265,6 +279,8 @@ py-cpuinfo==9.0.0 # via # blosc2 # tables +pycodestyle==2.11.1 + # via ifes_apt_tc_data_modeling (pyproject.toml) pycparser==2.21 # via cffi pygments==2.15.1 @@ -273,6 +289,8 @@ pygments==2.15.1 # nbconvert # readme-renderer # rich +pylint==3.0.3 + # via ifes_apt_tc_data_modeling (pyproject.toml) pyparsing==3.0.9 # via matplotlib pyrsistent==0.19.3 @@ -292,7 +310,7 @@ pyzmq==25.0.2 # nbclassic # notebook radioactivedecay==0.4.17 - # via ifes-apt-tc-data-modeling (pyproject.toml) + # via ifes_apt_tc_data_modeling (pyproject.toml) readme-renderer==37.3 # via twine requests==2.29.0 @@ -331,7 +349,7 @@ stack-data==0.6.2 sympy==1.11.1 # via radioactivedecay tables==3.9.2 - # via ifes-apt-tc-data-modeling (pyproject.toml) + # via ifes_apt_tc_data_modeling (pyproject.toml) terminado==0.17.1 # via # jupyter-server @@ -342,7 +360,12 @@ tifffile==2023.4.12 tinycss2==1.2.1 # via nbconvert tomli==2.0.1 - # via jupyterlab + # via + # jupyterlab + # mypy + # pylint +tomlkit==0.12.3 + # via pylint tornado==6.3.1 # via # ipykernel @@ -367,7 +390,11 @@ traitlets==5.9.0 # nbformat # notebook twine==4.0.2 - # via ifes-apt-tc-data-modeling (pyproject.toml) + # via ifes_apt_tc_data_modeling (pyproject.toml) +typing-extensions==4.9.0 + # via + # astroid + # mypy tzdata==2023.3 # via pandas urllib3==1.26.15 diff --git a/ifes_apt_tc_data_modeling/apt/apt6_reader.py b/ifes_apt_tc_data_modeling/apt/apt6_reader.py index 2c89844..23c231a 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_reader.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_reader.py @@ -1,4 +1,3 @@ -# AMETEK APT(6) data exchange file reader used by atom probe microscopists. # # Copyright The NOMAD Authors. # @@ -17,24 +16,19 @@ # limitations under the License. # +"""AMETEK APT(6) data exchange file reader used by atom probe microscopists.""" + # pylint: disable=no-member,duplicate-code import os - import numpy as np - import pandas as pd from ifes_apt_tc_data_modeling.apt.apt6_utils import np_uint16_to_string - from ifes_apt_tc_data_modeling.apt.apt6_headers import AptFileHeaderMetadata - from ifes_apt_tc_data_modeling.apt.apt6_sections import AptFileSectionMetadata - from ifes_apt_tc_data_modeling.apt.apt6_sections_branches import EXPECTED_SECTIONS - 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 @@ -115,14 +109,14 @@ def parse_file_structure(self): print(keyword) print(found_section) - assert keyword not in self.available_sections.keys(), \ + assert keyword not in self.available_sections, \ 'Found a duplicate of an already parsed section! Please \ contact the development team as we have never encountered \ an example of such a section duplication and here seems \ to be an example to inspect the matter.' if keyword not in ['Delta Pulse', 'Epos ToF']: - assert keyword in EXPECTED_SECTIONS.keys(), \ + assert keyword in EXPECTED_SECTIONS, \ 'Found an unknown section, seems like an unknown/new \ branch! Please contact the development team to enable us \ to contact AMETEK and discuss the situation.' @@ -175,20 +169,19 @@ def get_header(self): # 9714475f1b3bc224ea063af81566d873 repo # for converting Windows/MSDN time to Python time for key, value in iter(metadata_dict.items()): - print(key + ': ' + str(value)) + print(f"{key}: {value}") def get_metadata(self, keyword: str): """Report available metadata for quantity if it exists.""" - if keyword in self.available_sections.keys() \ - and keyword in self.byte_offsets.keys(): + if (keyword in self.available_sections) and (keyword in self.byte_offsets): metadata_dict = self.available_sections[keyword].get_metadata() for key, value in iter(metadata_dict.items()): - print(key + ': ' + str(value)) + print(f"{key}: {value}") def get_metadata_table(self): """Create table from all metadata for each section.""" column_names = ['section'] # header - assert 'Mass' in self.available_sections.keys(), \ + assert 'Mass' in self.available_sections, \ 'Cannot create table, Mass section not available to guide \ the creation of the table header!' for key in self.available_sections['Mass'].get_metadata().keys(): @@ -210,11 +203,10 @@ def get_metadata_table(self): def get_named_quantity(self, keyword: str): """Read quantity with name in keyword from APT file if it exists.""" - if keyword in self.available_sections.keys() \ - and keyword in self.byte_offsets.keys(): + if (keyword in self.available_sections) and (keyword in self.byte_offsets): byte_position_start = self.byte_offsets[keyword] \ - self.available_sections[keyword].get_ametek_size() - print('Reading section ' + keyword + ' at ' + str(byte_position_start)) + print(f"Reading section {keyword} at {byte_position_start}") dtype = self.available_sections[keyword].get_ametek_type() offset = byte_position_start diff --git a/ifes_apt_tc_data_modeling/apt/apt6_sections_branches.py b/ifes_apt_tc_data_modeling/apt/apt6_sections_branches.py index 886b4d9..790b7fe 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_sections_branches.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_sections_branches.py @@ -1,4 +1,3 @@ -# AMETEK APT(6) data exchange file reader used by atom probe microscopists. # # Copyright The NOMAD Authors. # @@ -17,6 +16,9 @@ # limitations under the License. # +"""AMETEK APT(6) data exchange file reader used by atom probe microscopists.""" + + # pylint: disable=no-member,duplicate-code from ifes_apt_tc_data_modeling.apt.apt6_sections import AptFileSectionMetadata diff --git a/ifes_apt_tc_data_modeling/apt/apt6_utils.py b/ifes_apt_tc_data_modeling/apt/apt6_utils.py index e2b2dd6..0a8dc9c 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_utils.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_utils.py @@ -1,4 +1,3 @@ -# AMETEK APT(6) data exchange file reader used by atom probe microscopists. # # Copyright The NOMAD Authors. # @@ -17,6 +16,8 @@ # limitations under the License. # +"""AMETEK APT(6) data exchange file reader used by atom probe microscopists.""" + # pylint: disable=no-member,duplicate-code import numpy as np diff --git a/ifes_apt_tc_data_modeling/ato/ato_reader.py b/ifes_apt_tc_data_modeling/ato/ato_reader.py index 87b759f..f24a6ab 100644 --- a/ifes_apt_tc_data_modeling/ato/ato_reader.py +++ b/ifes_apt_tc_data_modeling/ato/ato_reader.py @@ -1,4 +1,3 @@ -# POS file format reader used by atom probe microscopists. # # Copyright The NOMAD Authors. # @@ -17,10 +16,11 @@ # limitations under the License. # +"""ATO file format reader used by atom probe microscopists.""" + # pylint: disable=no-member,duplicate-code import os - import numpy as np from ifes_apt_tc_data_modeling.nexus.nx_field import NxField @@ -83,7 +83,8 @@ def get_reconstructed_positions(self): for dim in [0, 1, 2]: xyz.typed_value[:, dim] = \ get_memory_mapped_data(self.filename, " x, wpy -> y, fpz -> z if self.version == 5: # publicly available sources are inconclusive whether coordinates are in angstroem or nm @@ -93,10 +94,12 @@ def get_reconstructed_positions(self): # not at all wpx, wpy and fpz but x, y, z instead and here claims the nm xyz.typed_value[:, 0] = \ np.float32(get_memory_mapped_data(self.filename, " x + 5000 + 0, + 40, self.number_of_events) * 0.1) # wpx -> x xyz.typed_value[:, 1] = \ np.float32(get_memory_mapped_data(self.filename, " y + 5000 + 2, + 40, self.number_of_events) * 0.1) # wpy -> y xyz.typed_value[:, 2] = \ get_memory_mapped_data(self.filename, " z @@ -113,9 +116,9 @@ def get_mass_to_charge_state_ratio(self): if self.version == 3: m_n.typed_value[:, 0] = \ get_memory_mapped_data(self.filename, " dict: print(f"WARNING::ENV file ranging definition {line} has insignificant range!") return None - lst = [] + lst: list = [] if tmp[0] == "Hyd": lst = [] elif tmp[0] in get_smart_chemical_symbols(): @@ -83,8 +84,7 @@ def evaluate_env_range_line(line: str) -> dict: if (tokens[jdx][kdx:] == sym) and (tokens[jdx + 1].isdigit() is True): mult = int(tokens[jdx + 1]) kdx += len(tokens[jdx + 1]) - for cnt in np.arange(0, mult): - lst.append(sym) + lst.extend([sym] * mult) kdx += len(sym) info["atoms"] = lst return info @@ -95,7 +95,7 @@ class ReadEnvFileFormat(): def __init__(self, filename: str): if (len(filename) <= 4) or (filename.lower().endswith(".env") is False): - raise ImportError(f"WARNING::ENV file incorrect filename ending or file type!") + raise ImportError("WARNING::ENV file incorrect filename ending or file type!") self.filename = filename self.env: dict = {} self.env["ranges"] = {} @@ -117,15 +117,13 @@ def read_env(self): for idx in np.arange(0, len(txt_stripped)): if txt_stripped[idx].startswith("# Definition of") is False: continue - else: - rng_s = idx - break + rng_s = idx + break for idx in np.arange(rng_s + 1, len(txt_stripped)): if txt_stripped[idx].startswith("# Atom probe definition") is False: continue - else: - rng_e = idx - break + rng_e = idx + break if rng_s is None or rng_e is None: print("WARNING:: No ranging definitions were found!") return @@ -156,12 +154,11 @@ def read_env(self): # print(f"{recovered_charge_state}") m_ion.charge_state = NxField(np.int8(recovered_charge_state), "") m_ion.update_human_readable_name() - m_ion.add_charge_state_model( - {"min_abundance": PRACTICAL_ABUNDANCE, - "min_abundance_product": PRACTICAL_ABUNDANCE_PRODUCT, - "min_half_life": PRACTICAL_MIN_HALF_LIFE, - "sacrifice_isotopic_uniqueness": SACRIFICE_ISOTOPIC_UNIQUENESS}, - m_ion_candidates) + m_ion.add_charge_state_model({"min_abundance": PRACTICAL_ABUNDANCE, + "min_abundance_product": PRACTICAL_ABUNDANCE_PRODUCT, + "min_half_life": PRACTICAL_MIN_HALF_LIFE, + "sacrifice_isotopic_uniqueness": SACRIFICE_ISOTOPIC_UNIQUENESS}, + m_ion_candidates) self.env["molecular_ions"].append(m_ion) print(f"{self.filename} parsed successfully") diff --git a/ifes_apt_tc_data_modeling/fig/fig_reader.py b/ifes_apt_tc_data_modeling/fig/fig_reader.py index 1696ee3..27f621f 100644 --- a/ifes_apt_tc_data_modeling/fig/fig_reader.py +++ b/ifes_apt_tc_data_modeling/fig/fig_reader.py @@ -1,4 +1,3 @@ -# FIG.TXT range file reader used by atom probe microscopists. # # Copyright The NOMAD Authors. # @@ -17,35 +16,30 @@ # limitations under the License. # -# pylint: disable=no-member,duplicate-code +"""Reader for ranging defs extracted from FAU/Erlangen Atom Probe Toolbox Matlab figures FIG.TXT.""" -import re +# pylint: disable=no-member,duplicate-code,too-few-public-methods + +import re import numpy as np +from ase.data import atomic_numbers, chemical_symbols from ifes_apt_tc_data_modeling.nexus.nx_ion import NxField, NxIon - -from ifes_apt_tc_data_modeling.utils.utils import \ - create_isotope_vector, is_range_significant - from ifes_apt_tc_data_modeling.utils.definitions import \ - MQ_EPSILON, MAX_NUMBER_OF_ATOMS_PER_ION - + MAX_NUMBER_OF_ATOMS_PER_ION from ifes_apt_tc_data_modeling.utils.molecular_ions import \ isotope_to_hash, MolecularIonBuilder, \ PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ PRACTICAL_MIN_HALF_LIFE, VERBOSE, SACRIFICE_ISOTOPIC_UNIQUENESS -from ase.data import atomic_numbers, atomic_masses, chemical_symbols - class ReadFigTxtFileFormat(): """Read *.fig.txt file format.""" def __init__(self, filename: str): - assert len(filename) > 7, "FIG.TXT file incorrect filename ending!" - assert filename.lower().endswith(".fig.txt"), \ - "FIG.TXT file incorrect file type!" + if (len(filename) <= 7) or (filename.lower().endswith(".fig.txt") is False): + raise ImportError("WARNING::FIG.TXT file incorrect filename ending or file type!") self.filename = filename self.fig: dict = {} @@ -65,8 +59,8 @@ def read_fig_txt(self): if line.strip() != "" and line.startswith("#") is False] for molecular_ion in txt_stripped: tmp = molecular_ion.split(" ") - mqmin = np.float64(tmp[len(tmp)-2:-1][0]) - mqmax = np.float64(tmp[len(tmp)-1:][0]) + mqmin = np.float64(tmp[len(tmp) - 2:-1][0]) + mqmax = np.float64(tmp[len(tmp) - 1:][0]) ionname = " ".join(tmp[:-2]) # print(f"{ionname} [{mqmin}, {mqmax}]") # ionname = '16O 1H2 + + + + ' @@ -93,14 +87,11 @@ def read_fig_txt(self): multiplier = 1 if len(suffix) == 1: multiplier = int(suffix[0]) - symbol = isotope.replace( \ - str(mass_number), "").replace( \ - str(multiplier), "").replace(" ", "") + symbol = isotope.replace(f"{mass_number}", "").replace(f"{multiplier}", "").replace(" ", "") if (symbol != "X") and (symbol in chemical_symbols): - for cnt in np.arange(0, multiplier): - proton_number = atomic_numbers[symbol] - neutron_number = mass_number - proton_number - ivec.append(isotope_to_hash(proton_number, neutron_number)) + proton_number = atomic_numbers[symbol] + neutron_number = mass_number - proton_number + ivec.extend([isotope_to_hash(proton_number, neutron_number)] * multiplier) ivec = np.sort(np.asarray(ivec, np.uint16))[::-1] ivector = np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,), np.uint16) ivector[0:len(ivec)] = ivec @@ -132,9 +123,4 @@ def read_fig_txt(self): m_ion_candidates) self.fig["molecular_ions"].append(m_ion) - print(self.filename + " parsed successfully") - -if __name__ == "main": - pass - # testing - # parsedFile = ReadFigTxtFileFormat("../../02763-v01.rng.fig.txt") + print(f"{self.filename} parsed successfully") diff --git a/ifes_apt_tc_data_modeling/nexus/nx_field.py b/ifes_apt_tc_data_modeling/nexus/nx_field.py index 4ab0f33..8fb4aff 100644 --- a/ifes_apt_tc_data_modeling/nexus/nx_field.py +++ b/ifes_apt_tc_data_modeling/nexus/nx_field.py @@ -1,4 +1,3 @@ -# Set of utility tools for parsing file formats used by atom probe. # # Also convenience functions are included which translate human-readable ion # names into the isotope_vector description proposed by Kuehbach et al. in @@ -22,13 +21,7 @@ # limitations under the License. # -# pylint: disable=no-member,duplicate-code - -import typing - -from typing import Tuple - -import numpy as np +"""Set of utility tools for parsing file formats used by atom probe.""" class NxField(): diff --git a/ifes_apt_tc_data_modeling/nexus/nx_ion.py b/ifes_apt_tc_data_modeling/nexus/nx_ion.py index dc14f19..a959240 100644 --- a/ifes_apt_tc_data_modeling/nexus/nx_ion.py +++ b/ifes_apt_tc_data_modeling/nexus/nx_ion.py @@ -1,4 +1,3 @@ -# Set of utility tools for parsing file formats used by atom probe. # # Also convenience functions are included which translate human-readable ion # names into the isotope_vector description proposed by Kuehbach et al. in @@ -22,11 +21,9 @@ # limitations under the License. # -# pylint: disable=no-member,duplicate-code - -import typing +"""Set of utility tools for parsing file formats used by atom probe.""" -from typing import Tuple +# pylint: disable=no-member,duplicate-code import numpy as np @@ -34,8 +31,7 @@ MAX_NUMBER_OF_ATOMS_PER_ION from ifes_apt_tc_data_modeling.utils.utils import \ create_isotope_vector, isotope_vector_to_nuclid_list, \ - isotope_vector_to_human_readable_name, \ - is_range_overlapping, is_range_significant + isotope_vector_to_human_readable_name, is_range_significant from ifes_apt_tc_data_modeling.utils.molecular_ions import MolecularIonCandidate @@ -121,8 +117,8 @@ def report(self): print(self.volume.typed_value) def add_charge_state_model(self, - parameters={}, - candidates=[]): + parameters={}, + candidates=[]): """Add details about the model how self.charge_state was defined.""" self.charge_state_model = {} assert "min_abundance" in parameters.keys(), \ diff --git a/ifes_apt_tc_data_modeling/pos/pos_reader.py b/ifes_apt_tc_data_modeling/pos/pos_reader.py index 1a12ec5..c0ba7d5 100644 --- a/ifes_apt_tc_data_modeling/pos/pos_reader.py +++ b/ifes_apt_tc_data_modeling/pos/pos_reader.py @@ -1,4 +1,3 @@ -# POS file format reader used by atom probe microscopists. # # Copyright The NOMAD Authors. # @@ -17,14 +16,14 @@ # limitations under the License. # +"""POS file format reader used by atom probe microscopists.""" + # 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 @@ -32,9 +31,9 @@ class ReadPosFileFormat(): """Read *.pos file format.""" def __init__(self, filename: str): - assert len(filename) > 4, "POS file incorrect filename ending!" - assert filename.lower().endswith(".pos"), \ - "POS file incorrect file type!" + """Initialize the reader.""" + if (len(filename) <= 4) or (filename.lower().endswith(".pos") is False): + raise ImportError("WARNING::POS file incorrect filename ending or file type!") self.filename = filename self.filesize = os.path.getsize(self.filename) diff --git a/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py b/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py index 5b793d5..0c276f1 100644 --- a/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py +++ b/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py @@ -1,4 +1,3 @@ -# POS file format reader used by atom probe microscopists. # # Copyright The NOMAD Authors. # @@ -17,15 +16,15 @@ # limitations under the License. # +"""Reader for FAU/Erlangen's HDF5-based formats introduced with the pyccapt library.""" + # pylint: disable=no-member,duplicate-code import os - import h5py - import numpy as np - import pandas as pd +from typing import Dict from ase.data import atomic_numbers, chemical_symbols from ifes_apt_tc_data_modeling.nexus.nx_ion import NxIon @@ -44,9 +43,9 @@ # instructed as a set of Matlab live scripts this toolbox offers data analysis functionalities, # results are stored via an HDF5 file -# specific comments +# specific comments # pyccapt/control -# an HDF5 file keeping relevant quantities +# an HDF5 file keeping relevant quantities # pyccapt/calibration # unfortunately the generated HDF5 file has internally no provenance information @@ -116,12 +115,12 @@ def __init__(self, filename: str): self.df = pd.read_hdf(self.filename) self.number_of_events = np.shape(self.df)[0] - + def get_named_quantities(self, term: str): if term in self.df.keys(): return self.df[term] return None - + def get_reconstructed_positions(self): """Read xyz columns.""" @@ -179,7 +178,7 @@ def __init__(self, filename: str): return self.df = pd.read_hdf(self.filename) - self.rng = {} + self.rng: Dict = {} self.rng["molecular_ions"] = [] print(np.shape(self.df)[0]) for idx in np.arange(0, np.shape(self.df)[0]): @@ -201,7 +200,7 @@ def __init__(self, filename: str): for mult in np.arange(0, complexs[idxj]): hashvector.append(isotope_to_hash(proton_number, neutron_number)) ivec[0:len(hashvector)] = np.sort(np.asarray(hashvector, np.uint16), kind="stable")[::-1] - + m_ion = NxIon() m_ion.isotope_vector.typed_value = ivec m_ion.nuclid_list.typed_value = isotope_vector_to_nuclid_list(ivec) diff --git a/ifes_apt_tc_data_modeling/rng/rng_reader.py b/ifes_apt_tc_data_modeling/rng/rng_reader.py index ad42bf5..aa672f9 100644 --- a/ifes_apt_tc_data_modeling/rng/rng_reader.py +++ b/ifes_apt_tc_data_modeling/rng/rng_reader.py @@ -1,4 +1,3 @@ -# RNG range file reader used by atom probe microscopists. # # Copyright The NOMAD Authors. # @@ -17,22 +16,22 @@ # limitations under the License. # +"""RNG range file reader used by atom probe microscopists.""" + # pylint: disable=no-member,duplicate-code import re - import numpy as np +from ase.data import chemical_symbols from ifes_apt_tc_data_modeling.nexus.nx_ion import NxField, NxIon from ifes_apt_tc_data_modeling.utils.utils import \ create_isotope_vector, is_range_significant from ifes_apt_tc_data_modeling.utils.definitions import MQ_EPSILON -from ifes_apt_tc_data_modeling.utils.molecular_ions import MolecularIonBuilder -from ifes_apt_tc_data_modeling.utils.molecular_ions import \ +from ifes_apt_tc_data_modeling.utils.molecular_ions import MolecularIonBuilder, \ PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ PRACTICAL_MIN_HALF_LIFE, VERBOSE, SACRIFICE_ISOTOPIC_UNIQUENESS -from ase.data import atomic_numbers, atomic_masses, chemical_symbols # there are specific examples for unusual range files here: # https://hg.sr.ht/~mycae/libatomprobe/browse/test/samples/ranges?rev=tip @@ -66,14 +65,13 @@ def evaluate_rng_range_line( "Line " + line + " no element counts!" if np.sum(element_multiplicity) > 0: for j in np.arange(0, len(element_multiplicity)): - assert element_multiplicity[j] >= 0, "Line " + line \ - + " no negative element counts!" + assert element_multiplicity[j] >= 0, \ + f"Line {line} no negative element counts!" if element_multiplicity[j] > 0: symbol = column_id_to_label[j + 1] if (symbol in chemical_symbols) and (symbol != "X"): - info["atoms"] = np.append( - info["atoms"], [column_id_to_label[j + 1]] \ - * int(element_multiplicity[j])) + info["atoms"] = np.append(info["atoms"], + [column_id_to_label[j + 1]] * int(element_multiplicity[j])) else: info["name"] = symbol info["atoms"] = [] # will map to unknown type @@ -91,7 +89,7 @@ def evaluate_rng_ion_type_header(line: str) -> dict: # line = "------------------- Fe Mg Al Mn Si V C Ga Ti Ca O Na Co H" # line = "---- a" # line = "----------------- Sc Fe O C Al Si Cr H unknown" - info = {} + info: dict = {} info["column_id_to_label"] = {} tmp = re.split(r"\s+", line) assert len(tmp) > 1, "RNG file does not contain iontype labels!" @@ -104,9 +102,8 @@ class ReadRngFileFormat(): """Read *.rng file format.""" def __init__(self, filename: str): - assert len(filename) > 4, "RNG file incorrect filename ending!" - assert filename.lower().endswith(".rng"), \ - "RNG file incorrect file type!" + if (len(filename) <= 4) or (filename.lower().endswith(".rng") is False): + raise ImportError("WARNING::RNG file incorrect filename ending or file type!") self.filename = filename self.rng: dict = {} @@ -193,8 +190,3 @@ def read_rng(self): self.rng["molecular_ions"].append(m_ion) print(f"{self.filename} parsed successfully") - -if __name__ == "main": - pass - # testing - # parsedFile = ReadRngFileFormat("../../SeHoKim_R5076_44076_v02.rng") diff --git a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py index 3a043e1..05b85e7 100644 --- a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py +++ b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py @@ -1,4 +1,3 @@ -# RRNG range file reader used by atom probe microscopists. # # Copyright The NOMAD Authors. # @@ -17,12 +16,14 @@ # limitations under the License. # +"""RRNG range file reader used by atom probe microscopists.""" + # pylint: disable=no-member,duplicate-code import re - import numpy as np +from ase.data import chemical_symbols from ifes_apt_tc_data_modeling.nexus.nx_ion import NxField, NxIon from ifes_apt_tc_data_modeling.utils.utils import \ create_isotope_vector, is_range_significant @@ -32,8 +33,6 @@ PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ PRACTICAL_MIN_HALF_LIFE, VERBOSE, SACRIFICE_ISOTOPIC_UNIQUENESS -from ase.data import atomic_numbers, atomic_masses, chemical_symbols - def evaluate_rrng_range_line(i: int, line: str) -> dict: """Evaluate information content of a single range line.""" @@ -63,7 +62,7 @@ def evaluate_rrng_range_line(i: int, line: str) -> dict: if tmp[3].lower().startswith("vol:"): info["volume"] = np.float64(re.split(r":", tmp[3])[1]) if (tmp[-1].lower().startswith("color:")) and \ - (len(re.split(r":", tmp[-1])[1]) == 6): + (len(re.split(r":", tmp[-1])[1]) == 6): info["color"] = "#" + re.split(r":", tmp[-1])[1] # HEX_COLOR_REGEX = r"^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$" # replace r"^#( ... @@ -73,7 +72,7 @@ def evaluate_rrng_range_line(i: int, line: str) -> dict: for information in tmp[4:-1]: element_multiplicity = re.split(r":+", information) assert len(element_multiplicity) == 2, \ - "Element multiplicity is incorrectly formatted!" + "Element multiplicity is incorrectly formatted!" # skip vol, name, and color information if element_multiplicity[0].lower() == "name": info["name"] = str(element_multiplicity[1]) @@ -99,9 +98,9 @@ class ReadRrngFileFormat(): """Read *.rrng file format.""" def __init__(self, filename: str): - assert len(filename) > 5, "RRNG file incorrect filename ending!" - assert filename.lower().endswith(".rrng"), \ - "RRNG file incorrect file type!" + """Initialize the class.""" + if (len(filename) <= 5) or (filename.lower().endswith(".rrng") is False): + raise ImportError("WARNING::RRNG file incorrect filename ending or file type!") self.filename = filename self.rrng: dict = {} @@ -201,8 +200,3 @@ def read_rrng(self): self.rrng["molecular_ions"].append(m_ion) print(self.filename + " parsed successfully") - -if __name__ == "main": - pass - # testing - # parsedFile = ReadRrngFileFormat("../../R31_06365-v02.rrng") diff --git a/ifes_apt_tc_data_modeling/utils/mmapped_io.py b/ifes_apt_tc_data_modeling/utils/mmapped_io.py index a3c0d2f..1099e17 100644 --- a/ifes_apt_tc_data_modeling/utils/mmapped_io.py +++ b/ifes_apt_tc_data_modeling/utils/mmapped_io.py @@ -1,4 +1,3 @@ -# Utility for parsing files via memory mapping. # # Also convenience functions are included which translate human-readable ion # names into the isotope_vector description proposed by Kuehbach et al. in @@ -22,14 +21,13 @@ # limitations under the License. # -# pylint: disable=no-member,duplicate-code +"""Utility for parsing files via memory mapping.""" -import typing -from typing import Tuple +# pylint: disable=no-member,duplicate-code +import typing import mmap - import numpy as np diff --git a/ifes_apt_tc_data_modeling/utils/molecular_ions.py b/ifes_apt_tc_data_modeling/utils/molecular_ions.py index 6847f89..c3058c1 100644 --- a/ifes_apt_tc_data_modeling/utils/molecular_ions.py +++ b/ifes_apt_tc_data_modeling/utils/molecular_ions.py @@ -1,9 +1,3 @@ -# Utility tool to work with molecular ions in atom probe microscopy. -# -# Also convenience functions are included which translate human-readable ion -# names into the isotope_vector description proposed by Kuehbach et al. in -# DOI: 10.1017/S1431927621012241 to the human-readable ion names which are use -# in P. Felfer et al.'s atom probe toolbox # # Copyright The NOMAD Authors. # @@ -22,22 +16,16 @@ # limitations under the License. # -# pylint: disable=no-member,duplicate-code - -import typing +"""Utility tool to work with molecular ions in atom probe microscopy.""" -from typing import Tuple +# pylint: disable=no-member,duplicate-code import numpy as np - import radioactivedecay as rd -import ase -from ase.data import atomic_numbers, atomic_masses, atomic_names - +from ase.data import atomic_numbers from ifes_apt_tc_data_modeling.utils.utils import \ isotope_to_hash, hash_to_isotope, isotope_vector_to_dict_keyword - from ifes_apt_tc_data_modeling.utils.nist_isotope_data import isotopes # do not consider isotopes with a very low natural abundance @@ -57,11 +45,16 @@ # molecular ion candidate (which is non-trivial and maybe not even # with first principles theory possible... SACRIFICE_ISOTOPIC_UNIQUENESS = True -VERBOSE=False +VERBOSE = False class MolecularIonCandidate: - def __init__(self, ivec=[], charge_state=0, mass_sum=0., nat_abun_prod=0., min_half_life=np.inf): + def __init__(self, + ivec=[], + charge_state=0, + mass_sum=0., + nat_abun_prod=0., + min_half_life=np.inf): self.isotope_vector = np.asarray(np.atleast_1d(ivec), np.uint16) self.charge_state = np.int8(charge_state) self.mass = np.float64(mass_sum) @@ -97,6 +90,7 @@ def __init__(self, self.parms["min_half_life"] = min_half_life self.parms["sacrifice_isotopic_uniqueness"] = sacrifice_uniqueness self.parms["verbose"] = verbose + self.relevant = {} for symbol, atomic_number in atomic_numbers.items(): if symbol != "X": @@ -110,10 +104,10 @@ def __init__(self, unclear_half_life = False # test if half-life data available - trial_nuclid_name = symbol + "-" + str(mass_number) + trial_nuclid_name = f"{symbol}-{mass_number}" try: tmp = rd.Nuclide(trial_nuclid_name) - except: + except ValueError: tmp = None if tmp is not None: half_life = tmp.half_life() @@ -131,8 +125,8 @@ def __init__(self, # do not consider exotic isotopes with unclear # half-life as they are likely anyway irrelevant # for practical atom probe experiments - half_life = np.nan - unclear_half_life = True + # half_life = np.nan + # unclear_half_life = True # get ase abundance data n_protons = atomic_numbers[symbol] @@ -152,7 +146,7 @@ def __init__(self, self.nuclid_stable[hashvalue] = observationally_stable self.nuclid_unclear[hashvalue] = unclear_half_life self.nuclid_halflife[hashvalue] = half_life - assert np.uint16(0) not in self.nuclid_mass.keys(), \ + assert np.uint16(0) not in self.nuclid_mass, \ "0 must not be a key in nuclid_mass dict!" element_isotopes = np.append(element_isotopes, hashvalue) self.element_isotopes[atomic_number] = np.sort( @@ -221,7 +215,6 @@ def combinatorics(self, element_arr, low, high): # as an example the molecular ion C:2 H:1 will map to 6, 6, 1 max_depth = 0 # number of non-zero entries in element_arr for hashvalue in element_arr: - n_protons, n_neutrons = hash_to_isotope(hashvalue) if hashvalue != 0: max_depth += 1 if self.parms["verbose"] is True: @@ -241,8 +234,7 @@ def combinatorics(self, element_arr, low, high): print(f"Found {len(self.candidates)} candidates!") return self.try_to_reduce_to_unique_solution() # will return a tuple of charge_state and list of relevant_candidates - else: - return (0, []) + return (0, []) def iterate_molecular_ion(self, element_arr, jth_nuclids, cand_arr_prev, @@ -265,7 +257,7 @@ def iterate_molecular_ion(self, new_halflife = self.get_shortest_half_life(cand_arr_curr) for new_chrg in np.arange(1, 8): - mass_to_charge = new_mass / new_chrg; + mass_to_charge = new_mass / new_chrg if mass_to_charge < low: break # we can break the entire charge state generation here already instead of continue @@ -275,28 +267,32 @@ def iterate_molecular_ion(self, if mass_to_charge > high: # can be optimized and broken out of earlier if testing first chrg == 1 # and then chrg == APTMOLECULARION_MAX_CHANGE - continue; + continue # must not be break here because with adding more charge # we usually walk from right to left eventually into [low, high] ! # molecular ion is within user-specified bounds self.candidates.append( - MolecularIonCandidate(cand_arr_curr, new_chrg, new_mass, new_abun_prod, new_halflife)) + MolecularIonCandidate(cand_arr_curr, + new_chrg, + new_mass, + new_abun_prod, + new_halflife)) # do not start a new recursion else: # break the recursion return def try_to_reduce_to_unique_solution(self): - """Hueristics to identify if current candidates are unique.""" + """Heuristics to identify if current candidates are unique.""" if self.parms["verbose"] is True: print(f"Reduce set of {len(self.candidates)} candidates to a unique...") self.relevant = {} for cand in self.candidates: if cand.abundance_product >= self.parms["min_abundance_product"]: - if np.isnan(cand.shortest_half_life) == False: + if np.isnan(cand.shortest_half_life) is False: if cand.shortest_half_life >= self.parms["min_half_life"]: keyword = cand.unique_keyword() - if keyword not in self.relevant.keys(): + if keyword not in self.relevant: self.relevant[keyword] = cand relevant_candidates = [] if self.parms["verbose"] is True: @@ -312,40 +308,38 @@ def try_to_reduce_to_unique_solution(self): print("WARNING::No relevant candidate meets all criteria!") print("WARNING::No solution possible for given criteria!") return (0, relevant_candidates) - elif len(self.relevant) == 1: + if len(self.relevant) == 1: if self.parms["verbose"] is True: print("One relevant candidate which meets all criteria") keywords = [] - for key in self.relevant.keys(): + for key in self.relevant: if isinstance(key, str): keywords.append(key) assert len(keywords) >= 1, "List of relevant keywords is empty!" return (self.relevant[keywords[0]].charge_state, relevant_candidates) - else: - if self.parms["verbose"] is True: - print("Multiple relevant candidates meet all selection criteria") - keywords = [] - for key in self.relevant.keys(): - if isinstance(key, str): - keywords.append(key) - assert len(keywords) >= 1, "List of relevant keywords is empty!" - charge_state = self.relevant[keywords[0]].charge_state - for key, val in self.relevant.items(): - if val.charge_state == charge_state: - continue - else: - if self.parms["verbose"] is True: - print("WARNING::Multiple relevant candidates differ in charge_state!") - print("WARNING::No unique solution possible for given criteria!") - return (0, relevant_candidates) - # not returned yet, so all relevant candidates have the same charge_state - if self.parms["verbose"] is True: - print(f"Multiple relevant candidates have all the same charge_state {charge_state}") - if self.parms["sacrifice_isotopic_uniqueness"] is True: - return (charge_state, relevant_candidates) + if self.parms["verbose"] is True: + print("Multiple relevant candidates meet all selection criteria") + keywords = [] + for key in self.relevant: + if isinstance(key, str): + keywords.append(key) + assert len(keywords) >= 1, "List of relevant keywords is empty!" + charge_state = self.relevant[keywords[0]].charge_state + for key, val in self.relevant.items(): + if val.charge_state == charge_state: + continue if self.parms["verbose"] is True: - print("WARNING::Multiple relevant candidates differ in isotopes!") - print("WARNING::But these have the same charge_state!") + print("WARNING::Multiple relevant candidates differ in charge_state!") print("WARNING::No unique solution possible for given criteria!") return (0, relevant_candidates) + # not returned yet, so all relevant candidates have the same charge_state + if self.parms["verbose"] is True: + print(f"Multiple relevant candidates have all the same charge_state {charge_state}") + if self.parms["sacrifice_isotopic_uniqueness"] is True: + return (charge_state, relevant_candidates) + if self.parms["verbose"] is True: + print("WARNING::Multiple relevant candidates differ in isotopes!") + print("WARNING::But these have the same charge_state!") + print("WARNING::No unique solution possible for given criteria!") + return (0, relevant_candidates) diff --git a/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py b/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py index 3d38e15..cd12cf6 100644 --- a/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py +++ b/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py @@ -24,3354 +24,3354 @@ # to avoid having to download the data on-the-fly because ase uses requests isotopes = {1: {1: {"mass": 1.00782503223, "composition": 0.999885}, - 2: {"mass": 2.01410177812, "composition": 0.000115}, - 3: {"mass": 3.0160492779, "composition": 0.0}, - 4: {"mass": 4.02643, "composition": 0.0}, - 5: {"mass": 5.035311, "composition": 0.0}, - 6: {"mass": 6.04496, "composition": 0.0}, - 7: {"mass": 7.0527, "composition": 0.0}}, - 2: {3: {"mass": 3.0160293201, "composition": 1.34e-06}, - 4: {"mass": 4.00260325413, "composition": 0.99999866}, - 5: {"mass": 5.012057, "composition": 0.0}, - 6: {"mass": 6.018885891, "composition": 0.0}, - 7: {"mass": 7.0279907, "composition": 0.0}, - 8: {"mass": 8.03393439, "composition": 0.0}, - 9: {"mass": 9.043946, "composition": 0.0}, - 10: {"mass": 10.05279, "composition": 0.0}}, - 3: {3: {"mass": 3.0308, "composition": 0.0}, - 4: {"mass": 4.02719, "composition": 0.0}, - 5: {"mass": 5.012538, "composition": 0.0}, - 6: {"mass": 6.0151228874, "composition": 0.0759}, - 7: {"mass": 7.0160034366, "composition": 0.9241}, - 8: {"mass": 8.022486246, "composition": 0.0}, - 9: {"mass": 9.02679019, "composition": 0.0}, - 10: {"mass": 10.035483, "composition": 0.0}, - 11: {"mass": 11.04372358, "composition": 0.0}, - 12: {"mass": 12.052517, "composition": 0.0}, - 13: {"mass": 13.06263, "composition": 0.0}}, - 4: {5: {"mass": 5.0399, "composition": 0.0}, - 6: {"mass": 6.0197264, "composition": 0.0}, - 7: {"mass": 7.016928717, "composition": 0.0}, - 8: {"mass": 8.005305102, "composition": 0.0}, - 9: {"mass": 9.012183065, "composition": 1.0}, - 10: {"mass": 10.013534695, "composition": 0.0}, - 11: {"mass": 11.02166108, "composition": 0.0}, - 12: {"mass": 12.0269221, "composition": 0.0}, - 13: {"mass": 13.036135, "composition": 0.0}, - 14: {"mass": 14.04289, "composition": 0.0}, - 15: {"mass": 15.05342, "composition": 0.0}, - 16: {"mass": 16.06167, "composition": 0.0}}, - 5: {6: {"mass": 6.0508, "composition": 0.0}, - 7: {"mass": 7.029712, "composition": 0.0}, - 8: {"mass": 8.0246073, "composition": 0.0}, - 9: {"mass": 9.01332965, "composition": 0.0}, - 10: {"mass": 10.01293695, "composition": 0.199}, - 11: {"mass": 11.00930536, "composition": 0.801}, - 12: {"mass": 12.0143527, "composition": 0.0}, - 13: {"mass": 13.0177802, "composition": 0.0}, - 14: {"mass": 14.025404, "composition": 0.0}, - 15: {"mass": 15.031088, "composition": 0.0}, - 16: {"mass": 16.039842, "composition": 0.0}, - 17: {"mass": 17.04699, "composition": 0.0}, - 18: {"mass": 18.05566, "composition": 0.0}, - 19: {"mass": 19.0631, "composition": 0.0}, - 20: {"mass": 20.07207, "composition": 0.0}, - 21: {"mass": 21.08129, "composition": 0.0}}, - 6: {8: {"mass": 8.037643, "composition": 0.0}, - 9: {"mass": 9.0310372, "composition": 0.0}, - 10: {"mass": 10.01685331, "composition": 0.0}, - 11: {"mass": 11.0114336, "composition": 0.0}, - 12: {"mass": 12.0, "composition": 0.9893}, - 13: {"mass": 13.00335483507, "composition": 0.0107}, - 14: {"mass": 14.0032419884, "composition": 0.0}, - 15: {"mass": 15.01059926, "composition": 0.0}, - 16: {"mass": 16.0147013, "composition": 0.0}, - 17: {"mass": 17.022577, "composition": 0.0}, - 18: {"mass": 18.026751, "composition": 0.0}, - 19: {"mass": 19.0348, "composition": 0.0}, - 20: {"mass": 20.04032, "composition": 0.0}, - 21: {"mass": 21.049, "composition": 0.0}, - 22: {"mass": 22.05753, "composition": 0.0}, - 23: {"mass": 23.0689, "composition": 0.0}}, - 7: {10: {"mass": 10.04165, "composition": 0.0}, - 11: {"mass": 11.026091, "composition": 0.0}, - 12: {"mass": 12.0186132, "composition": 0.0}, - 13: {"mass": 13.00573861, "composition": 0.0}, - 14: {"mass": 14.00307400443, "composition": 0.99636}, - 15: {"mass": 15.00010889888, "composition": 0.00364}, - 16: {"mass": 16.0061019, "composition": 0.0}, - 17: {"mass": 17.008449, "composition": 0.0}, - 18: {"mass": 18.014078, "composition": 0.0}, - 19: {"mass": 19.017022, "composition": 0.0}, - 20: {"mass": 20.023366, "composition": 0.0}, - 21: {"mass": 21.02711, "composition": 0.0}, - 22: {"mass": 22.03439, "composition": 0.0}, - 23: {"mass": 23.04114, "composition": 0.0}, - 24: {"mass": 24.05039, "composition": 0.0}, - 25: {"mass": 25.0601, "composition": 0.0}}, - 8: {12: {"mass": 12.034262, "composition": 0.0}, - 13: {"mass": 13.024815, "composition": 0.0}, - 14: {"mass": 14.00859636, "composition": 0.0}, - 15: {"mass": 15.00306562, "composition": 0.0}, - 16: {"mass": 15.99491461957, "composition": 0.99757}, - 17: {"mass": 16.9991317565, "composition": 0.00038}, - 18: {"mass": 17.99915961286, "composition": 0.00205}, - 19: {"mass": 19.003578, "composition": 0.0}, - 20: {"mass": 20.00407535, "composition": 0.0}, - 21: {"mass": 21.008655, "composition": 0.0}, - 22: {"mass": 22.009966, "composition": 0.0}, - 23: {"mass": 23.015696, "composition": 0.0}, - 24: {"mass": 24.01986, "composition": 0.0}, - 25: {"mass": 25.02936, "composition": 0.0}, - 26: {"mass": 26.03729, "composition": 0.0}, - 27: {"mass": 27.04772, "composition": 0.0}, - 28: {"mass": 28.05591, "composition": 0.0}}, - 9: {14: {"mass": 14.034315, "composition": 0.0}, - 15: {"mass": 15.018043, "composition": 0.0}, - 16: {"mass": 16.0114657, "composition": 0.0}, - 17: {"mass": 17.00209524, "composition": 0.0}, - 18: {"mass": 18.00093733, "composition": 0.0}, - 19: {"mass": 18.99840316273, "composition": 1.0}, - 20: {"mass": 19.999981252, "composition": 0.0}, - 21: {"mass": 20.9999489, "composition": 0.0}, - 22: {"mass": 22.002999, "composition": 0.0}, - 23: {"mass": 23.003557, "composition": 0.0}, - 24: {"mass": 24.008115, "composition": 0.0}, - 25: {"mass": 25.012199, "composition": 0.0}, - 26: {"mass": 26.020038, "composition": 0.0}, - 27: {"mass": 27.02644, "composition": 0.0}, - 28: {"mass": 28.03534, "composition": 0.0}, - 29: {"mass": 29.04254, "composition": 0.0}, - 30: {"mass": 30.05165, "composition": 0.0}, - 31: {"mass": 31.05971, "composition": 0.0}}, - 10: {16: {"mass": 16.02575, "composition": 0.0}, - 17: {"mass": 17.01771396, "composition": 0.0}, - 18: {"mass": 18.0057087, "composition": 0.0}, - 19: {"mass": 19.00188091, "composition": 0.0}, - 20: {"mass": 19.9924401762, "composition": 0.9048}, - 21: {"mass": 20.993846685, "composition": 0.0027}, - 22: {"mass": 21.991385114, "composition": 0.0925}, - 23: {"mass": 22.99446691, "composition": 0.0}, - 24: {"mass": 23.99361065, "composition": 0.0}, - 25: {"mass": 24.997789, "composition": 0.0}, - 26: {"mass": 26.000515, "composition": 0.0}, - 27: {"mass": 27.007553, "composition": 0.0}, - 28: {"mass": 28.01212, "composition": 0.0}, - 29: {"mass": 29.01975, "composition": 0.0}, - 30: {"mass": 30.02473, "composition": 0.0}, - 31: {"mass": 31.0331, "composition": 0.0}, - 32: {"mass": 32.03972, "composition": 0.0}, - 33: {"mass": 33.04938, "composition": 0.0}, - 34: {"mass": 34.05673, "composition": 0.0}}, - 11: {18: {"mass": 18.02688, "composition": 0.0}, - 19: {"mass": 19.01388, "composition": 0.0}, - 20: {"mass": 20.0073544, "composition": 0.0}, - 21: {"mass": 20.99765469, "composition": 0.0}, - 22: {"mass": 21.99443741, "composition": 0.0}, - 23: {"mass": 22.989769282, "composition": 1.0}, - 24: {"mass": 23.99096295, "composition": 0.0}, - 25: {"mass": 24.989954, "composition": 0.0}, - 26: {"mass": 25.9926346, "composition": 0.0}, - 27: {"mass": 26.9940765, "composition": 0.0}, - 28: {"mass": 27.998939, "composition": 0.0}, - 29: {"mass": 29.0028771, "composition": 0.0}, - 30: {"mass": 30.0090979, "composition": 0.0}, - 31: {"mass": 31.013163, "composition": 0.0}, - 32: {"mass": 32.02019, "composition": 0.0}, - 33: {"mass": 33.02573, "composition": 0.0}, - 34: {"mass": 34.03359, "composition": 0.0}, - 35: {"mass": 35.04062, "composition": 0.0}, - 36: {"mass": 36.04929, "composition": 0.0}, - 37: {"mass": 37.05705, "composition": 0.0}}, - 12: {19: {"mass": 19.034169, "composition": 0.0}, - 20: {"mass": 20.01885, "composition": 0.0}, - 21: {"mass": 21.011716, "composition": 0.0}, - 22: {"mass": 21.99957065, "composition": 0.0}, - 23: {"mass": 22.99412421, "composition": 0.0}, - 24: {"mass": 23.985041697, "composition": 0.7899}, - 25: {"mass": 24.985836976, "composition": 0.1}, - 26: {"mass": 25.982592968, "composition": 0.1101}, - 27: {"mass": 26.984340624, "composition": 0.0}, - 28: {"mass": 27.9838767, "composition": 0.0}, - 29: {"mass": 28.988617, "composition": 0.0}, - 30: {"mass": 29.9904629, "composition": 0.0}, - 31: {"mass": 30.996648, "composition": 0.0}, - 32: {"mass": 31.9991102, "composition": 0.0}, - 33: {"mass": 33.0053271, "composition": 0.0}, - 34: {"mass": 34.008935, "composition": 0.0}, - 35: {"mass": 35.01679, "composition": 0.0}, - 36: {"mass": 36.02188, "composition": 0.0}, - 37: {"mass": 37.03037, "composition": 0.0}, - 38: {"mass": 38.03658, "composition": 0.0}, - 39: {"mass": 39.04538, "composition": 0.0}, - 40: {"mass": 40.05218, "composition": 0.0}}, - 13: {21: {"mass": 21.02897, "composition": 0.0}, - 22: {"mass": 22.01954, "composition": 0.0}, - 23: {"mass": 23.00724435, "composition": 0.0}, - 24: {"mass": 23.9999489, "composition": 0.0}, - 25: {"mass": 24.9904281, "composition": 0.0}, - 26: {"mass": 25.986891904, "composition": 0.0}, - 27: {"mass": 26.98153853, "composition": 1.0}, - 28: {"mass": 27.98191021, "composition": 0.0}, - 29: {"mass": 28.9804565, "composition": 0.0}, - 30: {"mass": 29.98296, "composition": 0.0}, - 31: {"mass": 30.983945, "composition": 0.0}, - 32: {"mass": 31.988085, "composition": 0.0}, - 33: {"mass": 32.990909, "composition": 0.0}, - 34: {"mass": 33.996705, "composition": 0.0}, - 35: {"mass": 34.999764, "composition": 0.0}, - 36: {"mass": 36.00639, "composition": 0.0}, - 37: {"mass": 37.01053, "composition": 0.0}, - 38: {"mass": 38.0174, "composition": 0.0}, - 39: {"mass": 39.02254, "composition": 0.0}, - 40: {"mass": 40.03003, "composition": 0.0}, - 41: {"mass": 41.03638, "composition": 0.0}, - 42: {"mass": 42.04384, "composition": 0.0}, - 43: {"mass": 43.05147, "composition": 0.0}}, - 14: {22: {"mass": 22.03579, "composition": 0.0}, - 23: {"mass": 23.02544, "composition": 0.0}, - 24: {"mass": 24.011535, "composition": 0.0}, - 25: {"mass": 25.004109, "composition": 0.0}, - 26: {"mass": 25.99233384, "composition": 0.0}, - 27: {"mass": 26.98670481, "composition": 0.0}, - 28: {"mass": 27.97692653465, "composition": 0.92223}, - 29: {"mass": 28.9764946649, "composition": 0.04685}, - 30: {"mass": 29.973770136, "composition": 0.03092}, - 31: {"mass": 30.975363194, "composition": 0.0}, - 32: {"mass": 31.97415154, "composition": 0.0}, - 33: {"mass": 32.97797696, "composition": 0.0}, - 34: {"mass": 33.978576, "composition": 0.0}, - 35: {"mass": 34.984583, "composition": 0.0}, - 36: {"mass": 35.986695, "composition": 0.0}, - 37: {"mass": 36.992921, "composition": 0.0}, - 38: {"mass": 37.995523, "composition": 0.0}, - 39: {"mass": 39.002491, "composition": 0.0}, - 40: {"mass": 40.00583, "composition": 0.0}, - 41: {"mass": 41.01301, "composition": 0.0}, - 42: {"mass": 42.01778, "composition": 0.0}, - 43: {"mass": 43.0248, "composition": 0.0}, - 44: {"mass": 44.03061, "composition": 0.0}, - 45: {"mass": 45.03995, "composition": 0.0}}, - 15: {24: {"mass": 24.03577, "composition": 0.0}, - 25: {"mass": 25.02119, "composition": 0.0}, - 26: {"mass": 26.01178, "composition": 0.0}, - 27: {"mass": 26.999224, "composition": 0.0}, - 28: {"mass": 27.9923266, "composition": 0.0}, - 29: {"mass": 28.98180079, "composition": 0.0}, - 30: {"mass": 29.97831375, "composition": 0.0}, - 31: {"mass": 30.97376199842, "composition": 1.0}, - 32: {"mass": 31.973907643, "composition": 0.0}, - 33: {"mass": 32.9717257, "composition": 0.0}, - 34: {"mass": 33.97364589, "composition": 0.0}, - 35: {"mass": 34.9733141, "composition": 0.0}, - 36: {"mass": 35.97826, "composition": 0.0}, - 37: {"mass": 36.979607, "composition": 0.0}, - 38: {"mass": 37.984252, "composition": 0.0}, - 39: {"mass": 38.986227, "composition": 0.0}, - 40: {"mass": 39.99133, "composition": 0.0}, - 41: {"mass": 40.994654, "composition": 0.0}, - 42: {"mass": 42.00108, "composition": 0.0}, - 43: {"mass": 43.00502, "composition": 0.0}, - 44: {"mass": 44.01121, "composition": 0.0}, - 45: {"mass": 45.01645, "composition": 0.0}, - 46: {"mass": 46.02446, "composition": 0.0}, - 47: {"mass": 47.03139, "composition": 0.0}}, - 16: {26: {"mass": 26.02907, "composition": 0.0}, - 27: {"mass": 27.01828, "composition": 0.0}, - 28: {"mass": 28.00437, "composition": 0.0}, - 29: {"mass": 28.996611, "composition": 0.0}, - 30: {"mass": 29.98490703, "composition": 0.0}, - 31: {"mass": 30.97955701, "composition": 0.0}, - 32: {"mass": 31.9720711744, "composition": 0.9499}, - 33: {"mass": 32.9714589098, "composition": 0.0075}, - 34: {"mass": 33.967867004, "composition": 0.0425}, - 35: {"mass": 34.96903231, "composition": 0.0}, - 36: {"mass": 35.96708071, "composition": 0.0001}, - 37: {"mass": 36.97112551, "composition": 0.0}, - 38: {"mass": 37.9711633, "composition": 0.0}, - 39: {"mass": 38.975134, "composition": 0.0}, - 40: {"mass": 39.9754826, "composition": 0.0}, - 41: {"mass": 40.9795935, "composition": 0.0}, - 42: {"mass": 41.9810651, "composition": 0.0}, - 43: {"mass": 42.9869076, "composition": 0.0}, - 44: {"mass": 43.9901188, "composition": 0.0}, - 45: {"mass": 44.99572, "composition": 0.0}, - 46: {"mass": 46.00004, "composition": 0.0}, - 47: {"mass": 47.00795, "composition": 0.0}, - 48: {"mass": 48.0137, "composition": 0.0}, - 49: {"mass": 49.02276, "composition": 0.0}}, - 17: {28: {"mass": 28.02954, "composition": 0.0}, - 29: {"mass": 29.01478, "composition": 0.0}, - 30: {"mass": 30.00477, "composition": 0.0}, - 31: {"mass": 30.992414, "composition": 0.0}, - 32: {"mass": 31.98568464, "composition": 0.0}, - 33: {"mass": 32.97745199, "composition": 0.0}, - 34: {"mass": 33.973762485, "composition": 0.0}, - 35: {"mass": 34.968852682, "composition": 0.7576}, - 36: {"mass": 35.968306809, "composition": 0.0}, - 37: {"mass": 36.965902602, "composition": 0.2424}, - 38: {"mass": 37.96801044, "composition": 0.0}, - 39: {"mass": 38.9680082, "composition": 0.0}, - 40: {"mass": 39.970415, "composition": 0.0}, - 41: {"mass": 40.970685, "composition": 0.0}, - 42: {"mass": 41.97325, "composition": 0.0}, - 43: {"mass": 42.97389, "composition": 0.0}, - 44: {"mass": 43.97787, "composition": 0.0}, - 45: {"mass": 44.98029, "composition": 0.0}, - 46: {"mass": 45.98517, "composition": 0.0}, - 47: {"mass": 46.98916, "composition": 0.0}, - 48: {"mass": 47.99564, "composition": 0.0}, - 49: {"mass": 49.00123, "composition": 0.0}, - 50: {"mass": 50.00905, "composition": 0.0}, - 51: {"mass": 51.01554, "composition": 0.0}}, - 18: {30: {"mass": 30.02307, "composition": 0.0}, - 31: {"mass": 31.01212, "composition": 0.0}, - 32: {"mass": 31.9976378, "composition": 0.0}, - 33: {"mass": 32.98992555, "composition": 0.0}, - 34: {"mass": 33.98027009, "composition": 0.0}, - 35: {"mass": 34.97525759, "composition": 0.0}, - 36: {"mass": 35.967545105, "composition": 0.003336}, - 37: {"mass": 36.96677633, "composition": 0.0}, - 38: {"mass": 37.96273211, "composition": 0.000629}, - 39: {"mass": 38.964313, "composition": 0.0}, - 40: {"mass": 39.9623831237, "composition": 0.996035}, - 41: {"mass": 40.96450057, "composition": 0.0}, - 42: {"mass": 41.9630457, "composition": 0.0}, - 43: {"mass": 42.9656361, "composition": 0.0}, - 44: {"mass": 43.9649238, "composition": 0.0}, - 45: {"mass": 44.96803973, "composition": 0.0}, - 46: {"mass": 45.968083, "composition": 0.0}, - 47: {"mass": 46.972935, "composition": 0.0}, - 48: {"mass": 47.97591, "composition": 0.0}, - 49: {"mass": 48.9819, "composition": 0.0}, - 50: {"mass": 49.98613, "composition": 0.0}, - 51: {"mass": 50.9937, "composition": 0.0}, - 52: {"mass": 51.99896, "composition": 0.0}, - 53: {"mass": 53.00729, "composition": 0.0}}, - 19: {32: {"mass": 32.02265, "composition": 0.0}, - 33: {"mass": 33.00756, "composition": 0.0}, - 34: {"mass": 33.99869, "composition": 0.0}, - 35: {"mass": 34.98800541, "composition": 0.0}, - 36: {"mass": 35.98130201, "composition": 0.0}, - 37: {"mass": 36.97337589, "composition": 0.0}, - 38: {"mass": 37.96908112, "composition": 0.0}, - 39: {"mass": 38.9637064864, "composition": 0.932581}, - 40: {"mass": 39.963998166, "composition": 0.000117}, - 41: {"mass": 40.9618252579, "composition": 0.067302}, - 42: {"mass": 41.96240231, "composition": 0.0}, - 43: {"mass": 42.9607347, "composition": 0.0}, - 44: {"mass": 43.96158699, "composition": 0.0}, - 45: {"mass": 44.96069149, "composition": 0.0}, - 46: {"mass": 45.96198159, "composition": 0.0}, - 47: {"mass": 46.9616616, "composition": 0.0}, - 48: {"mass": 47.96534119, "composition": 0.0}, - 49: {"mass": 48.96821075, "composition": 0.0}, - 50: {"mass": 49.97238, "composition": 0.0}, - 51: {"mass": 50.975828, "composition": 0.0}, - 52: {"mass": 51.98224, "composition": 0.0}, - 53: {"mass": 52.98746, "composition": 0.0}, - 54: {"mass": 53.99463, "composition": 0.0}, - 55: {"mass": 55.00076, "composition": 0.0}, - 56: {"mass": 56.00851, "composition": 0.0}}, - 20: {34: {"mass": 34.01487, "composition": 0.0}, - 35: {"mass": 35.00514, "composition": 0.0}, - 36: {"mass": 35.993074, "composition": 0.0}, - 37: {"mass": 36.98589785, "composition": 0.0}, - 38: {"mass": 37.97631922, "composition": 0.0}, - 39: {"mass": 38.97071081, "composition": 0.0}, - 40: {"mass": 39.962590863, "composition": 0.96941}, - 41: {"mass": 40.96227792, "composition": 0.0}, - 42: {"mass": 41.95861783, "composition": 0.00647}, - 43: {"mass": 42.95876644, "composition": 0.00135}, - 44: {"mass": 43.95548156, "composition": 0.02086}, - 45: {"mass": 44.95618635, "composition": 0.0}, - 46: {"mass": 45.953689, "composition": 4e-05}, - 47: {"mass": 46.9545424, "composition": 0.0}, - 48: {"mass": 47.95252276, "composition": 0.00187}, - 49: {"mass": 48.95566274, "composition": 0.0}, - 50: {"mass": 49.9574992, "composition": 0.0}, - 51: {"mass": 50.960989, "composition": 0.0}, - 52: {"mass": 51.963217, "composition": 0.0}, - 53: {"mass": 52.96945, "composition": 0.0}, - 54: {"mass": 53.9734, "composition": 0.0}, - 55: {"mass": 54.9803, "composition": 0.0}, - 56: {"mass": 55.98508, "composition": 0.0}, - 57: {"mass": 56.99262, "composition": 0.0}, - 58: {"mass": 57.99794, "composition": 0.0}}, - 21: {36: {"mass": 36.01648, "composition": 0.0}, - 37: {"mass": 37.00374, "composition": 0.0}, - 38: {"mass": 37.99512, "composition": 0.0}, - 39: {"mass": 38.984785, "composition": 0.0}, - 40: {"mass": 39.9779673, "composition": 0.0}, - 41: {"mass": 40.969251105, "composition": 0.0}, - 42: {"mass": 41.96551653, "composition": 0.0}, - 43: {"mass": 42.9611505, "composition": 0.0}, - 44: {"mass": 43.9594029, "composition": 0.0}, - 45: {"mass": 44.95590828, "composition": 1.0}, - 46: {"mass": 45.95516826, "composition": 0.0}, - 47: {"mass": 46.9524037, "composition": 0.0}, - 48: {"mass": 47.9522236, "composition": 0.0}, - 49: {"mass": 48.9500146, "composition": 0.0}, - 50: {"mass": 49.952176, "composition": 0.0}, - 51: {"mass": 50.953592, "composition": 0.0}, - 52: {"mass": 51.95688, "composition": 0.0}, - 53: {"mass": 52.95909, "composition": 0.0}, - 54: {"mass": 53.96393, "composition": 0.0}, - 55: {"mass": 54.96782, "composition": 0.0}, - 56: {"mass": 55.97345, "composition": 0.0}, - 57: {"mass": 56.97777, "composition": 0.0}, - 58: {"mass": 57.98403, "composition": 0.0}, - 59: {"mass": 58.98894, "composition": 0.0}, - 60: {"mass": 59.99565, "composition": 0.0}, - 61: {"mass": 61.001, "composition": 0.0}}, - 22: {38: {"mass": 38.01145, "composition": 0.0}, - 39: {"mass": 39.00236, "composition": 0.0}, - 40: {"mass": 39.9905, "composition": 0.0}, - 41: {"mass": 40.983148, "composition": 0.0}, - 42: {"mass": 41.97304903, "composition": 0.0}, - 43: {"mass": 42.9685225, "composition": 0.0}, - 44: {"mass": 43.95968995, "composition": 0.0}, - 45: {"mass": 44.95812198, "composition": 0.0}, - 46: {"mass": 45.95262772, "composition": 0.0825}, - 47: {"mass": 46.95175879, "composition": 0.0744}, - 48: {"mass": 47.94794198, "composition": 0.7372}, - 49: {"mass": 48.94786568, "composition": 0.0541}, - 50: {"mass": 49.94478689, "composition": 0.0518}, - 51: {"mass": 50.94661065, "composition": 0.0}, - 52: {"mass": 51.946893, "composition": 0.0}, - 53: {"mass": 52.94973, "composition": 0.0}, - 54: {"mass": 53.95105, "composition": 0.0}, - 55: {"mass": 54.95527, "composition": 0.0}, - 56: {"mass": 55.95791, "composition": 0.0}, - 57: {"mass": 56.96364, "composition": 0.0}, - 58: {"mass": 57.9666, "composition": 0.0}, - 59: {"mass": 58.97247, "composition": 0.0}, - 60: {"mass": 59.97603, "composition": 0.0}, - 61: {"mass": 60.98245, "composition": 0.0}, - 62: {"mass": 61.98651, "composition": 0.0}, - 63: {"mass": 62.99375, "composition": 0.0}}, - 23: {40: {"mass": 40.01276, "composition": 0.0}, - 41: {"mass": 41.00021, "composition": 0.0}, - 42: {"mass": 41.99182, "composition": 0.0}, - 43: {"mass": 42.980766, "composition": 0.0}, - 44: {"mass": 43.97411, "composition": 0.0}, - 45: {"mass": 44.9657748, "composition": 0.0}, - 46: {"mass": 45.96019878, "composition": 0.0}, - 47: {"mass": 46.95490491, "composition": 0.0}, - 48: {"mass": 47.9522522, "composition": 0.0}, - 49: {"mass": 48.9485118, "composition": 0.0}, - 50: {"mass": 49.94715601, "composition": 0.0025}, - 51: {"mass": 50.94395704, "composition": 0.9975}, - 52: {"mass": 51.94477301, "composition": 0.0}, - 53: {"mass": 52.9443367, "composition": 0.0}, - 54: {"mass": 53.946439, "composition": 0.0}, - 55: {"mass": 54.94724, "composition": 0.0}, - 56: {"mass": 55.95048, "composition": 0.0}, - 57: {"mass": 56.95252, "composition": 0.0}, - 58: {"mass": 57.95672, "composition": 0.0}, - 59: {"mass": 58.95939, "composition": 0.0}, - 60: {"mass": 59.96431, "composition": 0.0}, - 61: {"mass": 60.96725, "composition": 0.0}, - 62: {"mass": 61.97265, "composition": 0.0}, - 63: {"mass": 62.97639, "composition": 0.0}, - 64: {"mass": 63.98264, "composition": 0.0}, - 65: {"mass": 64.9875, "composition": 0.0}, - 66: {"mass": 65.99398, "composition": 0.0}}, - 24: {42: {"mass": 42.0067, "composition": 0.0}, - 43: {"mass": 42.99753, "composition": 0.0}, - 44: {"mass": 43.98536, "composition": 0.0}, - 45: {"mass": 44.97905, "composition": 0.0}, - 46: {"mass": 45.968359, "composition": 0.0}, - 47: {"mass": 46.9628974, "composition": 0.0}, - 48: {"mass": 47.9540291, "composition": 0.0}, - 49: {"mass": 48.9513333, "composition": 0.0}, - 50: {"mass": 49.94604183, "composition": 0.04345}, - 51: {"mass": 50.94476502, "composition": 0.0}, - 52: {"mass": 51.94050623, "composition": 0.83789}, - 53: {"mass": 52.94064815, "composition": 0.09501}, - 54: {"mass": 53.93887916, "composition": 0.02365}, - 55: {"mass": 54.94083843, "composition": 0.0}, - 56: {"mass": 55.9406531, "composition": 0.0}, - 57: {"mass": 56.943613, "composition": 0.0}, - 58: {"mass": 57.94435, "composition": 0.0}, - 59: {"mass": 58.94859, "composition": 0.0}, - 60: {"mass": 59.95008, "composition": 0.0}, - 61: {"mass": 60.95442, "composition": 0.0}, - 62: {"mass": 61.9561, "composition": 0.0}, - 63: {"mass": 62.96165, "composition": 0.0}, - 64: {"mass": 63.96408, "composition": 0.0}, - 65: {"mass": 64.96996, "composition": 0.0}, - 66: {"mass": 65.97366, "composition": 0.0}, - 67: {"mass": 66.98016, "composition": 0.0}, - 68: {"mass": 67.98403, "composition": 0.0}}, - 25: {44: {"mass": 44.00715, "composition": 0.0}, - 45: {"mass": 44.99449, "composition": 0.0}, - 46: {"mass": 45.98609, "composition": 0.0}, - 47: {"mass": 46.975775, "composition": 0.0}, - 48: {"mass": 47.96852, "composition": 0.0}, - 49: {"mass": 48.959595, "composition": 0.0}, - 50: {"mass": 49.95423778, "composition": 0.0}, - 51: {"mass": 50.94820847, "composition": 0.0}, - 52: {"mass": 51.9455639, "composition": 0.0}, - 53: {"mass": 52.94128889, "composition": 0.0}, - 54: {"mass": 53.9403576, "composition": 0.0}, - 55: {"mass": 54.93804391, "composition": 1.0}, - 56: {"mass": 55.93890369, "composition": 0.0}, - 57: {"mass": 56.9382861, "composition": 0.0}, - 58: {"mass": 57.9400666, "composition": 0.0}, - 59: {"mass": 58.9403911, "composition": 0.0}, - 60: {"mass": 59.9431366, "composition": 0.0}, - 61: {"mass": 60.9444525, "composition": 0.0}, - 62: {"mass": 61.94795, "composition": 0.0}, - 63: {"mass": 62.9496647, "composition": 0.0}, - 64: {"mass": 63.9538494, "composition": 0.0}, - 65: {"mass": 64.9560198, "composition": 0.0}, - 66: {"mass": 65.960547, "composition": 0.0}, - 67: {"mass": 66.96424, "composition": 0.0}, - 68: {"mass": 67.96962, "composition": 0.0}, - 69: {"mass": 68.97366, "composition": 0.0}, - 70: {"mass": 69.97937, "composition": 0.0}, - 71: {"mass": 70.98368, "composition": 0.0}}, - 26: {45: {"mass": 45.01442, "composition": 0.0}, - 46: {"mass": 46.00063, "composition": 0.0}, - 47: {"mass": 46.99185, "composition": 0.0}, - 48: {"mass": 47.98023, "composition": 0.0}, - 49: {"mass": 48.973429, "composition": 0.0}, - 50: {"mass": 49.962975, "composition": 0.0}, - 51: {"mass": 50.956841, "composition": 0.0}, - 52: {"mass": 51.9481131, "composition": 0.0}, - 53: {"mass": 52.9453064, "composition": 0.0}, - 54: {"mass": 53.93960899, "composition": 0.05845}, - 55: {"mass": 54.93829199, "composition": 0.0}, - 56: {"mass": 55.93493633, "composition": 0.91754}, - 57: {"mass": 56.93539284, "composition": 0.02119}, - 58: {"mass": 57.93327443, "composition": 0.00282}, - 59: {"mass": 58.93487434, "composition": 0.0}, - 60: {"mass": 59.9340711, "composition": 0.0}, - 61: {"mass": 60.9367462, "composition": 0.0}, - 62: {"mass": 61.9367918, "composition": 0.0}, - 63: {"mass": 62.9402727, "composition": 0.0}, - 64: {"mass": 63.9409878, "composition": 0.0}, - 65: {"mass": 64.9450115, "composition": 0.0}, - 66: {"mass": 65.94625, "composition": 0.0}, - 67: {"mass": 66.95054, "composition": 0.0}, - 68: {"mass": 67.95295, "composition": 0.0}, - 69: {"mass": 68.95807, "composition": 0.0}, - 70: {"mass": 69.96102, "composition": 0.0}, - 71: {"mass": 70.96672, "composition": 0.0}, - 72: {"mass": 71.96983, "composition": 0.0}, - 73: {"mass": 72.97572, "composition": 0.0}, - 74: {"mass": 73.97935, "composition": 0.0}}, - 27: {47: {"mass": 47.01057, "composition": 0.0}, - 48: {"mass": 48.00093, "composition": 0.0}, - 49: {"mass": 48.98891, "composition": 0.0}, - 50: {"mass": 49.98091, "composition": 0.0}, - 51: {"mass": 50.970647, "composition": 0.0}, - 52: {"mass": 51.96351, "composition": 0.0}, - 53: {"mass": 52.9542041, "composition": 0.0}, - 54: {"mass": 53.94845987, "composition": 0.0}, - 55: {"mass": 54.9419972, "composition": 0.0}, - 56: {"mass": 55.9398388, "composition": 0.0}, - 57: {"mass": 56.93629057, "composition": 0.0}, - 58: {"mass": 57.9357521, "composition": 0.0}, - 59: {"mass": 58.93319429, "composition": 1.0}, - 60: {"mass": 59.9338163, "composition": 0.0}, - 61: {"mass": 60.93247662, "composition": 0.0}, - 62: {"mass": 61.934059, "composition": 0.0}, - 63: {"mass": 62.9336, "composition": 0.0}, - 64: {"mass": 63.935811, "composition": 0.0}, - 65: {"mass": 64.9364621, "composition": 0.0}, - 66: {"mass": 65.939443, "composition": 0.0}, - 67: {"mass": 66.9406096, "composition": 0.0}, - 68: {"mass": 67.94426, "composition": 0.0}, - 69: {"mass": 68.94614, "composition": 0.0}, - 70: {"mass": 69.94963, "composition": 0.0}, - 71: {"mass": 70.95237, "composition": 0.0}, - 72: {"mass": 71.95729, "composition": 0.0}, - 73: {"mass": 72.96039, "composition": 0.0}, - 74: {"mass": 73.96515, "composition": 0.0}, - 75: {"mass": 74.96876, "composition": 0.0}, - 76: {"mass": 75.97413, "composition": 0.0}}, - 28: {48: {"mass": 48.01769, "composition": 0.0}, - 49: {"mass": 49.0077, "composition": 0.0}, - 50: {"mass": 49.99474, "composition": 0.0}, - 51: {"mass": 50.98611, "composition": 0.0}, - 52: {"mass": 51.9748, "composition": 0.0}, - 53: {"mass": 52.96819, "composition": 0.0}, - 54: {"mass": 53.957892, "composition": 0.0}, - 55: {"mass": 54.95133063, "composition": 0.0}, - 56: {"mass": 55.94212855, "composition": 0.0}, - 57: {"mass": 56.93979218, "composition": 0.0}, - 58: {"mass": 57.93534241, "composition": 0.68077}, - 59: {"mass": 58.9343462, "composition": 0.0}, - 60: {"mass": 59.93078588, "composition": 0.26223}, - 61: {"mass": 60.93105557, "composition": 0.011399}, - 62: {"mass": 61.92834537, "composition": 0.036346}, - 63: {"mass": 62.92966963, "composition": 0.0}, - 64: {"mass": 63.92796682, "composition": 0.009255}, - 65: {"mass": 64.93008517, "composition": 0.0}, - 66: {"mass": 65.9291393, "composition": 0.0}, - 67: {"mass": 66.9315694, "composition": 0.0}, - 68: {"mass": 67.9318688, "composition": 0.0}, - 69: {"mass": 68.9356103, "composition": 0.0}, - 70: {"mass": 69.9364313, "composition": 0.0}, - 71: {"mass": 70.940519, "composition": 0.0}, - 72: {"mass": 71.9417859, "composition": 0.0}, - 73: {"mass": 72.9462067, "composition": 0.0}, - 74: {"mass": 73.94798, "composition": 0.0}, - 75: {"mass": 74.9525, "composition": 0.0}, - 76: {"mass": 75.95533, "composition": 0.0}, - 77: {"mass": 76.96055, "composition": 0.0}, - 78: {"mass": 77.96336, "composition": 0.0}, - 79: {"mass": 78.97025, "composition": 0.0}}, - 29: {52: {"mass": 51.99671, "composition": 0.0}, - 53: {"mass": 52.98459, "composition": 0.0}, - 54: {"mass": 53.97666, "composition": 0.0}, - 55: {"mass": 54.96604, "composition": 0.0}, - 56: {"mass": 55.95895, "composition": 0.0}, - 57: {"mass": 56.9492125, "composition": 0.0}, - 58: {"mass": 57.94453305, "composition": 0.0}, - 59: {"mass": 58.93949748, "composition": 0.0}, - 60: {"mass": 59.9373645, "composition": 0.0}, - 61: {"mass": 60.9334576, "composition": 0.0}, - 62: {"mass": 61.93259541, "composition": 0.0}, - 63: {"mass": 62.92959772, "composition": 0.6915}, - 64: {"mass": 63.92976434, "composition": 0.0}, - 65: {"mass": 64.9277897, "composition": 0.3085}, - 66: {"mass": 65.92886903, "composition": 0.0}, - 67: {"mass": 66.9277303, "composition": 0.0}, - 68: {"mass": 67.9296109, "composition": 0.0}, - 69: {"mass": 68.9294293, "composition": 0.0}, - 70: {"mass": 69.9323921, "composition": 0.0}, - 71: {"mass": 70.9326768, "composition": 0.0}, - 72: {"mass": 71.9358203, "composition": 0.0}, - 73: {"mass": 72.9366744, "composition": 0.0}, - 74: {"mass": 73.9398749, "composition": 0.0}, - 75: {"mass": 74.9415226, "composition": 0.0}, - 76: {"mass": 75.945275, "composition": 0.0}, - 77: {"mass": 76.94792, "composition": 0.0}, - 78: {"mass": 77.95223, "composition": 0.0}, - 79: {"mass": 78.95502, "composition": 0.0}, - 80: {"mass": 79.96089, "composition": 0.0}, - 81: {"mass": 80.96587, "composition": 0.0}, - 82: {"mass": 81.97244, "composition": 0.0}}, - 30: {54: {"mass": 53.99204, "composition": 0.0}, - 55: {"mass": 54.98398, "composition": 0.0}, - 56: {"mass": 55.97254, "composition": 0.0}, - 57: {"mass": 56.96506, "composition": 0.0}, - 58: {"mass": 57.954591, "composition": 0.0}, - 59: {"mass": 58.94931266, "composition": 0.0}, - 60: {"mass": 59.9418421, "composition": 0.0}, - 61: {"mass": 60.939507, "composition": 0.0}, - 62: {"mass": 61.93433397, "composition": 0.0}, - 63: {"mass": 62.9332115, "composition": 0.0}, - 64: {"mass": 63.92914201, "composition": 0.4917}, - 65: {"mass": 64.92924077, "composition": 0.0}, - 66: {"mass": 65.92603381, "composition": 0.2773}, - 67: {"mass": 66.92712775, "composition": 0.0404}, - 68: {"mass": 67.92484455, "composition": 0.1845}, - 69: {"mass": 68.9265507, "composition": 0.0}, - 70: {"mass": 69.9253192, "composition": 0.0061}, - 71: {"mass": 70.9277196, "composition": 0.0}, - 72: {"mass": 71.9268428, "composition": 0.0}, - 73: {"mass": 72.9295826, "composition": 0.0}, - 74: {"mass": 73.9294073, "composition": 0.0}, - 75: {"mass": 74.9328402, "composition": 0.0}, - 76: {"mass": 75.933115, "composition": 0.0}, - 77: {"mass": 76.9368872, "composition": 0.0}, - 78: {"mass": 77.9382892, "composition": 0.0}, - 79: {"mass": 78.9426381, "composition": 0.0}, - 80: {"mass": 79.9445529, "composition": 0.0}, - 81: {"mass": 80.9504026, "composition": 0.0}, - 82: {"mass": 81.95426, "composition": 0.0}, - 83: {"mass": 82.96056, "composition": 0.0}, - 84: {"mass": 83.96521, "composition": 0.0}, - 85: {"mass": 84.97226, "composition": 0.0}}, - 31: {56: {"mass": 55.99536, "composition": 0.0}, - 57: {"mass": 56.9832, "composition": 0.0}, - 58: {"mass": 57.97478, "composition": 0.0}, - 59: {"mass": 58.96353, "composition": 0.0}, - 60: {"mass": 59.95729, "composition": 0.0}, - 61: {"mass": 60.949399, "composition": 0.0}, - 62: {"mass": 61.94419025, "composition": 0.0}, - 63: {"mass": 62.9392942, "composition": 0.0}, - 64: {"mass": 63.9368404, "composition": 0.0}, - 65: {"mass": 64.93273459, "composition": 0.0}, - 66: {"mass": 65.9315894, "composition": 0.0}, - 67: {"mass": 66.9282025, "composition": 0.0}, - 68: {"mass": 67.9279805, "composition": 0.0}, - 69: {"mass": 68.9255735, "composition": 0.60108}, - 70: {"mass": 69.9260219, "composition": 0.0}, - 71: {"mass": 70.92470258, "composition": 0.39892}, - 72: {"mass": 71.92636747, "composition": 0.0}, - 73: {"mass": 72.9251747, "composition": 0.0}, - 74: {"mass": 73.9269457, "composition": 0.0}, - 75: {"mass": 74.9265002, "composition": 0.0}, - 76: {"mass": 75.9288276, "composition": 0.0}, - 77: {"mass": 76.9291543, "composition": 0.0}, - 78: {"mass": 77.9316088, "composition": 0.0}, - 79: {"mass": 78.9328523, "composition": 0.0}, - 80: {"mass": 79.9364208, "composition": 0.0}, - 81: {"mass": 80.9381338, "composition": 0.0}, - 82: {"mass": 81.9431765, "composition": 0.0}, - 83: {"mass": 82.9471203, "composition": 0.0}, - 84: {"mass": 83.95246, "composition": 0.0}, - 85: {"mass": 84.95699, "composition": 0.0}, - 86: {"mass": 85.96301, "composition": 0.0}, - 87: {"mass": 86.96824, "composition": 0.0}}, - 32: {58: {"mass": 57.99172, "composition": 0.0}, - 59: {"mass": 58.98249, "composition": 0.0}, - 60: {"mass": 59.97036, "composition": 0.0}, - 61: {"mass": 60.96379, "composition": 0.0}, - 62: {"mass": 61.95502, "composition": 0.0}, - 63: {"mass": 62.949628, "composition": 0.0}, - 64: {"mass": 63.9416899, "composition": 0.0}, - 65: {"mass": 64.9393681, "composition": 0.0}, - 66: {"mass": 65.9338621, "composition": 0.0}, - 67: {"mass": 66.9327339, "composition": 0.0}, - 68: {"mass": 67.9280953, "composition": 0.0}, - 69: {"mass": 68.9279645, "composition": 0.0}, - 70: {"mass": 69.92424875, "composition": 0.2057}, - 71: {"mass": 70.92495233, "composition": 0.0}, - 72: {"mass": 71.922075826, "composition": 0.2745}, - 73: {"mass": 72.923458956, "composition": 0.0775}, - 74: {"mass": 73.921177761, "composition": 0.365}, - 75: {"mass": 74.92285837, "composition": 0.0}, - 76: {"mass": 75.921402726, "composition": 0.0773}, - 77: {"mass": 76.923549843, "composition": 0.0}, - 78: {"mass": 77.9228529, "composition": 0.0}, - 79: {"mass": 78.92536, "composition": 0.0}, - 80: {"mass": 79.9253508, "composition": 0.0}, - 81: {"mass": 80.9288329, "composition": 0.0}, - 82: {"mass": 81.929774, "composition": 0.0}, - 83: {"mass": 82.9345391, "composition": 0.0}, - 84: {"mass": 83.9375751, "composition": 0.0}, - 85: {"mass": 84.9429697, "composition": 0.0}, - 86: {"mass": 85.94658, "composition": 0.0}, - 87: {"mass": 86.95268, "composition": 0.0}, - 88: {"mass": 87.95691, "composition": 0.0}, - 89: {"mass": 88.96379, "composition": 0.0}, - 90: {"mass": 89.96863, "composition": 0.0}}, - 33: {60: {"mass": 59.99388, "composition": 0.0}, - 61: {"mass": 60.98112, "composition": 0.0}, - 62: {"mass": 61.97361, "composition": 0.0}, - 63: {"mass": 62.9639, "composition": 0.0}, - 64: {"mass": 63.95743, "composition": 0.0}, - 65: {"mass": 64.949611, "composition": 0.0}, - 66: {"mass": 65.9441488, "composition": 0.0}, - 67: {"mass": 66.93925111, "composition": 0.0}, - 68: {"mass": 67.9367741, "composition": 0.0}, - 69: {"mass": 68.932246, "composition": 0.0}, - 70: {"mass": 69.930926, "composition": 0.0}, - 71: {"mass": 70.9271138, "composition": 0.0}, - 72: {"mass": 71.9267523, "composition": 0.0}, - 73: {"mass": 72.9238291, "composition": 0.0}, - 74: {"mass": 73.9239286, "composition": 0.0}, - 75: {"mass": 74.92159457, "composition": 1.0}, - 76: {"mass": 75.92239202, "composition": 0.0}, - 77: {"mass": 76.9206476, "composition": 0.0}, - 78: {"mass": 77.921828, "composition": 0.0}, - 79: {"mass": 78.9209484, "composition": 0.0}, - 80: {"mass": 79.9224746, "composition": 0.0}, - 81: {"mass": 80.9221323, "composition": 0.0}, - 82: {"mass": 81.9247412, "composition": 0.0}, - 83: {"mass": 82.9252069, "composition": 0.0}, - 84: {"mass": 83.9293033, "composition": 0.0}, - 85: {"mass": 84.9321637, "composition": 0.0}, - 86: {"mass": 85.9367015, "composition": 0.0}, - 87: {"mass": 86.9402917, "composition": 0.0}, - 88: {"mass": 87.94555, "composition": 0.0}, - 89: {"mass": 88.94976, "composition": 0.0}, - 90: {"mass": 89.95563, "composition": 0.0}, - 91: {"mass": 90.96039, "composition": 0.0}, - 92: {"mass": 91.96674, "composition": 0.0}}, - 34: {64: {"mass": 63.97109, "composition": 0.0}, - 65: {"mass": 64.9644, "composition": 0.0}, - 66: {"mass": 65.95559, "composition": 0.0}, - 67: {"mass": 66.949994, "composition": 0.0}, - 68: {"mass": 67.94182524, "composition": 0.0}, - 69: {"mass": 68.9394148, "composition": 0.0}, - 70: {"mass": 69.9335155, "composition": 0.0}, - 71: {"mass": 70.9322094, "composition": 0.0}, - 72: {"mass": 71.9271405, "composition": 0.0}, - 73: {"mass": 72.9267549, "composition": 0.0}, - 74: {"mass": 73.922475934, "composition": 0.0089}, - 75: {"mass": 74.92252287, "composition": 0.0}, - 76: {"mass": 75.919213704, "composition": 0.0937}, - 77: {"mass": 76.919914154, "composition": 0.0763}, - 78: {"mass": 77.91730928, "composition": 0.2377}, - 79: {"mass": 78.91849929, "composition": 0.0}, - 80: {"mass": 79.9165218, "composition": 0.4961}, - 81: {"mass": 80.917993, "composition": 0.0}, - 82: {"mass": 81.9166995, "composition": 0.0873}, - 83: {"mass": 82.9191186, "composition": 0.0}, - 84: {"mass": 83.9184668, "composition": 0.0}, - 85: {"mass": 84.9222608, "composition": 0.0}, - 86: {"mass": 85.9243117, "composition": 0.0}, - 87: {"mass": 86.9286886, "composition": 0.0}, - 88: {"mass": 87.9314175, "composition": 0.0}, - 89: {"mass": 88.9366691, "composition": 0.0}, - 90: {"mass": 89.9401, "composition": 0.0}, - 91: {"mass": 90.94596, "composition": 0.0}, - 92: {"mass": 91.94984, "composition": 0.0}, - 93: {"mass": 92.95629, "composition": 0.0}, - 94: {"mass": 93.96049, "composition": 0.0}, - 95: {"mass": 94.9673, "composition": 0.0}}, - 35: {67: {"mass": 66.96465, "composition": 0.0}, - 68: {"mass": 67.95873, "composition": 0.0}, - 69: {"mass": 68.950497, "composition": 0.0}, - 70: {"mass": 69.944792, "composition": 0.0}, - 71: {"mass": 70.9393422, "composition": 0.0}, - 72: {"mass": 71.9365886, "composition": 0.0}, - 73: {"mass": 72.9316715, "composition": 0.0}, - 74: {"mass": 73.9299102, "composition": 0.0}, - 75: {"mass": 74.9258105, "composition": 0.0}, - 76: {"mass": 75.924542, "composition": 0.0}, - 77: {"mass": 76.9213792, "composition": 0.0}, - 78: {"mass": 77.9211459, "composition": 0.0}, - 79: {"mass": 78.9183376, "composition": 0.5069}, - 80: {"mass": 79.9185298, "composition": 0.0}, - 81: {"mass": 80.9162897, "composition": 0.4931}, - 82: {"mass": 81.9168032, "composition": 0.0}, - 83: {"mass": 82.9151756, "composition": 0.0}, - 84: {"mass": 83.916496, "composition": 0.0}, - 85: {"mass": 84.9156458, "composition": 0.0}, - 86: {"mass": 85.9188054, "composition": 0.0}, - 87: {"mass": 86.920674, "composition": 0.0}, - 88: {"mass": 87.9240833, "composition": 0.0}, - 89: {"mass": 88.9267046, "composition": 0.0}, - 90: {"mass": 89.9312928, "composition": 0.0}, - 91: {"mass": 90.9343986, "composition": 0.0}, - 92: {"mass": 91.9396316, "composition": 0.0}, - 93: {"mass": 92.94313, "composition": 0.0}, - 94: {"mass": 93.9489, "composition": 0.0}, - 95: {"mass": 94.95301, "composition": 0.0}, - 96: {"mass": 95.95903, "composition": 0.0}, - 97: {"mass": 96.96344, "composition": 0.0}, - 98: {"mass": 97.96946, "composition": 0.0}}, - 36: {69: {"mass": 68.96518, "composition": 0.0}, - 70: {"mass": 69.95604, "composition": 0.0}, - 71: {"mass": 70.95027, "composition": 0.0}, - 72: {"mass": 71.9420924, "composition": 0.0}, - 73: {"mass": 72.9392892, "composition": 0.0}, - 74: {"mass": 73.933084, "composition": 0.0}, - 75: {"mass": 74.9309457, "composition": 0.0}, - 76: {"mass": 75.9259103, "composition": 0.0}, - 77: {"mass": 76.92467, "composition": 0.0}, - 78: {"mass": 77.92036494, "composition": 0.00355}, - 79: {"mass": 78.9200829, "composition": 0.0}, - 80: {"mass": 79.91637808, "composition": 0.02286}, - 81: {"mass": 80.9165912, "composition": 0.0}, - 82: {"mass": 81.91348273, "composition": 0.11593}, - 83: {"mass": 82.91412716, "composition": 0.115}, - 84: {"mass": 83.9114977282, "composition": 0.56987}, - 85: {"mass": 84.9125273, "composition": 0.0}, - 86: {"mass": 85.9106106269, "composition": 0.17279}, - 87: {"mass": 86.91335476, "composition": 0.0}, - 88: {"mass": 87.9144479, "composition": 0.0}, - 89: {"mass": 88.9178355, "composition": 0.0}, - 90: {"mass": 89.9195279, "composition": 0.0}, - 91: {"mass": 90.9238063, "composition": 0.0}, - 92: {"mass": 91.9261731, "composition": 0.0}, - 93: {"mass": 92.9311472, "composition": 0.0}, - 94: {"mass": 93.93414, "composition": 0.0}, - 95: {"mass": 94.939711, "composition": 0.0}, - 96: {"mass": 95.943017, "composition": 0.0}, - 97: {"mass": 96.94909, "composition": 0.0}, - 98: {"mass": 97.95243, "composition": 0.0}, - 99: {"mass": 98.95839, "composition": 0.0}, - 100: {"mass": 99.96237, "composition": 0.0}, - 101: {"mass": 100.96873, "composition": 0.0}}, - 37: {71: {"mass": 70.96532, "composition": 0.0}, - 72: {"mass": 71.95908, "composition": 0.0}, - 73: {"mass": 72.95053, "composition": 0.0}, - 74: {"mass": 73.9442659, "composition": 0.0}, - 75: {"mass": 74.9385732, "composition": 0.0}, - 76: {"mass": 75.935073, "composition": 0.0}, - 77: {"mass": 76.9304016, "composition": 0.0}, - 78: {"mass": 77.9281419, "composition": 0.0}, - 79: {"mass": 78.9239899, "composition": 0.0}, - 80: {"mass": 79.9225164, "composition": 0.0}, - 81: {"mass": 80.9189939, "composition": 0.0}, - 82: {"mass": 81.918209, "composition": 0.0}, - 83: {"mass": 82.9151142, "composition": 0.0}, - 84: {"mass": 83.9143752, "composition": 0.0}, - 85: {"mass": 84.9117897379, "composition": 0.7217}, - 86: {"mass": 85.91116743, "composition": 0.0}, - 87: {"mass": 86.909180531, "composition": 0.2783}, - 88: {"mass": 87.91131559, "composition": 0.0}, - 89: {"mass": 88.9122783, "composition": 0.0}, - 90: {"mass": 89.9147985, "composition": 0.0}, - 91: {"mass": 90.9165372, "composition": 0.0}, - 92: {"mass": 91.9197284, "composition": 0.0}, - 93: {"mass": 92.9220393, "composition": 0.0}, - 94: {"mass": 93.9263948, "composition": 0.0}, - 95: {"mass": 94.92926, "composition": 0.0}, - 96: {"mass": 95.9341334, "composition": 0.0}, - 97: {"mass": 96.9371771, "composition": 0.0}, - 98: {"mass": 97.9416869, "composition": 0.0}, - 99: {"mass": 98.94503, "composition": 0.0}, - 100: {"mass": 99.95003, "composition": 0.0}, - 101: {"mass": 100.95404, "composition": 0.0}, - 102: {"mass": 101.95952, "composition": 0.0}, - 103: {"mass": 102.96392, "composition": 0.0}}, - 38: {73: {"mass": 72.9657, "composition": 0.0}, - 74: {"mass": 73.95617, "composition": 0.0}, - 75: {"mass": 74.94995, "composition": 0.0}, - 76: {"mass": 75.941763, "composition": 0.0}, - 77: {"mass": 76.9379455, "composition": 0.0}, - 78: {"mass": 77.93218, "composition": 0.0}, - 79: {"mass": 78.9297077, "composition": 0.0}, - 80: {"mass": 79.9245175, "composition": 0.0}, - 81: {"mass": 80.9232114, "composition": 0.0}, - 82: {"mass": 81.9183999, "composition": 0.0}, - 83: {"mass": 82.9175544, "composition": 0.0}, - 84: {"mass": 83.9134191, "composition": 0.0056}, - 85: {"mass": 84.912932, "composition": 0.0}, - 86: {"mass": 85.9092606, "composition": 0.0986}, - 87: {"mass": 86.9088775, "composition": 0.07}, - 88: {"mass": 87.9056125, "composition": 0.8258}, - 89: {"mass": 88.9074511, "composition": 0.0}, - 90: {"mass": 89.90773, "composition": 0.0}, - 91: {"mass": 90.9101954, "composition": 0.0}, - 92: {"mass": 91.9110382, "composition": 0.0}, - 93: {"mass": 92.9140242, "composition": 0.0}, - 94: {"mass": 93.9153556, "composition": 0.0}, - 95: {"mass": 94.9193529, "composition": 0.0}, - 96: {"mass": 95.9217066, "composition": 0.0}, - 97: {"mass": 96.926374, "composition": 0.0}, - 98: {"mass": 97.9286888, "composition": 0.0}, - 99: {"mass": 98.9328907, "composition": 0.0}, - 100: {"mass": 99.93577, "composition": 0.0}, - 101: {"mass": 100.940352, "composition": 0.0}, - 102: {"mass": 101.943791, "composition": 0.0}, - 103: {"mass": 102.94909, "composition": 0.0}, - 104: {"mass": 103.95265, "composition": 0.0}, - 105: {"mass": 104.95855, "composition": 0.0}, - 106: {"mass": 105.96265, "composition": 0.0}, - 107: {"mass": 106.96897, "composition": 0.0}}, - 39: {76: {"mass": 75.95856, "composition": 0.0}, - 77: {"mass": 76.949781, "composition": 0.0}, - 78: {"mass": 77.94361, "composition": 0.0}, - 79: {"mass": 78.93735, "composition": 0.0}, - 80: {"mass": 79.9343561, "composition": 0.0}, - 81: {"mass": 80.9294556, "composition": 0.0}, - 82: {"mass": 81.9269314, "composition": 0.0}, - 83: {"mass": 82.922485, "composition": 0.0}, - 84: {"mass": 83.9206721, "composition": 0.0}, - 85: {"mass": 84.916433, "composition": 0.0}, - 86: {"mass": 85.914886, "composition": 0.0}, - 87: {"mass": 86.9108761, "composition": 0.0}, - 88: {"mass": 87.9095016, "composition": 0.0}, - 89: {"mass": 88.9058403, "composition": 1.0}, - 90: {"mass": 89.9071439, "composition": 0.0}, - 91: {"mass": 90.9072974, "composition": 0.0}, - 92: {"mass": 91.9089451, "composition": 0.0}, - 93: {"mass": 92.909578, "composition": 0.0}, - 94: {"mass": 93.9115906, "composition": 0.0}, - 95: {"mass": 94.9128161, "composition": 0.0}, - 96: {"mass": 95.9158968, "composition": 0.0}, - 97: {"mass": 96.9182741, "composition": 0.0}, - 98: {"mass": 97.9223821, "composition": 0.0}, - 99: {"mass": 98.924148, "composition": 0.0}, - 100: {"mass": 99.927715, "composition": 0.0}, - 101: {"mass": 100.9301477, "composition": 0.0}, - 102: {"mass": 101.9343277, "composition": 0.0}, - 103: {"mass": 102.937243, "composition": 0.0}, - 104: {"mass": 103.94196, "composition": 0.0}, - 105: {"mass": 104.94544, "composition": 0.0}, - 106: {"mass": 105.95056, "composition": 0.0}, - 107: {"mass": 106.95452, "composition": 0.0}, - 108: {"mass": 107.95996, "composition": 0.0}, - 109: {"mass": 108.96436, "composition": 0.0}}, - 40: {78: {"mass": 77.95566, "composition": 0.0}, - 79: {"mass": 78.94948, "composition": 0.0}, - 80: {"mass": 79.9404, "composition": 0.0}, - 81: {"mass": 80.93731, "composition": 0.0}, - 82: {"mass": 81.93135, "composition": 0.0}, - 83: {"mass": 82.9292421, "composition": 0.0}, - 84: {"mass": 83.9233269, "composition": 0.0}, - 85: {"mass": 84.9214444, "composition": 0.0}, - 86: {"mass": 85.9162972, "composition": 0.0}, - 87: {"mass": 86.914818, "composition": 0.0}, - 88: {"mass": 87.9102213, "composition": 0.0}, - 89: {"mass": 88.9088814, "composition": 0.0}, - 90: {"mass": 89.9046977, "composition": 0.5145}, - 91: {"mass": 90.9056396, "composition": 0.1122}, - 92: {"mass": 91.9050347, "composition": 0.1715}, - 93: {"mass": 92.9064699, "composition": 0.0}, - 94: {"mass": 93.9063108, "composition": 0.1738}, - 95: {"mass": 94.9080385, "composition": 0.0}, - 96: {"mass": 95.9082714, "composition": 0.028}, - 97: {"mass": 96.9109512, "composition": 0.0}, - 98: {"mass": 97.9127289, "composition": 0.0}, - 99: {"mass": 98.916667, "composition": 0.0}, - 100: {"mass": 99.9180006, "composition": 0.0}, - 101: {"mass": 100.921448, "composition": 0.0}, - 102: {"mass": 101.9231409, "composition": 0.0}, - 103: {"mass": 102.927191, "composition": 0.0}, - 104: {"mass": 103.929436, "composition": 0.0}, - 105: {"mass": 104.934008, "composition": 0.0}, - 106: {"mass": 105.93676, "composition": 0.0}, - 107: {"mass": 106.94174, "composition": 0.0}, - 108: {"mass": 107.94487, "composition": 0.0}, - 109: {"mass": 108.95041, "composition": 0.0}, - 110: {"mass": 109.95396, "composition": 0.0}, - 111: {"mass": 110.95968, "composition": 0.0}, - 112: {"mass": 111.9637, "composition": 0.0}}, - 41: {81: {"mass": 80.9496, "composition": 0.0}, - 82: {"mass": 81.94396, "composition": 0.0}, - 83: {"mass": 82.93729, "composition": 0.0}, - 84: {"mass": 83.93449, "composition": 0.0}, - 85: {"mass": 84.9288458, "composition": 0.0}, - 86: {"mass": 85.9257828, "composition": 0.0}, - 87: {"mass": 86.9206937, "composition": 0.0}, - 88: {"mass": 87.918222, "composition": 0.0}, - 89: {"mass": 88.913445, "composition": 0.0}, - 90: {"mass": 89.9112584, "composition": 0.0}, - 91: {"mass": 90.9069897, "composition": 0.0}, - 92: {"mass": 91.9071881, "composition": 0.0}, - 93: {"mass": 92.906373, "composition": 1.0}, - 94: {"mass": 93.9072788, "composition": 0.0}, - 95: {"mass": 94.9068324, "composition": 0.0}, - 96: {"mass": 95.9080973, "composition": 0.0}, - 97: {"mass": 96.9080959, "composition": 0.0}, - 98: {"mass": 97.9103265, "composition": 0.0}, - 99: {"mass": 98.911613, "composition": 0.0}, - 100: {"mass": 99.9143276, "composition": 0.0}, - 101: {"mass": 100.9153103, "composition": 0.0}, - 102: {"mass": 101.9180772, "composition": 0.0}, - 103: {"mass": 102.9194572, "composition": 0.0}, - 104: {"mass": 103.9228925, "composition": 0.0}, - 105: {"mass": 104.9249465, "composition": 0.0}, - 106: {"mass": 105.9289317, "composition": 0.0}, - 107: {"mass": 106.9315937, "composition": 0.0}, - 108: {"mass": 107.9360748, "composition": 0.0}, - 109: {"mass": 108.93922, "composition": 0.0}, - 110: {"mass": 109.94403, "composition": 0.0}, - 111: {"mass": 110.94753, "composition": 0.0}, - 112: {"mass": 111.95247, "composition": 0.0}, - 113: {"mass": 112.95651, "composition": 0.0}, - 114: {"mass": 113.96201, "composition": 0.0}, - 115: {"mass": 114.96634, "composition": 0.0}}, - 42: {83: {"mass": 82.94988, "composition": 0.0}, - 84: {"mass": 83.94149, "composition": 0.0}, - 85: {"mass": 84.938261, "composition": 0.0}, - 86: {"mass": 85.9311748, "composition": 0.0}, - 87: {"mass": 86.9281962, "composition": 0.0}, - 88: {"mass": 87.9219678, "composition": 0.0}, - 89: {"mass": 88.9194682, "composition": 0.0}, - 90: {"mass": 89.9139309, "composition": 0.0}, - 91: {"mass": 90.9117453, "composition": 0.0}, - 92: {"mass": 91.90680796, "composition": 0.1453}, - 93: {"mass": 92.90680958, "composition": 0.0}, - 94: {"mass": 93.9050849, "composition": 0.0915}, - 95: {"mass": 94.90583877, "composition": 0.1584}, - 96: {"mass": 95.90467612, "composition": 0.1667}, - 97: {"mass": 96.90601812, "composition": 0.096}, - 98: {"mass": 97.90540482, "composition": 0.2439}, - 99: {"mass": 98.90770851, "composition": 0.0}, - 100: {"mass": 99.9074718, "composition": 0.0982}, - 101: {"mass": 100.9103414, "composition": 0.0}, - 102: {"mass": 101.9102834, "composition": 0.0}, - 103: {"mass": 102.913079, "composition": 0.0}, - 104: {"mass": 103.9137344, "composition": 0.0}, - 105: {"mass": 104.916969, "composition": 0.0}, - 106: {"mass": 105.918259, "composition": 0.0}, - 107: {"mass": 106.922106, "composition": 0.0}, - 108: {"mass": 107.924033, "composition": 0.0}, - 109: {"mass": 108.928424, "composition": 0.0}, - 110: {"mass": 109.930704, "composition": 0.0}, - 111: {"mass": 110.935654, "composition": 0.0}, - 112: {"mass": 111.93831, "composition": 0.0}, - 113: {"mass": 112.94335, "composition": 0.0}, - 114: {"mass": 113.94653, "composition": 0.0}, - 115: {"mass": 114.95196, "composition": 0.0}, - 116: {"mass": 115.95545, "composition": 0.0}, - 117: {"mass": 116.96117, "composition": 0.0}}, - 43: {85: {"mass": 84.95058, "composition": 0.0}, - 86: {"mass": 85.94493, "composition": 0.0}, - 87: {"mass": 86.9380672, "composition": 0.0}, - 88: {"mass": 87.93378, "composition": 0.0}, - 89: {"mass": 88.9276487, "composition": 0.0}, - 90: {"mass": 89.9240739, "composition": 0.0}, - 91: {"mass": 90.9184254, "composition": 0.0}, - 92: {"mass": 91.9152698, "composition": 0.0}, - 93: {"mass": 92.910246, "composition": 0.0}, - 94: {"mass": 93.9096536, "composition": 0.0}, - 95: {"mass": 94.9076536, "composition": 0.0}, - 96: {"mass": 95.907868, "composition": 0.0}, - 97: {"mass": 96.9063667, "composition": 0.0}, - 98: {"mass": 97.9072124, "composition": 0.0}, - 99: {"mass": 98.9062508, "composition": 0.0}, - 100: {"mass": 99.9076539, "composition": 0.0}, - 101: {"mass": 100.907309, "composition": 0.0}, - 102: {"mass": 101.9092097, "composition": 0.0}, - 103: {"mass": 102.909176, "composition": 0.0}, - 104: {"mass": 103.911425, "composition": 0.0}, - 105: {"mass": 104.911655, "composition": 0.0}, - 106: {"mass": 105.914358, "composition": 0.0}, - 107: {"mass": 106.9154606, "composition": 0.0}, - 108: {"mass": 107.9184957, "composition": 0.0}, - 109: {"mass": 108.920256, "composition": 0.0}, - 110: {"mass": 109.923744, "composition": 0.0}, - 111: {"mass": 110.925901, "composition": 0.0}, - 112: {"mass": 111.9299458, "composition": 0.0}, - 113: {"mass": 112.932569, "composition": 0.0}, - 114: {"mass": 113.93691, "composition": 0.0}, - 115: {"mass": 114.93998, "composition": 0.0}, - 116: {"mass": 115.94476, "composition": 0.0}, - 117: {"mass": 116.94806, "composition": 0.0}, - 118: {"mass": 117.95299, "composition": 0.0}, - 119: {"mass": 118.95666, "composition": 0.0}, - 120: {"mass": 119.96187, "composition": 0.0}}, - 44: {87: {"mass": 86.95069, "composition": 0.0}, - 88: {"mass": 87.9416, "composition": 0.0}, - 89: {"mass": 88.93762, "composition": 0.0}, - 90: {"mass": 89.9303444, "composition": 0.0}, - 91: {"mass": 90.9267419, "composition": 0.0}, - 92: {"mass": 91.9202344, "composition": 0.0}, - 93: {"mass": 92.9171044, "composition": 0.0}, - 94: {"mass": 93.9113429, "composition": 0.0}, - 95: {"mass": 94.910406, "composition": 0.0}, - 96: {"mass": 95.90759025, "composition": 0.0554}, - 97: {"mass": 96.9075471, "composition": 0.0}, - 98: {"mass": 97.9052868, "composition": 0.0187}, - 99: {"mass": 98.9059341, "composition": 0.1276}, - 100: {"mass": 99.9042143, "composition": 0.126}, - 101: {"mass": 100.9055769, "composition": 0.1706}, - 102: {"mass": 101.9043441, "composition": 0.3155}, - 103: {"mass": 102.9063186, "composition": 0.0}, - 104: {"mass": 103.9054275, "composition": 0.1862}, - 105: {"mass": 104.9077476, "composition": 0.0}, - 106: {"mass": 105.9073291, "composition": 0.0}, - 107: {"mass": 106.909972, "composition": 0.0}, - 108: {"mass": 107.910188, "composition": 0.0}, - 109: {"mass": 108.913326, "composition": 0.0}, - 110: {"mass": 109.9140407, "composition": 0.0}, - 111: {"mass": 110.91757, "composition": 0.0}, - 112: {"mass": 111.918809, "composition": 0.0}, - 113: {"mass": 112.922844, "composition": 0.0}, - 114: {"mass": 113.9246136, "composition": 0.0}, - 115: {"mass": 114.92882, "composition": 0.0}, - 116: {"mass": 115.9312192, "composition": 0.0}, - 117: {"mass": 116.9361, "composition": 0.0}, - 118: {"mass": 117.93853, "composition": 0.0}, - 119: {"mass": 118.94357, "composition": 0.0}, - 120: {"mass": 119.94631, "composition": 0.0}, - 121: {"mass": 120.95164, "composition": 0.0}, - 122: {"mass": 121.95447, "composition": 0.0}, - 123: {"mass": 122.95989, "composition": 0.0}, - 124: {"mass": 123.96305, "composition": 0.0}}, - 45: {89: {"mass": 88.95058, "composition": 0.0}, - 90: {"mass": 89.94422, "composition": 0.0}, - 91: {"mass": 90.93688, "composition": 0.0}, - 92: {"mass": 91.9323677, "composition": 0.0}, - 93: {"mass": 92.9259128, "composition": 0.0}, - 94: {"mass": 93.9217305, "composition": 0.0}, - 95: {"mass": 94.9158979, "composition": 0.0}, - 96: {"mass": 95.914453, "composition": 0.0}, - 97: {"mass": 96.911329, "composition": 0.0}, - 98: {"mass": 97.910708, "composition": 0.0}, - 99: {"mass": 98.9081282, "composition": 0.0}, - 100: {"mass": 99.908117, "composition": 0.0}, - 101: {"mass": 100.9061606, "composition": 0.0}, - 102: {"mass": 101.9068374, "composition": 0.0}, - 103: {"mass": 102.905498, "composition": 1.0}, - 104: {"mass": 103.9066492, "composition": 0.0}, - 105: {"mass": 104.9056885, "composition": 0.0}, - 106: {"mass": 105.9072868, "composition": 0.0}, - 107: {"mass": 106.906748, "composition": 0.0}, - 108: {"mass": 107.908714, "composition": 0.0}, - 109: {"mass": 108.9087488, "composition": 0.0}, - 110: {"mass": 109.911079, "composition": 0.0}, - 111: {"mass": 110.9116423, "composition": 0.0}, - 112: {"mass": 111.914403, "composition": 0.0}, - 113: {"mass": 112.9154393, "composition": 0.0}, - 114: {"mass": 113.918718, "composition": 0.0}, - 115: {"mass": 114.9203116, "composition": 0.0}, - 116: {"mass": 115.924059, "composition": 0.0}, - 117: {"mass": 116.9260354, "composition": 0.0}, - 118: {"mass": 117.93034, "composition": 0.0}, - 119: {"mass": 118.932557, "composition": 0.0}, - 120: {"mass": 119.93686, "composition": 0.0}, - 121: {"mass": 120.93942, "composition": 0.0}, - 122: {"mass": 121.94399, "composition": 0.0}, - 123: {"mass": 122.94685, "composition": 0.0}, - 124: {"mass": 123.95151, "composition": 0.0}, - 125: {"mass": 124.95469, "composition": 0.0}, - 126: {"mass": 125.95946, "composition": 0.0}}, - 46: {91: {"mass": 90.95032, "composition": 0.0}, - 92: {"mass": 91.94088, "composition": 0.0}, - 93: {"mass": 92.93651, "composition": 0.0}, - 94: {"mass": 93.9290376, "composition": 0.0}, - 95: {"mass": 94.9248898, "composition": 0.0}, - 96: {"mass": 95.9182151, "composition": 0.0}, - 97: {"mass": 96.916472, "composition": 0.0}, - 98: {"mass": 97.9126983, "composition": 0.0}, - 99: {"mass": 98.9117748, "composition": 0.0}, - 100: {"mass": 99.908505, "composition": 0.0}, - 101: {"mass": 100.9082864, "composition": 0.0}, - 102: {"mass": 101.9056022, "composition": 0.0102}, - 103: {"mass": 102.9060809, "composition": 0.0}, - 104: {"mass": 103.9040305, "composition": 0.1114}, - 105: {"mass": 104.9050796, "composition": 0.2233}, - 106: {"mass": 105.9034804, "composition": 0.2733}, - 107: {"mass": 106.9051282, "composition": 0.0}, - 108: {"mass": 107.9038916, "composition": 0.2646}, - 109: {"mass": 108.9059504, "composition": 0.0}, - 110: {"mass": 109.9051722, "composition": 0.1172}, - 111: {"mass": 110.90768968, "composition": 0.0}, - 112: {"mass": 111.9073297, "composition": 0.0}, - 113: {"mass": 112.910261, "composition": 0.0}, - 114: {"mass": 113.9103686, "composition": 0.0}, - 115: {"mass": 114.913659, "composition": 0.0}, - 116: {"mass": 115.914297, "composition": 0.0}, - 117: {"mass": 116.9179547, "composition": 0.0}, - 118: {"mass": 117.9190667, "composition": 0.0}, - 119: {"mass": 118.9233402, "composition": 0.0}, - 120: {"mass": 119.9245511, "composition": 0.0}, - 121: {"mass": 120.9289503, "composition": 0.0}, - 122: {"mass": 121.930632, "composition": 0.0}, - 123: {"mass": 122.93514, "composition": 0.0}, - 124: {"mass": 123.93714, "composition": 0.0}, - 125: {"mass": 124.94179, "composition": 0.0}, - 126: {"mass": 125.94416, "composition": 0.0}, - 127: {"mass": 126.94907, "composition": 0.0}, - 128: {"mass": 127.95183, "composition": 0.0}}, - 47: {93: {"mass": 92.95033, "composition": 0.0}, - 94: {"mass": 93.94373, "composition": 0.0}, - 95: {"mass": 94.93602, "composition": 0.0}, - 96: {"mass": 95.930744, "composition": 0.0}, - 97: {"mass": 96.92397, "composition": 0.0}, - 98: {"mass": 97.92156, "composition": 0.0}, - 99: {"mass": 98.9176458, "composition": 0.0}, - 100: {"mass": 99.9161154, "composition": 0.0}, - 101: {"mass": 100.912684, "composition": 0.0}, - 102: {"mass": 101.9117047, "composition": 0.0}, - 103: {"mass": 102.9089631, "composition": 0.0}, - 104: {"mass": 103.9086239, "composition": 0.0}, - 105: {"mass": 104.9065256, "composition": 0.0}, - 106: {"mass": 105.9066636, "composition": 0.0}, - 107: {"mass": 106.9050916, "composition": 0.51839}, - 108: {"mass": 107.9059503, "composition": 0.0}, - 109: {"mass": 108.9047553, "composition": 0.48161}, - 110: {"mass": 109.9061102, "composition": 0.0}, - 111: {"mass": 110.9052959, "composition": 0.0}, - 112: {"mass": 111.9070486, "composition": 0.0}, - 113: {"mass": 112.906573, "composition": 0.0}, - 114: {"mass": 113.908823, "composition": 0.0}, - 115: {"mass": 114.908767, "composition": 0.0}, - 116: {"mass": 115.9113868, "composition": 0.0}, - 117: {"mass": 116.911774, "composition": 0.0}, - 118: {"mass": 117.9145955, "composition": 0.0}, - 119: {"mass": 118.91557, "composition": 0.0}, - 120: {"mass": 119.9187848, "composition": 0.0}, - 121: {"mass": 120.920125, "composition": 0.0}, - 122: {"mass": 121.923664, "composition": 0.0}, - 123: {"mass": 122.925337, "composition": 0.0}, - 124: {"mass": 123.92893, "composition": 0.0}, - 125: {"mass": 124.93105, "composition": 0.0}, - 126: {"mass": 125.93475, "composition": 0.0}, - 127: {"mass": 126.93711, "composition": 0.0}, - 128: {"mass": 127.94106, "composition": 0.0}, - 129: {"mass": 128.94395, "composition": 0.0}, - 130: {"mass": 129.9507, "composition": 0.0}}, - 48: {95: {"mass": 94.94994, "composition": 0.0}, - 96: {"mass": 95.94034, "composition": 0.0}, - 97: {"mass": 96.9351, "composition": 0.0}, - 98: {"mass": 97.927389, "composition": 0.0}, - 99: {"mass": 98.9249258, "composition": 0.0}, - 100: {"mass": 99.9203488, "composition": 0.0}, - 101: {"mass": 100.9185862, "composition": 0.0}, - 102: {"mass": 101.914482, "composition": 0.0}, - 103: {"mass": 102.9134165, "composition": 0.0}, - 104: {"mass": 103.9098564, "composition": 0.0}, - 105: {"mass": 104.9094639, "composition": 0.0}, - 106: {"mass": 105.9064599, "composition": 0.0125}, - 107: {"mass": 106.9066121, "composition": 0.0}, - 108: {"mass": 107.9041834, "composition": 0.0089}, - 109: {"mass": 108.9049867, "composition": 0.0}, - 110: {"mass": 109.90300661, "composition": 0.1249}, - 111: {"mass": 110.90418287, "composition": 0.128}, - 112: {"mass": 111.90276287, "composition": 0.2413}, - 113: {"mass": 112.90440813, "composition": 0.1222}, - 114: {"mass": 113.90336509, "composition": 0.2873}, - 115: {"mass": 114.90543751, "composition": 0.0}, - 116: {"mass": 115.90476315, "composition": 0.0749}, - 117: {"mass": 116.907226, "composition": 0.0}, - 118: {"mass": 117.906922, "composition": 0.0}, - 119: {"mass": 118.909847, "composition": 0.0}, - 120: {"mass": 119.9098681, "composition": 0.0}, - 121: {"mass": 120.9129637, "composition": 0.0}, - 122: {"mass": 121.9134591, "composition": 0.0}, - 123: {"mass": 122.9168925, "composition": 0.0}, - 124: {"mass": 123.9176574, "composition": 0.0}, - 125: {"mass": 124.9212576, "composition": 0.0}, - 126: {"mass": 125.9224291, "composition": 0.0}, - 127: {"mass": 126.926472, "composition": 0.0}, - 128: {"mass": 127.9278129, "composition": 0.0}, - 129: {"mass": 128.93182, "composition": 0.0}, - 130: {"mass": 129.93394, "composition": 0.0}, - 131: {"mass": 130.9406, "composition": 0.0}, - 132: {"mass": 131.94604, "composition": 0.0}, - 133: {"mass": 132.95285, "composition": 0.0}}, - 49: {97: {"mass": 96.94934, "composition": 0.0}, - 98: {"mass": 97.94214, "composition": 0.0}, - 99: {"mass": 98.93411, "composition": 0.0}, - 100: {"mass": 99.93096, "composition": 0.0}, - 101: {"mass": 100.92634, "composition": 0.0}, - 102: {"mass": 101.9241071, "composition": 0.0}, - 103: {"mass": 102.9198819, "composition": 0.0}, - 104: {"mass": 103.9182145, "composition": 0.0}, - 105: {"mass": 104.914502, "composition": 0.0}, - 106: {"mass": 105.913464, "composition": 0.0}, - 107: {"mass": 106.91029, "composition": 0.0}, - 108: {"mass": 107.9096935, "composition": 0.0}, - 109: {"mass": 108.9071514, "composition": 0.0}, - 110: {"mass": 109.90717, "composition": 0.0}, - 111: {"mass": 110.9051085, "composition": 0.0}, - 112: {"mass": 111.9055377, "composition": 0.0}, - 113: {"mass": 112.90406184, "composition": 0.0429}, - 114: {"mass": 113.90491791, "composition": 0.0}, - 115: {"mass": 114.903878776, "composition": 0.9571}, - 116: {"mass": 115.90525999, "composition": 0.0}, - 117: {"mass": 116.9045157, "composition": 0.0}, - 118: {"mass": 117.9063566, "composition": 0.0}, - 119: {"mass": 118.9058507, "composition": 0.0}, - 120: {"mass": 119.907967, "composition": 0.0}, - 121: {"mass": 120.907851, "composition": 0.0}, - 122: {"mass": 121.910281, "composition": 0.0}, - 123: {"mass": 122.910434, "composition": 0.0}, - 124: {"mass": 123.913182, "composition": 0.0}, - 125: {"mass": 124.913605, "composition": 0.0}, - 126: {"mass": 125.916507, "composition": 0.0}, - 127: {"mass": 126.917446, "composition": 0.0}, - 128: {"mass": 127.9204, "composition": 0.0}, - 129: {"mass": 128.9218053, "composition": 0.0}, - 130: {"mass": 129.924977, "composition": 0.0}, - 131: {"mass": 130.9269715, "composition": 0.0}, - 132: {"mass": 131.933001, "composition": 0.0}, - 133: {"mass": 132.93831, "composition": 0.0}, - 134: {"mass": 133.94454, "composition": 0.0}, - 135: {"mass": 134.95005, "composition": 0.0}}, - 50: {99: {"mass": 98.94853, "composition": 0.0}, - 100: {"mass": 99.9385, "composition": 0.0}, - 101: {"mass": 100.93526, "composition": 0.0}, - 102: {"mass": 101.93029, "composition": 0.0}, - 103: {"mass": 102.928105, "composition": 0.0}, - 104: {"mass": 103.9231052, "composition": 0.0}, - 105: {"mass": 104.9212684, "composition": 0.0}, - 106: {"mass": 105.9169574, "composition": 0.0}, - 107: {"mass": 106.9157137, "composition": 0.0}, - 108: {"mass": 107.9118943, "composition": 0.0}, - 109: {"mass": 108.9112921, "composition": 0.0}, - 110: {"mass": 109.907845, "composition": 0.0}, - 111: {"mass": 110.9077401, "composition": 0.0}, - 112: {"mass": 111.90482387, "composition": 0.0097}, - 113: {"mass": 112.9051757, "composition": 0.0}, - 114: {"mass": 113.9027827, "composition": 0.0066}, - 115: {"mass": 114.903344699, "composition": 0.0034}, - 116: {"mass": 115.9017428, "composition": 0.1454}, - 117: {"mass": 116.90295398, "composition": 0.0768}, - 118: {"mass": 117.90160657, "composition": 0.2422}, - 119: {"mass": 118.90331117, "composition": 0.0859}, - 120: {"mass": 119.90220163, "composition": 0.3258}, - 121: {"mass": 120.9042426, "composition": 0.0}, - 122: {"mass": 121.9034438, "composition": 0.0463}, - 123: {"mass": 122.9057252, "composition": 0.0}, - 124: {"mass": 123.9052766, "composition": 0.0579}, - 125: {"mass": 124.9077864, "composition": 0.0}, - 126: {"mass": 125.907659, "composition": 0.0}, - 127: {"mass": 126.91039, "composition": 0.0}, - 128: {"mass": 127.910507, "composition": 0.0}, - 129: {"mass": 128.913465, "composition": 0.0}, - 130: {"mass": 129.9139738, "composition": 0.0}, - 131: {"mass": 130.917045, "composition": 0.0}, - 132: {"mass": 131.9178267, "composition": 0.0}, - 133: {"mass": 132.9239134, "composition": 0.0}, - 134: {"mass": 133.9286821, "composition": 0.0}, - 135: {"mass": 134.9349086, "composition": 0.0}, - 136: {"mass": 135.93999, "composition": 0.0}, - 137: {"mass": 136.94655, "composition": 0.0}, - 138: {"mass": 137.95184, "composition": 0.0}}, - 51: {103: {"mass": 102.93969, "composition": 0.0}, - 104: {"mass": 103.93648, "composition": 0.0}, - 105: {"mass": 104.931276, "composition": 0.0}, - 106: {"mass": 105.928638, "composition": 0.0}, - 107: {"mass": 106.9241506, "composition": 0.0}, - 108: {"mass": 107.9222267, "composition": 0.0}, - 109: {"mass": 108.9181411, "composition": 0.0}, - 110: {"mass": 109.9168543, "composition": 0.0}, - 111: {"mass": 110.9132182, "composition": 0.0}, - 112: {"mass": 111.9124, "composition": 0.0}, - 113: {"mass": 112.909375, "composition": 0.0}, - 114: {"mass": 113.90929, "composition": 0.0}, - 115: {"mass": 114.906598, "composition": 0.0}, - 116: {"mass": 115.9067931, "composition": 0.0}, - 117: {"mass": 116.9048415, "composition": 0.0}, - 118: {"mass": 117.9055321, "composition": 0.0}, - 119: {"mass": 118.9039455, "composition": 0.0}, - 120: {"mass": 119.9050794, "composition": 0.0}, - 121: {"mass": 120.903812, "composition": 0.5721}, - 122: {"mass": 121.9051699, "composition": 0.0}, - 123: {"mass": 122.9042132, "composition": 0.4279}, - 124: {"mass": 123.905935, "composition": 0.0}, - 125: {"mass": 124.905253, "composition": 0.0}, - 126: {"mass": 125.907253, "composition": 0.0}, - 127: {"mass": 126.9069243, "composition": 0.0}, - 128: {"mass": 127.909146, "composition": 0.0}, - 129: {"mass": 128.909147, "composition": 0.0}, - 130: {"mass": 129.911662, "composition": 0.0}, - 131: {"mass": 130.9119888, "composition": 0.0}, - 132: {"mass": 131.9145077, "composition": 0.0}, - 133: {"mass": 132.9152732, "composition": 0.0}, - 134: {"mass": 133.9205357, "composition": 0.0}, - 135: {"mass": 134.9251851, "composition": 0.0}, - 136: {"mass": 135.9307459, "composition": 0.0}, - 137: {"mass": 136.93555, "composition": 0.0}, - 138: {"mass": 137.94145, "composition": 0.0}, - 139: {"mass": 138.94655, "composition": 0.0}, - 140: {"mass": 139.95283, "composition": 0.0}}, - 52: {105: {"mass": 104.9433, "composition": 0.0}, - 106: {"mass": 105.9375, "composition": 0.0}, - 107: {"mass": 106.935012, "composition": 0.0}, - 108: {"mass": 107.9293805, "composition": 0.0}, - 109: {"mass": 108.9273045, "composition": 0.0}, - 110: {"mass": 109.9224581, "composition": 0.0}, - 111: {"mass": 110.9210006, "composition": 0.0}, - 112: {"mass": 111.9167279, "composition": 0.0}, - 113: {"mass": 112.915891, "composition": 0.0}, - 114: {"mass": 113.912089, "composition": 0.0}, - 115: {"mass": 114.911902, "composition": 0.0}, - 116: {"mass": 115.90846, "composition": 0.0}, - 117: {"mass": 116.908646, "composition": 0.0}, - 118: {"mass": 117.905854, "composition": 0.0}, - 119: {"mass": 118.9064071, "composition": 0.0}, - 120: {"mass": 119.9040593, "composition": 0.0009}, - 121: {"mass": 120.904944, "composition": 0.0}, - 122: {"mass": 121.9030435, "composition": 0.0255}, - 123: {"mass": 122.9042698, "composition": 0.0089}, - 124: {"mass": 123.9028171, "composition": 0.0474}, - 125: {"mass": 124.9044299, "composition": 0.0707}, - 126: {"mass": 125.9033109, "composition": 0.1884}, - 127: {"mass": 126.9052257, "composition": 0.0}, - 128: {"mass": 127.90446128, "composition": 0.3174}, - 129: {"mass": 128.90659646, "composition": 0.0}, - 130: {"mass": 129.906222748, "composition": 0.3408}, - 131: {"mass": 130.908522213, "composition": 0.0}, - 132: {"mass": 131.9085467, "composition": 0.0}, - 133: {"mass": 132.9109688, "composition": 0.0}, - 134: {"mass": 133.911394, "composition": 0.0}, - 135: {"mass": 134.9165557, "composition": 0.0}, - 136: {"mass": 135.9201006, "composition": 0.0}, - 137: {"mass": 136.9255989, "composition": 0.0}, - 138: {"mass": 137.9294722, "composition": 0.0}, - 139: {"mass": 138.9353672, "composition": 0.0}, - 140: {"mass": 139.939499, "composition": 0.0}, - 141: {"mass": 140.9458, "composition": 0.0}, - 142: {"mass": 141.95022, "composition": 0.0}, - 143: {"mass": 142.95676, "composition": 0.0}}, - 53: {107: {"mass": 106.94678, "composition": 0.0}, - 108: {"mass": 107.94348, "composition": 0.0}, - 109: {"mass": 108.9380853, "composition": 0.0}, - 110: {"mass": 109.935089, "composition": 0.0}, - 111: {"mass": 110.9302692, "composition": 0.0}, - 112: {"mass": 111.928005, "composition": 0.0}, - 113: {"mass": 112.9236501, "composition": 0.0}, - 114: {"mass": 113.92185, "composition": 0.0}, - 115: {"mass": 114.918048, "composition": 0.0}, - 116: {"mass": 115.91681, "composition": 0.0}, - 117: {"mass": 116.913648, "composition": 0.0}, - 118: {"mass": 117.913074, "composition": 0.0}, - 119: {"mass": 118.910074, "composition": 0.0}, - 120: {"mass": 119.910087, "composition": 0.0}, - 121: {"mass": 120.9074051, "composition": 0.0}, - 122: {"mass": 121.9075888, "composition": 0.0}, - 123: {"mass": 122.9055885, "composition": 0.0}, - 124: {"mass": 123.906209, "composition": 0.0}, - 125: {"mass": 124.9046294, "composition": 0.0}, - 126: {"mass": 125.9056233, "composition": 0.0}, - 127: {"mass": 126.9044719, "composition": 1.0}, - 128: {"mass": 127.9058086, "composition": 0.0}, - 129: {"mass": 128.9049837, "composition": 0.0}, - 130: {"mass": 129.9066702, "composition": 0.0}, - 131: {"mass": 130.9061263, "composition": 0.0}, - 132: {"mass": 131.9079935, "composition": 0.0}, - 133: {"mass": 132.907797, "composition": 0.0}, - 134: {"mass": 133.9097588, "composition": 0.0}, - 135: {"mass": 134.9100488, "composition": 0.0}, - 136: {"mass": 135.914604, "composition": 0.0}, - 137: {"mass": 136.9180282, "composition": 0.0}, - 138: {"mass": 137.9227264, "composition": 0.0}, - 139: {"mass": 138.926506, "composition": 0.0}, - 140: {"mass": 139.93173, "composition": 0.0}, - 141: {"mass": 140.93569, "composition": 0.0}, - 142: {"mass": 141.9412, "composition": 0.0}, - 143: {"mass": 142.94565, "composition": 0.0}, - 144: {"mass": 143.95139, "composition": 0.0}, - 145: {"mass": 144.95605, "composition": 0.0}}, - 54: {109: {"mass": 108.95043, "composition": 0.0}, - 110: {"mass": 109.94426, "composition": 0.0}, - 111: {"mass": 110.941607, "composition": 0.0}, - 112: {"mass": 111.935559, "composition": 0.0}, - 113: {"mass": 112.9332217, "composition": 0.0}, - 114: {"mass": 113.92798, "composition": 0.0}, - 115: {"mass": 114.926294, "composition": 0.0}, - 116: {"mass": 115.921581, "composition": 0.0}, - 117: {"mass": 116.920359, "composition": 0.0}, - 118: {"mass": 117.916179, "composition": 0.0}, - 119: {"mass": 118.915411, "composition": 0.0}, - 120: {"mass": 119.911784, "composition": 0.0}, - 121: {"mass": 120.911453, "composition": 0.0}, - 122: {"mass": 121.908368, "composition": 0.0}, - 123: {"mass": 122.908482, "composition": 0.0}, - 124: {"mass": 123.905892, "composition": 0.000952}, - 125: {"mass": 124.9063944, "composition": 0.0}, - 126: {"mass": 125.9042983, "composition": 0.00089}, - 127: {"mass": 126.9051829, "composition": 0.0}, - 128: {"mass": 127.903531, "composition": 0.019102}, - 129: {"mass": 128.9047808611, "composition": 0.264006}, - 130: {"mass": 129.903509349, "composition": 0.04071}, - 131: {"mass": 130.90508406, "composition": 0.212324}, - 132: {"mass": 131.9041550856, "composition": 0.269086}, - 133: {"mass": 132.9059108, "composition": 0.0}, - 134: {"mass": 133.90539466, "composition": 0.104357}, - 135: {"mass": 134.9072278, "composition": 0.0}, - 136: {"mass": 135.907214484, "composition": 0.088573}, - 137: {"mass": 136.91155778, "composition": 0.0}, - 138: {"mass": 137.9141463, "composition": 0.0}, - 139: {"mass": 138.9187922, "composition": 0.0}, - 140: {"mass": 139.9216458, "composition": 0.0}, - 141: {"mass": 140.9267872, "composition": 0.0}, - 142: {"mass": 141.9299731, "composition": 0.0}, - 143: {"mass": 142.9353696, "composition": 0.0}, - 144: {"mass": 143.9389451, "composition": 0.0}, - 145: {"mass": 144.94472, "composition": 0.0}, - 146: {"mass": 145.948518, "composition": 0.0}, - 147: {"mass": 146.95426, "composition": 0.0}, - 148: {"mass": 147.95813, "composition": 0.0}}, - 55: {112: {"mass": 111.950309, "composition": 0.0}, - 113: {"mass": 112.9444291, "composition": 0.0}, - 114: {"mass": 113.941296, "composition": 0.0}, - 115: {"mass": 114.93591, "composition": 0.0}, - 116: {"mass": 115.93337, "composition": 0.0}, - 117: {"mass": 116.928617, "composition": 0.0}, - 118: {"mass": 117.92656, "composition": 0.0}, - 119: {"mass": 118.922377, "composition": 0.0}, - 120: {"mass": 119.920677, "composition": 0.0}, - 121: {"mass": 120.917227, "composition": 0.0}, - 122: {"mass": 121.916108, "composition": 0.0}, - 123: {"mass": 122.912996, "composition": 0.0}, - 124: {"mass": 123.9122578, "composition": 0.0}, - 125: {"mass": 124.909728, "composition": 0.0}, - 126: {"mass": 125.909446, "composition": 0.0}, - 127: {"mass": 126.9074174, "composition": 0.0}, - 128: {"mass": 127.9077487, "composition": 0.0}, - 129: {"mass": 128.9060657, "composition": 0.0}, - 130: {"mass": 129.9067093, "composition": 0.0}, - 131: {"mass": 130.9054649, "composition": 0.0}, - 132: {"mass": 131.9064339, "composition": 0.0}, - 133: {"mass": 132.905451961, "composition": 1.0}, - 134: {"mass": 133.906718503, "composition": 0.0}, - 135: {"mass": 134.905977, "composition": 0.0}, - 136: {"mass": 135.9073114, "composition": 0.0}, - 137: {"mass": 136.90708923, "composition": 0.0}, - 138: {"mass": 137.9110171, "composition": 0.0}, - 139: {"mass": 138.9133638, "composition": 0.0}, - 140: {"mass": 139.9172831, "composition": 0.0}, - 141: {"mass": 140.9200455, "composition": 0.0}, - 142: {"mass": 141.924296, "composition": 0.0}, - 143: {"mass": 142.927349, "composition": 0.0}, - 144: {"mass": 143.932076, "composition": 0.0}, - 145: {"mass": 144.935527, "composition": 0.0}, - 146: {"mass": 145.940344, "composition": 0.0}, - 147: {"mass": 146.944156, "composition": 0.0}, - 148: {"mass": 147.94923, "composition": 0.0}, - 149: {"mass": 148.95302, "composition": 0.0}, - 150: {"mass": 149.95833, "composition": 0.0}, - 151: {"mass": 150.96258, "composition": 0.0}}, - 56: {114: {"mass": 113.95066, "composition": 0.0}, - 115: {"mass": 114.94737, "composition": 0.0}, - 116: {"mass": 115.94128, "composition": 0.0}, - 117: {"mass": 116.93814, "composition": 0.0}, - 118: {"mass": 117.93306, "composition": 0.0}, - 119: {"mass": 118.93066, "composition": 0.0}, - 120: {"mass": 119.92605, "composition": 0.0}, - 121: {"mass": 120.92405, "composition": 0.0}, - 122: {"mass": 121.919904, "composition": 0.0}, - 123: {"mass": 122.918781, "composition": 0.0}, - 124: {"mass": 123.915094, "composition": 0.0}, - 125: {"mass": 124.914472, "composition": 0.0}, - 126: {"mass": 125.91125, "composition": 0.0}, - 127: {"mass": 126.911091, "composition": 0.0}, - 128: {"mass": 127.908342, "composition": 0.0}, - 129: {"mass": 128.908681, "composition": 0.0}, - 130: {"mass": 129.9063207, "composition": 0.00106}, - 131: {"mass": 130.906941, "composition": 0.0}, - 132: {"mass": 131.9050611, "composition": 0.00101}, - 133: {"mass": 132.9060074, "composition": 0.0}, - 134: {"mass": 133.90450818, "composition": 0.02417}, - 135: {"mass": 134.90568838, "composition": 0.06592}, - 136: {"mass": 135.90457573, "composition": 0.07854}, - 137: {"mass": 136.90582714, "composition": 0.11232}, - 138: {"mass": 137.905247, "composition": 0.71698}, - 139: {"mass": 138.9088411, "composition": 0.0}, - 140: {"mass": 139.9106057, "composition": 0.0}, - 141: {"mass": 140.9144033, "composition": 0.0}, - 142: {"mass": 141.9164324, "composition": 0.0}, - 143: {"mass": 142.9206253, "composition": 0.0}, - 144: {"mass": 143.9229549, "composition": 0.0}, - 145: {"mass": 144.9275184, "composition": 0.0}, - 146: {"mass": 145.930284, "composition": 0.0}, - 147: {"mass": 146.935304, "composition": 0.0}, - 148: {"mass": 147.938171, "composition": 0.0}, - 149: {"mass": 148.94308, "composition": 0.0}, - 150: {"mass": 149.94605, "composition": 0.0}, - 151: {"mass": 150.95127, "composition": 0.0}, - 152: {"mass": 151.95481, "composition": 0.0}, - 153: {"mass": 152.96036, "composition": 0.0}}, - 57: {116: {"mass": 115.9563, "composition": 0.0}, - 117: {"mass": 116.94999, "composition": 0.0}, - 118: {"mass": 117.94673, "composition": 0.0}, - 119: {"mass": 118.94099, "composition": 0.0}, - 120: {"mass": 119.93807, "composition": 0.0}, - 121: {"mass": 120.93315, "composition": 0.0}, - 122: {"mass": 121.93071, "composition": 0.0}, - 123: {"mass": 122.9263, "composition": 0.0}, - 124: {"mass": 123.924574, "composition": 0.0}, - 125: {"mass": 124.920816, "composition": 0.0}, - 126: {"mass": 125.919513, "composition": 0.0}, - 127: {"mass": 126.916375, "composition": 0.0}, - 128: {"mass": 127.915592, "composition": 0.0}, - 129: {"mass": 128.912694, "composition": 0.0}, - 130: {"mass": 129.912369, "composition": 0.0}, - 131: {"mass": 130.91007, "composition": 0.0}, - 132: {"mass": 131.910119, "composition": 0.0}, - 133: {"mass": 132.908218, "composition": 0.0}, - 134: {"mass": 133.908514, "composition": 0.0}, - 135: {"mass": 134.906984, "composition": 0.0}, - 136: {"mass": 135.907635, "composition": 0.0}, - 137: {"mass": 136.9064504, "composition": 0.0}, - 138: {"mass": 137.9071149, "composition": 0.0008881}, - 139: {"mass": 138.9063563, "composition": 0.9991119}, - 140: {"mass": 139.9094806, "composition": 0.0}, - 141: {"mass": 140.910966, "composition": 0.0}, - 142: {"mass": 141.9140909, "composition": 0.0}, - 143: {"mass": 142.9160795, "composition": 0.0}, - 144: {"mass": 143.919646, "composition": 0.0}, - 145: {"mass": 144.921808, "composition": 0.0}, - 146: {"mass": 145.925875, "composition": 0.0}, - 147: {"mass": 146.928418, "composition": 0.0}, - 148: {"mass": 147.932679, "composition": 0.0}, - 149: {"mass": 148.93535, "composition": 0.0}, - 150: {"mass": 149.93947, "composition": 0.0}, - 151: {"mass": 150.94232, "composition": 0.0}, - 152: {"mass": 151.94682, "composition": 0.0}, - 153: {"mass": 152.95036, "composition": 0.0}, - 154: {"mass": 153.95517, "composition": 0.0}, - 155: {"mass": 154.95901, "composition": 0.0}}, - 58: {119: {"mass": 118.95271, "composition": 0.0}, - 120: {"mass": 119.94654, "composition": 0.0}, - 121: {"mass": 120.94335, "composition": 0.0}, - 122: {"mass": 121.93787, "composition": 0.0}, - 123: {"mass": 122.93528, "composition": 0.0}, - 124: {"mass": 123.93031, "composition": 0.0}, - 125: {"mass": 124.92844, "composition": 0.0}, - 126: {"mass": 125.923971, "composition": 0.0}, - 127: {"mass": 126.922727, "composition": 0.0}, - 128: {"mass": 127.918911, "composition": 0.0}, - 129: {"mass": 128.918102, "composition": 0.0}, - 130: {"mass": 129.914736, "composition": 0.0}, - 131: {"mass": 130.914429, "composition": 0.0}, - 132: {"mass": 131.911464, "composition": 0.0}, - 133: {"mass": 132.91152, "composition": 0.0}, - 134: {"mass": 133.908928, "composition": 0.0}, - 135: {"mass": 134.909161, "composition": 0.0}, - 136: {"mass": 135.90712921, "composition": 0.00185}, - 137: {"mass": 136.90776236, "composition": 0.0}, - 138: {"mass": 137.905991, "composition": 0.00251}, - 139: {"mass": 138.9066551, "composition": 0.0}, - 140: {"mass": 139.9054431, "composition": 0.8845}, - 141: {"mass": 140.9082807, "composition": 0.0}, - 142: {"mass": 141.9092504, "composition": 0.11114}, - 143: {"mass": 142.9123921, "composition": 0.0}, - 144: {"mass": 143.9136529, "composition": 0.0}, - 145: {"mass": 144.917265, "composition": 0.0}, - 146: {"mass": 145.918802, "composition": 0.0}, - 147: {"mass": 146.9226899, "composition": 0.0}, - 148: {"mass": 147.924424, "composition": 0.0}, - 149: {"mass": 148.928427, "composition": 0.0}, - 150: {"mass": 149.930384, "composition": 0.0}, - 151: {"mass": 150.934272, "composition": 0.0}, - 152: {"mass": 151.9366, "composition": 0.0}, - 153: {"mass": 152.94093, "composition": 0.0}, - 154: {"mass": 153.9438, "composition": 0.0}, - 155: {"mass": 154.94855, "composition": 0.0}, - 156: {"mass": 155.95183, "composition": 0.0}, - 157: {"mass": 156.95705, "composition": 0.0}}, - 59: {121: {"mass": 120.95532, "composition": 0.0}, - 122: {"mass": 121.95175, "composition": 0.0}, - 123: {"mass": 122.94596, "composition": 0.0}, - 124: {"mass": 123.94294, "composition": 0.0}, - 125: {"mass": 124.9377, "composition": 0.0}, - 126: {"mass": 125.93524, "composition": 0.0}, - 127: {"mass": 126.93071, "composition": 0.0}, - 128: {"mass": 127.928791, "composition": 0.0}, - 129: {"mass": 128.925095, "composition": 0.0}, - 130: {"mass": 129.92359, "composition": 0.0}, - 131: {"mass": 130.920235, "composition": 0.0}, - 132: {"mass": 131.919255, "composition": 0.0}, - 133: {"mass": 132.916331, "composition": 0.0}, - 134: {"mass": 133.915697, "composition": 0.0}, - 135: {"mass": 134.913112, "composition": 0.0}, - 136: {"mass": 135.912677, "composition": 0.0}, - 137: {"mass": 136.9106792, "composition": 0.0}, - 138: {"mass": 137.910754, "composition": 0.0}, - 139: {"mass": 138.9089408, "composition": 0.0}, - 140: {"mass": 139.9090803, "composition": 0.0}, - 141: {"mass": 140.9076576, "composition": 1.0}, - 142: {"mass": 141.9100496, "composition": 0.0}, - 143: {"mass": 142.9108228, "composition": 0.0}, - 144: {"mass": 143.9133109, "composition": 0.0}, - 145: {"mass": 144.9145182, "composition": 0.0}, - 146: {"mass": 145.91768, "composition": 0.0}, - 147: {"mass": 146.919008, "composition": 0.0}, - 148: {"mass": 147.92213, "composition": 0.0}, - 149: {"mass": 148.923736, "composition": 0.0}, - 150: {"mass": 149.9266765, "composition": 0.0}, - 151: {"mass": 150.928309, "composition": 0.0}, - 152: {"mass": 151.931553, "composition": 0.0}, - 153: {"mass": 152.933904, "composition": 0.0}, - 154: {"mass": 153.93753, "composition": 0.0}, - 155: {"mass": 154.940509, "composition": 0.0}, - 156: {"mass": 155.94464, "composition": 0.0}, - 157: {"mass": 156.94789, "composition": 0.0}, - 158: {"mass": 157.95241, "composition": 0.0}, - 159: {"mass": 158.95589, "composition": 0.0}}, - 60: {124: {"mass": 123.9522, "composition": 0.0}, - 125: {"mass": 124.9489, "composition": 0.0}, - 126: {"mass": 125.94311, "composition": 0.0}, - 127: {"mass": 126.94038, "composition": 0.0}, - 128: {"mass": 127.93525, "composition": 0.0}, - 129: {"mass": 128.9331, "composition": 0.0}, - 130: {"mass": 129.928506, "composition": 0.0}, - 131: {"mass": 130.927248, "composition": 0.0}, - 132: {"mass": 131.923321, "composition": 0.0}, - 133: {"mass": 132.922348, "composition": 0.0}, - 134: {"mass": 133.91879, "composition": 0.0}, - 135: {"mass": 134.918181, "composition": 0.0}, - 136: {"mass": 135.914976, "composition": 0.0}, - 137: {"mass": 136.914562, "composition": 0.0}, - 138: {"mass": 137.91195, "composition": 0.0}, - 139: {"mass": 138.911954, "composition": 0.0}, - 140: {"mass": 139.90955, "composition": 0.0}, - 141: {"mass": 140.9096147, "composition": 0.0}, - 142: {"mass": 141.907729, "composition": 0.27152}, - 143: {"mass": 142.90982, "composition": 0.12174}, - 144: {"mass": 143.910093, "composition": 0.23798}, - 145: {"mass": 144.9125793, "composition": 0.08293}, - 146: {"mass": 145.9131226, "composition": 0.17189}, - 147: {"mass": 146.9161061, "composition": 0.0}, - 148: {"mass": 147.9168993, "composition": 0.05756}, - 149: {"mass": 148.9201548, "composition": 0.0}, - 150: {"mass": 149.9209022, "composition": 0.05638}, - 151: {"mass": 150.9238403, "composition": 0.0}, - 152: {"mass": 151.924692, "composition": 0.0}, - 153: {"mass": 152.927718, "composition": 0.0}, - 154: {"mass": 153.92948, "composition": 0.0}, - 155: {"mass": 154.9331357, "composition": 0.0}, - 156: {"mass": 155.93508, "composition": 0.0}, - 157: {"mass": 156.939386, "composition": 0.0}, - 158: {"mass": 157.94197, "composition": 0.0}, - 159: {"mass": 158.94653, "composition": 0.0}, - 160: {"mass": 159.9494, "composition": 0.0}, - 161: {"mass": 160.95428, "composition": 0.0}}, - 61: {126: {"mass": 125.95792, "composition": 0.0}, - 127: {"mass": 126.95192, "composition": 0.0}, - 128: {"mass": 127.9487, "composition": 0.0}, - 129: {"mass": 128.94323, "composition": 0.0}, - 130: {"mass": 129.94053, "composition": 0.0}, - 131: {"mass": 130.93567, "composition": 0.0}, - 132: {"mass": 131.93384, "composition": 0.0}, - 133: {"mass": 132.929782, "composition": 0.0}, - 134: {"mass": 133.928353, "composition": 0.0}, - 135: {"mass": 134.924823, "composition": 0.0}, - 136: {"mass": 135.923585, "composition": 0.0}, - 137: {"mass": 136.92048, "composition": 0.0}, - 138: {"mass": 137.919548, "composition": 0.0}, - 139: {"mass": 138.9168, "composition": 0.0}, - 140: {"mass": 139.91604, "composition": 0.0}, - 141: {"mass": 140.913555, "composition": 0.0}, - 142: {"mass": 141.91289, "composition": 0.0}, - 143: {"mass": 142.9109383, "composition": 0.0}, - 144: {"mass": 143.9125964, "composition": 0.0}, - 145: {"mass": 144.9127559, "composition": 0.0}, - 146: {"mass": 145.9147024, "composition": 0.0}, - 147: {"mass": 146.915145, "composition": 0.0}, - 148: {"mass": 147.9174819, "composition": 0.0}, - 149: {"mass": 148.9183423, "composition": 0.0}, - 150: {"mass": 149.920991, "composition": 0.0}, - 151: {"mass": 150.9212175, "composition": 0.0}, - 152: {"mass": 151.923506, "composition": 0.0}, - 153: {"mass": 152.9241567, "composition": 0.0}, - 154: {"mass": 153.926472, "composition": 0.0}, - 155: {"mass": 154.928137, "composition": 0.0}, - 156: {"mass": 155.9311175, "composition": 0.0}, - 157: {"mass": 156.9331214, "composition": 0.0}, - 158: {"mass": 157.936565, "composition": 0.0}, - 159: {"mass": 158.939287, "composition": 0.0}, - 160: {"mass": 159.9431, "composition": 0.0}, - 161: {"mass": 160.94607, "composition": 0.0}, - 162: {"mass": 161.95022, "composition": 0.0}, - 163: {"mass": 162.95357, "composition": 0.0}}, - 62: {128: {"mass": 127.95842, "composition": 0.0}, - 129: {"mass": 128.95476, "composition": 0.0}, - 130: {"mass": 129.949, "composition": 0.0}, - 131: {"mass": 130.94618, "composition": 0.0}, - 132: {"mass": 131.94087, "composition": 0.0}, - 133: {"mass": 132.93856, "composition": 0.0}, - 134: {"mass": 133.93411, "composition": 0.0}, - 135: {"mass": 134.93252, "composition": 0.0}, - 136: {"mass": 135.928276, "composition": 0.0}, - 137: {"mass": 136.926971, "composition": 0.0}, - 138: {"mass": 137.923244, "composition": 0.0}, - 139: {"mass": 138.922297, "composition": 0.0}, - 140: {"mass": 139.918995, "composition": 0.0}, - 141: {"mass": 140.9184816, "composition": 0.0}, - 142: {"mass": 141.9152044, "composition": 0.0}, - 143: {"mass": 142.9146353, "composition": 0.0}, - 144: {"mass": 143.9120065, "composition": 0.0307}, - 145: {"mass": 144.9134173, "composition": 0.0}, - 146: {"mass": 145.913047, "composition": 0.0}, - 147: {"mass": 146.9149044, "composition": 0.1499}, - 148: {"mass": 147.9148292, "composition": 0.1124}, - 149: {"mass": 148.9171921, "composition": 0.1382}, - 150: {"mass": 149.9172829, "composition": 0.0738}, - 151: {"mass": 150.9199398, "composition": 0.0}, - 152: {"mass": 151.9197397, "composition": 0.2675}, - 153: {"mass": 152.9221047, "composition": 0.0}, - 154: {"mass": 153.9222169, "composition": 0.2275}, - 155: {"mass": 154.9246477, "composition": 0.0}, - 156: {"mass": 155.925536, "composition": 0.0}, - 157: {"mass": 156.9284187, "composition": 0.0}, - 158: {"mass": 157.929951, "composition": 0.0}, - 159: {"mass": 158.9332172, "composition": 0.0}, - 160: {"mass": 159.9353353, "composition": 0.0}, - 161: {"mass": 160.9391602, "composition": 0.0}, - 162: {"mass": 161.94146, "composition": 0.0}, - 163: {"mass": 162.94555, "composition": 0.0}, - 164: {"mass": 163.94836, "composition": 0.0}, - 165: {"mass": 164.95297, "composition": 0.0}}, - 63: {130: {"mass": 129.96369, "composition": 0.0}, - 131: {"mass": 130.95784, "composition": 0.0}, - 132: {"mass": 131.95467, "composition": 0.0}, - 133: {"mass": 132.94929, "composition": 0.0}, - 134: {"mass": 133.9464, "composition": 0.0}, - 135: {"mass": 134.94187, "composition": 0.0}, - 136: {"mass": 135.93962, "composition": 0.0}, - 137: {"mass": 136.93546, "composition": 0.0}, - 138: {"mass": 137.933709, "composition": 0.0}, - 139: {"mass": 138.929792, "composition": 0.0}, - 140: {"mass": 139.928088, "composition": 0.0}, - 141: {"mass": 140.924932, "composition": 0.0}, - 142: {"mass": 141.923442, "composition": 0.0}, - 143: {"mass": 142.920299, "composition": 0.0}, - 144: {"mass": 143.91882, "composition": 0.0}, - 145: {"mass": 144.9162726, "composition": 0.0}, - 146: {"mass": 145.917211, "composition": 0.0}, - 147: {"mass": 146.9167527, "composition": 0.0}, - 148: {"mass": 147.918089, "composition": 0.0}, - 149: {"mass": 148.9179378, "composition": 0.0}, - 150: {"mass": 149.9197077, "composition": 0.0}, - 151: {"mass": 150.9198578, "composition": 0.4781}, - 152: {"mass": 151.9217522, "composition": 0.0}, - 153: {"mass": 152.921238, "composition": 0.5219}, - 154: {"mass": 153.922987, "composition": 0.0}, - 155: {"mass": 154.9229011, "composition": 0.0}, - 156: {"mass": 155.9247605, "composition": 0.0}, - 157: {"mass": 156.9254334, "composition": 0.0}, - 158: {"mass": 157.927799, "composition": 0.0}, - 159: {"mass": 158.9291001, "composition": 0.0}, - 160: {"mass": 159.931851, "composition": 0.0}, - 161: {"mass": 160.933664, "composition": 0.0}, - 162: {"mass": 161.936989, "composition": 0.0}, - 163: {"mass": 162.939196, "composition": 0.0}, - 164: {"mass": 163.94274, "composition": 0.0}, - 165: {"mass": 164.94559, "composition": 0.0}, - 166: {"mass": 165.94962, "composition": 0.0}, - 167: {"mass": 166.95289, "composition": 0.0}}, - 64: {133: {"mass": 132.96133, "composition": 0.0}, - 134: {"mass": 133.95566, "composition": 0.0}, - 135: {"mass": 134.95245, "composition": 0.0}, - 136: {"mass": 135.9473, "composition": 0.0}, - 137: {"mass": 136.94502, "composition": 0.0}, - 138: {"mass": 137.94025, "composition": 0.0}, - 139: {"mass": 138.93813, "composition": 0.0}, - 140: {"mass": 139.933674, "composition": 0.0}, - 141: {"mass": 140.932126, "composition": 0.0}, - 142: {"mass": 141.928116, "composition": 0.0}, - 143: {"mass": 142.92675, "composition": 0.0}, - 144: {"mass": 143.922963, "composition": 0.0}, - 145: {"mass": 144.921713, "composition": 0.0}, - 146: {"mass": 145.9183188, "composition": 0.0}, - 147: {"mass": 146.9191014, "composition": 0.0}, - 148: {"mass": 147.9181215, "composition": 0.0}, - 149: {"mass": 148.9193481, "composition": 0.0}, - 150: {"mass": 149.9186644, "composition": 0.0}, - 151: {"mass": 150.920356, "composition": 0.0}, - 152: {"mass": 151.9197995, "composition": 0.002}, - 153: {"mass": 152.921758, "composition": 0.0}, - 154: {"mass": 153.9208741, "composition": 0.0218}, - 155: {"mass": 154.9226305, "composition": 0.148}, - 156: {"mass": 155.9221312, "composition": 0.2047}, - 157: {"mass": 156.9239686, "composition": 0.1565}, - 158: {"mass": 157.9241123, "composition": 0.2484}, - 159: {"mass": 158.926397, "composition": 0.0}, - 160: {"mass": 159.9270624, "composition": 0.2186}, - 161: {"mass": 160.9296775, "composition": 0.0}, - 162: {"mass": 161.930993, "composition": 0.0}, - 163: {"mass": 162.9341769, "composition": 0.0}, - 164: {"mass": 163.93583, "composition": 0.0}, - 165: {"mass": 164.93936, "composition": 0.0}, - 166: {"mass": 165.94146, "composition": 0.0}, - 167: {"mass": 166.94545, "composition": 0.0}, - 168: {"mass": 167.94808, "composition": 0.0}, - 169: {"mass": 168.9526, "composition": 0.0}}, - 65: {135: {"mass": 134.96476, "composition": 0.0}, - 136: {"mass": 135.96129, "composition": 0.0}, - 137: {"mass": 136.95602, "composition": 0.0}, - 138: {"mass": 137.95312, "composition": 0.0}, - 139: {"mass": 138.94833, "composition": 0.0}, - 140: {"mass": 139.94581, "composition": 0.0}, - 141: {"mass": 140.94145, "composition": 0.0}, - 142: {"mass": 141.93928, "composition": 0.0}, - 143: {"mass": 142.935137, "composition": 0.0}, - 144: {"mass": 143.933045, "composition": 0.0}, - 145: {"mass": 144.92882, "composition": 0.0}, - 146: {"mass": 145.927253, "composition": 0.0}, - 147: {"mass": 146.9240548, "composition": 0.0}, - 148: {"mass": 147.924282, "composition": 0.0}, - 149: {"mass": 148.9232535, "composition": 0.0}, - 150: {"mass": 149.9236649, "composition": 0.0}, - 151: {"mass": 150.9231096, "composition": 0.0}, - 152: {"mass": 151.924083, "composition": 0.0}, - 153: {"mass": 152.9234424, "composition": 0.0}, - 154: {"mass": 153.924685, "composition": 0.0}, - 155: {"mass": 154.923511, "composition": 0.0}, - 156: {"mass": 155.9247552, "composition": 0.0}, - 157: {"mass": 156.924033, "composition": 0.0}, - 158: {"mass": 157.9254209, "composition": 0.0}, - 159: {"mass": 158.9253547, "composition": 1.0}, - 160: {"mass": 159.9271756, "composition": 0.0}, - 161: {"mass": 160.9275778, "composition": 0.0}, - 162: {"mass": 161.929495, "composition": 0.0}, - 163: {"mass": 162.9306547, "composition": 0.0}, - 164: {"mass": 163.93336, "composition": 0.0}, - 165: {"mass": 164.93498, "composition": 0.0}, - 166: {"mass": 165.93786, "composition": 0.0}, - 167: {"mass": 166.93996, "composition": 0.0}, - 168: {"mass": 167.9434, "composition": 0.0}, - 169: {"mass": 168.94597, "composition": 0.0}, - 170: {"mass": 169.94984, "composition": 0.0}, - 171: {"mass": 170.95273, "composition": 0.0}}, - 66: {138: {"mass": 137.9625, "composition": 0.0}, - 139: {"mass": 138.95959, "composition": 0.0}, - 140: {"mass": 139.95402, "composition": 0.0}, - 141: {"mass": 140.95128, "composition": 0.0}, - 142: {"mass": 141.94619, "composition": 0.0}, - 143: {"mass": 142.943994, "composition": 0.0}, - 144: {"mass": 143.9392695, "composition": 0.0}, - 145: {"mass": 144.937474, "composition": 0.0}, - 146: {"mass": 145.9328445, "composition": 0.0}, - 147: {"mass": 146.9310827, "composition": 0.0}, - 148: {"mass": 147.927157, "composition": 0.0}, - 149: {"mass": 148.927322, "composition": 0.0}, - 150: {"mass": 149.9255933, "composition": 0.0}, - 151: {"mass": 150.9261916, "composition": 0.0}, - 152: {"mass": 151.9247253, "composition": 0.0}, - 153: {"mass": 152.9257724, "composition": 0.0}, - 154: {"mass": 153.9244293, "composition": 0.0}, - 155: {"mass": 154.925759, "composition": 0.0}, - 156: {"mass": 155.9242847, "composition": 0.00056}, - 157: {"mass": 156.9254707, "composition": 0.0}, - 158: {"mass": 157.9244159, "composition": 0.00095}, - 159: {"mass": 158.925747, "composition": 0.0}, - 160: {"mass": 159.9252046, "composition": 0.02329}, - 161: {"mass": 160.9269405, "composition": 0.18889}, - 162: {"mass": 161.9268056, "composition": 0.25475}, - 163: {"mass": 162.9287383, "composition": 0.24896}, - 164: {"mass": 163.9291819, "composition": 0.2826}, - 165: {"mass": 164.9317105, "composition": 0.0}, - 166: {"mass": 165.9328139, "composition": 0.0}, - 167: {"mass": 166.935661, "composition": 0.0}, - 168: {"mass": 167.93713, "composition": 0.0}, - 169: {"mass": 168.94031, "composition": 0.0}, - 170: {"mass": 169.94239, "composition": 0.0}, - 171: {"mass": 170.94612, "composition": 0.0}, - 172: {"mass": 171.94846, "composition": 0.0}, - 173: {"mass": 172.95283, "composition": 0.0}}, - 67: {140: {"mass": 139.96859, "composition": 0.0}, - 141: {"mass": 140.96311, "composition": 0.0}, - 142: {"mass": 141.96001, "composition": 0.0}, - 143: {"mass": 142.95486, "composition": 0.0}, - 144: {"mass": 143.9521097, "composition": 0.0}, - 145: {"mass": 144.9472674, "composition": 0.0}, - 146: {"mass": 145.9449935, "composition": 0.0}, - 147: {"mass": 146.9401423, "composition": 0.0}, - 148: {"mass": 147.937744, "composition": 0.0}, - 149: {"mass": 148.933803, "composition": 0.0}, - 150: {"mass": 149.933498, "composition": 0.0}, - 151: {"mass": 150.9316983, "composition": 0.0}, - 152: {"mass": 151.931724, "composition": 0.0}, - 153: {"mass": 152.9302064, "composition": 0.0}, - 154: {"mass": 153.9306068, "composition": 0.0}, - 155: {"mass": 154.929104, "composition": 0.0}, - 156: {"mass": 155.929706, "composition": 0.0}, - 157: {"mass": 156.928254, "composition": 0.0}, - 158: {"mass": 157.928946, "composition": 0.0}, - 159: {"mass": 158.9277197, "composition": 0.0}, - 160: {"mass": 159.928737, "composition": 0.0}, - 161: {"mass": 160.9278615, "composition": 0.0}, - 162: {"mass": 161.9291023, "composition": 0.0}, - 163: {"mass": 162.928741, "composition": 0.0}, - 164: {"mass": 163.9302403, "composition": 0.0}, - 165: {"mass": 164.9303288, "composition": 1.0}, - 166: {"mass": 165.9322909, "composition": 0.0}, - 167: {"mass": 166.9331385, "composition": 0.0}, - 168: {"mass": 167.935522, "composition": 0.0}, - 169: {"mass": 168.936878, "composition": 0.0}, - 170: {"mass": 169.939625, "composition": 0.0}, - 171: {"mass": 170.94147, "composition": 0.0}, - 172: {"mass": 171.94473, "composition": 0.0}, - 173: {"mass": 172.94702, "composition": 0.0}, - 174: {"mass": 173.95095, "composition": 0.0}, - 175: {"mass": 174.95362, "composition": 0.0}}, - 68: {142: {"mass": 141.9701, "composition": 0.0}, - 143: {"mass": 142.96662, "composition": 0.0}, - 144: {"mass": 143.9607, "composition": 0.0}, - 145: {"mass": 144.95805, "composition": 0.0}, - 146: {"mass": 145.9524184, "composition": 0.0}, - 147: {"mass": 146.949964, "composition": 0.0}, - 148: {"mass": 147.944735, "composition": 0.0}, - 149: {"mass": 148.942306, "composition": 0.0}, - 150: {"mass": 149.937916, "composition": 0.0}, - 151: {"mass": 150.937449, "composition": 0.0}, - 152: {"mass": 151.935057, "composition": 0.0}, - 153: {"mass": 152.93508, "composition": 0.0}, - 154: {"mass": 153.9327908, "composition": 0.0}, - 155: {"mass": 154.9332159, "composition": 0.0}, - 156: {"mass": 155.931067, "composition": 0.0}, - 157: {"mass": 156.931949, "composition": 0.0}, - 158: {"mass": 157.929893, "composition": 0.0}, - 159: {"mass": 158.9306918, "composition": 0.0}, - 160: {"mass": 159.929077, "composition": 0.0}, - 161: {"mass": 160.9300046, "composition": 0.0}, - 162: {"mass": 161.9287884, "composition": 0.00139}, - 163: {"mass": 162.9300408, "composition": 0.0}, - 164: {"mass": 163.9292088, "composition": 0.01601}, - 165: {"mass": 164.9307345, "composition": 0.0}, - 166: {"mass": 165.9302995, "composition": 0.33503}, - 167: {"mass": 166.9320546, "composition": 0.22869}, - 168: {"mass": 167.9323767, "composition": 0.26978}, - 169: {"mass": 168.9345968, "composition": 0.0}, - 170: {"mass": 169.9354702, "composition": 0.1491}, - 171: {"mass": 170.9380357, "composition": 0.0}, - 172: {"mass": 171.9393619, "composition": 0.0}, - 173: {"mass": 172.9424, "composition": 0.0}, - 174: {"mass": 173.94423, "composition": 0.0}, - 175: {"mass": 174.94777, "composition": 0.0}, - 176: {"mass": 175.94994, "composition": 0.0}, - 177: {"mass": 176.95399, "composition": 0.0}}, - 69: {144: {"mass": 143.97628, "composition": 0.0}, - 145: {"mass": 144.97039, "composition": 0.0}, - 146: {"mass": 145.96684, "composition": 0.0}, - 147: {"mass": 146.9613799, "composition": 0.0}, - 148: {"mass": 147.958384, "composition": 0.0}, - 149: {"mass": 148.95289, "composition": 0.0}, - 150: {"mass": 149.95009, "composition": 0.0}, - 151: {"mass": 150.945488, "composition": 0.0}, - 152: {"mass": 151.944422, "composition": 0.0}, - 153: {"mass": 152.94204, "composition": 0.0}, - 154: {"mass": 153.94157, "composition": 0.0}, - 155: {"mass": 154.93921, "composition": 0.0}, - 156: {"mass": 155.938992, "composition": 0.0}, - 157: {"mass": 156.936944, "composition": 0.0}, - 158: {"mass": 157.93698, "composition": 0.0}, - 159: {"mass": 158.934975, "composition": 0.0}, - 160: {"mass": 159.935263, "composition": 0.0}, - 161: {"mass": 160.933549, "composition": 0.0}, - 162: {"mass": 161.934002, "composition": 0.0}, - 163: {"mass": 162.9326592, "composition": 0.0}, - 164: {"mass": 163.933544, "composition": 0.0}, - 165: {"mass": 164.9324431, "composition": 0.0}, - 166: {"mass": 165.933561, "composition": 0.0}, - 167: {"mass": 166.9328562, "composition": 0.0}, - 168: {"mass": 167.9341774, "composition": 0.0}, - 169: {"mass": 168.9342179, "composition": 1.0}, - 170: {"mass": 169.935806, "composition": 0.0}, - 171: {"mass": 170.9364339, "composition": 0.0}, - 172: {"mass": 171.9384055, "composition": 0.0}, - 173: {"mass": 172.9396084, "composition": 0.0}, - 174: {"mass": 173.942173, "composition": 0.0}, - 175: {"mass": 174.943841, "composition": 0.0}, - 176: {"mass": 175.947, "composition": 0.0}, - 177: {"mass": 176.94904, "composition": 0.0}, - 178: {"mass": 177.95264, "composition": 0.0}, - 179: {"mass": 178.95534, "composition": 0.0}}, - 70: {148: {"mass": 147.96758, "composition": 0.0}, - 149: {"mass": 148.96436, "composition": 0.0}, - 150: {"mass": 149.95852, "composition": 0.0}, - 151: {"mass": 150.9554, "composition": 0.0}, - 152: {"mass": 151.95027, "composition": 0.0}, - 153: {"mass": 152.94932, "composition": 0.0}, - 154: {"mass": 153.946396, "composition": 0.0}, - 155: {"mass": 154.945783, "composition": 0.0}, - 156: {"mass": 155.942825, "composition": 0.0}, - 157: {"mass": 156.942645, "composition": 0.0}, - 158: {"mass": 157.9398705, "composition": 0.0}, - 159: {"mass": 158.940055, "composition": 0.0}, - 160: {"mass": 159.937557, "composition": 0.0}, - 161: {"mass": 160.937907, "composition": 0.0}, - 162: {"mass": 161.935774, "composition": 0.0}, - 163: {"mass": 162.93634, "composition": 0.0}, - 164: {"mass": 163.934495, "composition": 0.0}, - 165: {"mass": 164.93527, "composition": 0.0}, - 166: {"mass": 165.9338747, "composition": 0.0}, - 167: {"mass": 166.934953, "composition": 0.0}, - 168: {"mass": 167.9338896, "composition": 0.00123}, - 169: {"mass": 168.9351825, "composition": 0.0}, - 170: {"mass": 169.9347664, "composition": 0.02982}, - 171: {"mass": 170.9363302, "composition": 0.1409}, - 172: {"mass": 171.9363859, "composition": 0.2168}, - 173: {"mass": 172.9382151, "composition": 0.16103}, - 174: {"mass": 173.9388664, "composition": 0.32026}, - 175: {"mass": 174.9412808, "composition": 0.0}, - 176: {"mass": 175.9425764, "composition": 0.12996}, - 177: {"mass": 176.9452656, "composition": 0.0}, - 178: {"mass": 177.946651, "composition": 0.0}, - 179: {"mass": 178.95004, "composition": 0.0}, - 180: {"mass": 179.95212, "composition": 0.0}, - 181: {"mass": 180.95589, "composition": 0.0}}, - 71: {150: {"mass": 149.97355, "composition": 0.0}, - 151: {"mass": 150.96768, "composition": 0.0}, - 152: {"mass": 151.96412, "composition": 0.0}, - 153: {"mass": 152.95875, "composition": 0.0}, - 154: {"mass": 153.95736, "composition": 0.0}, - 155: {"mass": 154.954321, "composition": 0.0}, - 156: {"mass": 155.953033, "composition": 0.0}, - 157: {"mass": 156.950127, "composition": 0.0}, - 158: {"mass": 157.949316, "composition": 0.0}, - 159: {"mass": 158.946636, "composition": 0.0}, - 160: {"mass": 159.946033, "composition": 0.0}, - 161: {"mass": 160.943572, "composition": 0.0}, - 162: {"mass": 161.943283, "composition": 0.0}, - 163: {"mass": 162.941179, "composition": 0.0}, - 164: {"mass": 163.941339, "composition": 0.0}, - 165: {"mass": 164.939407, "composition": 0.0}, - 166: {"mass": 165.939859, "composition": 0.0}, - 167: {"mass": 166.93827, "composition": 0.0}, - 168: {"mass": 167.938736, "composition": 0.0}, - 169: {"mass": 168.9376441, "composition": 0.0}, - 170: {"mass": 169.938478, "composition": 0.0}, - 171: {"mass": 170.937917, "composition": 0.0}, - 172: {"mass": 171.9390891, "composition": 0.0}, - 173: {"mass": 172.938934, "composition": 0.0}, - 174: {"mass": 173.9403409, "composition": 0.0}, - 175: {"mass": 174.9407752, "composition": 0.97401}, - 176: {"mass": 175.9426897, "composition": 0.02599}, - 177: {"mass": 176.9437615, "composition": 0.0}, - 178: {"mass": 177.945958, "composition": 0.0}, - 179: {"mass": 178.9473309, "composition": 0.0}, - 180: {"mass": 179.949888, "composition": 0.0}, - 181: {"mass": 180.95191, "composition": 0.0}, - 182: {"mass": 181.95504, "composition": 0.0}, - 183: {"mass": 182.957363, "composition": 0.0}, - 184: {"mass": 183.96091, "composition": 0.0}, - 185: {"mass": 184.96362, "composition": 0.0}}, - 72: {153: {"mass": 152.97069, "composition": 0.0}, - 154: {"mass": 153.96486, "composition": 0.0}, - 155: {"mass": 154.96311, "composition": 0.0}, - 156: {"mass": 155.95935, "composition": 0.0}, - 157: {"mass": 156.95824, "composition": 0.0}, - 158: {"mass": 157.954801, "composition": 0.0}, - 159: {"mass": 158.953996, "composition": 0.0}, - 160: {"mass": 159.950691, "composition": 0.0}, - 161: {"mass": 160.950278, "composition": 0.0}, - 162: {"mass": 161.9472148, "composition": 0.0}, - 163: {"mass": 162.947113, "composition": 0.0}, - 164: {"mass": 163.944371, "composition": 0.0}, - 165: {"mass": 164.944567, "composition": 0.0}, - 166: {"mass": 165.94218, "composition": 0.0}, - 167: {"mass": 166.9426, "composition": 0.0}, - 168: {"mass": 167.940568, "composition": 0.0}, - 169: {"mass": 168.941259, "composition": 0.0}, - 170: {"mass": 169.939609, "composition": 0.0}, - 171: {"mass": 170.940492, "composition": 0.0}, - 172: {"mass": 171.93945, "composition": 0.0}, - 173: {"mass": 172.940513, "composition": 0.0}, - 174: {"mass": 173.9400461, "composition": 0.0016}, - 175: {"mass": 174.9415092, "composition": 0.0}, - 176: {"mass": 175.9414076, "composition": 0.0526}, - 177: {"mass": 176.9432277, "composition": 0.186}, - 178: {"mass": 177.9437058, "composition": 0.2728}, - 179: {"mass": 178.9458232, "composition": 0.1362}, - 180: {"mass": 179.946557, "composition": 0.3508}, - 181: {"mass": 180.9491083, "composition": 0.0}, - 182: {"mass": 181.9505612, "composition": 0.0}, - 183: {"mass": 182.95353, "composition": 0.0}, - 184: {"mass": 183.955446, "composition": 0.0}, - 185: {"mass": 184.958862, "composition": 0.0}, - 186: {"mass": 185.960897, "composition": 0.0}, - 187: {"mass": 186.96477, "composition": 0.0}, - 188: {"mass": 187.96685, "composition": 0.0}, - 189: {"mass": 188.97084, "composition": 0.0}}, - 73: {155: {"mass": 154.97424, "composition": 0.0}, - 156: {"mass": 155.97203, "composition": 0.0}, - 157: {"mass": 156.96818, "composition": 0.0}, - 158: {"mass": 157.96654, "composition": 0.0}, - 159: {"mass": 158.963023, "composition": 0.0}, - 160: {"mass": 159.961488, "composition": 0.0}, - 161: {"mass": 160.958452, "composition": 0.0}, - 162: {"mass": 161.957294, "composition": 0.0}, - 163: {"mass": 162.954337, "composition": 0.0}, - 164: {"mass": 163.953534, "composition": 0.0}, - 165: {"mass": 164.950781, "composition": 0.0}, - 166: {"mass": 165.950512, "composition": 0.0}, - 167: {"mass": 166.948093, "composition": 0.0}, - 168: {"mass": 167.948047, "composition": 0.0}, - 169: {"mass": 168.946011, "composition": 0.0}, - 170: {"mass": 169.946175, "composition": 0.0}, - 171: {"mass": 170.944476, "composition": 0.0}, - 172: {"mass": 171.944895, "composition": 0.0}, - 173: {"mass": 172.94375, "composition": 0.0}, - 174: {"mass": 173.944454, "composition": 0.0}, - 175: {"mass": 174.943737, "composition": 0.0}, - 176: {"mass": 175.944857, "composition": 0.0}, - 177: {"mass": 176.9444795, "composition": 0.0}, - 178: {"mass": 177.945678, "composition": 0.0}, - 179: {"mass": 178.9459366, "composition": 0.0}, - 180: {"mass": 179.9474648, "composition": 0.0001201}, - 181: {"mass": 180.9479958, "composition": 0.9998799}, - 182: {"mass": 181.9501519, "composition": 0.0}, - 183: {"mass": 182.9513726, "composition": 0.0}, - 184: {"mass": 183.954008, "composition": 0.0}, - 185: {"mass": 184.955559, "composition": 0.0}, - 186: {"mass": 185.958551, "composition": 0.0}, - 187: {"mass": 186.960386, "composition": 0.0}, - 188: {"mass": 187.963916, "composition": 0.0}, - 189: {"mass": 188.96583, "composition": 0.0}, - 190: {"mass": 189.96939, "composition": 0.0}, - 191: {"mass": 190.97156, "composition": 0.0}, - 192: {"mass": 191.97514, "composition": 0.0}}, - 74: {157: {"mass": 156.97884, "composition": 0.0}, - 158: {"mass": 157.97456, "composition": 0.0}, - 159: {"mass": 158.97264, "composition": 0.0}, - 160: {"mass": 159.96846, "composition": 0.0}, - 161: {"mass": 160.9672, "composition": 0.0}, - 162: {"mass": 161.963499, "composition": 0.0}, - 163: {"mass": 162.962524, "composition": 0.0}, - 164: {"mass": 163.958961, "composition": 0.0}, - 165: {"mass": 164.958281, "composition": 0.0}, - 166: {"mass": 165.955031, "composition": 0.0}, - 167: {"mass": 166.954805, "composition": 0.0}, - 168: {"mass": 167.951806, "composition": 0.0}, - 169: {"mass": 168.951779, "composition": 0.0}, - 170: {"mass": 169.949232, "composition": 0.0}, - 171: {"mass": 170.949451, "composition": 0.0}, - 172: {"mass": 171.947292, "composition": 0.0}, - 173: {"mass": 172.947689, "composition": 0.0}, - 174: {"mass": 173.946079, "composition": 0.0}, - 175: {"mass": 174.946717, "composition": 0.0}, - 176: {"mass": 175.945634, "composition": 0.0}, - 177: {"mass": 176.946643, "composition": 0.0}, - 178: {"mass": 177.945883, "composition": 0.0}, - 179: {"mass": 178.947077, "composition": 0.0}, - 180: {"mass": 179.9467108, "composition": 0.0012}, - 181: {"mass": 180.9481978, "composition": 0.0}, - 182: {"mass": 181.94820394, "composition": 0.265}, - 183: {"mass": 182.95022275, "composition": 0.1431}, - 184: {"mass": 183.95093092, "composition": 0.3064}, - 185: {"mass": 184.95341897, "composition": 0.0}, - 186: {"mass": 185.9543628, "composition": 0.2843}, - 187: {"mass": 186.9571588, "composition": 0.0}, - 188: {"mass": 187.9584862, "composition": 0.0}, - 189: {"mass": 188.961763, "composition": 0.0}, - 190: {"mass": 189.963091, "composition": 0.0}, - 191: {"mass": 190.966531, "composition": 0.0}, - 192: {"mass": 191.96817, "composition": 0.0}, - 193: {"mass": 192.97178, "composition": 0.0}, - 194: {"mass": 193.97367, "composition": 0.0}}, - 75: {159: {"mass": 158.98418, "composition": 0.0}, - 160: {"mass": 159.98182, "composition": 0.0}, - 161: {"mass": 160.97757, "composition": 0.0}, - 162: {"mass": 161.97584, "composition": 0.0}, - 163: {"mass": 162.97208, "composition": 0.0}, - 164: {"mass": 163.970453, "composition": 0.0}, - 165: {"mass": 164.967103, "composition": 0.0}, - 166: {"mass": 165.965761, "composition": 0.0}, - 167: {"mass": 166.962595, "composition": 0.0}, - 168: {"mass": 167.961573, "composition": 0.0}, - 169: {"mass": 168.958766, "composition": 0.0}, - 170: {"mass": 169.95822, "composition": 0.0}, - 171: {"mass": 170.955716, "composition": 0.0}, - 172: {"mass": 171.95542, "composition": 0.0}, - 173: {"mass": 172.953243, "composition": 0.0}, - 174: {"mass": 173.953115, "composition": 0.0}, - 175: {"mass": 174.951381, "composition": 0.0}, - 176: {"mass": 175.951623, "composition": 0.0}, - 177: {"mass": 176.950328, "composition": 0.0}, - 178: {"mass": 177.950989, "composition": 0.0}, - 179: {"mass": 178.949989, "composition": 0.0}, - 180: {"mass": 179.950792, "composition": 0.0}, - 181: {"mass": 180.950058, "composition": 0.0}, - 182: {"mass": 181.95121, "composition": 0.0}, - 183: {"mass": 182.9508196, "composition": 0.0}, - 184: {"mass": 183.9525228, "composition": 0.0}, - 185: {"mass": 184.9529545, "composition": 0.374}, - 186: {"mass": 185.9549856, "composition": 0.0}, - 187: {"mass": 186.9557501, "composition": 0.626}, - 188: {"mass": 187.9581115, "composition": 0.0}, - 189: {"mass": 188.959226, "composition": 0.0}, - 190: {"mass": 189.961744, "composition": 0.0}, - 191: {"mass": 190.963122, "composition": 0.0}, - 192: {"mass": 191.966088, "composition": 0.0}, - 193: {"mass": 192.967541, "composition": 0.0}, - 194: {"mass": 193.97076, "composition": 0.0}, - 195: {"mass": 194.97254, "composition": 0.0}, - 196: {"mass": 195.9758, "composition": 0.0}, - 197: {"mass": 196.97799, "composition": 0.0}, - 198: {"mass": 197.9816, "composition": 0.0}}, - 76: {161: {"mass": 160.98903, "composition": 0.0}, - 162: {"mass": 161.98443, "composition": 0.0}, - 163: {"mass": 162.98241, "composition": 0.0}, - 164: {"mass": 163.97802, "composition": 0.0}, - 165: {"mass": 164.9766, "composition": 0.0}, - 166: {"mass": 165.972692, "composition": 0.0}, - 167: {"mass": 166.971549, "composition": 0.0}, - 168: {"mass": 167.967808, "composition": 0.0}, - 169: {"mass": 168.967018, "composition": 0.0}, - 170: {"mass": 169.963578, "composition": 0.0}, - 171: {"mass": 170.963174, "composition": 0.0}, - 172: {"mass": 171.960017, "composition": 0.0}, - 173: {"mass": 172.959808, "composition": 0.0}, - 174: {"mass": 173.957064, "composition": 0.0}, - 175: {"mass": 174.956945, "composition": 0.0}, - 176: {"mass": 175.954806, "composition": 0.0}, - 177: {"mass": 176.954966, "composition": 0.0}, - 178: {"mass": 177.953254, "composition": 0.0}, - 179: {"mass": 178.953817, "composition": 0.0}, - 180: {"mass": 179.952375, "composition": 0.0}, - 181: {"mass": 180.953247, "composition": 0.0}, - 182: {"mass": 181.95211, "composition": 0.0}, - 183: {"mass": 182.953125, "composition": 0.0}, - 184: {"mass": 183.9524885, "composition": 0.0002}, - 185: {"mass": 184.9540417, "composition": 0.0}, - 186: {"mass": 185.953835, "composition": 0.0159}, - 187: {"mass": 186.9557474, "composition": 0.0196}, - 188: {"mass": 187.9558352, "composition": 0.1324}, - 189: {"mass": 188.9581442, "composition": 0.1615}, - 190: {"mass": 189.9584437, "composition": 0.2626}, - 191: {"mass": 190.9609264, "composition": 0.0}, - 192: {"mass": 191.961477, "composition": 0.4078}, - 193: {"mass": 192.9641479, "composition": 0.0}, - 194: {"mass": 193.9651772, "composition": 0.0}, - 195: {"mass": 194.968318, "composition": 0.0}, - 196: {"mass": 195.969641, "composition": 0.0}, - 197: {"mass": 196.97283, "composition": 0.0}, - 198: {"mass": 197.97441, "composition": 0.0}, - 199: {"mass": 198.97801, "composition": 0.0}, - 200: {"mass": 199.97984, "composition": 0.0}, - 201: {"mass": 200.98364, "composition": 0.0}, - 202: {"mass": 201.98595, "composition": 0.0}}, - 77: {164: {"mass": 163.99191, "composition": 0.0}, - 165: {"mass": 164.9875, "composition": 0.0}, - 166: {"mass": 165.98566, "composition": 0.0}, - 167: {"mass": 166.981666, "composition": 0.0}, - 168: {"mass": 167.979907, "composition": 0.0}, - 169: {"mass": 168.976298, "composition": 0.0}, - 170: {"mass": 169.974922, "composition": 0.0}, - 171: {"mass": 170.97164, "composition": 0.0}, - 172: {"mass": 171.970607, "composition": 0.0}, - 173: {"mass": 172.967506, "composition": 0.0}, - 174: {"mass": 173.966861, "composition": 0.0}, - 175: {"mass": 174.96415, "composition": 0.0}, - 176: {"mass": 175.96365, "composition": 0.0}, - 177: {"mass": 176.961301, "composition": 0.0}, - 178: {"mass": 177.961082, "composition": 0.0}, - 179: {"mass": 178.95912, "composition": 0.0}, - 180: {"mass": 179.959229, "composition": 0.0}, - 181: {"mass": 180.957625, "composition": 0.0}, - 182: {"mass": 181.958076, "composition": 0.0}, - 183: {"mass": 182.95684, "composition": 0.0}, - 184: {"mass": 183.957476, "composition": 0.0}, - 185: {"mass": 184.956698, "composition": 0.0}, - 186: {"mass": 185.957944, "composition": 0.0}, - 187: {"mass": 186.957542, "composition": 0.0}, - 188: {"mass": 187.958828, "composition": 0.0}, - 189: {"mass": 188.958715, "composition": 0.0}, - 190: {"mass": 189.9605412, "composition": 0.0}, - 191: {"mass": 190.9605893, "composition": 0.373}, - 192: {"mass": 191.9626002, "composition": 0.0}, - 193: {"mass": 192.9629216, "composition": 0.627}, - 194: {"mass": 193.9650735, "composition": 0.0}, - 195: {"mass": 194.9659747, "composition": 0.0}, - 196: {"mass": 195.968397, "composition": 0.0}, - 197: {"mass": 196.969655, "composition": 0.0}, - 198: {"mass": 197.97228, "composition": 0.0}, - 199: {"mass": 198.973805, "composition": 0.0}, - 200: {"mass": 199.9768, "composition": 0.0}, - 201: {"mass": 200.97864, "composition": 0.0}, - 202: {"mass": 201.98199, "composition": 0.0}, - 203: {"mass": 202.98423, "composition": 0.0}, - 204: {"mass": 203.9896, "composition": 0.0}}, - 78: {166: {"mass": 165.99486, "composition": 0.0}, - 167: {"mass": 166.99269, "composition": 0.0}, - 168: {"mass": 167.98813, "composition": 0.0}, - 169: {"mass": 168.98657, "composition": 0.0}, - 170: {"mass": 169.982496, "composition": 0.0}, - 171: {"mass": 170.981245, "composition": 0.0}, - 172: {"mass": 171.977351, "composition": 0.0}, - 173: {"mass": 172.976443, "composition": 0.0}, - 174: {"mass": 173.97282, "composition": 0.0}, - 175: {"mass": 174.97241, "composition": 0.0}, - 176: {"mass": 175.968938, "composition": 0.0}, - 177: {"mass": 176.96847, "composition": 0.0}, - 178: {"mass": 177.96565, "composition": 0.0}, - 179: {"mass": 178.965359, "composition": 0.0}, - 180: {"mass": 179.963032, "composition": 0.0}, - 181: {"mass": 180.963098, "composition": 0.0}, - 182: {"mass": 181.961172, "composition": 0.0}, - 183: {"mass": 182.961597, "composition": 0.0}, - 184: {"mass": 183.959915, "composition": 0.0}, - 185: {"mass": 184.960614, "composition": 0.0}, - 186: {"mass": 185.959351, "composition": 0.0}, - 187: {"mass": 186.960617, "composition": 0.0}, - 188: {"mass": 187.9593889, "composition": 0.0}, - 189: {"mass": 188.960831, "composition": 0.0}, - 190: {"mass": 189.9599297, "composition": 0.00012}, - 191: {"mass": 190.9616729, "composition": 0.0}, - 192: {"mass": 191.9610387, "composition": 0.00782}, - 193: {"mass": 192.9629824, "composition": 0.0}, - 194: {"mass": 193.9626809, "composition": 0.3286}, - 195: {"mass": 194.9647917, "composition": 0.3378}, - 196: {"mass": 195.96495209, "composition": 0.2521}, - 197: {"mass": 196.96734069, "composition": 0.0}, - 198: {"mass": 197.9678949, "composition": 0.07356}, - 199: {"mass": 198.9705952, "composition": 0.0}, - 200: {"mass": 199.971443, "composition": 0.0}, - 201: {"mass": 200.974513, "composition": 0.0}, - 202: {"mass": 201.975639, "composition": 0.0}, - 203: {"mass": 202.97893, "composition": 0.0}, - 204: {"mass": 203.98076, "composition": 0.0}, - 205: {"mass": 204.98608, "composition": 0.0}, - 206: {"mass": 205.98966, "composition": 0.0}}, - 79: {169: {"mass": 168.99808, "composition": 0.0}, - 170: {"mass": 169.99597, "composition": 0.0}, - 171: {"mass": 170.991876, "composition": 0.0}, - 172: {"mass": 171.989942, "composition": 0.0}, - 173: {"mass": 172.986241, "composition": 0.0}, - 174: {"mass": 173.984717, "composition": 0.0}, - 175: {"mass": 174.981304, "composition": 0.0}, - 176: {"mass": 175.98025, "composition": 0.0}, - 177: {"mass": 176.97687, "composition": 0.0}, - 178: {"mass": 177.976032, "composition": 0.0}, - 179: {"mass": 178.973174, "composition": 0.0}, - 180: {"mass": 179.972523, "composition": 0.0}, - 181: {"mass": 180.970079, "composition": 0.0}, - 182: {"mass": 181.969618, "composition": 0.0}, - 183: {"mass": 182.967591, "composition": 0.0}, - 184: {"mass": 183.967452, "composition": 0.0}, - 185: {"mass": 184.96579, "composition": 0.0}, - 186: {"mass": 185.965953, "composition": 0.0}, - 187: {"mass": 186.964543, "composition": 0.0}, - 188: {"mass": 187.965349, "composition": 0.0}, - 189: {"mass": 188.963948, "composition": 0.0}, - 190: {"mass": 189.964698, "composition": 0.0}, - 191: {"mass": 190.963702, "composition": 0.0}, - 192: {"mass": 191.964814, "composition": 0.0}, - 193: {"mass": 192.9641373, "composition": 0.0}, - 194: {"mass": 193.9654178, "composition": 0.0}, - 195: {"mass": 194.9650352, "composition": 0.0}, - 196: {"mass": 195.9665699, "composition": 0.0}, - 197: {"mass": 196.96656879, "composition": 1.0}, - 198: {"mass": 197.96824242, "composition": 0.0}, - 199: {"mass": 198.96876528, "composition": 0.0}, - 200: {"mass": 199.970756, "composition": 0.0}, - 201: {"mass": 200.9716575, "composition": 0.0}, - 202: {"mass": 201.973856, "composition": 0.0}, - 203: {"mass": 202.9751544, "composition": 0.0}, - 204: {"mass": 203.97783, "composition": 0.0}, - 205: {"mass": 204.97985, "composition": 0.0}, - 206: {"mass": 205.98474, "composition": 0.0}, - 207: {"mass": 206.9884, "composition": 0.0}, - 208: {"mass": 207.99345, "composition": 0.0}, - 209: {"mass": 208.99735, "composition": 0.0}, - 210: {"mass": 210.0025, "composition": 0.0}}, - 80: {171: {"mass": 171.00353, "composition": 0.0}, - 172: {"mass": 171.99881, "composition": 0.0}, - 173: {"mass": 172.99709, "composition": 0.0}, - 174: {"mass": 173.992865, "composition": 0.0}, - 175: {"mass": 174.991441, "composition": 0.0}, - 176: {"mass": 175.987361, "composition": 0.0}, - 177: {"mass": 176.986277, "composition": 0.0}, - 178: {"mass": 177.982484, "composition": 0.0}, - 179: {"mass": 178.981831, "composition": 0.0}, - 180: {"mass": 179.97826, "composition": 0.0}, - 181: {"mass": 180.977819, "composition": 0.0}, - 182: {"mass": 181.974689, "composition": 0.0}, - 183: {"mass": 182.9744448, "composition": 0.0}, - 184: {"mass": 183.971714, "composition": 0.0}, - 185: {"mass": 184.971899, "composition": 0.0}, - 186: {"mass": 185.969362, "composition": 0.0}, - 187: {"mass": 186.969814, "composition": 0.0}, - 188: {"mass": 187.967567, "composition": 0.0}, - 189: {"mass": 188.968195, "composition": 0.0}, - 190: {"mass": 189.966323, "composition": 0.0}, - 191: {"mass": 190.967157, "composition": 0.0}, - 192: {"mass": 191.965635, "composition": 0.0}, - 193: {"mass": 192.966653, "composition": 0.0}, - 194: {"mass": 193.9654491, "composition": 0.0}, - 195: {"mass": 194.966721, "composition": 0.0}, - 196: {"mass": 195.9658326, "composition": 0.0015}, - 197: {"mass": 196.9672128, "composition": 0.0}, - 198: {"mass": 197.9667686, "composition": 0.0997}, - 199: {"mass": 198.96828064, "composition": 0.1687}, - 200: {"mass": 199.96832659, "composition": 0.231}, - 201: {"mass": 200.97030284, "composition": 0.1318}, - 202: {"mass": 201.9706434, "composition": 0.2986}, - 203: {"mass": 202.9728728, "composition": 0.0}, - 204: {"mass": 203.97349398, "composition": 0.0687}, - 205: {"mass": 204.9760734, "composition": 0.0}, - 206: {"mass": 205.977514, "composition": 0.0}, - 207: {"mass": 206.9823, "composition": 0.0}, - 208: {"mass": 207.985759, "composition": 0.0}, - 209: {"mass": 208.99072, "composition": 0.0}, - 210: {"mass": 209.99424, "composition": 0.0}, - 211: {"mass": 210.99933, "composition": 0.0}, - 212: {"mass": 212.00296, "composition": 0.0}, - 213: {"mass": 213.00823, "composition": 0.0}, - 214: {"mass": 214.012, "composition": 0.0}, - 215: {"mass": 215.0174, "composition": 0.0}, - 216: {"mass": 216.02132, "composition": 0.0}}, - 81: {176: {"mass": 176.000624, "composition": 0.0}, - 177: {"mass": 176.996431, "composition": 0.0}, - 178: {"mass": 177.99485, "composition": 0.0}, - 179: {"mass": 178.991111, "composition": 0.0}, - 180: {"mass": 179.990057, "composition": 0.0}, - 181: {"mass": 180.98626, "composition": 0.0}, - 182: {"mass": 181.985713, "composition": 0.0}, - 183: {"mass": 182.982193, "composition": 0.0}, - 184: {"mass": 183.981886, "composition": 0.0}, - 185: {"mass": 184.978789, "composition": 0.0}, - 186: {"mass": 185.978651, "composition": 0.0}, - 187: {"mass": 186.9759063, "composition": 0.0}, - 188: {"mass": 187.976021, "composition": 0.0}, - 189: {"mass": 188.973588, "composition": 0.0}, - 190: {"mass": 189.973828, "composition": 0.0}, - 191: {"mass": 190.9717842, "composition": 0.0}, - 192: {"mass": 191.972225, "composition": 0.0}, - 193: {"mass": 192.970502, "composition": 0.0}, - 194: {"mass": 193.971081, "composition": 0.0}, - 195: {"mass": 194.969774, "composition": 0.0}, - 196: {"mass": 195.970481, "composition": 0.0}, - 197: {"mass": 196.969576, "composition": 0.0}, - 198: {"mass": 197.970483, "composition": 0.0}, - 199: {"mass": 198.969877, "composition": 0.0}, - 200: {"mass": 199.9709633, "composition": 0.0}, - 201: {"mass": 200.970822, "composition": 0.0}, - 202: {"mass": 201.972102, "composition": 0.0}, - 203: {"mass": 202.9723446, "composition": 0.2952}, - 204: {"mass": 203.9738639, "composition": 0.0}, - 205: {"mass": 204.9744278, "composition": 0.7048}, - 206: {"mass": 205.9761106, "composition": 0.0}, - 207: {"mass": 206.9774197, "composition": 0.0}, - 208: {"mass": 207.982019, "composition": 0.0}, - 209: {"mass": 208.9853594, "composition": 0.0}, - 210: {"mass": 209.990074, "composition": 0.0}, - 211: {"mass": 210.993475, "composition": 0.0}, - 212: {"mass": 211.99834, "composition": 0.0}, - 213: {"mass": 213.001915, "composition": 0.0}, - 214: {"mass": 214.00694, "composition": 0.0}, - 215: {"mass": 215.01064, "composition": 0.0}, - 216: {"mass": 216.0158, "composition": 0.0}, - 217: {"mass": 217.01966, "composition": 0.0}, - 218: {"mass": 218.02479, "composition": 0.0}}, - 82: {178: {"mass": 178.003831, "composition": 0.0}, - 179: {"mass": 179.002201, "composition": 0.0}, - 180: {"mass": 179.997928, "composition": 0.0}, - 181: {"mass": 180.996653, "composition": 0.0}, - 182: {"mass": 181.992672, "composition": 0.0}, - 183: {"mass": 182.991872, "composition": 0.0}, - 184: {"mass": 183.988136, "composition": 0.0}, - 185: {"mass": 184.98761, "composition": 0.0}, - 186: {"mass": 185.984238, "composition": 0.0}, - 187: {"mass": 186.9839109, "composition": 0.0}, - 188: {"mass": 187.980875, "composition": 0.0}, - 189: {"mass": 188.980807, "composition": 0.0}, - 190: {"mass": 189.978082, "composition": 0.0}, - 191: {"mass": 190.978276, "composition": 0.0}, - 192: {"mass": 191.975775, "composition": 0.0}, - 193: {"mass": 192.976173, "composition": 0.0}, - 194: {"mass": 193.974012, "composition": 0.0}, - 195: {"mass": 194.974543, "composition": 0.0}, - 196: {"mass": 195.972774, "composition": 0.0}, - 197: {"mass": 196.9734312, "composition": 0.0}, - 198: {"mass": 197.972034, "composition": 0.0}, - 199: {"mass": 198.972913, "composition": 0.0}, - 200: {"mass": 199.971819, "composition": 0.0}, - 201: {"mass": 200.972883, "composition": 0.0}, - 202: {"mass": 201.972152, "composition": 0.0}, - 203: {"mass": 202.9733911, "composition": 0.0}, - 204: {"mass": 203.973044, "composition": 0.014}, - 205: {"mass": 204.9744822, "composition": 0.0}, - 206: {"mass": 205.9744657, "composition": 0.241}, - 207: {"mass": 206.9758973, "composition": 0.221}, - 208: {"mass": 207.9766525, "composition": 0.524}, - 209: {"mass": 208.9810905, "composition": 0.0}, - 210: {"mass": 209.9841889, "composition": 0.0}, - 211: {"mass": 210.9887371, "composition": 0.0}, - 212: {"mass": 211.9918977, "composition": 0.0}, - 213: {"mass": 212.9965629, "composition": 0.0}, - 214: {"mass": 213.9998059, "composition": 0.0}, - 215: {"mass": 215.00474, "composition": 0.0}, - 216: {"mass": 216.00803, "composition": 0.0}, - 217: {"mass": 217.01314, "composition": 0.0}, - 218: {"mass": 218.01659, "composition": 0.0}, - 219: {"mass": 219.02177, "composition": 0.0}, - 220: {"mass": 220.02541, "composition": 0.0}}, - 83: {184: {"mass": 184.001275, "composition": 0.0}, - 185: {"mass": 184.9976, "composition": 0.0}, - 186: {"mass": 185.996644, "composition": 0.0}, - 187: {"mass": 186.993147, "composition": 0.0}, - 188: {"mass": 187.992287, "composition": 0.0}, - 189: {"mass": 188.989195, "composition": 0.0}, - 190: {"mass": 189.988622, "composition": 0.0}, - 191: {"mass": 190.9857866, "composition": 0.0}, - 192: {"mass": 191.985469, "composition": 0.0}, - 193: {"mass": 192.98296, "composition": 0.0}, - 194: {"mass": 193.982785, "composition": 0.0}, - 195: {"mass": 194.9806488, "composition": 0.0}, - 196: {"mass": 195.980667, "composition": 0.0}, - 197: {"mass": 196.9788651, "composition": 0.0}, - 198: {"mass": 197.979206, "composition": 0.0}, - 199: {"mass": 198.977673, "composition": 0.0}, - 200: {"mass": 199.978131, "composition": 0.0}, - 201: {"mass": 200.97701, "composition": 0.0}, - 202: {"mass": 201.977734, "composition": 0.0}, - 203: {"mass": 202.976893, "composition": 0.0}, - 204: {"mass": 203.9778361, "composition": 0.0}, - 205: {"mass": 204.9773867, "composition": 0.0}, - 206: {"mass": 205.9784993, "composition": 0.0}, - 207: {"mass": 206.978471, "composition": 0.0}, - 208: {"mass": 207.9797425, "composition": 0.0}, - 209: {"mass": 208.9803991, "composition": 1.0}, - 210: {"mass": 209.9841207, "composition": 0.0}, - 211: {"mass": 210.9872697, "composition": 0.0}, - 212: {"mass": 211.991286, "composition": 0.0}, - 213: {"mass": 212.9943851, "composition": 0.0}, - 214: {"mass": 213.998712, "composition": 0.0}, - 215: {"mass": 215.00177, "composition": 0.0}, - 216: {"mass": 216.006306, "composition": 0.0}, - 217: {"mass": 217.009372, "composition": 0.0}, - 218: {"mass": 218.014188, "composition": 0.0}, - 219: {"mass": 219.01748, "composition": 0.0}, - 220: {"mass": 220.02235, "composition": 0.0}, - 221: {"mass": 221.02587, "composition": 0.0}, - 222: {"mass": 222.03078, "composition": 0.0}, - 223: {"mass": 223.0345, "composition": 0.0}, - 224: {"mass": 224.03947, "composition": 0.0}}, - 84: {186: {"mass": 186.004393, "composition": 0.0}, - 187: {"mass": 187.003041, "composition": 0.0}, - 188: {"mass": 187.999416, "composition": 0.0}, - 189: {"mass": 188.998473, "composition": 0.0}, - 190: {"mass": 189.995101, "composition": 0.0}, - 191: {"mass": 190.9945585, "composition": 0.0}, - 192: {"mass": 191.991336, "composition": 0.0}, - 193: {"mass": 192.991026, "composition": 0.0}, - 194: {"mass": 193.988186, "composition": 0.0}, - 195: {"mass": 194.988126, "composition": 0.0}, - 196: {"mass": 195.985526, "composition": 0.0}, - 197: {"mass": 196.98566, "composition": 0.0}, - 198: {"mass": 197.983389, "composition": 0.0}, - 199: {"mass": 198.983667, "composition": 0.0}, - 200: {"mass": 199.981799, "composition": 0.0}, - 201: {"mass": 200.9822598, "composition": 0.0}, - 202: {"mass": 201.980758, "composition": 0.0}, - 203: {"mass": 202.9814161, "composition": 0.0}, - 204: {"mass": 203.98031, "composition": 0.0}, - 205: {"mass": 204.981203, "composition": 0.0}, - 206: {"mass": 205.980474, "composition": 0.0}, - 207: {"mass": 206.9815938, "composition": 0.0}, - 208: {"mass": 207.9812461, "composition": 0.0}, - 209: {"mass": 208.9824308, "composition": 0.0}, - 210: {"mass": 209.9828741, "composition": 0.0}, - 211: {"mass": 210.9866536, "composition": 0.0}, - 212: {"mass": 211.9888684, "composition": 0.0}, - 213: {"mass": 212.9928576, "composition": 0.0}, - 214: {"mass": 213.9952017, "composition": 0.0}, - 215: {"mass": 214.9994201, "composition": 0.0}, - 216: {"mass": 216.0019152, "composition": 0.0}, - 217: {"mass": 217.0063182, "composition": 0.0}, - 218: {"mass": 218.0089735, "composition": 0.0}, - 219: {"mass": 219.013614, "composition": 0.0}, - 220: {"mass": 220.016386, "composition": 0.0}, - 221: {"mass": 221.021228, "composition": 0.0}, - 222: {"mass": 222.02414, "composition": 0.0}, - 223: {"mass": 223.02907, "composition": 0.0}, - 224: {"mass": 224.03211, "composition": 0.0}, - 225: {"mass": 225.03707, "composition": 0.0}, - 226: {"mass": 226.04031, "composition": 0.0}, - 227: {"mass": 227.04539, "composition": 0.0}}, - 85: {191: {"mass": 191.004148, "composition": 0.0}, - 192: {"mass": 192.003152, "composition": 0.0}, - 193: {"mass": 192.999927, "composition": 0.0}, - 194: {"mass": 193.999236, "composition": 0.0}, - 195: {"mass": 194.9962685, "composition": 0.0}, - 196: {"mass": 195.9958, "composition": 0.0}, - 197: {"mass": 196.993189, "composition": 0.0}, - 198: {"mass": 197.992784, "composition": 0.0}, - 199: {"mass": 198.9905277, "composition": 0.0}, - 200: {"mass": 199.990351, "composition": 0.0}, - 201: {"mass": 200.9884171, "composition": 0.0}, - 202: {"mass": 201.98863, "composition": 0.0}, - 203: {"mass": 202.986943, "composition": 0.0}, - 204: {"mass": 203.987251, "composition": 0.0}, - 205: {"mass": 204.986076, "composition": 0.0}, - 206: {"mass": 205.986657, "composition": 0.0}, - 207: {"mass": 206.9858, "composition": 0.0}, - 208: {"mass": 207.9866133, "composition": 0.0}, - 209: {"mass": 208.9861702, "composition": 0.0}, - 210: {"mass": 209.9871479, "composition": 0.0}, - 211: {"mass": 210.9874966, "composition": 0.0}, - 212: {"mass": 211.9907377, "composition": 0.0}, - 213: {"mass": 212.992937, "composition": 0.0}, - 214: {"mass": 213.9963721, "composition": 0.0}, - 215: {"mass": 214.9986528, "composition": 0.0}, - 216: {"mass": 216.0024236, "composition": 0.0}, - 217: {"mass": 217.0047192, "composition": 0.0}, - 218: {"mass": 218.008695, "composition": 0.0}, - 219: {"mass": 219.0111618, "composition": 0.0}, - 220: {"mass": 220.015433, "composition": 0.0}, - 221: {"mass": 221.018017, "composition": 0.0}, - 222: {"mass": 222.022494, "composition": 0.0}, - 223: {"mass": 223.025151, "composition": 0.0}, - 224: {"mass": 224.029749, "composition": 0.0}, - 225: {"mass": 225.03263, "composition": 0.0}, - 226: {"mass": 226.03716, "composition": 0.0}, - 227: {"mass": 227.04024, "composition": 0.0}, - 228: {"mass": 228.04475, "composition": 0.0}, - 229: {"mass": 229.04812, "composition": 0.0}}, - 86: {193: {"mass": 193.009708, "composition": 0.0}, - 194: {"mass": 194.006144, "composition": 0.0}, - 195: {"mass": 195.005422, "composition": 0.0}, - 196: {"mass": 196.002116, "composition": 0.0}, - 197: {"mass": 197.001585, "composition": 0.0}, - 198: {"mass": 197.998679, "composition": 0.0}, - 199: {"mass": 198.99839, "composition": 0.0}, - 200: {"mass": 199.99569, "composition": 0.0}, - 201: {"mass": 200.995628, "composition": 0.0}, - 202: {"mass": 201.993264, "composition": 0.0}, - 203: {"mass": 202.993388, "composition": 0.0}, - 204: {"mass": 203.99143, "composition": 0.0}, - 205: {"mass": 204.991719, "composition": 0.0}, - 206: {"mass": 205.990214, "composition": 0.0}, - 207: {"mass": 206.9907303, "composition": 0.0}, - 208: {"mass": 207.989635, "composition": 0.0}, - 209: {"mass": 208.990415, "composition": 0.0}, - 210: {"mass": 209.9896891, "composition": 0.0}, - 211: {"mass": 210.9906011, "composition": 0.0}, - 212: {"mass": 211.9907039, "composition": 0.0}, - 213: {"mass": 212.9938831, "composition": 0.0}, - 214: {"mass": 213.995363, "composition": 0.0}, - 215: {"mass": 214.9987459, "composition": 0.0}, - 216: {"mass": 216.0002719, "composition": 0.0}, - 217: {"mass": 217.003928, "composition": 0.0}, - 218: {"mass": 218.0056016, "composition": 0.0}, - 219: {"mass": 219.0094804, "composition": 0.0}, - 220: {"mass": 220.0113941, "composition": 0.0}, - 221: {"mass": 221.0155371, "composition": 0.0}, - 222: {"mass": 222.0175782, "composition": 0.0}, - 223: {"mass": 223.0218893, "composition": 0.0}, - 224: {"mass": 224.024096, "composition": 0.0}, - 225: {"mass": 225.028486, "composition": 0.0}, - 226: {"mass": 226.030861, "composition": 0.0}, - 227: {"mass": 227.035304, "composition": 0.0}, - 228: {"mass": 228.037835, "composition": 0.0}, - 229: {"mass": 229.042257, "composition": 0.0}, - 230: {"mass": 230.04514, "composition": 0.0}, - 231: {"mass": 231.04987, "composition": 0.0}}, - 87: {199: {"mass": 199.007259, "composition": 0.0}, - 200: {"mass": 200.006586, "composition": 0.0}, - 201: {"mass": 201.003867, "composition": 0.0}, - 202: {"mass": 202.00332, "composition": 0.0}, - 203: {"mass": 203.0009407, "composition": 0.0}, - 204: {"mass": 204.000652, "composition": 0.0}, - 205: {"mass": 204.9985939, "composition": 0.0}, - 206: {"mass": 205.998666, "composition": 0.0}, - 207: {"mass": 206.996946, "composition": 0.0}, - 208: {"mass": 207.997138, "composition": 0.0}, - 209: {"mass": 208.995955, "composition": 0.0}, - 210: {"mass": 209.996422, "composition": 0.0}, - 211: {"mass": 210.995556, "composition": 0.0}, - 212: {"mass": 211.9962257, "composition": 0.0}, - 213: {"mass": 212.996186, "composition": 0.0}, - 214: {"mass": 213.9989713, "composition": 0.0}, - 215: {"mass": 215.0003418, "composition": 0.0}, - 216: {"mass": 216.0031899, "composition": 0.0}, - 217: {"mass": 217.0046323, "composition": 0.0}, - 218: {"mass": 218.0075787, "composition": 0.0}, - 219: {"mass": 219.0092524, "composition": 0.0}, - 220: {"mass": 220.0123277, "composition": 0.0}, - 221: {"mass": 221.0142552, "composition": 0.0}, - 222: {"mass": 222.017552, "composition": 0.0}, - 223: {"mass": 223.019736, "composition": 0.0}, - 224: {"mass": 224.023398, "composition": 0.0}, - 225: {"mass": 225.025573, "composition": 0.0}, - 226: {"mass": 226.029566, "composition": 0.0}, - 227: {"mass": 227.031869, "composition": 0.0}, - 228: {"mass": 228.035823, "composition": 0.0}, - 229: {"mass": 229.038298, "composition": 0.0}, - 230: {"mass": 230.042416, "composition": 0.0}, - 231: {"mass": 231.045158, "composition": 0.0}, - 232: {"mass": 232.04937, "composition": 0.0}, - 233: {"mass": 233.05264, "composition": 0.0}}, - 88: {201: {"mass": 201.01271, "composition": 0.0}, - 202: {"mass": 202.00976, "composition": 0.0}, - 203: {"mass": 203.009304, "composition": 0.0}, - 204: {"mass": 204.006492, "composition": 0.0}, - 205: {"mass": 205.006268, "composition": 0.0}, - 206: {"mass": 206.003828, "composition": 0.0}, - 207: {"mass": 207.003799, "composition": 0.0}, - 208: {"mass": 208.001841, "composition": 0.0}, - 209: {"mass": 209.00199, "composition": 0.0}, - 210: {"mass": 210.000494, "composition": 0.0}, - 211: {"mass": 211.0008932, "composition": 0.0}, - 212: {"mass": 211.999787, "composition": 0.0}, - 213: {"mass": 213.000384, "composition": 0.0}, - 214: {"mass": 214.0000997, "composition": 0.0}, - 215: {"mass": 215.0027204, "composition": 0.0}, - 216: {"mass": 216.0035334, "composition": 0.0}, - 217: {"mass": 217.0063207, "composition": 0.0}, - 218: {"mass": 218.007141, "composition": 0.0}, - 219: {"mass": 219.0100855, "composition": 0.0}, - 220: {"mass": 220.0110259, "composition": 0.0}, - 221: {"mass": 221.0139177, "composition": 0.0}, - 222: {"mass": 222.0153748, "composition": 0.0}, - 223: {"mass": 223.0185023, "composition": 0.0}, - 224: {"mass": 224.020212, "composition": 0.0}, - 225: {"mass": 225.0236119, "composition": 0.0}, - 226: {"mass": 226.0254103, "composition": 0.0}, - 227: {"mass": 227.0291783, "composition": 0.0}, - 228: {"mass": 228.0310707, "composition": 0.0}, - 229: {"mass": 229.034942, "composition": 0.0}, - 230: {"mass": 230.037055, "composition": 0.0}, - 231: {"mass": 231.041027, "composition": 0.0}, - 232: {"mass": 232.0434753, "composition": 0.0}, - 233: {"mass": 233.047582, "composition": 0.0}, - 234: {"mass": 234.050342, "composition": 0.0}, - 235: {"mass": 235.05497, "composition": 0.0}}, - 89: {206: {"mass": 206.014452, "composition": 0.0}, - 207: {"mass": 207.011966, "composition": 0.0}, - 208: {"mass": 208.01155, "composition": 0.0}, - 209: {"mass": 209.009495, "composition": 0.0}, - 210: {"mass": 210.009436, "composition": 0.0}, - 211: {"mass": 211.007732, "composition": 0.0}, - 212: {"mass": 212.007813, "composition": 0.0}, - 213: {"mass": 213.006609, "composition": 0.0}, - 214: {"mass": 214.006918, "composition": 0.0}, - 215: {"mass": 215.006475, "composition": 0.0}, - 216: {"mass": 216.008743, "composition": 0.0}, - 217: {"mass": 217.009344, "composition": 0.0}, - 218: {"mass": 218.011642, "composition": 0.0}, - 219: {"mass": 219.012421, "composition": 0.0}, - 220: {"mass": 220.0147549, "composition": 0.0}, - 221: {"mass": 221.015592, "composition": 0.0}, - 222: {"mass": 222.0178442, "composition": 0.0}, - 223: {"mass": 223.0191377, "composition": 0.0}, - 224: {"mass": 224.0217232, "composition": 0.0}, - 225: {"mass": 225.02323, "composition": 0.0}, - 226: {"mass": 226.0260984, "composition": 0.0}, - 227: {"mass": 227.0277523, "composition": 0.0}, - 228: {"mass": 228.0310215, "composition": 0.0}, - 229: {"mass": 229.032956, "composition": 0.0}, - 230: {"mass": 230.036327, "composition": 0.0}, - 231: {"mass": 231.038393, "composition": 0.0}, - 232: {"mass": 232.042034, "composition": 0.0}, - 233: {"mass": 233.044346, "composition": 0.0}, - 234: {"mass": 234.048139, "composition": 0.0}, - 235: {"mass": 235.05084, "composition": 0.0}, - 236: {"mass": 236.054988, "composition": 0.0}, - 237: {"mass": 237.05827, "composition": 0.0}}, - 90: {208: {"mass": 208.0179, "composition": 0.0}, - 209: {"mass": 209.017753, "composition": 0.0}, - 210: {"mass": 210.015094, "composition": 0.0}, - 211: {"mass": 211.014929, "composition": 0.0}, - 212: {"mass": 212.012988, "composition": 0.0}, - 213: {"mass": 213.013009, "composition": 0.0}, - 214: {"mass": 214.0115, "composition": 0.0}, - 215: {"mass": 215.0117248, "composition": 0.0}, - 216: {"mass": 216.011056, "composition": 0.0}, - 217: {"mass": 217.013117, "composition": 0.0}, - 218: {"mass": 218.013276, "composition": 0.0}, - 219: {"mass": 219.015537, "composition": 0.0}, - 220: {"mass": 220.015748, "composition": 0.0}, - 221: {"mass": 221.018184, "composition": 0.0}, - 222: {"mass": 222.018469, "composition": 0.0}, - 223: {"mass": 223.0208119, "composition": 0.0}, - 224: {"mass": 224.021464, "composition": 0.0}, - 225: {"mass": 225.0239514, "composition": 0.0}, - 226: {"mass": 226.0249034, "composition": 0.0}, - 227: {"mass": 227.0277042, "composition": 0.0}, - 228: {"mass": 228.0287413, "composition": 0.0}, - 229: {"mass": 229.0317627, "composition": 0.0}, - 230: {"mass": 230.0331341, "composition": 0.0}, - 231: {"mass": 231.0363046, "composition": 0.0}, - 232: {"mass": 232.0380558, "composition": 1.0}, - 233: {"mass": 233.0415823, "composition": 0.0}, - 234: {"mass": 234.0436014, "composition": 0.0}, - 235: {"mass": 235.047255, "composition": 0.0}, - 236: {"mass": 236.049657, "composition": 0.0}, - 237: {"mass": 237.053629, "composition": 0.0}, - 238: {"mass": 238.0565, "composition": 0.0}, - 239: {"mass": 239.06077, "composition": 0.0}}, - 91: {212: {"mass": 212.023203, "composition": 0.0}, - 213: {"mass": 213.021109, "composition": 0.0}, - 214: {"mass": 214.020918, "composition": 0.0}, - 215: {"mass": 215.019183, "composition": 0.0}, - 216: {"mass": 216.019109, "composition": 0.0}, - 217: {"mass": 217.018325, "composition": 0.0}, - 218: {"mass": 218.020059, "composition": 0.0}, - 219: {"mass": 219.019904, "composition": 0.0}, - 220: {"mass": 220.021705, "composition": 0.0}, - 221: {"mass": 221.021875, "composition": 0.0}, - 222: {"mass": 222.023784, "composition": 0.0}, - 223: {"mass": 223.023963, "composition": 0.0}, - 224: {"mass": 224.0256176, "composition": 0.0}, - 225: {"mass": 225.026131, "composition": 0.0}, - 226: {"mass": 226.027948, "composition": 0.0}, - 227: {"mass": 227.0288054, "composition": 0.0}, - 228: {"mass": 228.0310517, "composition": 0.0}, - 229: {"mass": 229.0320972, "composition": 0.0}, - 230: {"mass": 230.034541, "composition": 0.0}, - 231: {"mass": 231.0358842, "composition": 1.0}, - 232: {"mass": 232.0385917, "composition": 0.0}, - 233: {"mass": 233.0402472, "composition": 0.0}, - 234: {"mass": 234.0433072, "composition": 0.0}, - 235: {"mass": 235.045399, "composition": 0.0}, - 236: {"mass": 236.048668, "composition": 0.0}, - 237: {"mass": 237.051023, "composition": 0.0}, - 238: {"mass": 238.054637, "composition": 0.0}, - 239: {"mass": 239.05726, "composition": 0.0}, - 240: {"mass": 240.06098, "composition": 0.0}, - 241: {"mass": 241.06408, "composition": 0.0}}, - 92: {217: {"mass": 217.02466, "composition": 0.0}, - 218: {"mass": 218.023523, "composition": 0.0}, - 219: {"mass": 219.024999, "composition": 0.0}, - 220: {"mass": 220.02462, "composition": 0.0}, - 221: {"mass": 221.02628, "composition": 0.0}, - 222: {"mass": 222.026, "composition": 0.0}, - 223: {"mass": 223.027739, "composition": 0.0}, - 224: {"mass": 224.027605, "composition": 0.0}, - 225: {"mass": 225.029391, "composition": 0.0}, - 226: {"mass": 226.029339, "composition": 0.0}, - 227: {"mass": 227.031157, "composition": 0.0}, - 228: {"mass": 228.031371, "composition": 0.0}, - 229: {"mass": 229.0335063, "composition": 0.0}, - 230: {"mass": 230.0339401, "composition": 0.0}, - 231: {"mass": 231.0362939, "composition": 0.0}, - 232: {"mass": 232.0371563, "composition": 0.0}, - 233: {"mass": 233.0396355, "composition": 0.0}, - 234: {"mass": 234.0409523, "composition": 5.4e-05}, - 235: {"mass": 235.0439301, "composition": 0.007204}, - 236: {"mass": 236.0455682, "composition": 0.0}, - 237: {"mass": 237.0487304, "composition": 0.0}, - 238: {"mass": 238.0507884, "composition": 0.992742}, - 239: {"mass": 239.0542935, "composition": 0.0}, - 240: {"mass": 240.0565934, "composition": 0.0}, - 241: {"mass": 241.06033, "composition": 0.0}, - 242: {"mass": 242.06293, "composition": 0.0}, - 243: {"mass": 243.06699, "composition": 0.0}}, - 93: {219: {"mass": 219.03143, "composition": 0.0}, - 220: {"mass": 220.03254, "composition": 0.0}, - 221: {"mass": 221.03204, "composition": 0.0}, - 222: {"mass": 222.0333, "composition": 0.0}, - 223: {"mass": 223.03285, "composition": 0.0}, - 224: {"mass": 224.03422, "composition": 0.0}, - 225: {"mass": 225.033911, "composition": 0.0}, - 226: {"mass": 226.035188, "composition": 0.0}, - 227: {"mass": 227.034957, "composition": 0.0}, - 228: {"mass": 228.036067, "composition": 0.0}, - 229: {"mass": 229.036264, "composition": 0.0}, - 230: {"mass": 230.037828, "composition": 0.0}, - 231: {"mass": 231.038245, "composition": 0.0}, - 232: {"mass": 232.04011, "composition": 0.0}, - 233: {"mass": 233.040741, "composition": 0.0}, - 234: {"mass": 234.0428953, "composition": 0.0}, - 235: {"mass": 235.0440635, "composition": 0.0}, - 236: {"mass": 236.04657, "composition": 0.0}, - 237: {"mass": 237.0481736, "composition": 0.0}, - 238: {"mass": 238.0509466, "composition": 0.0}, - 239: {"mass": 239.0529392, "composition": 0.0}, - 240: {"mass": 240.056165, "composition": 0.0}, - 241: {"mass": 241.058253, "composition": 0.0}, - 242: {"mass": 242.06164, "composition": 0.0}, - 243: {"mass": 243.06428, "composition": 0.0}, - 244: {"mass": 244.06785, "composition": 0.0}, - 245: {"mass": 245.0708, "composition": 0.0}}, - 94: {228: {"mass": 228.038732, "composition": 0.0}, - 229: {"mass": 229.040144, "composition": 0.0}, - 230: {"mass": 230.03965, "composition": 0.0}, - 231: {"mass": 231.041102, "composition": 0.0}, - 232: {"mass": 232.041185, "composition": 0.0}, - 233: {"mass": 233.042998, "composition": 0.0}, - 234: {"mass": 234.0433174, "composition": 0.0}, - 235: {"mass": 235.045286, "composition": 0.0}, - 236: {"mass": 236.0460581, "composition": 0.0}, - 237: {"mass": 237.0484098, "composition": 0.0}, - 238: {"mass": 238.0495601, "composition": 0.0}, - 239: {"mass": 239.0521636, "composition": 0.0}, - 240: {"mass": 240.0538138, "composition": 0.0}, - 241: {"mass": 241.0568517, "composition": 0.0}, - 242: {"mass": 242.0587428, "composition": 0.0}, - 243: {"mass": 243.0620036, "composition": 0.0}, - 244: {"mass": 244.0642053, "composition": 0.0}, - 245: {"mass": 245.067826, "composition": 0.0}, - 246: {"mass": 246.070205, "composition": 0.0}, - 247: {"mass": 247.07419, "composition": 0.0}}, - 95: {230: {"mass": 230.04609, "composition": 0.0}, - 231: {"mass": 231.04556, "composition": 0.0}, - 232: {"mass": 232.04645, "composition": 0.0}, - 233: {"mass": 233.04644, "composition": 0.0}, - 234: {"mass": 234.04773, "composition": 0.0}, - 235: {"mass": 235.047908, "composition": 0.0}, - 236: {"mass": 236.04943, "composition": 0.0}, - 237: {"mass": 237.049996, "composition": 0.0}, - 238: {"mass": 238.051985, "composition": 0.0}, - 239: {"mass": 239.0530247, "composition": 0.0}, - 240: {"mass": 240.0553, "composition": 0.0}, - 241: {"mass": 241.0568293, "composition": 0.0}, - 242: {"mass": 242.0595494, "composition": 0.0}, - 243: {"mass": 243.0613813, "composition": 0.0}, - 244: {"mass": 244.0642851, "composition": 0.0}, - 245: {"mass": 245.0664548, "composition": 0.0}, - 246: {"mass": 246.069775, "composition": 0.0}, - 247: {"mass": 247.07209, "composition": 0.0}, - 248: {"mass": 248.07575, "composition": 0.0}, - 249: {"mass": 249.07848, "composition": 0.0}}, - 96: {232: {"mass": 232.04982, "composition": 0.0}, - 233: {"mass": 233.05077, "composition": 0.0}, - 234: {"mass": 234.05016, "composition": 0.0}, - 235: {"mass": 235.05154, "composition": 0.0}, - 236: {"mass": 236.051374, "composition": 0.0}, - 237: {"mass": 237.052869, "composition": 0.0}, - 238: {"mass": 238.053081, "composition": 0.0}, - 239: {"mass": 239.05491, "composition": 0.0}, - 240: {"mass": 240.0555297, "composition": 0.0}, - 241: {"mass": 241.0576532, "composition": 0.0}, - 242: {"mass": 242.058836, "composition": 0.0}, - 243: {"mass": 243.0613893, "composition": 0.0}, - 244: {"mass": 244.0627528, "composition": 0.0}, - 245: {"mass": 245.0654915, "composition": 0.0}, - 246: {"mass": 246.0672238, "composition": 0.0}, - 247: {"mass": 247.0703541, "composition": 0.0}, - 248: {"mass": 248.0723499, "composition": 0.0}, - 249: {"mass": 249.0759548, "composition": 0.0}, - 250: {"mass": 250.078358, "composition": 0.0}, - 251: {"mass": 251.082286, "composition": 0.0}, - 252: {"mass": 252.08487, "composition": 0.0}}, - 97: {234: {"mass": 234.05727, "composition": 0.0}, - 235: {"mass": 235.05658, "composition": 0.0}, - 236: {"mass": 236.05748, "composition": 0.0}, - 237: {"mass": 237.0571, "composition": 0.0}, - 238: {"mass": 238.0582, "composition": 0.0}, - 239: {"mass": 239.05824, "composition": 0.0}, - 240: {"mass": 240.05976, "composition": 0.0}, - 241: {"mass": 241.06016, "composition": 0.0}, - 242: {"mass": 242.06198, "composition": 0.0}, - 243: {"mass": 243.0630078, "composition": 0.0}, - 244: {"mass": 244.065181, "composition": 0.0}, - 245: {"mass": 245.0663618, "composition": 0.0}, - 246: {"mass": 246.068673, "composition": 0.0}, - 247: {"mass": 247.0703073, "composition": 0.0}, - 248: {"mass": 248.073088, "composition": 0.0}, - 249: {"mass": 249.0749877, "composition": 0.0}, - 250: {"mass": 250.0783167, "composition": 0.0}, - 251: {"mass": 251.080762, "composition": 0.0}, - 252: {"mass": 252.08431, "composition": 0.0}, - 253: {"mass": 253.08688, "composition": 0.0}, - 254: {"mass": 254.0906, "composition": 0.0}}, - 98: {237: {"mass": 237.062198, "composition": 0.0}, - 238: {"mass": 238.06149, "composition": 0.0}, - 239: {"mass": 239.06253, "composition": 0.0}, - 240: {"mass": 240.062256, "composition": 0.0}, - 241: {"mass": 241.06369, "composition": 0.0}, - 242: {"mass": 242.063754, "composition": 0.0}, - 243: {"mass": 243.06548, "composition": 0.0}, - 244: {"mass": 244.0660008, "composition": 0.0}, - 245: {"mass": 245.0680487, "composition": 0.0}, - 246: {"mass": 246.0688055, "composition": 0.0}, - 247: {"mass": 247.070965, "composition": 0.0}, - 248: {"mass": 248.0721851, "composition": 0.0}, - 249: {"mass": 249.0748539, "composition": 0.0}, - 250: {"mass": 250.0764062, "composition": 0.0}, - 251: {"mass": 251.0795886, "composition": 0.0}, - 252: {"mass": 252.0816272, "composition": 0.0}, - 253: {"mass": 253.0851345, "composition": 0.0}, - 254: {"mass": 254.087324, "composition": 0.0}, - 255: {"mass": 255.09105, "composition": 0.0}, - 256: {"mass": 256.09344, "composition": 0.0}}, - 99: {239: {"mass": 239.06823, "composition": 0.0}, - 240: {"mass": 240.06892, "composition": 0.0}, - 241: {"mass": 241.06856, "composition": 0.0}, - 242: {"mass": 242.06957, "composition": 0.0}, - 243: {"mass": 243.06951, "composition": 0.0}, - 244: {"mass": 244.07088, "composition": 0.0}, - 245: {"mass": 245.07125, "composition": 0.0}, - 246: {"mass": 246.0729, "composition": 0.0}, - 247: {"mass": 247.073622, "composition": 0.0}, - 248: {"mass": 248.075471, "composition": 0.0}, - 249: {"mass": 249.076411, "composition": 0.0}, - 250: {"mass": 250.07861, "composition": 0.0}, - 251: {"mass": 251.0799936, "composition": 0.0}, - 252: {"mass": 252.08298, "composition": 0.0}, - 253: {"mass": 253.0848257, "composition": 0.0}, - 254: {"mass": 254.0880222, "composition": 0.0}, - 255: {"mass": 255.090275, "composition": 0.0}, - 256: {"mass": 256.0936, "composition": 0.0}, - 257: {"mass": 257.09598, "composition": 0.0}, - 258: {"mass": 258.09952, "composition": 0.0}}, - 100: {241: {"mass": 241.07421, "composition": 0.0}, - 242: {"mass": 242.07343, "composition": 0.0}, - 243: {"mass": 243.07446, "composition": 0.0}, - 244: {"mass": 244.07404, "composition": 0.0}, - 245: {"mass": 245.07535, "composition": 0.0}, - 246: {"mass": 246.07535, "composition": 0.0}, - 247: {"mass": 247.07694, "composition": 0.0}, - 248: {"mass": 248.0771865, "composition": 0.0}, - 249: {"mass": 249.0789275, "composition": 0.0}, - 250: {"mass": 250.079521, "composition": 0.0}, - 251: {"mass": 251.08154, "composition": 0.0}, - 252: {"mass": 252.0824671, "composition": 0.0}, - 253: {"mass": 253.0851846, "composition": 0.0}, - 254: {"mass": 254.0868544, "composition": 0.0}, - 255: {"mass": 255.089964, "composition": 0.0}, - 256: {"mass": 256.0917745, "composition": 0.0}, - 257: {"mass": 257.0951061, "composition": 0.0}, - 258: {"mass": 258.09708, "composition": 0.0}, - 259: {"mass": 259.1006, "composition": 0.0}, - 260: {"mass": 260.10281, "composition": 0.0}}, - 101: {245: {"mass": 245.08081, "composition": 0.0}, - 246: {"mass": 246.08171, "composition": 0.0}, - 247: {"mass": 247.08152, "composition": 0.0}, - 248: {"mass": 248.08282, "composition": 0.0}, - 249: {"mass": 249.08291, "composition": 0.0}, - 250: {"mass": 250.08441, "composition": 0.0}, - 251: {"mass": 251.084774, "composition": 0.0}, - 252: {"mass": 252.08643, "composition": 0.0}, - 253: {"mass": 253.087144, "composition": 0.0}, - 254: {"mass": 254.08959, "composition": 0.0}, - 255: {"mass": 255.0910841, "composition": 0.0}, - 256: {"mass": 256.09389, "composition": 0.0}, - 257: {"mass": 257.0955424, "composition": 0.0}, - 258: {"mass": 258.0984315, "composition": 0.0}, - 259: {"mass": 259.10051, "composition": 0.0}, - 260: {"mass": 260.10365, "composition": 0.0}, - 261: {"mass": 261.10583, "composition": 0.0}, - 262: {"mass": 262.1091, "composition": 0.0}}, - 102: {248: {"mass": 248.08655, "composition": 0.0}, - 249: {"mass": 249.0878, "composition": 0.0}, - 250: {"mass": 250.08756, "composition": 0.0}, - 251: {"mass": 251.08894, "composition": 0.0}, - 252: {"mass": 252.088967, "composition": 0.0}, - 253: {"mass": 253.0905641, "composition": 0.0}, - 254: {"mass": 254.090956, "composition": 0.0}, - 255: {"mass": 255.093191, "composition": 0.0}, - 256: {"mass": 256.0942829, "composition": 0.0}, - 257: {"mass": 257.0968878, "composition": 0.0}, - 258: {"mass": 258.09821, "composition": 0.0}, - 259: {"mass": 259.10103, "composition": 0.0}, - 260: {"mass": 260.10264, "composition": 0.0}, - 261: {"mass": 261.1057, "composition": 0.0}, - 262: {"mass": 262.10746, "composition": 0.0}, - 263: {"mass": 263.11071, "composition": 0.0}, - 264: {"mass": 264.11273, "composition": 0.0}}, - 103: {251: {"mass": 251.09418, "composition": 0.0}, - 252: {"mass": 252.09526, "composition": 0.0}, - 253: {"mass": 253.09509, "composition": 0.0}, - 254: {"mass": 254.09648, "composition": 0.0}, - 255: {"mass": 255.096562, "composition": 0.0}, - 256: {"mass": 256.098494, "composition": 0.0}, - 257: {"mass": 257.099418, "composition": 0.0}, - 258: {"mass": 258.10176, "composition": 0.0}, - 259: {"mass": 259.102902, "composition": 0.0}, - 260: {"mass": 260.1055, "composition": 0.0}, - 261: {"mass": 261.10688, "composition": 0.0}, - 262: {"mass": 262.10961, "composition": 0.0}, - 263: {"mass": 263.11136, "composition": 0.0}, - 264: {"mass": 264.1142, "composition": 0.0}, - 265: {"mass": 265.11619, "composition": 0.0}, - 266: {"mass": 266.11983, "composition": 0.0}}, - 104: {253: {"mass": 253.10044, "composition": 0.0}, - 254: {"mass": 254.10005, "composition": 0.0}, - 255: {"mass": 255.10127, "composition": 0.0}, - 256: {"mass": 256.101152, "composition": 0.0}, - 257: {"mass": 257.102918, "composition": 0.0}, - 258: {"mass": 258.103428, "composition": 0.0}, - 259: {"mass": 259.105596, "composition": 0.0}, - 260: {"mass": 260.10644, "composition": 0.0}, - 261: {"mass": 261.108773, "composition": 0.0}, - 262: {"mass": 262.10992, "composition": 0.0}, - 263: {"mass": 263.11249, "composition": 0.0}, - 264: {"mass": 264.11388, "composition": 0.0}, - 265: {"mass": 265.11668, "composition": 0.0}, - 266: {"mass": 266.11817, "composition": 0.0}, - 267: {"mass": 267.12179, "composition": 0.0}, - 268: {"mass": 268.12397, "composition": 0.0}}, - 105: {255: {"mass": 255.10707, "composition": 0.0}, - 256: {"mass": 256.10789, "composition": 0.0}, - 257: {"mass": 257.10758, "composition": 0.0}, - 258: {"mass": 258.10928, "composition": 0.0}, - 259: {"mass": 259.109492, "composition": 0.0}, - 260: {"mass": 260.1113, "composition": 0.0}, - 261: {"mass": 261.11192, "composition": 0.0}, - 262: {"mass": 262.11407, "composition": 0.0}, - 263: {"mass": 263.11499, "composition": 0.0}, - 264: {"mass": 264.11741, "composition": 0.0}, - 265: {"mass": 265.11861, "composition": 0.0}, - 266: {"mass": 266.12103, "composition": 0.0}, - 267: {"mass": 267.12247, "composition": 0.0}, - 268: {"mass": 268.12567, "composition": 0.0}, - 269: {"mass": 269.12791, "composition": 0.0}, - 270: {"mass": 270.13136, "composition": 0.0}}, - 106: {258: {"mass": 258.11298, "composition": 0.0}, - 259: {"mass": 259.1144, "composition": 0.0}, - 260: {"mass": 260.114384, "composition": 0.0}, - 261: {"mass": 261.115949, "composition": 0.0}, - 262: {"mass": 262.116337, "composition": 0.0}, - 263: {"mass": 263.11829, "composition": 0.0}, - 264: {"mass": 264.11893, "composition": 0.0}, - 265: {"mass": 265.12109, "composition": 0.0}, - 266: {"mass": 266.12198, "composition": 0.0}, - 267: {"mass": 267.12436, "composition": 0.0}, - 268: {"mass": 268.12539, "composition": 0.0}, - 269: {"mass": 269.12863, "composition": 0.0}, - 270: {"mass": 270.13043, "composition": 0.0}, - 271: {"mass": 271.13393, "composition": 0.0}, - 272: {"mass": 272.13589, "composition": 0.0}, - 273: {"mass": 273.13958, "composition": 0.0}}, - 107: {260: {"mass": 260.12166, "composition": 0.0}, - 261: {"mass": 261.12145, "composition": 0.0}, - 262: {"mass": 262.12297, "composition": 0.0}, - 263: {"mass": 263.12292, "composition": 0.0}, - 264: {"mass": 264.12459, "composition": 0.0}, - 265: {"mass": 265.12491, "composition": 0.0}, - 266: {"mass": 266.12679, "composition": 0.0}, - 267: {"mass": 267.1275, "composition": 0.0}, - 268: {"mass": 268.12969, "composition": 0.0}, - 269: {"mass": 269.13042, "composition": 0.0}, - 270: {"mass": 270.13336, "composition": 0.0}, - 271: {"mass": 271.13526, "composition": 0.0}, - 272: {"mass": 272.13826, "composition": 0.0}, - 273: {"mass": 273.14024, "composition": 0.0}, - 274: {"mass": 274.14355, "composition": 0.0}, - 275: {"mass": 275.14567, "composition": 0.0}}, - 108: {263: {"mass": 263.12852, "composition": 0.0}, - 264: {"mass": 264.128357, "composition": 0.0}, - 265: {"mass": 265.129793, "composition": 0.0}, - 266: {"mass": 266.130046, "composition": 0.0}, - 267: {"mass": 267.13167, "composition": 0.0}, - 268: {"mass": 268.13186, "composition": 0.0}, - 269: {"mass": 269.13375, "composition": 0.0}, - 270: {"mass": 270.13429, "composition": 0.0}, - 271: {"mass": 271.13717, "composition": 0.0}, - 272: {"mass": 272.1385, "composition": 0.0}, - 273: {"mass": 273.14168, "composition": 0.0}, - 274: {"mass": 274.1433, "composition": 0.0}, - 275: {"mass": 275.14667, "composition": 0.0}, - 276: {"mass": 276.14846, "composition": 0.0}, - 277: {"mass": 277.1519, "composition": 0.0}}, - 109: {265: {"mass": 265.136, "composition": 0.0}, - 266: {"mass": 266.13737, "composition": 0.0}, - 267: {"mass": 267.13719, "composition": 0.0}, - 268: {"mass": 268.13865, "composition": 0.0}, - 269: {"mass": 269.13882, "composition": 0.0}, - 270: {"mass": 270.14033, "composition": 0.0}, - 271: {"mass": 271.14074, "composition": 0.0}, - 272: {"mass": 272.14341, "composition": 0.0}, - 273: {"mass": 273.1444, "composition": 0.0}, - 274: {"mass": 274.14724, "composition": 0.0}, - 275: {"mass": 275.14882, "composition": 0.0}, - 276: {"mass": 276.15159, "composition": 0.0}, - 277: {"mass": 277.15327, "composition": 0.0}, - 278: {"mass": 278.15631, "composition": 0.0}, - 279: {"mass": 279.15808, "composition": 0.0}}, - 110: {267: {"mass": 267.14377, "composition": 0.0}, - 268: {"mass": 268.14348, "composition": 0.0}, - 269: {"mass": 269.144752, "composition": 0.0}, - 270: {"mass": 270.144584, "composition": 0.0}, - 271: {"mass": 271.14595, "composition": 0.0}, - 272: {"mass": 272.14602, "composition": 0.0}, - 273: {"mass": 273.14856, "composition": 0.0}, - 274: {"mass": 274.14941, "composition": 0.0}, - 275: {"mass": 275.15203, "composition": 0.0}, - 276: {"mass": 276.15303, "composition": 0.0}, - 277: {"mass": 277.15591, "composition": 0.0}, - 278: {"mass": 278.15704, "composition": 0.0}, - 279: {"mass": 279.1601, "composition": 0.0}, - 280: {"mass": 280.16131, "composition": 0.0}, - 281: {"mass": 281.16451, "composition": 0.0}}, - 111: {272: {"mass": 272.15327, "composition": 0.0}, - 273: {"mass": 273.15313, "composition": 0.0}, - 274: {"mass": 274.15525, "composition": 0.0}, - 275: {"mass": 275.15594, "composition": 0.0}, - 276: {"mass": 276.15833, "composition": 0.0}, - 277: {"mass": 277.15907, "composition": 0.0}, - 278: {"mass": 278.16149, "composition": 0.0}, - 279: {"mass": 279.16272, "composition": 0.0}, - 280: {"mass": 280.16514, "composition": 0.0}, - 281: {"mass": 281.16636, "composition": 0.0}, - 282: {"mass": 282.16912, "composition": 0.0}, - 283: {"mass": 283.17054, "composition": 0.0}}, - 112: {276: {"mass": 276.16141, "composition": 0.0}, - 277: {"mass": 277.16364, "composition": 0.0}, - 278: {"mass": 278.16416, "composition": 0.0}, - 279: {"mass": 279.16654, "composition": 0.0}, - 280: {"mass": 280.16715, "composition": 0.0}, - 281: {"mass": 281.16975, "composition": 0.0}, - 282: {"mass": 282.1705, "composition": 0.0}, - 283: {"mass": 283.17327, "composition": 0.0}, - 284: {"mass": 284.17416, "composition": 0.0}, - 285: {"mass": 285.17712, "composition": 0.0}}, - 113: {278: {"mass": 278.17058, "composition": 0.0}, - 279: {"mass": 279.17095, "composition": 0.0}, - 280: {"mass": 280.17293, "composition": 0.0}, - 281: {"mass": 281.17348, "composition": 0.0}, - 282: {"mass": 282.17567, "composition": 0.0}, - 283: {"mass": 283.17657, "composition": 0.0}, - 284: {"mass": 284.17873, "composition": 0.0}, - 285: {"mass": 285.17973, "composition": 0.0}, - 286: {"mass": 286.18221, "composition": 0.0}, - 287: {"mass": 287.18339, "composition": 0.0}}, - 114: {285: {"mass": 285.18364, "composition": 0.0}, - 286: {"mass": 286.18423, "composition": 0.0}, - 287: {"mass": 287.18678, "composition": 0.0}, - 288: {"mass": 288.18757, "composition": 0.0}, - 289: {"mass": 289.19042, "composition": 0.0}}, - 115: {287: {"mass": 287.1907, "composition": 0.0}, - 288: {"mass": 288.19274, "composition": 0.0}, - 289: {"mass": 289.19363, "composition": 0.0}, - 290: {"mass": 290.19598, "composition": 0.0}, - 291: {"mass": 291.19707, "composition": 0.0}}, - 116: {289: {"mass": 289.19816, "composition": 0.0}, - 290: {"mass": 290.19864, "composition": 0.0}, - 291: {"mass": 291.20108, "composition": 0.0}, - 292: {"mass": 292.20174, "composition": 0.0}, - 293: {"mass": 293.20449, "composition": 0.0}}, - 117: {291: {"mass": 291.20553, "composition": 0.0}, - 292: {"mass": 292.20746, "composition": 0.0}, - 293: {"mass": 293.20824, "composition": 0.0}, - 294: {"mass": 294.21046, "composition": 0.0}}, - 118: {293: {"mass": 293.21356, "composition": 0.0}, - 294: {"mass": 294.21392, "composition": 0.0}, - 295: {"mass": 295.21624, "composition": 0.0}}} \ No newline at end of file + 2: {"mass": 2.01410177812, "composition": 0.000115}, + 3: {"mass": 3.0160492779, "composition": 0.0}, + 4: {"mass": 4.02643, "composition": 0.0}, + 5: {"mass": 5.035311, "composition": 0.0}, + 6: {"mass": 6.04496, "composition": 0.0}, + 7: {"mass": 7.0527, "composition": 0.0}}, + 2: {3: {"mass": 3.0160293201, "composition": 1.34e-06}, + 4: {"mass": 4.00260325413, "composition": 0.99999866}, + 5: {"mass": 5.012057, "composition": 0.0}, + 6: {"mass": 6.018885891, "composition": 0.0}, + 7: {"mass": 7.0279907, "composition": 0.0}, + 8: {"mass": 8.03393439, "composition": 0.0}, + 9: {"mass": 9.043946, "composition": 0.0}, + 10: {"mass": 10.05279, "composition": 0.0}}, + 3: {3: {"mass": 3.0308, "composition": 0.0}, + 4: {"mass": 4.02719, "composition": 0.0}, + 5: {"mass": 5.012538, "composition": 0.0}, + 6: {"mass": 6.0151228874, "composition": 0.0759}, + 7: {"mass": 7.0160034366, "composition": 0.9241}, + 8: {"mass": 8.022486246, "composition": 0.0}, + 9: {"mass": 9.02679019, "composition": 0.0}, + 10: {"mass": 10.035483, "composition": 0.0}, + 11: {"mass": 11.04372358, "composition": 0.0}, + 12: {"mass": 12.052517, "composition": 0.0}, + 13: {"mass": 13.06263, "composition": 0.0}}, + 4: {5: {"mass": 5.0399, "composition": 0.0}, + 6: {"mass": 6.0197264, "composition": 0.0}, + 7: {"mass": 7.016928717, "composition": 0.0}, + 8: {"mass": 8.005305102, "composition": 0.0}, + 9: {"mass": 9.012183065, "composition": 1.0}, + 10: {"mass": 10.013534695, "composition": 0.0}, + 11: {"mass": 11.02166108, "composition": 0.0}, + 12: {"mass": 12.0269221, "composition": 0.0}, + 13: {"mass": 13.036135, "composition": 0.0}, + 14: {"mass": 14.04289, "composition": 0.0}, + 15: {"mass": 15.05342, "composition": 0.0}, + 16: {"mass": 16.06167, "composition": 0.0}}, + 5: {6: {"mass": 6.0508, "composition": 0.0}, + 7: {"mass": 7.029712, "composition": 0.0}, + 8: {"mass": 8.0246073, "composition": 0.0}, + 9: {"mass": 9.01332965, "composition": 0.0}, + 10: {"mass": 10.01293695, "composition": 0.199}, + 11: {"mass": 11.00930536, "composition": 0.801}, + 12: {"mass": 12.0143527, "composition": 0.0}, + 13: {"mass": 13.0177802, "composition": 0.0}, + 14: {"mass": 14.025404, "composition": 0.0}, + 15: {"mass": 15.031088, "composition": 0.0}, + 16: {"mass": 16.039842, "composition": 0.0}, + 17: {"mass": 17.04699, "composition": 0.0}, + 18: {"mass": 18.05566, "composition": 0.0}, + 19: {"mass": 19.0631, "composition": 0.0}, + 20: {"mass": 20.07207, "composition": 0.0}, + 21: {"mass": 21.08129, "composition": 0.0}}, + 6: {8: {"mass": 8.037643, "composition": 0.0}, + 9: {"mass": 9.0310372, "composition": 0.0}, + 10: {"mass": 10.01685331, "composition": 0.0}, + 11: {"mass": 11.0114336, "composition": 0.0}, + 12: {"mass": 12.0, "composition": 0.9893}, + 13: {"mass": 13.00335483507, "composition": 0.0107}, + 14: {"mass": 14.0032419884, "composition": 0.0}, + 15: {"mass": 15.01059926, "composition": 0.0}, + 16: {"mass": 16.0147013, "composition": 0.0}, + 17: {"mass": 17.022577, "composition": 0.0}, + 18: {"mass": 18.026751, "composition": 0.0}, + 19: {"mass": 19.0348, "composition": 0.0}, + 20: {"mass": 20.04032, "composition": 0.0}, + 21: {"mass": 21.049, "composition": 0.0}, + 22: {"mass": 22.05753, "composition": 0.0}, + 23: {"mass": 23.0689, "composition": 0.0}}, + 7: {10: {"mass": 10.04165, "composition": 0.0}, + 11: {"mass": 11.026091, "composition": 0.0}, + 12: {"mass": 12.0186132, "composition": 0.0}, + 13: {"mass": 13.00573861, "composition": 0.0}, + 14: {"mass": 14.00307400443, "composition": 0.99636}, + 15: {"mass": 15.00010889888, "composition": 0.00364}, + 16: {"mass": 16.0061019, "composition": 0.0}, + 17: {"mass": 17.008449, "composition": 0.0}, + 18: {"mass": 18.014078, "composition": 0.0}, + 19: {"mass": 19.017022, "composition": 0.0}, + 20: {"mass": 20.023366, "composition": 0.0}, + 21: {"mass": 21.02711, "composition": 0.0}, + 22: {"mass": 22.03439, "composition": 0.0}, + 23: {"mass": 23.04114, "composition": 0.0}, + 24: {"mass": 24.05039, "composition": 0.0}, + 25: {"mass": 25.0601, "composition": 0.0}}, + 8: {12: {"mass": 12.034262, "composition": 0.0}, + 13: {"mass": 13.024815, "composition": 0.0}, + 14: {"mass": 14.00859636, "composition": 0.0}, + 15: {"mass": 15.00306562, "composition": 0.0}, + 16: {"mass": 15.99491461957, "composition": 0.99757}, + 17: {"mass": 16.9991317565, "composition": 0.00038}, + 18: {"mass": 17.99915961286, "composition": 0.00205}, + 19: {"mass": 19.003578, "composition": 0.0}, + 20: {"mass": 20.00407535, "composition": 0.0}, + 21: {"mass": 21.008655, "composition": 0.0}, + 22: {"mass": 22.009966, "composition": 0.0}, + 23: {"mass": 23.015696, "composition": 0.0}, + 24: {"mass": 24.01986, "composition": 0.0}, + 25: {"mass": 25.02936, "composition": 0.0}, + 26: {"mass": 26.03729, "composition": 0.0}, + 27: {"mass": 27.04772, "composition": 0.0}, + 28: {"mass": 28.05591, "composition": 0.0}}, + 9: {14: {"mass": 14.034315, "composition": 0.0}, + 15: {"mass": 15.018043, "composition": 0.0}, + 16: {"mass": 16.0114657, "composition": 0.0}, + 17: {"mass": 17.00209524, "composition": 0.0}, + 18: {"mass": 18.00093733, "composition": 0.0}, + 19: {"mass": 18.99840316273, "composition": 1.0}, + 20: {"mass": 19.999981252, "composition": 0.0}, + 21: {"mass": 20.9999489, "composition": 0.0}, + 22: {"mass": 22.002999, "composition": 0.0}, + 23: {"mass": 23.003557, "composition": 0.0}, + 24: {"mass": 24.008115, "composition": 0.0}, + 25: {"mass": 25.012199, "composition": 0.0}, + 26: {"mass": 26.020038, "composition": 0.0}, + 27: {"mass": 27.02644, "composition": 0.0}, + 28: {"mass": 28.03534, "composition": 0.0}, + 29: {"mass": 29.04254, "composition": 0.0}, + 30: {"mass": 30.05165, "composition": 0.0}, + 31: {"mass": 31.05971, "composition": 0.0}}, + 10: {16: {"mass": 16.02575, "composition": 0.0}, + 17: {"mass": 17.01771396, "composition": 0.0}, + 18: {"mass": 18.0057087, "composition": 0.0}, + 19: {"mass": 19.00188091, "composition": 0.0}, + 20: {"mass": 19.9924401762, "composition": 0.9048}, + 21: {"mass": 20.993846685, "composition": 0.0027}, + 22: {"mass": 21.991385114, "composition": 0.0925}, + 23: {"mass": 22.99446691, "composition": 0.0}, + 24: {"mass": 23.99361065, "composition": 0.0}, + 25: {"mass": 24.997789, "composition": 0.0}, + 26: {"mass": 26.000515, "composition": 0.0}, + 27: {"mass": 27.007553, "composition": 0.0}, + 28: {"mass": 28.01212, "composition": 0.0}, + 29: {"mass": 29.01975, "composition": 0.0}, + 30: {"mass": 30.02473, "composition": 0.0}, + 31: {"mass": 31.0331, "composition": 0.0}, + 32: {"mass": 32.03972, "composition": 0.0}, + 33: {"mass": 33.04938, "composition": 0.0}, + 34: {"mass": 34.05673, "composition": 0.0}}, + 11: {18: {"mass": 18.02688, "composition": 0.0}, + 19: {"mass": 19.01388, "composition": 0.0}, + 20: {"mass": 20.0073544, "composition": 0.0}, + 21: {"mass": 20.99765469, "composition": 0.0}, + 22: {"mass": 21.99443741, "composition": 0.0}, + 23: {"mass": 22.989769282, "composition": 1.0}, + 24: {"mass": 23.99096295, "composition": 0.0}, + 25: {"mass": 24.989954, "composition": 0.0}, + 26: {"mass": 25.9926346, "composition": 0.0}, + 27: {"mass": 26.9940765, "composition": 0.0}, + 28: {"mass": 27.998939, "composition": 0.0}, + 29: {"mass": 29.0028771, "composition": 0.0}, + 30: {"mass": 30.0090979, "composition": 0.0}, + 31: {"mass": 31.013163, "composition": 0.0}, + 32: {"mass": 32.02019, "composition": 0.0}, + 33: {"mass": 33.02573, "composition": 0.0}, + 34: {"mass": 34.03359, "composition": 0.0}, + 35: {"mass": 35.04062, "composition": 0.0}, + 36: {"mass": 36.04929, "composition": 0.0}, + 37: {"mass": 37.05705, "composition": 0.0}}, + 12: {19: {"mass": 19.034169, "composition": 0.0}, + 20: {"mass": 20.01885, "composition": 0.0}, + 21: {"mass": 21.011716, "composition": 0.0}, + 22: {"mass": 21.99957065, "composition": 0.0}, + 23: {"mass": 22.99412421, "composition": 0.0}, + 24: {"mass": 23.985041697, "composition": 0.7899}, + 25: {"mass": 24.985836976, "composition": 0.1}, + 26: {"mass": 25.982592968, "composition": 0.1101}, + 27: {"mass": 26.984340624, "composition": 0.0}, + 28: {"mass": 27.9838767, "composition": 0.0}, + 29: {"mass": 28.988617, "composition": 0.0}, + 30: {"mass": 29.9904629, "composition": 0.0}, + 31: {"mass": 30.996648, "composition": 0.0}, + 32: {"mass": 31.9991102, "composition": 0.0}, + 33: {"mass": 33.0053271, "composition": 0.0}, + 34: {"mass": 34.008935, "composition": 0.0}, + 35: {"mass": 35.01679, "composition": 0.0}, + 36: {"mass": 36.02188, "composition": 0.0}, + 37: {"mass": 37.03037, "composition": 0.0}, + 38: {"mass": 38.03658, "composition": 0.0}, + 39: {"mass": 39.04538, "composition": 0.0}, + 40: {"mass": 40.05218, "composition": 0.0}}, + 13: {21: {"mass": 21.02897, "composition": 0.0}, + 22: {"mass": 22.01954, "composition": 0.0}, + 23: {"mass": 23.00724435, "composition": 0.0}, + 24: {"mass": 23.9999489, "composition": 0.0}, + 25: {"mass": 24.9904281, "composition": 0.0}, + 26: {"mass": 25.986891904, "composition": 0.0}, + 27: {"mass": 26.98153853, "composition": 1.0}, + 28: {"mass": 27.98191021, "composition": 0.0}, + 29: {"mass": 28.9804565, "composition": 0.0}, + 30: {"mass": 29.98296, "composition": 0.0}, + 31: {"mass": 30.983945, "composition": 0.0}, + 32: {"mass": 31.988085, "composition": 0.0}, + 33: {"mass": 32.990909, "composition": 0.0}, + 34: {"mass": 33.996705, "composition": 0.0}, + 35: {"mass": 34.999764, "composition": 0.0}, + 36: {"mass": 36.00639, "composition": 0.0}, + 37: {"mass": 37.01053, "composition": 0.0}, + 38: {"mass": 38.0174, "composition": 0.0}, + 39: {"mass": 39.02254, "composition": 0.0}, + 40: {"mass": 40.03003, "composition": 0.0}, + 41: {"mass": 41.03638, "composition": 0.0}, + 42: {"mass": 42.04384, "composition": 0.0}, + 43: {"mass": 43.05147, "composition": 0.0}}, + 14: {22: {"mass": 22.03579, "composition": 0.0}, + 23: {"mass": 23.02544, "composition": 0.0}, + 24: {"mass": 24.011535, "composition": 0.0}, + 25: {"mass": 25.004109, "composition": 0.0}, + 26: {"mass": 25.99233384, "composition": 0.0}, + 27: {"mass": 26.98670481, "composition": 0.0}, + 28: {"mass": 27.97692653465, "composition": 0.92223}, + 29: {"mass": 28.9764946649, "composition": 0.04685}, + 30: {"mass": 29.973770136, "composition": 0.03092}, + 31: {"mass": 30.975363194, "composition": 0.0}, + 32: {"mass": 31.97415154, "composition": 0.0}, + 33: {"mass": 32.97797696, "composition": 0.0}, + 34: {"mass": 33.978576, "composition": 0.0}, + 35: {"mass": 34.984583, "composition": 0.0}, + 36: {"mass": 35.986695, "composition": 0.0}, + 37: {"mass": 36.992921, "composition": 0.0}, + 38: {"mass": 37.995523, "composition": 0.0}, + 39: {"mass": 39.002491, "composition": 0.0}, + 40: {"mass": 40.00583, "composition": 0.0}, + 41: {"mass": 41.01301, "composition": 0.0}, + 42: {"mass": 42.01778, "composition": 0.0}, + 43: {"mass": 43.0248, "composition": 0.0}, + 44: {"mass": 44.03061, "composition": 0.0}, + 45: {"mass": 45.03995, "composition": 0.0}}, + 15: {24: {"mass": 24.03577, "composition": 0.0}, + 25: {"mass": 25.02119, "composition": 0.0}, + 26: {"mass": 26.01178, "composition": 0.0}, + 27: {"mass": 26.999224, "composition": 0.0}, + 28: {"mass": 27.9923266, "composition": 0.0}, + 29: {"mass": 28.98180079, "composition": 0.0}, + 30: {"mass": 29.97831375, "composition": 0.0}, + 31: {"mass": 30.97376199842, "composition": 1.0}, + 32: {"mass": 31.973907643, "composition": 0.0}, + 33: {"mass": 32.9717257, "composition": 0.0}, + 34: {"mass": 33.97364589, "composition": 0.0}, + 35: {"mass": 34.9733141, "composition": 0.0}, + 36: {"mass": 35.97826, "composition": 0.0}, + 37: {"mass": 36.979607, "composition": 0.0}, + 38: {"mass": 37.984252, "composition": 0.0}, + 39: {"mass": 38.986227, "composition": 0.0}, + 40: {"mass": 39.99133, "composition": 0.0}, + 41: {"mass": 40.994654, "composition": 0.0}, + 42: {"mass": 42.00108, "composition": 0.0}, + 43: {"mass": 43.00502, "composition": 0.0}, + 44: {"mass": 44.01121, "composition": 0.0}, + 45: {"mass": 45.01645, "composition": 0.0}, + 46: {"mass": 46.02446, "composition": 0.0}, + 47: {"mass": 47.03139, "composition": 0.0}}, + 16: {26: {"mass": 26.02907, "composition": 0.0}, + 27: {"mass": 27.01828, "composition": 0.0}, + 28: {"mass": 28.00437, "composition": 0.0}, + 29: {"mass": 28.996611, "composition": 0.0}, + 30: {"mass": 29.98490703, "composition": 0.0}, + 31: {"mass": 30.97955701, "composition": 0.0}, + 32: {"mass": 31.9720711744, "composition": 0.9499}, + 33: {"mass": 32.9714589098, "composition": 0.0075}, + 34: {"mass": 33.967867004, "composition": 0.0425}, + 35: {"mass": 34.96903231, "composition": 0.0}, + 36: {"mass": 35.96708071, "composition": 0.0001}, + 37: {"mass": 36.97112551, "composition": 0.0}, + 38: {"mass": 37.9711633, "composition": 0.0}, + 39: {"mass": 38.975134, "composition": 0.0}, + 40: {"mass": 39.9754826, "composition": 0.0}, + 41: {"mass": 40.9795935, "composition": 0.0}, + 42: {"mass": 41.9810651, "composition": 0.0}, + 43: {"mass": 42.9869076, "composition": 0.0}, + 44: {"mass": 43.9901188, "composition": 0.0}, + 45: {"mass": 44.99572, "composition": 0.0}, + 46: {"mass": 46.00004, "composition": 0.0}, + 47: {"mass": 47.00795, "composition": 0.0}, + 48: {"mass": 48.0137, "composition": 0.0}, + 49: {"mass": 49.02276, "composition": 0.0}}, + 17: {28: {"mass": 28.02954, "composition": 0.0}, + 29: {"mass": 29.01478, "composition": 0.0}, + 30: {"mass": 30.00477, "composition": 0.0}, + 31: {"mass": 30.992414, "composition": 0.0}, + 32: {"mass": 31.98568464, "composition": 0.0}, + 33: {"mass": 32.97745199, "composition": 0.0}, + 34: {"mass": 33.973762485, "composition": 0.0}, + 35: {"mass": 34.968852682, "composition": 0.7576}, + 36: {"mass": 35.968306809, "composition": 0.0}, + 37: {"mass": 36.965902602, "composition": 0.2424}, + 38: {"mass": 37.96801044, "composition": 0.0}, + 39: {"mass": 38.9680082, "composition": 0.0}, + 40: {"mass": 39.970415, "composition": 0.0}, + 41: {"mass": 40.970685, "composition": 0.0}, + 42: {"mass": 41.97325, "composition": 0.0}, + 43: {"mass": 42.97389, "composition": 0.0}, + 44: {"mass": 43.97787, "composition": 0.0}, + 45: {"mass": 44.98029, "composition": 0.0}, + 46: {"mass": 45.98517, "composition": 0.0}, + 47: {"mass": 46.98916, "composition": 0.0}, + 48: {"mass": 47.99564, "composition": 0.0}, + 49: {"mass": 49.00123, "composition": 0.0}, + 50: {"mass": 50.00905, "composition": 0.0}, + 51: {"mass": 51.01554, "composition": 0.0}}, + 18: {30: {"mass": 30.02307, "composition": 0.0}, + 31: {"mass": 31.01212, "composition": 0.0}, + 32: {"mass": 31.9976378, "composition": 0.0}, + 33: {"mass": 32.98992555, "composition": 0.0}, + 34: {"mass": 33.98027009, "composition": 0.0}, + 35: {"mass": 34.97525759, "composition": 0.0}, + 36: {"mass": 35.967545105, "composition": 0.003336}, + 37: {"mass": 36.96677633, "composition": 0.0}, + 38: {"mass": 37.96273211, "composition": 0.000629}, + 39: {"mass": 38.964313, "composition": 0.0}, + 40: {"mass": 39.9623831237, "composition": 0.996035}, + 41: {"mass": 40.96450057, "composition": 0.0}, + 42: {"mass": 41.9630457, "composition": 0.0}, + 43: {"mass": 42.9656361, "composition": 0.0}, + 44: {"mass": 43.9649238, "composition": 0.0}, + 45: {"mass": 44.96803973, "composition": 0.0}, + 46: {"mass": 45.968083, "composition": 0.0}, + 47: {"mass": 46.972935, "composition": 0.0}, + 48: {"mass": 47.97591, "composition": 0.0}, + 49: {"mass": 48.9819, "composition": 0.0}, + 50: {"mass": 49.98613, "composition": 0.0}, + 51: {"mass": 50.9937, "composition": 0.0}, + 52: {"mass": 51.99896, "composition": 0.0}, + 53: {"mass": 53.00729, "composition": 0.0}}, + 19: {32: {"mass": 32.02265, "composition": 0.0}, + 33: {"mass": 33.00756, "composition": 0.0}, + 34: {"mass": 33.99869, "composition": 0.0}, + 35: {"mass": 34.98800541, "composition": 0.0}, + 36: {"mass": 35.98130201, "composition": 0.0}, + 37: {"mass": 36.97337589, "composition": 0.0}, + 38: {"mass": 37.96908112, "composition": 0.0}, + 39: {"mass": 38.9637064864, "composition": 0.932581}, + 40: {"mass": 39.963998166, "composition": 0.000117}, + 41: {"mass": 40.9618252579, "composition": 0.067302}, + 42: {"mass": 41.96240231, "composition": 0.0}, + 43: {"mass": 42.9607347, "composition": 0.0}, + 44: {"mass": 43.96158699, "composition": 0.0}, + 45: {"mass": 44.96069149, "composition": 0.0}, + 46: {"mass": 45.96198159, "composition": 0.0}, + 47: {"mass": 46.9616616, "composition": 0.0}, + 48: {"mass": 47.96534119, "composition": 0.0}, + 49: {"mass": 48.96821075, "composition": 0.0}, + 50: {"mass": 49.97238, "composition": 0.0}, + 51: {"mass": 50.975828, "composition": 0.0}, + 52: {"mass": 51.98224, "composition": 0.0}, + 53: {"mass": 52.98746, "composition": 0.0}, + 54: {"mass": 53.99463, "composition": 0.0}, + 55: {"mass": 55.00076, "composition": 0.0}, + 56: {"mass": 56.00851, "composition": 0.0}}, + 20: {34: {"mass": 34.01487, "composition": 0.0}, + 35: {"mass": 35.00514, "composition": 0.0}, + 36: {"mass": 35.993074, "composition": 0.0}, + 37: {"mass": 36.98589785, "composition": 0.0}, + 38: {"mass": 37.97631922, "composition": 0.0}, + 39: {"mass": 38.97071081, "composition": 0.0}, + 40: {"mass": 39.962590863, "composition": 0.96941}, + 41: {"mass": 40.96227792, "composition": 0.0}, + 42: {"mass": 41.95861783, "composition": 0.00647}, + 43: {"mass": 42.95876644, "composition": 0.00135}, + 44: {"mass": 43.95548156, "composition": 0.02086}, + 45: {"mass": 44.95618635, "composition": 0.0}, + 46: {"mass": 45.953689, "composition": 4e-05}, + 47: {"mass": 46.9545424, "composition": 0.0}, + 48: {"mass": 47.95252276, "composition": 0.00187}, + 49: {"mass": 48.95566274, "composition": 0.0}, + 50: {"mass": 49.9574992, "composition": 0.0}, + 51: {"mass": 50.960989, "composition": 0.0}, + 52: {"mass": 51.963217, "composition": 0.0}, + 53: {"mass": 52.96945, "composition": 0.0}, + 54: {"mass": 53.9734, "composition": 0.0}, + 55: {"mass": 54.9803, "composition": 0.0}, + 56: {"mass": 55.98508, "composition": 0.0}, + 57: {"mass": 56.99262, "composition": 0.0}, + 58: {"mass": 57.99794, "composition": 0.0}}, + 21: {36: {"mass": 36.01648, "composition": 0.0}, + 37: {"mass": 37.00374, "composition": 0.0}, + 38: {"mass": 37.99512, "composition": 0.0}, + 39: {"mass": 38.984785, "composition": 0.0}, + 40: {"mass": 39.9779673, "composition": 0.0}, + 41: {"mass": 40.969251105, "composition": 0.0}, + 42: {"mass": 41.96551653, "composition": 0.0}, + 43: {"mass": 42.9611505, "composition": 0.0}, + 44: {"mass": 43.9594029, "composition": 0.0}, + 45: {"mass": 44.95590828, "composition": 1.0}, + 46: {"mass": 45.95516826, "composition": 0.0}, + 47: {"mass": 46.9524037, "composition": 0.0}, + 48: {"mass": 47.9522236, "composition": 0.0}, + 49: {"mass": 48.9500146, "composition": 0.0}, + 50: {"mass": 49.952176, "composition": 0.0}, + 51: {"mass": 50.953592, "composition": 0.0}, + 52: {"mass": 51.95688, "composition": 0.0}, + 53: {"mass": 52.95909, "composition": 0.0}, + 54: {"mass": 53.96393, "composition": 0.0}, + 55: {"mass": 54.96782, "composition": 0.0}, + 56: {"mass": 55.97345, "composition": 0.0}, + 57: {"mass": 56.97777, "composition": 0.0}, + 58: {"mass": 57.98403, "composition": 0.0}, + 59: {"mass": 58.98894, "composition": 0.0}, + 60: {"mass": 59.99565, "composition": 0.0}, + 61: {"mass": 61.001, "composition": 0.0}}, + 22: {38: {"mass": 38.01145, "composition": 0.0}, + 39: {"mass": 39.00236, "composition": 0.0}, + 40: {"mass": 39.9905, "composition": 0.0}, + 41: {"mass": 40.983148, "composition": 0.0}, + 42: {"mass": 41.97304903, "composition": 0.0}, + 43: {"mass": 42.9685225, "composition": 0.0}, + 44: {"mass": 43.95968995, "composition": 0.0}, + 45: {"mass": 44.95812198, "composition": 0.0}, + 46: {"mass": 45.95262772, "composition": 0.0825}, + 47: {"mass": 46.95175879, "composition": 0.0744}, + 48: {"mass": 47.94794198, "composition": 0.7372}, + 49: {"mass": 48.94786568, "composition": 0.0541}, + 50: {"mass": 49.94478689, "composition": 0.0518}, + 51: {"mass": 50.94661065, "composition": 0.0}, + 52: {"mass": 51.946893, "composition": 0.0}, + 53: {"mass": 52.94973, "composition": 0.0}, + 54: {"mass": 53.95105, "composition": 0.0}, + 55: {"mass": 54.95527, "composition": 0.0}, + 56: {"mass": 55.95791, "composition": 0.0}, + 57: {"mass": 56.96364, "composition": 0.0}, + 58: {"mass": 57.9666, "composition": 0.0}, + 59: {"mass": 58.97247, "composition": 0.0}, + 60: {"mass": 59.97603, "composition": 0.0}, + 61: {"mass": 60.98245, "composition": 0.0}, + 62: {"mass": 61.98651, "composition": 0.0}, + 63: {"mass": 62.99375, "composition": 0.0}}, + 23: {40: {"mass": 40.01276, "composition": 0.0}, + 41: {"mass": 41.00021, "composition": 0.0}, + 42: {"mass": 41.99182, "composition": 0.0}, + 43: {"mass": 42.980766, "composition": 0.0}, + 44: {"mass": 43.97411, "composition": 0.0}, + 45: {"mass": 44.9657748, "composition": 0.0}, + 46: {"mass": 45.96019878, "composition": 0.0}, + 47: {"mass": 46.95490491, "composition": 0.0}, + 48: {"mass": 47.9522522, "composition": 0.0}, + 49: {"mass": 48.9485118, "composition": 0.0}, + 50: {"mass": 49.94715601, "composition": 0.0025}, + 51: {"mass": 50.94395704, "composition": 0.9975}, + 52: {"mass": 51.94477301, "composition": 0.0}, + 53: {"mass": 52.9443367, "composition": 0.0}, + 54: {"mass": 53.946439, "composition": 0.0}, + 55: {"mass": 54.94724, "composition": 0.0}, + 56: {"mass": 55.95048, "composition": 0.0}, + 57: {"mass": 56.95252, "composition": 0.0}, + 58: {"mass": 57.95672, "composition": 0.0}, + 59: {"mass": 58.95939, "composition": 0.0}, + 60: {"mass": 59.96431, "composition": 0.0}, + 61: {"mass": 60.96725, "composition": 0.0}, + 62: {"mass": 61.97265, "composition": 0.0}, + 63: {"mass": 62.97639, "composition": 0.0}, + 64: {"mass": 63.98264, "composition": 0.0}, + 65: {"mass": 64.9875, "composition": 0.0}, + 66: {"mass": 65.99398, "composition": 0.0}}, + 24: {42: {"mass": 42.0067, "composition": 0.0}, + 43: {"mass": 42.99753, "composition": 0.0}, + 44: {"mass": 43.98536, "composition": 0.0}, + 45: {"mass": 44.97905, "composition": 0.0}, + 46: {"mass": 45.968359, "composition": 0.0}, + 47: {"mass": 46.9628974, "composition": 0.0}, + 48: {"mass": 47.9540291, "composition": 0.0}, + 49: {"mass": 48.9513333, "composition": 0.0}, + 50: {"mass": 49.94604183, "composition": 0.04345}, + 51: {"mass": 50.94476502, "composition": 0.0}, + 52: {"mass": 51.94050623, "composition": 0.83789}, + 53: {"mass": 52.94064815, "composition": 0.09501}, + 54: {"mass": 53.93887916, "composition": 0.02365}, + 55: {"mass": 54.94083843, "composition": 0.0}, + 56: {"mass": 55.9406531, "composition": 0.0}, + 57: {"mass": 56.943613, "composition": 0.0}, + 58: {"mass": 57.94435, "composition": 0.0}, + 59: {"mass": 58.94859, "composition": 0.0}, + 60: {"mass": 59.95008, "composition": 0.0}, + 61: {"mass": 60.95442, "composition": 0.0}, + 62: {"mass": 61.9561, "composition": 0.0}, + 63: {"mass": 62.96165, "composition": 0.0}, + 64: {"mass": 63.96408, "composition": 0.0}, + 65: {"mass": 64.96996, "composition": 0.0}, + 66: {"mass": 65.97366, "composition": 0.0}, + 67: {"mass": 66.98016, "composition": 0.0}, + 68: {"mass": 67.98403, "composition": 0.0}}, + 25: {44: {"mass": 44.00715, "composition": 0.0}, + 45: {"mass": 44.99449, "composition": 0.0}, + 46: {"mass": 45.98609, "composition": 0.0}, + 47: {"mass": 46.975775, "composition": 0.0}, + 48: {"mass": 47.96852, "composition": 0.0}, + 49: {"mass": 48.959595, "composition": 0.0}, + 50: {"mass": 49.95423778, "composition": 0.0}, + 51: {"mass": 50.94820847, "composition": 0.0}, + 52: {"mass": 51.9455639, "composition": 0.0}, + 53: {"mass": 52.94128889, "composition": 0.0}, + 54: {"mass": 53.9403576, "composition": 0.0}, + 55: {"mass": 54.93804391, "composition": 1.0}, + 56: {"mass": 55.93890369, "composition": 0.0}, + 57: {"mass": 56.9382861, "composition": 0.0}, + 58: {"mass": 57.9400666, "composition": 0.0}, + 59: {"mass": 58.9403911, "composition": 0.0}, + 60: {"mass": 59.9431366, "composition": 0.0}, + 61: {"mass": 60.9444525, "composition": 0.0}, + 62: {"mass": 61.94795, "composition": 0.0}, + 63: {"mass": 62.9496647, "composition": 0.0}, + 64: {"mass": 63.9538494, "composition": 0.0}, + 65: {"mass": 64.9560198, "composition": 0.0}, + 66: {"mass": 65.960547, "composition": 0.0}, + 67: {"mass": 66.96424, "composition": 0.0}, + 68: {"mass": 67.96962, "composition": 0.0}, + 69: {"mass": 68.97366, "composition": 0.0}, + 70: {"mass": 69.97937, "composition": 0.0}, + 71: {"mass": 70.98368, "composition": 0.0}}, + 26: {45: {"mass": 45.01442, "composition": 0.0}, + 46: {"mass": 46.00063, "composition": 0.0}, + 47: {"mass": 46.99185, "composition": 0.0}, + 48: {"mass": 47.98023, "composition": 0.0}, + 49: {"mass": 48.973429, "composition": 0.0}, + 50: {"mass": 49.962975, "composition": 0.0}, + 51: {"mass": 50.956841, "composition": 0.0}, + 52: {"mass": 51.9481131, "composition": 0.0}, + 53: {"mass": 52.9453064, "composition": 0.0}, + 54: {"mass": 53.93960899, "composition": 0.05845}, + 55: {"mass": 54.93829199, "composition": 0.0}, + 56: {"mass": 55.93493633, "composition": 0.91754}, + 57: {"mass": 56.93539284, "composition": 0.02119}, + 58: {"mass": 57.93327443, "composition": 0.00282}, + 59: {"mass": 58.93487434, "composition": 0.0}, + 60: {"mass": 59.9340711, "composition": 0.0}, + 61: {"mass": 60.9367462, "composition": 0.0}, + 62: {"mass": 61.9367918, "composition": 0.0}, + 63: {"mass": 62.9402727, "composition": 0.0}, + 64: {"mass": 63.9409878, "composition": 0.0}, + 65: {"mass": 64.9450115, "composition": 0.0}, + 66: {"mass": 65.94625, "composition": 0.0}, + 67: {"mass": 66.95054, "composition": 0.0}, + 68: {"mass": 67.95295, "composition": 0.0}, + 69: {"mass": 68.95807, "composition": 0.0}, + 70: {"mass": 69.96102, "composition": 0.0}, + 71: {"mass": 70.96672, "composition": 0.0}, + 72: {"mass": 71.96983, "composition": 0.0}, + 73: {"mass": 72.97572, "composition": 0.0}, + 74: {"mass": 73.97935, "composition": 0.0}}, + 27: {47: {"mass": 47.01057, "composition": 0.0}, + 48: {"mass": 48.00093, "composition": 0.0}, + 49: {"mass": 48.98891, "composition": 0.0}, + 50: {"mass": 49.98091, "composition": 0.0}, + 51: {"mass": 50.970647, "composition": 0.0}, + 52: {"mass": 51.96351, "composition": 0.0}, + 53: {"mass": 52.9542041, "composition": 0.0}, + 54: {"mass": 53.94845987, "composition": 0.0}, + 55: {"mass": 54.9419972, "composition": 0.0}, + 56: {"mass": 55.9398388, "composition": 0.0}, + 57: {"mass": 56.93629057, "composition": 0.0}, + 58: {"mass": 57.9357521, "composition": 0.0}, + 59: {"mass": 58.93319429, "composition": 1.0}, + 60: {"mass": 59.9338163, "composition": 0.0}, + 61: {"mass": 60.93247662, "composition": 0.0}, + 62: {"mass": 61.934059, "composition": 0.0}, + 63: {"mass": 62.9336, "composition": 0.0}, + 64: {"mass": 63.935811, "composition": 0.0}, + 65: {"mass": 64.9364621, "composition": 0.0}, + 66: {"mass": 65.939443, "composition": 0.0}, + 67: {"mass": 66.9406096, "composition": 0.0}, + 68: {"mass": 67.94426, "composition": 0.0}, + 69: {"mass": 68.94614, "composition": 0.0}, + 70: {"mass": 69.94963, "composition": 0.0}, + 71: {"mass": 70.95237, "composition": 0.0}, + 72: {"mass": 71.95729, "composition": 0.0}, + 73: {"mass": 72.96039, "composition": 0.0}, + 74: {"mass": 73.96515, "composition": 0.0}, + 75: {"mass": 74.96876, "composition": 0.0}, + 76: {"mass": 75.97413, "composition": 0.0}}, + 28: {48: {"mass": 48.01769, "composition": 0.0}, + 49: {"mass": 49.0077, "composition": 0.0}, + 50: {"mass": 49.99474, "composition": 0.0}, + 51: {"mass": 50.98611, "composition": 0.0}, + 52: {"mass": 51.9748, "composition": 0.0}, + 53: {"mass": 52.96819, "composition": 0.0}, + 54: {"mass": 53.957892, "composition": 0.0}, + 55: {"mass": 54.95133063, "composition": 0.0}, + 56: {"mass": 55.94212855, "composition": 0.0}, + 57: {"mass": 56.93979218, "composition": 0.0}, + 58: {"mass": 57.93534241, "composition": 0.68077}, + 59: {"mass": 58.9343462, "composition": 0.0}, + 60: {"mass": 59.93078588, "composition": 0.26223}, + 61: {"mass": 60.93105557, "composition": 0.011399}, + 62: {"mass": 61.92834537, "composition": 0.036346}, + 63: {"mass": 62.92966963, "composition": 0.0}, + 64: {"mass": 63.92796682, "composition": 0.009255}, + 65: {"mass": 64.93008517, "composition": 0.0}, + 66: {"mass": 65.9291393, "composition": 0.0}, + 67: {"mass": 66.9315694, "composition": 0.0}, + 68: {"mass": 67.9318688, "composition": 0.0}, + 69: {"mass": 68.9356103, "composition": 0.0}, + 70: {"mass": 69.9364313, "composition": 0.0}, + 71: {"mass": 70.940519, "composition": 0.0}, + 72: {"mass": 71.9417859, "composition": 0.0}, + 73: {"mass": 72.9462067, "composition": 0.0}, + 74: {"mass": 73.94798, "composition": 0.0}, + 75: {"mass": 74.9525, "composition": 0.0}, + 76: {"mass": 75.95533, "composition": 0.0}, + 77: {"mass": 76.96055, "composition": 0.0}, + 78: {"mass": 77.96336, "composition": 0.0}, + 79: {"mass": 78.97025, "composition": 0.0}}, + 29: {52: {"mass": 51.99671, "composition": 0.0}, + 53: {"mass": 52.98459, "composition": 0.0}, + 54: {"mass": 53.97666, "composition": 0.0}, + 55: {"mass": 54.96604, "composition": 0.0}, + 56: {"mass": 55.95895, "composition": 0.0}, + 57: {"mass": 56.9492125, "composition": 0.0}, + 58: {"mass": 57.94453305, "composition": 0.0}, + 59: {"mass": 58.93949748, "composition": 0.0}, + 60: {"mass": 59.9373645, "composition": 0.0}, + 61: {"mass": 60.9334576, "composition": 0.0}, + 62: {"mass": 61.93259541, "composition": 0.0}, + 63: {"mass": 62.92959772, "composition": 0.6915}, + 64: {"mass": 63.92976434, "composition": 0.0}, + 65: {"mass": 64.9277897, "composition": 0.3085}, + 66: {"mass": 65.92886903, "composition": 0.0}, + 67: {"mass": 66.9277303, "composition": 0.0}, + 68: {"mass": 67.9296109, "composition": 0.0}, + 69: {"mass": 68.9294293, "composition": 0.0}, + 70: {"mass": 69.9323921, "composition": 0.0}, + 71: {"mass": 70.9326768, "composition": 0.0}, + 72: {"mass": 71.9358203, "composition": 0.0}, + 73: {"mass": 72.9366744, "composition": 0.0}, + 74: {"mass": 73.9398749, "composition": 0.0}, + 75: {"mass": 74.9415226, "composition": 0.0}, + 76: {"mass": 75.945275, "composition": 0.0}, + 77: {"mass": 76.94792, "composition": 0.0}, + 78: {"mass": 77.95223, "composition": 0.0}, + 79: {"mass": 78.95502, "composition": 0.0}, + 80: {"mass": 79.96089, "composition": 0.0}, + 81: {"mass": 80.96587, "composition": 0.0}, + 82: {"mass": 81.97244, "composition": 0.0}}, + 30: {54: {"mass": 53.99204, "composition": 0.0}, + 55: {"mass": 54.98398, "composition": 0.0}, + 56: {"mass": 55.97254, "composition": 0.0}, + 57: {"mass": 56.96506, "composition": 0.0}, + 58: {"mass": 57.954591, "composition": 0.0}, + 59: {"mass": 58.94931266, "composition": 0.0}, + 60: {"mass": 59.9418421, "composition": 0.0}, + 61: {"mass": 60.939507, "composition": 0.0}, + 62: {"mass": 61.93433397, "composition": 0.0}, + 63: {"mass": 62.9332115, "composition": 0.0}, + 64: {"mass": 63.92914201, "composition": 0.4917}, + 65: {"mass": 64.92924077, "composition": 0.0}, + 66: {"mass": 65.92603381, "composition": 0.2773}, + 67: {"mass": 66.92712775, "composition": 0.0404}, + 68: {"mass": 67.92484455, "composition": 0.1845}, + 69: {"mass": 68.9265507, "composition": 0.0}, + 70: {"mass": 69.9253192, "composition": 0.0061}, + 71: {"mass": 70.9277196, "composition": 0.0}, + 72: {"mass": 71.9268428, "composition": 0.0}, + 73: {"mass": 72.9295826, "composition": 0.0}, + 74: {"mass": 73.9294073, "composition": 0.0}, + 75: {"mass": 74.9328402, "composition": 0.0}, + 76: {"mass": 75.933115, "composition": 0.0}, + 77: {"mass": 76.9368872, "composition": 0.0}, + 78: {"mass": 77.9382892, "composition": 0.0}, + 79: {"mass": 78.9426381, "composition": 0.0}, + 80: {"mass": 79.9445529, "composition": 0.0}, + 81: {"mass": 80.9504026, "composition": 0.0}, + 82: {"mass": 81.95426, "composition": 0.0}, + 83: {"mass": 82.96056, "composition": 0.0}, + 84: {"mass": 83.96521, "composition": 0.0}, + 85: {"mass": 84.97226, "composition": 0.0}}, + 31: {56: {"mass": 55.99536, "composition": 0.0}, + 57: {"mass": 56.9832, "composition": 0.0}, + 58: {"mass": 57.97478, "composition": 0.0}, + 59: {"mass": 58.96353, "composition": 0.0}, + 60: {"mass": 59.95729, "composition": 0.0}, + 61: {"mass": 60.949399, "composition": 0.0}, + 62: {"mass": 61.94419025, "composition": 0.0}, + 63: {"mass": 62.9392942, "composition": 0.0}, + 64: {"mass": 63.9368404, "composition": 0.0}, + 65: {"mass": 64.93273459, "composition": 0.0}, + 66: {"mass": 65.9315894, "composition": 0.0}, + 67: {"mass": 66.9282025, "composition": 0.0}, + 68: {"mass": 67.9279805, "composition": 0.0}, + 69: {"mass": 68.9255735, "composition": 0.60108}, + 70: {"mass": 69.9260219, "composition": 0.0}, + 71: {"mass": 70.92470258, "composition": 0.39892}, + 72: {"mass": 71.92636747, "composition": 0.0}, + 73: {"mass": 72.9251747, "composition": 0.0}, + 74: {"mass": 73.9269457, "composition": 0.0}, + 75: {"mass": 74.9265002, "composition": 0.0}, + 76: {"mass": 75.9288276, "composition": 0.0}, + 77: {"mass": 76.9291543, "composition": 0.0}, + 78: {"mass": 77.9316088, "composition": 0.0}, + 79: {"mass": 78.9328523, "composition": 0.0}, + 80: {"mass": 79.9364208, "composition": 0.0}, + 81: {"mass": 80.9381338, "composition": 0.0}, + 82: {"mass": 81.9431765, "composition": 0.0}, + 83: {"mass": 82.9471203, "composition": 0.0}, + 84: {"mass": 83.95246, "composition": 0.0}, + 85: {"mass": 84.95699, "composition": 0.0}, + 86: {"mass": 85.96301, "composition": 0.0}, + 87: {"mass": 86.96824, "composition": 0.0}}, + 32: {58: {"mass": 57.99172, "composition": 0.0}, + 59: {"mass": 58.98249, "composition": 0.0}, + 60: {"mass": 59.97036, "composition": 0.0}, + 61: {"mass": 60.96379, "composition": 0.0}, + 62: {"mass": 61.95502, "composition": 0.0}, + 63: {"mass": 62.949628, "composition": 0.0}, + 64: {"mass": 63.9416899, "composition": 0.0}, + 65: {"mass": 64.9393681, "composition": 0.0}, + 66: {"mass": 65.9338621, "composition": 0.0}, + 67: {"mass": 66.9327339, "composition": 0.0}, + 68: {"mass": 67.9280953, "composition": 0.0}, + 69: {"mass": 68.9279645, "composition": 0.0}, + 70: {"mass": 69.92424875, "composition": 0.2057}, + 71: {"mass": 70.92495233, "composition": 0.0}, + 72: {"mass": 71.922075826, "composition": 0.2745}, + 73: {"mass": 72.923458956, "composition": 0.0775}, + 74: {"mass": 73.921177761, "composition": 0.365}, + 75: {"mass": 74.92285837, "composition": 0.0}, + 76: {"mass": 75.921402726, "composition": 0.0773}, + 77: {"mass": 76.923549843, "composition": 0.0}, + 78: {"mass": 77.9228529, "composition": 0.0}, + 79: {"mass": 78.92536, "composition": 0.0}, + 80: {"mass": 79.9253508, "composition": 0.0}, + 81: {"mass": 80.9288329, "composition": 0.0}, + 82: {"mass": 81.929774, "composition": 0.0}, + 83: {"mass": 82.9345391, "composition": 0.0}, + 84: {"mass": 83.9375751, "composition": 0.0}, + 85: {"mass": 84.9429697, "composition": 0.0}, + 86: {"mass": 85.94658, "composition": 0.0}, + 87: {"mass": 86.95268, "composition": 0.0}, + 88: {"mass": 87.95691, "composition": 0.0}, + 89: {"mass": 88.96379, "composition": 0.0}, + 90: {"mass": 89.96863, "composition": 0.0}}, + 33: {60: {"mass": 59.99388, "composition": 0.0}, + 61: {"mass": 60.98112, "composition": 0.0}, + 62: {"mass": 61.97361, "composition": 0.0}, + 63: {"mass": 62.9639, "composition": 0.0}, + 64: {"mass": 63.95743, "composition": 0.0}, + 65: {"mass": 64.949611, "composition": 0.0}, + 66: {"mass": 65.9441488, "composition": 0.0}, + 67: {"mass": 66.93925111, "composition": 0.0}, + 68: {"mass": 67.9367741, "composition": 0.0}, + 69: {"mass": 68.932246, "composition": 0.0}, + 70: {"mass": 69.930926, "composition": 0.0}, + 71: {"mass": 70.9271138, "composition": 0.0}, + 72: {"mass": 71.9267523, "composition": 0.0}, + 73: {"mass": 72.9238291, "composition": 0.0}, + 74: {"mass": 73.9239286, "composition": 0.0}, + 75: {"mass": 74.92159457, "composition": 1.0}, + 76: {"mass": 75.92239202, "composition": 0.0}, + 77: {"mass": 76.9206476, "composition": 0.0}, + 78: {"mass": 77.921828, "composition": 0.0}, + 79: {"mass": 78.9209484, "composition": 0.0}, + 80: {"mass": 79.9224746, "composition": 0.0}, + 81: {"mass": 80.9221323, "composition": 0.0}, + 82: {"mass": 81.9247412, "composition": 0.0}, + 83: {"mass": 82.9252069, "composition": 0.0}, + 84: {"mass": 83.9293033, "composition": 0.0}, + 85: {"mass": 84.9321637, "composition": 0.0}, + 86: {"mass": 85.9367015, "composition": 0.0}, + 87: {"mass": 86.9402917, "composition": 0.0}, + 88: {"mass": 87.94555, "composition": 0.0}, + 89: {"mass": 88.94976, "composition": 0.0}, + 90: {"mass": 89.95563, "composition": 0.0}, + 91: {"mass": 90.96039, "composition": 0.0}, + 92: {"mass": 91.96674, "composition": 0.0}}, + 34: {64: {"mass": 63.97109, "composition": 0.0}, + 65: {"mass": 64.9644, "composition": 0.0}, + 66: {"mass": 65.95559, "composition": 0.0}, + 67: {"mass": 66.949994, "composition": 0.0}, + 68: {"mass": 67.94182524, "composition": 0.0}, + 69: {"mass": 68.9394148, "composition": 0.0}, + 70: {"mass": 69.9335155, "composition": 0.0}, + 71: {"mass": 70.9322094, "composition": 0.0}, + 72: {"mass": 71.9271405, "composition": 0.0}, + 73: {"mass": 72.9267549, "composition": 0.0}, + 74: {"mass": 73.922475934, "composition": 0.0089}, + 75: {"mass": 74.92252287, "composition": 0.0}, + 76: {"mass": 75.919213704, "composition": 0.0937}, + 77: {"mass": 76.919914154, "composition": 0.0763}, + 78: {"mass": 77.91730928, "composition": 0.2377}, + 79: {"mass": 78.91849929, "composition": 0.0}, + 80: {"mass": 79.9165218, "composition": 0.4961}, + 81: {"mass": 80.917993, "composition": 0.0}, + 82: {"mass": 81.9166995, "composition": 0.0873}, + 83: {"mass": 82.9191186, "composition": 0.0}, + 84: {"mass": 83.9184668, "composition": 0.0}, + 85: {"mass": 84.9222608, "composition": 0.0}, + 86: {"mass": 85.9243117, "composition": 0.0}, + 87: {"mass": 86.9286886, "composition": 0.0}, + 88: {"mass": 87.9314175, "composition": 0.0}, + 89: {"mass": 88.9366691, "composition": 0.0}, + 90: {"mass": 89.9401, "composition": 0.0}, + 91: {"mass": 90.94596, "composition": 0.0}, + 92: {"mass": 91.94984, "composition": 0.0}, + 93: {"mass": 92.95629, "composition": 0.0}, + 94: {"mass": 93.96049, "composition": 0.0}, + 95: {"mass": 94.9673, "composition": 0.0}}, + 35: {67: {"mass": 66.96465, "composition": 0.0}, + 68: {"mass": 67.95873, "composition": 0.0}, + 69: {"mass": 68.950497, "composition": 0.0}, + 70: {"mass": 69.944792, "composition": 0.0}, + 71: {"mass": 70.9393422, "composition": 0.0}, + 72: {"mass": 71.9365886, "composition": 0.0}, + 73: {"mass": 72.9316715, "composition": 0.0}, + 74: {"mass": 73.9299102, "composition": 0.0}, + 75: {"mass": 74.9258105, "composition": 0.0}, + 76: {"mass": 75.924542, "composition": 0.0}, + 77: {"mass": 76.9213792, "composition": 0.0}, + 78: {"mass": 77.9211459, "composition": 0.0}, + 79: {"mass": 78.9183376, "composition": 0.5069}, + 80: {"mass": 79.9185298, "composition": 0.0}, + 81: {"mass": 80.9162897, "composition": 0.4931}, + 82: {"mass": 81.9168032, "composition": 0.0}, + 83: {"mass": 82.9151756, "composition": 0.0}, + 84: {"mass": 83.916496, "composition": 0.0}, + 85: {"mass": 84.9156458, "composition": 0.0}, + 86: {"mass": 85.9188054, "composition": 0.0}, + 87: {"mass": 86.920674, "composition": 0.0}, + 88: {"mass": 87.9240833, "composition": 0.0}, + 89: {"mass": 88.9267046, "composition": 0.0}, + 90: {"mass": 89.9312928, "composition": 0.0}, + 91: {"mass": 90.9343986, "composition": 0.0}, + 92: {"mass": 91.9396316, "composition": 0.0}, + 93: {"mass": 92.94313, "composition": 0.0}, + 94: {"mass": 93.9489, "composition": 0.0}, + 95: {"mass": 94.95301, "composition": 0.0}, + 96: {"mass": 95.95903, "composition": 0.0}, + 97: {"mass": 96.96344, "composition": 0.0}, + 98: {"mass": 97.96946, "composition": 0.0}}, + 36: {69: {"mass": 68.96518, "composition": 0.0}, + 70: {"mass": 69.95604, "composition": 0.0}, + 71: {"mass": 70.95027, "composition": 0.0}, + 72: {"mass": 71.9420924, "composition": 0.0}, + 73: {"mass": 72.9392892, "composition": 0.0}, + 74: {"mass": 73.933084, "composition": 0.0}, + 75: {"mass": 74.9309457, "composition": 0.0}, + 76: {"mass": 75.9259103, "composition": 0.0}, + 77: {"mass": 76.92467, "composition": 0.0}, + 78: {"mass": 77.92036494, "composition": 0.00355}, + 79: {"mass": 78.9200829, "composition": 0.0}, + 80: {"mass": 79.91637808, "composition": 0.02286}, + 81: {"mass": 80.9165912, "composition": 0.0}, + 82: {"mass": 81.91348273, "composition": 0.11593}, + 83: {"mass": 82.91412716, "composition": 0.115}, + 84: {"mass": 83.9114977282, "composition": 0.56987}, + 85: {"mass": 84.9125273, "composition": 0.0}, + 86: {"mass": 85.9106106269, "composition": 0.17279}, + 87: {"mass": 86.91335476, "composition": 0.0}, + 88: {"mass": 87.9144479, "composition": 0.0}, + 89: {"mass": 88.9178355, "composition": 0.0}, + 90: {"mass": 89.9195279, "composition": 0.0}, + 91: {"mass": 90.9238063, "composition": 0.0}, + 92: {"mass": 91.9261731, "composition": 0.0}, + 93: {"mass": 92.9311472, "composition": 0.0}, + 94: {"mass": 93.93414, "composition": 0.0}, + 95: {"mass": 94.939711, "composition": 0.0}, + 96: {"mass": 95.943017, "composition": 0.0}, + 97: {"mass": 96.94909, "composition": 0.0}, + 98: {"mass": 97.95243, "composition": 0.0}, + 99: {"mass": 98.95839, "composition": 0.0}, + 100: {"mass": 99.96237, "composition": 0.0}, + 101: {"mass": 100.96873, "composition": 0.0}}, + 37: {71: {"mass": 70.96532, "composition": 0.0}, + 72: {"mass": 71.95908, "composition": 0.0}, + 73: {"mass": 72.95053, "composition": 0.0}, + 74: {"mass": 73.9442659, "composition": 0.0}, + 75: {"mass": 74.9385732, "composition": 0.0}, + 76: {"mass": 75.935073, "composition": 0.0}, + 77: {"mass": 76.9304016, "composition": 0.0}, + 78: {"mass": 77.9281419, "composition": 0.0}, + 79: {"mass": 78.9239899, "composition": 0.0}, + 80: {"mass": 79.9225164, "composition": 0.0}, + 81: {"mass": 80.9189939, "composition": 0.0}, + 82: {"mass": 81.918209, "composition": 0.0}, + 83: {"mass": 82.9151142, "composition": 0.0}, + 84: {"mass": 83.9143752, "composition": 0.0}, + 85: {"mass": 84.9117897379, "composition": 0.7217}, + 86: {"mass": 85.91116743, "composition": 0.0}, + 87: {"mass": 86.909180531, "composition": 0.2783}, + 88: {"mass": 87.91131559, "composition": 0.0}, + 89: {"mass": 88.9122783, "composition": 0.0}, + 90: {"mass": 89.9147985, "composition": 0.0}, + 91: {"mass": 90.9165372, "composition": 0.0}, + 92: {"mass": 91.9197284, "composition": 0.0}, + 93: {"mass": 92.9220393, "composition": 0.0}, + 94: {"mass": 93.9263948, "composition": 0.0}, + 95: {"mass": 94.92926, "composition": 0.0}, + 96: {"mass": 95.9341334, "composition": 0.0}, + 97: {"mass": 96.9371771, "composition": 0.0}, + 98: {"mass": 97.9416869, "composition": 0.0}, + 99: {"mass": 98.94503, "composition": 0.0}, + 100: {"mass": 99.95003, "composition": 0.0}, + 101: {"mass": 100.95404, "composition": 0.0}, + 102: {"mass": 101.95952, "composition": 0.0}, + 103: {"mass": 102.96392, "composition": 0.0}}, + 38: {73: {"mass": 72.9657, "composition": 0.0}, + 74: {"mass": 73.95617, "composition": 0.0}, + 75: {"mass": 74.94995, "composition": 0.0}, + 76: {"mass": 75.941763, "composition": 0.0}, + 77: {"mass": 76.9379455, "composition": 0.0}, + 78: {"mass": 77.93218, "composition": 0.0}, + 79: {"mass": 78.9297077, "composition": 0.0}, + 80: {"mass": 79.9245175, "composition": 0.0}, + 81: {"mass": 80.9232114, "composition": 0.0}, + 82: {"mass": 81.9183999, "composition": 0.0}, + 83: {"mass": 82.9175544, "composition": 0.0}, + 84: {"mass": 83.9134191, "composition": 0.0056}, + 85: {"mass": 84.912932, "composition": 0.0}, + 86: {"mass": 85.9092606, "composition": 0.0986}, + 87: {"mass": 86.9088775, "composition": 0.07}, + 88: {"mass": 87.9056125, "composition": 0.8258}, + 89: {"mass": 88.9074511, "composition": 0.0}, + 90: {"mass": 89.90773, "composition": 0.0}, + 91: {"mass": 90.9101954, "composition": 0.0}, + 92: {"mass": 91.9110382, "composition": 0.0}, + 93: {"mass": 92.9140242, "composition": 0.0}, + 94: {"mass": 93.9153556, "composition": 0.0}, + 95: {"mass": 94.9193529, "composition": 0.0}, + 96: {"mass": 95.9217066, "composition": 0.0}, + 97: {"mass": 96.926374, "composition": 0.0}, + 98: {"mass": 97.9286888, "composition": 0.0}, + 99: {"mass": 98.9328907, "composition": 0.0}, + 100: {"mass": 99.93577, "composition": 0.0}, + 101: {"mass": 100.940352, "composition": 0.0}, + 102: {"mass": 101.943791, "composition": 0.0}, + 103: {"mass": 102.94909, "composition": 0.0}, + 104: {"mass": 103.95265, "composition": 0.0}, + 105: {"mass": 104.95855, "composition": 0.0}, + 106: {"mass": 105.96265, "composition": 0.0}, + 107: {"mass": 106.96897, "composition": 0.0}}, + 39: {76: {"mass": 75.95856, "composition": 0.0}, + 77: {"mass": 76.949781, "composition": 0.0}, + 78: {"mass": 77.94361, "composition": 0.0}, + 79: {"mass": 78.93735, "composition": 0.0}, + 80: {"mass": 79.9343561, "composition": 0.0}, + 81: {"mass": 80.9294556, "composition": 0.0}, + 82: {"mass": 81.9269314, "composition": 0.0}, + 83: {"mass": 82.922485, "composition": 0.0}, + 84: {"mass": 83.9206721, "composition": 0.0}, + 85: {"mass": 84.916433, "composition": 0.0}, + 86: {"mass": 85.914886, "composition": 0.0}, + 87: {"mass": 86.9108761, "composition": 0.0}, + 88: {"mass": 87.9095016, "composition": 0.0}, + 89: {"mass": 88.9058403, "composition": 1.0}, + 90: {"mass": 89.9071439, "composition": 0.0}, + 91: {"mass": 90.9072974, "composition": 0.0}, + 92: {"mass": 91.9089451, "composition": 0.0}, + 93: {"mass": 92.909578, "composition": 0.0}, + 94: {"mass": 93.9115906, "composition": 0.0}, + 95: {"mass": 94.9128161, "composition": 0.0}, + 96: {"mass": 95.9158968, "composition": 0.0}, + 97: {"mass": 96.9182741, "composition": 0.0}, + 98: {"mass": 97.9223821, "composition": 0.0}, + 99: {"mass": 98.924148, "composition": 0.0}, + 100: {"mass": 99.927715, "composition": 0.0}, + 101: {"mass": 100.9301477, "composition": 0.0}, + 102: {"mass": 101.9343277, "composition": 0.0}, + 103: {"mass": 102.937243, "composition": 0.0}, + 104: {"mass": 103.94196, "composition": 0.0}, + 105: {"mass": 104.94544, "composition": 0.0}, + 106: {"mass": 105.95056, "composition": 0.0}, + 107: {"mass": 106.95452, "composition": 0.0}, + 108: {"mass": 107.95996, "composition": 0.0}, + 109: {"mass": 108.96436, "composition": 0.0}}, + 40: {78: {"mass": 77.95566, "composition": 0.0}, + 79: {"mass": 78.94948, "composition": 0.0}, + 80: {"mass": 79.9404, "composition": 0.0}, + 81: {"mass": 80.93731, "composition": 0.0}, + 82: {"mass": 81.93135, "composition": 0.0}, + 83: {"mass": 82.9292421, "composition": 0.0}, + 84: {"mass": 83.9233269, "composition": 0.0}, + 85: {"mass": 84.9214444, "composition": 0.0}, + 86: {"mass": 85.9162972, "composition": 0.0}, + 87: {"mass": 86.914818, "composition": 0.0}, + 88: {"mass": 87.9102213, "composition": 0.0}, + 89: {"mass": 88.9088814, "composition": 0.0}, + 90: {"mass": 89.9046977, "composition": 0.5145}, + 91: {"mass": 90.9056396, "composition": 0.1122}, + 92: {"mass": 91.9050347, "composition": 0.1715}, + 93: {"mass": 92.9064699, "composition": 0.0}, + 94: {"mass": 93.9063108, "composition": 0.1738}, + 95: {"mass": 94.9080385, "composition": 0.0}, + 96: {"mass": 95.9082714, "composition": 0.028}, + 97: {"mass": 96.9109512, "composition": 0.0}, + 98: {"mass": 97.9127289, "composition": 0.0}, + 99: {"mass": 98.916667, "composition": 0.0}, + 100: {"mass": 99.9180006, "composition": 0.0}, + 101: {"mass": 100.921448, "composition": 0.0}, + 102: {"mass": 101.9231409, "composition": 0.0}, + 103: {"mass": 102.927191, "composition": 0.0}, + 104: {"mass": 103.929436, "composition": 0.0}, + 105: {"mass": 104.934008, "composition": 0.0}, + 106: {"mass": 105.93676, "composition": 0.0}, + 107: {"mass": 106.94174, "composition": 0.0}, + 108: {"mass": 107.94487, "composition": 0.0}, + 109: {"mass": 108.95041, "composition": 0.0}, + 110: {"mass": 109.95396, "composition": 0.0}, + 111: {"mass": 110.95968, "composition": 0.0}, + 112: {"mass": 111.9637, "composition": 0.0}}, + 41: {81: {"mass": 80.9496, "composition": 0.0}, + 82: {"mass": 81.94396, "composition": 0.0}, + 83: {"mass": 82.93729, "composition": 0.0}, + 84: {"mass": 83.93449, "composition": 0.0}, + 85: {"mass": 84.9288458, "composition": 0.0}, + 86: {"mass": 85.9257828, "composition": 0.0}, + 87: {"mass": 86.9206937, "composition": 0.0}, + 88: {"mass": 87.918222, "composition": 0.0}, + 89: {"mass": 88.913445, "composition": 0.0}, + 90: {"mass": 89.9112584, "composition": 0.0}, + 91: {"mass": 90.9069897, "composition": 0.0}, + 92: {"mass": 91.9071881, "composition": 0.0}, + 93: {"mass": 92.906373, "composition": 1.0}, + 94: {"mass": 93.9072788, "composition": 0.0}, + 95: {"mass": 94.9068324, "composition": 0.0}, + 96: {"mass": 95.9080973, "composition": 0.0}, + 97: {"mass": 96.9080959, "composition": 0.0}, + 98: {"mass": 97.9103265, "composition": 0.0}, + 99: {"mass": 98.911613, "composition": 0.0}, + 100: {"mass": 99.9143276, "composition": 0.0}, + 101: {"mass": 100.9153103, "composition": 0.0}, + 102: {"mass": 101.9180772, "composition": 0.0}, + 103: {"mass": 102.9194572, "composition": 0.0}, + 104: {"mass": 103.9228925, "composition": 0.0}, + 105: {"mass": 104.9249465, "composition": 0.0}, + 106: {"mass": 105.9289317, "composition": 0.0}, + 107: {"mass": 106.9315937, "composition": 0.0}, + 108: {"mass": 107.9360748, "composition": 0.0}, + 109: {"mass": 108.93922, "composition": 0.0}, + 110: {"mass": 109.94403, "composition": 0.0}, + 111: {"mass": 110.94753, "composition": 0.0}, + 112: {"mass": 111.95247, "composition": 0.0}, + 113: {"mass": 112.95651, "composition": 0.0}, + 114: {"mass": 113.96201, "composition": 0.0}, + 115: {"mass": 114.96634, "composition": 0.0}}, + 42: {83: {"mass": 82.94988, "composition": 0.0}, + 84: {"mass": 83.94149, "composition": 0.0}, + 85: {"mass": 84.938261, "composition": 0.0}, + 86: {"mass": 85.9311748, "composition": 0.0}, + 87: {"mass": 86.9281962, "composition": 0.0}, + 88: {"mass": 87.9219678, "composition": 0.0}, + 89: {"mass": 88.9194682, "composition": 0.0}, + 90: {"mass": 89.9139309, "composition": 0.0}, + 91: {"mass": 90.9117453, "composition": 0.0}, + 92: {"mass": 91.90680796, "composition": 0.1453}, + 93: {"mass": 92.90680958, "composition": 0.0}, + 94: {"mass": 93.9050849, "composition": 0.0915}, + 95: {"mass": 94.90583877, "composition": 0.1584}, + 96: {"mass": 95.90467612, "composition": 0.1667}, + 97: {"mass": 96.90601812, "composition": 0.096}, + 98: {"mass": 97.90540482, "composition": 0.2439}, + 99: {"mass": 98.90770851, "composition": 0.0}, + 100: {"mass": 99.9074718, "composition": 0.0982}, + 101: {"mass": 100.9103414, "composition": 0.0}, + 102: {"mass": 101.9102834, "composition": 0.0}, + 103: {"mass": 102.913079, "composition": 0.0}, + 104: {"mass": 103.9137344, "composition": 0.0}, + 105: {"mass": 104.916969, "composition": 0.0}, + 106: {"mass": 105.918259, "composition": 0.0}, + 107: {"mass": 106.922106, "composition": 0.0}, + 108: {"mass": 107.924033, "composition": 0.0}, + 109: {"mass": 108.928424, "composition": 0.0}, + 110: {"mass": 109.930704, "composition": 0.0}, + 111: {"mass": 110.935654, "composition": 0.0}, + 112: {"mass": 111.93831, "composition": 0.0}, + 113: {"mass": 112.94335, "composition": 0.0}, + 114: {"mass": 113.94653, "composition": 0.0}, + 115: {"mass": 114.95196, "composition": 0.0}, + 116: {"mass": 115.95545, "composition": 0.0}, + 117: {"mass": 116.96117, "composition": 0.0}}, + 43: {85: {"mass": 84.95058, "composition": 0.0}, + 86: {"mass": 85.94493, "composition": 0.0}, + 87: {"mass": 86.9380672, "composition": 0.0}, + 88: {"mass": 87.93378, "composition": 0.0}, + 89: {"mass": 88.9276487, "composition": 0.0}, + 90: {"mass": 89.9240739, "composition": 0.0}, + 91: {"mass": 90.9184254, "composition": 0.0}, + 92: {"mass": 91.9152698, "composition": 0.0}, + 93: {"mass": 92.910246, "composition": 0.0}, + 94: {"mass": 93.9096536, "composition": 0.0}, + 95: {"mass": 94.9076536, "composition": 0.0}, + 96: {"mass": 95.907868, "composition": 0.0}, + 97: {"mass": 96.9063667, "composition": 0.0}, + 98: {"mass": 97.9072124, "composition": 0.0}, + 99: {"mass": 98.9062508, "composition": 0.0}, + 100: {"mass": 99.9076539, "composition": 0.0}, + 101: {"mass": 100.907309, "composition": 0.0}, + 102: {"mass": 101.9092097, "composition": 0.0}, + 103: {"mass": 102.909176, "composition": 0.0}, + 104: {"mass": 103.911425, "composition": 0.0}, + 105: {"mass": 104.911655, "composition": 0.0}, + 106: {"mass": 105.914358, "composition": 0.0}, + 107: {"mass": 106.9154606, "composition": 0.0}, + 108: {"mass": 107.9184957, "composition": 0.0}, + 109: {"mass": 108.920256, "composition": 0.0}, + 110: {"mass": 109.923744, "composition": 0.0}, + 111: {"mass": 110.925901, "composition": 0.0}, + 112: {"mass": 111.9299458, "composition": 0.0}, + 113: {"mass": 112.932569, "composition": 0.0}, + 114: {"mass": 113.93691, "composition": 0.0}, + 115: {"mass": 114.93998, "composition": 0.0}, + 116: {"mass": 115.94476, "composition": 0.0}, + 117: {"mass": 116.94806, "composition": 0.0}, + 118: {"mass": 117.95299, "composition": 0.0}, + 119: {"mass": 118.95666, "composition": 0.0}, + 120: {"mass": 119.96187, "composition": 0.0}}, + 44: {87: {"mass": 86.95069, "composition": 0.0}, + 88: {"mass": 87.9416, "composition": 0.0}, + 89: {"mass": 88.93762, "composition": 0.0}, + 90: {"mass": 89.9303444, "composition": 0.0}, + 91: {"mass": 90.9267419, "composition": 0.0}, + 92: {"mass": 91.9202344, "composition": 0.0}, + 93: {"mass": 92.9171044, "composition": 0.0}, + 94: {"mass": 93.9113429, "composition": 0.0}, + 95: {"mass": 94.910406, "composition": 0.0}, + 96: {"mass": 95.90759025, "composition": 0.0554}, + 97: {"mass": 96.9075471, "composition": 0.0}, + 98: {"mass": 97.9052868, "composition": 0.0187}, + 99: {"mass": 98.9059341, "composition": 0.1276}, + 100: {"mass": 99.9042143, "composition": 0.126}, + 101: {"mass": 100.9055769, "composition": 0.1706}, + 102: {"mass": 101.9043441, "composition": 0.3155}, + 103: {"mass": 102.9063186, "composition": 0.0}, + 104: {"mass": 103.9054275, "composition": 0.1862}, + 105: {"mass": 104.9077476, "composition": 0.0}, + 106: {"mass": 105.9073291, "composition": 0.0}, + 107: {"mass": 106.909972, "composition": 0.0}, + 108: {"mass": 107.910188, "composition": 0.0}, + 109: {"mass": 108.913326, "composition": 0.0}, + 110: {"mass": 109.9140407, "composition": 0.0}, + 111: {"mass": 110.91757, "composition": 0.0}, + 112: {"mass": 111.918809, "composition": 0.0}, + 113: {"mass": 112.922844, "composition": 0.0}, + 114: {"mass": 113.9246136, "composition": 0.0}, + 115: {"mass": 114.92882, "composition": 0.0}, + 116: {"mass": 115.9312192, "composition": 0.0}, + 117: {"mass": 116.9361, "composition": 0.0}, + 118: {"mass": 117.93853, "composition": 0.0}, + 119: {"mass": 118.94357, "composition": 0.0}, + 120: {"mass": 119.94631, "composition": 0.0}, + 121: {"mass": 120.95164, "composition": 0.0}, + 122: {"mass": 121.95447, "composition": 0.0}, + 123: {"mass": 122.95989, "composition": 0.0}, + 124: {"mass": 123.96305, "composition": 0.0}}, + 45: {89: {"mass": 88.95058, "composition": 0.0}, + 90: {"mass": 89.94422, "composition": 0.0}, + 91: {"mass": 90.93688, "composition": 0.0}, + 92: {"mass": 91.9323677, "composition": 0.0}, + 93: {"mass": 92.9259128, "composition": 0.0}, + 94: {"mass": 93.9217305, "composition": 0.0}, + 95: {"mass": 94.9158979, "composition": 0.0}, + 96: {"mass": 95.914453, "composition": 0.0}, + 97: {"mass": 96.911329, "composition": 0.0}, + 98: {"mass": 97.910708, "composition": 0.0}, + 99: {"mass": 98.9081282, "composition": 0.0}, + 100: {"mass": 99.908117, "composition": 0.0}, + 101: {"mass": 100.9061606, "composition": 0.0}, + 102: {"mass": 101.9068374, "composition": 0.0}, + 103: {"mass": 102.905498, "composition": 1.0}, + 104: {"mass": 103.9066492, "composition": 0.0}, + 105: {"mass": 104.9056885, "composition": 0.0}, + 106: {"mass": 105.9072868, "composition": 0.0}, + 107: {"mass": 106.906748, "composition": 0.0}, + 108: {"mass": 107.908714, "composition": 0.0}, + 109: {"mass": 108.9087488, "composition": 0.0}, + 110: {"mass": 109.911079, "composition": 0.0}, + 111: {"mass": 110.9116423, "composition": 0.0}, + 112: {"mass": 111.914403, "composition": 0.0}, + 113: {"mass": 112.9154393, "composition": 0.0}, + 114: {"mass": 113.918718, "composition": 0.0}, + 115: {"mass": 114.9203116, "composition": 0.0}, + 116: {"mass": 115.924059, "composition": 0.0}, + 117: {"mass": 116.9260354, "composition": 0.0}, + 118: {"mass": 117.93034, "composition": 0.0}, + 119: {"mass": 118.932557, "composition": 0.0}, + 120: {"mass": 119.93686, "composition": 0.0}, + 121: {"mass": 120.93942, "composition": 0.0}, + 122: {"mass": 121.94399, "composition": 0.0}, + 123: {"mass": 122.94685, "composition": 0.0}, + 124: {"mass": 123.95151, "composition": 0.0}, + 125: {"mass": 124.95469, "composition": 0.0}, + 126: {"mass": 125.95946, "composition": 0.0}}, + 46: {91: {"mass": 90.95032, "composition": 0.0}, + 92: {"mass": 91.94088, "composition": 0.0}, + 93: {"mass": 92.93651, "composition": 0.0}, + 94: {"mass": 93.9290376, "composition": 0.0}, + 95: {"mass": 94.9248898, "composition": 0.0}, + 96: {"mass": 95.9182151, "composition": 0.0}, + 97: {"mass": 96.916472, "composition": 0.0}, + 98: {"mass": 97.9126983, "composition": 0.0}, + 99: {"mass": 98.9117748, "composition": 0.0}, + 100: {"mass": 99.908505, "composition": 0.0}, + 101: {"mass": 100.9082864, "composition": 0.0}, + 102: {"mass": 101.9056022, "composition": 0.0102}, + 103: {"mass": 102.9060809, "composition": 0.0}, + 104: {"mass": 103.9040305, "composition": 0.1114}, + 105: {"mass": 104.9050796, "composition": 0.2233}, + 106: {"mass": 105.9034804, "composition": 0.2733}, + 107: {"mass": 106.9051282, "composition": 0.0}, + 108: {"mass": 107.9038916, "composition": 0.2646}, + 109: {"mass": 108.9059504, "composition": 0.0}, + 110: {"mass": 109.9051722, "composition": 0.1172}, + 111: {"mass": 110.90768968, "composition": 0.0}, + 112: {"mass": 111.9073297, "composition": 0.0}, + 113: {"mass": 112.910261, "composition": 0.0}, + 114: {"mass": 113.9103686, "composition": 0.0}, + 115: {"mass": 114.913659, "composition": 0.0}, + 116: {"mass": 115.914297, "composition": 0.0}, + 117: {"mass": 116.9179547, "composition": 0.0}, + 118: {"mass": 117.9190667, "composition": 0.0}, + 119: {"mass": 118.9233402, "composition": 0.0}, + 120: {"mass": 119.9245511, "composition": 0.0}, + 121: {"mass": 120.9289503, "composition": 0.0}, + 122: {"mass": 121.930632, "composition": 0.0}, + 123: {"mass": 122.93514, "composition": 0.0}, + 124: {"mass": 123.93714, "composition": 0.0}, + 125: {"mass": 124.94179, "composition": 0.0}, + 126: {"mass": 125.94416, "composition": 0.0}, + 127: {"mass": 126.94907, "composition": 0.0}, + 128: {"mass": 127.95183, "composition": 0.0}}, + 47: {93: {"mass": 92.95033, "composition": 0.0}, + 94: {"mass": 93.94373, "composition": 0.0}, + 95: {"mass": 94.93602, "composition": 0.0}, + 96: {"mass": 95.930744, "composition": 0.0}, + 97: {"mass": 96.92397, "composition": 0.0}, + 98: {"mass": 97.92156, "composition": 0.0}, + 99: {"mass": 98.9176458, "composition": 0.0}, + 100: {"mass": 99.9161154, "composition": 0.0}, + 101: {"mass": 100.912684, "composition": 0.0}, + 102: {"mass": 101.9117047, "composition": 0.0}, + 103: {"mass": 102.9089631, "composition": 0.0}, + 104: {"mass": 103.9086239, "composition": 0.0}, + 105: {"mass": 104.9065256, "composition": 0.0}, + 106: {"mass": 105.9066636, "composition": 0.0}, + 107: {"mass": 106.9050916, "composition": 0.51839}, + 108: {"mass": 107.9059503, "composition": 0.0}, + 109: {"mass": 108.9047553, "composition": 0.48161}, + 110: {"mass": 109.9061102, "composition": 0.0}, + 111: {"mass": 110.9052959, "composition": 0.0}, + 112: {"mass": 111.9070486, "composition": 0.0}, + 113: {"mass": 112.906573, "composition": 0.0}, + 114: {"mass": 113.908823, "composition": 0.0}, + 115: {"mass": 114.908767, "composition": 0.0}, + 116: {"mass": 115.9113868, "composition": 0.0}, + 117: {"mass": 116.911774, "composition": 0.0}, + 118: {"mass": 117.9145955, "composition": 0.0}, + 119: {"mass": 118.91557, "composition": 0.0}, + 120: {"mass": 119.9187848, "composition": 0.0}, + 121: {"mass": 120.920125, "composition": 0.0}, + 122: {"mass": 121.923664, "composition": 0.0}, + 123: {"mass": 122.925337, "composition": 0.0}, + 124: {"mass": 123.92893, "composition": 0.0}, + 125: {"mass": 124.93105, "composition": 0.0}, + 126: {"mass": 125.93475, "composition": 0.0}, + 127: {"mass": 126.93711, "composition": 0.0}, + 128: {"mass": 127.94106, "composition": 0.0}, + 129: {"mass": 128.94395, "composition": 0.0}, + 130: {"mass": 129.9507, "composition": 0.0}}, + 48: {95: {"mass": 94.94994, "composition": 0.0}, + 96: {"mass": 95.94034, "composition": 0.0}, + 97: {"mass": 96.9351, "composition": 0.0}, + 98: {"mass": 97.927389, "composition": 0.0}, + 99: {"mass": 98.9249258, "composition": 0.0}, + 100: {"mass": 99.9203488, "composition": 0.0}, + 101: {"mass": 100.9185862, "composition": 0.0}, + 102: {"mass": 101.914482, "composition": 0.0}, + 103: {"mass": 102.9134165, "composition": 0.0}, + 104: {"mass": 103.9098564, "composition": 0.0}, + 105: {"mass": 104.9094639, "composition": 0.0}, + 106: {"mass": 105.9064599, "composition": 0.0125}, + 107: {"mass": 106.9066121, "composition": 0.0}, + 108: {"mass": 107.9041834, "composition": 0.0089}, + 109: {"mass": 108.9049867, "composition": 0.0}, + 110: {"mass": 109.90300661, "composition": 0.1249}, + 111: {"mass": 110.90418287, "composition": 0.128}, + 112: {"mass": 111.90276287, "composition": 0.2413}, + 113: {"mass": 112.90440813, "composition": 0.1222}, + 114: {"mass": 113.90336509, "composition": 0.2873}, + 115: {"mass": 114.90543751, "composition": 0.0}, + 116: {"mass": 115.90476315, "composition": 0.0749}, + 117: {"mass": 116.907226, "composition": 0.0}, + 118: {"mass": 117.906922, "composition": 0.0}, + 119: {"mass": 118.909847, "composition": 0.0}, + 120: {"mass": 119.9098681, "composition": 0.0}, + 121: {"mass": 120.9129637, "composition": 0.0}, + 122: {"mass": 121.9134591, "composition": 0.0}, + 123: {"mass": 122.9168925, "composition": 0.0}, + 124: {"mass": 123.9176574, "composition": 0.0}, + 125: {"mass": 124.9212576, "composition": 0.0}, + 126: {"mass": 125.9224291, "composition": 0.0}, + 127: {"mass": 126.926472, "composition": 0.0}, + 128: {"mass": 127.9278129, "composition": 0.0}, + 129: {"mass": 128.93182, "composition": 0.0}, + 130: {"mass": 129.93394, "composition": 0.0}, + 131: {"mass": 130.9406, "composition": 0.0}, + 132: {"mass": 131.94604, "composition": 0.0}, + 133: {"mass": 132.95285, "composition": 0.0}}, + 49: {97: {"mass": 96.94934, "composition": 0.0}, + 98: {"mass": 97.94214, "composition": 0.0}, + 99: {"mass": 98.93411, "composition": 0.0}, + 100: {"mass": 99.93096, "composition": 0.0}, + 101: {"mass": 100.92634, "composition": 0.0}, + 102: {"mass": 101.9241071, "composition": 0.0}, + 103: {"mass": 102.9198819, "composition": 0.0}, + 104: {"mass": 103.9182145, "composition": 0.0}, + 105: {"mass": 104.914502, "composition": 0.0}, + 106: {"mass": 105.913464, "composition": 0.0}, + 107: {"mass": 106.91029, "composition": 0.0}, + 108: {"mass": 107.9096935, "composition": 0.0}, + 109: {"mass": 108.9071514, "composition": 0.0}, + 110: {"mass": 109.90717, "composition": 0.0}, + 111: {"mass": 110.9051085, "composition": 0.0}, + 112: {"mass": 111.9055377, "composition": 0.0}, + 113: {"mass": 112.90406184, "composition": 0.0429}, + 114: {"mass": 113.90491791, "composition": 0.0}, + 115: {"mass": 114.903878776, "composition": 0.9571}, + 116: {"mass": 115.90525999, "composition": 0.0}, + 117: {"mass": 116.9045157, "composition": 0.0}, + 118: {"mass": 117.9063566, "composition": 0.0}, + 119: {"mass": 118.9058507, "composition": 0.0}, + 120: {"mass": 119.907967, "composition": 0.0}, + 121: {"mass": 120.907851, "composition": 0.0}, + 122: {"mass": 121.910281, "composition": 0.0}, + 123: {"mass": 122.910434, "composition": 0.0}, + 124: {"mass": 123.913182, "composition": 0.0}, + 125: {"mass": 124.913605, "composition": 0.0}, + 126: {"mass": 125.916507, "composition": 0.0}, + 127: {"mass": 126.917446, "composition": 0.0}, + 128: {"mass": 127.9204, "composition": 0.0}, + 129: {"mass": 128.9218053, "composition": 0.0}, + 130: {"mass": 129.924977, "composition": 0.0}, + 131: {"mass": 130.9269715, "composition": 0.0}, + 132: {"mass": 131.933001, "composition": 0.0}, + 133: {"mass": 132.93831, "composition": 0.0}, + 134: {"mass": 133.94454, "composition": 0.0}, + 135: {"mass": 134.95005, "composition": 0.0}}, + 50: {99: {"mass": 98.94853, "composition": 0.0}, + 100: {"mass": 99.9385, "composition": 0.0}, + 101: {"mass": 100.93526, "composition": 0.0}, + 102: {"mass": 101.93029, "composition": 0.0}, + 103: {"mass": 102.928105, "composition": 0.0}, + 104: {"mass": 103.9231052, "composition": 0.0}, + 105: {"mass": 104.9212684, "composition": 0.0}, + 106: {"mass": 105.9169574, "composition": 0.0}, + 107: {"mass": 106.9157137, "composition": 0.0}, + 108: {"mass": 107.9118943, "composition": 0.0}, + 109: {"mass": 108.9112921, "composition": 0.0}, + 110: {"mass": 109.907845, "composition": 0.0}, + 111: {"mass": 110.9077401, "composition": 0.0}, + 112: {"mass": 111.90482387, "composition": 0.0097}, + 113: {"mass": 112.9051757, "composition": 0.0}, + 114: {"mass": 113.9027827, "composition": 0.0066}, + 115: {"mass": 114.903344699, "composition": 0.0034}, + 116: {"mass": 115.9017428, "composition": 0.1454}, + 117: {"mass": 116.90295398, "composition": 0.0768}, + 118: {"mass": 117.90160657, "composition": 0.2422}, + 119: {"mass": 118.90331117, "composition": 0.0859}, + 120: {"mass": 119.90220163, "composition": 0.3258}, + 121: {"mass": 120.9042426, "composition": 0.0}, + 122: {"mass": 121.9034438, "composition": 0.0463}, + 123: {"mass": 122.9057252, "composition": 0.0}, + 124: {"mass": 123.9052766, "composition": 0.0579}, + 125: {"mass": 124.9077864, "composition": 0.0}, + 126: {"mass": 125.907659, "composition": 0.0}, + 127: {"mass": 126.91039, "composition": 0.0}, + 128: {"mass": 127.910507, "composition": 0.0}, + 129: {"mass": 128.913465, "composition": 0.0}, + 130: {"mass": 129.9139738, "composition": 0.0}, + 131: {"mass": 130.917045, "composition": 0.0}, + 132: {"mass": 131.9178267, "composition": 0.0}, + 133: {"mass": 132.9239134, "composition": 0.0}, + 134: {"mass": 133.9286821, "composition": 0.0}, + 135: {"mass": 134.9349086, "composition": 0.0}, + 136: {"mass": 135.93999, "composition": 0.0}, + 137: {"mass": 136.94655, "composition": 0.0}, + 138: {"mass": 137.95184, "composition": 0.0}}, + 51: {103: {"mass": 102.93969, "composition": 0.0}, + 104: {"mass": 103.93648, "composition": 0.0}, + 105: {"mass": 104.931276, "composition": 0.0}, + 106: {"mass": 105.928638, "composition": 0.0}, + 107: {"mass": 106.9241506, "composition": 0.0}, + 108: {"mass": 107.9222267, "composition": 0.0}, + 109: {"mass": 108.9181411, "composition": 0.0}, + 110: {"mass": 109.9168543, "composition": 0.0}, + 111: {"mass": 110.9132182, "composition": 0.0}, + 112: {"mass": 111.9124, "composition": 0.0}, + 113: {"mass": 112.909375, "composition": 0.0}, + 114: {"mass": 113.90929, "composition": 0.0}, + 115: {"mass": 114.906598, "composition": 0.0}, + 116: {"mass": 115.9067931, "composition": 0.0}, + 117: {"mass": 116.9048415, "composition": 0.0}, + 118: {"mass": 117.9055321, "composition": 0.0}, + 119: {"mass": 118.9039455, "composition": 0.0}, + 120: {"mass": 119.9050794, "composition": 0.0}, + 121: {"mass": 120.903812, "composition": 0.5721}, + 122: {"mass": 121.9051699, "composition": 0.0}, + 123: {"mass": 122.9042132, "composition": 0.4279}, + 124: {"mass": 123.905935, "composition": 0.0}, + 125: {"mass": 124.905253, "composition": 0.0}, + 126: {"mass": 125.907253, "composition": 0.0}, + 127: {"mass": 126.9069243, "composition": 0.0}, + 128: {"mass": 127.909146, "composition": 0.0}, + 129: {"mass": 128.909147, "composition": 0.0}, + 130: {"mass": 129.911662, "composition": 0.0}, + 131: {"mass": 130.9119888, "composition": 0.0}, + 132: {"mass": 131.9145077, "composition": 0.0}, + 133: {"mass": 132.9152732, "composition": 0.0}, + 134: {"mass": 133.9205357, "composition": 0.0}, + 135: {"mass": 134.9251851, "composition": 0.0}, + 136: {"mass": 135.9307459, "composition": 0.0}, + 137: {"mass": 136.93555, "composition": 0.0}, + 138: {"mass": 137.94145, "composition": 0.0}, + 139: {"mass": 138.94655, "composition": 0.0}, + 140: {"mass": 139.95283, "composition": 0.0}}, + 52: {105: {"mass": 104.9433, "composition": 0.0}, + 106: {"mass": 105.9375, "composition": 0.0}, + 107: {"mass": 106.935012, "composition": 0.0}, + 108: {"mass": 107.9293805, "composition": 0.0}, + 109: {"mass": 108.9273045, "composition": 0.0}, + 110: {"mass": 109.9224581, "composition": 0.0}, + 111: {"mass": 110.9210006, "composition": 0.0}, + 112: {"mass": 111.9167279, "composition": 0.0}, + 113: {"mass": 112.915891, "composition": 0.0}, + 114: {"mass": 113.912089, "composition": 0.0}, + 115: {"mass": 114.911902, "composition": 0.0}, + 116: {"mass": 115.90846, "composition": 0.0}, + 117: {"mass": 116.908646, "composition": 0.0}, + 118: {"mass": 117.905854, "composition": 0.0}, + 119: {"mass": 118.9064071, "composition": 0.0}, + 120: {"mass": 119.9040593, "composition": 0.0009}, + 121: {"mass": 120.904944, "composition": 0.0}, + 122: {"mass": 121.9030435, "composition": 0.0255}, + 123: {"mass": 122.9042698, "composition": 0.0089}, + 124: {"mass": 123.9028171, "composition": 0.0474}, + 125: {"mass": 124.9044299, "composition": 0.0707}, + 126: {"mass": 125.9033109, "composition": 0.1884}, + 127: {"mass": 126.9052257, "composition": 0.0}, + 128: {"mass": 127.90446128, "composition": 0.3174}, + 129: {"mass": 128.90659646, "composition": 0.0}, + 130: {"mass": 129.906222748, "composition": 0.3408}, + 131: {"mass": 130.908522213, "composition": 0.0}, + 132: {"mass": 131.9085467, "composition": 0.0}, + 133: {"mass": 132.9109688, "composition": 0.0}, + 134: {"mass": 133.911394, "composition": 0.0}, + 135: {"mass": 134.9165557, "composition": 0.0}, + 136: {"mass": 135.9201006, "composition": 0.0}, + 137: {"mass": 136.9255989, "composition": 0.0}, + 138: {"mass": 137.9294722, "composition": 0.0}, + 139: {"mass": 138.9353672, "composition": 0.0}, + 140: {"mass": 139.939499, "composition": 0.0}, + 141: {"mass": 140.9458, "composition": 0.0}, + 142: {"mass": 141.95022, "composition": 0.0}, + 143: {"mass": 142.95676, "composition": 0.0}}, + 53: {107: {"mass": 106.94678, "composition": 0.0}, + 108: {"mass": 107.94348, "composition": 0.0}, + 109: {"mass": 108.9380853, "composition": 0.0}, + 110: {"mass": 109.935089, "composition": 0.0}, + 111: {"mass": 110.9302692, "composition": 0.0}, + 112: {"mass": 111.928005, "composition": 0.0}, + 113: {"mass": 112.9236501, "composition": 0.0}, + 114: {"mass": 113.92185, "composition": 0.0}, + 115: {"mass": 114.918048, "composition": 0.0}, + 116: {"mass": 115.91681, "composition": 0.0}, + 117: {"mass": 116.913648, "composition": 0.0}, + 118: {"mass": 117.913074, "composition": 0.0}, + 119: {"mass": 118.910074, "composition": 0.0}, + 120: {"mass": 119.910087, "composition": 0.0}, + 121: {"mass": 120.9074051, "composition": 0.0}, + 122: {"mass": 121.9075888, "composition": 0.0}, + 123: {"mass": 122.9055885, "composition": 0.0}, + 124: {"mass": 123.906209, "composition": 0.0}, + 125: {"mass": 124.9046294, "composition": 0.0}, + 126: {"mass": 125.9056233, "composition": 0.0}, + 127: {"mass": 126.9044719, "composition": 1.0}, + 128: {"mass": 127.9058086, "composition": 0.0}, + 129: {"mass": 128.9049837, "composition": 0.0}, + 130: {"mass": 129.9066702, "composition": 0.0}, + 131: {"mass": 130.9061263, "composition": 0.0}, + 132: {"mass": 131.9079935, "composition": 0.0}, + 133: {"mass": 132.907797, "composition": 0.0}, + 134: {"mass": 133.9097588, "composition": 0.0}, + 135: {"mass": 134.9100488, "composition": 0.0}, + 136: {"mass": 135.914604, "composition": 0.0}, + 137: {"mass": 136.9180282, "composition": 0.0}, + 138: {"mass": 137.9227264, "composition": 0.0}, + 139: {"mass": 138.926506, "composition": 0.0}, + 140: {"mass": 139.93173, "composition": 0.0}, + 141: {"mass": 140.93569, "composition": 0.0}, + 142: {"mass": 141.9412, "composition": 0.0}, + 143: {"mass": 142.94565, "composition": 0.0}, + 144: {"mass": 143.95139, "composition": 0.0}, + 145: {"mass": 144.95605, "composition": 0.0}}, + 54: {109: {"mass": 108.95043, "composition": 0.0}, + 110: {"mass": 109.94426, "composition": 0.0}, + 111: {"mass": 110.941607, "composition": 0.0}, + 112: {"mass": 111.935559, "composition": 0.0}, + 113: {"mass": 112.9332217, "composition": 0.0}, + 114: {"mass": 113.92798, "composition": 0.0}, + 115: {"mass": 114.926294, "composition": 0.0}, + 116: {"mass": 115.921581, "composition": 0.0}, + 117: {"mass": 116.920359, "composition": 0.0}, + 118: {"mass": 117.916179, "composition": 0.0}, + 119: {"mass": 118.915411, "composition": 0.0}, + 120: {"mass": 119.911784, "composition": 0.0}, + 121: {"mass": 120.911453, "composition": 0.0}, + 122: {"mass": 121.908368, "composition": 0.0}, + 123: {"mass": 122.908482, "composition": 0.0}, + 124: {"mass": 123.905892, "composition": 0.000952}, + 125: {"mass": 124.9063944, "composition": 0.0}, + 126: {"mass": 125.9042983, "composition": 0.00089}, + 127: {"mass": 126.9051829, "composition": 0.0}, + 128: {"mass": 127.903531, "composition": 0.019102}, + 129: {"mass": 128.9047808611, "composition": 0.264006}, + 130: {"mass": 129.903509349, "composition": 0.04071}, + 131: {"mass": 130.90508406, "composition": 0.212324}, + 132: {"mass": 131.9041550856, "composition": 0.269086}, + 133: {"mass": 132.9059108, "composition": 0.0}, + 134: {"mass": 133.90539466, "composition": 0.104357}, + 135: {"mass": 134.9072278, "composition": 0.0}, + 136: {"mass": 135.907214484, "composition": 0.088573}, + 137: {"mass": 136.91155778, "composition": 0.0}, + 138: {"mass": 137.9141463, "composition": 0.0}, + 139: {"mass": 138.9187922, "composition": 0.0}, + 140: {"mass": 139.9216458, "composition": 0.0}, + 141: {"mass": 140.9267872, "composition": 0.0}, + 142: {"mass": 141.9299731, "composition": 0.0}, + 143: {"mass": 142.9353696, "composition": 0.0}, + 144: {"mass": 143.9389451, "composition": 0.0}, + 145: {"mass": 144.94472, "composition": 0.0}, + 146: {"mass": 145.948518, "composition": 0.0}, + 147: {"mass": 146.95426, "composition": 0.0}, + 148: {"mass": 147.95813, "composition": 0.0}}, + 55: {112: {"mass": 111.950309, "composition": 0.0}, + 113: {"mass": 112.9444291, "composition": 0.0}, + 114: {"mass": 113.941296, "composition": 0.0}, + 115: {"mass": 114.93591, "composition": 0.0}, + 116: {"mass": 115.93337, "composition": 0.0}, + 117: {"mass": 116.928617, "composition": 0.0}, + 118: {"mass": 117.92656, "composition": 0.0}, + 119: {"mass": 118.922377, "composition": 0.0}, + 120: {"mass": 119.920677, "composition": 0.0}, + 121: {"mass": 120.917227, "composition": 0.0}, + 122: {"mass": 121.916108, "composition": 0.0}, + 123: {"mass": 122.912996, "composition": 0.0}, + 124: {"mass": 123.9122578, "composition": 0.0}, + 125: {"mass": 124.909728, "composition": 0.0}, + 126: {"mass": 125.909446, "composition": 0.0}, + 127: {"mass": 126.9074174, "composition": 0.0}, + 128: {"mass": 127.9077487, "composition": 0.0}, + 129: {"mass": 128.9060657, "composition": 0.0}, + 130: {"mass": 129.9067093, "composition": 0.0}, + 131: {"mass": 130.9054649, "composition": 0.0}, + 132: {"mass": 131.9064339, "composition": 0.0}, + 133: {"mass": 132.905451961, "composition": 1.0}, + 134: {"mass": 133.906718503, "composition": 0.0}, + 135: {"mass": 134.905977, "composition": 0.0}, + 136: {"mass": 135.9073114, "composition": 0.0}, + 137: {"mass": 136.90708923, "composition": 0.0}, + 138: {"mass": 137.9110171, "composition": 0.0}, + 139: {"mass": 138.9133638, "composition": 0.0}, + 140: {"mass": 139.9172831, "composition": 0.0}, + 141: {"mass": 140.9200455, "composition": 0.0}, + 142: {"mass": 141.924296, "composition": 0.0}, + 143: {"mass": 142.927349, "composition": 0.0}, + 144: {"mass": 143.932076, "composition": 0.0}, + 145: {"mass": 144.935527, "composition": 0.0}, + 146: {"mass": 145.940344, "composition": 0.0}, + 147: {"mass": 146.944156, "composition": 0.0}, + 148: {"mass": 147.94923, "composition": 0.0}, + 149: {"mass": 148.95302, "composition": 0.0}, + 150: {"mass": 149.95833, "composition": 0.0}, + 151: {"mass": 150.96258, "composition": 0.0}}, + 56: {114: {"mass": 113.95066, "composition": 0.0}, + 115: {"mass": 114.94737, "composition": 0.0}, + 116: {"mass": 115.94128, "composition": 0.0}, + 117: {"mass": 116.93814, "composition": 0.0}, + 118: {"mass": 117.93306, "composition": 0.0}, + 119: {"mass": 118.93066, "composition": 0.0}, + 120: {"mass": 119.92605, "composition": 0.0}, + 121: {"mass": 120.92405, "composition": 0.0}, + 122: {"mass": 121.919904, "composition": 0.0}, + 123: {"mass": 122.918781, "composition": 0.0}, + 124: {"mass": 123.915094, "composition": 0.0}, + 125: {"mass": 124.914472, "composition": 0.0}, + 126: {"mass": 125.91125, "composition": 0.0}, + 127: {"mass": 126.911091, "composition": 0.0}, + 128: {"mass": 127.908342, "composition": 0.0}, + 129: {"mass": 128.908681, "composition": 0.0}, + 130: {"mass": 129.9063207, "composition": 0.00106}, + 131: {"mass": 130.906941, "composition": 0.0}, + 132: {"mass": 131.9050611, "composition": 0.00101}, + 133: {"mass": 132.9060074, "composition": 0.0}, + 134: {"mass": 133.90450818, "composition": 0.02417}, + 135: {"mass": 134.90568838, "composition": 0.06592}, + 136: {"mass": 135.90457573, "composition": 0.07854}, + 137: {"mass": 136.90582714, "composition": 0.11232}, + 138: {"mass": 137.905247, "composition": 0.71698}, + 139: {"mass": 138.9088411, "composition": 0.0}, + 140: {"mass": 139.9106057, "composition": 0.0}, + 141: {"mass": 140.9144033, "composition": 0.0}, + 142: {"mass": 141.9164324, "composition": 0.0}, + 143: {"mass": 142.9206253, "composition": 0.0}, + 144: {"mass": 143.9229549, "composition": 0.0}, + 145: {"mass": 144.9275184, "composition": 0.0}, + 146: {"mass": 145.930284, "composition": 0.0}, + 147: {"mass": 146.935304, "composition": 0.0}, + 148: {"mass": 147.938171, "composition": 0.0}, + 149: {"mass": 148.94308, "composition": 0.0}, + 150: {"mass": 149.94605, "composition": 0.0}, + 151: {"mass": 150.95127, "composition": 0.0}, + 152: {"mass": 151.95481, "composition": 0.0}, + 153: {"mass": 152.96036, "composition": 0.0}}, + 57: {116: {"mass": 115.9563, "composition": 0.0}, + 117: {"mass": 116.94999, "composition": 0.0}, + 118: {"mass": 117.94673, "composition": 0.0}, + 119: {"mass": 118.94099, "composition": 0.0}, + 120: {"mass": 119.93807, "composition": 0.0}, + 121: {"mass": 120.93315, "composition": 0.0}, + 122: {"mass": 121.93071, "composition": 0.0}, + 123: {"mass": 122.9263, "composition": 0.0}, + 124: {"mass": 123.924574, "composition": 0.0}, + 125: {"mass": 124.920816, "composition": 0.0}, + 126: {"mass": 125.919513, "composition": 0.0}, + 127: {"mass": 126.916375, "composition": 0.0}, + 128: {"mass": 127.915592, "composition": 0.0}, + 129: {"mass": 128.912694, "composition": 0.0}, + 130: {"mass": 129.912369, "composition": 0.0}, + 131: {"mass": 130.91007, "composition": 0.0}, + 132: {"mass": 131.910119, "composition": 0.0}, + 133: {"mass": 132.908218, "composition": 0.0}, + 134: {"mass": 133.908514, "composition": 0.0}, + 135: {"mass": 134.906984, "composition": 0.0}, + 136: {"mass": 135.907635, "composition": 0.0}, + 137: {"mass": 136.9064504, "composition": 0.0}, + 138: {"mass": 137.9071149, "composition": 0.0008881}, + 139: {"mass": 138.9063563, "composition": 0.9991119}, + 140: {"mass": 139.9094806, "composition": 0.0}, + 141: {"mass": 140.910966, "composition": 0.0}, + 142: {"mass": 141.9140909, "composition": 0.0}, + 143: {"mass": 142.9160795, "composition": 0.0}, + 144: {"mass": 143.919646, "composition": 0.0}, + 145: {"mass": 144.921808, "composition": 0.0}, + 146: {"mass": 145.925875, "composition": 0.0}, + 147: {"mass": 146.928418, "composition": 0.0}, + 148: {"mass": 147.932679, "composition": 0.0}, + 149: {"mass": 148.93535, "composition": 0.0}, + 150: {"mass": 149.93947, "composition": 0.0}, + 151: {"mass": 150.94232, "composition": 0.0}, + 152: {"mass": 151.94682, "composition": 0.0}, + 153: {"mass": 152.95036, "composition": 0.0}, + 154: {"mass": 153.95517, "composition": 0.0}, + 155: {"mass": 154.95901, "composition": 0.0}}, + 58: {119: {"mass": 118.95271, "composition": 0.0}, + 120: {"mass": 119.94654, "composition": 0.0}, + 121: {"mass": 120.94335, "composition": 0.0}, + 122: {"mass": 121.93787, "composition": 0.0}, + 123: {"mass": 122.93528, "composition": 0.0}, + 124: {"mass": 123.93031, "composition": 0.0}, + 125: {"mass": 124.92844, "composition": 0.0}, + 126: {"mass": 125.923971, "composition": 0.0}, + 127: {"mass": 126.922727, "composition": 0.0}, + 128: {"mass": 127.918911, "composition": 0.0}, + 129: {"mass": 128.918102, "composition": 0.0}, + 130: {"mass": 129.914736, "composition": 0.0}, + 131: {"mass": 130.914429, "composition": 0.0}, + 132: {"mass": 131.911464, "composition": 0.0}, + 133: {"mass": 132.91152, "composition": 0.0}, + 134: {"mass": 133.908928, "composition": 0.0}, + 135: {"mass": 134.909161, "composition": 0.0}, + 136: {"mass": 135.90712921, "composition": 0.00185}, + 137: {"mass": 136.90776236, "composition": 0.0}, + 138: {"mass": 137.905991, "composition": 0.00251}, + 139: {"mass": 138.9066551, "composition": 0.0}, + 140: {"mass": 139.9054431, "composition": 0.8845}, + 141: {"mass": 140.9082807, "composition": 0.0}, + 142: {"mass": 141.9092504, "composition": 0.11114}, + 143: {"mass": 142.9123921, "composition": 0.0}, + 144: {"mass": 143.9136529, "composition": 0.0}, + 145: {"mass": 144.917265, "composition": 0.0}, + 146: {"mass": 145.918802, "composition": 0.0}, + 147: {"mass": 146.9226899, "composition": 0.0}, + 148: {"mass": 147.924424, "composition": 0.0}, + 149: {"mass": 148.928427, "composition": 0.0}, + 150: {"mass": 149.930384, "composition": 0.0}, + 151: {"mass": 150.934272, "composition": 0.0}, + 152: {"mass": 151.9366, "composition": 0.0}, + 153: {"mass": 152.94093, "composition": 0.0}, + 154: {"mass": 153.9438, "composition": 0.0}, + 155: {"mass": 154.94855, "composition": 0.0}, + 156: {"mass": 155.95183, "composition": 0.0}, + 157: {"mass": 156.95705, "composition": 0.0}}, + 59: {121: {"mass": 120.95532, "composition": 0.0}, + 122: {"mass": 121.95175, "composition": 0.0}, + 123: {"mass": 122.94596, "composition": 0.0}, + 124: {"mass": 123.94294, "composition": 0.0}, + 125: {"mass": 124.9377, "composition": 0.0}, + 126: {"mass": 125.93524, "composition": 0.0}, + 127: {"mass": 126.93071, "composition": 0.0}, + 128: {"mass": 127.928791, "composition": 0.0}, + 129: {"mass": 128.925095, "composition": 0.0}, + 130: {"mass": 129.92359, "composition": 0.0}, + 131: {"mass": 130.920235, "composition": 0.0}, + 132: {"mass": 131.919255, "composition": 0.0}, + 133: {"mass": 132.916331, "composition": 0.0}, + 134: {"mass": 133.915697, "composition": 0.0}, + 135: {"mass": 134.913112, "composition": 0.0}, + 136: {"mass": 135.912677, "composition": 0.0}, + 137: {"mass": 136.9106792, "composition": 0.0}, + 138: {"mass": 137.910754, "composition": 0.0}, + 139: {"mass": 138.9089408, "composition": 0.0}, + 140: {"mass": 139.9090803, "composition": 0.0}, + 141: {"mass": 140.9076576, "composition": 1.0}, + 142: {"mass": 141.9100496, "composition": 0.0}, + 143: {"mass": 142.9108228, "composition": 0.0}, + 144: {"mass": 143.9133109, "composition": 0.0}, + 145: {"mass": 144.9145182, "composition": 0.0}, + 146: {"mass": 145.91768, "composition": 0.0}, + 147: {"mass": 146.919008, "composition": 0.0}, + 148: {"mass": 147.92213, "composition": 0.0}, + 149: {"mass": 148.923736, "composition": 0.0}, + 150: {"mass": 149.9266765, "composition": 0.0}, + 151: {"mass": 150.928309, "composition": 0.0}, + 152: {"mass": 151.931553, "composition": 0.0}, + 153: {"mass": 152.933904, "composition": 0.0}, + 154: {"mass": 153.93753, "composition": 0.0}, + 155: {"mass": 154.940509, "composition": 0.0}, + 156: {"mass": 155.94464, "composition": 0.0}, + 157: {"mass": 156.94789, "composition": 0.0}, + 158: {"mass": 157.95241, "composition": 0.0}, + 159: {"mass": 158.95589, "composition": 0.0}}, + 60: {124: {"mass": 123.9522, "composition": 0.0}, + 125: {"mass": 124.9489, "composition": 0.0}, + 126: {"mass": 125.94311, "composition": 0.0}, + 127: {"mass": 126.94038, "composition": 0.0}, + 128: {"mass": 127.93525, "composition": 0.0}, + 129: {"mass": 128.9331, "composition": 0.0}, + 130: {"mass": 129.928506, "composition": 0.0}, + 131: {"mass": 130.927248, "composition": 0.0}, + 132: {"mass": 131.923321, "composition": 0.0}, + 133: {"mass": 132.922348, "composition": 0.0}, + 134: {"mass": 133.91879, "composition": 0.0}, + 135: {"mass": 134.918181, "composition": 0.0}, + 136: {"mass": 135.914976, "composition": 0.0}, + 137: {"mass": 136.914562, "composition": 0.0}, + 138: {"mass": 137.91195, "composition": 0.0}, + 139: {"mass": 138.911954, "composition": 0.0}, + 140: {"mass": 139.90955, "composition": 0.0}, + 141: {"mass": 140.9096147, "composition": 0.0}, + 142: {"mass": 141.907729, "composition": 0.27152}, + 143: {"mass": 142.90982, "composition": 0.12174}, + 144: {"mass": 143.910093, "composition": 0.23798}, + 145: {"mass": 144.9125793, "composition": 0.08293}, + 146: {"mass": 145.9131226, "composition": 0.17189}, + 147: {"mass": 146.9161061, "composition": 0.0}, + 148: {"mass": 147.9168993, "composition": 0.05756}, + 149: {"mass": 148.9201548, "composition": 0.0}, + 150: {"mass": 149.9209022, "composition": 0.05638}, + 151: {"mass": 150.9238403, "composition": 0.0}, + 152: {"mass": 151.924692, "composition": 0.0}, + 153: {"mass": 152.927718, "composition": 0.0}, + 154: {"mass": 153.92948, "composition": 0.0}, + 155: {"mass": 154.9331357, "composition": 0.0}, + 156: {"mass": 155.93508, "composition": 0.0}, + 157: {"mass": 156.939386, "composition": 0.0}, + 158: {"mass": 157.94197, "composition": 0.0}, + 159: {"mass": 158.94653, "composition": 0.0}, + 160: {"mass": 159.9494, "composition": 0.0}, + 161: {"mass": 160.95428, "composition": 0.0}}, + 61: {126: {"mass": 125.95792, "composition": 0.0}, + 127: {"mass": 126.95192, "composition": 0.0}, + 128: {"mass": 127.9487, "composition": 0.0}, + 129: {"mass": 128.94323, "composition": 0.0}, + 130: {"mass": 129.94053, "composition": 0.0}, + 131: {"mass": 130.93567, "composition": 0.0}, + 132: {"mass": 131.93384, "composition": 0.0}, + 133: {"mass": 132.929782, "composition": 0.0}, + 134: {"mass": 133.928353, "composition": 0.0}, + 135: {"mass": 134.924823, "composition": 0.0}, + 136: {"mass": 135.923585, "composition": 0.0}, + 137: {"mass": 136.92048, "composition": 0.0}, + 138: {"mass": 137.919548, "composition": 0.0}, + 139: {"mass": 138.9168, "composition": 0.0}, + 140: {"mass": 139.91604, "composition": 0.0}, + 141: {"mass": 140.913555, "composition": 0.0}, + 142: {"mass": 141.91289, "composition": 0.0}, + 143: {"mass": 142.9109383, "composition": 0.0}, + 144: {"mass": 143.9125964, "composition": 0.0}, + 145: {"mass": 144.9127559, "composition": 0.0}, + 146: {"mass": 145.9147024, "composition": 0.0}, + 147: {"mass": 146.915145, "composition": 0.0}, + 148: {"mass": 147.9174819, "composition": 0.0}, + 149: {"mass": 148.9183423, "composition": 0.0}, + 150: {"mass": 149.920991, "composition": 0.0}, + 151: {"mass": 150.9212175, "composition": 0.0}, + 152: {"mass": 151.923506, "composition": 0.0}, + 153: {"mass": 152.9241567, "composition": 0.0}, + 154: {"mass": 153.926472, "composition": 0.0}, + 155: {"mass": 154.928137, "composition": 0.0}, + 156: {"mass": 155.9311175, "composition": 0.0}, + 157: {"mass": 156.9331214, "composition": 0.0}, + 158: {"mass": 157.936565, "composition": 0.0}, + 159: {"mass": 158.939287, "composition": 0.0}, + 160: {"mass": 159.9431, "composition": 0.0}, + 161: {"mass": 160.94607, "composition": 0.0}, + 162: {"mass": 161.95022, "composition": 0.0}, + 163: {"mass": 162.95357, "composition": 0.0}}, + 62: {128: {"mass": 127.95842, "composition": 0.0}, + 129: {"mass": 128.95476, "composition": 0.0}, + 130: {"mass": 129.949, "composition": 0.0}, + 131: {"mass": 130.94618, "composition": 0.0}, + 132: {"mass": 131.94087, "composition": 0.0}, + 133: {"mass": 132.93856, "composition": 0.0}, + 134: {"mass": 133.93411, "composition": 0.0}, + 135: {"mass": 134.93252, "composition": 0.0}, + 136: {"mass": 135.928276, "composition": 0.0}, + 137: {"mass": 136.926971, "composition": 0.0}, + 138: {"mass": 137.923244, "composition": 0.0}, + 139: {"mass": 138.922297, "composition": 0.0}, + 140: {"mass": 139.918995, "composition": 0.0}, + 141: {"mass": 140.9184816, "composition": 0.0}, + 142: {"mass": 141.9152044, "composition": 0.0}, + 143: {"mass": 142.9146353, "composition": 0.0}, + 144: {"mass": 143.9120065, "composition": 0.0307}, + 145: {"mass": 144.9134173, "composition": 0.0}, + 146: {"mass": 145.913047, "composition": 0.0}, + 147: {"mass": 146.9149044, "composition": 0.1499}, + 148: {"mass": 147.9148292, "composition": 0.1124}, + 149: {"mass": 148.9171921, "composition": 0.1382}, + 150: {"mass": 149.9172829, "composition": 0.0738}, + 151: {"mass": 150.9199398, "composition": 0.0}, + 152: {"mass": 151.9197397, "composition": 0.2675}, + 153: {"mass": 152.9221047, "composition": 0.0}, + 154: {"mass": 153.9222169, "composition": 0.2275}, + 155: {"mass": 154.9246477, "composition": 0.0}, + 156: {"mass": 155.925536, "composition": 0.0}, + 157: {"mass": 156.9284187, "composition": 0.0}, + 158: {"mass": 157.929951, "composition": 0.0}, + 159: {"mass": 158.9332172, "composition": 0.0}, + 160: {"mass": 159.9353353, "composition": 0.0}, + 161: {"mass": 160.9391602, "composition": 0.0}, + 162: {"mass": 161.94146, "composition": 0.0}, + 163: {"mass": 162.94555, "composition": 0.0}, + 164: {"mass": 163.94836, "composition": 0.0}, + 165: {"mass": 164.95297, "composition": 0.0}}, + 63: {130: {"mass": 129.96369, "composition": 0.0}, + 131: {"mass": 130.95784, "composition": 0.0}, + 132: {"mass": 131.95467, "composition": 0.0}, + 133: {"mass": 132.94929, "composition": 0.0}, + 134: {"mass": 133.9464, "composition": 0.0}, + 135: {"mass": 134.94187, "composition": 0.0}, + 136: {"mass": 135.93962, "composition": 0.0}, + 137: {"mass": 136.93546, "composition": 0.0}, + 138: {"mass": 137.933709, "composition": 0.0}, + 139: {"mass": 138.929792, "composition": 0.0}, + 140: {"mass": 139.928088, "composition": 0.0}, + 141: {"mass": 140.924932, "composition": 0.0}, + 142: {"mass": 141.923442, "composition": 0.0}, + 143: {"mass": 142.920299, "composition": 0.0}, + 144: {"mass": 143.91882, "composition": 0.0}, + 145: {"mass": 144.9162726, "composition": 0.0}, + 146: {"mass": 145.917211, "composition": 0.0}, + 147: {"mass": 146.9167527, "composition": 0.0}, + 148: {"mass": 147.918089, "composition": 0.0}, + 149: {"mass": 148.9179378, "composition": 0.0}, + 150: {"mass": 149.9197077, "composition": 0.0}, + 151: {"mass": 150.9198578, "composition": 0.4781}, + 152: {"mass": 151.9217522, "composition": 0.0}, + 153: {"mass": 152.921238, "composition": 0.5219}, + 154: {"mass": 153.922987, "composition": 0.0}, + 155: {"mass": 154.9229011, "composition": 0.0}, + 156: {"mass": 155.9247605, "composition": 0.0}, + 157: {"mass": 156.9254334, "composition": 0.0}, + 158: {"mass": 157.927799, "composition": 0.0}, + 159: {"mass": 158.9291001, "composition": 0.0}, + 160: {"mass": 159.931851, "composition": 0.0}, + 161: {"mass": 160.933664, "composition": 0.0}, + 162: {"mass": 161.936989, "composition": 0.0}, + 163: {"mass": 162.939196, "composition": 0.0}, + 164: {"mass": 163.94274, "composition": 0.0}, + 165: {"mass": 164.94559, "composition": 0.0}, + 166: {"mass": 165.94962, "composition": 0.0}, + 167: {"mass": 166.95289, "composition": 0.0}}, + 64: {133: {"mass": 132.96133, "composition": 0.0}, + 134: {"mass": 133.95566, "composition": 0.0}, + 135: {"mass": 134.95245, "composition": 0.0}, + 136: {"mass": 135.9473, "composition": 0.0}, + 137: {"mass": 136.94502, "composition": 0.0}, + 138: {"mass": 137.94025, "composition": 0.0}, + 139: {"mass": 138.93813, "composition": 0.0}, + 140: {"mass": 139.933674, "composition": 0.0}, + 141: {"mass": 140.932126, "composition": 0.0}, + 142: {"mass": 141.928116, "composition": 0.0}, + 143: {"mass": 142.92675, "composition": 0.0}, + 144: {"mass": 143.922963, "composition": 0.0}, + 145: {"mass": 144.921713, "composition": 0.0}, + 146: {"mass": 145.9183188, "composition": 0.0}, + 147: {"mass": 146.9191014, "composition": 0.0}, + 148: {"mass": 147.9181215, "composition": 0.0}, + 149: {"mass": 148.9193481, "composition": 0.0}, + 150: {"mass": 149.9186644, "composition": 0.0}, + 151: {"mass": 150.920356, "composition": 0.0}, + 152: {"mass": 151.9197995, "composition": 0.002}, + 153: {"mass": 152.921758, "composition": 0.0}, + 154: {"mass": 153.9208741, "composition": 0.0218}, + 155: {"mass": 154.9226305, "composition": 0.148}, + 156: {"mass": 155.9221312, "composition": 0.2047}, + 157: {"mass": 156.9239686, "composition": 0.1565}, + 158: {"mass": 157.9241123, "composition": 0.2484}, + 159: {"mass": 158.926397, "composition": 0.0}, + 160: {"mass": 159.9270624, "composition": 0.2186}, + 161: {"mass": 160.9296775, "composition": 0.0}, + 162: {"mass": 161.930993, "composition": 0.0}, + 163: {"mass": 162.9341769, "composition": 0.0}, + 164: {"mass": 163.93583, "composition": 0.0}, + 165: {"mass": 164.93936, "composition": 0.0}, + 166: {"mass": 165.94146, "composition": 0.0}, + 167: {"mass": 166.94545, "composition": 0.0}, + 168: {"mass": 167.94808, "composition": 0.0}, + 169: {"mass": 168.9526, "composition": 0.0}}, + 65: {135: {"mass": 134.96476, "composition": 0.0}, + 136: {"mass": 135.96129, "composition": 0.0}, + 137: {"mass": 136.95602, "composition": 0.0}, + 138: {"mass": 137.95312, "composition": 0.0}, + 139: {"mass": 138.94833, "composition": 0.0}, + 140: {"mass": 139.94581, "composition": 0.0}, + 141: {"mass": 140.94145, "composition": 0.0}, + 142: {"mass": 141.93928, "composition": 0.0}, + 143: {"mass": 142.935137, "composition": 0.0}, + 144: {"mass": 143.933045, "composition": 0.0}, + 145: {"mass": 144.92882, "composition": 0.0}, + 146: {"mass": 145.927253, "composition": 0.0}, + 147: {"mass": 146.9240548, "composition": 0.0}, + 148: {"mass": 147.924282, "composition": 0.0}, + 149: {"mass": 148.9232535, "composition": 0.0}, + 150: {"mass": 149.9236649, "composition": 0.0}, + 151: {"mass": 150.9231096, "composition": 0.0}, + 152: {"mass": 151.924083, "composition": 0.0}, + 153: {"mass": 152.9234424, "composition": 0.0}, + 154: {"mass": 153.924685, "composition": 0.0}, + 155: {"mass": 154.923511, "composition": 0.0}, + 156: {"mass": 155.9247552, "composition": 0.0}, + 157: {"mass": 156.924033, "composition": 0.0}, + 158: {"mass": 157.9254209, "composition": 0.0}, + 159: {"mass": 158.9253547, "composition": 1.0}, + 160: {"mass": 159.9271756, "composition": 0.0}, + 161: {"mass": 160.9275778, "composition": 0.0}, + 162: {"mass": 161.929495, "composition": 0.0}, + 163: {"mass": 162.9306547, "composition": 0.0}, + 164: {"mass": 163.93336, "composition": 0.0}, + 165: {"mass": 164.93498, "composition": 0.0}, + 166: {"mass": 165.93786, "composition": 0.0}, + 167: {"mass": 166.93996, "composition": 0.0}, + 168: {"mass": 167.9434, "composition": 0.0}, + 169: {"mass": 168.94597, "composition": 0.0}, + 170: {"mass": 169.94984, "composition": 0.0}, + 171: {"mass": 170.95273, "composition": 0.0}}, + 66: {138: {"mass": 137.9625, "composition": 0.0}, + 139: {"mass": 138.95959, "composition": 0.0}, + 140: {"mass": 139.95402, "composition": 0.0}, + 141: {"mass": 140.95128, "composition": 0.0}, + 142: {"mass": 141.94619, "composition": 0.0}, + 143: {"mass": 142.943994, "composition": 0.0}, + 144: {"mass": 143.9392695, "composition": 0.0}, + 145: {"mass": 144.937474, "composition": 0.0}, + 146: {"mass": 145.9328445, "composition": 0.0}, + 147: {"mass": 146.9310827, "composition": 0.0}, + 148: {"mass": 147.927157, "composition": 0.0}, + 149: {"mass": 148.927322, "composition": 0.0}, + 150: {"mass": 149.9255933, "composition": 0.0}, + 151: {"mass": 150.9261916, "composition": 0.0}, + 152: {"mass": 151.9247253, "composition": 0.0}, + 153: {"mass": 152.9257724, "composition": 0.0}, + 154: {"mass": 153.9244293, "composition": 0.0}, + 155: {"mass": 154.925759, "composition": 0.0}, + 156: {"mass": 155.9242847, "composition": 0.00056}, + 157: {"mass": 156.9254707, "composition": 0.0}, + 158: {"mass": 157.9244159, "composition": 0.00095}, + 159: {"mass": 158.925747, "composition": 0.0}, + 160: {"mass": 159.9252046, "composition": 0.02329}, + 161: {"mass": 160.9269405, "composition": 0.18889}, + 162: {"mass": 161.9268056, "composition": 0.25475}, + 163: {"mass": 162.9287383, "composition": 0.24896}, + 164: {"mass": 163.9291819, "composition": 0.2826}, + 165: {"mass": 164.9317105, "composition": 0.0}, + 166: {"mass": 165.9328139, "composition": 0.0}, + 167: {"mass": 166.935661, "composition": 0.0}, + 168: {"mass": 167.93713, "composition": 0.0}, + 169: {"mass": 168.94031, "composition": 0.0}, + 170: {"mass": 169.94239, "composition": 0.0}, + 171: {"mass": 170.94612, "composition": 0.0}, + 172: {"mass": 171.94846, "composition": 0.0}, + 173: {"mass": 172.95283, "composition": 0.0}}, + 67: {140: {"mass": 139.96859, "composition": 0.0}, + 141: {"mass": 140.96311, "composition": 0.0}, + 142: {"mass": 141.96001, "composition": 0.0}, + 143: {"mass": 142.95486, "composition": 0.0}, + 144: {"mass": 143.9521097, "composition": 0.0}, + 145: {"mass": 144.9472674, "composition": 0.0}, + 146: {"mass": 145.9449935, "composition": 0.0}, + 147: {"mass": 146.9401423, "composition": 0.0}, + 148: {"mass": 147.937744, "composition": 0.0}, + 149: {"mass": 148.933803, "composition": 0.0}, + 150: {"mass": 149.933498, "composition": 0.0}, + 151: {"mass": 150.9316983, "composition": 0.0}, + 152: {"mass": 151.931724, "composition": 0.0}, + 153: {"mass": 152.9302064, "composition": 0.0}, + 154: {"mass": 153.9306068, "composition": 0.0}, + 155: {"mass": 154.929104, "composition": 0.0}, + 156: {"mass": 155.929706, "composition": 0.0}, + 157: {"mass": 156.928254, "composition": 0.0}, + 158: {"mass": 157.928946, "composition": 0.0}, + 159: {"mass": 158.9277197, "composition": 0.0}, + 160: {"mass": 159.928737, "composition": 0.0}, + 161: {"mass": 160.9278615, "composition": 0.0}, + 162: {"mass": 161.9291023, "composition": 0.0}, + 163: {"mass": 162.928741, "composition": 0.0}, + 164: {"mass": 163.9302403, "composition": 0.0}, + 165: {"mass": 164.9303288, "composition": 1.0}, + 166: {"mass": 165.9322909, "composition": 0.0}, + 167: {"mass": 166.9331385, "composition": 0.0}, + 168: {"mass": 167.935522, "composition": 0.0}, + 169: {"mass": 168.936878, "composition": 0.0}, + 170: {"mass": 169.939625, "composition": 0.0}, + 171: {"mass": 170.94147, "composition": 0.0}, + 172: {"mass": 171.94473, "composition": 0.0}, + 173: {"mass": 172.94702, "composition": 0.0}, + 174: {"mass": 173.95095, "composition": 0.0}, + 175: {"mass": 174.95362, "composition": 0.0}}, + 68: {142: {"mass": 141.9701, "composition": 0.0}, + 143: {"mass": 142.96662, "composition": 0.0}, + 144: {"mass": 143.9607, "composition": 0.0}, + 145: {"mass": 144.95805, "composition": 0.0}, + 146: {"mass": 145.9524184, "composition": 0.0}, + 147: {"mass": 146.949964, "composition": 0.0}, + 148: {"mass": 147.944735, "composition": 0.0}, + 149: {"mass": 148.942306, "composition": 0.0}, + 150: {"mass": 149.937916, "composition": 0.0}, + 151: {"mass": 150.937449, "composition": 0.0}, + 152: {"mass": 151.935057, "composition": 0.0}, + 153: {"mass": 152.93508, "composition": 0.0}, + 154: {"mass": 153.9327908, "composition": 0.0}, + 155: {"mass": 154.9332159, "composition": 0.0}, + 156: {"mass": 155.931067, "composition": 0.0}, + 157: {"mass": 156.931949, "composition": 0.0}, + 158: {"mass": 157.929893, "composition": 0.0}, + 159: {"mass": 158.9306918, "composition": 0.0}, + 160: {"mass": 159.929077, "composition": 0.0}, + 161: {"mass": 160.9300046, "composition": 0.0}, + 162: {"mass": 161.9287884, "composition": 0.00139}, + 163: {"mass": 162.9300408, "composition": 0.0}, + 164: {"mass": 163.9292088, "composition": 0.01601}, + 165: {"mass": 164.9307345, "composition": 0.0}, + 166: {"mass": 165.9302995, "composition": 0.33503}, + 167: {"mass": 166.9320546, "composition": 0.22869}, + 168: {"mass": 167.9323767, "composition": 0.26978}, + 169: {"mass": 168.9345968, "composition": 0.0}, + 170: {"mass": 169.9354702, "composition": 0.1491}, + 171: {"mass": 170.9380357, "composition": 0.0}, + 172: {"mass": 171.9393619, "composition": 0.0}, + 173: {"mass": 172.9424, "composition": 0.0}, + 174: {"mass": 173.94423, "composition": 0.0}, + 175: {"mass": 174.94777, "composition": 0.0}, + 176: {"mass": 175.94994, "composition": 0.0}, + 177: {"mass": 176.95399, "composition": 0.0}}, + 69: {144: {"mass": 143.97628, "composition": 0.0}, + 145: {"mass": 144.97039, "composition": 0.0}, + 146: {"mass": 145.96684, "composition": 0.0}, + 147: {"mass": 146.9613799, "composition": 0.0}, + 148: {"mass": 147.958384, "composition": 0.0}, + 149: {"mass": 148.95289, "composition": 0.0}, + 150: {"mass": 149.95009, "composition": 0.0}, + 151: {"mass": 150.945488, "composition": 0.0}, + 152: {"mass": 151.944422, "composition": 0.0}, + 153: {"mass": 152.94204, "composition": 0.0}, + 154: {"mass": 153.94157, "composition": 0.0}, + 155: {"mass": 154.93921, "composition": 0.0}, + 156: {"mass": 155.938992, "composition": 0.0}, + 157: {"mass": 156.936944, "composition": 0.0}, + 158: {"mass": 157.93698, "composition": 0.0}, + 159: {"mass": 158.934975, "composition": 0.0}, + 160: {"mass": 159.935263, "composition": 0.0}, + 161: {"mass": 160.933549, "composition": 0.0}, + 162: {"mass": 161.934002, "composition": 0.0}, + 163: {"mass": 162.9326592, "composition": 0.0}, + 164: {"mass": 163.933544, "composition": 0.0}, + 165: {"mass": 164.9324431, "composition": 0.0}, + 166: {"mass": 165.933561, "composition": 0.0}, + 167: {"mass": 166.9328562, "composition": 0.0}, + 168: {"mass": 167.9341774, "composition": 0.0}, + 169: {"mass": 168.9342179, "composition": 1.0}, + 170: {"mass": 169.935806, "composition": 0.0}, + 171: {"mass": 170.9364339, "composition": 0.0}, + 172: {"mass": 171.9384055, "composition": 0.0}, + 173: {"mass": 172.9396084, "composition": 0.0}, + 174: {"mass": 173.942173, "composition": 0.0}, + 175: {"mass": 174.943841, "composition": 0.0}, + 176: {"mass": 175.947, "composition": 0.0}, + 177: {"mass": 176.94904, "composition": 0.0}, + 178: {"mass": 177.95264, "composition": 0.0}, + 179: {"mass": 178.95534, "composition": 0.0}}, + 70: {148: {"mass": 147.96758, "composition": 0.0}, + 149: {"mass": 148.96436, "composition": 0.0}, + 150: {"mass": 149.95852, "composition": 0.0}, + 151: {"mass": 150.9554, "composition": 0.0}, + 152: {"mass": 151.95027, "composition": 0.0}, + 153: {"mass": 152.94932, "composition": 0.0}, + 154: {"mass": 153.946396, "composition": 0.0}, + 155: {"mass": 154.945783, "composition": 0.0}, + 156: {"mass": 155.942825, "composition": 0.0}, + 157: {"mass": 156.942645, "composition": 0.0}, + 158: {"mass": 157.9398705, "composition": 0.0}, + 159: {"mass": 158.940055, "composition": 0.0}, + 160: {"mass": 159.937557, "composition": 0.0}, + 161: {"mass": 160.937907, "composition": 0.0}, + 162: {"mass": 161.935774, "composition": 0.0}, + 163: {"mass": 162.93634, "composition": 0.0}, + 164: {"mass": 163.934495, "composition": 0.0}, + 165: {"mass": 164.93527, "composition": 0.0}, + 166: {"mass": 165.9338747, "composition": 0.0}, + 167: {"mass": 166.934953, "composition": 0.0}, + 168: {"mass": 167.9338896, "composition": 0.00123}, + 169: {"mass": 168.9351825, "composition": 0.0}, + 170: {"mass": 169.9347664, "composition": 0.02982}, + 171: {"mass": 170.9363302, "composition": 0.1409}, + 172: {"mass": 171.9363859, "composition": 0.2168}, + 173: {"mass": 172.9382151, "composition": 0.16103}, + 174: {"mass": 173.9388664, "composition": 0.32026}, + 175: {"mass": 174.9412808, "composition": 0.0}, + 176: {"mass": 175.9425764, "composition": 0.12996}, + 177: {"mass": 176.9452656, "composition": 0.0}, + 178: {"mass": 177.946651, "composition": 0.0}, + 179: {"mass": 178.95004, "composition": 0.0}, + 180: {"mass": 179.95212, "composition": 0.0}, + 181: {"mass": 180.95589, "composition": 0.0}}, + 71: {150: {"mass": 149.97355, "composition": 0.0}, + 151: {"mass": 150.96768, "composition": 0.0}, + 152: {"mass": 151.96412, "composition": 0.0}, + 153: {"mass": 152.95875, "composition": 0.0}, + 154: {"mass": 153.95736, "composition": 0.0}, + 155: {"mass": 154.954321, "composition": 0.0}, + 156: {"mass": 155.953033, "composition": 0.0}, + 157: {"mass": 156.950127, "composition": 0.0}, + 158: {"mass": 157.949316, "composition": 0.0}, + 159: {"mass": 158.946636, "composition": 0.0}, + 160: {"mass": 159.946033, "composition": 0.0}, + 161: {"mass": 160.943572, "composition": 0.0}, + 162: {"mass": 161.943283, "composition": 0.0}, + 163: {"mass": 162.941179, "composition": 0.0}, + 164: {"mass": 163.941339, "composition": 0.0}, + 165: {"mass": 164.939407, "composition": 0.0}, + 166: {"mass": 165.939859, "composition": 0.0}, + 167: {"mass": 166.93827, "composition": 0.0}, + 168: {"mass": 167.938736, "composition": 0.0}, + 169: {"mass": 168.9376441, "composition": 0.0}, + 170: {"mass": 169.938478, "composition": 0.0}, + 171: {"mass": 170.937917, "composition": 0.0}, + 172: {"mass": 171.9390891, "composition": 0.0}, + 173: {"mass": 172.938934, "composition": 0.0}, + 174: {"mass": 173.9403409, "composition": 0.0}, + 175: {"mass": 174.9407752, "composition": 0.97401}, + 176: {"mass": 175.9426897, "composition": 0.02599}, + 177: {"mass": 176.9437615, "composition": 0.0}, + 178: {"mass": 177.945958, "composition": 0.0}, + 179: {"mass": 178.9473309, "composition": 0.0}, + 180: {"mass": 179.949888, "composition": 0.0}, + 181: {"mass": 180.95191, "composition": 0.0}, + 182: {"mass": 181.95504, "composition": 0.0}, + 183: {"mass": 182.957363, "composition": 0.0}, + 184: {"mass": 183.96091, "composition": 0.0}, + 185: {"mass": 184.96362, "composition": 0.0}}, + 72: {153: {"mass": 152.97069, "composition": 0.0}, + 154: {"mass": 153.96486, "composition": 0.0}, + 155: {"mass": 154.96311, "composition": 0.0}, + 156: {"mass": 155.95935, "composition": 0.0}, + 157: {"mass": 156.95824, "composition": 0.0}, + 158: {"mass": 157.954801, "composition": 0.0}, + 159: {"mass": 158.953996, "composition": 0.0}, + 160: {"mass": 159.950691, "composition": 0.0}, + 161: {"mass": 160.950278, "composition": 0.0}, + 162: {"mass": 161.9472148, "composition": 0.0}, + 163: {"mass": 162.947113, "composition": 0.0}, + 164: {"mass": 163.944371, "composition": 0.0}, + 165: {"mass": 164.944567, "composition": 0.0}, + 166: {"mass": 165.94218, "composition": 0.0}, + 167: {"mass": 166.9426, "composition": 0.0}, + 168: {"mass": 167.940568, "composition": 0.0}, + 169: {"mass": 168.941259, "composition": 0.0}, + 170: {"mass": 169.939609, "composition": 0.0}, + 171: {"mass": 170.940492, "composition": 0.0}, + 172: {"mass": 171.93945, "composition": 0.0}, + 173: {"mass": 172.940513, "composition": 0.0}, + 174: {"mass": 173.9400461, "composition": 0.0016}, + 175: {"mass": 174.9415092, "composition": 0.0}, + 176: {"mass": 175.9414076, "composition": 0.0526}, + 177: {"mass": 176.9432277, "composition": 0.186}, + 178: {"mass": 177.9437058, "composition": 0.2728}, + 179: {"mass": 178.9458232, "composition": 0.1362}, + 180: {"mass": 179.946557, "composition": 0.3508}, + 181: {"mass": 180.9491083, "composition": 0.0}, + 182: {"mass": 181.9505612, "composition": 0.0}, + 183: {"mass": 182.95353, "composition": 0.0}, + 184: {"mass": 183.955446, "composition": 0.0}, + 185: {"mass": 184.958862, "composition": 0.0}, + 186: {"mass": 185.960897, "composition": 0.0}, + 187: {"mass": 186.96477, "composition": 0.0}, + 188: {"mass": 187.96685, "composition": 0.0}, + 189: {"mass": 188.97084, "composition": 0.0}}, + 73: {155: {"mass": 154.97424, "composition": 0.0}, + 156: {"mass": 155.97203, "composition": 0.0}, + 157: {"mass": 156.96818, "composition": 0.0}, + 158: {"mass": 157.96654, "composition": 0.0}, + 159: {"mass": 158.963023, "composition": 0.0}, + 160: {"mass": 159.961488, "composition": 0.0}, + 161: {"mass": 160.958452, "composition": 0.0}, + 162: {"mass": 161.957294, "composition": 0.0}, + 163: {"mass": 162.954337, "composition": 0.0}, + 164: {"mass": 163.953534, "composition": 0.0}, + 165: {"mass": 164.950781, "composition": 0.0}, + 166: {"mass": 165.950512, "composition": 0.0}, + 167: {"mass": 166.948093, "composition": 0.0}, + 168: {"mass": 167.948047, "composition": 0.0}, + 169: {"mass": 168.946011, "composition": 0.0}, + 170: {"mass": 169.946175, "composition": 0.0}, + 171: {"mass": 170.944476, "composition": 0.0}, + 172: {"mass": 171.944895, "composition": 0.0}, + 173: {"mass": 172.94375, "composition": 0.0}, + 174: {"mass": 173.944454, "composition": 0.0}, + 175: {"mass": 174.943737, "composition": 0.0}, + 176: {"mass": 175.944857, "composition": 0.0}, + 177: {"mass": 176.9444795, "composition": 0.0}, + 178: {"mass": 177.945678, "composition": 0.0}, + 179: {"mass": 178.9459366, "composition": 0.0}, + 180: {"mass": 179.9474648, "composition": 0.0001201}, + 181: {"mass": 180.9479958, "composition": 0.9998799}, + 182: {"mass": 181.9501519, "composition": 0.0}, + 183: {"mass": 182.9513726, "composition": 0.0}, + 184: {"mass": 183.954008, "composition": 0.0}, + 185: {"mass": 184.955559, "composition": 0.0}, + 186: {"mass": 185.958551, "composition": 0.0}, + 187: {"mass": 186.960386, "composition": 0.0}, + 188: {"mass": 187.963916, "composition": 0.0}, + 189: {"mass": 188.96583, "composition": 0.0}, + 190: {"mass": 189.96939, "composition": 0.0}, + 191: {"mass": 190.97156, "composition": 0.0}, + 192: {"mass": 191.97514, "composition": 0.0}}, + 74: {157: {"mass": 156.97884, "composition": 0.0}, + 158: {"mass": 157.97456, "composition": 0.0}, + 159: {"mass": 158.97264, "composition": 0.0}, + 160: {"mass": 159.96846, "composition": 0.0}, + 161: {"mass": 160.9672, "composition": 0.0}, + 162: {"mass": 161.963499, "composition": 0.0}, + 163: {"mass": 162.962524, "composition": 0.0}, + 164: {"mass": 163.958961, "composition": 0.0}, + 165: {"mass": 164.958281, "composition": 0.0}, + 166: {"mass": 165.955031, "composition": 0.0}, + 167: {"mass": 166.954805, "composition": 0.0}, + 168: {"mass": 167.951806, "composition": 0.0}, + 169: {"mass": 168.951779, "composition": 0.0}, + 170: {"mass": 169.949232, "composition": 0.0}, + 171: {"mass": 170.949451, "composition": 0.0}, + 172: {"mass": 171.947292, "composition": 0.0}, + 173: {"mass": 172.947689, "composition": 0.0}, + 174: {"mass": 173.946079, "composition": 0.0}, + 175: {"mass": 174.946717, "composition": 0.0}, + 176: {"mass": 175.945634, "composition": 0.0}, + 177: {"mass": 176.946643, "composition": 0.0}, + 178: {"mass": 177.945883, "composition": 0.0}, + 179: {"mass": 178.947077, "composition": 0.0}, + 180: {"mass": 179.9467108, "composition": 0.0012}, + 181: {"mass": 180.9481978, "composition": 0.0}, + 182: {"mass": 181.94820394, "composition": 0.265}, + 183: {"mass": 182.95022275, "composition": 0.1431}, + 184: {"mass": 183.95093092, "composition": 0.3064}, + 185: {"mass": 184.95341897, "composition": 0.0}, + 186: {"mass": 185.9543628, "composition": 0.2843}, + 187: {"mass": 186.9571588, "composition": 0.0}, + 188: {"mass": 187.9584862, "composition": 0.0}, + 189: {"mass": 188.961763, "composition": 0.0}, + 190: {"mass": 189.963091, "composition": 0.0}, + 191: {"mass": 190.966531, "composition": 0.0}, + 192: {"mass": 191.96817, "composition": 0.0}, + 193: {"mass": 192.97178, "composition": 0.0}, + 194: {"mass": 193.97367, "composition": 0.0}}, + 75: {159: {"mass": 158.98418, "composition": 0.0}, + 160: {"mass": 159.98182, "composition": 0.0}, + 161: {"mass": 160.97757, "composition": 0.0}, + 162: {"mass": 161.97584, "composition": 0.0}, + 163: {"mass": 162.97208, "composition": 0.0}, + 164: {"mass": 163.970453, "composition": 0.0}, + 165: {"mass": 164.967103, "composition": 0.0}, + 166: {"mass": 165.965761, "composition": 0.0}, + 167: {"mass": 166.962595, "composition": 0.0}, + 168: {"mass": 167.961573, "composition": 0.0}, + 169: {"mass": 168.958766, "composition": 0.0}, + 170: {"mass": 169.95822, "composition": 0.0}, + 171: {"mass": 170.955716, "composition": 0.0}, + 172: {"mass": 171.95542, "composition": 0.0}, + 173: {"mass": 172.953243, "composition": 0.0}, + 174: {"mass": 173.953115, "composition": 0.0}, + 175: {"mass": 174.951381, "composition": 0.0}, + 176: {"mass": 175.951623, "composition": 0.0}, + 177: {"mass": 176.950328, "composition": 0.0}, + 178: {"mass": 177.950989, "composition": 0.0}, + 179: {"mass": 178.949989, "composition": 0.0}, + 180: {"mass": 179.950792, "composition": 0.0}, + 181: {"mass": 180.950058, "composition": 0.0}, + 182: {"mass": 181.95121, "composition": 0.0}, + 183: {"mass": 182.9508196, "composition": 0.0}, + 184: {"mass": 183.9525228, "composition": 0.0}, + 185: {"mass": 184.9529545, "composition": 0.374}, + 186: {"mass": 185.9549856, "composition": 0.0}, + 187: {"mass": 186.9557501, "composition": 0.626}, + 188: {"mass": 187.9581115, "composition": 0.0}, + 189: {"mass": 188.959226, "composition": 0.0}, + 190: {"mass": 189.961744, "composition": 0.0}, + 191: {"mass": 190.963122, "composition": 0.0}, + 192: {"mass": 191.966088, "composition": 0.0}, + 193: {"mass": 192.967541, "composition": 0.0}, + 194: {"mass": 193.97076, "composition": 0.0}, + 195: {"mass": 194.97254, "composition": 0.0}, + 196: {"mass": 195.9758, "composition": 0.0}, + 197: {"mass": 196.97799, "composition": 0.0}, + 198: {"mass": 197.9816, "composition": 0.0}}, + 76: {161: {"mass": 160.98903, "composition": 0.0}, + 162: {"mass": 161.98443, "composition": 0.0}, + 163: {"mass": 162.98241, "composition": 0.0}, + 164: {"mass": 163.97802, "composition": 0.0}, + 165: {"mass": 164.9766, "composition": 0.0}, + 166: {"mass": 165.972692, "composition": 0.0}, + 167: {"mass": 166.971549, "composition": 0.0}, + 168: {"mass": 167.967808, "composition": 0.0}, + 169: {"mass": 168.967018, "composition": 0.0}, + 170: {"mass": 169.963578, "composition": 0.0}, + 171: {"mass": 170.963174, "composition": 0.0}, + 172: {"mass": 171.960017, "composition": 0.0}, + 173: {"mass": 172.959808, "composition": 0.0}, + 174: {"mass": 173.957064, "composition": 0.0}, + 175: {"mass": 174.956945, "composition": 0.0}, + 176: {"mass": 175.954806, "composition": 0.0}, + 177: {"mass": 176.954966, "composition": 0.0}, + 178: {"mass": 177.953254, "composition": 0.0}, + 179: {"mass": 178.953817, "composition": 0.0}, + 180: {"mass": 179.952375, "composition": 0.0}, + 181: {"mass": 180.953247, "composition": 0.0}, + 182: {"mass": 181.95211, "composition": 0.0}, + 183: {"mass": 182.953125, "composition": 0.0}, + 184: {"mass": 183.9524885, "composition": 0.0002}, + 185: {"mass": 184.9540417, "composition": 0.0}, + 186: {"mass": 185.953835, "composition": 0.0159}, + 187: {"mass": 186.9557474, "composition": 0.0196}, + 188: {"mass": 187.9558352, "composition": 0.1324}, + 189: {"mass": 188.9581442, "composition": 0.1615}, + 190: {"mass": 189.9584437, "composition": 0.2626}, + 191: {"mass": 190.9609264, "composition": 0.0}, + 192: {"mass": 191.961477, "composition": 0.4078}, + 193: {"mass": 192.9641479, "composition": 0.0}, + 194: {"mass": 193.9651772, "composition": 0.0}, + 195: {"mass": 194.968318, "composition": 0.0}, + 196: {"mass": 195.969641, "composition": 0.0}, + 197: {"mass": 196.97283, "composition": 0.0}, + 198: {"mass": 197.97441, "composition": 0.0}, + 199: {"mass": 198.97801, "composition": 0.0}, + 200: {"mass": 199.97984, "composition": 0.0}, + 201: {"mass": 200.98364, "composition": 0.0}, + 202: {"mass": 201.98595, "composition": 0.0}}, + 77: {164: {"mass": 163.99191, "composition": 0.0}, + 165: {"mass": 164.9875, "composition": 0.0}, + 166: {"mass": 165.98566, "composition": 0.0}, + 167: {"mass": 166.981666, "composition": 0.0}, + 168: {"mass": 167.979907, "composition": 0.0}, + 169: {"mass": 168.976298, "composition": 0.0}, + 170: {"mass": 169.974922, "composition": 0.0}, + 171: {"mass": 170.97164, "composition": 0.0}, + 172: {"mass": 171.970607, "composition": 0.0}, + 173: {"mass": 172.967506, "composition": 0.0}, + 174: {"mass": 173.966861, "composition": 0.0}, + 175: {"mass": 174.96415, "composition": 0.0}, + 176: {"mass": 175.96365, "composition": 0.0}, + 177: {"mass": 176.961301, "composition": 0.0}, + 178: {"mass": 177.961082, "composition": 0.0}, + 179: {"mass": 178.95912, "composition": 0.0}, + 180: {"mass": 179.959229, "composition": 0.0}, + 181: {"mass": 180.957625, "composition": 0.0}, + 182: {"mass": 181.958076, "composition": 0.0}, + 183: {"mass": 182.95684, "composition": 0.0}, + 184: {"mass": 183.957476, "composition": 0.0}, + 185: {"mass": 184.956698, "composition": 0.0}, + 186: {"mass": 185.957944, "composition": 0.0}, + 187: {"mass": 186.957542, "composition": 0.0}, + 188: {"mass": 187.958828, "composition": 0.0}, + 189: {"mass": 188.958715, "composition": 0.0}, + 190: {"mass": 189.9605412, "composition": 0.0}, + 191: {"mass": 190.9605893, "composition": 0.373}, + 192: {"mass": 191.9626002, "composition": 0.0}, + 193: {"mass": 192.9629216, "composition": 0.627}, + 194: {"mass": 193.9650735, "composition": 0.0}, + 195: {"mass": 194.9659747, "composition": 0.0}, + 196: {"mass": 195.968397, "composition": 0.0}, + 197: {"mass": 196.969655, "composition": 0.0}, + 198: {"mass": 197.97228, "composition": 0.0}, + 199: {"mass": 198.973805, "composition": 0.0}, + 200: {"mass": 199.9768, "composition": 0.0}, + 201: {"mass": 200.97864, "composition": 0.0}, + 202: {"mass": 201.98199, "composition": 0.0}, + 203: {"mass": 202.98423, "composition": 0.0}, + 204: {"mass": 203.9896, "composition": 0.0}}, + 78: {166: {"mass": 165.99486, "composition": 0.0}, + 167: {"mass": 166.99269, "composition": 0.0}, + 168: {"mass": 167.98813, "composition": 0.0}, + 169: {"mass": 168.98657, "composition": 0.0}, + 170: {"mass": 169.982496, "composition": 0.0}, + 171: {"mass": 170.981245, "composition": 0.0}, + 172: {"mass": 171.977351, "composition": 0.0}, + 173: {"mass": 172.976443, "composition": 0.0}, + 174: {"mass": 173.97282, "composition": 0.0}, + 175: {"mass": 174.97241, "composition": 0.0}, + 176: {"mass": 175.968938, "composition": 0.0}, + 177: {"mass": 176.96847, "composition": 0.0}, + 178: {"mass": 177.96565, "composition": 0.0}, + 179: {"mass": 178.965359, "composition": 0.0}, + 180: {"mass": 179.963032, "composition": 0.0}, + 181: {"mass": 180.963098, "composition": 0.0}, + 182: {"mass": 181.961172, "composition": 0.0}, + 183: {"mass": 182.961597, "composition": 0.0}, + 184: {"mass": 183.959915, "composition": 0.0}, + 185: {"mass": 184.960614, "composition": 0.0}, + 186: {"mass": 185.959351, "composition": 0.0}, + 187: {"mass": 186.960617, "composition": 0.0}, + 188: {"mass": 187.9593889, "composition": 0.0}, + 189: {"mass": 188.960831, "composition": 0.0}, + 190: {"mass": 189.9599297, "composition": 0.00012}, + 191: {"mass": 190.9616729, "composition": 0.0}, + 192: {"mass": 191.9610387, "composition": 0.00782}, + 193: {"mass": 192.9629824, "composition": 0.0}, + 194: {"mass": 193.9626809, "composition": 0.3286}, + 195: {"mass": 194.9647917, "composition": 0.3378}, + 196: {"mass": 195.96495209, "composition": 0.2521}, + 197: {"mass": 196.96734069, "composition": 0.0}, + 198: {"mass": 197.9678949, "composition": 0.07356}, + 199: {"mass": 198.9705952, "composition": 0.0}, + 200: {"mass": 199.971443, "composition": 0.0}, + 201: {"mass": 200.974513, "composition": 0.0}, + 202: {"mass": 201.975639, "composition": 0.0}, + 203: {"mass": 202.97893, "composition": 0.0}, + 204: {"mass": 203.98076, "composition": 0.0}, + 205: {"mass": 204.98608, "composition": 0.0}, + 206: {"mass": 205.98966, "composition": 0.0}}, + 79: {169: {"mass": 168.99808, "composition": 0.0}, + 170: {"mass": 169.99597, "composition": 0.0}, + 171: {"mass": 170.991876, "composition": 0.0}, + 172: {"mass": 171.989942, "composition": 0.0}, + 173: {"mass": 172.986241, "composition": 0.0}, + 174: {"mass": 173.984717, "composition": 0.0}, + 175: {"mass": 174.981304, "composition": 0.0}, + 176: {"mass": 175.98025, "composition": 0.0}, + 177: {"mass": 176.97687, "composition": 0.0}, + 178: {"mass": 177.976032, "composition": 0.0}, + 179: {"mass": 178.973174, "composition": 0.0}, + 180: {"mass": 179.972523, "composition": 0.0}, + 181: {"mass": 180.970079, "composition": 0.0}, + 182: {"mass": 181.969618, "composition": 0.0}, + 183: {"mass": 182.967591, "composition": 0.0}, + 184: {"mass": 183.967452, "composition": 0.0}, + 185: {"mass": 184.96579, "composition": 0.0}, + 186: {"mass": 185.965953, "composition": 0.0}, + 187: {"mass": 186.964543, "composition": 0.0}, + 188: {"mass": 187.965349, "composition": 0.0}, + 189: {"mass": 188.963948, "composition": 0.0}, + 190: {"mass": 189.964698, "composition": 0.0}, + 191: {"mass": 190.963702, "composition": 0.0}, + 192: {"mass": 191.964814, "composition": 0.0}, + 193: {"mass": 192.9641373, "composition": 0.0}, + 194: {"mass": 193.9654178, "composition": 0.0}, + 195: {"mass": 194.9650352, "composition": 0.0}, + 196: {"mass": 195.9665699, "composition": 0.0}, + 197: {"mass": 196.96656879, "composition": 1.0}, + 198: {"mass": 197.96824242, "composition": 0.0}, + 199: {"mass": 198.96876528, "composition": 0.0}, + 200: {"mass": 199.970756, "composition": 0.0}, + 201: {"mass": 200.9716575, "composition": 0.0}, + 202: {"mass": 201.973856, "composition": 0.0}, + 203: {"mass": 202.9751544, "composition": 0.0}, + 204: {"mass": 203.97783, "composition": 0.0}, + 205: {"mass": 204.97985, "composition": 0.0}, + 206: {"mass": 205.98474, "composition": 0.0}, + 207: {"mass": 206.9884, "composition": 0.0}, + 208: {"mass": 207.99345, "composition": 0.0}, + 209: {"mass": 208.99735, "composition": 0.0}, + 210: {"mass": 210.0025, "composition": 0.0}}, + 80: {171: {"mass": 171.00353, "composition": 0.0}, + 172: {"mass": 171.99881, "composition": 0.0}, + 173: {"mass": 172.99709, "composition": 0.0}, + 174: {"mass": 173.992865, "composition": 0.0}, + 175: {"mass": 174.991441, "composition": 0.0}, + 176: {"mass": 175.987361, "composition": 0.0}, + 177: {"mass": 176.986277, "composition": 0.0}, + 178: {"mass": 177.982484, "composition": 0.0}, + 179: {"mass": 178.981831, "composition": 0.0}, + 180: {"mass": 179.97826, "composition": 0.0}, + 181: {"mass": 180.977819, "composition": 0.0}, + 182: {"mass": 181.974689, "composition": 0.0}, + 183: {"mass": 182.9744448, "composition": 0.0}, + 184: {"mass": 183.971714, "composition": 0.0}, + 185: {"mass": 184.971899, "composition": 0.0}, + 186: {"mass": 185.969362, "composition": 0.0}, + 187: {"mass": 186.969814, "composition": 0.0}, + 188: {"mass": 187.967567, "composition": 0.0}, + 189: {"mass": 188.968195, "composition": 0.0}, + 190: {"mass": 189.966323, "composition": 0.0}, + 191: {"mass": 190.967157, "composition": 0.0}, + 192: {"mass": 191.965635, "composition": 0.0}, + 193: {"mass": 192.966653, "composition": 0.0}, + 194: {"mass": 193.9654491, "composition": 0.0}, + 195: {"mass": 194.966721, "composition": 0.0}, + 196: {"mass": 195.9658326, "composition": 0.0015}, + 197: {"mass": 196.9672128, "composition": 0.0}, + 198: {"mass": 197.9667686, "composition": 0.0997}, + 199: {"mass": 198.96828064, "composition": 0.1687}, + 200: {"mass": 199.96832659, "composition": 0.231}, + 201: {"mass": 200.97030284, "composition": 0.1318}, + 202: {"mass": 201.9706434, "composition": 0.2986}, + 203: {"mass": 202.9728728, "composition": 0.0}, + 204: {"mass": 203.97349398, "composition": 0.0687}, + 205: {"mass": 204.9760734, "composition": 0.0}, + 206: {"mass": 205.977514, "composition": 0.0}, + 207: {"mass": 206.9823, "composition": 0.0}, + 208: {"mass": 207.985759, "composition": 0.0}, + 209: {"mass": 208.99072, "composition": 0.0}, + 210: {"mass": 209.99424, "composition": 0.0}, + 211: {"mass": 210.99933, "composition": 0.0}, + 212: {"mass": 212.00296, "composition": 0.0}, + 213: {"mass": 213.00823, "composition": 0.0}, + 214: {"mass": 214.012, "composition": 0.0}, + 215: {"mass": 215.0174, "composition": 0.0}, + 216: {"mass": 216.02132, "composition": 0.0}}, + 81: {176: {"mass": 176.000624, "composition": 0.0}, + 177: {"mass": 176.996431, "composition": 0.0}, + 178: {"mass": 177.99485, "composition": 0.0}, + 179: {"mass": 178.991111, "composition": 0.0}, + 180: {"mass": 179.990057, "composition": 0.0}, + 181: {"mass": 180.98626, "composition": 0.0}, + 182: {"mass": 181.985713, "composition": 0.0}, + 183: {"mass": 182.982193, "composition": 0.0}, + 184: {"mass": 183.981886, "composition": 0.0}, + 185: {"mass": 184.978789, "composition": 0.0}, + 186: {"mass": 185.978651, "composition": 0.0}, + 187: {"mass": 186.9759063, "composition": 0.0}, + 188: {"mass": 187.976021, "composition": 0.0}, + 189: {"mass": 188.973588, "composition": 0.0}, + 190: {"mass": 189.973828, "composition": 0.0}, + 191: {"mass": 190.9717842, "composition": 0.0}, + 192: {"mass": 191.972225, "composition": 0.0}, + 193: {"mass": 192.970502, "composition": 0.0}, + 194: {"mass": 193.971081, "composition": 0.0}, + 195: {"mass": 194.969774, "composition": 0.0}, + 196: {"mass": 195.970481, "composition": 0.0}, + 197: {"mass": 196.969576, "composition": 0.0}, + 198: {"mass": 197.970483, "composition": 0.0}, + 199: {"mass": 198.969877, "composition": 0.0}, + 200: {"mass": 199.9709633, "composition": 0.0}, + 201: {"mass": 200.970822, "composition": 0.0}, + 202: {"mass": 201.972102, "composition": 0.0}, + 203: {"mass": 202.9723446, "composition": 0.2952}, + 204: {"mass": 203.9738639, "composition": 0.0}, + 205: {"mass": 204.9744278, "composition": 0.7048}, + 206: {"mass": 205.9761106, "composition": 0.0}, + 207: {"mass": 206.9774197, "composition": 0.0}, + 208: {"mass": 207.982019, "composition": 0.0}, + 209: {"mass": 208.9853594, "composition": 0.0}, + 210: {"mass": 209.990074, "composition": 0.0}, + 211: {"mass": 210.993475, "composition": 0.0}, + 212: {"mass": 211.99834, "composition": 0.0}, + 213: {"mass": 213.001915, "composition": 0.0}, + 214: {"mass": 214.00694, "composition": 0.0}, + 215: {"mass": 215.01064, "composition": 0.0}, + 216: {"mass": 216.0158, "composition": 0.0}, + 217: {"mass": 217.01966, "composition": 0.0}, + 218: {"mass": 218.02479, "composition": 0.0}}, + 82: {178: {"mass": 178.003831, "composition": 0.0}, + 179: {"mass": 179.002201, "composition": 0.0}, + 180: {"mass": 179.997928, "composition": 0.0}, + 181: {"mass": 180.996653, "composition": 0.0}, + 182: {"mass": 181.992672, "composition": 0.0}, + 183: {"mass": 182.991872, "composition": 0.0}, + 184: {"mass": 183.988136, "composition": 0.0}, + 185: {"mass": 184.98761, "composition": 0.0}, + 186: {"mass": 185.984238, "composition": 0.0}, + 187: {"mass": 186.9839109, "composition": 0.0}, + 188: {"mass": 187.980875, "composition": 0.0}, + 189: {"mass": 188.980807, "composition": 0.0}, + 190: {"mass": 189.978082, "composition": 0.0}, + 191: {"mass": 190.978276, "composition": 0.0}, + 192: {"mass": 191.975775, "composition": 0.0}, + 193: {"mass": 192.976173, "composition": 0.0}, + 194: {"mass": 193.974012, "composition": 0.0}, + 195: {"mass": 194.974543, "composition": 0.0}, + 196: {"mass": 195.972774, "composition": 0.0}, + 197: {"mass": 196.9734312, "composition": 0.0}, + 198: {"mass": 197.972034, "composition": 0.0}, + 199: {"mass": 198.972913, "composition": 0.0}, + 200: {"mass": 199.971819, "composition": 0.0}, + 201: {"mass": 200.972883, "composition": 0.0}, + 202: {"mass": 201.972152, "composition": 0.0}, + 203: {"mass": 202.9733911, "composition": 0.0}, + 204: {"mass": 203.973044, "composition": 0.014}, + 205: {"mass": 204.9744822, "composition": 0.0}, + 206: {"mass": 205.9744657, "composition": 0.241}, + 207: {"mass": 206.9758973, "composition": 0.221}, + 208: {"mass": 207.9766525, "composition": 0.524}, + 209: {"mass": 208.9810905, "composition": 0.0}, + 210: {"mass": 209.9841889, "composition": 0.0}, + 211: {"mass": 210.9887371, "composition": 0.0}, + 212: {"mass": 211.9918977, "composition": 0.0}, + 213: {"mass": 212.9965629, "composition": 0.0}, + 214: {"mass": 213.9998059, "composition": 0.0}, + 215: {"mass": 215.00474, "composition": 0.0}, + 216: {"mass": 216.00803, "composition": 0.0}, + 217: {"mass": 217.01314, "composition": 0.0}, + 218: {"mass": 218.01659, "composition": 0.0}, + 219: {"mass": 219.02177, "composition": 0.0}, + 220: {"mass": 220.02541, "composition": 0.0}}, + 83: {184: {"mass": 184.001275, "composition": 0.0}, + 185: {"mass": 184.9976, "composition": 0.0}, + 186: {"mass": 185.996644, "composition": 0.0}, + 187: {"mass": 186.993147, "composition": 0.0}, + 188: {"mass": 187.992287, "composition": 0.0}, + 189: {"mass": 188.989195, "composition": 0.0}, + 190: {"mass": 189.988622, "composition": 0.0}, + 191: {"mass": 190.9857866, "composition": 0.0}, + 192: {"mass": 191.985469, "composition": 0.0}, + 193: {"mass": 192.98296, "composition": 0.0}, + 194: {"mass": 193.982785, "composition": 0.0}, + 195: {"mass": 194.9806488, "composition": 0.0}, + 196: {"mass": 195.980667, "composition": 0.0}, + 197: {"mass": 196.9788651, "composition": 0.0}, + 198: {"mass": 197.979206, "composition": 0.0}, + 199: {"mass": 198.977673, "composition": 0.0}, + 200: {"mass": 199.978131, "composition": 0.0}, + 201: {"mass": 200.97701, "composition": 0.0}, + 202: {"mass": 201.977734, "composition": 0.0}, + 203: {"mass": 202.976893, "composition": 0.0}, + 204: {"mass": 203.9778361, "composition": 0.0}, + 205: {"mass": 204.9773867, "composition": 0.0}, + 206: {"mass": 205.9784993, "composition": 0.0}, + 207: {"mass": 206.978471, "composition": 0.0}, + 208: {"mass": 207.9797425, "composition": 0.0}, + 209: {"mass": 208.9803991, "composition": 1.0}, + 210: {"mass": 209.9841207, "composition": 0.0}, + 211: {"mass": 210.9872697, "composition": 0.0}, + 212: {"mass": 211.991286, "composition": 0.0}, + 213: {"mass": 212.9943851, "composition": 0.0}, + 214: {"mass": 213.998712, "composition": 0.0}, + 215: {"mass": 215.00177, "composition": 0.0}, + 216: {"mass": 216.006306, "composition": 0.0}, + 217: {"mass": 217.009372, "composition": 0.0}, + 218: {"mass": 218.014188, "composition": 0.0}, + 219: {"mass": 219.01748, "composition": 0.0}, + 220: {"mass": 220.02235, "composition": 0.0}, + 221: {"mass": 221.02587, "composition": 0.0}, + 222: {"mass": 222.03078, "composition": 0.0}, + 223: {"mass": 223.0345, "composition": 0.0}, + 224: {"mass": 224.03947, "composition": 0.0}}, + 84: {186: {"mass": 186.004393, "composition": 0.0}, + 187: {"mass": 187.003041, "composition": 0.0}, + 188: {"mass": 187.999416, "composition": 0.0}, + 189: {"mass": 188.998473, "composition": 0.0}, + 190: {"mass": 189.995101, "composition": 0.0}, + 191: {"mass": 190.9945585, "composition": 0.0}, + 192: {"mass": 191.991336, "composition": 0.0}, + 193: {"mass": 192.991026, "composition": 0.0}, + 194: {"mass": 193.988186, "composition": 0.0}, + 195: {"mass": 194.988126, "composition": 0.0}, + 196: {"mass": 195.985526, "composition": 0.0}, + 197: {"mass": 196.98566, "composition": 0.0}, + 198: {"mass": 197.983389, "composition": 0.0}, + 199: {"mass": 198.983667, "composition": 0.0}, + 200: {"mass": 199.981799, "composition": 0.0}, + 201: {"mass": 200.9822598, "composition": 0.0}, + 202: {"mass": 201.980758, "composition": 0.0}, + 203: {"mass": 202.9814161, "composition": 0.0}, + 204: {"mass": 203.98031, "composition": 0.0}, + 205: {"mass": 204.981203, "composition": 0.0}, + 206: {"mass": 205.980474, "composition": 0.0}, + 207: {"mass": 206.9815938, "composition": 0.0}, + 208: {"mass": 207.9812461, "composition": 0.0}, + 209: {"mass": 208.9824308, "composition": 0.0}, + 210: {"mass": 209.9828741, "composition": 0.0}, + 211: {"mass": 210.9866536, "composition": 0.0}, + 212: {"mass": 211.9888684, "composition": 0.0}, + 213: {"mass": 212.9928576, "composition": 0.0}, + 214: {"mass": 213.9952017, "composition": 0.0}, + 215: {"mass": 214.9994201, "composition": 0.0}, + 216: {"mass": 216.0019152, "composition": 0.0}, + 217: {"mass": 217.0063182, "composition": 0.0}, + 218: {"mass": 218.0089735, "composition": 0.0}, + 219: {"mass": 219.013614, "composition": 0.0}, + 220: {"mass": 220.016386, "composition": 0.0}, + 221: {"mass": 221.021228, "composition": 0.0}, + 222: {"mass": 222.02414, "composition": 0.0}, + 223: {"mass": 223.02907, "composition": 0.0}, + 224: {"mass": 224.03211, "composition": 0.0}, + 225: {"mass": 225.03707, "composition": 0.0}, + 226: {"mass": 226.04031, "composition": 0.0}, + 227: {"mass": 227.04539, "composition": 0.0}}, + 85: {191: {"mass": 191.004148, "composition": 0.0}, + 192: {"mass": 192.003152, "composition": 0.0}, + 193: {"mass": 192.999927, "composition": 0.0}, + 194: {"mass": 193.999236, "composition": 0.0}, + 195: {"mass": 194.9962685, "composition": 0.0}, + 196: {"mass": 195.9958, "composition": 0.0}, + 197: {"mass": 196.993189, "composition": 0.0}, + 198: {"mass": 197.992784, "composition": 0.0}, + 199: {"mass": 198.9905277, "composition": 0.0}, + 200: {"mass": 199.990351, "composition": 0.0}, + 201: {"mass": 200.9884171, "composition": 0.0}, + 202: {"mass": 201.98863, "composition": 0.0}, + 203: {"mass": 202.986943, "composition": 0.0}, + 204: {"mass": 203.987251, "composition": 0.0}, + 205: {"mass": 204.986076, "composition": 0.0}, + 206: {"mass": 205.986657, "composition": 0.0}, + 207: {"mass": 206.9858, "composition": 0.0}, + 208: {"mass": 207.9866133, "composition": 0.0}, + 209: {"mass": 208.9861702, "composition": 0.0}, + 210: {"mass": 209.9871479, "composition": 0.0}, + 211: {"mass": 210.9874966, "composition": 0.0}, + 212: {"mass": 211.9907377, "composition": 0.0}, + 213: {"mass": 212.992937, "composition": 0.0}, + 214: {"mass": 213.9963721, "composition": 0.0}, + 215: {"mass": 214.9986528, "composition": 0.0}, + 216: {"mass": 216.0024236, "composition": 0.0}, + 217: {"mass": 217.0047192, "composition": 0.0}, + 218: {"mass": 218.008695, "composition": 0.0}, + 219: {"mass": 219.0111618, "composition": 0.0}, + 220: {"mass": 220.015433, "composition": 0.0}, + 221: {"mass": 221.018017, "composition": 0.0}, + 222: {"mass": 222.022494, "composition": 0.0}, + 223: {"mass": 223.025151, "composition": 0.0}, + 224: {"mass": 224.029749, "composition": 0.0}, + 225: {"mass": 225.03263, "composition": 0.0}, + 226: {"mass": 226.03716, "composition": 0.0}, + 227: {"mass": 227.04024, "composition": 0.0}, + 228: {"mass": 228.04475, "composition": 0.0}, + 229: {"mass": 229.04812, "composition": 0.0}}, + 86: {193: {"mass": 193.009708, "composition": 0.0}, + 194: {"mass": 194.006144, "composition": 0.0}, + 195: {"mass": 195.005422, "composition": 0.0}, + 196: {"mass": 196.002116, "composition": 0.0}, + 197: {"mass": 197.001585, "composition": 0.0}, + 198: {"mass": 197.998679, "composition": 0.0}, + 199: {"mass": 198.99839, "composition": 0.0}, + 200: {"mass": 199.99569, "composition": 0.0}, + 201: {"mass": 200.995628, "composition": 0.0}, + 202: {"mass": 201.993264, "composition": 0.0}, + 203: {"mass": 202.993388, "composition": 0.0}, + 204: {"mass": 203.99143, "composition": 0.0}, + 205: {"mass": 204.991719, "composition": 0.0}, + 206: {"mass": 205.990214, "composition": 0.0}, + 207: {"mass": 206.9907303, "composition": 0.0}, + 208: {"mass": 207.989635, "composition": 0.0}, + 209: {"mass": 208.990415, "composition": 0.0}, + 210: {"mass": 209.9896891, "composition": 0.0}, + 211: {"mass": 210.9906011, "composition": 0.0}, + 212: {"mass": 211.9907039, "composition": 0.0}, + 213: {"mass": 212.9938831, "composition": 0.0}, + 214: {"mass": 213.995363, "composition": 0.0}, + 215: {"mass": 214.9987459, "composition": 0.0}, + 216: {"mass": 216.0002719, "composition": 0.0}, + 217: {"mass": 217.003928, "composition": 0.0}, + 218: {"mass": 218.0056016, "composition": 0.0}, + 219: {"mass": 219.0094804, "composition": 0.0}, + 220: {"mass": 220.0113941, "composition": 0.0}, + 221: {"mass": 221.0155371, "composition": 0.0}, + 222: {"mass": 222.0175782, "composition": 0.0}, + 223: {"mass": 223.0218893, "composition": 0.0}, + 224: {"mass": 224.024096, "composition": 0.0}, + 225: {"mass": 225.028486, "composition": 0.0}, + 226: {"mass": 226.030861, "composition": 0.0}, + 227: {"mass": 227.035304, "composition": 0.0}, + 228: {"mass": 228.037835, "composition": 0.0}, + 229: {"mass": 229.042257, "composition": 0.0}, + 230: {"mass": 230.04514, "composition": 0.0}, + 231: {"mass": 231.04987, "composition": 0.0}}, + 87: {199: {"mass": 199.007259, "composition": 0.0}, + 200: {"mass": 200.006586, "composition": 0.0}, + 201: {"mass": 201.003867, "composition": 0.0}, + 202: {"mass": 202.00332, "composition": 0.0}, + 203: {"mass": 203.0009407, "composition": 0.0}, + 204: {"mass": 204.000652, "composition": 0.0}, + 205: {"mass": 204.9985939, "composition": 0.0}, + 206: {"mass": 205.998666, "composition": 0.0}, + 207: {"mass": 206.996946, "composition": 0.0}, + 208: {"mass": 207.997138, "composition": 0.0}, + 209: {"mass": 208.995955, "composition": 0.0}, + 210: {"mass": 209.996422, "composition": 0.0}, + 211: {"mass": 210.995556, "composition": 0.0}, + 212: {"mass": 211.9962257, "composition": 0.0}, + 213: {"mass": 212.996186, "composition": 0.0}, + 214: {"mass": 213.9989713, "composition": 0.0}, + 215: {"mass": 215.0003418, "composition": 0.0}, + 216: {"mass": 216.0031899, "composition": 0.0}, + 217: {"mass": 217.0046323, "composition": 0.0}, + 218: {"mass": 218.0075787, "composition": 0.0}, + 219: {"mass": 219.0092524, "composition": 0.0}, + 220: {"mass": 220.0123277, "composition": 0.0}, + 221: {"mass": 221.0142552, "composition": 0.0}, + 222: {"mass": 222.017552, "composition": 0.0}, + 223: {"mass": 223.019736, "composition": 0.0}, + 224: {"mass": 224.023398, "composition": 0.0}, + 225: {"mass": 225.025573, "composition": 0.0}, + 226: {"mass": 226.029566, "composition": 0.0}, + 227: {"mass": 227.031869, "composition": 0.0}, + 228: {"mass": 228.035823, "composition": 0.0}, + 229: {"mass": 229.038298, "composition": 0.0}, + 230: {"mass": 230.042416, "composition": 0.0}, + 231: {"mass": 231.045158, "composition": 0.0}, + 232: {"mass": 232.04937, "composition": 0.0}, + 233: {"mass": 233.05264, "composition": 0.0}}, + 88: {201: {"mass": 201.01271, "composition": 0.0}, + 202: {"mass": 202.00976, "composition": 0.0}, + 203: {"mass": 203.009304, "composition": 0.0}, + 204: {"mass": 204.006492, "composition": 0.0}, + 205: {"mass": 205.006268, "composition": 0.0}, + 206: {"mass": 206.003828, "composition": 0.0}, + 207: {"mass": 207.003799, "composition": 0.0}, + 208: {"mass": 208.001841, "composition": 0.0}, + 209: {"mass": 209.00199, "composition": 0.0}, + 210: {"mass": 210.000494, "composition": 0.0}, + 211: {"mass": 211.0008932, "composition": 0.0}, + 212: {"mass": 211.999787, "composition": 0.0}, + 213: {"mass": 213.000384, "composition": 0.0}, + 214: {"mass": 214.0000997, "composition": 0.0}, + 215: {"mass": 215.0027204, "composition": 0.0}, + 216: {"mass": 216.0035334, "composition": 0.0}, + 217: {"mass": 217.0063207, "composition": 0.0}, + 218: {"mass": 218.007141, "composition": 0.0}, + 219: {"mass": 219.0100855, "composition": 0.0}, + 220: {"mass": 220.0110259, "composition": 0.0}, + 221: {"mass": 221.0139177, "composition": 0.0}, + 222: {"mass": 222.0153748, "composition": 0.0}, + 223: {"mass": 223.0185023, "composition": 0.0}, + 224: {"mass": 224.020212, "composition": 0.0}, + 225: {"mass": 225.0236119, "composition": 0.0}, + 226: {"mass": 226.0254103, "composition": 0.0}, + 227: {"mass": 227.0291783, "composition": 0.0}, + 228: {"mass": 228.0310707, "composition": 0.0}, + 229: {"mass": 229.034942, "composition": 0.0}, + 230: {"mass": 230.037055, "composition": 0.0}, + 231: {"mass": 231.041027, "composition": 0.0}, + 232: {"mass": 232.0434753, "composition": 0.0}, + 233: {"mass": 233.047582, "composition": 0.0}, + 234: {"mass": 234.050342, "composition": 0.0}, + 235: {"mass": 235.05497, "composition": 0.0}}, + 89: {206: {"mass": 206.014452, "composition": 0.0}, + 207: {"mass": 207.011966, "composition": 0.0}, + 208: {"mass": 208.01155, "composition": 0.0}, + 209: {"mass": 209.009495, "composition": 0.0}, + 210: {"mass": 210.009436, "composition": 0.0}, + 211: {"mass": 211.007732, "composition": 0.0}, + 212: {"mass": 212.007813, "composition": 0.0}, + 213: {"mass": 213.006609, "composition": 0.0}, + 214: {"mass": 214.006918, "composition": 0.0}, + 215: {"mass": 215.006475, "composition": 0.0}, + 216: {"mass": 216.008743, "composition": 0.0}, + 217: {"mass": 217.009344, "composition": 0.0}, + 218: {"mass": 218.011642, "composition": 0.0}, + 219: {"mass": 219.012421, "composition": 0.0}, + 220: {"mass": 220.0147549, "composition": 0.0}, + 221: {"mass": 221.015592, "composition": 0.0}, + 222: {"mass": 222.0178442, "composition": 0.0}, + 223: {"mass": 223.0191377, "composition": 0.0}, + 224: {"mass": 224.0217232, "composition": 0.0}, + 225: {"mass": 225.02323, "composition": 0.0}, + 226: {"mass": 226.0260984, "composition": 0.0}, + 227: {"mass": 227.0277523, "composition": 0.0}, + 228: {"mass": 228.0310215, "composition": 0.0}, + 229: {"mass": 229.032956, "composition": 0.0}, + 230: {"mass": 230.036327, "composition": 0.0}, + 231: {"mass": 231.038393, "composition": 0.0}, + 232: {"mass": 232.042034, "composition": 0.0}, + 233: {"mass": 233.044346, "composition": 0.0}, + 234: {"mass": 234.048139, "composition": 0.0}, + 235: {"mass": 235.05084, "composition": 0.0}, + 236: {"mass": 236.054988, "composition": 0.0}, + 237: {"mass": 237.05827, "composition": 0.0}}, + 90: {208: {"mass": 208.0179, "composition": 0.0}, + 209: {"mass": 209.017753, "composition": 0.0}, + 210: {"mass": 210.015094, "composition": 0.0}, + 211: {"mass": 211.014929, "composition": 0.0}, + 212: {"mass": 212.012988, "composition": 0.0}, + 213: {"mass": 213.013009, "composition": 0.0}, + 214: {"mass": 214.0115, "composition": 0.0}, + 215: {"mass": 215.0117248, "composition": 0.0}, + 216: {"mass": 216.011056, "composition": 0.0}, + 217: {"mass": 217.013117, "composition": 0.0}, + 218: {"mass": 218.013276, "composition": 0.0}, + 219: {"mass": 219.015537, "composition": 0.0}, + 220: {"mass": 220.015748, "composition": 0.0}, + 221: {"mass": 221.018184, "composition": 0.0}, + 222: {"mass": 222.018469, "composition": 0.0}, + 223: {"mass": 223.0208119, "composition": 0.0}, + 224: {"mass": 224.021464, "composition": 0.0}, + 225: {"mass": 225.0239514, "composition": 0.0}, + 226: {"mass": 226.0249034, "composition": 0.0}, + 227: {"mass": 227.0277042, "composition": 0.0}, + 228: {"mass": 228.0287413, "composition": 0.0}, + 229: {"mass": 229.0317627, "composition": 0.0}, + 230: {"mass": 230.0331341, "composition": 0.0}, + 231: {"mass": 231.0363046, "composition": 0.0}, + 232: {"mass": 232.0380558, "composition": 1.0}, + 233: {"mass": 233.0415823, "composition": 0.0}, + 234: {"mass": 234.0436014, "composition": 0.0}, + 235: {"mass": 235.047255, "composition": 0.0}, + 236: {"mass": 236.049657, "composition": 0.0}, + 237: {"mass": 237.053629, "composition": 0.0}, + 238: {"mass": 238.0565, "composition": 0.0}, + 239: {"mass": 239.06077, "composition": 0.0}}, + 91: {212: {"mass": 212.023203, "composition": 0.0}, + 213: {"mass": 213.021109, "composition": 0.0}, + 214: {"mass": 214.020918, "composition": 0.0}, + 215: {"mass": 215.019183, "composition": 0.0}, + 216: {"mass": 216.019109, "composition": 0.0}, + 217: {"mass": 217.018325, "composition": 0.0}, + 218: {"mass": 218.020059, "composition": 0.0}, + 219: {"mass": 219.019904, "composition": 0.0}, + 220: {"mass": 220.021705, "composition": 0.0}, + 221: {"mass": 221.021875, "composition": 0.0}, + 222: {"mass": 222.023784, "composition": 0.0}, + 223: {"mass": 223.023963, "composition": 0.0}, + 224: {"mass": 224.0256176, "composition": 0.0}, + 225: {"mass": 225.026131, "composition": 0.0}, + 226: {"mass": 226.027948, "composition": 0.0}, + 227: {"mass": 227.0288054, "composition": 0.0}, + 228: {"mass": 228.0310517, "composition": 0.0}, + 229: {"mass": 229.0320972, "composition": 0.0}, + 230: {"mass": 230.034541, "composition": 0.0}, + 231: {"mass": 231.0358842, "composition": 1.0}, + 232: {"mass": 232.0385917, "composition": 0.0}, + 233: {"mass": 233.0402472, "composition": 0.0}, + 234: {"mass": 234.0433072, "composition": 0.0}, + 235: {"mass": 235.045399, "composition": 0.0}, + 236: {"mass": 236.048668, "composition": 0.0}, + 237: {"mass": 237.051023, "composition": 0.0}, + 238: {"mass": 238.054637, "composition": 0.0}, + 239: {"mass": 239.05726, "composition": 0.0}, + 240: {"mass": 240.06098, "composition": 0.0}, + 241: {"mass": 241.06408, "composition": 0.0}}, + 92: {217: {"mass": 217.02466, "composition": 0.0}, + 218: {"mass": 218.023523, "composition": 0.0}, + 219: {"mass": 219.024999, "composition": 0.0}, + 220: {"mass": 220.02462, "composition": 0.0}, + 221: {"mass": 221.02628, "composition": 0.0}, + 222: {"mass": 222.026, "composition": 0.0}, + 223: {"mass": 223.027739, "composition": 0.0}, + 224: {"mass": 224.027605, "composition": 0.0}, + 225: {"mass": 225.029391, "composition": 0.0}, + 226: {"mass": 226.029339, "composition": 0.0}, + 227: {"mass": 227.031157, "composition": 0.0}, + 228: {"mass": 228.031371, "composition": 0.0}, + 229: {"mass": 229.0335063, "composition": 0.0}, + 230: {"mass": 230.0339401, "composition": 0.0}, + 231: {"mass": 231.0362939, "composition": 0.0}, + 232: {"mass": 232.0371563, "composition": 0.0}, + 233: {"mass": 233.0396355, "composition": 0.0}, + 234: {"mass": 234.0409523, "composition": 5.4e-05}, + 235: {"mass": 235.0439301, "composition": 0.007204}, + 236: {"mass": 236.0455682, "composition": 0.0}, + 237: {"mass": 237.0487304, "composition": 0.0}, + 238: {"mass": 238.0507884, "composition": 0.992742}, + 239: {"mass": 239.0542935, "composition": 0.0}, + 240: {"mass": 240.0565934, "composition": 0.0}, + 241: {"mass": 241.06033, "composition": 0.0}, + 242: {"mass": 242.06293, "composition": 0.0}, + 243: {"mass": 243.06699, "composition": 0.0}}, + 93: {219: {"mass": 219.03143, "composition": 0.0}, + 220: {"mass": 220.03254, "composition": 0.0}, + 221: {"mass": 221.03204, "composition": 0.0}, + 222: {"mass": 222.0333, "composition": 0.0}, + 223: {"mass": 223.03285, "composition": 0.0}, + 224: {"mass": 224.03422, "composition": 0.0}, + 225: {"mass": 225.033911, "composition": 0.0}, + 226: {"mass": 226.035188, "composition": 0.0}, + 227: {"mass": 227.034957, "composition": 0.0}, + 228: {"mass": 228.036067, "composition": 0.0}, + 229: {"mass": 229.036264, "composition": 0.0}, + 230: {"mass": 230.037828, "composition": 0.0}, + 231: {"mass": 231.038245, "composition": 0.0}, + 232: {"mass": 232.04011, "composition": 0.0}, + 233: {"mass": 233.040741, "composition": 0.0}, + 234: {"mass": 234.0428953, "composition": 0.0}, + 235: {"mass": 235.0440635, "composition": 0.0}, + 236: {"mass": 236.04657, "composition": 0.0}, + 237: {"mass": 237.0481736, "composition": 0.0}, + 238: {"mass": 238.0509466, "composition": 0.0}, + 239: {"mass": 239.0529392, "composition": 0.0}, + 240: {"mass": 240.056165, "composition": 0.0}, + 241: {"mass": 241.058253, "composition": 0.0}, + 242: {"mass": 242.06164, "composition": 0.0}, + 243: {"mass": 243.06428, "composition": 0.0}, + 244: {"mass": 244.06785, "composition": 0.0}, + 245: {"mass": 245.0708, "composition": 0.0}}, + 94: {228: {"mass": 228.038732, "composition": 0.0}, + 229: {"mass": 229.040144, "composition": 0.0}, + 230: {"mass": 230.03965, "composition": 0.0}, + 231: {"mass": 231.041102, "composition": 0.0}, + 232: {"mass": 232.041185, "composition": 0.0}, + 233: {"mass": 233.042998, "composition": 0.0}, + 234: {"mass": 234.0433174, "composition": 0.0}, + 235: {"mass": 235.045286, "composition": 0.0}, + 236: {"mass": 236.0460581, "composition": 0.0}, + 237: {"mass": 237.0484098, "composition": 0.0}, + 238: {"mass": 238.0495601, "composition": 0.0}, + 239: {"mass": 239.0521636, "composition": 0.0}, + 240: {"mass": 240.0538138, "composition": 0.0}, + 241: {"mass": 241.0568517, "composition": 0.0}, + 242: {"mass": 242.0587428, "composition": 0.0}, + 243: {"mass": 243.0620036, "composition": 0.0}, + 244: {"mass": 244.0642053, "composition": 0.0}, + 245: {"mass": 245.067826, "composition": 0.0}, + 246: {"mass": 246.070205, "composition": 0.0}, + 247: {"mass": 247.07419, "composition": 0.0}}, + 95: {230: {"mass": 230.04609, "composition": 0.0}, + 231: {"mass": 231.04556, "composition": 0.0}, + 232: {"mass": 232.04645, "composition": 0.0}, + 233: {"mass": 233.04644, "composition": 0.0}, + 234: {"mass": 234.04773, "composition": 0.0}, + 235: {"mass": 235.047908, "composition": 0.0}, + 236: {"mass": 236.04943, "composition": 0.0}, + 237: {"mass": 237.049996, "composition": 0.0}, + 238: {"mass": 238.051985, "composition": 0.0}, + 239: {"mass": 239.0530247, "composition": 0.0}, + 240: {"mass": 240.0553, "composition": 0.0}, + 241: {"mass": 241.0568293, "composition": 0.0}, + 242: {"mass": 242.0595494, "composition": 0.0}, + 243: {"mass": 243.0613813, "composition": 0.0}, + 244: {"mass": 244.0642851, "composition": 0.0}, + 245: {"mass": 245.0664548, "composition": 0.0}, + 246: {"mass": 246.069775, "composition": 0.0}, + 247: {"mass": 247.07209, "composition": 0.0}, + 248: {"mass": 248.07575, "composition": 0.0}, + 249: {"mass": 249.07848, "composition": 0.0}}, + 96: {232: {"mass": 232.04982, "composition": 0.0}, + 233: {"mass": 233.05077, "composition": 0.0}, + 234: {"mass": 234.05016, "composition": 0.0}, + 235: {"mass": 235.05154, "composition": 0.0}, + 236: {"mass": 236.051374, "composition": 0.0}, + 237: {"mass": 237.052869, "composition": 0.0}, + 238: {"mass": 238.053081, "composition": 0.0}, + 239: {"mass": 239.05491, "composition": 0.0}, + 240: {"mass": 240.0555297, "composition": 0.0}, + 241: {"mass": 241.0576532, "composition": 0.0}, + 242: {"mass": 242.058836, "composition": 0.0}, + 243: {"mass": 243.0613893, "composition": 0.0}, + 244: {"mass": 244.0627528, "composition": 0.0}, + 245: {"mass": 245.0654915, "composition": 0.0}, + 246: {"mass": 246.0672238, "composition": 0.0}, + 247: {"mass": 247.0703541, "composition": 0.0}, + 248: {"mass": 248.0723499, "composition": 0.0}, + 249: {"mass": 249.0759548, "composition": 0.0}, + 250: {"mass": 250.078358, "composition": 0.0}, + 251: {"mass": 251.082286, "composition": 0.0}, + 252: {"mass": 252.08487, "composition": 0.0}}, + 97: {234: {"mass": 234.05727, "composition": 0.0}, + 235: {"mass": 235.05658, "composition": 0.0}, + 236: {"mass": 236.05748, "composition": 0.0}, + 237: {"mass": 237.0571, "composition": 0.0}, + 238: {"mass": 238.0582, "composition": 0.0}, + 239: {"mass": 239.05824, "composition": 0.0}, + 240: {"mass": 240.05976, "composition": 0.0}, + 241: {"mass": 241.06016, "composition": 0.0}, + 242: {"mass": 242.06198, "composition": 0.0}, + 243: {"mass": 243.0630078, "composition": 0.0}, + 244: {"mass": 244.065181, "composition": 0.0}, + 245: {"mass": 245.0663618, "composition": 0.0}, + 246: {"mass": 246.068673, "composition": 0.0}, + 247: {"mass": 247.0703073, "composition": 0.0}, + 248: {"mass": 248.073088, "composition": 0.0}, + 249: {"mass": 249.0749877, "composition": 0.0}, + 250: {"mass": 250.0783167, "composition": 0.0}, + 251: {"mass": 251.080762, "composition": 0.0}, + 252: {"mass": 252.08431, "composition": 0.0}, + 253: {"mass": 253.08688, "composition": 0.0}, + 254: {"mass": 254.0906, "composition": 0.0}}, + 98: {237: {"mass": 237.062198, "composition": 0.0}, + 238: {"mass": 238.06149, "composition": 0.0}, + 239: {"mass": 239.06253, "composition": 0.0}, + 240: {"mass": 240.062256, "composition": 0.0}, + 241: {"mass": 241.06369, "composition": 0.0}, + 242: {"mass": 242.063754, "composition": 0.0}, + 243: {"mass": 243.06548, "composition": 0.0}, + 244: {"mass": 244.0660008, "composition": 0.0}, + 245: {"mass": 245.0680487, "composition": 0.0}, + 246: {"mass": 246.0688055, "composition": 0.0}, + 247: {"mass": 247.070965, "composition": 0.0}, + 248: {"mass": 248.0721851, "composition": 0.0}, + 249: {"mass": 249.0748539, "composition": 0.0}, + 250: {"mass": 250.0764062, "composition": 0.0}, + 251: {"mass": 251.0795886, "composition": 0.0}, + 252: {"mass": 252.0816272, "composition": 0.0}, + 253: {"mass": 253.0851345, "composition": 0.0}, + 254: {"mass": 254.087324, "composition": 0.0}, + 255: {"mass": 255.09105, "composition": 0.0}, + 256: {"mass": 256.09344, "composition": 0.0}}, + 99: {239: {"mass": 239.06823, "composition": 0.0}, + 240: {"mass": 240.06892, "composition": 0.0}, + 241: {"mass": 241.06856, "composition": 0.0}, + 242: {"mass": 242.06957, "composition": 0.0}, + 243: {"mass": 243.06951, "composition": 0.0}, + 244: {"mass": 244.07088, "composition": 0.0}, + 245: {"mass": 245.07125, "composition": 0.0}, + 246: {"mass": 246.0729, "composition": 0.0}, + 247: {"mass": 247.073622, "composition": 0.0}, + 248: {"mass": 248.075471, "composition": 0.0}, + 249: {"mass": 249.076411, "composition": 0.0}, + 250: {"mass": 250.07861, "composition": 0.0}, + 251: {"mass": 251.0799936, "composition": 0.0}, + 252: {"mass": 252.08298, "composition": 0.0}, + 253: {"mass": 253.0848257, "composition": 0.0}, + 254: {"mass": 254.0880222, "composition": 0.0}, + 255: {"mass": 255.090275, "composition": 0.0}, + 256: {"mass": 256.0936, "composition": 0.0}, + 257: {"mass": 257.09598, "composition": 0.0}, + 258: {"mass": 258.09952, "composition": 0.0}}, + 100: {241: {"mass": 241.07421, "composition": 0.0}, + 242: {"mass": 242.07343, "composition": 0.0}, + 243: {"mass": 243.07446, "composition": 0.0}, + 244: {"mass": 244.07404, "composition": 0.0}, + 245: {"mass": 245.07535, "composition": 0.0}, + 246: {"mass": 246.07535, "composition": 0.0}, + 247: {"mass": 247.07694, "composition": 0.0}, + 248: {"mass": 248.0771865, "composition": 0.0}, + 249: {"mass": 249.0789275, "composition": 0.0}, + 250: {"mass": 250.079521, "composition": 0.0}, + 251: {"mass": 251.08154, "composition": 0.0}, + 252: {"mass": 252.0824671, "composition": 0.0}, + 253: {"mass": 253.0851846, "composition": 0.0}, + 254: {"mass": 254.0868544, "composition": 0.0}, + 255: {"mass": 255.089964, "composition": 0.0}, + 256: {"mass": 256.0917745, "composition": 0.0}, + 257: {"mass": 257.0951061, "composition": 0.0}, + 258: {"mass": 258.09708, "composition": 0.0}, + 259: {"mass": 259.1006, "composition": 0.0}, + 260: {"mass": 260.10281, "composition": 0.0}}, + 101: {245: {"mass": 245.08081, "composition": 0.0}, + 246: {"mass": 246.08171, "composition": 0.0}, + 247: {"mass": 247.08152, "composition": 0.0}, + 248: {"mass": 248.08282, "composition": 0.0}, + 249: {"mass": 249.08291, "composition": 0.0}, + 250: {"mass": 250.08441, "composition": 0.0}, + 251: {"mass": 251.084774, "composition": 0.0}, + 252: {"mass": 252.08643, "composition": 0.0}, + 253: {"mass": 253.087144, "composition": 0.0}, + 254: {"mass": 254.08959, "composition": 0.0}, + 255: {"mass": 255.0910841, "composition": 0.0}, + 256: {"mass": 256.09389, "composition": 0.0}, + 257: {"mass": 257.0955424, "composition": 0.0}, + 258: {"mass": 258.0984315, "composition": 0.0}, + 259: {"mass": 259.10051, "composition": 0.0}, + 260: {"mass": 260.10365, "composition": 0.0}, + 261: {"mass": 261.10583, "composition": 0.0}, + 262: {"mass": 262.1091, "composition": 0.0}}, + 102: {248: {"mass": 248.08655, "composition": 0.0}, + 249: {"mass": 249.0878, "composition": 0.0}, + 250: {"mass": 250.08756, "composition": 0.0}, + 251: {"mass": 251.08894, "composition": 0.0}, + 252: {"mass": 252.088967, "composition": 0.0}, + 253: {"mass": 253.0905641, "composition": 0.0}, + 254: {"mass": 254.090956, "composition": 0.0}, + 255: {"mass": 255.093191, "composition": 0.0}, + 256: {"mass": 256.0942829, "composition": 0.0}, + 257: {"mass": 257.0968878, "composition": 0.0}, + 258: {"mass": 258.09821, "composition": 0.0}, + 259: {"mass": 259.10103, "composition": 0.0}, + 260: {"mass": 260.10264, "composition": 0.0}, + 261: {"mass": 261.1057, "composition": 0.0}, + 262: {"mass": 262.10746, "composition": 0.0}, + 263: {"mass": 263.11071, "composition": 0.0}, + 264: {"mass": 264.11273, "composition": 0.0}}, + 103: {251: {"mass": 251.09418, "composition": 0.0}, + 252: {"mass": 252.09526, "composition": 0.0}, + 253: {"mass": 253.09509, "composition": 0.0}, + 254: {"mass": 254.09648, "composition": 0.0}, + 255: {"mass": 255.096562, "composition": 0.0}, + 256: {"mass": 256.098494, "composition": 0.0}, + 257: {"mass": 257.099418, "composition": 0.0}, + 258: {"mass": 258.10176, "composition": 0.0}, + 259: {"mass": 259.102902, "composition": 0.0}, + 260: {"mass": 260.1055, "composition": 0.0}, + 261: {"mass": 261.10688, "composition": 0.0}, + 262: {"mass": 262.10961, "composition": 0.0}, + 263: {"mass": 263.11136, "composition": 0.0}, + 264: {"mass": 264.1142, "composition": 0.0}, + 265: {"mass": 265.11619, "composition": 0.0}, + 266: {"mass": 266.11983, "composition": 0.0}}, + 104: {253: {"mass": 253.10044, "composition": 0.0}, + 254: {"mass": 254.10005, "composition": 0.0}, + 255: {"mass": 255.10127, "composition": 0.0}, + 256: {"mass": 256.101152, "composition": 0.0}, + 257: {"mass": 257.102918, "composition": 0.0}, + 258: {"mass": 258.103428, "composition": 0.0}, + 259: {"mass": 259.105596, "composition": 0.0}, + 260: {"mass": 260.10644, "composition": 0.0}, + 261: {"mass": 261.108773, "composition": 0.0}, + 262: {"mass": 262.10992, "composition": 0.0}, + 263: {"mass": 263.11249, "composition": 0.0}, + 264: {"mass": 264.11388, "composition": 0.0}, + 265: {"mass": 265.11668, "composition": 0.0}, + 266: {"mass": 266.11817, "composition": 0.0}, + 267: {"mass": 267.12179, "composition": 0.0}, + 268: {"mass": 268.12397, "composition": 0.0}}, + 105: {255: {"mass": 255.10707, "composition": 0.0}, + 256: {"mass": 256.10789, "composition": 0.0}, + 257: {"mass": 257.10758, "composition": 0.0}, + 258: {"mass": 258.10928, "composition": 0.0}, + 259: {"mass": 259.109492, "composition": 0.0}, + 260: {"mass": 260.1113, "composition": 0.0}, + 261: {"mass": 261.11192, "composition": 0.0}, + 262: {"mass": 262.11407, "composition": 0.0}, + 263: {"mass": 263.11499, "composition": 0.0}, + 264: {"mass": 264.11741, "composition": 0.0}, + 265: {"mass": 265.11861, "composition": 0.0}, + 266: {"mass": 266.12103, "composition": 0.0}, + 267: {"mass": 267.12247, "composition": 0.0}, + 268: {"mass": 268.12567, "composition": 0.0}, + 269: {"mass": 269.12791, "composition": 0.0}, + 270: {"mass": 270.13136, "composition": 0.0}}, + 106: {258: {"mass": 258.11298, "composition": 0.0}, + 259: {"mass": 259.1144, "composition": 0.0}, + 260: {"mass": 260.114384, "composition": 0.0}, + 261: {"mass": 261.115949, "composition": 0.0}, + 262: {"mass": 262.116337, "composition": 0.0}, + 263: {"mass": 263.11829, "composition": 0.0}, + 264: {"mass": 264.11893, "composition": 0.0}, + 265: {"mass": 265.12109, "composition": 0.0}, + 266: {"mass": 266.12198, "composition": 0.0}, + 267: {"mass": 267.12436, "composition": 0.0}, + 268: {"mass": 268.12539, "composition": 0.0}, + 269: {"mass": 269.12863, "composition": 0.0}, + 270: {"mass": 270.13043, "composition": 0.0}, + 271: {"mass": 271.13393, "composition": 0.0}, + 272: {"mass": 272.13589, "composition": 0.0}, + 273: {"mass": 273.13958, "composition": 0.0}}, + 107: {260: {"mass": 260.12166, "composition": 0.0}, + 261: {"mass": 261.12145, "composition": 0.0}, + 262: {"mass": 262.12297, "composition": 0.0}, + 263: {"mass": 263.12292, "composition": 0.0}, + 264: {"mass": 264.12459, "composition": 0.0}, + 265: {"mass": 265.12491, "composition": 0.0}, + 266: {"mass": 266.12679, "composition": 0.0}, + 267: {"mass": 267.1275, "composition": 0.0}, + 268: {"mass": 268.12969, "composition": 0.0}, + 269: {"mass": 269.13042, "composition": 0.0}, + 270: {"mass": 270.13336, "composition": 0.0}, + 271: {"mass": 271.13526, "composition": 0.0}, + 272: {"mass": 272.13826, "composition": 0.0}, + 273: {"mass": 273.14024, "composition": 0.0}, + 274: {"mass": 274.14355, "composition": 0.0}, + 275: {"mass": 275.14567, "composition": 0.0}}, + 108: {263: {"mass": 263.12852, "composition": 0.0}, + 264: {"mass": 264.128357, "composition": 0.0}, + 265: {"mass": 265.129793, "composition": 0.0}, + 266: {"mass": 266.130046, "composition": 0.0}, + 267: {"mass": 267.13167, "composition": 0.0}, + 268: {"mass": 268.13186, "composition": 0.0}, + 269: {"mass": 269.13375, "composition": 0.0}, + 270: {"mass": 270.13429, "composition": 0.0}, + 271: {"mass": 271.13717, "composition": 0.0}, + 272: {"mass": 272.1385, "composition": 0.0}, + 273: {"mass": 273.14168, "composition": 0.0}, + 274: {"mass": 274.1433, "composition": 0.0}, + 275: {"mass": 275.14667, "composition": 0.0}, + 276: {"mass": 276.14846, "composition": 0.0}, + 277: {"mass": 277.1519, "composition": 0.0}}, + 109: {265: {"mass": 265.136, "composition": 0.0}, + 266: {"mass": 266.13737, "composition": 0.0}, + 267: {"mass": 267.13719, "composition": 0.0}, + 268: {"mass": 268.13865, "composition": 0.0}, + 269: {"mass": 269.13882, "composition": 0.0}, + 270: {"mass": 270.14033, "composition": 0.0}, + 271: {"mass": 271.14074, "composition": 0.0}, + 272: {"mass": 272.14341, "composition": 0.0}, + 273: {"mass": 273.1444, "composition": 0.0}, + 274: {"mass": 274.14724, "composition": 0.0}, + 275: {"mass": 275.14882, "composition": 0.0}, + 276: {"mass": 276.15159, "composition": 0.0}, + 277: {"mass": 277.15327, "composition": 0.0}, + 278: {"mass": 278.15631, "composition": 0.0}, + 279: {"mass": 279.15808, "composition": 0.0}}, + 110: {267: {"mass": 267.14377, "composition": 0.0}, + 268: {"mass": 268.14348, "composition": 0.0}, + 269: {"mass": 269.144752, "composition": 0.0}, + 270: {"mass": 270.144584, "composition": 0.0}, + 271: {"mass": 271.14595, "composition": 0.0}, + 272: {"mass": 272.14602, "composition": 0.0}, + 273: {"mass": 273.14856, "composition": 0.0}, + 274: {"mass": 274.14941, "composition": 0.0}, + 275: {"mass": 275.15203, "composition": 0.0}, + 276: {"mass": 276.15303, "composition": 0.0}, + 277: {"mass": 277.15591, "composition": 0.0}, + 278: {"mass": 278.15704, "composition": 0.0}, + 279: {"mass": 279.1601, "composition": 0.0}, + 280: {"mass": 280.16131, "composition": 0.0}, + 281: {"mass": 281.16451, "composition": 0.0}}, + 111: {272: {"mass": 272.15327, "composition": 0.0}, + 273: {"mass": 273.15313, "composition": 0.0}, + 274: {"mass": 274.15525, "composition": 0.0}, + 275: {"mass": 275.15594, "composition": 0.0}, + 276: {"mass": 276.15833, "composition": 0.0}, + 277: {"mass": 277.15907, "composition": 0.0}, + 278: {"mass": 278.16149, "composition": 0.0}, + 279: {"mass": 279.16272, "composition": 0.0}, + 280: {"mass": 280.16514, "composition": 0.0}, + 281: {"mass": 281.16636, "composition": 0.0}, + 282: {"mass": 282.16912, "composition": 0.0}, + 283: {"mass": 283.17054, "composition": 0.0}}, + 112: {276: {"mass": 276.16141, "composition": 0.0}, + 277: {"mass": 277.16364, "composition": 0.0}, + 278: {"mass": 278.16416, "composition": 0.0}, + 279: {"mass": 279.16654, "composition": 0.0}, + 280: {"mass": 280.16715, "composition": 0.0}, + 281: {"mass": 281.16975, "composition": 0.0}, + 282: {"mass": 282.1705, "composition": 0.0}, + 283: {"mass": 283.17327, "composition": 0.0}, + 284: {"mass": 284.17416, "composition": 0.0}, + 285: {"mass": 285.17712, "composition": 0.0}}, + 113: {278: {"mass": 278.17058, "composition": 0.0}, + 279: {"mass": 279.17095, "composition": 0.0}, + 280: {"mass": 280.17293, "composition": 0.0}, + 281: {"mass": 281.17348, "composition": 0.0}, + 282: {"mass": 282.17567, "composition": 0.0}, + 283: {"mass": 283.17657, "composition": 0.0}, + 284: {"mass": 284.17873, "composition": 0.0}, + 285: {"mass": 285.17973, "composition": 0.0}, + 286: {"mass": 286.18221, "composition": 0.0}, + 287: {"mass": 287.18339, "composition": 0.0}}, + 114: {285: {"mass": 285.18364, "composition": 0.0}, + 286: {"mass": 286.18423, "composition": 0.0}, + 287: {"mass": 287.18678, "composition": 0.0}, + 288: {"mass": 288.18757, "composition": 0.0}, + 289: {"mass": 289.19042, "composition": 0.0}}, + 115: {287: {"mass": 287.1907, "composition": 0.0}, + 288: {"mass": 288.19274, "composition": 0.0}, + 289: {"mass": 289.19363, "composition": 0.0}, + 290: {"mass": 290.19598, "composition": 0.0}, + 291: {"mass": 291.19707, "composition": 0.0}}, + 116: {289: {"mass": 289.19816, "composition": 0.0}, + 290: {"mass": 290.19864, "composition": 0.0}, + 291: {"mass": 291.20108, "composition": 0.0}, + 292: {"mass": 292.20174, "composition": 0.0}, + 293: {"mass": 293.20449, "composition": 0.0}}, + 117: {291: {"mass": 291.20553, "composition": 0.0}, + 292: {"mass": 292.20746, "composition": 0.0}, + 293: {"mass": 293.20824, "composition": 0.0}, + 294: {"mass": 294.21046, "composition": 0.0}}, + 118: {293: {"mass": 293.21356, "composition": 0.0}, + 294: {"mass": 294.21392, "composition": 0.0}, + 295: {"mass": 295.21624, "composition": 0.0}}} diff --git a/ifes_apt_tc_data_modeling/utils/string_handling.py b/ifes_apt_tc_data_modeling/utils/string_handling.py index 424347c..8a75f3e 100644 --- a/ifes_apt_tc_data_modeling/utils/string_handling.py +++ b/ifes_apt_tc_data_modeling/utils/string_handling.py @@ -22,12 +22,6 @@ # limitations under the License. # -# pylint: disable=no-member,duplicate-code - -import typing - -from typing import Tuple - def rchop(string: str = "", suffix: str = "") -> str: """Right-chop a string.""" diff --git a/ifes_apt_tc_data_modeling/utils/utils.py b/ifes_apt_tc_data_modeling/utils/utils.py index 96ab3f7..c9c2835 100644 --- a/ifes_apt_tc_data_modeling/utils/utils.py +++ b/ifes_apt_tc_data_modeling/utils/utils.py @@ -24,27 +24,17 @@ # pylint: disable=no-member,duplicate-code -import re - -import typing - from typing import Tuple - -import mmap - import numpy as np from ase.data import atomic_numbers, chemical_symbols - from ifes_apt_tc_data_modeling.utils.nist_isotope_data import isotopes - -from ifes_apt_tc_data_modeling.utils.definitions import MAX_NUMBER_OF_ION_SPECIES -from ifes_apt_tc_data_modeling.utils.definitions import MAX_NUMBER_OF_ATOMS_PER_ION -from ifes_apt_tc_data_modeling.utils.definitions import MQ_EPSILON +from ifes_apt_tc_data_modeling.utils.definitions import \ + MAX_NUMBER_OF_ATOMS_PER_ION, MQ_EPSILON def isotope_to_hash(proton_number: int = 0, - neutron_number: int = 0) -> int: + neutron_number: int = 0) -> int: """Encode an isotope to a hashvalue.""" n_protons = np.uint16(proton_number) n_neutrons = np.uint16(neutron_number) @@ -110,7 +100,7 @@ def create_isotope_vector(building_blocks: list) -> np.ndarray: neutron_number = mass_number - proton_number assert proton_number in isotopes.keys(), \ "No isotopes for proton_number " + str(proton_number) + " via ase!" - assert mass_number in isotopes[proton_number].keys(), \ + assert mass_number in isotopes[proton_number], \ "No isotope for mass_number " + str(mass_number) + " via ase!" hashvector.append(isotope_to_hash(proton_number, neutron_number)) else: @@ -170,12 +160,11 @@ def isotope_vector_to_human_readable_name(ivec: np.ndarray, charge_state: np.int else: human_readable = human_readable.rstrip() return human_readable - else: - return "unknown_iontype" + return "unknown_iontype" def is_range_overlapping(interval: np.ndarray, - interval_set: np.float64) -> bool: + interval_set: np.float64) -> bool: """Check if interval overlaps within with members of interval set.""" assert np.shape(interval) == (2,), "Interval needs to have two columns!" assert np.shape(interval_set)[1] == 2, \ diff --git a/pyproject.toml b/pyproject.toml index fe02f70..0a9acc4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,10 @@ dependencies = [ dev = [ "twine", "jupyterlab_h5web", - "jupyterlab" + "jupyterlab", + "mypy", + "pylint", + "pycodestyle" ] # [tool.setuptools] diff --git a/tests/TestsForDevelopers.ipynb b/tests/TestsForDevelopers.ipynb index 93da2a5..c52717c 100644 --- a/tests/TestsForDevelopers.ipynb +++ b/tests/TestsForDevelopers.ipynb @@ -20,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "fc6c2ca9-ba62-4580-8eed-223467c58b22", "metadata": { "tags": [] @@ -61,7 +61,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "d239daae-b751-4f18-96c9-1f1e87ffacb6", "metadata": {}, "outputs": [], @@ -72,7 +72,27 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, + "id": "ae40fca2-f0d3-49c9-8563-faddcc5b924c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]\n" + ] + } + ], + "source": [ + "lst = [2]\n", + "lst.extend([3] * 10)\n", + "print(lst)" + ] + }, + { + "cell_type": "code", + "execution_count": null, "id": "8203e807-847d-45bd-853a-3adfb7dcb1b1", "metadata": {}, "outputs": [], @@ -82,578 +102,10 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "6b5b4e1f-847a-4579-bef1-15ba2fe0faf4", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "/home/kaiobach/Research/hu_hu_hu/sprint17/ifes/ifes_apt_tc_data_modeling/tests/data/env/examples_without_provenance/ErMnO.env parsed successfully\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", - " [8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "O +\n", - "charge_state\n", - "1\n", - "ranges\n", - "[[15.88 16.84]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Mn ++\n", - "charge_state\n", - "2\n", - "ranges\n", - "[[27.33 27.95]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er ++\n", - "charge_state\n", - "2\n", - "ranges\n", - "[[81.89 82.36]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er ++\n", - "charge_state\n", - "2\n", - "ranges\n", - "[[82.91 83.41]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er ++\n", - "charge_state\n", - "2\n", - "ranges\n", - "[[83.41 83.91]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er ++\n", - "charge_state\n", - "2\n", - "ranges\n", - "[[83.93 84.9 ]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er ++\n", - "charge_state\n", - "2\n", - "ranges\n", - "[[84.92 85.45]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er +++\n", - "charge_state\n", - "3\n", - "ranges\n", - "[[53.93 54.13]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er +++\n", - "charge_state\n", - "3\n", - "ranges\n", - "[[54.49 54.75]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er +++\n", - "charge_state\n", - "3\n", - "ranges\n", - "[[55.09 55.55]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er +++\n", - "charge_state\n", - "3\n", - "ranges\n", - "[[55.543 55.88 ]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er +++\n", - "charge_state\n", - "3\n", - "ranges\n", - "[[55.877 56.27 ]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er +++\n", - "charge_state\n", - "3\n", - "ranges\n", - "[[56.5 56.97]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Mn +\n", - "charge_state\n", - "1\n", - "ranges\n", - "[[54.77 55.02]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[25 25 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[25 25 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [25 25 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Mn Mn O ++\n", - "charge_state\n", - "2\n", - "ranges\n", - "[[62.85 63.13]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[25 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[25 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [25 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Mn O O ++\n", - "charge_state\n", - "2\n", - "ranges\n", - "[[43.38 43.65]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[25 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[25 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [25 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Mn O +\n", - "charge_state\n", - "1\n", - "ranges\n", - "[[70.59 72.81]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[25 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[25 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [25 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Mn O O +\n", - "charge_state\n", - "1\n", - "ranges\n", - "[[86.76 87.27]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er O ++\n", - "charge_state\n", - "2\n", - "ranges\n", - "[[89.81 93.86]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er O O ++\n", - "charge_state\n", - "2\n", - "ranges\n", - "[[ 98.8 101.36]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[25 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[25 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [25 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Mn O O O +\n", - "charge_state\n", - "1\n", - "ranges\n", - "[[102.77 103.53]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er O +\n", - "charge_state\n", - "1\n", - "ranges\n", - "[[180.33 187.3 ]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[68 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[68 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]\n", - " [68 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", - " 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "Er O O +\n", - "charge_state\n", - "1\n", - "ranges\n", - "[[197. 203.38]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", - " [8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "O O +\n", - "charge_state\n", - "1\n", - "ranges\n", - "[[31.72 34.3 ]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", - " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "unknown_iontype\n", - "charge_state\n", - "0\n", - "ranges\n", - "[[22.24 22.72]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n", - "ion_type\n", - "\n", - "isotope_vector\n", - "[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", - "nuclid_list\n", - "[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", - " [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]\n", - "human-readable name\n", - "unknown_iontype\n", - "charge_state\n", - "0\n", - "ranges\n", - "[[0.93 3.18]]\n", - "comment\n", - "\n", - "color\n", - "\n", - "volume\n", - "0.0\n" - ] - } - ], + "outputs": [], "source": [ "env = ReadEnvFileFormat(f\"{prefix}/{fnm[0]}\")\n", "for m_ion in env.env[\"molecular_ions\"]:\n", @@ -662,158 +114,10 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "id": "9dd0fa4d-650d-4978-982c-6f9b2253d614", - "metadata": { - "collapsed": true, - "jupyter": { - "outputs_hidden": true - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "#\n", - "#\n", - "#\t\tGerald Da Costa\t / Alain Bostel\n", - "#\n", - "#\t\tCopyright (C)\tGPM de Rouen\n", - "#\t\tUMR 6634 CNRS - Universite et Insa de Rouen\n", - "#\t\t76821 Mont Saint Aignan Cedex\n", - "#\n", - "#\t\tRev 2.0 : Environment file for 3D Atom Probe\n", - "#\n", - "#\n", - "# Version Id\n", - "Rev_2.0\n", - "# Alloy definition\n", - "# Number of elements / Number of mass ranges\n", - "12\t26\n", - "# List of Element and Color components ( Red / Green / Blue )\n", - "O\t0.0\t1.0\t0.0\n", - "Mn\t0.0\t0.5\t1.0\n", - "Er\t1.0\t0.0\t0.0\n", - "Mn2O\t0.0\t0.0\t0.0\n", - "MnO2\t0.5\t0.5\t0.5\n", - "MnO\t0.5\t0.5\t0.5\n", - "ErO\t1.0\t0.0\t0.0\n", - "ErO2\t1.0\t0.0\t0.0\n", - "MnO3\t0.5\t0.5\t0.5\n", - "O2\t0.0\t0.0\t1.0\n", - "X23\t0.3\t0.5\t0.5\n", - "Hyd\t0.0\t0.0\t0.0\n", - "# Definition of Mass ranges / Atomic volumes / Increment for concentration\n", - "O\t15.880\t16.840\t20.000\t1.000\n", - "Mn\t27.330\t27.950\t11.660\t1.000\n", - "Er\t81.890\t82.360\t11.660\t1.000\n", - "Er\t82.910\t83.410\t11.660\t1.000\n", - "Er\t83.410\t83.910\t11.660\t1.000\n", - "Er\t83.930\t84.900\t11.660\t1.000\n", - "Er\t84.920\t85.450\t11.660\t1.000\n", - "Er\t53.930\t54.130\t11.660\t1.000\n", - "Er\t54.490\t54.750\t11.660\t1.000\n", - "Er\t55.090\t55.550\t11.660\t1.000\n", - "Er\t55.543\t55.880\t11.660\t1.000\n", - "Er\t55.877\t56.270\t11.660\t1.000\n", - "Er\t56.500\t56.970\t11.660\t1.000\n", - "Mn\t54.770\t55.020\t11.660\t1.000\n", - "Mn2O\t62.850\t63.130\t11.660\t1.000\n", - "MnO2\t43.380\t43.650\t11.660\t1.000\n", - "MnO\t70.590\t72.810\t11.660\t1.000\n", - "MnO2\t86.760\t87.270\t11.660\t1.000\n", - "ErO\t89.810\t93.860\t11.660\t1.000\n", - "ErO2\t98.800\t101.360\t11.660\t1.000\n", - "MnO3\t102.770\t103.530\t11.660\t1.000\n", - "ErO\t180.330\t187.300\t11.660\t1.000\n", - "ErO2\t197.000\t203.380\t11.660\t1.000\n", - "O2\t31.720\t34.300\t11.660\t1.000\n", - "X23\t22.240\t22.720\t11.660\t1.000\n", - "Hyd\t0.930\t3.180\t11.660\t1.000\n", - "# Atom probe definition\n", - "# Flight length (m)\n", - "0.100500\n", - "# Pulse fraction (%)\n", - "0.000000\n", - "# Coupling factor (%)\n", - "100.000000\n", - "# Time added to the tof for mass calculation (ns)\n", - "-3.000000\n", - "# Reflectron factor\n", - "1.006500\n", - "# Input Voltage of the detection system (kV)\n", - "2.700000\n", - "# Distance between Grid and MCPin (m)\n", - "0.014000\n", - "# Space definition\n", - "# Ebeta value\n", - "24.000000\n", - "# Projection point value (m+1)\n", - "1.600000\n", - "# Surface of the detection system (m²)\n", - "0.004656\n", - "# Efficiency of the detection system\n", - "0.550000\n", - "# Angle used for the rotation of the tip\n", - "0.000000\n", - "# Angle used for the tilt of the tip\n", - "0.000000\n", - "---->['O', '15.880', '16.840', '20.000', '1.000']\n", - "['O']\n", - "---->['Mn', '27.330', '27.950', '11.660', '1.000']\n", - "['Mn']\n", - "---->['Er', '81.890', '82.360', '11.660', '1.000']\n", - "['Er']\n", - "---->['Er', '82.910', '83.410', '11.660', '1.000']\n", - "['Er']\n", - "---->['Er', '83.410', '83.910', '11.660', '1.000']\n", - "['Er']\n", - "---->['Er', '83.930', '84.900', '11.660', '1.000']\n", - "['Er']\n", - "---->['Er', '84.920', '85.450', '11.660', '1.000']\n", - "['Er']\n", - "---->['Er', '53.930', '54.130', '11.660', '1.000']\n", - "['Er']\n", - "---->['Er', '54.490', '54.750', '11.660', '1.000']\n", - "['Er']\n", - "---->['Er', '55.090', '55.550', '11.660', '1.000']\n", - "['Er']\n", - "---->['Er', '55.543', '55.880', '11.660', '1.000']\n", - "['Er']\n", - "---->['Er', '55.877', '56.270', '11.660', '1.000']\n", - "['Er']\n", - "---->['Er', '56.500', '56.970', '11.660', '1.000']\n", - "['Er']\n", - "---->['Mn', '54.770', '55.020', '11.660', '1.000']\n", - "['Mn']\n", - "---->['Mn2O', '62.850', '63.130', '11.660', '1.000']\n", - "['Mn', 'Mn', 'O']\n", - "---->['MnO2', '43.380', '43.650', '11.660', '1.000']\n", - "['Mn', 'O', 'O']\n", - "---->['MnO', '70.590', '72.810', '11.660', '1.000']\n", - "['Mn', 'O']\n", - "---->['MnO2', '86.760', '87.270', '11.660', '1.000']\n", - "['Mn', 'O', 'O']\n", - "---->['ErO', '89.810', '93.860', '11.660', '1.000']\n", - "['Er', 'O']\n", - "---->['ErO2', '98.800', '101.360', '11.660', '1.000']\n", - "['Er', 'O', 'O']\n", - "---->['MnO3', '102.770', '103.530', '11.660', '1.000']\n", - "['Mn', 'O', 'O', 'O']\n", - "---->['ErO', '180.330', '187.300', '11.660', '1.000']\n", - "['Er', 'O']\n", - "---->['ErO2', '197.000', '203.380', '11.660', '1.000']\n", - "['Er', 'O', 'O']\n", - "---->['O2', '31.720', '34.300', '11.660', '1.000']\n", - "['O', 'O']\n", - "---->['X23', '22.240', '22.720', '11.660', '1.000']\n", - "[]\n", - "---->['Hyd', '0.930', '3.180', '11.660', '1.000']\n", - "[]\n" - ] - } - ], + "metadata": {}, + "outputs": [], "source": [ "def get_smart_chemical_symbols():\n", " priority_queue = []\n", From 2f9c095bb8be8016020be4dd0ef5322168c51051 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 28 Dec 2023 22:36:47 +0100 Subject: [PATCH 03/20] Further linting, styling, pycodestyle ignore only E0501 --- ifes_apt_tc_data_modeling/apt/apt6_headers.py | 3 +- .../apt/apt6_sections.py | 3 +- ifes_apt_tc_data_modeling/env/env_reader.py | 1 + ifes_apt_tc_data_modeling/epos/epos_reader.py | 6 +- ifes_apt_tc_data_modeling/fig/fig_reader.py | 3 +- ifes_apt_tc_data_modeling/nexus/nx_ion.py | 2 +- ifes_apt_tc_data_modeling/rng/rng_reader.py | 2 +- .../utils/definitions.py | 3 +- .../utils/molecular_ions.py | 31 +- .../utils/nist_isotope_data.py | 6660 +++++++++-------- .../utils/string_handling.py | 3 +- ifes_apt_tc_data_modeling/utils/utils.py | 29 +- 12 files changed, 3381 insertions(+), 3365 deletions(-) diff --git a/ifes_apt_tc_data_modeling/apt/apt6_headers.py b/ifes_apt_tc_data_modeling/apt/apt6_headers.py index 70d13a8..b4c3785 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_headers.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_headers.py @@ -1,4 +1,3 @@ -# AMETEK APT(6) data exchange file reader used by atom probe microscopists. # # Copyright The NOMAD Authors. # @@ -17,6 +16,8 @@ # limitations under the License. # +"""AMETEK APT(6) data exchange file reader used by atom probe microscopists.""" + # pylint: disable=no-member,duplicate-code import numpy as np diff --git a/ifes_apt_tc_data_modeling/apt/apt6_sections.py b/ifes_apt_tc_data_modeling/apt/apt6_sections.py index f81c18a..6f70e93 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_sections.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_sections.py @@ -1,4 +1,3 @@ -# AMETEK APT(6) data exchange file reader used by atom probe microscopists. # # Copyright The NOMAD Authors. # @@ -17,6 +16,8 @@ # limitations under the License. # +"""AMETEK APT(6) data exchange file reader used by atom probe microscopists.""" + # pylint: disable=no-member,duplicate-code import numpy as np diff --git a/ifes_apt_tc_data_modeling/env/env_reader.py b/ifes_apt_tc_data_modeling/env/env_reader.py index 70e3671..f1fe1e3 100644 --- a/ifes_apt_tc_data_modeling/env/env_reader.py +++ b/ifes_apt_tc_data_modeling/env/env_reader.py @@ -33,6 +33,7 @@ def get_smart_chemical_symbols(): + """Organize element symbols such that search H does not match He.""" priority_queue = [] for symbol in chemical_symbols: if len(symbol) == 2: diff --git a/ifes_apt_tc_data_modeling/epos/epos_reader.py b/ifes_apt_tc_data_modeling/epos/epos_reader.py index 4bd8b57..8828544 100644 --- a/ifes_apt_tc_data_modeling/epos/epos_reader.py +++ b/ifes_apt_tc_data_modeling/epos/epos_reader.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python3 -# ePOS file format reader used by atom probe microscopists. # # Copyright The NOMAD Authors. # @@ -18,14 +16,14 @@ # limitations under the License. # +"""ePOS file format reader used by atom probe microscopists.""" + # 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 diff --git a/ifes_apt_tc_data_modeling/fig/fig_reader.py b/ifes_apt_tc_data_modeling/fig/fig_reader.py index 27f621f..fb12049 100644 --- a/ifes_apt_tc_data_modeling/fig/fig_reader.py +++ b/ifes_apt_tc_data_modeling/fig/fig_reader.py @@ -87,7 +87,8 @@ def read_fig_txt(self): multiplier = 1 if len(suffix) == 1: multiplier = int(suffix[0]) - symbol = isotope.replace(f"{mass_number}", "").replace(f"{multiplier}", "").replace(" ", "") + symbol = isotope.replace( + f"{mass_number}", "").replace(f"{multiplier}", "").replace(" ", "") if (symbol != "X") and (symbol in chemical_symbols): proton_number = atomic_numbers[symbol] neutron_number = mass_number - proton_number diff --git a/ifes_apt_tc_data_modeling/nexus/nx_ion.py b/ifes_apt_tc_data_modeling/nexus/nx_ion.py index a959240..e23ea10 100644 --- a/ifes_apt_tc_data_modeling/nexus/nx_ion.py +++ b/ifes_apt_tc_data_modeling/nexus/nx_ion.py @@ -136,7 +136,7 @@ def add_charge_state_model(self, "nat_abun_prod_vector": [], "min_half_life_vector": []} for key, val in parameters.items(): - if key not in self.charge_state_model.keys(): + if key not in self.charge_state_model: self.charge_state_model[key] = val n_cand = len(candidates) # print("n_cand " + str(n_cand)) diff --git a/ifes_apt_tc_data_modeling/rng/rng_reader.py b/ifes_apt_tc_data_modeling/rng/rng_reader.py index aa672f9..68aa136 100644 --- a/ifes_apt_tc_data_modeling/rng/rng_reader.py +++ b/ifes_apt_tc_data_modeling/rng/rng_reader.py @@ -18,7 +18,7 @@ """RNG range file reader used by atom probe microscopists.""" -# pylint: disable=no-member,duplicate-code +# pylint: disable=no-member,duplicate-code,line-too-long import re import numpy as np diff --git a/ifes_apt_tc_data_modeling/utils/definitions.py b/ifes_apt_tc_data_modeling/utils/definitions.py index 487084d..c5e65bb 100644 --- a/ifes_apt_tc_data_modeling/utils/definitions.py +++ b/ifes_apt_tc_data_modeling/utils/definitions.py @@ -1,4 +1,3 @@ -# Generic definitions when parsing molecular ions in atom probe microscopy. # # Also convenience functions are included which translate human-readable ion # names into the isotope_vector description proposed by Kuehbach et al. in @@ -22,6 +21,8 @@ # limitations under the License. # +"""Generic definitions when parsing molecular ions in atom probe microscopy.""" + # pylint: disable=no-member,duplicate-code import numpy as np diff --git a/ifes_apt_tc_data_modeling/utils/molecular_ions.py b/ifes_apt_tc_data_modeling/utils/molecular_ions.py index c3058c1..ab0e15b 100644 --- a/ifes_apt_tc_data_modeling/utils/molecular_ions.py +++ b/ifes_apt_tc_data_modeling/utils/molecular_ions.py @@ -18,7 +18,7 @@ """Utility tool to work with molecular ions in atom probe microscopy.""" -# pylint: disable=no-member,duplicate-code +# pylint: disable=line-too-long import numpy as np import radioactivedecay as rd @@ -49,6 +49,7 @@ class MolecularIonCandidate: + """Define """ def __init__(self, ivec=[], charge_state=0, @@ -62,14 +63,14 @@ def __init__(self, self.shortest_half_life = np.float64(min_half_life) def unique_keyword(self): - keyword = "" - keyword += isotope_vector_to_dict_keyword( - np.sort(np.asarray(self.isotope_vector, np.uint16), kind="stable")[::-1]) - keyword += "__" + str(self.charge_state) + """Generate unique keyword.""" + keyword = f"{isotope_vector_to_dict_keyword(np.sort(np.asarray(self.isotope_vector, np.uint16), kind='stable')[::-1])}__{self.charge_state}" return keyword class MolecularIonBuilder: + """Class for holding properties of constructed molecular ions.""" + def __init__(self, min_abundance=1.0e-6, min_abundance_product=1.0e-6, @@ -182,6 +183,7 @@ def get_isotope_mass_sum(self, nuclid_arr=[]): return mass def get_natural_abundance_product(self, nuclid_arr=[]): + """Get natural abundance product.""" abun_prod = 1. for hashvalue in nuclid_arr: if hashvalue != 0: @@ -189,6 +191,7 @@ def get_natural_abundance_product(self, nuclid_arr=[]): return abun_prod def get_shortest_half_life(self, nuclid_arr=[]): + """Get shortest half life for set of nuclids.""" min_half_life = self.parms["min_half_life"] for hashvalue in nuclid_arr: if hashvalue != 0: @@ -207,6 +210,7 @@ def get_shortest_half_life(self, nuclid_arr=[]): return min_half_life def combinatorics(self, element_arr, low, high): + """Combinatorial analysis which (molecular) elements match within [low, high].""" # RNG/RRNG range files do store element information for each range # BUT not isotope information, correspondingly this can yield # only an isotope_vector whose hashvalues have ALL in common @@ -239,6 +243,7 @@ def combinatorics(self, element_arr, low, high): def iterate_molecular_ion(self, element_arr, jth_nuclids, cand_arr_prev, i, max_n, low, high): + """Recursive analysis of combinatorics on molecular ions.""" if i < (max_n - 1): for nuclid in jth_nuclids: @@ -260,16 +265,20 @@ def iterate_molecular_ion(self, mass_to_charge = new_mass / new_chrg if mass_to_charge < low: break - # we can break the entire charge state generation here already instead of continue - # because already the current mq is left out of interval [mqmin, mqmax] - # and all mq in the next iterations will result in even lower mass-to-charge - # you walk to the left increasing your distance to the left bound + # we can break the entire charge state generation here already + # instead of continue because already the current mq is left out + # of interval [mqmin, mqmax] + # and all mq in the next iterations will result in even lower + # mass-to-charge you walk to the left increasing your + # distance to the left bound if mass_to_charge > high: - # can be optimized and broken out of earlier if testing first chrg == 1 + # can be optimized and broken out of earlier + # if testing first chrg == 1 # and then chrg == APTMOLECULARION_MAX_CHANGE continue # must not be break here because with adding more charge - # we usually walk from right to left eventually into [low, high] ! + # we usually walk from right to left eventually into + # [low, high] ! # molecular ion is within user-specified bounds self.candidates.append( MolecularIonCandidate(cand_arr_curr, diff --git a/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py b/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py index cd12cf6..56cd8bf 100644 --- a/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py +++ b/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py @@ -16,7 +16,9 @@ # limitations under the License. # -# pylint: disable=E1101 +"""Look-up table of stable and radioactive nuclids for all elements.""" + +# pylint: disable=too-many-lines # this is a copy of downloadable data from ase # from ase.data.isotopes import download_isotope_data @@ -25,3353 +27,3353 @@ isotopes = {1: {1: {"mass": 1.00782503223, "composition": 0.999885}, 2: {"mass": 2.01410177812, "composition": 0.000115}, - 3: {"mass": 3.0160492779, "composition": 0.0}, - 4: {"mass": 4.02643, "composition": 0.0}, - 5: {"mass": 5.035311, "composition": 0.0}, - 6: {"mass": 6.04496, "composition": 0.0}, - 7: {"mass": 7.0527, "composition": 0.0}}, + 3: {"mass": 3.0160492779, "composition": 0.}, + 4: {"mass": 4.02643, "composition": 0.}, + 5: {"mass": 5.035311, "composition": 0.}, + 6: {"mass": 6.04496, "composition": 0.}, + 7: {"mass": 7.0527, "composition": 0.}}, 2: {3: {"mass": 3.0160293201, "composition": 1.34e-06}, 4: {"mass": 4.00260325413, "composition": 0.99999866}, - 5: {"mass": 5.012057, "composition": 0.0}, - 6: {"mass": 6.018885891, "composition": 0.0}, - 7: {"mass": 7.0279907, "composition": 0.0}, - 8: {"mass": 8.03393439, "composition": 0.0}, - 9: {"mass": 9.043946, "composition": 0.0}, - 10: {"mass": 10.05279, "composition": 0.0}}, - 3: {3: {"mass": 3.0308, "composition": 0.0}, - 4: {"mass": 4.02719, "composition": 0.0}, - 5: {"mass": 5.012538, "composition": 0.0}, + 5: {"mass": 5.012057, "composition": 0.}, + 6: {"mass": 6.018885891, "composition": 0.}, + 7: {"mass": 7.0279907, "composition": 0.}, + 8: {"mass": 8.03393439, "composition": 0.}, + 9: {"mass": 9.043946, "composition": 0.}, + 10: {"mass": 10.05279, "composition": 0.}}, + 3: {3: {"mass": 3.0308, "composition": 0.}, + 4: {"mass": 4.02719, "composition": 0.}, + 5: {"mass": 5.012538, "composition": 0.}, 6: {"mass": 6.0151228874, "composition": 0.0759}, 7: {"mass": 7.0160034366, "composition": 0.9241}, - 8: {"mass": 8.022486246, "composition": 0.0}, - 9: {"mass": 9.02679019, "composition": 0.0}, - 10: {"mass": 10.035483, "composition": 0.0}, - 11: {"mass": 11.04372358, "composition": 0.0}, - 12: {"mass": 12.052517, "composition": 0.0}, - 13: {"mass": 13.06263, "composition": 0.0}}, - 4: {5: {"mass": 5.0399, "composition": 0.0}, - 6: {"mass": 6.0197264, "composition": 0.0}, - 7: {"mass": 7.016928717, "composition": 0.0}, - 8: {"mass": 8.005305102, "composition": 0.0}, - 9: {"mass": 9.012183065, "composition": 1.0}, - 10: {"mass": 10.013534695, "composition": 0.0}, - 11: {"mass": 11.02166108, "composition": 0.0}, - 12: {"mass": 12.0269221, "composition": 0.0}, - 13: {"mass": 13.036135, "composition": 0.0}, - 14: {"mass": 14.04289, "composition": 0.0}, - 15: {"mass": 15.05342, "composition": 0.0}, - 16: {"mass": 16.06167, "composition": 0.0}}, - 5: {6: {"mass": 6.0508, "composition": 0.0}, - 7: {"mass": 7.029712, "composition": 0.0}, - 8: {"mass": 8.0246073, "composition": 0.0}, - 9: {"mass": 9.01332965, "composition": 0.0}, + 8: {"mass": 8.022486246, "composition": 0.}, + 9: {"mass": 9.02679019, "composition": 0.}, + 10: {"mass": 10.035483, "composition": 0.}, + 11: {"mass": 11.04372358, "composition": 0.}, + 12: {"mass": 12.052517, "composition": 0.}, + 13: {"mass": 13.06263, "composition": 0.}}, + 4: {5: {"mass": 5.0399, "composition": 0.}, + 6: {"mass": 6.0197264, "composition": 0.}, + 7: {"mass": 7.016928717, "composition": 0.}, + 8: {"mass": 8.005305102, "composition": 0.}, + 9: {"mass": 9.012183065, "composition": 1.}, + 10: {"mass": 10.013534695, "composition": 0.}, + 11: {"mass": 11.02166108, "composition": 0.}, + 12: {"mass": 12.0269221, "composition": 0.}, + 13: {"mass": 13.036135, "composition": 0.}, + 14: {"mass": 14.04289, "composition": 0.}, + 15: {"mass": 15.05342, "composition": 0.}, + 16: {"mass": 16.06167, "composition": 0.}}, + 5: {6: {"mass": 6.0508, "composition": 0.}, + 7: {"mass": 7.029712, "composition": 0.}, + 8: {"mass": 8.0246073, "composition": 0.}, + 9: {"mass": 9.01332965, "composition": 0.}, 10: {"mass": 10.01293695, "composition": 0.199}, 11: {"mass": 11.00930536, "composition": 0.801}, - 12: {"mass": 12.0143527, "composition": 0.0}, - 13: {"mass": 13.0177802, "composition": 0.0}, - 14: {"mass": 14.025404, "composition": 0.0}, - 15: {"mass": 15.031088, "composition": 0.0}, - 16: {"mass": 16.039842, "composition": 0.0}, - 17: {"mass": 17.04699, "composition": 0.0}, - 18: {"mass": 18.05566, "composition": 0.0}, - 19: {"mass": 19.0631, "composition": 0.0}, - 20: {"mass": 20.07207, "composition": 0.0}, - 21: {"mass": 21.08129, "composition": 0.0}}, - 6: {8: {"mass": 8.037643, "composition": 0.0}, - 9: {"mass": 9.0310372, "composition": 0.0}, - 10: {"mass": 10.01685331, "composition": 0.0}, - 11: {"mass": 11.0114336, "composition": 0.0}, + 12: {"mass": 12.0143527, "composition": 0.}, + 13: {"mass": 13.0177802, "composition": 0.}, + 14: {"mass": 14.025404, "composition": 0.}, + 15: {"mass": 15.031088, "composition": 0.}, + 16: {"mass": 16.039842, "composition": 0.}, + 17: {"mass": 17.04699, "composition": 0.}, + 18: {"mass": 18.05566, "composition": 0.}, + 19: {"mass": 19.0631, "composition": 0.}, + 20: {"mass": 20.07207, "composition": 0.}, + 21: {"mass": 21.08129, "composition": 0.}}, + 6: {8: {"mass": 8.037643, "composition": 0.}, + 9: {"mass": 9.0310372, "composition": 0.}, + 10: {"mass": 10.01685331, "composition": 0.}, + 11: {"mass": 11.0114336, "composition": 0.}, 12: {"mass": 12.0, "composition": 0.9893}, 13: {"mass": 13.00335483507, "composition": 0.0107}, - 14: {"mass": 14.0032419884, "composition": 0.0}, - 15: {"mass": 15.01059926, "composition": 0.0}, - 16: {"mass": 16.0147013, "composition": 0.0}, - 17: {"mass": 17.022577, "composition": 0.0}, - 18: {"mass": 18.026751, "composition": 0.0}, - 19: {"mass": 19.0348, "composition": 0.0}, - 20: {"mass": 20.04032, "composition": 0.0}, - 21: {"mass": 21.049, "composition": 0.0}, - 22: {"mass": 22.05753, "composition": 0.0}, - 23: {"mass": 23.0689, "composition": 0.0}}, - 7: {10: {"mass": 10.04165, "composition": 0.0}, - 11: {"mass": 11.026091, "composition": 0.0}, - 12: {"mass": 12.0186132, "composition": 0.0}, - 13: {"mass": 13.00573861, "composition": 0.0}, + 14: {"mass": 14.0032419884, "composition": 0.}, + 15: {"mass": 15.01059926, "composition": 0.}, + 16: {"mass": 16.0147013, "composition": 0.}, + 17: {"mass": 17.022577, "composition": 0.}, + 18: {"mass": 18.026751, "composition": 0.}, + 19: {"mass": 19.0348, "composition": 0.}, + 20: {"mass": 20.04032, "composition": 0.}, + 21: {"mass": 21.049, "composition": 0.}, + 22: {"mass": 22.05753, "composition": 0.}, + 23: {"mass": 23.0689, "composition": 0.}}, + 7: {10: {"mass": 10.04165, "composition": 0.}, + 11: {"mass": 11.026091, "composition": 0.}, + 12: {"mass": 12.0186132, "composition": 0.}, + 13: {"mass": 13.00573861, "composition": 0.}, 14: {"mass": 14.00307400443, "composition": 0.99636}, 15: {"mass": 15.00010889888, "composition": 0.00364}, - 16: {"mass": 16.0061019, "composition": 0.0}, - 17: {"mass": 17.008449, "composition": 0.0}, - 18: {"mass": 18.014078, "composition": 0.0}, - 19: {"mass": 19.017022, "composition": 0.0}, - 20: {"mass": 20.023366, "composition": 0.0}, - 21: {"mass": 21.02711, "composition": 0.0}, - 22: {"mass": 22.03439, "composition": 0.0}, - 23: {"mass": 23.04114, "composition": 0.0}, - 24: {"mass": 24.05039, "composition": 0.0}, - 25: {"mass": 25.0601, "composition": 0.0}}, - 8: {12: {"mass": 12.034262, "composition": 0.0}, - 13: {"mass": 13.024815, "composition": 0.0}, - 14: {"mass": 14.00859636, "composition": 0.0}, - 15: {"mass": 15.00306562, "composition": 0.0}, + 16: {"mass": 16.0061019, "composition": 0.}, + 17: {"mass": 17.008449, "composition": 0.}, + 18: {"mass": 18.014078, "composition": 0.}, + 19: {"mass": 19.017022, "composition": 0.}, + 20: {"mass": 20.023366, "composition": 0.}, + 21: {"mass": 21.02711, "composition": 0.}, + 22: {"mass": 22.03439, "composition": 0.}, + 23: {"mass": 23.04114, "composition": 0.}, + 24: {"mass": 24.05039, "composition": 0.}, + 25: {"mass": 25.0601, "composition": 0.}}, + 8: {12: {"mass": 12.034262, "composition": 0.}, + 13: {"mass": 13.024815, "composition": 0.}, + 14: {"mass": 14.00859636, "composition": 0.}, + 15: {"mass": 15.00306562, "composition": 0.}, 16: {"mass": 15.99491461957, "composition": 0.99757}, 17: {"mass": 16.9991317565, "composition": 0.00038}, 18: {"mass": 17.99915961286, "composition": 0.00205}, - 19: {"mass": 19.003578, "composition": 0.0}, - 20: {"mass": 20.00407535, "composition": 0.0}, - 21: {"mass": 21.008655, "composition": 0.0}, - 22: {"mass": 22.009966, "composition": 0.0}, - 23: {"mass": 23.015696, "composition": 0.0}, - 24: {"mass": 24.01986, "composition": 0.0}, - 25: {"mass": 25.02936, "composition": 0.0}, - 26: {"mass": 26.03729, "composition": 0.0}, - 27: {"mass": 27.04772, "composition": 0.0}, - 28: {"mass": 28.05591, "composition": 0.0}}, - 9: {14: {"mass": 14.034315, "composition": 0.0}, - 15: {"mass": 15.018043, "composition": 0.0}, - 16: {"mass": 16.0114657, "composition": 0.0}, - 17: {"mass": 17.00209524, "composition": 0.0}, - 18: {"mass": 18.00093733, "composition": 0.0}, - 19: {"mass": 18.99840316273, "composition": 1.0}, - 20: {"mass": 19.999981252, "composition": 0.0}, - 21: {"mass": 20.9999489, "composition": 0.0}, - 22: {"mass": 22.002999, "composition": 0.0}, - 23: {"mass": 23.003557, "composition": 0.0}, - 24: {"mass": 24.008115, "composition": 0.0}, - 25: {"mass": 25.012199, "composition": 0.0}, - 26: {"mass": 26.020038, "composition": 0.0}, - 27: {"mass": 27.02644, "composition": 0.0}, - 28: {"mass": 28.03534, "composition": 0.0}, - 29: {"mass": 29.04254, "composition": 0.0}, - 30: {"mass": 30.05165, "composition": 0.0}, - 31: {"mass": 31.05971, "composition": 0.0}}, - 10: {16: {"mass": 16.02575, "composition": 0.0}, - 17: {"mass": 17.01771396, "composition": 0.0}, - 18: {"mass": 18.0057087, "composition": 0.0}, - 19: {"mass": 19.00188091, "composition": 0.0}, + 19: {"mass": 19.003578, "composition": 0.}, + 20: {"mass": 20.00407535, "composition": 0.}, + 21: {"mass": 21.008655, "composition": 0.}, + 22: {"mass": 22.009966, "composition": 0.}, + 23: {"mass": 23.015696, "composition": 0.}, + 24: {"mass": 24.01986, "composition": 0.}, + 25: {"mass": 25.02936, "composition": 0.}, + 26: {"mass": 26.03729, "composition": 0.}, + 27: {"mass": 27.04772, "composition": 0.}, + 28: {"mass": 28.05591, "composition": 0.}}, + 9: {14: {"mass": 14.034315, "composition": 0.}, + 15: {"mass": 15.018043, "composition": 0.}, + 16: {"mass": 16.0114657, "composition": 0.}, + 17: {"mass": 17.00209524, "composition": 0.}, + 18: {"mass": 18.00093733, "composition": 0.}, + 19: {"mass": 18.99840316273, "composition": 1.}, + 20: {"mass": 19.999981252, "composition": 0.}, + 21: {"mass": 20.9999489, "composition": 0.}, + 22: {"mass": 22.002999, "composition": 0.}, + 23: {"mass": 23.003557, "composition": 0.}, + 24: {"mass": 24.008115, "composition": 0.}, + 25: {"mass": 25.012199, "composition": 0.}, + 26: {"mass": 26.020038, "composition": 0.}, + 27: {"mass": 27.02644, "composition": 0.}, + 28: {"mass": 28.03534, "composition": 0.}, + 29: {"mass": 29.04254, "composition": 0.}, + 30: {"mass": 30.05165, "composition": 0.}, + 31: {"mass": 31.05971, "composition": 0.}}, + 10: {16: {"mass": 16.02575, "composition": 0.}, + 17: {"mass": 17.01771396, "composition": 0.}, + 18: {"mass": 18.0057087, "composition": 0.}, + 19: {"mass": 19.00188091, "composition": 0.}, 20: {"mass": 19.9924401762, "composition": 0.9048}, 21: {"mass": 20.993846685, "composition": 0.0027}, 22: {"mass": 21.991385114, "composition": 0.0925}, - 23: {"mass": 22.99446691, "composition": 0.0}, - 24: {"mass": 23.99361065, "composition": 0.0}, - 25: {"mass": 24.997789, "composition": 0.0}, - 26: {"mass": 26.000515, "composition": 0.0}, - 27: {"mass": 27.007553, "composition": 0.0}, - 28: {"mass": 28.01212, "composition": 0.0}, - 29: {"mass": 29.01975, "composition": 0.0}, - 30: {"mass": 30.02473, "composition": 0.0}, - 31: {"mass": 31.0331, "composition": 0.0}, - 32: {"mass": 32.03972, "composition": 0.0}, - 33: {"mass": 33.04938, "composition": 0.0}, - 34: {"mass": 34.05673, "composition": 0.0}}, - 11: {18: {"mass": 18.02688, "composition": 0.0}, - 19: {"mass": 19.01388, "composition": 0.0}, - 20: {"mass": 20.0073544, "composition": 0.0}, - 21: {"mass": 20.99765469, "composition": 0.0}, - 22: {"mass": 21.99443741, "composition": 0.0}, - 23: {"mass": 22.989769282, "composition": 1.0}, - 24: {"mass": 23.99096295, "composition": 0.0}, - 25: {"mass": 24.989954, "composition": 0.0}, - 26: {"mass": 25.9926346, "composition": 0.0}, - 27: {"mass": 26.9940765, "composition": 0.0}, - 28: {"mass": 27.998939, "composition": 0.0}, - 29: {"mass": 29.0028771, "composition": 0.0}, - 30: {"mass": 30.0090979, "composition": 0.0}, - 31: {"mass": 31.013163, "composition": 0.0}, - 32: {"mass": 32.02019, "composition": 0.0}, - 33: {"mass": 33.02573, "composition": 0.0}, - 34: {"mass": 34.03359, "composition": 0.0}, - 35: {"mass": 35.04062, "composition": 0.0}, - 36: {"mass": 36.04929, "composition": 0.0}, - 37: {"mass": 37.05705, "composition": 0.0}}, - 12: {19: {"mass": 19.034169, "composition": 0.0}, - 20: {"mass": 20.01885, "composition": 0.0}, - 21: {"mass": 21.011716, "composition": 0.0}, - 22: {"mass": 21.99957065, "composition": 0.0}, - 23: {"mass": 22.99412421, "composition": 0.0}, + 23: {"mass": 22.99446691, "composition": 0.}, + 24: {"mass": 23.99361065, "composition": 0.}, + 25: {"mass": 24.997789, "composition": 0.}, + 26: {"mass": 26.000515, "composition": 0.}, + 27: {"mass": 27.007553, "composition": 0.}, + 28: {"mass": 28.01212, "composition": 0.}, + 29: {"mass": 29.01975, "composition": 0.}, + 30: {"mass": 30.02473, "composition": 0.}, + 31: {"mass": 31.0331, "composition": 0.}, + 32: {"mass": 32.03972, "composition": 0.}, + 33: {"mass": 33.04938, "composition": 0.}, + 34: {"mass": 34.05673, "composition": 0.}}, + 11: {18: {"mass": 18.02688, "composition": 0.}, + 19: {"mass": 19.01388, "composition": 0.}, + 20: {"mass": 20.0073544, "composition": 0.}, + 21: {"mass": 20.99765469, "composition": 0.}, + 22: {"mass": 21.99443741, "composition": 0.}, + 23: {"mass": 22.989769282, "composition": 1.}, + 24: {"mass": 23.99096295, "composition": 0.}, + 25: {"mass": 24.989954, "composition": 0.}, + 26: {"mass": 25.9926346, "composition": 0.}, + 27: {"mass": 26.9940765, "composition": 0.}, + 28: {"mass": 27.998939, "composition": 0.}, + 29: {"mass": 29.0028771, "composition": 0.}, + 30: {"mass": 30.0090979, "composition": 0.}, + 31: {"mass": 31.013163, "composition": 0.}, + 32: {"mass": 32.02019, "composition": 0.}, + 33: {"mass": 33.02573, "composition": 0.}, + 34: {"mass": 34.03359, "composition": 0.}, + 35: {"mass": 35.04062, "composition": 0.}, + 36: {"mass": 36.04929, "composition": 0.}, + 37: {"mass": 37.05705, "composition": 0.}}, + 12: {19: {"mass": 19.034169, "composition": 0.}, + 20: {"mass": 20.01885, "composition": 0.}, + 21: {"mass": 21.011716, "composition": 0.}, + 22: {"mass": 21.99957065, "composition": 0.}, + 23: {"mass": 22.99412421, "composition": 0.}, 24: {"mass": 23.985041697, "composition": 0.7899}, 25: {"mass": 24.985836976, "composition": 0.1}, 26: {"mass": 25.982592968, "composition": 0.1101}, - 27: {"mass": 26.984340624, "composition": 0.0}, - 28: {"mass": 27.9838767, "composition": 0.0}, - 29: {"mass": 28.988617, "composition": 0.0}, - 30: {"mass": 29.9904629, "composition": 0.0}, - 31: {"mass": 30.996648, "composition": 0.0}, - 32: {"mass": 31.9991102, "composition": 0.0}, - 33: {"mass": 33.0053271, "composition": 0.0}, - 34: {"mass": 34.008935, "composition": 0.0}, - 35: {"mass": 35.01679, "composition": 0.0}, - 36: {"mass": 36.02188, "composition": 0.0}, - 37: {"mass": 37.03037, "composition": 0.0}, - 38: {"mass": 38.03658, "composition": 0.0}, - 39: {"mass": 39.04538, "composition": 0.0}, - 40: {"mass": 40.05218, "composition": 0.0}}, - 13: {21: {"mass": 21.02897, "composition": 0.0}, - 22: {"mass": 22.01954, "composition": 0.0}, - 23: {"mass": 23.00724435, "composition": 0.0}, - 24: {"mass": 23.9999489, "composition": 0.0}, - 25: {"mass": 24.9904281, "composition": 0.0}, - 26: {"mass": 25.986891904, "composition": 0.0}, - 27: {"mass": 26.98153853, "composition": 1.0}, - 28: {"mass": 27.98191021, "composition": 0.0}, - 29: {"mass": 28.9804565, "composition": 0.0}, - 30: {"mass": 29.98296, "composition": 0.0}, - 31: {"mass": 30.983945, "composition": 0.0}, - 32: {"mass": 31.988085, "composition": 0.0}, - 33: {"mass": 32.990909, "composition": 0.0}, - 34: {"mass": 33.996705, "composition": 0.0}, - 35: {"mass": 34.999764, "composition": 0.0}, - 36: {"mass": 36.00639, "composition": 0.0}, - 37: {"mass": 37.01053, "composition": 0.0}, - 38: {"mass": 38.0174, "composition": 0.0}, - 39: {"mass": 39.02254, "composition": 0.0}, - 40: {"mass": 40.03003, "composition": 0.0}, - 41: {"mass": 41.03638, "composition": 0.0}, - 42: {"mass": 42.04384, "composition": 0.0}, - 43: {"mass": 43.05147, "composition": 0.0}}, - 14: {22: {"mass": 22.03579, "composition": 0.0}, - 23: {"mass": 23.02544, "composition": 0.0}, - 24: {"mass": 24.011535, "composition": 0.0}, - 25: {"mass": 25.004109, "composition": 0.0}, - 26: {"mass": 25.99233384, "composition": 0.0}, - 27: {"mass": 26.98670481, "composition": 0.0}, + 27: {"mass": 26.984340624, "composition": 0.}, + 28: {"mass": 27.9838767, "composition": 0.}, + 29: {"mass": 28.988617, "composition": 0.}, + 30: {"mass": 29.9904629, "composition": 0.}, + 31: {"mass": 30.996648, "composition": 0.}, + 32: {"mass": 31.9991102, "composition": 0.}, + 33: {"mass": 33.0053271, "composition": 0.}, + 34: {"mass": 34.008935, "composition": 0.}, + 35: {"mass": 35.01679, "composition": 0.}, + 36: {"mass": 36.02188, "composition": 0.}, + 37: {"mass": 37.03037, "composition": 0.}, + 38: {"mass": 38.03658, "composition": 0.}, + 39: {"mass": 39.04538, "composition": 0.}, + 40: {"mass": 40.05218, "composition": 0.}}, + 13: {21: {"mass": 21.02897, "composition": 0.}, + 22: {"mass": 22.01954, "composition": 0.}, + 23: {"mass": 23.00724435, "composition": 0.}, + 24: {"mass": 23.9999489, "composition": 0.}, + 25: {"mass": 24.9904281, "composition": 0.}, + 26: {"mass": 25.986891904, "composition": 0.}, + 27: {"mass": 26.98153853, "composition": 1.}, + 28: {"mass": 27.98191021, "composition": 0.}, + 29: {"mass": 28.9804565, "composition": 0.}, + 30: {"mass": 29.98296, "composition": 0.}, + 31: {"mass": 30.983945, "composition": 0.}, + 32: {"mass": 31.988085, "composition": 0.}, + 33: {"mass": 32.990909, "composition": 0.}, + 34: {"mass": 33.996705, "composition": 0.}, + 35: {"mass": 34.999764, "composition": 0.}, + 36: {"mass": 36.00639, "composition": 0.}, + 37: {"mass": 37.01053, "composition": 0.}, + 38: {"mass": 38.0174, "composition": 0.}, + 39: {"mass": 39.02254, "composition": 0.}, + 40: {"mass": 40.03003, "composition": 0.}, + 41: {"mass": 41.03638, "composition": 0.}, + 42: {"mass": 42.04384, "composition": 0.}, + 43: {"mass": 43.05147, "composition": 0.}}, + 14: {22: {"mass": 22.03579, "composition": 0.}, + 23: {"mass": 23.02544, "composition": 0.}, + 24: {"mass": 24.011535, "composition": 0.}, + 25: {"mass": 25.004109, "composition": 0.}, + 26: {"mass": 25.99233384, "composition": 0.}, + 27: {"mass": 26.98670481, "composition": 0.}, 28: {"mass": 27.97692653465, "composition": 0.92223}, 29: {"mass": 28.9764946649, "composition": 0.04685}, 30: {"mass": 29.973770136, "composition": 0.03092}, - 31: {"mass": 30.975363194, "composition": 0.0}, - 32: {"mass": 31.97415154, "composition": 0.0}, - 33: {"mass": 32.97797696, "composition": 0.0}, - 34: {"mass": 33.978576, "composition": 0.0}, - 35: {"mass": 34.984583, "composition": 0.0}, - 36: {"mass": 35.986695, "composition": 0.0}, - 37: {"mass": 36.992921, "composition": 0.0}, - 38: {"mass": 37.995523, "composition": 0.0}, - 39: {"mass": 39.002491, "composition": 0.0}, - 40: {"mass": 40.00583, "composition": 0.0}, - 41: {"mass": 41.01301, "composition": 0.0}, - 42: {"mass": 42.01778, "composition": 0.0}, - 43: {"mass": 43.0248, "composition": 0.0}, - 44: {"mass": 44.03061, "composition": 0.0}, - 45: {"mass": 45.03995, "composition": 0.0}}, - 15: {24: {"mass": 24.03577, "composition": 0.0}, - 25: {"mass": 25.02119, "composition": 0.0}, - 26: {"mass": 26.01178, "composition": 0.0}, - 27: {"mass": 26.999224, "composition": 0.0}, - 28: {"mass": 27.9923266, "composition": 0.0}, - 29: {"mass": 28.98180079, "composition": 0.0}, - 30: {"mass": 29.97831375, "composition": 0.0}, - 31: {"mass": 30.97376199842, "composition": 1.0}, - 32: {"mass": 31.973907643, "composition": 0.0}, - 33: {"mass": 32.9717257, "composition": 0.0}, - 34: {"mass": 33.97364589, "composition": 0.0}, - 35: {"mass": 34.9733141, "composition": 0.0}, - 36: {"mass": 35.97826, "composition": 0.0}, - 37: {"mass": 36.979607, "composition": 0.0}, - 38: {"mass": 37.984252, "composition": 0.0}, - 39: {"mass": 38.986227, "composition": 0.0}, - 40: {"mass": 39.99133, "composition": 0.0}, - 41: {"mass": 40.994654, "composition": 0.0}, - 42: {"mass": 42.00108, "composition": 0.0}, - 43: {"mass": 43.00502, "composition": 0.0}, - 44: {"mass": 44.01121, "composition": 0.0}, - 45: {"mass": 45.01645, "composition": 0.0}, - 46: {"mass": 46.02446, "composition": 0.0}, - 47: {"mass": 47.03139, "composition": 0.0}}, - 16: {26: {"mass": 26.02907, "composition": 0.0}, - 27: {"mass": 27.01828, "composition": 0.0}, - 28: {"mass": 28.00437, "composition": 0.0}, - 29: {"mass": 28.996611, "composition": 0.0}, - 30: {"mass": 29.98490703, "composition": 0.0}, - 31: {"mass": 30.97955701, "composition": 0.0}, - 32: {"mass": 31.9720711744, "composition": 0.9499}, - 33: {"mass": 32.9714589098, "composition": 0.0075}, - 34: {"mass": 33.967867004, "composition": 0.0425}, - 35: {"mass": 34.96903231, "composition": 0.0}, - 36: {"mass": 35.96708071, "composition": 0.0001}, - 37: {"mass": 36.97112551, "composition": 0.0}, - 38: {"mass": 37.9711633, "composition": 0.0}, - 39: {"mass": 38.975134, "composition": 0.0}, - 40: {"mass": 39.9754826, "composition": 0.0}, - 41: {"mass": 40.9795935, "composition": 0.0}, - 42: {"mass": 41.9810651, "composition": 0.0}, - 43: {"mass": 42.9869076, "composition": 0.0}, - 44: {"mass": 43.9901188, "composition": 0.0}, - 45: {"mass": 44.99572, "composition": 0.0}, - 46: {"mass": 46.00004, "composition": 0.0}, - 47: {"mass": 47.00795, "composition": 0.0}, - 48: {"mass": 48.0137, "composition": 0.0}, - 49: {"mass": 49.02276, "composition": 0.0}}, - 17: {28: {"mass": 28.02954, "composition": 0.0}, - 29: {"mass": 29.01478, "composition": 0.0}, - 30: {"mass": 30.00477, "composition": 0.0}, - 31: {"mass": 30.992414, "composition": 0.0}, - 32: {"mass": 31.98568464, "composition": 0.0}, - 33: {"mass": 32.97745199, "composition": 0.0}, - 34: {"mass": 33.973762485, "composition": 0.0}, - 35: {"mass": 34.968852682, "composition": 0.7576}, - 36: {"mass": 35.968306809, "composition": 0.0}, - 37: {"mass": 36.965902602, "composition": 0.2424}, - 38: {"mass": 37.96801044, "composition": 0.0}, - 39: {"mass": 38.9680082, "composition": 0.0}, - 40: {"mass": 39.970415, "composition": 0.0}, - 41: {"mass": 40.970685, "composition": 0.0}, - 42: {"mass": 41.97325, "composition": 0.0}, - 43: {"mass": 42.97389, "composition": 0.0}, - 44: {"mass": 43.97787, "composition": 0.0}, - 45: {"mass": 44.98029, "composition": 0.0}, - 46: {"mass": 45.98517, "composition": 0.0}, - 47: {"mass": 46.98916, "composition": 0.0}, - 48: {"mass": 47.99564, "composition": 0.0}, - 49: {"mass": 49.00123, "composition": 0.0}, - 50: {"mass": 50.00905, "composition": 0.0}, - 51: {"mass": 51.01554, "composition": 0.0}}, - 18: {30: {"mass": 30.02307, "composition": 0.0}, - 31: {"mass": 31.01212, "composition": 0.0}, - 32: {"mass": 31.9976378, "composition": 0.0}, - 33: {"mass": 32.98992555, "composition": 0.0}, - 34: {"mass": 33.98027009, "composition": 0.0}, - 35: {"mass": 34.97525759, "composition": 0.0}, - 36: {"mass": 35.967545105, "composition": 0.003336}, - 37: {"mass": 36.96677633, "composition": 0.0}, - 38: {"mass": 37.96273211, "composition": 0.000629}, - 39: {"mass": 38.964313, "composition": 0.0}, - 40: {"mass": 39.9623831237, "composition": 0.996035}, - 41: {"mass": 40.96450057, "composition": 0.0}, - 42: {"mass": 41.9630457, "composition": 0.0}, - 43: {"mass": 42.9656361, "composition": 0.0}, - 44: {"mass": 43.9649238, "composition": 0.0}, - 45: {"mass": 44.96803973, "composition": 0.0}, - 46: {"mass": 45.968083, "composition": 0.0}, - 47: {"mass": 46.972935, "composition": 0.0}, - 48: {"mass": 47.97591, "composition": 0.0}, - 49: {"mass": 48.9819, "composition": 0.0}, - 50: {"mass": 49.98613, "composition": 0.0}, - 51: {"mass": 50.9937, "composition": 0.0}, - 52: {"mass": 51.99896, "composition": 0.0}, - 53: {"mass": 53.00729, "composition": 0.0}}, - 19: {32: {"mass": 32.02265, "composition": 0.0}, - 33: {"mass": 33.00756, "composition": 0.0}, - 34: {"mass": 33.99869, "composition": 0.0}, - 35: {"mass": 34.98800541, "composition": 0.0}, - 36: {"mass": 35.98130201, "composition": 0.0}, - 37: {"mass": 36.97337589, "composition": 0.0}, - 38: {"mass": 37.96908112, "composition": 0.0}, - 39: {"mass": 38.9637064864, "composition": 0.932581}, - 40: {"mass": 39.963998166, "composition": 0.000117}, - 41: {"mass": 40.9618252579, "composition": 0.067302}, - 42: {"mass": 41.96240231, "composition": 0.0}, - 43: {"mass": 42.9607347, "composition": 0.0}, - 44: {"mass": 43.96158699, "composition": 0.0}, - 45: {"mass": 44.96069149, "composition": 0.0}, - 46: {"mass": 45.96198159, "composition": 0.0}, - 47: {"mass": 46.9616616, "composition": 0.0}, - 48: {"mass": 47.96534119, "composition": 0.0}, - 49: {"mass": 48.96821075, "composition": 0.0}, - 50: {"mass": 49.97238, "composition": 0.0}, - 51: {"mass": 50.975828, "composition": 0.0}, - 52: {"mass": 51.98224, "composition": 0.0}, - 53: {"mass": 52.98746, "composition": 0.0}, - 54: {"mass": 53.99463, "composition": 0.0}, - 55: {"mass": 55.00076, "composition": 0.0}, - 56: {"mass": 56.00851, "composition": 0.0}}, - 20: {34: {"mass": 34.01487, "composition": 0.0}, - 35: {"mass": 35.00514, "composition": 0.0}, - 36: {"mass": 35.993074, "composition": 0.0}, - 37: {"mass": 36.98589785, "composition": 0.0}, - 38: {"mass": 37.97631922, "composition": 0.0}, - 39: {"mass": 38.97071081, "composition": 0.0}, - 40: {"mass": 39.962590863, "composition": 0.96941}, - 41: {"mass": 40.96227792, "composition": 0.0}, - 42: {"mass": 41.95861783, "composition": 0.00647}, - 43: {"mass": 42.95876644, "composition": 0.00135}, - 44: {"mass": 43.95548156, "composition": 0.02086}, - 45: {"mass": 44.95618635, "composition": 0.0}, - 46: {"mass": 45.953689, "composition": 4e-05}, - 47: {"mass": 46.9545424, "composition": 0.0}, - 48: {"mass": 47.95252276, "composition": 0.00187}, - 49: {"mass": 48.95566274, "composition": 0.0}, - 50: {"mass": 49.9574992, "composition": 0.0}, - 51: {"mass": 50.960989, "composition": 0.0}, - 52: {"mass": 51.963217, "composition": 0.0}, - 53: {"mass": 52.96945, "composition": 0.0}, - 54: {"mass": 53.9734, "composition": 0.0}, - 55: {"mass": 54.9803, "composition": 0.0}, - 56: {"mass": 55.98508, "composition": 0.0}, - 57: {"mass": 56.99262, "composition": 0.0}, - 58: {"mass": 57.99794, "composition": 0.0}}, - 21: {36: {"mass": 36.01648, "composition": 0.0}, - 37: {"mass": 37.00374, "composition": 0.0}, - 38: {"mass": 37.99512, "composition": 0.0}, - 39: {"mass": 38.984785, "composition": 0.0}, - 40: {"mass": 39.9779673, "composition": 0.0}, - 41: {"mass": 40.969251105, "composition": 0.0}, - 42: {"mass": 41.96551653, "composition": 0.0}, - 43: {"mass": 42.9611505, "composition": 0.0}, - 44: {"mass": 43.9594029, "composition": 0.0}, - 45: {"mass": 44.95590828, "composition": 1.0}, - 46: {"mass": 45.95516826, "composition": 0.0}, - 47: {"mass": 46.9524037, "composition": 0.0}, - 48: {"mass": 47.9522236, "composition": 0.0}, - 49: {"mass": 48.9500146, "composition": 0.0}, - 50: {"mass": 49.952176, "composition": 0.0}, - 51: {"mass": 50.953592, "composition": 0.0}, - 52: {"mass": 51.95688, "composition": 0.0}, - 53: {"mass": 52.95909, "composition": 0.0}, - 54: {"mass": 53.96393, "composition": 0.0}, - 55: {"mass": 54.96782, "composition": 0.0}, - 56: {"mass": 55.97345, "composition": 0.0}, - 57: {"mass": 56.97777, "composition": 0.0}, - 58: {"mass": 57.98403, "composition": 0.0}, - 59: {"mass": 58.98894, "composition": 0.0}, - 60: {"mass": 59.99565, "composition": 0.0}, - 61: {"mass": 61.001, "composition": 0.0}}, - 22: {38: {"mass": 38.01145, "composition": 0.0}, - 39: {"mass": 39.00236, "composition": 0.0}, - 40: {"mass": 39.9905, "composition": 0.0}, - 41: {"mass": 40.983148, "composition": 0.0}, - 42: {"mass": 41.97304903, "composition": 0.0}, - 43: {"mass": 42.9685225, "composition": 0.0}, - 44: {"mass": 43.95968995, "composition": 0.0}, - 45: {"mass": 44.95812198, "composition": 0.0}, - 46: {"mass": 45.95262772, "composition": 0.0825}, - 47: {"mass": 46.95175879, "composition": 0.0744}, - 48: {"mass": 47.94794198, "composition": 0.7372}, - 49: {"mass": 48.94786568, "composition": 0.0541}, - 50: {"mass": 49.94478689, "composition": 0.0518}, - 51: {"mass": 50.94661065, "composition": 0.0}, - 52: {"mass": 51.946893, "composition": 0.0}, - 53: {"mass": 52.94973, "composition": 0.0}, - 54: {"mass": 53.95105, "composition": 0.0}, - 55: {"mass": 54.95527, "composition": 0.0}, - 56: {"mass": 55.95791, "composition": 0.0}, - 57: {"mass": 56.96364, "composition": 0.0}, - 58: {"mass": 57.9666, "composition": 0.0}, - 59: {"mass": 58.97247, "composition": 0.0}, - 60: {"mass": 59.97603, "composition": 0.0}, - 61: {"mass": 60.98245, "composition": 0.0}, - 62: {"mass": 61.98651, "composition": 0.0}, - 63: {"mass": 62.99375, "composition": 0.0}}, - 23: {40: {"mass": 40.01276, "composition": 0.0}, - 41: {"mass": 41.00021, "composition": 0.0}, - 42: {"mass": 41.99182, "composition": 0.0}, - 43: {"mass": 42.980766, "composition": 0.0}, - 44: {"mass": 43.97411, "composition": 0.0}, - 45: {"mass": 44.9657748, "composition": 0.0}, - 46: {"mass": 45.96019878, "composition": 0.0}, - 47: {"mass": 46.95490491, "composition": 0.0}, - 48: {"mass": 47.9522522, "composition": 0.0}, - 49: {"mass": 48.9485118, "composition": 0.0}, - 50: {"mass": 49.94715601, "composition": 0.0025}, - 51: {"mass": 50.94395704, "composition": 0.9975}, - 52: {"mass": 51.94477301, "composition": 0.0}, - 53: {"mass": 52.9443367, "composition": 0.0}, - 54: {"mass": 53.946439, "composition": 0.0}, - 55: {"mass": 54.94724, "composition": 0.0}, - 56: {"mass": 55.95048, "composition": 0.0}, - 57: {"mass": 56.95252, "composition": 0.0}, - 58: {"mass": 57.95672, "composition": 0.0}, - 59: {"mass": 58.95939, "composition": 0.0}, - 60: {"mass": 59.96431, "composition": 0.0}, - 61: {"mass": 60.96725, "composition": 0.0}, - 62: {"mass": 61.97265, "composition": 0.0}, - 63: {"mass": 62.97639, "composition": 0.0}, - 64: {"mass": 63.98264, "composition": 0.0}, - 65: {"mass": 64.9875, "composition": 0.0}, - 66: {"mass": 65.99398, "composition": 0.0}}, - 24: {42: {"mass": 42.0067, "composition": 0.0}, - 43: {"mass": 42.99753, "composition": 0.0}, - 44: {"mass": 43.98536, "composition": 0.0}, - 45: {"mass": 44.97905, "composition": 0.0}, - 46: {"mass": 45.968359, "composition": 0.0}, - 47: {"mass": 46.9628974, "composition": 0.0}, - 48: {"mass": 47.9540291, "composition": 0.0}, - 49: {"mass": 48.9513333, "composition": 0.0}, - 50: {"mass": 49.94604183, "composition": 0.04345}, - 51: {"mass": 50.94476502, "composition": 0.0}, - 52: {"mass": 51.94050623, "composition": 0.83789}, - 53: {"mass": 52.94064815, "composition": 0.09501}, - 54: {"mass": 53.93887916, "composition": 0.02365}, - 55: {"mass": 54.94083843, "composition": 0.0}, - 56: {"mass": 55.9406531, "composition": 0.0}, - 57: {"mass": 56.943613, "composition": 0.0}, - 58: {"mass": 57.94435, "composition": 0.0}, - 59: {"mass": 58.94859, "composition": 0.0}, - 60: {"mass": 59.95008, "composition": 0.0}, - 61: {"mass": 60.95442, "composition": 0.0}, - 62: {"mass": 61.9561, "composition": 0.0}, - 63: {"mass": 62.96165, "composition": 0.0}, - 64: {"mass": 63.96408, "composition": 0.0}, - 65: {"mass": 64.96996, "composition": 0.0}, - 66: {"mass": 65.97366, "composition": 0.0}, - 67: {"mass": 66.98016, "composition": 0.0}, - 68: {"mass": 67.98403, "composition": 0.0}}, - 25: {44: {"mass": 44.00715, "composition": 0.0}, - 45: {"mass": 44.99449, "composition": 0.0}, - 46: {"mass": 45.98609, "composition": 0.0}, - 47: {"mass": 46.975775, "composition": 0.0}, - 48: {"mass": 47.96852, "composition": 0.0}, - 49: {"mass": 48.959595, "composition": 0.0}, - 50: {"mass": 49.95423778, "composition": 0.0}, - 51: {"mass": 50.94820847, "composition": 0.0}, - 52: {"mass": 51.9455639, "composition": 0.0}, - 53: {"mass": 52.94128889, "composition": 0.0}, - 54: {"mass": 53.9403576, "composition": 0.0}, - 55: {"mass": 54.93804391, "composition": 1.0}, - 56: {"mass": 55.93890369, "composition": 0.0}, - 57: {"mass": 56.9382861, "composition": 0.0}, - 58: {"mass": 57.9400666, "composition": 0.0}, - 59: {"mass": 58.9403911, "composition": 0.0}, - 60: {"mass": 59.9431366, "composition": 0.0}, - 61: {"mass": 60.9444525, "composition": 0.0}, - 62: {"mass": 61.94795, "composition": 0.0}, - 63: {"mass": 62.9496647, "composition": 0.0}, - 64: {"mass": 63.9538494, "composition": 0.0}, - 65: {"mass": 64.9560198, "composition": 0.0}, - 66: {"mass": 65.960547, "composition": 0.0}, - 67: {"mass": 66.96424, "composition": 0.0}, - 68: {"mass": 67.96962, "composition": 0.0}, - 69: {"mass": 68.97366, "composition": 0.0}, - 70: {"mass": 69.97937, "composition": 0.0}, - 71: {"mass": 70.98368, "composition": 0.0}}, - 26: {45: {"mass": 45.01442, "composition": 0.0}, - 46: {"mass": 46.00063, "composition": 0.0}, - 47: {"mass": 46.99185, "composition": 0.0}, - 48: {"mass": 47.98023, "composition": 0.0}, - 49: {"mass": 48.973429, "composition": 0.0}, - 50: {"mass": 49.962975, "composition": 0.0}, - 51: {"mass": 50.956841, "composition": 0.0}, - 52: {"mass": 51.9481131, "composition": 0.0}, - 53: {"mass": 52.9453064, "composition": 0.0}, - 54: {"mass": 53.93960899, "composition": 0.05845}, - 55: {"mass": 54.93829199, "composition": 0.0}, - 56: {"mass": 55.93493633, "composition": 0.91754}, - 57: {"mass": 56.93539284, "composition": 0.02119}, - 58: {"mass": 57.93327443, "composition": 0.00282}, - 59: {"mass": 58.93487434, "composition": 0.0}, - 60: {"mass": 59.9340711, "composition": 0.0}, - 61: {"mass": 60.9367462, "composition": 0.0}, - 62: {"mass": 61.9367918, "composition": 0.0}, - 63: {"mass": 62.9402727, "composition": 0.0}, - 64: {"mass": 63.9409878, "composition": 0.0}, - 65: {"mass": 64.9450115, "composition": 0.0}, - 66: {"mass": 65.94625, "composition": 0.0}, - 67: {"mass": 66.95054, "composition": 0.0}, - 68: {"mass": 67.95295, "composition": 0.0}, - 69: {"mass": 68.95807, "composition": 0.0}, - 70: {"mass": 69.96102, "composition": 0.0}, - 71: {"mass": 70.96672, "composition": 0.0}, - 72: {"mass": 71.96983, "composition": 0.0}, - 73: {"mass": 72.97572, "composition": 0.0}, - 74: {"mass": 73.97935, "composition": 0.0}}, - 27: {47: {"mass": 47.01057, "composition": 0.0}, - 48: {"mass": 48.00093, "composition": 0.0}, - 49: {"mass": 48.98891, "composition": 0.0}, - 50: {"mass": 49.98091, "composition": 0.0}, - 51: {"mass": 50.970647, "composition": 0.0}, - 52: {"mass": 51.96351, "composition": 0.0}, - 53: {"mass": 52.9542041, "composition": 0.0}, - 54: {"mass": 53.94845987, "composition": 0.0}, - 55: {"mass": 54.9419972, "composition": 0.0}, - 56: {"mass": 55.9398388, "composition": 0.0}, - 57: {"mass": 56.93629057, "composition": 0.0}, - 58: {"mass": 57.9357521, "composition": 0.0}, - 59: {"mass": 58.93319429, "composition": 1.0}, - 60: {"mass": 59.9338163, "composition": 0.0}, - 61: {"mass": 60.93247662, "composition": 0.0}, - 62: {"mass": 61.934059, "composition": 0.0}, - 63: {"mass": 62.9336, "composition": 0.0}, - 64: {"mass": 63.935811, "composition": 0.0}, - 65: {"mass": 64.9364621, "composition": 0.0}, - 66: {"mass": 65.939443, "composition": 0.0}, - 67: {"mass": 66.9406096, "composition": 0.0}, - 68: {"mass": 67.94426, "composition": 0.0}, - 69: {"mass": 68.94614, "composition": 0.0}, - 70: {"mass": 69.94963, "composition": 0.0}, - 71: {"mass": 70.95237, "composition": 0.0}, - 72: {"mass": 71.95729, "composition": 0.0}, - 73: {"mass": 72.96039, "composition": 0.0}, - 74: {"mass": 73.96515, "composition": 0.0}, - 75: {"mass": 74.96876, "composition": 0.0}, - 76: {"mass": 75.97413, "composition": 0.0}}, - 28: {48: {"mass": 48.01769, "composition": 0.0}, - 49: {"mass": 49.0077, "composition": 0.0}, - 50: {"mass": 49.99474, "composition": 0.0}, - 51: {"mass": 50.98611, "composition": 0.0}, - 52: {"mass": 51.9748, "composition": 0.0}, - 53: {"mass": 52.96819, "composition": 0.0}, - 54: {"mass": 53.957892, "composition": 0.0}, - 55: {"mass": 54.95133063, "composition": 0.0}, - 56: {"mass": 55.94212855, "composition": 0.0}, - 57: {"mass": 56.93979218, "composition": 0.0}, - 58: {"mass": 57.93534241, "composition": 0.68077}, - 59: {"mass": 58.9343462, "composition": 0.0}, - 60: {"mass": 59.93078588, "composition": 0.26223}, - 61: {"mass": 60.93105557, "composition": 0.011399}, - 62: {"mass": 61.92834537, "composition": 0.036346}, - 63: {"mass": 62.92966963, "composition": 0.0}, - 64: {"mass": 63.92796682, "composition": 0.009255}, - 65: {"mass": 64.93008517, "composition": 0.0}, - 66: {"mass": 65.9291393, "composition": 0.0}, - 67: {"mass": 66.9315694, "composition": 0.0}, - 68: {"mass": 67.9318688, "composition": 0.0}, - 69: {"mass": 68.9356103, "composition": 0.0}, - 70: {"mass": 69.9364313, "composition": 0.0}, - 71: {"mass": 70.940519, "composition": 0.0}, - 72: {"mass": 71.9417859, "composition": 0.0}, - 73: {"mass": 72.9462067, "composition": 0.0}, - 74: {"mass": 73.94798, "composition": 0.0}, - 75: {"mass": 74.9525, "composition": 0.0}, - 76: {"mass": 75.95533, "composition": 0.0}, - 77: {"mass": 76.96055, "composition": 0.0}, - 78: {"mass": 77.96336, "composition": 0.0}, - 79: {"mass": 78.97025, "composition": 0.0}}, - 29: {52: {"mass": 51.99671, "composition": 0.0}, - 53: {"mass": 52.98459, "composition": 0.0}, - 54: {"mass": 53.97666, "composition": 0.0}, - 55: {"mass": 54.96604, "composition": 0.0}, - 56: {"mass": 55.95895, "composition": 0.0}, - 57: {"mass": 56.9492125, "composition": 0.0}, - 58: {"mass": 57.94453305, "composition": 0.0}, - 59: {"mass": 58.93949748, "composition": 0.0}, - 60: {"mass": 59.9373645, "composition": 0.0}, - 61: {"mass": 60.9334576, "composition": 0.0}, - 62: {"mass": 61.93259541, "composition": 0.0}, - 63: {"mass": 62.92959772, "composition": 0.6915}, - 64: {"mass": 63.92976434, "composition": 0.0}, - 65: {"mass": 64.9277897, "composition": 0.3085}, - 66: {"mass": 65.92886903, "composition": 0.0}, - 67: {"mass": 66.9277303, "composition": 0.0}, - 68: {"mass": 67.9296109, "composition": 0.0}, - 69: {"mass": 68.9294293, "composition": 0.0}, - 70: {"mass": 69.9323921, "composition": 0.0}, - 71: {"mass": 70.9326768, "composition": 0.0}, - 72: {"mass": 71.9358203, "composition": 0.0}, - 73: {"mass": 72.9366744, "composition": 0.0}, - 74: {"mass": 73.9398749, "composition": 0.0}, - 75: {"mass": 74.9415226, "composition": 0.0}, - 76: {"mass": 75.945275, "composition": 0.0}, - 77: {"mass": 76.94792, "composition": 0.0}, - 78: {"mass": 77.95223, "composition": 0.0}, - 79: {"mass": 78.95502, "composition": 0.0}, - 80: {"mass": 79.96089, "composition": 0.0}, - 81: {"mass": 80.96587, "composition": 0.0}, - 82: {"mass": 81.97244, "composition": 0.0}}, - 30: {54: {"mass": 53.99204, "composition": 0.0}, - 55: {"mass": 54.98398, "composition": 0.0}, - 56: {"mass": 55.97254, "composition": 0.0}, - 57: {"mass": 56.96506, "composition": 0.0}, - 58: {"mass": 57.954591, "composition": 0.0}, - 59: {"mass": 58.94931266, "composition": 0.0}, - 60: {"mass": 59.9418421, "composition": 0.0}, - 61: {"mass": 60.939507, "composition": 0.0}, - 62: {"mass": 61.93433397, "composition": 0.0}, - 63: {"mass": 62.9332115, "composition": 0.0}, - 64: {"mass": 63.92914201, "composition": 0.4917}, - 65: {"mass": 64.92924077, "composition": 0.0}, - 66: {"mass": 65.92603381, "composition": 0.2773}, - 67: {"mass": 66.92712775, "composition": 0.0404}, - 68: {"mass": 67.92484455, "composition": 0.1845}, - 69: {"mass": 68.9265507, "composition": 0.0}, - 70: {"mass": 69.9253192, "composition": 0.0061}, - 71: {"mass": 70.9277196, "composition": 0.0}, - 72: {"mass": 71.9268428, "composition": 0.0}, - 73: {"mass": 72.9295826, "composition": 0.0}, - 74: {"mass": 73.9294073, "composition": 0.0}, - 75: {"mass": 74.9328402, "composition": 0.0}, - 76: {"mass": 75.933115, "composition": 0.0}, - 77: {"mass": 76.9368872, "composition": 0.0}, - 78: {"mass": 77.9382892, "composition": 0.0}, - 79: {"mass": 78.9426381, "composition": 0.0}, - 80: {"mass": 79.9445529, "composition": 0.0}, - 81: {"mass": 80.9504026, "composition": 0.0}, - 82: {"mass": 81.95426, "composition": 0.0}, - 83: {"mass": 82.96056, "composition": 0.0}, - 84: {"mass": 83.96521, "composition": 0.0}, - 85: {"mass": 84.97226, "composition": 0.0}}, - 31: {56: {"mass": 55.99536, "composition": 0.0}, - 57: {"mass": 56.9832, "composition": 0.0}, - 58: {"mass": 57.97478, "composition": 0.0}, - 59: {"mass": 58.96353, "composition": 0.0}, - 60: {"mass": 59.95729, "composition": 0.0}, - 61: {"mass": 60.949399, "composition": 0.0}, - 62: {"mass": 61.94419025, "composition": 0.0}, - 63: {"mass": 62.9392942, "composition": 0.0}, - 64: {"mass": 63.9368404, "composition": 0.0}, - 65: {"mass": 64.93273459, "composition": 0.0}, - 66: {"mass": 65.9315894, "composition": 0.0}, - 67: {"mass": 66.9282025, "composition": 0.0}, - 68: {"mass": 67.9279805, "composition": 0.0}, - 69: {"mass": 68.9255735, "composition": 0.60108}, - 70: {"mass": 69.9260219, "composition": 0.0}, - 71: {"mass": 70.92470258, "composition": 0.39892}, - 72: {"mass": 71.92636747, "composition": 0.0}, - 73: {"mass": 72.9251747, "composition": 0.0}, - 74: {"mass": 73.9269457, "composition": 0.0}, - 75: {"mass": 74.9265002, "composition": 0.0}, - 76: {"mass": 75.9288276, "composition": 0.0}, - 77: {"mass": 76.9291543, "composition": 0.0}, - 78: {"mass": 77.9316088, "composition": 0.0}, - 79: {"mass": 78.9328523, "composition": 0.0}, - 80: {"mass": 79.9364208, "composition": 0.0}, - 81: {"mass": 80.9381338, "composition": 0.0}, - 82: {"mass": 81.9431765, "composition": 0.0}, - 83: {"mass": 82.9471203, "composition": 0.0}, - 84: {"mass": 83.95246, "composition": 0.0}, - 85: {"mass": 84.95699, "composition": 0.0}, - 86: {"mass": 85.96301, "composition": 0.0}, - 87: {"mass": 86.96824, "composition": 0.0}}, - 32: {58: {"mass": 57.99172, "composition": 0.0}, - 59: {"mass": 58.98249, "composition": 0.0}, - 60: {"mass": 59.97036, "composition": 0.0}, - 61: {"mass": 60.96379, "composition": 0.0}, - 62: {"mass": 61.95502, "composition": 0.0}, - 63: {"mass": 62.949628, "composition": 0.0}, - 64: {"mass": 63.9416899, "composition": 0.0}, - 65: {"mass": 64.9393681, "composition": 0.0}, - 66: {"mass": 65.9338621, "composition": 0.0}, - 67: {"mass": 66.9327339, "composition": 0.0}, - 68: {"mass": 67.9280953, "composition": 0.0}, - 69: {"mass": 68.9279645, "composition": 0.0}, - 70: {"mass": 69.92424875, "composition": 0.2057}, - 71: {"mass": 70.92495233, "composition": 0.0}, - 72: {"mass": 71.922075826, "composition": 0.2745}, - 73: {"mass": 72.923458956, "composition": 0.0775}, - 74: {"mass": 73.921177761, "composition": 0.365}, - 75: {"mass": 74.92285837, "composition": 0.0}, - 76: {"mass": 75.921402726, "composition": 0.0773}, - 77: {"mass": 76.923549843, "composition": 0.0}, - 78: {"mass": 77.9228529, "composition": 0.0}, - 79: {"mass": 78.92536, "composition": 0.0}, - 80: {"mass": 79.9253508, "composition": 0.0}, - 81: {"mass": 80.9288329, "composition": 0.0}, - 82: {"mass": 81.929774, "composition": 0.0}, - 83: {"mass": 82.9345391, "composition": 0.0}, - 84: {"mass": 83.9375751, "composition": 0.0}, - 85: {"mass": 84.9429697, "composition": 0.0}, - 86: {"mass": 85.94658, "composition": 0.0}, - 87: {"mass": 86.95268, "composition": 0.0}, - 88: {"mass": 87.95691, "composition": 0.0}, - 89: {"mass": 88.96379, "composition": 0.0}, - 90: {"mass": 89.96863, "composition": 0.0}}, - 33: {60: {"mass": 59.99388, "composition": 0.0}, - 61: {"mass": 60.98112, "composition": 0.0}, - 62: {"mass": 61.97361, "composition": 0.0}, - 63: {"mass": 62.9639, "composition": 0.0}, - 64: {"mass": 63.95743, "composition": 0.0}, - 65: {"mass": 64.949611, "composition": 0.0}, - 66: {"mass": 65.9441488, "composition": 0.0}, - 67: {"mass": 66.93925111, "composition": 0.0}, - 68: {"mass": 67.9367741, "composition": 0.0}, - 69: {"mass": 68.932246, "composition": 0.0}, - 70: {"mass": 69.930926, "composition": 0.0}, - 71: {"mass": 70.9271138, "composition": 0.0}, - 72: {"mass": 71.9267523, "composition": 0.0}, - 73: {"mass": 72.9238291, "composition": 0.0}, - 74: {"mass": 73.9239286, "composition": 0.0}, - 75: {"mass": 74.92159457, "composition": 1.0}, - 76: {"mass": 75.92239202, "composition": 0.0}, - 77: {"mass": 76.9206476, "composition": 0.0}, - 78: {"mass": 77.921828, "composition": 0.0}, - 79: {"mass": 78.9209484, "composition": 0.0}, - 80: {"mass": 79.9224746, "composition": 0.0}, - 81: {"mass": 80.9221323, "composition": 0.0}, - 82: {"mass": 81.9247412, "composition": 0.0}, - 83: {"mass": 82.9252069, "composition": 0.0}, - 84: {"mass": 83.9293033, "composition": 0.0}, - 85: {"mass": 84.9321637, "composition": 0.0}, - 86: {"mass": 85.9367015, "composition": 0.0}, - 87: {"mass": 86.9402917, "composition": 0.0}, - 88: {"mass": 87.94555, "composition": 0.0}, - 89: {"mass": 88.94976, "composition": 0.0}, - 90: {"mass": 89.95563, "composition": 0.0}, - 91: {"mass": 90.96039, "composition": 0.0}, - 92: {"mass": 91.96674, "composition": 0.0}}, - 34: {64: {"mass": 63.97109, "composition": 0.0}, - 65: {"mass": 64.9644, "composition": 0.0}, - 66: {"mass": 65.95559, "composition": 0.0}, - 67: {"mass": 66.949994, "composition": 0.0}, - 68: {"mass": 67.94182524, "composition": 0.0}, - 69: {"mass": 68.9394148, "composition": 0.0}, - 70: {"mass": 69.9335155, "composition": 0.0}, - 71: {"mass": 70.9322094, "composition": 0.0}, - 72: {"mass": 71.9271405, "composition": 0.0}, - 73: {"mass": 72.9267549, "composition": 0.0}, - 74: {"mass": 73.922475934, "composition": 0.0089}, - 75: {"mass": 74.92252287, "composition": 0.0}, - 76: {"mass": 75.919213704, "composition": 0.0937}, - 77: {"mass": 76.919914154, "composition": 0.0763}, - 78: {"mass": 77.91730928, "composition": 0.2377}, - 79: {"mass": 78.91849929, "composition": 0.0}, - 80: {"mass": 79.9165218, "composition": 0.4961}, - 81: {"mass": 80.917993, "composition": 0.0}, - 82: {"mass": 81.9166995, "composition": 0.0873}, - 83: {"mass": 82.9191186, "composition": 0.0}, - 84: {"mass": 83.9184668, "composition": 0.0}, - 85: {"mass": 84.9222608, "composition": 0.0}, - 86: {"mass": 85.9243117, "composition": 0.0}, - 87: {"mass": 86.9286886, "composition": 0.0}, - 88: {"mass": 87.9314175, "composition": 0.0}, - 89: {"mass": 88.9366691, "composition": 0.0}, - 90: {"mass": 89.9401, "composition": 0.0}, - 91: {"mass": 90.94596, "composition": 0.0}, - 92: {"mass": 91.94984, "composition": 0.0}, - 93: {"mass": 92.95629, "composition": 0.0}, - 94: {"mass": 93.96049, "composition": 0.0}, - 95: {"mass": 94.9673, "composition": 0.0}}, - 35: {67: {"mass": 66.96465, "composition": 0.0}, - 68: {"mass": 67.95873, "composition": 0.0}, - 69: {"mass": 68.950497, "composition": 0.0}, - 70: {"mass": 69.944792, "composition": 0.0}, - 71: {"mass": 70.9393422, "composition": 0.0}, - 72: {"mass": 71.9365886, "composition": 0.0}, - 73: {"mass": 72.9316715, "composition": 0.0}, - 74: {"mass": 73.9299102, "composition": 0.0}, - 75: {"mass": 74.9258105, "composition": 0.0}, - 76: {"mass": 75.924542, "composition": 0.0}, - 77: {"mass": 76.9213792, "composition": 0.0}, - 78: {"mass": 77.9211459, "composition": 0.0}, - 79: {"mass": 78.9183376, "composition": 0.5069}, - 80: {"mass": 79.9185298, "composition": 0.0}, - 81: {"mass": 80.9162897, "composition": 0.4931}, - 82: {"mass": 81.9168032, "composition": 0.0}, - 83: {"mass": 82.9151756, "composition": 0.0}, - 84: {"mass": 83.916496, "composition": 0.0}, - 85: {"mass": 84.9156458, "composition": 0.0}, - 86: {"mass": 85.9188054, "composition": 0.0}, - 87: {"mass": 86.920674, "composition": 0.0}, - 88: {"mass": 87.9240833, "composition": 0.0}, - 89: {"mass": 88.9267046, "composition": 0.0}, - 90: {"mass": 89.9312928, "composition": 0.0}, - 91: {"mass": 90.9343986, "composition": 0.0}, - 92: {"mass": 91.9396316, "composition": 0.0}, - 93: {"mass": 92.94313, "composition": 0.0}, - 94: {"mass": 93.9489, "composition": 0.0}, - 95: {"mass": 94.95301, "composition": 0.0}, - 96: {"mass": 95.95903, "composition": 0.0}, - 97: {"mass": 96.96344, "composition": 0.0}, - 98: {"mass": 97.96946, "composition": 0.0}}, - 36: {69: {"mass": 68.96518, "composition": 0.0}, - 70: {"mass": 69.95604, "composition": 0.0}, - 71: {"mass": 70.95027, "composition": 0.0}, - 72: {"mass": 71.9420924, "composition": 0.0}, - 73: {"mass": 72.9392892, "composition": 0.0}, - 74: {"mass": 73.933084, "composition": 0.0}, - 75: {"mass": 74.9309457, "composition": 0.0}, - 76: {"mass": 75.9259103, "composition": 0.0}, - 77: {"mass": 76.92467, "composition": 0.0}, - 78: {"mass": 77.92036494, "composition": 0.00355}, - 79: {"mass": 78.9200829, "composition": 0.0}, - 80: {"mass": 79.91637808, "composition": 0.02286}, - 81: {"mass": 80.9165912, "composition": 0.0}, - 82: {"mass": 81.91348273, "composition": 0.11593}, - 83: {"mass": 82.91412716, "composition": 0.115}, - 84: {"mass": 83.9114977282, "composition": 0.56987}, - 85: {"mass": 84.9125273, "composition": 0.0}, - 86: {"mass": 85.9106106269, "composition": 0.17279}, - 87: {"mass": 86.91335476, "composition": 0.0}, - 88: {"mass": 87.9144479, "composition": 0.0}, - 89: {"mass": 88.9178355, "composition": 0.0}, - 90: {"mass": 89.9195279, "composition": 0.0}, - 91: {"mass": 90.9238063, "composition": 0.0}, - 92: {"mass": 91.9261731, "composition": 0.0}, - 93: {"mass": 92.9311472, "composition": 0.0}, - 94: {"mass": 93.93414, "composition": 0.0}, - 95: {"mass": 94.939711, "composition": 0.0}, - 96: {"mass": 95.943017, "composition": 0.0}, - 97: {"mass": 96.94909, "composition": 0.0}, - 98: {"mass": 97.95243, "composition": 0.0}, - 99: {"mass": 98.95839, "composition": 0.0}, - 100: {"mass": 99.96237, "composition": 0.0}, - 101: {"mass": 100.96873, "composition": 0.0}}, - 37: {71: {"mass": 70.96532, "composition": 0.0}, - 72: {"mass": 71.95908, "composition": 0.0}, - 73: {"mass": 72.95053, "composition": 0.0}, - 74: {"mass": 73.9442659, "composition": 0.0}, - 75: {"mass": 74.9385732, "composition": 0.0}, - 76: {"mass": 75.935073, "composition": 0.0}, - 77: {"mass": 76.9304016, "composition": 0.0}, - 78: {"mass": 77.9281419, "composition": 0.0}, - 79: {"mass": 78.9239899, "composition": 0.0}, - 80: {"mass": 79.9225164, "composition": 0.0}, - 81: {"mass": 80.9189939, "composition": 0.0}, - 82: {"mass": 81.918209, "composition": 0.0}, - 83: {"mass": 82.9151142, "composition": 0.0}, - 84: {"mass": 83.9143752, "composition": 0.0}, - 85: {"mass": 84.9117897379, "composition": 0.7217}, - 86: {"mass": 85.91116743, "composition": 0.0}, - 87: {"mass": 86.909180531, "composition": 0.2783}, - 88: {"mass": 87.91131559, "composition": 0.0}, - 89: {"mass": 88.9122783, "composition": 0.0}, - 90: {"mass": 89.9147985, "composition": 0.0}, - 91: {"mass": 90.9165372, "composition": 0.0}, - 92: {"mass": 91.9197284, "composition": 0.0}, - 93: {"mass": 92.9220393, "composition": 0.0}, - 94: {"mass": 93.9263948, "composition": 0.0}, - 95: {"mass": 94.92926, "composition": 0.0}, - 96: {"mass": 95.9341334, "composition": 0.0}, - 97: {"mass": 96.9371771, "composition": 0.0}, - 98: {"mass": 97.9416869, "composition": 0.0}, - 99: {"mass": 98.94503, "composition": 0.0}, - 100: {"mass": 99.95003, "composition": 0.0}, - 101: {"mass": 100.95404, "composition": 0.0}, - 102: {"mass": 101.95952, "composition": 0.0}, - 103: {"mass": 102.96392, "composition": 0.0}}, - 38: {73: {"mass": 72.9657, "composition": 0.0}, - 74: {"mass": 73.95617, "composition": 0.0}, - 75: {"mass": 74.94995, "composition": 0.0}, - 76: {"mass": 75.941763, "composition": 0.0}, - 77: {"mass": 76.9379455, "composition": 0.0}, - 78: {"mass": 77.93218, "composition": 0.0}, - 79: {"mass": 78.9297077, "composition": 0.0}, - 80: {"mass": 79.9245175, "composition": 0.0}, - 81: {"mass": 80.9232114, "composition": 0.0}, - 82: {"mass": 81.9183999, "composition": 0.0}, - 83: {"mass": 82.9175544, "composition": 0.0}, - 84: {"mass": 83.9134191, "composition": 0.0056}, - 85: {"mass": 84.912932, "composition": 0.0}, - 86: {"mass": 85.9092606, "composition": 0.0986}, - 87: {"mass": 86.9088775, "composition": 0.07}, - 88: {"mass": 87.9056125, "composition": 0.8258}, - 89: {"mass": 88.9074511, "composition": 0.0}, - 90: {"mass": 89.90773, "composition": 0.0}, - 91: {"mass": 90.9101954, "composition": 0.0}, - 92: {"mass": 91.9110382, "composition": 0.0}, - 93: {"mass": 92.9140242, "composition": 0.0}, - 94: {"mass": 93.9153556, "composition": 0.0}, - 95: {"mass": 94.9193529, "composition": 0.0}, - 96: {"mass": 95.9217066, "composition": 0.0}, - 97: {"mass": 96.926374, "composition": 0.0}, - 98: {"mass": 97.9286888, "composition": 0.0}, - 99: {"mass": 98.9328907, "composition": 0.0}, - 100: {"mass": 99.93577, "composition": 0.0}, - 101: {"mass": 100.940352, "composition": 0.0}, - 102: {"mass": 101.943791, "composition": 0.0}, - 103: {"mass": 102.94909, "composition": 0.0}, - 104: {"mass": 103.95265, "composition": 0.0}, - 105: {"mass": 104.95855, "composition": 0.0}, - 106: {"mass": 105.96265, "composition": 0.0}, - 107: {"mass": 106.96897, "composition": 0.0}}, - 39: {76: {"mass": 75.95856, "composition": 0.0}, - 77: {"mass": 76.949781, "composition": 0.0}, - 78: {"mass": 77.94361, "composition": 0.0}, - 79: {"mass": 78.93735, "composition": 0.0}, - 80: {"mass": 79.9343561, "composition": 0.0}, - 81: {"mass": 80.9294556, "composition": 0.0}, - 82: {"mass": 81.9269314, "composition": 0.0}, - 83: {"mass": 82.922485, "composition": 0.0}, - 84: {"mass": 83.9206721, "composition": 0.0}, - 85: {"mass": 84.916433, "composition": 0.0}, - 86: {"mass": 85.914886, "composition": 0.0}, - 87: {"mass": 86.9108761, "composition": 0.0}, - 88: {"mass": 87.9095016, "composition": 0.0}, - 89: {"mass": 88.9058403, "composition": 1.0}, - 90: {"mass": 89.9071439, "composition": 0.0}, - 91: {"mass": 90.9072974, "composition": 0.0}, - 92: {"mass": 91.9089451, "composition": 0.0}, - 93: {"mass": 92.909578, "composition": 0.0}, - 94: {"mass": 93.9115906, "composition": 0.0}, - 95: {"mass": 94.9128161, "composition": 0.0}, - 96: {"mass": 95.9158968, "composition": 0.0}, - 97: {"mass": 96.9182741, "composition": 0.0}, - 98: {"mass": 97.9223821, "composition": 0.0}, - 99: {"mass": 98.924148, "composition": 0.0}, - 100: {"mass": 99.927715, "composition": 0.0}, - 101: {"mass": 100.9301477, "composition": 0.0}, - 102: {"mass": 101.9343277, "composition": 0.0}, - 103: {"mass": 102.937243, "composition": 0.0}, - 104: {"mass": 103.94196, "composition": 0.0}, - 105: {"mass": 104.94544, "composition": 0.0}, - 106: {"mass": 105.95056, "composition": 0.0}, - 107: {"mass": 106.95452, "composition": 0.0}, - 108: {"mass": 107.95996, "composition": 0.0}, - 109: {"mass": 108.96436, "composition": 0.0}}, - 40: {78: {"mass": 77.95566, "composition": 0.0}, - 79: {"mass": 78.94948, "composition": 0.0}, - 80: {"mass": 79.9404, "composition": 0.0}, - 81: {"mass": 80.93731, "composition": 0.0}, - 82: {"mass": 81.93135, "composition": 0.0}, - 83: {"mass": 82.9292421, "composition": 0.0}, - 84: {"mass": 83.9233269, "composition": 0.0}, - 85: {"mass": 84.9214444, "composition": 0.0}, - 86: {"mass": 85.9162972, "composition": 0.0}, - 87: {"mass": 86.914818, "composition": 0.0}, - 88: {"mass": 87.9102213, "composition": 0.0}, - 89: {"mass": 88.9088814, "composition": 0.0}, - 90: {"mass": 89.9046977, "composition": 0.5145}, - 91: {"mass": 90.9056396, "composition": 0.1122}, - 92: {"mass": 91.9050347, "composition": 0.1715}, - 93: {"mass": 92.9064699, "composition": 0.0}, - 94: {"mass": 93.9063108, "composition": 0.1738}, - 95: {"mass": 94.9080385, "composition": 0.0}, - 96: {"mass": 95.9082714, "composition": 0.028}, - 97: {"mass": 96.9109512, "composition": 0.0}, - 98: {"mass": 97.9127289, "composition": 0.0}, - 99: {"mass": 98.916667, "composition": 0.0}, - 100: {"mass": 99.9180006, "composition": 0.0}, - 101: {"mass": 100.921448, "composition": 0.0}, - 102: {"mass": 101.9231409, "composition": 0.0}, - 103: {"mass": 102.927191, "composition": 0.0}, - 104: {"mass": 103.929436, "composition": 0.0}, - 105: {"mass": 104.934008, "composition": 0.0}, - 106: {"mass": 105.93676, "composition": 0.0}, - 107: {"mass": 106.94174, "composition": 0.0}, - 108: {"mass": 107.94487, "composition": 0.0}, - 109: {"mass": 108.95041, "composition": 0.0}, - 110: {"mass": 109.95396, "composition": 0.0}, - 111: {"mass": 110.95968, "composition": 0.0}, - 112: {"mass": 111.9637, "composition": 0.0}}, - 41: {81: {"mass": 80.9496, "composition": 0.0}, - 82: {"mass": 81.94396, "composition": 0.0}, - 83: {"mass": 82.93729, "composition": 0.0}, - 84: {"mass": 83.93449, "composition": 0.0}, - 85: {"mass": 84.9288458, "composition": 0.0}, - 86: {"mass": 85.9257828, "composition": 0.0}, - 87: {"mass": 86.9206937, "composition": 0.0}, - 88: {"mass": 87.918222, "composition": 0.0}, - 89: {"mass": 88.913445, "composition": 0.0}, - 90: {"mass": 89.9112584, "composition": 0.0}, - 91: {"mass": 90.9069897, "composition": 0.0}, - 92: {"mass": 91.9071881, "composition": 0.0}, - 93: {"mass": 92.906373, "composition": 1.0}, - 94: {"mass": 93.9072788, "composition": 0.0}, - 95: {"mass": 94.9068324, "composition": 0.0}, - 96: {"mass": 95.9080973, "composition": 0.0}, - 97: {"mass": 96.9080959, "composition": 0.0}, - 98: {"mass": 97.9103265, "composition": 0.0}, - 99: {"mass": 98.911613, "composition": 0.0}, - 100: {"mass": 99.9143276, "composition": 0.0}, - 101: {"mass": 100.9153103, "composition": 0.0}, - 102: {"mass": 101.9180772, "composition": 0.0}, - 103: {"mass": 102.9194572, "composition": 0.0}, - 104: {"mass": 103.9228925, "composition": 0.0}, - 105: {"mass": 104.9249465, "composition": 0.0}, - 106: {"mass": 105.9289317, "composition": 0.0}, - 107: {"mass": 106.9315937, "composition": 0.0}, - 108: {"mass": 107.9360748, "composition": 0.0}, - 109: {"mass": 108.93922, "composition": 0.0}, - 110: {"mass": 109.94403, "composition": 0.0}, - 111: {"mass": 110.94753, "composition": 0.0}, - 112: {"mass": 111.95247, "composition": 0.0}, - 113: {"mass": 112.95651, "composition": 0.0}, - 114: {"mass": 113.96201, "composition": 0.0}, - 115: {"mass": 114.96634, "composition": 0.0}}, - 42: {83: {"mass": 82.94988, "composition": 0.0}, - 84: {"mass": 83.94149, "composition": 0.0}, - 85: {"mass": 84.938261, "composition": 0.0}, - 86: {"mass": 85.9311748, "composition": 0.0}, - 87: {"mass": 86.9281962, "composition": 0.0}, - 88: {"mass": 87.9219678, "composition": 0.0}, - 89: {"mass": 88.9194682, "composition": 0.0}, - 90: {"mass": 89.9139309, "composition": 0.0}, - 91: {"mass": 90.9117453, "composition": 0.0}, - 92: {"mass": 91.90680796, "composition": 0.1453}, - 93: {"mass": 92.90680958, "composition": 0.0}, - 94: {"mass": 93.9050849, "composition": 0.0915}, - 95: {"mass": 94.90583877, "composition": 0.1584}, - 96: {"mass": 95.90467612, "composition": 0.1667}, - 97: {"mass": 96.90601812, "composition": 0.096}, - 98: {"mass": 97.90540482, "composition": 0.2439}, - 99: {"mass": 98.90770851, "composition": 0.0}, - 100: {"mass": 99.9074718, "composition": 0.0982}, - 101: {"mass": 100.9103414, "composition": 0.0}, - 102: {"mass": 101.9102834, "composition": 0.0}, - 103: {"mass": 102.913079, "composition": 0.0}, - 104: {"mass": 103.9137344, "composition": 0.0}, - 105: {"mass": 104.916969, "composition": 0.0}, - 106: {"mass": 105.918259, "composition": 0.0}, - 107: {"mass": 106.922106, "composition": 0.0}, - 108: {"mass": 107.924033, "composition": 0.0}, - 109: {"mass": 108.928424, "composition": 0.0}, - 110: {"mass": 109.930704, "composition": 0.0}, - 111: {"mass": 110.935654, "composition": 0.0}, - 112: {"mass": 111.93831, "composition": 0.0}, - 113: {"mass": 112.94335, "composition": 0.0}, - 114: {"mass": 113.94653, "composition": 0.0}, - 115: {"mass": 114.95196, "composition": 0.0}, - 116: {"mass": 115.95545, "composition": 0.0}, - 117: {"mass": 116.96117, "composition": 0.0}}, - 43: {85: {"mass": 84.95058, "composition": 0.0}, - 86: {"mass": 85.94493, "composition": 0.0}, - 87: {"mass": 86.9380672, "composition": 0.0}, - 88: {"mass": 87.93378, "composition": 0.0}, - 89: {"mass": 88.9276487, "composition": 0.0}, - 90: {"mass": 89.9240739, "composition": 0.0}, - 91: {"mass": 90.9184254, "composition": 0.0}, - 92: {"mass": 91.9152698, "composition": 0.0}, - 93: {"mass": 92.910246, "composition": 0.0}, - 94: {"mass": 93.9096536, "composition": 0.0}, - 95: {"mass": 94.9076536, "composition": 0.0}, - 96: {"mass": 95.907868, "composition": 0.0}, - 97: {"mass": 96.9063667, "composition": 0.0}, - 98: {"mass": 97.9072124, "composition": 0.0}, - 99: {"mass": 98.9062508, "composition": 0.0}, - 100: {"mass": 99.9076539, "composition": 0.0}, - 101: {"mass": 100.907309, "composition": 0.0}, - 102: {"mass": 101.9092097, "composition": 0.0}, - 103: {"mass": 102.909176, "composition": 0.0}, - 104: {"mass": 103.911425, "composition": 0.0}, - 105: {"mass": 104.911655, "composition": 0.0}, - 106: {"mass": 105.914358, "composition": 0.0}, - 107: {"mass": 106.9154606, "composition": 0.0}, - 108: {"mass": 107.9184957, "composition": 0.0}, - 109: {"mass": 108.920256, "composition": 0.0}, - 110: {"mass": 109.923744, "composition": 0.0}, - 111: {"mass": 110.925901, "composition": 0.0}, - 112: {"mass": 111.9299458, "composition": 0.0}, - 113: {"mass": 112.932569, "composition": 0.0}, - 114: {"mass": 113.93691, "composition": 0.0}, - 115: {"mass": 114.93998, "composition": 0.0}, - 116: {"mass": 115.94476, "composition": 0.0}, - 117: {"mass": 116.94806, "composition": 0.0}, - 118: {"mass": 117.95299, "composition": 0.0}, - 119: {"mass": 118.95666, "composition": 0.0}, - 120: {"mass": 119.96187, "composition": 0.0}}, - 44: {87: {"mass": 86.95069, "composition": 0.0}, - 88: {"mass": 87.9416, "composition": 0.0}, - 89: {"mass": 88.93762, "composition": 0.0}, - 90: {"mass": 89.9303444, "composition": 0.0}, - 91: {"mass": 90.9267419, "composition": 0.0}, - 92: {"mass": 91.9202344, "composition": 0.0}, - 93: {"mass": 92.9171044, "composition": 0.0}, - 94: {"mass": 93.9113429, "composition": 0.0}, - 95: {"mass": 94.910406, "composition": 0.0}, - 96: {"mass": 95.90759025, "composition": 0.0554}, - 97: {"mass": 96.9075471, "composition": 0.0}, - 98: {"mass": 97.9052868, "composition": 0.0187}, - 99: {"mass": 98.9059341, "composition": 0.1276}, - 100: {"mass": 99.9042143, "composition": 0.126}, - 101: {"mass": 100.9055769, "composition": 0.1706}, - 102: {"mass": 101.9043441, "composition": 0.3155}, - 103: {"mass": 102.9063186, "composition": 0.0}, - 104: {"mass": 103.9054275, "composition": 0.1862}, - 105: {"mass": 104.9077476, "composition": 0.0}, - 106: {"mass": 105.9073291, "composition": 0.0}, - 107: {"mass": 106.909972, "composition": 0.0}, - 108: {"mass": 107.910188, "composition": 0.0}, - 109: {"mass": 108.913326, "composition": 0.0}, - 110: {"mass": 109.9140407, "composition": 0.0}, - 111: {"mass": 110.91757, "composition": 0.0}, - 112: {"mass": 111.918809, "composition": 0.0}, - 113: {"mass": 112.922844, "composition": 0.0}, - 114: {"mass": 113.9246136, "composition": 0.0}, - 115: {"mass": 114.92882, "composition": 0.0}, - 116: {"mass": 115.9312192, "composition": 0.0}, - 117: {"mass": 116.9361, "composition": 0.0}, - 118: {"mass": 117.93853, "composition": 0.0}, - 119: {"mass": 118.94357, "composition": 0.0}, - 120: {"mass": 119.94631, "composition": 0.0}, - 121: {"mass": 120.95164, "composition": 0.0}, - 122: {"mass": 121.95447, "composition": 0.0}, - 123: {"mass": 122.95989, "composition": 0.0}, - 124: {"mass": 123.96305, "composition": 0.0}}, - 45: {89: {"mass": 88.95058, "composition": 0.0}, - 90: {"mass": 89.94422, "composition": 0.0}, - 91: {"mass": 90.93688, "composition": 0.0}, - 92: {"mass": 91.9323677, "composition": 0.0}, - 93: {"mass": 92.9259128, "composition": 0.0}, - 94: {"mass": 93.9217305, "composition": 0.0}, - 95: {"mass": 94.9158979, "composition": 0.0}, - 96: {"mass": 95.914453, "composition": 0.0}, - 97: {"mass": 96.911329, "composition": 0.0}, - 98: {"mass": 97.910708, "composition": 0.0}, - 99: {"mass": 98.9081282, "composition": 0.0}, - 100: {"mass": 99.908117, "composition": 0.0}, - 101: {"mass": 100.9061606, "composition": 0.0}, - 102: {"mass": 101.9068374, "composition": 0.0}, - 103: {"mass": 102.905498, "composition": 1.0}, - 104: {"mass": 103.9066492, "composition": 0.0}, - 105: {"mass": 104.9056885, "composition": 0.0}, - 106: {"mass": 105.9072868, "composition": 0.0}, - 107: {"mass": 106.906748, "composition": 0.0}, - 108: {"mass": 107.908714, "composition": 0.0}, - 109: {"mass": 108.9087488, "composition": 0.0}, - 110: {"mass": 109.911079, "composition": 0.0}, - 111: {"mass": 110.9116423, "composition": 0.0}, - 112: {"mass": 111.914403, "composition": 0.0}, - 113: {"mass": 112.9154393, "composition": 0.0}, - 114: {"mass": 113.918718, "composition": 0.0}, - 115: {"mass": 114.9203116, "composition": 0.0}, - 116: {"mass": 115.924059, "composition": 0.0}, - 117: {"mass": 116.9260354, "composition": 0.0}, - 118: {"mass": 117.93034, "composition": 0.0}, - 119: {"mass": 118.932557, "composition": 0.0}, - 120: {"mass": 119.93686, "composition": 0.0}, - 121: {"mass": 120.93942, "composition": 0.0}, - 122: {"mass": 121.94399, "composition": 0.0}, - 123: {"mass": 122.94685, "composition": 0.0}, - 124: {"mass": 123.95151, "composition": 0.0}, - 125: {"mass": 124.95469, "composition": 0.0}, - 126: {"mass": 125.95946, "composition": 0.0}}, - 46: {91: {"mass": 90.95032, "composition": 0.0}, - 92: {"mass": 91.94088, "composition": 0.0}, - 93: {"mass": 92.93651, "composition": 0.0}, - 94: {"mass": 93.9290376, "composition": 0.0}, - 95: {"mass": 94.9248898, "composition": 0.0}, - 96: {"mass": 95.9182151, "composition": 0.0}, - 97: {"mass": 96.916472, "composition": 0.0}, - 98: {"mass": 97.9126983, "composition": 0.0}, - 99: {"mass": 98.9117748, "composition": 0.0}, - 100: {"mass": 99.908505, "composition": 0.0}, - 101: {"mass": 100.9082864, "composition": 0.0}, - 102: {"mass": 101.9056022, "composition": 0.0102}, - 103: {"mass": 102.9060809, "composition": 0.0}, - 104: {"mass": 103.9040305, "composition": 0.1114}, - 105: {"mass": 104.9050796, "composition": 0.2233}, - 106: {"mass": 105.9034804, "composition": 0.2733}, - 107: {"mass": 106.9051282, "composition": 0.0}, - 108: {"mass": 107.9038916, "composition": 0.2646}, - 109: {"mass": 108.9059504, "composition": 0.0}, - 110: {"mass": 109.9051722, "composition": 0.1172}, - 111: {"mass": 110.90768968, "composition": 0.0}, - 112: {"mass": 111.9073297, "composition": 0.0}, - 113: {"mass": 112.910261, "composition": 0.0}, - 114: {"mass": 113.9103686, "composition": 0.0}, - 115: {"mass": 114.913659, "composition": 0.0}, - 116: {"mass": 115.914297, "composition": 0.0}, - 117: {"mass": 116.9179547, "composition": 0.0}, - 118: {"mass": 117.9190667, "composition": 0.0}, - 119: {"mass": 118.9233402, "composition": 0.0}, - 120: {"mass": 119.9245511, "composition": 0.0}, - 121: {"mass": 120.9289503, "composition": 0.0}, - 122: {"mass": 121.930632, "composition": 0.0}, - 123: {"mass": 122.93514, "composition": 0.0}, - 124: {"mass": 123.93714, "composition": 0.0}, - 125: {"mass": 124.94179, "composition": 0.0}, - 126: {"mass": 125.94416, "composition": 0.0}, - 127: {"mass": 126.94907, "composition": 0.0}, - 128: {"mass": 127.95183, "composition": 0.0}}, - 47: {93: {"mass": 92.95033, "composition": 0.0}, - 94: {"mass": 93.94373, "composition": 0.0}, - 95: {"mass": 94.93602, "composition": 0.0}, - 96: {"mass": 95.930744, "composition": 0.0}, - 97: {"mass": 96.92397, "composition": 0.0}, - 98: {"mass": 97.92156, "composition": 0.0}, - 99: {"mass": 98.9176458, "composition": 0.0}, - 100: {"mass": 99.9161154, "composition": 0.0}, - 101: {"mass": 100.912684, "composition": 0.0}, - 102: {"mass": 101.9117047, "composition": 0.0}, - 103: {"mass": 102.9089631, "composition": 0.0}, - 104: {"mass": 103.9086239, "composition": 0.0}, - 105: {"mass": 104.9065256, "composition": 0.0}, - 106: {"mass": 105.9066636, "composition": 0.0}, - 107: {"mass": 106.9050916, "composition": 0.51839}, - 108: {"mass": 107.9059503, "composition": 0.0}, - 109: {"mass": 108.9047553, "composition": 0.48161}, - 110: {"mass": 109.9061102, "composition": 0.0}, - 111: {"mass": 110.9052959, "composition": 0.0}, - 112: {"mass": 111.9070486, "composition": 0.0}, - 113: {"mass": 112.906573, "composition": 0.0}, - 114: {"mass": 113.908823, "composition": 0.0}, - 115: {"mass": 114.908767, "composition": 0.0}, - 116: {"mass": 115.9113868, "composition": 0.0}, - 117: {"mass": 116.911774, "composition": 0.0}, - 118: {"mass": 117.9145955, "composition": 0.0}, - 119: {"mass": 118.91557, "composition": 0.0}, - 120: {"mass": 119.9187848, "composition": 0.0}, - 121: {"mass": 120.920125, "composition": 0.0}, - 122: {"mass": 121.923664, "composition": 0.0}, - 123: {"mass": 122.925337, "composition": 0.0}, - 124: {"mass": 123.92893, "composition": 0.0}, - 125: {"mass": 124.93105, "composition": 0.0}, - 126: {"mass": 125.93475, "composition": 0.0}, - 127: {"mass": 126.93711, "composition": 0.0}, - 128: {"mass": 127.94106, "composition": 0.0}, - 129: {"mass": 128.94395, "composition": 0.0}, - 130: {"mass": 129.9507, "composition": 0.0}}, - 48: {95: {"mass": 94.94994, "composition": 0.0}, - 96: {"mass": 95.94034, "composition": 0.0}, - 97: {"mass": 96.9351, "composition": 0.0}, - 98: {"mass": 97.927389, "composition": 0.0}, - 99: {"mass": 98.9249258, "composition": 0.0}, - 100: {"mass": 99.9203488, "composition": 0.0}, - 101: {"mass": 100.9185862, "composition": 0.0}, - 102: {"mass": 101.914482, "composition": 0.0}, - 103: {"mass": 102.9134165, "composition": 0.0}, - 104: {"mass": 103.9098564, "composition": 0.0}, - 105: {"mass": 104.9094639, "composition": 0.0}, - 106: {"mass": 105.9064599, "composition": 0.0125}, - 107: {"mass": 106.9066121, "composition": 0.0}, - 108: {"mass": 107.9041834, "composition": 0.0089}, - 109: {"mass": 108.9049867, "composition": 0.0}, - 110: {"mass": 109.90300661, "composition": 0.1249}, - 111: {"mass": 110.90418287, "composition": 0.128}, - 112: {"mass": 111.90276287, "composition": 0.2413}, - 113: {"mass": 112.90440813, "composition": 0.1222}, - 114: {"mass": 113.90336509, "composition": 0.2873}, - 115: {"mass": 114.90543751, "composition": 0.0}, - 116: {"mass": 115.90476315, "composition": 0.0749}, - 117: {"mass": 116.907226, "composition": 0.0}, - 118: {"mass": 117.906922, "composition": 0.0}, - 119: {"mass": 118.909847, "composition": 0.0}, - 120: {"mass": 119.9098681, "composition": 0.0}, - 121: {"mass": 120.9129637, "composition": 0.0}, - 122: {"mass": 121.9134591, "composition": 0.0}, - 123: {"mass": 122.9168925, "composition": 0.0}, - 124: {"mass": 123.9176574, "composition": 0.0}, - 125: {"mass": 124.9212576, "composition": 0.0}, - 126: {"mass": 125.9224291, "composition": 0.0}, - 127: {"mass": 126.926472, "composition": 0.0}, - 128: {"mass": 127.9278129, "composition": 0.0}, - 129: {"mass": 128.93182, "composition": 0.0}, - 130: {"mass": 129.93394, "composition": 0.0}, - 131: {"mass": 130.9406, "composition": 0.0}, - 132: {"mass": 131.94604, "composition": 0.0}, - 133: {"mass": 132.95285, "composition": 0.0}}, - 49: {97: {"mass": 96.94934, "composition": 0.0}, - 98: {"mass": 97.94214, "composition": 0.0}, - 99: {"mass": 98.93411, "composition": 0.0}, - 100: {"mass": 99.93096, "composition": 0.0}, - 101: {"mass": 100.92634, "composition": 0.0}, - 102: {"mass": 101.9241071, "composition": 0.0}, - 103: {"mass": 102.9198819, "composition": 0.0}, - 104: {"mass": 103.9182145, "composition": 0.0}, - 105: {"mass": 104.914502, "composition": 0.0}, - 106: {"mass": 105.913464, "composition": 0.0}, - 107: {"mass": 106.91029, "composition": 0.0}, - 108: {"mass": 107.9096935, "composition": 0.0}, - 109: {"mass": 108.9071514, "composition": 0.0}, - 110: {"mass": 109.90717, "composition": 0.0}, - 111: {"mass": 110.9051085, "composition": 0.0}, - 112: {"mass": 111.9055377, "composition": 0.0}, - 113: {"mass": 112.90406184, "composition": 0.0429}, - 114: {"mass": 113.90491791, "composition": 0.0}, - 115: {"mass": 114.903878776, "composition": 0.9571}, - 116: {"mass": 115.90525999, "composition": 0.0}, - 117: {"mass": 116.9045157, "composition": 0.0}, - 118: {"mass": 117.9063566, "composition": 0.0}, - 119: {"mass": 118.9058507, "composition": 0.0}, - 120: {"mass": 119.907967, "composition": 0.0}, - 121: {"mass": 120.907851, "composition": 0.0}, - 122: {"mass": 121.910281, "composition": 0.0}, - 123: {"mass": 122.910434, "composition": 0.0}, - 124: {"mass": 123.913182, "composition": 0.0}, - 125: {"mass": 124.913605, "composition": 0.0}, - 126: {"mass": 125.916507, "composition": 0.0}, - 127: {"mass": 126.917446, "composition": 0.0}, - 128: {"mass": 127.9204, "composition": 0.0}, - 129: {"mass": 128.9218053, "composition": 0.0}, - 130: {"mass": 129.924977, "composition": 0.0}, - 131: {"mass": 130.9269715, "composition": 0.0}, - 132: {"mass": 131.933001, "composition": 0.0}, - 133: {"mass": 132.93831, "composition": 0.0}, - 134: {"mass": 133.94454, "composition": 0.0}, - 135: {"mass": 134.95005, "composition": 0.0}}, - 50: {99: {"mass": 98.94853, "composition": 0.0}, - 100: {"mass": 99.9385, "composition": 0.0}, - 101: {"mass": 100.93526, "composition": 0.0}, - 102: {"mass": 101.93029, "composition": 0.0}, - 103: {"mass": 102.928105, "composition": 0.0}, - 104: {"mass": 103.9231052, "composition": 0.0}, - 105: {"mass": 104.9212684, "composition": 0.0}, - 106: {"mass": 105.9169574, "composition": 0.0}, - 107: {"mass": 106.9157137, "composition": 0.0}, - 108: {"mass": 107.9118943, "composition": 0.0}, - 109: {"mass": 108.9112921, "composition": 0.0}, - 110: {"mass": 109.907845, "composition": 0.0}, - 111: {"mass": 110.9077401, "composition": 0.0}, - 112: {"mass": 111.90482387, "composition": 0.0097}, - 113: {"mass": 112.9051757, "composition": 0.0}, - 114: {"mass": 113.9027827, "composition": 0.0066}, - 115: {"mass": 114.903344699, "composition": 0.0034}, - 116: {"mass": 115.9017428, "composition": 0.1454}, - 117: {"mass": 116.90295398, "composition": 0.0768}, - 118: {"mass": 117.90160657, "composition": 0.2422}, - 119: {"mass": 118.90331117, "composition": 0.0859}, - 120: {"mass": 119.90220163, "composition": 0.3258}, - 121: {"mass": 120.9042426, "composition": 0.0}, - 122: {"mass": 121.9034438, "composition": 0.0463}, - 123: {"mass": 122.9057252, "composition": 0.0}, - 124: {"mass": 123.9052766, "composition": 0.0579}, - 125: {"mass": 124.9077864, "composition": 0.0}, - 126: {"mass": 125.907659, "composition": 0.0}, - 127: {"mass": 126.91039, "composition": 0.0}, - 128: {"mass": 127.910507, "composition": 0.0}, - 129: {"mass": 128.913465, "composition": 0.0}, - 130: {"mass": 129.9139738, "composition": 0.0}, - 131: {"mass": 130.917045, "composition": 0.0}, - 132: {"mass": 131.9178267, "composition": 0.0}, - 133: {"mass": 132.9239134, "composition": 0.0}, - 134: {"mass": 133.9286821, "composition": 0.0}, - 135: {"mass": 134.9349086, "composition": 0.0}, - 136: {"mass": 135.93999, "composition": 0.0}, - 137: {"mass": 136.94655, "composition": 0.0}, - 138: {"mass": 137.95184, "composition": 0.0}}, - 51: {103: {"mass": 102.93969, "composition": 0.0}, - 104: {"mass": 103.93648, "composition": 0.0}, - 105: {"mass": 104.931276, "composition": 0.0}, - 106: {"mass": 105.928638, "composition": 0.0}, - 107: {"mass": 106.9241506, "composition": 0.0}, - 108: {"mass": 107.9222267, "composition": 0.0}, - 109: {"mass": 108.9181411, "composition": 0.0}, - 110: {"mass": 109.9168543, "composition": 0.0}, - 111: {"mass": 110.9132182, "composition": 0.0}, - 112: {"mass": 111.9124, "composition": 0.0}, - 113: {"mass": 112.909375, "composition": 0.0}, - 114: {"mass": 113.90929, "composition": 0.0}, - 115: {"mass": 114.906598, "composition": 0.0}, - 116: {"mass": 115.9067931, "composition": 0.0}, - 117: {"mass": 116.9048415, "composition": 0.0}, - 118: {"mass": 117.9055321, "composition": 0.0}, - 119: {"mass": 118.9039455, "composition": 0.0}, - 120: {"mass": 119.9050794, "composition": 0.0}, - 121: {"mass": 120.903812, "composition": 0.5721}, - 122: {"mass": 121.9051699, "composition": 0.0}, - 123: {"mass": 122.9042132, "composition": 0.4279}, - 124: {"mass": 123.905935, "composition": 0.0}, - 125: {"mass": 124.905253, "composition": 0.0}, - 126: {"mass": 125.907253, "composition": 0.0}, - 127: {"mass": 126.9069243, "composition": 0.0}, - 128: {"mass": 127.909146, "composition": 0.0}, - 129: {"mass": 128.909147, "composition": 0.0}, - 130: {"mass": 129.911662, "composition": 0.0}, - 131: {"mass": 130.9119888, "composition": 0.0}, - 132: {"mass": 131.9145077, "composition": 0.0}, - 133: {"mass": 132.9152732, "composition": 0.0}, - 134: {"mass": 133.9205357, "composition": 0.0}, - 135: {"mass": 134.9251851, "composition": 0.0}, - 136: {"mass": 135.9307459, "composition": 0.0}, - 137: {"mass": 136.93555, "composition": 0.0}, - 138: {"mass": 137.94145, "composition": 0.0}, - 139: {"mass": 138.94655, "composition": 0.0}, - 140: {"mass": 139.95283, "composition": 0.0}}, - 52: {105: {"mass": 104.9433, "composition": 0.0}, - 106: {"mass": 105.9375, "composition": 0.0}, - 107: {"mass": 106.935012, "composition": 0.0}, - 108: {"mass": 107.9293805, "composition": 0.0}, - 109: {"mass": 108.9273045, "composition": 0.0}, - 110: {"mass": 109.9224581, "composition": 0.0}, - 111: {"mass": 110.9210006, "composition": 0.0}, - 112: {"mass": 111.9167279, "composition": 0.0}, - 113: {"mass": 112.915891, "composition": 0.0}, - 114: {"mass": 113.912089, "composition": 0.0}, - 115: {"mass": 114.911902, "composition": 0.0}, - 116: {"mass": 115.90846, "composition": 0.0}, - 117: {"mass": 116.908646, "composition": 0.0}, - 118: {"mass": 117.905854, "composition": 0.0}, - 119: {"mass": 118.9064071, "composition": 0.0}, - 120: {"mass": 119.9040593, "composition": 0.0009}, - 121: {"mass": 120.904944, "composition": 0.0}, - 122: {"mass": 121.9030435, "composition": 0.0255}, - 123: {"mass": 122.9042698, "composition": 0.0089}, - 124: {"mass": 123.9028171, "composition": 0.0474}, - 125: {"mass": 124.9044299, "composition": 0.0707}, - 126: {"mass": 125.9033109, "composition": 0.1884}, - 127: {"mass": 126.9052257, "composition": 0.0}, - 128: {"mass": 127.90446128, "composition": 0.3174}, - 129: {"mass": 128.90659646, "composition": 0.0}, - 130: {"mass": 129.906222748, "composition": 0.3408}, - 131: {"mass": 130.908522213, "composition": 0.0}, - 132: {"mass": 131.9085467, "composition": 0.0}, - 133: {"mass": 132.9109688, "composition": 0.0}, - 134: {"mass": 133.911394, "composition": 0.0}, - 135: {"mass": 134.9165557, "composition": 0.0}, - 136: {"mass": 135.9201006, "composition": 0.0}, - 137: {"mass": 136.9255989, "composition": 0.0}, - 138: {"mass": 137.9294722, "composition": 0.0}, - 139: {"mass": 138.9353672, "composition": 0.0}, - 140: {"mass": 139.939499, "composition": 0.0}, - 141: {"mass": 140.9458, "composition": 0.0}, - 142: {"mass": 141.95022, "composition": 0.0}, - 143: {"mass": 142.95676, "composition": 0.0}}, - 53: {107: {"mass": 106.94678, "composition": 0.0}, - 108: {"mass": 107.94348, "composition": 0.0}, - 109: {"mass": 108.9380853, "composition": 0.0}, - 110: {"mass": 109.935089, "composition": 0.0}, - 111: {"mass": 110.9302692, "composition": 0.0}, - 112: {"mass": 111.928005, "composition": 0.0}, - 113: {"mass": 112.9236501, "composition": 0.0}, - 114: {"mass": 113.92185, "composition": 0.0}, - 115: {"mass": 114.918048, "composition": 0.0}, - 116: {"mass": 115.91681, "composition": 0.0}, - 117: {"mass": 116.913648, "composition": 0.0}, - 118: {"mass": 117.913074, "composition": 0.0}, - 119: {"mass": 118.910074, "composition": 0.0}, - 120: {"mass": 119.910087, "composition": 0.0}, - 121: {"mass": 120.9074051, "composition": 0.0}, - 122: {"mass": 121.9075888, "composition": 0.0}, - 123: {"mass": 122.9055885, "composition": 0.0}, - 124: {"mass": 123.906209, "composition": 0.0}, - 125: {"mass": 124.9046294, "composition": 0.0}, - 126: {"mass": 125.9056233, "composition": 0.0}, - 127: {"mass": 126.9044719, "composition": 1.0}, - 128: {"mass": 127.9058086, "composition": 0.0}, - 129: {"mass": 128.9049837, "composition": 0.0}, - 130: {"mass": 129.9066702, "composition": 0.0}, - 131: {"mass": 130.9061263, "composition": 0.0}, - 132: {"mass": 131.9079935, "composition": 0.0}, - 133: {"mass": 132.907797, "composition": 0.0}, - 134: {"mass": 133.9097588, "composition": 0.0}, - 135: {"mass": 134.9100488, "composition": 0.0}, - 136: {"mass": 135.914604, "composition": 0.0}, - 137: {"mass": 136.9180282, "composition": 0.0}, - 138: {"mass": 137.9227264, "composition": 0.0}, - 139: {"mass": 138.926506, "composition": 0.0}, - 140: {"mass": 139.93173, "composition": 0.0}, - 141: {"mass": 140.93569, "composition": 0.0}, - 142: {"mass": 141.9412, "composition": 0.0}, - 143: {"mass": 142.94565, "composition": 0.0}, - 144: {"mass": 143.95139, "composition": 0.0}, - 145: {"mass": 144.95605, "composition": 0.0}}, - 54: {109: {"mass": 108.95043, "composition": 0.0}, - 110: {"mass": 109.94426, "composition": 0.0}, - 111: {"mass": 110.941607, "composition": 0.0}, - 112: {"mass": 111.935559, "composition": 0.0}, - 113: {"mass": 112.9332217, "composition": 0.0}, - 114: {"mass": 113.92798, "composition": 0.0}, - 115: {"mass": 114.926294, "composition": 0.0}, - 116: {"mass": 115.921581, "composition": 0.0}, - 117: {"mass": 116.920359, "composition": 0.0}, - 118: {"mass": 117.916179, "composition": 0.0}, - 119: {"mass": 118.915411, "composition": 0.0}, - 120: {"mass": 119.911784, "composition": 0.0}, - 121: {"mass": 120.911453, "composition": 0.0}, - 122: {"mass": 121.908368, "composition": 0.0}, - 123: {"mass": 122.908482, "composition": 0.0}, - 124: {"mass": 123.905892, "composition": 0.000952}, - 125: {"mass": 124.9063944, "composition": 0.0}, - 126: {"mass": 125.9042983, "composition": 0.00089}, - 127: {"mass": 126.9051829, "composition": 0.0}, - 128: {"mass": 127.903531, "composition": 0.019102}, - 129: {"mass": 128.9047808611, "composition": 0.264006}, - 130: {"mass": 129.903509349, "composition": 0.04071}, - 131: {"mass": 130.90508406, "composition": 0.212324}, - 132: {"mass": 131.9041550856, "composition": 0.269086}, - 133: {"mass": 132.9059108, "composition": 0.0}, - 134: {"mass": 133.90539466, "composition": 0.104357}, - 135: {"mass": 134.9072278, "composition": 0.0}, - 136: {"mass": 135.907214484, "composition": 0.088573}, - 137: {"mass": 136.91155778, "composition": 0.0}, - 138: {"mass": 137.9141463, "composition": 0.0}, - 139: {"mass": 138.9187922, "composition": 0.0}, - 140: {"mass": 139.9216458, "composition": 0.0}, - 141: {"mass": 140.9267872, "composition": 0.0}, - 142: {"mass": 141.9299731, "composition": 0.0}, - 143: {"mass": 142.9353696, "composition": 0.0}, - 144: {"mass": 143.9389451, "composition": 0.0}, - 145: {"mass": 144.94472, "composition": 0.0}, - 146: {"mass": 145.948518, "composition": 0.0}, - 147: {"mass": 146.95426, "composition": 0.0}, - 148: {"mass": 147.95813, "composition": 0.0}}, - 55: {112: {"mass": 111.950309, "composition": 0.0}, - 113: {"mass": 112.9444291, "composition": 0.0}, - 114: {"mass": 113.941296, "composition": 0.0}, - 115: {"mass": 114.93591, "composition": 0.0}, - 116: {"mass": 115.93337, "composition": 0.0}, - 117: {"mass": 116.928617, "composition": 0.0}, - 118: {"mass": 117.92656, "composition": 0.0}, - 119: {"mass": 118.922377, "composition": 0.0}, - 120: {"mass": 119.920677, "composition": 0.0}, - 121: {"mass": 120.917227, "composition": 0.0}, - 122: {"mass": 121.916108, "composition": 0.0}, - 123: {"mass": 122.912996, "composition": 0.0}, - 124: {"mass": 123.9122578, "composition": 0.0}, - 125: {"mass": 124.909728, "composition": 0.0}, - 126: {"mass": 125.909446, "composition": 0.0}, - 127: {"mass": 126.9074174, "composition": 0.0}, - 128: {"mass": 127.9077487, "composition": 0.0}, - 129: {"mass": 128.9060657, "composition": 0.0}, - 130: {"mass": 129.9067093, "composition": 0.0}, - 131: {"mass": 130.9054649, "composition": 0.0}, - 132: {"mass": 131.9064339, "composition": 0.0}, - 133: {"mass": 132.905451961, "composition": 1.0}, - 134: {"mass": 133.906718503, "composition": 0.0}, - 135: {"mass": 134.905977, "composition": 0.0}, - 136: {"mass": 135.9073114, "composition": 0.0}, - 137: {"mass": 136.90708923, "composition": 0.0}, - 138: {"mass": 137.9110171, "composition": 0.0}, - 139: {"mass": 138.9133638, "composition": 0.0}, - 140: {"mass": 139.9172831, "composition": 0.0}, - 141: {"mass": 140.9200455, "composition": 0.0}, - 142: {"mass": 141.924296, "composition": 0.0}, - 143: {"mass": 142.927349, "composition": 0.0}, - 144: {"mass": 143.932076, "composition": 0.0}, - 145: {"mass": 144.935527, "composition": 0.0}, - 146: {"mass": 145.940344, "composition": 0.0}, - 147: {"mass": 146.944156, "composition": 0.0}, - 148: {"mass": 147.94923, "composition": 0.0}, - 149: {"mass": 148.95302, "composition": 0.0}, - 150: {"mass": 149.95833, "composition": 0.0}, - 151: {"mass": 150.96258, "composition": 0.0}}, - 56: {114: {"mass": 113.95066, "composition": 0.0}, - 115: {"mass": 114.94737, "composition": 0.0}, - 116: {"mass": 115.94128, "composition": 0.0}, - 117: {"mass": 116.93814, "composition": 0.0}, - 118: {"mass": 117.93306, "composition": 0.0}, - 119: {"mass": 118.93066, "composition": 0.0}, - 120: {"mass": 119.92605, "composition": 0.0}, - 121: {"mass": 120.92405, "composition": 0.0}, - 122: {"mass": 121.919904, "composition": 0.0}, - 123: {"mass": 122.918781, "composition": 0.0}, - 124: {"mass": 123.915094, "composition": 0.0}, - 125: {"mass": 124.914472, "composition": 0.0}, - 126: {"mass": 125.91125, "composition": 0.0}, - 127: {"mass": 126.911091, "composition": 0.0}, - 128: {"mass": 127.908342, "composition": 0.0}, - 129: {"mass": 128.908681, "composition": 0.0}, - 130: {"mass": 129.9063207, "composition": 0.00106}, - 131: {"mass": 130.906941, "composition": 0.0}, - 132: {"mass": 131.9050611, "composition": 0.00101}, - 133: {"mass": 132.9060074, "composition": 0.0}, - 134: {"mass": 133.90450818, "composition": 0.02417}, - 135: {"mass": 134.90568838, "composition": 0.06592}, - 136: {"mass": 135.90457573, "composition": 0.07854}, - 137: {"mass": 136.90582714, "composition": 0.11232}, - 138: {"mass": 137.905247, "composition": 0.71698}, - 139: {"mass": 138.9088411, "composition": 0.0}, - 140: {"mass": 139.9106057, "composition": 0.0}, - 141: {"mass": 140.9144033, "composition": 0.0}, - 142: {"mass": 141.9164324, "composition": 0.0}, - 143: {"mass": 142.9206253, "composition": 0.0}, - 144: {"mass": 143.9229549, "composition": 0.0}, - 145: {"mass": 144.9275184, "composition": 0.0}, - 146: {"mass": 145.930284, "composition": 0.0}, - 147: {"mass": 146.935304, "composition": 0.0}, - 148: {"mass": 147.938171, "composition": 0.0}, - 149: {"mass": 148.94308, "composition": 0.0}, - 150: {"mass": 149.94605, "composition": 0.0}, - 151: {"mass": 150.95127, "composition": 0.0}, - 152: {"mass": 151.95481, "composition": 0.0}, - 153: {"mass": 152.96036, "composition": 0.0}}, - 57: {116: {"mass": 115.9563, "composition": 0.0}, - 117: {"mass": 116.94999, "composition": 0.0}, - 118: {"mass": 117.94673, "composition": 0.0}, - 119: {"mass": 118.94099, "composition": 0.0}, - 120: {"mass": 119.93807, "composition": 0.0}, - 121: {"mass": 120.93315, "composition": 0.0}, - 122: {"mass": 121.93071, "composition": 0.0}, - 123: {"mass": 122.9263, "composition": 0.0}, - 124: {"mass": 123.924574, "composition": 0.0}, - 125: {"mass": 124.920816, "composition": 0.0}, - 126: {"mass": 125.919513, "composition": 0.0}, - 127: {"mass": 126.916375, "composition": 0.0}, - 128: {"mass": 127.915592, "composition": 0.0}, - 129: {"mass": 128.912694, "composition": 0.0}, - 130: {"mass": 129.912369, "composition": 0.0}, - 131: {"mass": 130.91007, "composition": 0.0}, - 132: {"mass": 131.910119, "composition": 0.0}, - 133: {"mass": 132.908218, "composition": 0.0}, - 134: {"mass": 133.908514, "composition": 0.0}, - 135: {"mass": 134.906984, "composition": 0.0}, - 136: {"mass": 135.907635, "composition": 0.0}, - 137: {"mass": 136.9064504, "composition": 0.0}, - 138: {"mass": 137.9071149, "composition": 0.0008881}, - 139: {"mass": 138.9063563, "composition": 0.9991119}, - 140: {"mass": 139.9094806, "composition": 0.0}, - 141: {"mass": 140.910966, "composition": 0.0}, - 142: {"mass": 141.9140909, "composition": 0.0}, - 143: {"mass": 142.9160795, "composition": 0.0}, - 144: {"mass": 143.919646, "composition": 0.0}, - 145: {"mass": 144.921808, "composition": 0.0}, - 146: {"mass": 145.925875, "composition": 0.0}, - 147: {"mass": 146.928418, "composition": 0.0}, - 148: {"mass": 147.932679, "composition": 0.0}, - 149: {"mass": 148.93535, "composition": 0.0}, - 150: {"mass": 149.93947, "composition": 0.0}, - 151: {"mass": 150.94232, "composition": 0.0}, - 152: {"mass": 151.94682, "composition": 0.0}, - 153: {"mass": 152.95036, "composition": 0.0}, - 154: {"mass": 153.95517, "composition": 0.0}, - 155: {"mass": 154.95901, "composition": 0.0}}, - 58: {119: {"mass": 118.95271, "composition": 0.0}, - 120: {"mass": 119.94654, "composition": 0.0}, - 121: {"mass": 120.94335, "composition": 0.0}, - 122: {"mass": 121.93787, "composition": 0.0}, - 123: {"mass": 122.93528, "composition": 0.0}, - 124: {"mass": 123.93031, "composition": 0.0}, - 125: {"mass": 124.92844, "composition": 0.0}, - 126: {"mass": 125.923971, "composition": 0.0}, - 127: {"mass": 126.922727, "composition": 0.0}, - 128: {"mass": 127.918911, "composition": 0.0}, - 129: {"mass": 128.918102, "composition": 0.0}, - 130: {"mass": 129.914736, "composition": 0.0}, - 131: {"mass": 130.914429, "composition": 0.0}, - 132: {"mass": 131.911464, "composition": 0.0}, - 133: {"mass": 132.91152, "composition": 0.0}, - 134: {"mass": 133.908928, "composition": 0.0}, - 135: {"mass": 134.909161, "composition": 0.0}, - 136: {"mass": 135.90712921, "composition": 0.00185}, - 137: {"mass": 136.90776236, "composition": 0.0}, - 138: {"mass": 137.905991, "composition": 0.00251}, - 139: {"mass": 138.9066551, "composition": 0.0}, - 140: {"mass": 139.9054431, "composition": 0.8845}, - 141: {"mass": 140.9082807, "composition": 0.0}, - 142: {"mass": 141.9092504, "composition": 0.11114}, - 143: {"mass": 142.9123921, "composition": 0.0}, - 144: {"mass": 143.9136529, "composition": 0.0}, - 145: {"mass": 144.917265, "composition": 0.0}, - 146: {"mass": 145.918802, "composition": 0.0}, - 147: {"mass": 146.9226899, "composition": 0.0}, - 148: {"mass": 147.924424, "composition": 0.0}, - 149: {"mass": 148.928427, "composition": 0.0}, - 150: {"mass": 149.930384, "composition": 0.0}, - 151: {"mass": 150.934272, "composition": 0.0}, - 152: {"mass": 151.9366, "composition": 0.0}, - 153: {"mass": 152.94093, "composition": 0.0}, - 154: {"mass": 153.9438, "composition": 0.0}, - 155: {"mass": 154.94855, "composition": 0.0}, - 156: {"mass": 155.95183, "composition": 0.0}, - 157: {"mass": 156.95705, "composition": 0.0}}, - 59: {121: {"mass": 120.95532, "composition": 0.0}, - 122: {"mass": 121.95175, "composition": 0.0}, - 123: {"mass": 122.94596, "composition": 0.0}, - 124: {"mass": 123.94294, "composition": 0.0}, - 125: {"mass": 124.9377, "composition": 0.0}, - 126: {"mass": 125.93524, "composition": 0.0}, - 127: {"mass": 126.93071, "composition": 0.0}, - 128: {"mass": 127.928791, "composition": 0.0}, - 129: {"mass": 128.925095, "composition": 0.0}, - 130: {"mass": 129.92359, "composition": 0.0}, - 131: {"mass": 130.920235, "composition": 0.0}, - 132: {"mass": 131.919255, "composition": 0.0}, - 133: {"mass": 132.916331, "composition": 0.0}, - 134: {"mass": 133.915697, "composition": 0.0}, - 135: {"mass": 134.913112, "composition": 0.0}, - 136: {"mass": 135.912677, "composition": 0.0}, - 137: {"mass": 136.9106792, "composition": 0.0}, - 138: {"mass": 137.910754, "composition": 0.0}, - 139: {"mass": 138.9089408, "composition": 0.0}, - 140: {"mass": 139.9090803, "composition": 0.0}, - 141: {"mass": 140.9076576, "composition": 1.0}, - 142: {"mass": 141.9100496, "composition": 0.0}, - 143: {"mass": 142.9108228, "composition": 0.0}, - 144: {"mass": 143.9133109, "composition": 0.0}, - 145: {"mass": 144.9145182, "composition": 0.0}, - 146: {"mass": 145.91768, "composition": 0.0}, - 147: {"mass": 146.919008, "composition": 0.0}, - 148: {"mass": 147.92213, "composition": 0.0}, - 149: {"mass": 148.923736, "composition": 0.0}, - 150: {"mass": 149.9266765, "composition": 0.0}, - 151: {"mass": 150.928309, "composition": 0.0}, - 152: {"mass": 151.931553, "composition": 0.0}, - 153: {"mass": 152.933904, "composition": 0.0}, - 154: {"mass": 153.93753, "composition": 0.0}, - 155: {"mass": 154.940509, "composition": 0.0}, - 156: {"mass": 155.94464, "composition": 0.0}, - 157: {"mass": 156.94789, "composition": 0.0}, - 158: {"mass": 157.95241, "composition": 0.0}, - 159: {"mass": 158.95589, "composition": 0.0}}, - 60: {124: {"mass": 123.9522, "composition": 0.0}, - 125: {"mass": 124.9489, "composition": 0.0}, - 126: {"mass": 125.94311, "composition": 0.0}, - 127: {"mass": 126.94038, "composition": 0.0}, - 128: {"mass": 127.93525, "composition": 0.0}, - 129: {"mass": 128.9331, "composition": 0.0}, - 130: {"mass": 129.928506, "composition": 0.0}, - 131: {"mass": 130.927248, "composition": 0.0}, - 132: {"mass": 131.923321, "composition": 0.0}, - 133: {"mass": 132.922348, "composition": 0.0}, - 134: {"mass": 133.91879, "composition": 0.0}, - 135: {"mass": 134.918181, "composition": 0.0}, - 136: {"mass": 135.914976, "composition": 0.0}, - 137: {"mass": 136.914562, "composition": 0.0}, - 138: {"mass": 137.91195, "composition": 0.0}, - 139: {"mass": 138.911954, "composition": 0.0}, - 140: {"mass": 139.90955, "composition": 0.0}, - 141: {"mass": 140.9096147, "composition": 0.0}, - 142: {"mass": 141.907729, "composition": 0.27152}, - 143: {"mass": 142.90982, "composition": 0.12174}, - 144: {"mass": 143.910093, "composition": 0.23798}, - 145: {"mass": 144.9125793, "composition": 0.08293}, - 146: {"mass": 145.9131226, "composition": 0.17189}, - 147: {"mass": 146.9161061, "composition": 0.0}, - 148: {"mass": 147.9168993, "composition": 0.05756}, - 149: {"mass": 148.9201548, "composition": 0.0}, - 150: {"mass": 149.9209022, "composition": 0.05638}, - 151: {"mass": 150.9238403, "composition": 0.0}, - 152: {"mass": 151.924692, "composition": 0.0}, - 153: {"mass": 152.927718, "composition": 0.0}, - 154: {"mass": 153.92948, "composition": 0.0}, - 155: {"mass": 154.9331357, "composition": 0.0}, - 156: {"mass": 155.93508, "composition": 0.0}, - 157: {"mass": 156.939386, "composition": 0.0}, - 158: {"mass": 157.94197, "composition": 0.0}, - 159: {"mass": 158.94653, "composition": 0.0}, - 160: {"mass": 159.9494, "composition": 0.0}, - 161: {"mass": 160.95428, "composition": 0.0}}, - 61: {126: {"mass": 125.95792, "composition": 0.0}, - 127: {"mass": 126.95192, "composition": 0.0}, - 128: {"mass": 127.9487, "composition": 0.0}, - 129: {"mass": 128.94323, "composition": 0.0}, - 130: {"mass": 129.94053, "composition": 0.0}, - 131: {"mass": 130.93567, "composition": 0.0}, - 132: {"mass": 131.93384, "composition": 0.0}, - 133: {"mass": 132.929782, "composition": 0.0}, - 134: {"mass": 133.928353, "composition": 0.0}, - 135: {"mass": 134.924823, "composition": 0.0}, - 136: {"mass": 135.923585, "composition": 0.0}, - 137: {"mass": 136.92048, "composition": 0.0}, - 138: {"mass": 137.919548, "composition": 0.0}, - 139: {"mass": 138.9168, "composition": 0.0}, - 140: {"mass": 139.91604, "composition": 0.0}, - 141: {"mass": 140.913555, "composition": 0.0}, - 142: {"mass": 141.91289, "composition": 0.0}, - 143: {"mass": 142.9109383, "composition": 0.0}, - 144: {"mass": 143.9125964, "composition": 0.0}, - 145: {"mass": 144.9127559, "composition": 0.0}, - 146: {"mass": 145.9147024, "composition": 0.0}, - 147: {"mass": 146.915145, "composition": 0.0}, - 148: {"mass": 147.9174819, "composition": 0.0}, - 149: {"mass": 148.9183423, "composition": 0.0}, - 150: {"mass": 149.920991, "composition": 0.0}, - 151: {"mass": 150.9212175, "composition": 0.0}, - 152: {"mass": 151.923506, "composition": 0.0}, - 153: {"mass": 152.9241567, "composition": 0.0}, - 154: {"mass": 153.926472, "composition": 0.0}, - 155: {"mass": 154.928137, "composition": 0.0}, - 156: {"mass": 155.9311175, "composition": 0.0}, - 157: {"mass": 156.9331214, "composition": 0.0}, - 158: {"mass": 157.936565, "composition": 0.0}, - 159: {"mass": 158.939287, "composition": 0.0}, - 160: {"mass": 159.9431, "composition": 0.0}, - 161: {"mass": 160.94607, "composition": 0.0}, - 162: {"mass": 161.95022, "composition": 0.0}, - 163: {"mass": 162.95357, "composition": 0.0}}, - 62: {128: {"mass": 127.95842, "composition": 0.0}, - 129: {"mass": 128.95476, "composition": 0.0}, - 130: {"mass": 129.949, "composition": 0.0}, - 131: {"mass": 130.94618, "composition": 0.0}, - 132: {"mass": 131.94087, "composition": 0.0}, - 133: {"mass": 132.93856, "composition": 0.0}, - 134: {"mass": 133.93411, "composition": 0.0}, - 135: {"mass": 134.93252, "composition": 0.0}, - 136: {"mass": 135.928276, "composition": 0.0}, - 137: {"mass": 136.926971, "composition": 0.0}, - 138: {"mass": 137.923244, "composition": 0.0}, - 139: {"mass": 138.922297, "composition": 0.0}, - 140: {"mass": 139.918995, "composition": 0.0}, - 141: {"mass": 140.9184816, "composition": 0.0}, - 142: {"mass": 141.9152044, "composition": 0.0}, - 143: {"mass": 142.9146353, "composition": 0.0}, - 144: {"mass": 143.9120065, "composition": 0.0307}, - 145: {"mass": 144.9134173, "composition": 0.0}, - 146: {"mass": 145.913047, "composition": 0.0}, - 147: {"mass": 146.9149044, "composition": 0.1499}, - 148: {"mass": 147.9148292, "composition": 0.1124}, - 149: {"mass": 148.9171921, "composition": 0.1382}, - 150: {"mass": 149.9172829, "composition": 0.0738}, - 151: {"mass": 150.9199398, "composition": 0.0}, - 152: {"mass": 151.9197397, "composition": 0.2675}, - 153: {"mass": 152.9221047, "composition": 0.0}, - 154: {"mass": 153.9222169, "composition": 0.2275}, - 155: {"mass": 154.9246477, "composition": 0.0}, - 156: {"mass": 155.925536, "composition": 0.0}, - 157: {"mass": 156.9284187, "composition": 0.0}, - 158: {"mass": 157.929951, "composition": 0.0}, - 159: {"mass": 158.9332172, "composition": 0.0}, - 160: {"mass": 159.9353353, "composition": 0.0}, - 161: {"mass": 160.9391602, "composition": 0.0}, - 162: {"mass": 161.94146, "composition": 0.0}, - 163: {"mass": 162.94555, "composition": 0.0}, - 164: {"mass": 163.94836, "composition": 0.0}, - 165: {"mass": 164.95297, "composition": 0.0}}, - 63: {130: {"mass": 129.96369, "composition": 0.0}, - 131: {"mass": 130.95784, "composition": 0.0}, - 132: {"mass": 131.95467, "composition": 0.0}, - 133: {"mass": 132.94929, "composition": 0.0}, - 134: {"mass": 133.9464, "composition": 0.0}, - 135: {"mass": 134.94187, "composition": 0.0}, - 136: {"mass": 135.93962, "composition": 0.0}, - 137: {"mass": 136.93546, "composition": 0.0}, - 138: {"mass": 137.933709, "composition": 0.0}, - 139: {"mass": 138.929792, "composition": 0.0}, - 140: {"mass": 139.928088, "composition": 0.0}, - 141: {"mass": 140.924932, "composition": 0.0}, - 142: {"mass": 141.923442, "composition": 0.0}, - 143: {"mass": 142.920299, "composition": 0.0}, - 144: {"mass": 143.91882, "composition": 0.0}, - 145: {"mass": 144.9162726, "composition": 0.0}, - 146: {"mass": 145.917211, "composition": 0.0}, - 147: {"mass": 146.9167527, "composition": 0.0}, - 148: {"mass": 147.918089, "composition": 0.0}, - 149: {"mass": 148.9179378, "composition": 0.0}, - 150: {"mass": 149.9197077, "composition": 0.0}, - 151: {"mass": 150.9198578, "composition": 0.4781}, - 152: {"mass": 151.9217522, "composition": 0.0}, - 153: {"mass": 152.921238, "composition": 0.5219}, - 154: {"mass": 153.922987, "composition": 0.0}, - 155: {"mass": 154.9229011, "composition": 0.0}, - 156: {"mass": 155.9247605, "composition": 0.0}, - 157: {"mass": 156.9254334, "composition": 0.0}, - 158: {"mass": 157.927799, "composition": 0.0}, - 159: {"mass": 158.9291001, "composition": 0.0}, - 160: {"mass": 159.931851, "composition": 0.0}, - 161: {"mass": 160.933664, "composition": 0.0}, - 162: {"mass": 161.936989, "composition": 0.0}, - 163: {"mass": 162.939196, "composition": 0.0}, - 164: {"mass": 163.94274, "composition": 0.0}, - 165: {"mass": 164.94559, "composition": 0.0}, - 166: {"mass": 165.94962, "composition": 0.0}, - 167: {"mass": 166.95289, "composition": 0.0}}, - 64: {133: {"mass": 132.96133, "composition": 0.0}, - 134: {"mass": 133.95566, "composition": 0.0}, - 135: {"mass": 134.95245, "composition": 0.0}, - 136: {"mass": 135.9473, "composition": 0.0}, - 137: {"mass": 136.94502, "composition": 0.0}, - 138: {"mass": 137.94025, "composition": 0.0}, - 139: {"mass": 138.93813, "composition": 0.0}, - 140: {"mass": 139.933674, "composition": 0.0}, - 141: {"mass": 140.932126, "composition": 0.0}, - 142: {"mass": 141.928116, "composition": 0.0}, - 143: {"mass": 142.92675, "composition": 0.0}, - 144: {"mass": 143.922963, "composition": 0.0}, - 145: {"mass": 144.921713, "composition": 0.0}, - 146: {"mass": 145.9183188, "composition": 0.0}, - 147: {"mass": 146.9191014, "composition": 0.0}, - 148: {"mass": 147.9181215, "composition": 0.0}, - 149: {"mass": 148.9193481, "composition": 0.0}, - 150: {"mass": 149.9186644, "composition": 0.0}, - 151: {"mass": 150.920356, "composition": 0.0}, - 152: {"mass": 151.9197995, "composition": 0.002}, - 153: {"mass": 152.921758, "composition": 0.0}, - 154: {"mass": 153.9208741, "composition": 0.0218}, - 155: {"mass": 154.9226305, "composition": 0.148}, - 156: {"mass": 155.9221312, "composition": 0.2047}, - 157: {"mass": 156.9239686, "composition": 0.1565}, - 158: {"mass": 157.9241123, "composition": 0.2484}, - 159: {"mass": 158.926397, "composition": 0.0}, - 160: {"mass": 159.9270624, "composition": 0.2186}, - 161: {"mass": 160.9296775, "composition": 0.0}, - 162: {"mass": 161.930993, "composition": 0.0}, - 163: {"mass": 162.9341769, "composition": 0.0}, - 164: {"mass": 163.93583, "composition": 0.0}, - 165: {"mass": 164.93936, "composition": 0.0}, - 166: {"mass": 165.94146, "composition": 0.0}, - 167: {"mass": 166.94545, "composition": 0.0}, - 168: {"mass": 167.94808, "composition": 0.0}, - 169: {"mass": 168.9526, "composition": 0.0}}, - 65: {135: {"mass": 134.96476, "composition": 0.0}, - 136: {"mass": 135.96129, "composition": 0.0}, - 137: {"mass": 136.95602, "composition": 0.0}, - 138: {"mass": 137.95312, "composition": 0.0}, - 139: {"mass": 138.94833, "composition": 0.0}, - 140: {"mass": 139.94581, "composition": 0.0}, - 141: {"mass": 140.94145, "composition": 0.0}, - 142: {"mass": 141.93928, "composition": 0.0}, - 143: {"mass": 142.935137, "composition": 0.0}, - 144: {"mass": 143.933045, "composition": 0.0}, - 145: {"mass": 144.92882, "composition": 0.0}, - 146: {"mass": 145.927253, "composition": 0.0}, - 147: {"mass": 146.9240548, "composition": 0.0}, - 148: {"mass": 147.924282, "composition": 0.0}, - 149: {"mass": 148.9232535, "composition": 0.0}, - 150: {"mass": 149.9236649, "composition": 0.0}, - 151: {"mass": 150.9231096, "composition": 0.0}, - 152: {"mass": 151.924083, "composition": 0.0}, - 153: {"mass": 152.9234424, "composition": 0.0}, - 154: {"mass": 153.924685, "composition": 0.0}, - 155: {"mass": 154.923511, "composition": 0.0}, - 156: {"mass": 155.9247552, "composition": 0.0}, - 157: {"mass": 156.924033, "composition": 0.0}, - 158: {"mass": 157.9254209, "composition": 0.0}, - 159: {"mass": 158.9253547, "composition": 1.0}, - 160: {"mass": 159.9271756, "composition": 0.0}, - 161: {"mass": 160.9275778, "composition": 0.0}, - 162: {"mass": 161.929495, "composition": 0.0}, - 163: {"mass": 162.9306547, "composition": 0.0}, - 164: {"mass": 163.93336, "composition": 0.0}, - 165: {"mass": 164.93498, "composition": 0.0}, - 166: {"mass": 165.93786, "composition": 0.0}, - 167: {"mass": 166.93996, "composition": 0.0}, - 168: {"mass": 167.9434, "composition": 0.0}, - 169: {"mass": 168.94597, "composition": 0.0}, - 170: {"mass": 169.94984, "composition": 0.0}, - 171: {"mass": 170.95273, "composition": 0.0}}, - 66: {138: {"mass": 137.9625, "composition": 0.0}, - 139: {"mass": 138.95959, "composition": 0.0}, - 140: {"mass": 139.95402, "composition": 0.0}, - 141: {"mass": 140.95128, "composition": 0.0}, - 142: {"mass": 141.94619, "composition": 0.0}, - 143: {"mass": 142.943994, "composition": 0.0}, - 144: {"mass": 143.9392695, "composition": 0.0}, - 145: {"mass": 144.937474, "composition": 0.0}, - 146: {"mass": 145.9328445, "composition": 0.0}, - 147: {"mass": 146.9310827, "composition": 0.0}, - 148: {"mass": 147.927157, "composition": 0.0}, - 149: {"mass": 148.927322, "composition": 0.0}, - 150: {"mass": 149.9255933, "composition": 0.0}, - 151: {"mass": 150.9261916, "composition": 0.0}, - 152: {"mass": 151.9247253, "composition": 0.0}, - 153: {"mass": 152.9257724, "composition": 0.0}, - 154: {"mass": 153.9244293, "composition": 0.0}, - 155: {"mass": 154.925759, "composition": 0.0}, - 156: {"mass": 155.9242847, "composition": 0.00056}, - 157: {"mass": 156.9254707, "composition": 0.0}, - 158: {"mass": 157.9244159, "composition": 0.00095}, - 159: {"mass": 158.925747, "composition": 0.0}, - 160: {"mass": 159.9252046, "composition": 0.02329}, - 161: {"mass": 160.9269405, "composition": 0.18889}, - 162: {"mass": 161.9268056, "composition": 0.25475}, - 163: {"mass": 162.9287383, "composition": 0.24896}, - 164: {"mass": 163.9291819, "composition": 0.2826}, - 165: {"mass": 164.9317105, "composition": 0.0}, - 166: {"mass": 165.9328139, "composition": 0.0}, - 167: {"mass": 166.935661, "composition": 0.0}, - 168: {"mass": 167.93713, "composition": 0.0}, - 169: {"mass": 168.94031, "composition": 0.0}, - 170: {"mass": 169.94239, "composition": 0.0}, - 171: {"mass": 170.94612, "composition": 0.0}, - 172: {"mass": 171.94846, "composition": 0.0}, - 173: {"mass": 172.95283, "composition": 0.0}}, - 67: {140: {"mass": 139.96859, "composition": 0.0}, - 141: {"mass": 140.96311, "composition": 0.0}, - 142: {"mass": 141.96001, "composition": 0.0}, - 143: {"mass": 142.95486, "composition": 0.0}, - 144: {"mass": 143.9521097, "composition": 0.0}, - 145: {"mass": 144.9472674, "composition": 0.0}, - 146: {"mass": 145.9449935, "composition": 0.0}, - 147: {"mass": 146.9401423, "composition": 0.0}, - 148: {"mass": 147.937744, "composition": 0.0}, - 149: {"mass": 148.933803, "composition": 0.0}, - 150: {"mass": 149.933498, "composition": 0.0}, - 151: {"mass": 150.9316983, "composition": 0.0}, - 152: {"mass": 151.931724, "composition": 0.0}, - 153: {"mass": 152.9302064, "composition": 0.0}, - 154: {"mass": 153.9306068, "composition": 0.0}, - 155: {"mass": 154.929104, "composition": 0.0}, - 156: {"mass": 155.929706, "composition": 0.0}, - 157: {"mass": 156.928254, "composition": 0.0}, - 158: {"mass": 157.928946, "composition": 0.0}, - 159: {"mass": 158.9277197, "composition": 0.0}, - 160: {"mass": 159.928737, "composition": 0.0}, - 161: {"mass": 160.9278615, "composition": 0.0}, - 162: {"mass": 161.9291023, "composition": 0.0}, - 163: {"mass": 162.928741, "composition": 0.0}, - 164: {"mass": 163.9302403, "composition": 0.0}, - 165: {"mass": 164.9303288, "composition": 1.0}, - 166: {"mass": 165.9322909, "composition": 0.0}, - 167: {"mass": 166.9331385, "composition": 0.0}, - 168: {"mass": 167.935522, "composition": 0.0}, - 169: {"mass": 168.936878, "composition": 0.0}, - 170: {"mass": 169.939625, "composition": 0.0}, - 171: {"mass": 170.94147, "composition": 0.0}, - 172: {"mass": 171.94473, "composition": 0.0}, - 173: {"mass": 172.94702, "composition": 0.0}, - 174: {"mass": 173.95095, "composition": 0.0}, - 175: {"mass": 174.95362, "composition": 0.0}}, - 68: {142: {"mass": 141.9701, "composition": 0.0}, - 143: {"mass": 142.96662, "composition": 0.0}, - 144: {"mass": 143.9607, "composition": 0.0}, - 145: {"mass": 144.95805, "composition": 0.0}, - 146: {"mass": 145.9524184, "composition": 0.0}, - 147: {"mass": 146.949964, "composition": 0.0}, - 148: {"mass": 147.944735, "composition": 0.0}, - 149: {"mass": 148.942306, "composition": 0.0}, - 150: {"mass": 149.937916, "composition": 0.0}, - 151: {"mass": 150.937449, "composition": 0.0}, - 152: {"mass": 151.935057, "composition": 0.0}, - 153: {"mass": 152.93508, "composition": 0.0}, - 154: {"mass": 153.9327908, "composition": 0.0}, - 155: {"mass": 154.9332159, "composition": 0.0}, - 156: {"mass": 155.931067, "composition": 0.0}, - 157: {"mass": 156.931949, "composition": 0.0}, - 158: {"mass": 157.929893, "composition": 0.0}, - 159: {"mass": 158.9306918, "composition": 0.0}, - 160: {"mass": 159.929077, "composition": 0.0}, - 161: {"mass": 160.9300046, "composition": 0.0}, - 162: {"mass": 161.9287884, "composition": 0.00139}, - 163: {"mass": 162.9300408, "composition": 0.0}, - 164: {"mass": 163.9292088, "composition": 0.01601}, - 165: {"mass": 164.9307345, "composition": 0.0}, - 166: {"mass": 165.9302995, "composition": 0.33503}, - 167: {"mass": 166.9320546, "composition": 0.22869}, - 168: {"mass": 167.9323767, "composition": 0.26978}, - 169: {"mass": 168.9345968, "composition": 0.0}, - 170: {"mass": 169.9354702, "composition": 0.1491}, - 171: {"mass": 170.9380357, "composition": 0.0}, - 172: {"mass": 171.9393619, "composition": 0.0}, - 173: {"mass": 172.9424, "composition": 0.0}, - 174: {"mass": 173.94423, "composition": 0.0}, - 175: {"mass": 174.94777, "composition": 0.0}, - 176: {"mass": 175.94994, "composition": 0.0}, - 177: {"mass": 176.95399, "composition": 0.0}}, - 69: {144: {"mass": 143.97628, "composition": 0.0}, - 145: {"mass": 144.97039, "composition": 0.0}, - 146: {"mass": 145.96684, "composition": 0.0}, - 147: {"mass": 146.9613799, "composition": 0.0}, - 148: {"mass": 147.958384, "composition": 0.0}, - 149: {"mass": 148.95289, "composition": 0.0}, - 150: {"mass": 149.95009, "composition": 0.0}, - 151: {"mass": 150.945488, "composition": 0.0}, - 152: {"mass": 151.944422, "composition": 0.0}, - 153: {"mass": 152.94204, "composition": 0.0}, - 154: {"mass": 153.94157, "composition": 0.0}, - 155: {"mass": 154.93921, "composition": 0.0}, - 156: {"mass": 155.938992, "composition": 0.0}, - 157: {"mass": 156.936944, "composition": 0.0}, - 158: {"mass": 157.93698, "composition": 0.0}, - 159: {"mass": 158.934975, "composition": 0.0}, - 160: {"mass": 159.935263, "composition": 0.0}, - 161: {"mass": 160.933549, "composition": 0.0}, - 162: {"mass": 161.934002, "composition": 0.0}, - 163: {"mass": 162.9326592, "composition": 0.0}, - 164: {"mass": 163.933544, "composition": 0.0}, - 165: {"mass": 164.9324431, "composition": 0.0}, - 166: {"mass": 165.933561, "composition": 0.0}, - 167: {"mass": 166.9328562, "composition": 0.0}, - 168: {"mass": 167.9341774, "composition": 0.0}, - 169: {"mass": 168.9342179, "composition": 1.0}, - 170: {"mass": 169.935806, "composition": 0.0}, - 171: {"mass": 170.9364339, "composition": 0.0}, - 172: {"mass": 171.9384055, "composition": 0.0}, - 173: {"mass": 172.9396084, "composition": 0.0}, - 174: {"mass": 173.942173, "composition": 0.0}, - 175: {"mass": 174.943841, "composition": 0.0}, - 176: {"mass": 175.947, "composition": 0.0}, - 177: {"mass": 176.94904, "composition": 0.0}, - 178: {"mass": 177.95264, "composition": 0.0}, - 179: {"mass": 178.95534, "composition": 0.0}}, - 70: {148: {"mass": 147.96758, "composition": 0.0}, - 149: {"mass": 148.96436, "composition": 0.0}, - 150: {"mass": 149.95852, "composition": 0.0}, - 151: {"mass": 150.9554, "composition": 0.0}, - 152: {"mass": 151.95027, "composition": 0.0}, - 153: {"mass": 152.94932, "composition": 0.0}, - 154: {"mass": 153.946396, "composition": 0.0}, - 155: {"mass": 154.945783, "composition": 0.0}, - 156: {"mass": 155.942825, "composition": 0.0}, - 157: {"mass": 156.942645, "composition": 0.0}, - 158: {"mass": 157.9398705, "composition": 0.0}, - 159: {"mass": 158.940055, "composition": 0.0}, - 160: {"mass": 159.937557, "composition": 0.0}, - 161: {"mass": 160.937907, "composition": 0.0}, - 162: {"mass": 161.935774, "composition": 0.0}, - 163: {"mass": 162.93634, "composition": 0.0}, - 164: {"mass": 163.934495, "composition": 0.0}, - 165: {"mass": 164.93527, "composition": 0.0}, - 166: {"mass": 165.9338747, "composition": 0.0}, - 167: {"mass": 166.934953, "composition": 0.0}, - 168: {"mass": 167.9338896, "composition": 0.00123}, - 169: {"mass": 168.9351825, "composition": 0.0}, - 170: {"mass": 169.9347664, "composition": 0.02982}, - 171: {"mass": 170.9363302, "composition": 0.1409}, - 172: {"mass": 171.9363859, "composition": 0.2168}, - 173: {"mass": 172.9382151, "composition": 0.16103}, - 174: {"mass": 173.9388664, "composition": 0.32026}, - 175: {"mass": 174.9412808, "composition": 0.0}, - 176: {"mass": 175.9425764, "composition": 0.12996}, - 177: {"mass": 176.9452656, "composition": 0.0}, - 178: {"mass": 177.946651, "composition": 0.0}, - 179: {"mass": 178.95004, "composition": 0.0}, - 180: {"mass": 179.95212, "composition": 0.0}, - 181: {"mass": 180.95589, "composition": 0.0}}, - 71: {150: {"mass": 149.97355, "composition": 0.0}, - 151: {"mass": 150.96768, "composition": 0.0}, - 152: {"mass": 151.96412, "composition": 0.0}, - 153: {"mass": 152.95875, "composition": 0.0}, - 154: {"mass": 153.95736, "composition": 0.0}, - 155: {"mass": 154.954321, "composition": 0.0}, - 156: {"mass": 155.953033, "composition": 0.0}, - 157: {"mass": 156.950127, "composition": 0.0}, - 158: {"mass": 157.949316, "composition": 0.0}, - 159: {"mass": 158.946636, "composition": 0.0}, - 160: {"mass": 159.946033, "composition": 0.0}, - 161: {"mass": 160.943572, "composition": 0.0}, - 162: {"mass": 161.943283, "composition": 0.0}, - 163: {"mass": 162.941179, "composition": 0.0}, - 164: {"mass": 163.941339, "composition": 0.0}, - 165: {"mass": 164.939407, "composition": 0.0}, - 166: {"mass": 165.939859, "composition": 0.0}, - 167: {"mass": 166.93827, "composition": 0.0}, - 168: {"mass": 167.938736, "composition": 0.0}, - 169: {"mass": 168.9376441, "composition": 0.0}, - 170: {"mass": 169.938478, "composition": 0.0}, - 171: {"mass": 170.937917, "composition": 0.0}, - 172: {"mass": 171.9390891, "composition": 0.0}, - 173: {"mass": 172.938934, "composition": 0.0}, - 174: {"mass": 173.9403409, "composition": 0.0}, - 175: {"mass": 174.9407752, "composition": 0.97401}, - 176: {"mass": 175.9426897, "composition": 0.02599}, - 177: {"mass": 176.9437615, "composition": 0.0}, - 178: {"mass": 177.945958, "composition": 0.0}, - 179: {"mass": 178.9473309, "composition": 0.0}, - 180: {"mass": 179.949888, "composition": 0.0}, - 181: {"mass": 180.95191, "composition": 0.0}, - 182: {"mass": 181.95504, "composition": 0.0}, - 183: {"mass": 182.957363, "composition": 0.0}, - 184: {"mass": 183.96091, "composition": 0.0}, - 185: {"mass": 184.96362, "composition": 0.0}}, - 72: {153: {"mass": 152.97069, "composition": 0.0}, - 154: {"mass": 153.96486, "composition": 0.0}, - 155: {"mass": 154.96311, "composition": 0.0}, - 156: {"mass": 155.95935, "composition": 0.0}, - 157: {"mass": 156.95824, "composition": 0.0}, - 158: {"mass": 157.954801, "composition": 0.0}, - 159: {"mass": 158.953996, "composition": 0.0}, - 160: {"mass": 159.950691, "composition": 0.0}, - 161: {"mass": 160.950278, "composition": 0.0}, - 162: {"mass": 161.9472148, "composition": 0.0}, - 163: {"mass": 162.947113, "composition": 0.0}, - 164: {"mass": 163.944371, "composition": 0.0}, - 165: {"mass": 164.944567, "composition": 0.0}, - 166: {"mass": 165.94218, "composition": 0.0}, - 167: {"mass": 166.9426, "composition": 0.0}, - 168: {"mass": 167.940568, "composition": 0.0}, - 169: {"mass": 168.941259, "composition": 0.0}, - 170: {"mass": 169.939609, "composition": 0.0}, - 171: {"mass": 170.940492, "composition": 0.0}, - 172: {"mass": 171.93945, "composition": 0.0}, - 173: {"mass": 172.940513, "composition": 0.0}, - 174: {"mass": 173.9400461, "composition": 0.0016}, - 175: {"mass": 174.9415092, "composition": 0.0}, - 176: {"mass": 175.9414076, "composition": 0.0526}, - 177: {"mass": 176.9432277, "composition": 0.186}, - 178: {"mass": 177.9437058, "composition": 0.2728}, - 179: {"mass": 178.9458232, "composition": 0.1362}, - 180: {"mass": 179.946557, "composition": 0.3508}, - 181: {"mass": 180.9491083, "composition": 0.0}, - 182: {"mass": 181.9505612, "composition": 0.0}, - 183: {"mass": 182.95353, "composition": 0.0}, - 184: {"mass": 183.955446, "composition": 0.0}, - 185: {"mass": 184.958862, "composition": 0.0}, - 186: {"mass": 185.960897, "composition": 0.0}, - 187: {"mass": 186.96477, "composition": 0.0}, - 188: {"mass": 187.96685, "composition": 0.0}, - 189: {"mass": 188.97084, "composition": 0.0}}, - 73: {155: {"mass": 154.97424, "composition": 0.0}, - 156: {"mass": 155.97203, "composition": 0.0}, - 157: {"mass": 156.96818, "composition": 0.0}, - 158: {"mass": 157.96654, "composition": 0.0}, - 159: {"mass": 158.963023, "composition": 0.0}, - 160: {"mass": 159.961488, "composition": 0.0}, - 161: {"mass": 160.958452, "composition": 0.0}, - 162: {"mass": 161.957294, "composition": 0.0}, - 163: {"mass": 162.954337, "composition": 0.0}, - 164: {"mass": 163.953534, "composition": 0.0}, - 165: {"mass": 164.950781, "composition": 0.0}, - 166: {"mass": 165.950512, "composition": 0.0}, - 167: {"mass": 166.948093, "composition": 0.0}, - 168: {"mass": 167.948047, "composition": 0.0}, - 169: {"mass": 168.946011, "composition": 0.0}, - 170: {"mass": 169.946175, "composition": 0.0}, - 171: {"mass": 170.944476, "composition": 0.0}, - 172: {"mass": 171.944895, "composition": 0.0}, - 173: {"mass": 172.94375, "composition": 0.0}, - 174: {"mass": 173.944454, "composition": 0.0}, - 175: {"mass": 174.943737, "composition": 0.0}, - 176: {"mass": 175.944857, "composition": 0.0}, - 177: {"mass": 176.9444795, "composition": 0.0}, - 178: {"mass": 177.945678, "composition": 0.0}, - 179: {"mass": 178.9459366, "composition": 0.0}, - 180: {"mass": 179.9474648, "composition": 0.0001201}, - 181: {"mass": 180.9479958, "composition": 0.9998799}, - 182: {"mass": 181.9501519, "composition": 0.0}, - 183: {"mass": 182.9513726, "composition": 0.0}, - 184: {"mass": 183.954008, "composition": 0.0}, - 185: {"mass": 184.955559, "composition": 0.0}, - 186: {"mass": 185.958551, "composition": 0.0}, - 187: {"mass": 186.960386, "composition": 0.0}, - 188: {"mass": 187.963916, "composition": 0.0}, - 189: {"mass": 188.96583, "composition": 0.0}, - 190: {"mass": 189.96939, "composition": 0.0}, - 191: {"mass": 190.97156, "composition": 0.0}, - 192: {"mass": 191.97514, "composition": 0.0}}, - 74: {157: {"mass": 156.97884, "composition": 0.0}, - 158: {"mass": 157.97456, "composition": 0.0}, - 159: {"mass": 158.97264, "composition": 0.0}, - 160: {"mass": 159.96846, "composition": 0.0}, - 161: {"mass": 160.9672, "composition": 0.0}, - 162: {"mass": 161.963499, "composition": 0.0}, - 163: {"mass": 162.962524, "composition": 0.0}, - 164: {"mass": 163.958961, "composition": 0.0}, - 165: {"mass": 164.958281, "composition": 0.0}, - 166: {"mass": 165.955031, "composition": 0.0}, - 167: {"mass": 166.954805, "composition": 0.0}, - 168: {"mass": 167.951806, "composition": 0.0}, - 169: {"mass": 168.951779, "composition": 0.0}, - 170: {"mass": 169.949232, "composition": 0.0}, - 171: {"mass": 170.949451, "composition": 0.0}, - 172: {"mass": 171.947292, "composition": 0.0}, - 173: {"mass": 172.947689, "composition": 0.0}, - 174: {"mass": 173.946079, "composition": 0.0}, - 175: {"mass": 174.946717, "composition": 0.0}, - 176: {"mass": 175.945634, "composition": 0.0}, - 177: {"mass": 176.946643, "composition": 0.0}, - 178: {"mass": 177.945883, "composition": 0.0}, - 179: {"mass": 178.947077, "composition": 0.0}, - 180: {"mass": 179.9467108, "composition": 0.0012}, - 181: {"mass": 180.9481978, "composition": 0.0}, - 182: {"mass": 181.94820394, "composition": 0.265}, - 183: {"mass": 182.95022275, "composition": 0.1431}, - 184: {"mass": 183.95093092, "composition": 0.3064}, - 185: {"mass": 184.95341897, "composition": 0.0}, - 186: {"mass": 185.9543628, "composition": 0.2843}, - 187: {"mass": 186.9571588, "composition": 0.0}, - 188: {"mass": 187.9584862, "composition": 0.0}, - 189: {"mass": 188.961763, "composition": 0.0}, - 190: {"mass": 189.963091, "composition": 0.0}, - 191: {"mass": 190.966531, "composition": 0.0}, - 192: {"mass": 191.96817, "composition": 0.0}, - 193: {"mass": 192.97178, "composition": 0.0}, - 194: {"mass": 193.97367, "composition": 0.0}}, - 75: {159: {"mass": 158.98418, "composition": 0.0}, - 160: {"mass": 159.98182, "composition": 0.0}, - 161: {"mass": 160.97757, "composition": 0.0}, - 162: {"mass": 161.97584, "composition": 0.0}, - 163: {"mass": 162.97208, "composition": 0.0}, - 164: {"mass": 163.970453, "composition": 0.0}, - 165: {"mass": 164.967103, "composition": 0.0}, - 166: {"mass": 165.965761, "composition": 0.0}, - 167: {"mass": 166.962595, "composition": 0.0}, - 168: {"mass": 167.961573, "composition": 0.0}, - 169: {"mass": 168.958766, "composition": 0.0}, - 170: {"mass": 169.95822, "composition": 0.0}, - 171: {"mass": 170.955716, "composition": 0.0}, - 172: {"mass": 171.95542, "composition": 0.0}, - 173: {"mass": 172.953243, "composition": 0.0}, - 174: {"mass": 173.953115, "composition": 0.0}, - 175: {"mass": 174.951381, "composition": 0.0}, - 176: {"mass": 175.951623, "composition": 0.0}, - 177: {"mass": 176.950328, "composition": 0.0}, - 178: {"mass": 177.950989, "composition": 0.0}, - 179: {"mass": 178.949989, "composition": 0.0}, - 180: {"mass": 179.950792, "composition": 0.0}, - 181: {"mass": 180.950058, "composition": 0.0}, - 182: {"mass": 181.95121, "composition": 0.0}, - 183: {"mass": 182.9508196, "composition": 0.0}, - 184: {"mass": 183.9525228, "composition": 0.0}, - 185: {"mass": 184.9529545, "composition": 0.374}, - 186: {"mass": 185.9549856, "composition": 0.0}, - 187: {"mass": 186.9557501, "composition": 0.626}, - 188: {"mass": 187.9581115, "composition": 0.0}, - 189: {"mass": 188.959226, "composition": 0.0}, - 190: {"mass": 189.961744, "composition": 0.0}, - 191: {"mass": 190.963122, "composition": 0.0}, - 192: {"mass": 191.966088, "composition": 0.0}, - 193: {"mass": 192.967541, "composition": 0.0}, - 194: {"mass": 193.97076, "composition": 0.0}, - 195: {"mass": 194.97254, "composition": 0.0}, - 196: {"mass": 195.9758, "composition": 0.0}, - 197: {"mass": 196.97799, "composition": 0.0}, - 198: {"mass": 197.9816, "composition": 0.0}}, - 76: {161: {"mass": 160.98903, "composition": 0.0}, - 162: {"mass": 161.98443, "composition": 0.0}, - 163: {"mass": 162.98241, "composition": 0.0}, - 164: {"mass": 163.97802, "composition": 0.0}, - 165: {"mass": 164.9766, "composition": 0.0}, - 166: {"mass": 165.972692, "composition": 0.0}, - 167: {"mass": 166.971549, "composition": 0.0}, - 168: {"mass": 167.967808, "composition": 0.0}, - 169: {"mass": 168.967018, "composition": 0.0}, - 170: {"mass": 169.963578, "composition": 0.0}, - 171: {"mass": 170.963174, "composition": 0.0}, - 172: {"mass": 171.960017, "composition": 0.0}, - 173: {"mass": 172.959808, "composition": 0.0}, - 174: {"mass": 173.957064, "composition": 0.0}, - 175: {"mass": 174.956945, "composition": 0.0}, - 176: {"mass": 175.954806, "composition": 0.0}, - 177: {"mass": 176.954966, "composition": 0.0}, - 178: {"mass": 177.953254, "composition": 0.0}, - 179: {"mass": 178.953817, "composition": 0.0}, - 180: {"mass": 179.952375, "composition": 0.0}, - 181: {"mass": 180.953247, "composition": 0.0}, - 182: {"mass": 181.95211, "composition": 0.0}, - 183: {"mass": 182.953125, "composition": 0.0}, - 184: {"mass": 183.9524885, "composition": 0.0002}, - 185: {"mass": 184.9540417, "composition": 0.0}, - 186: {"mass": 185.953835, "composition": 0.0159}, - 187: {"mass": 186.9557474, "composition": 0.0196}, - 188: {"mass": 187.9558352, "composition": 0.1324}, - 189: {"mass": 188.9581442, "composition": 0.1615}, - 190: {"mass": 189.9584437, "composition": 0.2626}, - 191: {"mass": 190.9609264, "composition": 0.0}, - 192: {"mass": 191.961477, "composition": 0.4078}, - 193: {"mass": 192.9641479, "composition": 0.0}, - 194: {"mass": 193.9651772, "composition": 0.0}, - 195: {"mass": 194.968318, "composition": 0.0}, - 196: {"mass": 195.969641, "composition": 0.0}, - 197: {"mass": 196.97283, "composition": 0.0}, - 198: {"mass": 197.97441, "composition": 0.0}, - 199: {"mass": 198.97801, "composition": 0.0}, - 200: {"mass": 199.97984, "composition": 0.0}, - 201: {"mass": 200.98364, "composition": 0.0}, - 202: {"mass": 201.98595, "composition": 0.0}}, - 77: {164: {"mass": 163.99191, "composition": 0.0}, - 165: {"mass": 164.9875, "composition": 0.0}, - 166: {"mass": 165.98566, "composition": 0.0}, - 167: {"mass": 166.981666, "composition": 0.0}, - 168: {"mass": 167.979907, "composition": 0.0}, - 169: {"mass": 168.976298, "composition": 0.0}, - 170: {"mass": 169.974922, "composition": 0.0}, - 171: {"mass": 170.97164, "composition": 0.0}, - 172: {"mass": 171.970607, "composition": 0.0}, - 173: {"mass": 172.967506, "composition": 0.0}, - 174: {"mass": 173.966861, "composition": 0.0}, - 175: {"mass": 174.96415, "composition": 0.0}, - 176: {"mass": 175.96365, "composition": 0.0}, - 177: {"mass": 176.961301, "composition": 0.0}, - 178: {"mass": 177.961082, "composition": 0.0}, - 179: {"mass": 178.95912, "composition": 0.0}, - 180: {"mass": 179.959229, "composition": 0.0}, - 181: {"mass": 180.957625, "composition": 0.0}, - 182: {"mass": 181.958076, "composition": 0.0}, - 183: {"mass": 182.95684, "composition": 0.0}, - 184: {"mass": 183.957476, "composition": 0.0}, - 185: {"mass": 184.956698, "composition": 0.0}, - 186: {"mass": 185.957944, "composition": 0.0}, - 187: {"mass": 186.957542, "composition": 0.0}, - 188: {"mass": 187.958828, "composition": 0.0}, - 189: {"mass": 188.958715, "composition": 0.0}, - 190: {"mass": 189.9605412, "composition": 0.0}, - 191: {"mass": 190.9605893, "composition": 0.373}, - 192: {"mass": 191.9626002, "composition": 0.0}, - 193: {"mass": 192.9629216, "composition": 0.627}, - 194: {"mass": 193.9650735, "composition": 0.0}, - 195: {"mass": 194.9659747, "composition": 0.0}, - 196: {"mass": 195.968397, "composition": 0.0}, - 197: {"mass": 196.969655, "composition": 0.0}, - 198: {"mass": 197.97228, "composition": 0.0}, - 199: {"mass": 198.973805, "composition": 0.0}, - 200: {"mass": 199.9768, "composition": 0.0}, - 201: {"mass": 200.97864, "composition": 0.0}, - 202: {"mass": 201.98199, "composition": 0.0}, - 203: {"mass": 202.98423, "composition": 0.0}, - 204: {"mass": 203.9896, "composition": 0.0}}, - 78: {166: {"mass": 165.99486, "composition": 0.0}, - 167: {"mass": 166.99269, "composition": 0.0}, - 168: {"mass": 167.98813, "composition": 0.0}, - 169: {"mass": 168.98657, "composition": 0.0}, - 170: {"mass": 169.982496, "composition": 0.0}, - 171: {"mass": 170.981245, "composition": 0.0}, - 172: {"mass": 171.977351, "composition": 0.0}, - 173: {"mass": 172.976443, "composition": 0.0}, - 174: {"mass": 173.97282, "composition": 0.0}, - 175: {"mass": 174.97241, "composition": 0.0}, - 176: {"mass": 175.968938, "composition": 0.0}, - 177: {"mass": 176.96847, "composition": 0.0}, - 178: {"mass": 177.96565, "composition": 0.0}, - 179: {"mass": 178.965359, "composition": 0.0}, - 180: {"mass": 179.963032, "composition": 0.0}, - 181: {"mass": 180.963098, "composition": 0.0}, - 182: {"mass": 181.961172, "composition": 0.0}, - 183: {"mass": 182.961597, "composition": 0.0}, - 184: {"mass": 183.959915, "composition": 0.0}, - 185: {"mass": 184.960614, "composition": 0.0}, - 186: {"mass": 185.959351, "composition": 0.0}, - 187: {"mass": 186.960617, "composition": 0.0}, - 188: {"mass": 187.9593889, "composition": 0.0}, - 189: {"mass": 188.960831, "composition": 0.0}, - 190: {"mass": 189.9599297, "composition": 0.00012}, - 191: {"mass": 190.9616729, "composition": 0.0}, - 192: {"mass": 191.9610387, "composition": 0.00782}, - 193: {"mass": 192.9629824, "composition": 0.0}, - 194: {"mass": 193.9626809, "composition": 0.3286}, - 195: {"mass": 194.9647917, "composition": 0.3378}, - 196: {"mass": 195.96495209, "composition": 0.2521}, - 197: {"mass": 196.96734069, "composition": 0.0}, - 198: {"mass": 197.9678949, "composition": 0.07356}, - 199: {"mass": 198.9705952, "composition": 0.0}, - 200: {"mass": 199.971443, "composition": 0.0}, - 201: {"mass": 200.974513, "composition": 0.0}, - 202: {"mass": 201.975639, "composition": 0.0}, - 203: {"mass": 202.97893, "composition": 0.0}, - 204: {"mass": 203.98076, "composition": 0.0}, - 205: {"mass": 204.98608, "composition": 0.0}, - 206: {"mass": 205.98966, "composition": 0.0}}, - 79: {169: {"mass": 168.99808, "composition": 0.0}, - 170: {"mass": 169.99597, "composition": 0.0}, - 171: {"mass": 170.991876, "composition": 0.0}, - 172: {"mass": 171.989942, "composition": 0.0}, - 173: {"mass": 172.986241, "composition": 0.0}, - 174: {"mass": 173.984717, "composition": 0.0}, - 175: {"mass": 174.981304, "composition": 0.0}, - 176: {"mass": 175.98025, "composition": 0.0}, - 177: {"mass": 176.97687, "composition": 0.0}, - 178: {"mass": 177.976032, "composition": 0.0}, - 179: {"mass": 178.973174, "composition": 0.0}, - 180: {"mass": 179.972523, "composition": 0.0}, - 181: {"mass": 180.970079, "composition": 0.0}, - 182: {"mass": 181.969618, "composition": 0.0}, - 183: {"mass": 182.967591, "composition": 0.0}, - 184: {"mass": 183.967452, "composition": 0.0}, - 185: {"mass": 184.96579, "composition": 0.0}, - 186: {"mass": 185.965953, "composition": 0.0}, - 187: {"mass": 186.964543, "composition": 0.0}, - 188: {"mass": 187.965349, "composition": 0.0}, - 189: {"mass": 188.963948, "composition": 0.0}, - 190: {"mass": 189.964698, "composition": 0.0}, - 191: {"mass": 190.963702, "composition": 0.0}, - 192: {"mass": 191.964814, "composition": 0.0}, - 193: {"mass": 192.9641373, "composition": 0.0}, - 194: {"mass": 193.9654178, "composition": 0.0}, - 195: {"mass": 194.9650352, "composition": 0.0}, - 196: {"mass": 195.9665699, "composition": 0.0}, - 197: {"mass": 196.96656879, "composition": 1.0}, - 198: {"mass": 197.96824242, "composition": 0.0}, - 199: {"mass": 198.96876528, "composition": 0.0}, - 200: {"mass": 199.970756, "composition": 0.0}, - 201: {"mass": 200.9716575, "composition": 0.0}, - 202: {"mass": 201.973856, "composition": 0.0}, - 203: {"mass": 202.9751544, "composition": 0.0}, - 204: {"mass": 203.97783, "composition": 0.0}, - 205: {"mass": 204.97985, "composition": 0.0}, - 206: {"mass": 205.98474, "composition": 0.0}, - 207: {"mass": 206.9884, "composition": 0.0}, - 208: {"mass": 207.99345, "composition": 0.0}, - 209: {"mass": 208.99735, "composition": 0.0}, - 210: {"mass": 210.0025, "composition": 0.0}}, - 80: {171: {"mass": 171.00353, "composition": 0.0}, - 172: {"mass": 171.99881, "composition": 0.0}, - 173: {"mass": 172.99709, "composition": 0.0}, - 174: {"mass": 173.992865, "composition": 0.0}, - 175: {"mass": 174.991441, "composition": 0.0}, - 176: {"mass": 175.987361, "composition": 0.0}, - 177: {"mass": 176.986277, "composition": 0.0}, - 178: {"mass": 177.982484, "composition": 0.0}, - 179: {"mass": 178.981831, "composition": 0.0}, - 180: {"mass": 179.97826, "composition": 0.0}, - 181: {"mass": 180.977819, "composition": 0.0}, - 182: {"mass": 181.974689, "composition": 0.0}, - 183: {"mass": 182.9744448, "composition": 0.0}, - 184: {"mass": 183.971714, "composition": 0.0}, - 185: {"mass": 184.971899, "composition": 0.0}, - 186: {"mass": 185.969362, "composition": 0.0}, - 187: {"mass": 186.969814, "composition": 0.0}, - 188: {"mass": 187.967567, "composition": 0.0}, - 189: {"mass": 188.968195, "composition": 0.0}, - 190: {"mass": 189.966323, "composition": 0.0}, - 191: {"mass": 190.967157, "composition": 0.0}, - 192: {"mass": 191.965635, "composition": 0.0}, - 193: {"mass": 192.966653, "composition": 0.0}, - 194: {"mass": 193.9654491, "composition": 0.0}, - 195: {"mass": 194.966721, "composition": 0.0}, - 196: {"mass": 195.9658326, "composition": 0.0015}, - 197: {"mass": 196.9672128, "composition": 0.0}, - 198: {"mass": 197.9667686, "composition": 0.0997}, - 199: {"mass": 198.96828064, "composition": 0.1687}, - 200: {"mass": 199.96832659, "composition": 0.231}, - 201: {"mass": 200.97030284, "composition": 0.1318}, - 202: {"mass": 201.9706434, "composition": 0.2986}, - 203: {"mass": 202.9728728, "composition": 0.0}, - 204: {"mass": 203.97349398, "composition": 0.0687}, - 205: {"mass": 204.9760734, "composition": 0.0}, - 206: {"mass": 205.977514, "composition": 0.0}, - 207: {"mass": 206.9823, "composition": 0.0}, - 208: {"mass": 207.985759, "composition": 0.0}, - 209: {"mass": 208.99072, "composition": 0.0}, - 210: {"mass": 209.99424, "composition": 0.0}, - 211: {"mass": 210.99933, "composition": 0.0}, - 212: {"mass": 212.00296, "composition": 0.0}, - 213: {"mass": 213.00823, "composition": 0.0}, - 214: {"mass": 214.012, "composition": 0.0}, - 215: {"mass": 215.0174, "composition": 0.0}, - 216: {"mass": 216.02132, "composition": 0.0}}, - 81: {176: {"mass": 176.000624, "composition": 0.0}, - 177: {"mass": 176.996431, "composition": 0.0}, - 178: {"mass": 177.99485, "composition": 0.0}, - 179: {"mass": 178.991111, "composition": 0.0}, - 180: {"mass": 179.990057, "composition": 0.0}, - 181: {"mass": 180.98626, "composition": 0.0}, - 182: {"mass": 181.985713, "composition": 0.0}, - 183: {"mass": 182.982193, "composition": 0.0}, - 184: {"mass": 183.981886, "composition": 0.0}, - 185: {"mass": 184.978789, "composition": 0.0}, - 186: {"mass": 185.978651, "composition": 0.0}, - 187: {"mass": 186.9759063, "composition": 0.0}, - 188: {"mass": 187.976021, "composition": 0.0}, - 189: {"mass": 188.973588, "composition": 0.0}, - 190: {"mass": 189.973828, "composition": 0.0}, - 191: {"mass": 190.9717842, "composition": 0.0}, - 192: {"mass": 191.972225, "composition": 0.0}, - 193: {"mass": 192.970502, "composition": 0.0}, - 194: {"mass": 193.971081, "composition": 0.0}, - 195: {"mass": 194.969774, "composition": 0.0}, - 196: {"mass": 195.970481, "composition": 0.0}, - 197: {"mass": 196.969576, "composition": 0.0}, - 198: {"mass": 197.970483, "composition": 0.0}, - 199: {"mass": 198.969877, "composition": 0.0}, - 200: {"mass": 199.9709633, "composition": 0.0}, - 201: {"mass": 200.970822, "composition": 0.0}, - 202: {"mass": 201.972102, "composition": 0.0}, - 203: {"mass": 202.9723446, "composition": 0.2952}, - 204: {"mass": 203.9738639, "composition": 0.0}, - 205: {"mass": 204.9744278, "composition": 0.7048}, - 206: {"mass": 205.9761106, "composition": 0.0}, - 207: {"mass": 206.9774197, "composition": 0.0}, - 208: {"mass": 207.982019, "composition": 0.0}, - 209: {"mass": 208.9853594, "composition": 0.0}, - 210: {"mass": 209.990074, "composition": 0.0}, - 211: {"mass": 210.993475, "composition": 0.0}, - 212: {"mass": 211.99834, "composition": 0.0}, - 213: {"mass": 213.001915, "composition": 0.0}, - 214: {"mass": 214.00694, "composition": 0.0}, - 215: {"mass": 215.01064, "composition": 0.0}, - 216: {"mass": 216.0158, "composition": 0.0}, - 217: {"mass": 217.01966, "composition": 0.0}, - 218: {"mass": 218.02479, "composition": 0.0}}, - 82: {178: {"mass": 178.003831, "composition": 0.0}, - 179: {"mass": 179.002201, "composition": 0.0}, - 180: {"mass": 179.997928, "composition": 0.0}, - 181: {"mass": 180.996653, "composition": 0.0}, - 182: {"mass": 181.992672, "composition": 0.0}, - 183: {"mass": 182.991872, "composition": 0.0}, - 184: {"mass": 183.988136, "composition": 0.0}, - 185: {"mass": 184.98761, "composition": 0.0}, - 186: {"mass": 185.984238, "composition": 0.0}, - 187: {"mass": 186.9839109, "composition": 0.0}, - 188: {"mass": 187.980875, "composition": 0.0}, - 189: {"mass": 188.980807, "composition": 0.0}, - 190: {"mass": 189.978082, "composition": 0.0}, - 191: {"mass": 190.978276, "composition": 0.0}, - 192: {"mass": 191.975775, "composition": 0.0}, - 193: {"mass": 192.976173, "composition": 0.0}, - 194: {"mass": 193.974012, "composition": 0.0}, - 195: {"mass": 194.974543, "composition": 0.0}, - 196: {"mass": 195.972774, "composition": 0.0}, - 197: {"mass": 196.9734312, "composition": 0.0}, - 198: {"mass": 197.972034, "composition": 0.0}, - 199: {"mass": 198.972913, "composition": 0.0}, - 200: {"mass": 199.971819, "composition": 0.0}, - 201: {"mass": 200.972883, "composition": 0.0}, - 202: {"mass": 201.972152, "composition": 0.0}, - 203: {"mass": 202.9733911, "composition": 0.0}, - 204: {"mass": 203.973044, "composition": 0.014}, - 205: {"mass": 204.9744822, "composition": 0.0}, - 206: {"mass": 205.9744657, "composition": 0.241}, - 207: {"mass": 206.9758973, "composition": 0.221}, - 208: {"mass": 207.9766525, "composition": 0.524}, - 209: {"mass": 208.9810905, "composition": 0.0}, - 210: {"mass": 209.9841889, "composition": 0.0}, - 211: {"mass": 210.9887371, "composition": 0.0}, - 212: {"mass": 211.9918977, "composition": 0.0}, - 213: {"mass": 212.9965629, "composition": 0.0}, - 214: {"mass": 213.9998059, "composition": 0.0}, - 215: {"mass": 215.00474, "composition": 0.0}, - 216: {"mass": 216.00803, "composition": 0.0}, - 217: {"mass": 217.01314, "composition": 0.0}, - 218: {"mass": 218.01659, "composition": 0.0}, - 219: {"mass": 219.02177, "composition": 0.0}, - 220: {"mass": 220.02541, "composition": 0.0}}, - 83: {184: {"mass": 184.001275, "composition": 0.0}, - 185: {"mass": 184.9976, "composition": 0.0}, - 186: {"mass": 185.996644, "composition": 0.0}, - 187: {"mass": 186.993147, "composition": 0.0}, - 188: {"mass": 187.992287, "composition": 0.0}, - 189: {"mass": 188.989195, "composition": 0.0}, - 190: {"mass": 189.988622, "composition": 0.0}, - 191: {"mass": 190.9857866, "composition": 0.0}, - 192: {"mass": 191.985469, "composition": 0.0}, - 193: {"mass": 192.98296, "composition": 0.0}, - 194: {"mass": 193.982785, "composition": 0.0}, - 195: {"mass": 194.9806488, "composition": 0.0}, - 196: {"mass": 195.980667, "composition": 0.0}, - 197: {"mass": 196.9788651, "composition": 0.0}, - 198: {"mass": 197.979206, "composition": 0.0}, - 199: {"mass": 198.977673, "composition": 0.0}, - 200: {"mass": 199.978131, "composition": 0.0}, - 201: {"mass": 200.97701, "composition": 0.0}, - 202: {"mass": 201.977734, "composition": 0.0}, - 203: {"mass": 202.976893, "composition": 0.0}, - 204: {"mass": 203.9778361, "composition": 0.0}, - 205: {"mass": 204.9773867, "composition": 0.0}, - 206: {"mass": 205.9784993, "composition": 0.0}, - 207: {"mass": 206.978471, "composition": 0.0}, - 208: {"mass": 207.9797425, "composition": 0.0}, - 209: {"mass": 208.9803991, "composition": 1.0}, - 210: {"mass": 209.9841207, "composition": 0.0}, - 211: {"mass": 210.9872697, "composition": 0.0}, - 212: {"mass": 211.991286, "composition": 0.0}, - 213: {"mass": 212.9943851, "composition": 0.0}, - 214: {"mass": 213.998712, "composition": 0.0}, - 215: {"mass": 215.00177, "composition": 0.0}, - 216: {"mass": 216.006306, "composition": 0.0}, - 217: {"mass": 217.009372, "composition": 0.0}, - 218: {"mass": 218.014188, "composition": 0.0}, - 219: {"mass": 219.01748, "composition": 0.0}, - 220: {"mass": 220.02235, "composition": 0.0}, - 221: {"mass": 221.02587, "composition": 0.0}, - 222: {"mass": 222.03078, "composition": 0.0}, - 223: {"mass": 223.0345, "composition": 0.0}, - 224: {"mass": 224.03947, "composition": 0.0}}, - 84: {186: {"mass": 186.004393, "composition": 0.0}, - 187: {"mass": 187.003041, "composition": 0.0}, - 188: {"mass": 187.999416, "composition": 0.0}, - 189: {"mass": 188.998473, "composition": 0.0}, - 190: {"mass": 189.995101, "composition": 0.0}, - 191: {"mass": 190.9945585, "composition": 0.0}, - 192: {"mass": 191.991336, "composition": 0.0}, - 193: {"mass": 192.991026, "composition": 0.0}, - 194: {"mass": 193.988186, "composition": 0.0}, - 195: {"mass": 194.988126, "composition": 0.0}, - 196: {"mass": 195.985526, "composition": 0.0}, - 197: {"mass": 196.98566, "composition": 0.0}, - 198: {"mass": 197.983389, "composition": 0.0}, - 199: {"mass": 198.983667, "composition": 0.0}, - 200: {"mass": 199.981799, "composition": 0.0}, - 201: {"mass": 200.9822598, "composition": 0.0}, - 202: {"mass": 201.980758, "composition": 0.0}, - 203: {"mass": 202.9814161, "composition": 0.0}, - 204: {"mass": 203.98031, "composition": 0.0}, - 205: {"mass": 204.981203, "composition": 0.0}, - 206: {"mass": 205.980474, "composition": 0.0}, - 207: {"mass": 206.9815938, "composition": 0.0}, - 208: {"mass": 207.9812461, "composition": 0.0}, - 209: {"mass": 208.9824308, "composition": 0.0}, - 210: {"mass": 209.9828741, "composition": 0.0}, - 211: {"mass": 210.9866536, "composition": 0.0}, - 212: {"mass": 211.9888684, "composition": 0.0}, - 213: {"mass": 212.9928576, "composition": 0.0}, - 214: {"mass": 213.9952017, "composition": 0.0}, - 215: {"mass": 214.9994201, "composition": 0.0}, - 216: {"mass": 216.0019152, "composition": 0.0}, - 217: {"mass": 217.0063182, "composition": 0.0}, - 218: {"mass": 218.0089735, "composition": 0.0}, - 219: {"mass": 219.013614, "composition": 0.0}, - 220: {"mass": 220.016386, "composition": 0.0}, - 221: {"mass": 221.021228, "composition": 0.0}, - 222: {"mass": 222.02414, "composition": 0.0}, - 223: {"mass": 223.02907, "composition": 0.0}, - 224: {"mass": 224.03211, "composition": 0.0}, - 225: {"mass": 225.03707, "composition": 0.0}, - 226: {"mass": 226.04031, "composition": 0.0}, - 227: {"mass": 227.04539, "composition": 0.0}}, - 85: {191: {"mass": 191.004148, "composition": 0.0}, - 192: {"mass": 192.003152, "composition": 0.0}, - 193: {"mass": 192.999927, "composition": 0.0}, - 194: {"mass": 193.999236, "composition": 0.0}, - 195: {"mass": 194.9962685, "composition": 0.0}, - 196: {"mass": 195.9958, "composition": 0.0}, - 197: {"mass": 196.993189, "composition": 0.0}, - 198: {"mass": 197.992784, "composition": 0.0}, - 199: {"mass": 198.9905277, "composition": 0.0}, - 200: {"mass": 199.990351, "composition": 0.0}, - 201: {"mass": 200.9884171, "composition": 0.0}, - 202: {"mass": 201.98863, "composition": 0.0}, - 203: {"mass": 202.986943, "composition": 0.0}, - 204: {"mass": 203.987251, "composition": 0.0}, - 205: {"mass": 204.986076, "composition": 0.0}, - 206: {"mass": 205.986657, "composition": 0.0}, - 207: {"mass": 206.9858, "composition": 0.0}, - 208: {"mass": 207.9866133, "composition": 0.0}, - 209: {"mass": 208.9861702, "composition": 0.0}, - 210: {"mass": 209.9871479, "composition": 0.0}, - 211: {"mass": 210.9874966, "composition": 0.0}, - 212: {"mass": 211.9907377, "composition": 0.0}, - 213: {"mass": 212.992937, "composition": 0.0}, - 214: {"mass": 213.9963721, "composition": 0.0}, - 215: {"mass": 214.9986528, "composition": 0.0}, - 216: {"mass": 216.0024236, "composition": 0.0}, - 217: {"mass": 217.0047192, "composition": 0.0}, - 218: {"mass": 218.008695, "composition": 0.0}, - 219: {"mass": 219.0111618, "composition": 0.0}, - 220: {"mass": 220.015433, "composition": 0.0}, - 221: {"mass": 221.018017, "composition": 0.0}, - 222: {"mass": 222.022494, "composition": 0.0}, - 223: {"mass": 223.025151, "composition": 0.0}, - 224: {"mass": 224.029749, "composition": 0.0}, - 225: {"mass": 225.03263, "composition": 0.0}, - 226: {"mass": 226.03716, "composition": 0.0}, - 227: {"mass": 227.04024, "composition": 0.0}, - 228: {"mass": 228.04475, "composition": 0.0}, - 229: {"mass": 229.04812, "composition": 0.0}}, - 86: {193: {"mass": 193.009708, "composition": 0.0}, - 194: {"mass": 194.006144, "composition": 0.0}, - 195: {"mass": 195.005422, "composition": 0.0}, - 196: {"mass": 196.002116, "composition": 0.0}, - 197: {"mass": 197.001585, "composition": 0.0}, - 198: {"mass": 197.998679, "composition": 0.0}, - 199: {"mass": 198.99839, "composition": 0.0}, - 200: {"mass": 199.99569, "composition": 0.0}, - 201: {"mass": 200.995628, "composition": 0.0}, - 202: {"mass": 201.993264, "composition": 0.0}, - 203: {"mass": 202.993388, "composition": 0.0}, - 204: {"mass": 203.99143, "composition": 0.0}, - 205: {"mass": 204.991719, "composition": 0.0}, - 206: {"mass": 205.990214, "composition": 0.0}, - 207: {"mass": 206.9907303, "composition": 0.0}, - 208: {"mass": 207.989635, "composition": 0.0}, - 209: {"mass": 208.990415, "composition": 0.0}, - 210: {"mass": 209.9896891, "composition": 0.0}, - 211: {"mass": 210.9906011, "composition": 0.0}, - 212: {"mass": 211.9907039, "composition": 0.0}, - 213: {"mass": 212.9938831, "composition": 0.0}, - 214: {"mass": 213.995363, "composition": 0.0}, - 215: {"mass": 214.9987459, "composition": 0.0}, - 216: {"mass": 216.0002719, "composition": 0.0}, - 217: {"mass": 217.003928, "composition": 0.0}, - 218: {"mass": 218.0056016, "composition": 0.0}, - 219: {"mass": 219.0094804, "composition": 0.0}, - 220: {"mass": 220.0113941, "composition": 0.0}, - 221: {"mass": 221.0155371, "composition": 0.0}, - 222: {"mass": 222.0175782, "composition": 0.0}, - 223: {"mass": 223.0218893, "composition": 0.0}, - 224: {"mass": 224.024096, "composition": 0.0}, - 225: {"mass": 225.028486, "composition": 0.0}, - 226: {"mass": 226.030861, "composition": 0.0}, - 227: {"mass": 227.035304, "composition": 0.0}, - 228: {"mass": 228.037835, "composition": 0.0}, - 229: {"mass": 229.042257, "composition": 0.0}, - 230: {"mass": 230.04514, "composition": 0.0}, - 231: {"mass": 231.04987, "composition": 0.0}}, - 87: {199: {"mass": 199.007259, "composition": 0.0}, - 200: {"mass": 200.006586, "composition": 0.0}, - 201: {"mass": 201.003867, "composition": 0.0}, - 202: {"mass": 202.00332, "composition": 0.0}, - 203: {"mass": 203.0009407, "composition": 0.0}, - 204: {"mass": 204.000652, "composition": 0.0}, - 205: {"mass": 204.9985939, "composition": 0.0}, - 206: {"mass": 205.998666, "composition": 0.0}, - 207: {"mass": 206.996946, "composition": 0.0}, - 208: {"mass": 207.997138, "composition": 0.0}, - 209: {"mass": 208.995955, "composition": 0.0}, - 210: {"mass": 209.996422, "composition": 0.0}, - 211: {"mass": 210.995556, "composition": 0.0}, - 212: {"mass": 211.9962257, "composition": 0.0}, - 213: {"mass": 212.996186, "composition": 0.0}, - 214: {"mass": 213.9989713, "composition": 0.0}, - 215: {"mass": 215.0003418, "composition": 0.0}, - 216: {"mass": 216.0031899, "composition": 0.0}, - 217: {"mass": 217.0046323, "composition": 0.0}, - 218: {"mass": 218.0075787, "composition": 0.0}, - 219: {"mass": 219.0092524, "composition": 0.0}, - 220: {"mass": 220.0123277, "composition": 0.0}, - 221: {"mass": 221.0142552, "composition": 0.0}, - 222: {"mass": 222.017552, "composition": 0.0}, - 223: {"mass": 223.019736, "composition": 0.0}, - 224: {"mass": 224.023398, "composition": 0.0}, - 225: {"mass": 225.025573, "composition": 0.0}, - 226: {"mass": 226.029566, "composition": 0.0}, - 227: {"mass": 227.031869, "composition": 0.0}, - 228: {"mass": 228.035823, "composition": 0.0}, - 229: {"mass": 229.038298, "composition": 0.0}, - 230: {"mass": 230.042416, "composition": 0.0}, - 231: {"mass": 231.045158, "composition": 0.0}, - 232: {"mass": 232.04937, "composition": 0.0}, - 233: {"mass": 233.05264, "composition": 0.0}}, - 88: {201: {"mass": 201.01271, "composition": 0.0}, - 202: {"mass": 202.00976, "composition": 0.0}, - 203: {"mass": 203.009304, "composition": 0.0}, - 204: {"mass": 204.006492, "composition": 0.0}, - 205: {"mass": 205.006268, "composition": 0.0}, - 206: {"mass": 206.003828, "composition": 0.0}, - 207: {"mass": 207.003799, "composition": 0.0}, - 208: {"mass": 208.001841, "composition": 0.0}, - 209: {"mass": 209.00199, "composition": 0.0}, - 210: {"mass": 210.000494, "composition": 0.0}, - 211: {"mass": 211.0008932, "composition": 0.0}, - 212: {"mass": 211.999787, "composition": 0.0}, - 213: {"mass": 213.000384, "composition": 0.0}, - 214: {"mass": 214.0000997, "composition": 0.0}, - 215: {"mass": 215.0027204, "composition": 0.0}, - 216: {"mass": 216.0035334, "composition": 0.0}, - 217: {"mass": 217.0063207, "composition": 0.0}, - 218: {"mass": 218.007141, "composition": 0.0}, - 219: {"mass": 219.0100855, "composition": 0.0}, - 220: {"mass": 220.0110259, "composition": 0.0}, - 221: {"mass": 221.0139177, "composition": 0.0}, - 222: {"mass": 222.0153748, "composition": 0.0}, - 223: {"mass": 223.0185023, "composition": 0.0}, - 224: {"mass": 224.020212, "composition": 0.0}, - 225: {"mass": 225.0236119, "composition": 0.0}, - 226: {"mass": 226.0254103, "composition": 0.0}, - 227: {"mass": 227.0291783, "composition": 0.0}, - 228: {"mass": 228.0310707, "composition": 0.0}, - 229: {"mass": 229.034942, "composition": 0.0}, - 230: {"mass": 230.037055, "composition": 0.0}, - 231: {"mass": 231.041027, "composition": 0.0}, - 232: {"mass": 232.0434753, "composition": 0.0}, - 233: {"mass": 233.047582, "composition": 0.0}, - 234: {"mass": 234.050342, "composition": 0.0}, - 235: {"mass": 235.05497, "composition": 0.0}}, - 89: {206: {"mass": 206.014452, "composition": 0.0}, - 207: {"mass": 207.011966, "composition": 0.0}, - 208: {"mass": 208.01155, "composition": 0.0}, - 209: {"mass": 209.009495, "composition": 0.0}, - 210: {"mass": 210.009436, "composition": 0.0}, - 211: {"mass": 211.007732, "composition": 0.0}, - 212: {"mass": 212.007813, "composition": 0.0}, - 213: {"mass": 213.006609, "composition": 0.0}, - 214: {"mass": 214.006918, "composition": 0.0}, - 215: {"mass": 215.006475, "composition": 0.0}, - 216: {"mass": 216.008743, "composition": 0.0}, - 217: {"mass": 217.009344, "composition": 0.0}, - 218: {"mass": 218.011642, "composition": 0.0}, - 219: {"mass": 219.012421, "composition": 0.0}, - 220: {"mass": 220.0147549, "composition": 0.0}, - 221: {"mass": 221.015592, "composition": 0.0}, - 222: {"mass": 222.0178442, "composition": 0.0}, - 223: {"mass": 223.0191377, "composition": 0.0}, - 224: {"mass": 224.0217232, "composition": 0.0}, - 225: {"mass": 225.02323, "composition": 0.0}, - 226: {"mass": 226.0260984, "composition": 0.0}, - 227: {"mass": 227.0277523, "composition": 0.0}, - 228: {"mass": 228.0310215, "composition": 0.0}, - 229: {"mass": 229.032956, "composition": 0.0}, - 230: {"mass": 230.036327, "composition": 0.0}, - 231: {"mass": 231.038393, "composition": 0.0}, - 232: {"mass": 232.042034, "composition": 0.0}, - 233: {"mass": 233.044346, "composition": 0.0}, - 234: {"mass": 234.048139, "composition": 0.0}, - 235: {"mass": 235.05084, "composition": 0.0}, - 236: {"mass": 236.054988, "composition": 0.0}, - 237: {"mass": 237.05827, "composition": 0.0}}, - 90: {208: {"mass": 208.0179, "composition": 0.0}, - 209: {"mass": 209.017753, "composition": 0.0}, - 210: {"mass": 210.015094, "composition": 0.0}, - 211: {"mass": 211.014929, "composition": 0.0}, - 212: {"mass": 212.012988, "composition": 0.0}, - 213: {"mass": 213.013009, "composition": 0.0}, - 214: {"mass": 214.0115, "composition": 0.0}, - 215: {"mass": 215.0117248, "composition": 0.0}, - 216: {"mass": 216.011056, "composition": 0.0}, - 217: {"mass": 217.013117, "composition": 0.0}, - 218: {"mass": 218.013276, "composition": 0.0}, - 219: {"mass": 219.015537, "composition": 0.0}, - 220: {"mass": 220.015748, "composition": 0.0}, - 221: {"mass": 221.018184, "composition": 0.0}, - 222: {"mass": 222.018469, "composition": 0.0}, - 223: {"mass": 223.0208119, "composition": 0.0}, - 224: {"mass": 224.021464, "composition": 0.0}, - 225: {"mass": 225.0239514, "composition": 0.0}, - 226: {"mass": 226.0249034, "composition": 0.0}, - 227: {"mass": 227.0277042, "composition": 0.0}, - 228: {"mass": 228.0287413, "composition": 0.0}, - 229: {"mass": 229.0317627, "composition": 0.0}, - 230: {"mass": 230.0331341, "composition": 0.0}, - 231: {"mass": 231.0363046, "composition": 0.0}, - 232: {"mass": 232.0380558, "composition": 1.0}, - 233: {"mass": 233.0415823, "composition": 0.0}, - 234: {"mass": 234.0436014, "composition": 0.0}, - 235: {"mass": 235.047255, "composition": 0.0}, - 236: {"mass": 236.049657, "composition": 0.0}, - 237: {"mass": 237.053629, "composition": 0.0}, - 238: {"mass": 238.0565, "composition": 0.0}, - 239: {"mass": 239.06077, "composition": 0.0}}, - 91: {212: {"mass": 212.023203, "composition": 0.0}, - 213: {"mass": 213.021109, "composition": 0.0}, - 214: {"mass": 214.020918, "composition": 0.0}, - 215: {"mass": 215.019183, "composition": 0.0}, - 216: {"mass": 216.019109, "composition": 0.0}, - 217: {"mass": 217.018325, "composition": 0.0}, - 218: {"mass": 218.020059, "composition": 0.0}, - 219: {"mass": 219.019904, "composition": 0.0}, - 220: {"mass": 220.021705, "composition": 0.0}, - 221: {"mass": 221.021875, "composition": 0.0}, - 222: {"mass": 222.023784, "composition": 0.0}, - 223: {"mass": 223.023963, "composition": 0.0}, - 224: {"mass": 224.0256176, "composition": 0.0}, - 225: {"mass": 225.026131, "composition": 0.0}, - 226: {"mass": 226.027948, "composition": 0.0}, - 227: {"mass": 227.0288054, "composition": 0.0}, - 228: {"mass": 228.0310517, "composition": 0.0}, - 229: {"mass": 229.0320972, "composition": 0.0}, - 230: {"mass": 230.034541, "composition": 0.0}, - 231: {"mass": 231.0358842, "composition": 1.0}, - 232: {"mass": 232.0385917, "composition": 0.0}, - 233: {"mass": 233.0402472, "composition": 0.0}, - 234: {"mass": 234.0433072, "composition": 0.0}, - 235: {"mass": 235.045399, "composition": 0.0}, - 236: {"mass": 236.048668, "composition": 0.0}, - 237: {"mass": 237.051023, "composition": 0.0}, - 238: {"mass": 238.054637, "composition": 0.0}, - 239: {"mass": 239.05726, "composition": 0.0}, - 240: {"mass": 240.06098, "composition": 0.0}, - 241: {"mass": 241.06408, "composition": 0.0}}, - 92: {217: {"mass": 217.02466, "composition": 0.0}, - 218: {"mass": 218.023523, "composition": 0.0}, - 219: {"mass": 219.024999, "composition": 0.0}, - 220: {"mass": 220.02462, "composition": 0.0}, - 221: {"mass": 221.02628, "composition": 0.0}, - 222: {"mass": 222.026, "composition": 0.0}, - 223: {"mass": 223.027739, "composition": 0.0}, - 224: {"mass": 224.027605, "composition": 0.0}, - 225: {"mass": 225.029391, "composition": 0.0}, - 226: {"mass": 226.029339, "composition": 0.0}, - 227: {"mass": 227.031157, "composition": 0.0}, - 228: {"mass": 228.031371, "composition": 0.0}, - 229: {"mass": 229.0335063, "composition": 0.0}, - 230: {"mass": 230.0339401, "composition": 0.0}, - 231: {"mass": 231.0362939, "composition": 0.0}, - 232: {"mass": 232.0371563, "composition": 0.0}, - 233: {"mass": 233.0396355, "composition": 0.0}, - 234: {"mass": 234.0409523, "composition": 5.4e-05}, - 235: {"mass": 235.0439301, "composition": 0.007204}, - 236: {"mass": 236.0455682, "composition": 0.0}, - 237: {"mass": 237.0487304, "composition": 0.0}, - 238: {"mass": 238.0507884, "composition": 0.992742}, - 239: {"mass": 239.0542935, "composition": 0.0}, - 240: {"mass": 240.0565934, "composition": 0.0}, - 241: {"mass": 241.06033, "composition": 0.0}, - 242: {"mass": 242.06293, "composition": 0.0}, - 243: {"mass": 243.06699, "composition": 0.0}}, - 93: {219: {"mass": 219.03143, "composition": 0.0}, - 220: {"mass": 220.03254, "composition": 0.0}, - 221: {"mass": 221.03204, "composition": 0.0}, - 222: {"mass": 222.0333, "composition": 0.0}, - 223: {"mass": 223.03285, "composition": 0.0}, - 224: {"mass": 224.03422, "composition": 0.0}, - 225: {"mass": 225.033911, "composition": 0.0}, - 226: {"mass": 226.035188, "composition": 0.0}, - 227: {"mass": 227.034957, "composition": 0.0}, - 228: {"mass": 228.036067, "composition": 0.0}, - 229: {"mass": 229.036264, "composition": 0.0}, - 230: {"mass": 230.037828, "composition": 0.0}, - 231: {"mass": 231.038245, "composition": 0.0}, - 232: {"mass": 232.04011, "composition": 0.0}, - 233: {"mass": 233.040741, "composition": 0.0}, - 234: {"mass": 234.0428953, "composition": 0.0}, - 235: {"mass": 235.0440635, "composition": 0.0}, - 236: {"mass": 236.04657, "composition": 0.0}, - 237: {"mass": 237.0481736, "composition": 0.0}, - 238: {"mass": 238.0509466, "composition": 0.0}, - 239: {"mass": 239.0529392, "composition": 0.0}, - 240: {"mass": 240.056165, "composition": 0.0}, - 241: {"mass": 241.058253, "composition": 0.0}, - 242: {"mass": 242.06164, "composition": 0.0}, - 243: {"mass": 243.06428, "composition": 0.0}, - 244: {"mass": 244.06785, "composition": 0.0}, - 245: {"mass": 245.0708, "composition": 0.0}}, - 94: {228: {"mass": 228.038732, "composition": 0.0}, - 229: {"mass": 229.040144, "composition": 0.0}, - 230: {"mass": 230.03965, "composition": 0.0}, - 231: {"mass": 231.041102, "composition": 0.0}, - 232: {"mass": 232.041185, "composition": 0.0}, - 233: {"mass": 233.042998, "composition": 0.0}, - 234: {"mass": 234.0433174, "composition": 0.0}, - 235: {"mass": 235.045286, "composition": 0.0}, - 236: {"mass": 236.0460581, "composition": 0.0}, - 237: {"mass": 237.0484098, "composition": 0.0}, - 238: {"mass": 238.0495601, "composition": 0.0}, - 239: {"mass": 239.0521636, "composition": 0.0}, - 240: {"mass": 240.0538138, "composition": 0.0}, - 241: {"mass": 241.0568517, "composition": 0.0}, - 242: {"mass": 242.0587428, "composition": 0.0}, - 243: {"mass": 243.0620036, "composition": 0.0}, - 244: {"mass": 244.0642053, "composition": 0.0}, - 245: {"mass": 245.067826, "composition": 0.0}, - 246: {"mass": 246.070205, "composition": 0.0}, - 247: {"mass": 247.07419, "composition": 0.0}}, - 95: {230: {"mass": 230.04609, "composition": 0.0}, - 231: {"mass": 231.04556, "composition": 0.0}, - 232: {"mass": 232.04645, "composition": 0.0}, - 233: {"mass": 233.04644, "composition": 0.0}, - 234: {"mass": 234.04773, "composition": 0.0}, - 235: {"mass": 235.047908, "composition": 0.0}, - 236: {"mass": 236.04943, "composition": 0.0}, - 237: {"mass": 237.049996, "composition": 0.0}, - 238: {"mass": 238.051985, "composition": 0.0}, - 239: {"mass": 239.0530247, "composition": 0.0}, - 240: {"mass": 240.0553, "composition": 0.0}, - 241: {"mass": 241.0568293, "composition": 0.0}, - 242: {"mass": 242.0595494, "composition": 0.0}, - 243: {"mass": 243.0613813, "composition": 0.0}, - 244: {"mass": 244.0642851, "composition": 0.0}, - 245: {"mass": 245.0664548, "composition": 0.0}, - 246: {"mass": 246.069775, "composition": 0.0}, - 247: {"mass": 247.07209, "composition": 0.0}, - 248: {"mass": 248.07575, "composition": 0.0}, - 249: {"mass": 249.07848, "composition": 0.0}}, - 96: {232: {"mass": 232.04982, "composition": 0.0}, - 233: {"mass": 233.05077, "composition": 0.0}, - 234: {"mass": 234.05016, "composition": 0.0}, - 235: {"mass": 235.05154, "composition": 0.0}, - 236: {"mass": 236.051374, "composition": 0.0}, - 237: {"mass": 237.052869, "composition": 0.0}, - 238: {"mass": 238.053081, "composition": 0.0}, - 239: {"mass": 239.05491, "composition": 0.0}, - 240: {"mass": 240.0555297, "composition": 0.0}, - 241: {"mass": 241.0576532, "composition": 0.0}, - 242: {"mass": 242.058836, "composition": 0.0}, - 243: {"mass": 243.0613893, "composition": 0.0}, - 244: {"mass": 244.0627528, "composition": 0.0}, - 245: {"mass": 245.0654915, "composition": 0.0}, - 246: {"mass": 246.0672238, "composition": 0.0}, - 247: {"mass": 247.0703541, "composition": 0.0}, - 248: {"mass": 248.0723499, "composition": 0.0}, - 249: {"mass": 249.0759548, "composition": 0.0}, - 250: {"mass": 250.078358, "composition": 0.0}, - 251: {"mass": 251.082286, "composition": 0.0}, - 252: {"mass": 252.08487, "composition": 0.0}}, - 97: {234: {"mass": 234.05727, "composition": 0.0}, - 235: {"mass": 235.05658, "composition": 0.0}, - 236: {"mass": 236.05748, "composition": 0.0}, - 237: {"mass": 237.0571, "composition": 0.0}, - 238: {"mass": 238.0582, "composition": 0.0}, - 239: {"mass": 239.05824, "composition": 0.0}, - 240: {"mass": 240.05976, "composition": 0.0}, - 241: {"mass": 241.06016, "composition": 0.0}, - 242: {"mass": 242.06198, "composition": 0.0}, - 243: {"mass": 243.0630078, "composition": 0.0}, - 244: {"mass": 244.065181, "composition": 0.0}, - 245: {"mass": 245.0663618, "composition": 0.0}, - 246: {"mass": 246.068673, "composition": 0.0}, - 247: {"mass": 247.0703073, "composition": 0.0}, - 248: {"mass": 248.073088, "composition": 0.0}, - 249: {"mass": 249.0749877, "composition": 0.0}, - 250: {"mass": 250.0783167, "composition": 0.0}, - 251: {"mass": 251.080762, "composition": 0.0}, - 252: {"mass": 252.08431, "composition": 0.0}, - 253: {"mass": 253.08688, "composition": 0.0}, - 254: {"mass": 254.0906, "composition": 0.0}}, - 98: {237: {"mass": 237.062198, "composition": 0.0}, - 238: {"mass": 238.06149, "composition": 0.0}, - 239: {"mass": 239.06253, "composition": 0.0}, - 240: {"mass": 240.062256, "composition": 0.0}, - 241: {"mass": 241.06369, "composition": 0.0}, - 242: {"mass": 242.063754, "composition": 0.0}, - 243: {"mass": 243.06548, "composition": 0.0}, - 244: {"mass": 244.0660008, "composition": 0.0}, - 245: {"mass": 245.0680487, "composition": 0.0}, - 246: {"mass": 246.0688055, "composition": 0.0}, - 247: {"mass": 247.070965, "composition": 0.0}, - 248: {"mass": 248.0721851, "composition": 0.0}, - 249: {"mass": 249.0748539, "composition": 0.0}, - 250: {"mass": 250.0764062, "composition": 0.0}, - 251: {"mass": 251.0795886, "composition": 0.0}, - 252: {"mass": 252.0816272, "composition": 0.0}, - 253: {"mass": 253.0851345, "composition": 0.0}, - 254: {"mass": 254.087324, "composition": 0.0}, - 255: {"mass": 255.09105, "composition": 0.0}, - 256: {"mass": 256.09344, "composition": 0.0}}, - 99: {239: {"mass": 239.06823, "composition": 0.0}, - 240: {"mass": 240.06892, "composition": 0.0}, - 241: {"mass": 241.06856, "composition": 0.0}, - 242: {"mass": 242.06957, "composition": 0.0}, - 243: {"mass": 243.06951, "composition": 0.0}, - 244: {"mass": 244.07088, "composition": 0.0}, - 245: {"mass": 245.07125, "composition": 0.0}, - 246: {"mass": 246.0729, "composition": 0.0}, - 247: {"mass": 247.073622, "composition": 0.0}, - 248: {"mass": 248.075471, "composition": 0.0}, - 249: {"mass": 249.076411, "composition": 0.0}, - 250: {"mass": 250.07861, "composition": 0.0}, - 251: {"mass": 251.0799936, "composition": 0.0}, - 252: {"mass": 252.08298, "composition": 0.0}, - 253: {"mass": 253.0848257, "composition": 0.0}, - 254: {"mass": 254.0880222, "composition": 0.0}, - 255: {"mass": 255.090275, "composition": 0.0}, - 256: {"mass": 256.0936, "composition": 0.0}, - 257: {"mass": 257.09598, "composition": 0.0}, - 258: {"mass": 258.09952, "composition": 0.0}}, - 100: {241: {"mass": 241.07421, "composition": 0.0}, - 242: {"mass": 242.07343, "composition": 0.0}, - 243: {"mass": 243.07446, "composition": 0.0}, - 244: {"mass": 244.07404, "composition": 0.0}, - 245: {"mass": 245.07535, "composition": 0.0}, - 246: {"mass": 246.07535, "composition": 0.0}, - 247: {"mass": 247.07694, "composition": 0.0}, - 248: {"mass": 248.0771865, "composition": 0.0}, - 249: {"mass": 249.0789275, "composition": 0.0}, - 250: {"mass": 250.079521, "composition": 0.0}, - 251: {"mass": 251.08154, "composition": 0.0}, - 252: {"mass": 252.0824671, "composition": 0.0}, - 253: {"mass": 253.0851846, "composition": 0.0}, - 254: {"mass": 254.0868544, "composition": 0.0}, - 255: {"mass": 255.089964, "composition": 0.0}, - 256: {"mass": 256.0917745, "composition": 0.0}, - 257: {"mass": 257.0951061, "composition": 0.0}, - 258: {"mass": 258.09708, "composition": 0.0}, - 259: {"mass": 259.1006, "composition": 0.0}, - 260: {"mass": 260.10281, "composition": 0.0}}, - 101: {245: {"mass": 245.08081, "composition": 0.0}, - 246: {"mass": 246.08171, "composition": 0.0}, - 247: {"mass": 247.08152, "composition": 0.0}, - 248: {"mass": 248.08282, "composition": 0.0}, - 249: {"mass": 249.08291, "composition": 0.0}, - 250: {"mass": 250.08441, "composition": 0.0}, - 251: {"mass": 251.084774, "composition": 0.0}, - 252: {"mass": 252.08643, "composition": 0.0}, - 253: {"mass": 253.087144, "composition": 0.0}, - 254: {"mass": 254.08959, "composition": 0.0}, - 255: {"mass": 255.0910841, "composition": 0.0}, - 256: {"mass": 256.09389, "composition": 0.0}, - 257: {"mass": 257.0955424, "composition": 0.0}, - 258: {"mass": 258.0984315, "composition": 0.0}, - 259: {"mass": 259.10051, "composition": 0.0}, - 260: {"mass": 260.10365, "composition": 0.0}, - 261: {"mass": 261.10583, "composition": 0.0}, - 262: {"mass": 262.1091, "composition": 0.0}}, - 102: {248: {"mass": 248.08655, "composition": 0.0}, - 249: {"mass": 249.0878, "composition": 0.0}, - 250: {"mass": 250.08756, "composition": 0.0}, - 251: {"mass": 251.08894, "composition": 0.0}, - 252: {"mass": 252.088967, "composition": 0.0}, - 253: {"mass": 253.0905641, "composition": 0.0}, - 254: {"mass": 254.090956, "composition": 0.0}, - 255: {"mass": 255.093191, "composition": 0.0}, - 256: {"mass": 256.0942829, "composition": 0.0}, - 257: {"mass": 257.0968878, "composition": 0.0}, - 258: {"mass": 258.09821, "composition": 0.0}, - 259: {"mass": 259.10103, "composition": 0.0}, - 260: {"mass": 260.10264, "composition": 0.0}, - 261: {"mass": 261.1057, "composition": 0.0}, - 262: {"mass": 262.10746, "composition": 0.0}, - 263: {"mass": 263.11071, "composition": 0.0}, - 264: {"mass": 264.11273, "composition": 0.0}}, - 103: {251: {"mass": 251.09418, "composition": 0.0}, - 252: {"mass": 252.09526, "composition": 0.0}, - 253: {"mass": 253.09509, "composition": 0.0}, - 254: {"mass": 254.09648, "composition": 0.0}, - 255: {"mass": 255.096562, "composition": 0.0}, - 256: {"mass": 256.098494, "composition": 0.0}, - 257: {"mass": 257.099418, "composition": 0.0}, - 258: {"mass": 258.10176, "composition": 0.0}, - 259: {"mass": 259.102902, "composition": 0.0}, - 260: {"mass": 260.1055, "composition": 0.0}, - 261: {"mass": 261.10688, "composition": 0.0}, - 262: {"mass": 262.10961, "composition": 0.0}, - 263: {"mass": 263.11136, "composition": 0.0}, - 264: {"mass": 264.1142, "composition": 0.0}, - 265: {"mass": 265.11619, "composition": 0.0}, - 266: {"mass": 266.11983, "composition": 0.0}}, - 104: {253: {"mass": 253.10044, "composition": 0.0}, - 254: {"mass": 254.10005, "composition": 0.0}, - 255: {"mass": 255.10127, "composition": 0.0}, - 256: {"mass": 256.101152, "composition": 0.0}, - 257: {"mass": 257.102918, "composition": 0.0}, - 258: {"mass": 258.103428, "composition": 0.0}, - 259: {"mass": 259.105596, "composition": 0.0}, - 260: {"mass": 260.10644, "composition": 0.0}, - 261: {"mass": 261.108773, "composition": 0.0}, - 262: {"mass": 262.10992, "composition": 0.0}, - 263: {"mass": 263.11249, "composition": 0.0}, - 264: {"mass": 264.11388, "composition": 0.0}, - 265: {"mass": 265.11668, "composition": 0.0}, - 266: {"mass": 266.11817, "composition": 0.0}, - 267: {"mass": 267.12179, "composition": 0.0}, - 268: {"mass": 268.12397, "composition": 0.0}}, - 105: {255: {"mass": 255.10707, "composition": 0.0}, - 256: {"mass": 256.10789, "composition": 0.0}, - 257: {"mass": 257.10758, "composition": 0.0}, - 258: {"mass": 258.10928, "composition": 0.0}, - 259: {"mass": 259.109492, "composition": 0.0}, - 260: {"mass": 260.1113, "composition": 0.0}, - 261: {"mass": 261.11192, "composition": 0.0}, - 262: {"mass": 262.11407, "composition": 0.0}, - 263: {"mass": 263.11499, "composition": 0.0}, - 264: {"mass": 264.11741, "composition": 0.0}, - 265: {"mass": 265.11861, "composition": 0.0}, - 266: {"mass": 266.12103, "composition": 0.0}, - 267: {"mass": 267.12247, "composition": 0.0}, - 268: {"mass": 268.12567, "composition": 0.0}, - 269: {"mass": 269.12791, "composition": 0.0}, - 270: {"mass": 270.13136, "composition": 0.0}}, - 106: {258: {"mass": 258.11298, "composition": 0.0}, - 259: {"mass": 259.1144, "composition": 0.0}, - 260: {"mass": 260.114384, "composition": 0.0}, - 261: {"mass": 261.115949, "composition": 0.0}, - 262: {"mass": 262.116337, "composition": 0.0}, - 263: {"mass": 263.11829, "composition": 0.0}, - 264: {"mass": 264.11893, "composition": 0.0}, - 265: {"mass": 265.12109, "composition": 0.0}, - 266: {"mass": 266.12198, "composition": 0.0}, - 267: {"mass": 267.12436, "composition": 0.0}, - 268: {"mass": 268.12539, "composition": 0.0}, - 269: {"mass": 269.12863, "composition": 0.0}, - 270: {"mass": 270.13043, "composition": 0.0}, - 271: {"mass": 271.13393, "composition": 0.0}, - 272: {"mass": 272.13589, "composition": 0.0}, - 273: {"mass": 273.13958, "composition": 0.0}}, - 107: {260: {"mass": 260.12166, "composition": 0.0}, - 261: {"mass": 261.12145, "composition": 0.0}, - 262: {"mass": 262.12297, "composition": 0.0}, - 263: {"mass": 263.12292, "composition": 0.0}, - 264: {"mass": 264.12459, "composition": 0.0}, - 265: {"mass": 265.12491, "composition": 0.0}, - 266: {"mass": 266.12679, "composition": 0.0}, - 267: {"mass": 267.1275, "composition": 0.0}, - 268: {"mass": 268.12969, "composition": 0.0}, - 269: {"mass": 269.13042, "composition": 0.0}, - 270: {"mass": 270.13336, "composition": 0.0}, - 271: {"mass": 271.13526, "composition": 0.0}, - 272: {"mass": 272.13826, "composition": 0.0}, - 273: {"mass": 273.14024, "composition": 0.0}, - 274: {"mass": 274.14355, "composition": 0.0}, - 275: {"mass": 275.14567, "composition": 0.0}}, - 108: {263: {"mass": 263.12852, "composition": 0.0}, - 264: {"mass": 264.128357, "composition": 0.0}, - 265: {"mass": 265.129793, "composition": 0.0}, - 266: {"mass": 266.130046, "composition": 0.0}, - 267: {"mass": 267.13167, "composition": 0.0}, - 268: {"mass": 268.13186, "composition": 0.0}, - 269: {"mass": 269.13375, "composition": 0.0}, - 270: {"mass": 270.13429, "composition": 0.0}, - 271: {"mass": 271.13717, "composition": 0.0}, - 272: {"mass": 272.1385, "composition": 0.0}, - 273: {"mass": 273.14168, "composition": 0.0}, - 274: {"mass": 274.1433, "composition": 0.0}, - 275: {"mass": 275.14667, "composition": 0.0}, - 276: {"mass": 276.14846, "composition": 0.0}, - 277: {"mass": 277.1519, "composition": 0.0}}, - 109: {265: {"mass": 265.136, "composition": 0.0}, - 266: {"mass": 266.13737, "composition": 0.0}, - 267: {"mass": 267.13719, "composition": 0.0}, - 268: {"mass": 268.13865, "composition": 0.0}, - 269: {"mass": 269.13882, "composition": 0.0}, - 270: {"mass": 270.14033, "composition": 0.0}, - 271: {"mass": 271.14074, "composition": 0.0}, - 272: {"mass": 272.14341, "composition": 0.0}, - 273: {"mass": 273.1444, "composition": 0.0}, - 274: {"mass": 274.14724, "composition": 0.0}, - 275: {"mass": 275.14882, "composition": 0.0}, - 276: {"mass": 276.15159, "composition": 0.0}, - 277: {"mass": 277.15327, "composition": 0.0}, - 278: {"mass": 278.15631, "composition": 0.0}, - 279: {"mass": 279.15808, "composition": 0.0}}, - 110: {267: {"mass": 267.14377, "composition": 0.0}, - 268: {"mass": 268.14348, "composition": 0.0}, - 269: {"mass": 269.144752, "composition": 0.0}, - 270: {"mass": 270.144584, "composition": 0.0}, - 271: {"mass": 271.14595, "composition": 0.0}, - 272: {"mass": 272.14602, "composition": 0.0}, - 273: {"mass": 273.14856, "composition": 0.0}, - 274: {"mass": 274.14941, "composition": 0.0}, - 275: {"mass": 275.15203, "composition": 0.0}, - 276: {"mass": 276.15303, "composition": 0.0}, - 277: {"mass": 277.15591, "composition": 0.0}, - 278: {"mass": 278.15704, "composition": 0.0}, - 279: {"mass": 279.1601, "composition": 0.0}, - 280: {"mass": 280.16131, "composition": 0.0}, - 281: {"mass": 281.16451, "composition": 0.0}}, - 111: {272: {"mass": 272.15327, "composition": 0.0}, - 273: {"mass": 273.15313, "composition": 0.0}, - 274: {"mass": 274.15525, "composition": 0.0}, - 275: {"mass": 275.15594, "composition": 0.0}, - 276: {"mass": 276.15833, "composition": 0.0}, - 277: {"mass": 277.15907, "composition": 0.0}, - 278: {"mass": 278.16149, "composition": 0.0}, - 279: {"mass": 279.16272, "composition": 0.0}, - 280: {"mass": 280.16514, "composition": 0.0}, - 281: {"mass": 281.16636, "composition": 0.0}, - 282: {"mass": 282.16912, "composition": 0.0}, - 283: {"mass": 283.17054, "composition": 0.0}}, - 112: {276: {"mass": 276.16141, "composition": 0.0}, - 277: {"mass": 277.16364, "composition": 0.0}, - 278: {"mass": 278.16416, "composition": 0.0}, - 279: {"mass": 279.16654, "composition": 0.0}, - 280: {"mass": 280.16715, "composition": 0.0}, - 281: {"mass": 281.16975, "composition": 0.0}, - 282: {"mass": 282.1705, "composition": 0.0}, - 283: {"mass": 283.17327, "composition": 0.0}, - 284: {"mass": 284.17416, "composition": 0.0}, - 285: {"mass": 285.17712, "composition": 0.0}}, - 113: {278: {"mass": 278.17058, "composition": 0.0}, - 279: {"mass": 279.17095, "composition": 0.0}, - 280: {"mass": 280.17293, "composition": 0.0}, - 281: {"mass": 281.17348, "composition": 0.0}, - 282: {"mass": 282.17567, "composition": 0.0}, - 283: {"mass": 283.17657, "composition": 0.0}, - 284: {"mass": 284.17873, "composition": 0.0}, - 285: {"mass": 285.17973, "composition": 0.0}, - 286: {"mass": 286.18221, "composition": 0.0}, - 287: {"mass": 287.18339, "composition": 0.0}}, - 114: {285: {"mass": 285.18364, "composition": 0.0}, - 286: {"mass": 286.18423, "composition": 0.0}, - 287: {"mass": 287.18678, "composition": 0.0}, - 288: {"mass": 288.18757, "composition": 0.0}, - 289: {"mass": 289.19042, "composition": 0.0}}, - 115: {287: {"mass": 287.1907, "composition": 0.0}, - 288: {"mass": 288.19274, "composition": 0.0}, - 289: {"mass": 289.19363, "composition": 0.0}, - 290: {"mass": 290.19598, "composition": 0.0}, - 291: {"mass": 291.19707, "composition": 0.0}}, - 116: {289: {"mass": 289.19816, "composition": 0.0}, - 290: {"mass": 290.19864, "composition": 0.0}, - 291: {"mass": 291.20108, "composition": 0.0}, - 292: {"mass": 292.20174, "composition": 0.0}, - 293: {"mass": 293.20449, "composition": 0.0}}, - 117: {291: {"mass": 291.20553, "composition": 0.0}, - 292: {"mass": 292.20746, "composition": 0.0}, - 293: {"mass": 293.20824, "composition": 0.0}, - 294: {"mass": 294.21046, "composition": 0.0}}, - 118: {293: {"mass": 293.21356, "composition": 0.0}, - 294: {"mass": 294.21392, "composition": 0.0}, - 295: {"mass": 295.21624, "composition": 0.0}}} + 31: {"mass": 30.975363194, "composition": 0.}, + 32: {"mass": 31.97415154, "composition": 0.}, + 33: {"mass": 32.97797696, "composition": 0.}, + 34: {"mass": 33.978576, "composition": 0.}, + 35: {"mass": 34.984583, "composition": 0.}, + 36: {"mass": 35.986695, "composition": 0.}, + 37: {"mass": 36.992921, "composition": 0.}, + 38: {"mass": 37.995523, "composition": 0.}, + 39: {"mass": 39.002491, "composition": 0.}, + 40: {"mass": 40.00583, "composition": 0.}, + 41: {"mass": 41.01301, "composition": 0.}, + 42: {"mass": 42.01778, "composition": 0.}, + 43: {"mass": 43.0248, "composition": 0.}, + 44: {"mass": 44.03061, "composition": 0.}, + 45: {"mass": 45.03995, "composition": 0.}}, + 15: {24: {"mass": 24.03577, "composition": 0.}, + 25: {"mass": 25.02119, "composition": 0.}, + 26: {"mass": 26.01178, "composition": 0.}, + 27: {"mass": 26.999224, "composition": 0.}, + 28: {"mass": 27.9923266, "composition": 0.}, + 29: {"mass": 28.98180079, "composition": 0.}, + 30: {"mass": 29.97831375, "composition": 0.}, + 31: {"mass": 30.97376199842, "composition": 1.}, + 32: {"mass": 31.973907643, "composition": 0.}, + 33: {"mass": 32.9717257, "composition": 0.}, + 34: {"mass": 33.97364589, "composition": 0.}, + 35: {"mass": 34.9733141, "composition": 0.}, + 36: {"mass": 35.97826, "composition": 0.}, + 37: {"mass": 36.979607, "composition": 0.}, + 38: {"mass": 37.984252, "composition": 0.}, + 39: {"mass": 38.986227, "composition": 0.}, + 40: {"mass": 39.99133, "composition": 0.}, + 41: {"mass": 40.994654, "composition": 0.}, + 42: {"mass": 42.00108, "composition": 0.}, + 43: {"mass": 43.00502, "composition": 0.}, + 44: {"mass": 44.01121, "composition": 0.}, + 45: {"mass": 45.01645, "composition": 0.}, + 46: {"mass": 46.02446, "composition": 0.}, + 47: {"mass": 47.03139, "composition": 0.}}, + 16: {26: {"mass": 26.02907, "composition": 0.}, + 27: {"mass": 27.01828, "composition": 0.}, + 28: {"mass": 28.00437, "composition": 0.}, + 29: {"mass": 28.996611, "composition": 0.}, + 30: {"mass": 29.98490703, "composition": 0.}, + 31: {"mass": 30.97955701, "composition": 0.}, + 32: {"mass": 31.9720711744, "composition": 0.9499}, + 33: {"mass": 32.9714589098, "composition": 0.0075}, + 34: {"mass": 33.967867004, "composition": 0.0425}, + 35: {"mass": 34.96903231, "composition": 0.}, + 36: {"mass": 35.96708071, "composition": 0.0001}, + 37: {"mass": 36.97112551, "composition": 0.}, + 38: {"mass": 37.9711633, "composition": 0.}, + 39: {"mass": 38.975134, "composition": 0.}, + 40: {"mass": 39.9754826, "composition": 0.}, + 41: {"mass": 40.9795935, "composition": 0.}, + 42: {"mass": 41.9810651, "composition": 0.}, + 43: {"mass": 42.9869076, "composition": 0.}, + 44: {"mass": 43.9901188, "composition": 0.}, + 45: {"mass": 44.99572, "composition": 0.}, + 46: {"mass": 46.00004, "composition": 0.}, + 47: {"mass": 47.00795, "composition": 0.}, + 48: {"mass": 48.0137, "composition": 0.}, + 49: {"mass": 49.02276, "composition": 0.}}, + 17: {28: {"mass": 28.02954, "composition": 0.}, + 29: {"mass": 29.01478, "composition": 0.}, + 30: {"mass": 30.00477, "composition": 0.}, + 31: {"mass": 30.992414, "composition": 0.}, + 32: {"mass": 31.98568464, "composition": 0.}, + 33: {"mass": 32.97745199, "composition": 0.}, + 34: {"mass": 33.973762485, "composition": 0.}, + 35: {"mass": 34.968852682, "composition": 0.7576}, + 36: {"mass": 35.968306809, "composition": 0.}, + 37: {"mass": 36.965902602, "composition": 0.2424}, + 38: {"mass": 37.96801044, "composition": 0.}, + 39: {"mass": 38.9680082, "composition": 0.}, + 40: {"mass": 39.970415, "composition": 0.}, + 41: {"mass": 40.970685, "composition": 0.}, + 42: {"mass": 41.97325, "composition": 0.}, + 43: {"mass": 42.97389, "composition": 0.}, + 44: {"mass": 43.97787, "composition": 0.}, + 45: {"mass": 44.98029, "composition": 0.}, + 46: {"mass": 45.98517, "composition": 0.}, + 47: {"mass": 46.98916, "composition": 0.}, + 48: {"mass": 47.99564, "composition": 0.}, + 49: {"mass": 49.00123, "composition": 0.}, + 50: {"mass": 50.00905, "composition": 0.}, + 51: {"mass": 51.01554, "composition": 0.}}, + 18: {30: {"mass": 30.02307, "composition": 0.}, + 31: {"mass": 31.01212, "composition": 0.}, + 32: {"mass": 31.9976378, "composition": 0.}, + 33: {"mass": 32.98992555, "composition": 0.}, + 34: {"mass": 33.98027009, "composition": 0.}, + 35: {"mass": 34.97525759, "composition": 0.}, + 36: {"mass": 35.967545105, "composition": 0.003336}, + 37: {"mass": 36.96677633, "composition": 0.}, + 38: {"mass": 37.96273211, "composition": 0.000629}, + 39: {"mass": 38.964313, "composition": 0.}, + 40: {"mass": 39.9623831237, "composition": 0.996035}, + 41: {"mass": 40.96450057, "composition": 0.}, + 42: {"mass": 41.9630457, "composition": 0.}, + 43: {"mass": 42.9656361, "composition": 0.}, + 44: {"mass": 43.9649238, "composition": 0.}, + 45: {"mass": 44.96803973, "composition": 0.}, + 46: {"mass": 45.968083, "composition": 0.}, + 47: {"mass": 46.972935, "composition": 0.}, + 48: {"mass": 47.97591, "composition": 0.}, + 49: {"mass": 48.9819, "composition": 0.}, + 50: {"mass": 49.98613, "composition": 0.}, + 51: {"mass": 50.9937, "composition": 0.}, + 52: {"mass": 51.99896, "composition": 0.}, + 53: {"mass": 53.00729, "composition": 0.}}, + 19: {32: {"mass": 32.02265, "composition": 0.}, + 33: {"mass": 33.00756, "composition": 0.}, + 34: {"mass": 33.99869, "composition": 0.}, + 35: {"mass": 34.98800541, "composition": 0.}, + 36: {"mass": 35.98130201, "composition": 0.}, + 37: {"mass": 36.97337589, "composition": 0.}, + 38: {"mass": 37.96908112, "composition": 0.}, + 39: {"mass": 38.9637064864, "composition": 0.932581}, + 40: {"mass": 39.963998166, "composition": 0.000117}, + 41: {"mass": 40.9618252579, "composition": 0.067302}, + 42: {"mass": 41.96240231, "composition": 0.}, + 43: {"mass": 42.9607347, "composition": 0.}, + 44: {"mass": 43.96158699, "composition": 0.}, + 45: {"mass": 44.96069149, "composition": 0.}, + 46: {"mass": 45.96198159, "composition": 0.}, + 47: {"mass": 46.9616616, "composition": 0.}, + 48: {"mass": 47.96534119, "composition": 0.}, + 49: {"mass": 48.96821075, "composition": 0.}, + 50: {"mass": 49.97238, "composition": 0.}, + 51: {"mass": 50.975828, "composition": 0.}, + 52: {"mass": 51.98224, "composition": 0.}, + 53: {"mass": 52.98746, "composition": 0.}, + 54: {"mass": 53.99463, "composition": 0.}, + 55: {"mass": 55.00076, "composition": 0.}, + 56: {"mass": 56.00851, "composition": 0.}}, + 20: {34: {"mass": 34.01487, "composition": 0.}, + 35: {"mass": 35.00514, "composition": 0.}, + 36: {"mass": 35.993074, "composition": 0.}, + 37: {"mass": 36.98589785, "composition": 0.}, + 38: {"mass": 37.97631922, "composition": 0.}, + 39: {"mass": 38.97071081, "composition": 0.}, + 40: {"mass": 39.962590863, "composition": 0.96941}, + 41: {"mass": 40.96227792, "composition": 0.}, + 42: {"mass": 41.95861783, "composition": 0.00647}, + 43: {"mass": 42.95876644, "composition": 0.00135}, + 44: {"mass": 43.95548156, "composition": 0.02086}, + 45: {"mass": 44.95618635, "composition": 0.}, + 46: {"mass": 45.953689, "composition": 4e-05}, + 47: {"mass": 46.9545424, "composition": 0.}, + 48: {"mass": 47.95252276, "composition": 0.00187}, + 49: {"mass": 48.95566274, "composition": 0.}, + 50: {"mass": 49.9574992, "composition": 0.}, + 51: {"mass": 50.960989, "composition": 0.}, + 52: {"mass": 51.963217, "composition": 0.}, + 53: {"mass": 52.96945, "composition": 0.}, + 54: {"mass": 53.9734, "composition": 0.}, + 55: {"mass": 54.9803, "composition": 0.}, + 56: {"mass": 55.98508, "composition": 0.}, + 57: {"mass": 56.99262, "composition": 0.}, + 58: {"mass": 57.99794, "composition": 0.}}, + 21: {36: {"mass": 36.01648, "composition": 0.}, + 37: {"mass": 37.00374, "composition": 0.}, + 38: {"mass": 37.99512, "composition": 0.}, + 39: {"mass": 38.984785, "composition": 0.}, + 40: {"mass": 39.9779673, "composition": 0.}, + 41: {"mass": 40.969251105, "composition": 0.}, + 42: {"mass": 41.96551653, "composition": 0.}, + 43: {"mass": 42.9611505, "composition": 0.}, + 44: {"mass": 43.9594029, "composition": 0.}, + 45: {"mass": 44.95590828, "composition": 1.}, + 46: {"mass": 45.95516826, "composition": 0.}, + 47: {"mass": 46.9524037, "composition": 0.}, + 48: {"mass": 47.9522236, "composition": 0.}, + 49: {"mass": 48.9500146, "composition": 0.}, + 50: {"mass": 49.952176, "composition": 0.}, + 51: {"mass": 50.953592, "composition": 0.}, + 52: {"mass": 51.95688, "composition": 0.}, + 53: {"mass": 52.95909, "composition": 0.}, + 54: {"mass": 53.96393, "composition": 0.}, + 55: {"mass": 54.96782, "composition": 0.}, + 56: {"mass": 55.97345, "composition": 0.}, + 57: {"mass": 56.97777, "composition": 0.}, + 58: {"mass": 57.98403, "composition": 0.}, + 59: {"mass": 58.98894, "composition": 0.}, + 60: {"mass": 59.99565, "composition": 0.}, + 61: {"mass": 61.001, "composition": 0.}}, + 22: {38: {"mass": 38.01145, "composition": 0.}, + 39: {"mass": 39.00236, "composition": 0.}, + 40: {"mass": 39.9905, "composition": 0.}, + 41: {"mass": 40.983148, "composition": 0.}, + 42: {"mass": 41.97304903, "composition": 0.}, + 43: {"mass": 42.9685225, "composition": 0.}, + 44: {"mass": 43.95968995, "composition": 0.}, + 45: {"mass": 44.95812198, "composition": 0.}, + 46: {"mass": 45.95262772, "composition": 0.0825}, + 47: {"mass": 46.95175879, "composition": 0.0744}, + 48: {"mass": 47.94794198, "composition": 0.7372}, + 49: {"mass": 48.94786568, "composition": 0.0541}, + 50: {"mass": 49.94478689, "composition": 0.0518}, + 51: {"mass": 50.94661065, "composition": 0.}, + 52: {"mass": 51.946893, "composition": 0.}, + 53: {"mass": 52.94973, "composition": 0.}, + 54: {"mass": 53.95105, "composition": 0.}, + 55: {"mass": 54.95527, "composition": 0.}, + 56: {"mass": 55.95791, "composition": 0.}, + 57: {"mass": 56.96364, "composition": 0.}, + 58: {"mass": 57.9666, "composition": 0.}, + 59: {"mass": 58.97247, "composition": 0.}, + 60: {"mass": 59.97603, "composition": 0.}, + 61: {"mass": 60.98245, "composition": 0.}, + 62: {"mass": 61.98651, "composition": 0.}, + 63: {"mass": 62.99375, "composition": 0.}}, + 23: {40: {"mass": 40.01276, "composition": 0.}, + 41: {"mass": 41.00021, "composition": 0.}, + 42: {"mass": 41.99182, "composition": 0.}, + 43: {"mass": 42.980766, "composition": 0.}, + 44: {"mass": 43.97411, "composition": 0.}, + 45: {"mass": 44.9657748, "composition": 0.}, + 46: {"mass": 45.96019878, "composition": 0.}, + 47: {"mass": 46.95490491, "composition": 0.}, + 48: {"mass": 47.9522522, "composition": 0.}, + 49: {"mass": 48.9485118, "composition": 0.}, + 50: {"mass": 49.94715601, "composition": 0.0025}, + 51: {"mass": 50.94395704, "composition": 0.9975}, + 52: {"mass": 51.94477301, "composition": 0.}, + 53: {"mass": 52.9443367, "composition": 0.}, + 54: {"mass": 53.946439, "composition": 0.}, + 55: {"mass": 54.94724, "composition": 0.}, + 56: {"mass": 55.95048, "composition": 0.}, + 57: {"mass": 56.95252, "composition": 0.}, + 58: {"mass": 57.95672, "composition": 0.}, + 59: {"mass": 58.95939, "composition": 0.}, + 60: {"mass": 59.96431, "composition": 0.}, + 61: {"mass": 60.96725, "composition": 0.}, + 62: {"mass": 61.97265, "composition": 0.}, + 63: {"mass": 62.97639, "composition": 0.}, + 64: {"mass": 63.98264, "composition": 0.}, + 65: {"mass": 64.9875, "composition": 0.}, + 66: {"mass": 65.99398, "composition": 0.}}, + 24: {42: {"mass": 42.0067, "composition": 0.}, + 43: {"mass": 42.99753, "composition": 0.}, + 44: {"mass": 43.98536, "composition": 0.}, + 45: {"mass": 44.97905, "composition": 0.}, + 46: {"mass": 45.968359, "composition": 0.}, + 47: {"mass": 46.9628974, "composition": 0.}, + 48: {"mass": 47.9540291, "composition": 0.}, + 49: {"mass": 48.9513333, "composition": 0.}, + 50: {"mass": 49.94604183, "composition": 0.04345}, + 51: {"mass": 50.94476502, "composition": 0.}, + 52: {"mass": 51.94050623, "composition": 0.83789}, + 53: {"mass": 52.94064815, "composition": 0.09501}, + 54: {"mass": 53.93887916, "composition": 0.02365}, + 55: {"mass": 54.94083843, "composition": 0.}, + 56: {"mass": 55.9406531, "composition": 0.}, + 57: {"mass": 56.943613, "composition": 0.}, + 58: {"mass": 57.94435, "composition": 0.}, + 59: {"mass": 58.94859, "composition": 0.}, + 60: {"mass": 59.95008, "composition": 0.}, + 61: {"mass": 60.95442, "composition": 0.}, + 62: {"mass": 61.9561, "composition": 0.}, + 63: {"mass": 62.96165, "composition": 0.}, + 64: {"mass": 63.96408, "composition": 0.}, + 65: {"mass": 64.96996, "composition": 0.}, + 66: {"mass": 65.97366, "composition": 0.}, + 67: {"mass": 66.98016, "composition": 0.}, + 68: {"mass": 67.98403, "composition": 0.}}, + 25: {44: {"mass": 44.00715, "composition": 0.}, + 45: {"mass": 44.99449, "composition": 0.}, + 46: {"mass": 45.98609, "composition": 0.}, + 47: {"mass": 46.975775, "composition": 0.}, + 48: {"mass": 47.96852, "composition": 0.}, + 49: {"mass": 48.959595, "composition": 0.}, + 50: {"mass": 49.95423778, "composition": 0.}, + 51: {"mass": 50.94820847, "composition": 0.}, + 52: {"mass": 51.9455639, "composition": 0.}, + 53: {"mass": 52.94128889, "composition": 0.}, + 54: {"mass": 53.9403576, "composition": 0.}, + 55: {"mass": 54.93804391, "composition": 1.}, + 56: {"mass": 55.93890369, "composition": 0.}, + 57: {"mass": 56.9382861, "composition": 0.}, + 58: {"mass": 57.9400666, "composition": 0.}, + 59: {"mass": 58.9403911, "composition": 0.}, + 60: {"mass": 59.9431366, "composition": 0.}, + 61: {"mass": 60.9444525, "composition": 0.}, + 62: {"mass": 61.94795, "composition": 0.}, + 63: {"mass": 62.9496647, "composition": 0.}, + 64: {"mass": 63.9538494, "composition": 0.}, + 65: {"mass": 64.9560198, "composition": 0.}, + 66: {"mass": 65.960547, "composition": 0.}, + 67: {"mass": 66.96424, "composition": 0.}, + 68: {"mass": 67.96962, "composition": 0.}, + 69: {"mass": 68.97366, "composition": 0.}, + 70: {"mass": 69.97937, "composition": 0.}, + 71: {"mass": 70.98368, "composition": 0.}}, + 26: {45: {"mass": 45.01442, "composition": 0.}, + 46: {"mass": 46.00063, "composition": 0.}, + 47: {"mass": 46.99185, "composition": 0.}, + 48: {"mass": 47.98023, "composition": 0.}, + 49: {"mass": 48.973429, "composition": 0.}, + 50: {"mass": 49.962975, "composition": 0.}, + 51: {"mass": 50.956841, "composition": 0.}, + 52: {"mass": 51.9481131, "composition": 0.}, + 53: {"mass": 52.9453064, "composition": 0.}, + 54: {"mass": 53.93960899, "composition": 0.05845}, + 55: {"mass": 54.93829199, "composition": 0.}, + 56: {"mass": 55.93493633, "composition": 0.91754}, + 57: {"mass": 56.93539284, "composition": 0.02119}, + 58: {"mass": 57.93327443, "composition": 0.00282}, + 59: {"mass": 58.93487434, "composition": 0.}, + 60: {"mass": 59.9340711, "composition": 0.}, + 61: {"mass": 60.9367462, "composition": 0.}, + 62: {"mass": 61.9367918, "composition": 0.}, + 63: {"mass": 62.9402727, "composition": 0.}, + 64: {"mass": 63.9409878, "composition": 0.}, + 65: {"mass": 64.9450115, "composition": 0.}, + 66: {"mass": 65.94625, "composition": 0.}, + 67: {"mass": 66.95054, "composition": 0.}, + 68: {"mass": 67.95295, "composition": 0.}, + 69: {"mass": 68.95807, "composition": 0.}, + 70: {"mass": 69.96102, "composition": 0.}, + 71: {"mass": 70.96672, "composition": 0.}, + 72: {"mass": 71.96983, "composition": 0.}, + 73: {"mass": 72.97572, "composition": 0.}, + 74: {"mass": 73.97935, "composition": 0.}}, + 27: {47: {"mass": 47.01057, "composition": 0.}, + 48: {"mass": 48.00093, "composition": 0.}, + 49: {"mass": 48.98891, "composition": 0.}, + 50: {"mass": 49.98091, "composition": 0.}, + 51: {"mass": 50.970647, "composition": 0.}, + 52: {"mass": 51.96351, "composition": 0.}, + 53: {"mass": 52.9542041, "composition": 0.}, + 54: {"mass": 53.94845987, "composition": 0.}, + 55: {"mass": 54.9419972, "composition": 0.}, + 56: {"mass": 55.9398388, "composition": 0.}, + 57: {"mass": 56.93629057, "composition": 0.}, + 58: {"mass": 57.9357521, "composition": 0.}, + 59: {"mass": 58.93319429, "composition": 1.}, + 60: {"mass": 59.9338163, "composition": 0.}, + 61: {"mass": 60.93247662, "composition": 0.}, + 62: {"mass": 61.934059, "composition": 0.}, + 63: {"mass": 62.9336, "composition": 0.}, + 64: {"mass": 63.935811, "composition": 0.}, + 65: {"mass": 64.9364621, "composition": 0.}, + 66: {"mass": 65.939443, "composition": 0.}, + 67: {"mass": 66.9406096, "composition": 0.}, + 68: {"mass": 67.94426, "composition": 0.}, + 69: {"mass": 68.94614, "composition": 0.}, + 70: {"mass": 69.94963, "composition": 0.}, + 71: {"mass": 70.95237, "composition": 0.}, + 72: {"mass": 71.95729, "composition": 0.}, + 73: {"mass": 72.96039, "composition": 0.}, + 74: {"mass": 73.96515, "composition": 0.}, + 75: {"mass": 74.96876, "composition": 0.}, + 76: {"mass": 75.97413, "composition": 0.}}, + 28: {48: {"mass": 48.01769, "composition": 0.}, + 49: {"mass": 49.0077, "composition": 0.}, + 50: {"mass": 49.99474, "composition": 0.}, + 51: {"mass": 50.98611, "composition": 0.}, + 52: {"mass": 51.9748, "composition": 0.}, + 53: {"mass": 52.96819, "composition": 0.}, + 54: {"mass": 53.957892, "composition": 0.}, + 55: {"mass": 54.95133063, "composition": 0.}, + 56: {"mass": 55.94212855, "composition": 0.}, + 57: {"mass": 56.93979218, "composition": 0.}, + 58: {"mass": 57.93534241, "composition": 0.68077}, + 59: {"mass": 58.9343462, "composition": 0.}, + 60: {"mass": 59.93078588, "composition": 0.26223}, + 61: {"mass": 60.93105557, "composition": 0.011399}, + 62: {"mass": 61.92834537, "composition": 0.036346}, + 63: {"mass": 62.92966963, "composition": 0.}, + 64: {"mass": 63.92796682, "composition": 0.009255}, + 65: {"mass": 64.93008517, "composition": 0.}, + 66: {"mass": 65.9291393, "composition": 0.}, + 67: {"mass": 66.9315694, "composition": 0.}, + 68: {"mass": 67.9318688, "composition": 0.}, + 69: {"mass": 68.9356103, "composition": 0.}, + 70: {"mass": 69.9364313, "composition": 0.}, + 71: {"mass": 70.940519, "composition": 0.}, + 72: {"mass": 71.9417859, "composition": 0.}, + 73: {"mass": 72.9462067, "composition": 0.}, + 74: {"mass": 73.94798, "composition": 0.}, + 75: {"mass": 74.9525, "composition": 0.}, + 76: {"mass": 75.95533, "composition": 0.}, + 77: {"mass": 76.96055, "composition": 0.}, + 78: {"mass": 77.96336, "composition": 0.}, + 79: {"mass": 78.97025, "composition": 0.}}, + 29: {52: {"mass": 51.99671, "composition": 0.}, + 53: {"mass": 52.98459, "composition": 0.}, + 54: {"mass": 53.97666, "composition": 0.}, + 55: {"mass": 54.96604, "composition": 0.}, + 56: {"mass": 55.95895, "composition": 0.}, + 57: {"mass": 56.9492125, "composition": 0.}, + 58: {"mass": 57.94453305, "composition": 0.}, + 59: {"mass": 58.93949748, "composition": 0.}, + 60: {"mass": 59.9373645, "composition": 0.}, + 61: {"mass": 60.9334576, "composition": 0.}, + 62: {"mass": 61.93259541, "composition": 0.}, + 63: {"mass": 62.92959772, "composition": 0.6915}, + 64: {"mass": 63.92976434, "composition": 0.}, + 65: {"mass": 64.9277897, "composition": 0.3085}, + 66: {"mass": 65.92886903, "composition": 0.}, + 67: {"mass": 66.9277303, "composition": 0.}, + 68: {"mass": 67.9296109, "composition": 0.}, + 69: {"mass": 68.9294293, "composition": 0.}, + 70: {"mass": 69.9323921, "composition": 0.}, + 71: {"mass": 70.9326768, "composition": 0.}, + 72: {"mass": 71.9358203, "composition": 0.}, + 73: {"mass": 72.9366744, "composition": 0.}, + 74: {"mass": 73.9398749, "composition": 0.}, + 75: {"mass": 74.9415226, "composition": 0.}, + 76: {"mass": 75.945275, "composition": 0.}, + 77: {"mass": 76.94792, "composition": 0.}, + 78: {"mass": 77.95223, "composition": 0.}, + 79: {"mass": 78.95502, "composition": 0.}, + 80: {"mass": 79.96089, "composition": 0.}, + 81: {"mass": 80.96587, "composition": 0.}, + 82: {"mass": 81.97244, "composition": 0.}}, + 30: {54: {"mass": 53.99204, "composition": 0.}, + 55: {"mass": 54.98398, "composition": 0.}, + 56: {"mass": 55.97254, "composition": 0.}, + 57: {"mass": 56.96506, "composition": 0.}, + 58: {"mass": 57.954591, "composition": 0.}, + 59: {"mass": 58.94931266, "composition": 0.}, + 60: {"mass": 59.9418421, "composition": 0.}, + 61: {"mass": 60.939507, "composition": 0.}, + 62: {"mass": 61.93433397, "composition": 0.}, + 63: {"mass": 62.9332115, "composition": 0.}, + 64: {"mass": 63.92914201, "composition": 0.4917}, + 65: {"mass": 64.92924077, "composition": 0.}, + 66: {"mass": 65.92603381, "composition": 0.2773}, + 67: {"mass": 66.92712775, "composition": 0.0404}, + 68: {"mass": 67.92484455, "composition": 0.1845}, + 69: {"mass": 68.9265507, "composition": 0.}, + 70: {"mass": 69.9253192, "composition": 0.0061}, + 71: {"mass": 70.9277196, "composition": 0.}, + 72: {"mass": 71.9268428, "composition": 0.}, + 73: {"mass": 72.9295826, "composition": 0.}, + 74: {"mass": 73.9294073, "composition": 0.}, + 75: {"mass": 74.9328402, "composition": 0.}, + 76: {"mass": 75.933115, "composition": 0.}, + 77: {"mass": 76.9368872, "composition": 0.}, + 78: {"mass": 77.9382892, "composition": 0.}, + 79: {"mass": 78.9426381, "composition": 0.}, + 80: {"mass": 79.9445529, "composition": 0.}, + 81: {"mass": 80.9504026, "composition": 0.}, + 82: {"mass": 81.95426, "composition": 0.}, + 83: {"mass": 82.96056, "composition": 0.}, + 84: {"mass": 83.96521, "composition": 0.}, + 85: {"mass": 84.97226, "composition": 0.}}, + 31: {56: {"mass": 55.99536, "composition": 0.}, + 57: {"mass": 56.9832, "composition": 0.}, + 58: {"mass": 57.97478, "composition": 0.}, + 59: {"mass": 58.96353, "composition": 0.}, + 60: {"mass": 59.95729, "composition": 0.}, + 61: {"mass": 60.949399, "composition": 0.}, + 62: {"mass": 61.94419025, "composition": 0.}, + 63: {"mass": 62.9392942, "composition": 0.}, + 64: {"mass": 63.9368404, "composition": 0.}, + 65: {"mass": 64.93273459, "composition": 0.}, + 66: {"mass": 65.9315894, "composition": 0.}, + 67: {"mass": 66.9282025, "composition": 0.}, + 68: {"mass": 67.9279805, "composition": 0.}, + 69: {"mass": 68.9255735, "composition": 0.60108}, + 70: {"mass": 69.9260219, "composition": 0.}, + 71: {"mass": 70.92470258, "composition": 0.39892}, + 72: {"mass": 71.92636747, "composition": 0.}, + 73: {"mass": 72.9251747, "composition": 0.}, + 74: {"mass": 73.9269457, "composition": 0.}, + 75: {"mass": 74.9265002, "composition": 0.}, + 76: {"mass": 75.9288276, "composition": 0.}, + 77: {"mass": 76.9291543, "composition": 0.}, + 78: {"mass": 77.9316088, "composition": 0.}, + 79: {"mass": 78.9328523, "composition": 0.}, + 80: {"mass": 79.9364208, "composition": 0.}, + 81: {"mass": 80.9381338, "composition": 0.}, + 82: {"mass": 81.9431765, "composition": 0.}, + 83: {"mass": 82.9471203, "composition": 0.}, + 84: {"mass": 83.95246, "composition": 0.}, + 85: {"mass": 84.95699, "composition": 0.}, + 86: {"mass": 85.96301, "composition": 0.}, + 87: {"mass": 86.96824, "composition": 0.}}, + 32: {58: {"mass": 57.99172, "composition": 0.}, + 59: {"mass": 58.98249, "composition": 0.}, + 60: {"mass": 59.97036, "composition": 0.}, + 61: {"mass": 60.96379, "composition": 0.}, + 62: {"mass": 61.95502, "composition": 0.}, + 63: {"mass": 62.949628, "composition": 0.}, + 64: {"mass": 63.9416899, "composition": 0.}, + 65: {"mass": 64.9393681, "composition": 0.}, + 66: {"mass": 65.9338621, "composition": 0.}, + 67: {"mass": 66.9327339, "composition": 0.}, + 68: {"mass": 67.9280953, "composition": 0.}, + 69: {"mass": 68.9279645, "composition": 0.}, + 70: {"mass": 69.92424875, "composition": 0.2057}, + 71: {"mass": 70.92495233, "composition": 0.}, + 72: {"mass": 71.922075826, "composition": 0.2745}, + 73: {"mass": 72.923458956, "composition": 0.0775}, + 74: {"mass": 73.921177761, "composition": 0.365}, + 75: {"mass": 74.92285837, "composition": 0.}, + 76: {"mass": 75.921402726, "composition": 0.0773}, + 77: {"mass": 76.923549843, "composition": 0.}, + 78: {"mass": 77.9228529, "composition": 0.}, + 79: {"mass": 78.92536, "composition": 0.}, + 80: {"mass": 79.9253508, "composition": 0.}, + 81: {"mass": 80.9288329, "composition": 0.}, + 82: {"mass": 81.929774, "composition": 0.}, + 83: {"mass": 82.9345391, "composition": 0.}, + 84: {"mass": 83.9375751, "composition": 0.}, + 85: {"mass": 84.9429697, "composition": 0.}, + 86: {"mass": 85.94658, "composition": 0.}, + 87: {"mass": 86.95268, "composition": 0.}, + 88: {"mass": 87.95691, "composition": 0.}, + 89: {"mass": 88.96379, "composition": 0.}, + 90: {"mass": 89.96863, "composition": 0.}}, + 33: {60: {"mass": 59.99388, "composition": 0.}, + 61: {"mass": 60.98112, "composition": 0.}, + 62: {"mass": 61.97361, "composition": 0.}, + 63: {"mass": 62.9639, "composition": 0.}, + 64: {"mass": 63.95743, "composition": 0.}, + 65: {"mass": 64.949611, "composition": 0.}, + 66: {"mass": 65.9441488, "composition": 0.}, + 67: {"mass": 66.93925111, "composition": 0.}, + 68: {"mass": 67.9367741, "composition": 0.}, + 69: {"mass": 68.932246, "composition": 0.}, + 70: {"mass": 69.930926, "composition": 0.}, + 71: {"mass": 70.9271138, "composition": 0.}, + 72: {"mass": 71.9267523, "composition": 0.}, + 73: {"mass": 72.9238291, "composition": 0.}, + 74: {"mass": 73.9239286, "composition": 0.}, + 75: {"mass": 74.92159457, "composition": 1.}, + 76: {"mass": 75.92239202, "composition": 0.}, + 77: {"mass": 76.9206476, "composition": 0.}, + 78: {"mass": 77.921828, "composition": 0.}, + 79: {"mass": 78.9209484, "composition": 0.}, + 80: {"mass": 79.9224746, "composition": 0.}, + 81: {"mass": 80.9221323, "composition": 0.}, + 82: {"mass": 81.9247412, "composition": 0.}, + 83: {"mass": 82.9252069, "composition": 0.}, + 84: {"mass": 83.9293033, "composition": 0.}, + 85: {"mass": 84.9321637, "composition": 0.}, + 86: {"mass": 85.9367015, "composition": 0.}, + 87: {"mass": 86.9402917, "composition": 0.}, + 88: {"mass": 87.94555, "composition": 0.}, + 89: {"mass": 88.94976, "composition": 0.}, + 90: {"mass": 89.95563, "composition": 0.}, + 91: {"mass": 90.96039, "composition": 0.}, + 92: {"mass": 91.96674, "composition": 0.}}, + 34: {64: {"mass": 63.97109, "composition": 0.}, + 65: {"mass": 64.9644, "composition": 0.}, + 66: {"mass": 65.95559, "composition": 0.}, + 67: {"mass": 66.949994, "composition": 0.}, + 68: {"mass": 67.94182524, "composition": 0.}, + 69: {"mass": 68.9394148, "composition": 0.}, + 70: {"mass": 69.9335155, "composition": 0.}, + 71: {"mass": 70.9322094, "composition": 0.}, + 72: {"mass": 71.9271405, "composition": 0.}, + 73: {"mass": 72.9267549, "composition": 0.}, + 74: {"mass": 73.922475934, "composition": 0.0089}, + 75: {"mass": 74.92252287, "composition": 0.}, + 76: {"mass": 75.919213704, "composition": 0.0937}, + 77: {"mass": 76.919914154, "composition": 0.0763}, + 78: {"mass": 77.91730928, "composition": 0.2377}, + 79: {"mass": 78.91849929, "composition": 0.}, + 80: {"mass": 79.9165218, "composition": 0.4961}, + 81: {"mass": 80.917993, "composition": 0.}, + 82: {"mass": 81.9166995, "composition": 0.0873}, + 83: {"mass": 82.9191186, "composition": 0.}, + 84: {"mass": 83.9184668, "composition": 0.}, + 85: {"mass": 84.9222608, "composition": 0.}, + 86: {"mass": 85.9243117, "composition": 0.}, + 87: {"mass": 86.9286886, "composition": 0.}, + 88: {"mass": 87.9314175, "composition": 0.}, + 89: {"mass": 88.9366691, "composition": 0.}, + 90: {"mass": 89.9401, "composition": 0.}, + 91: {"mass": 90.94596, "composition": 0.}, + 92: {"mass": 91.94984, "composition": 0.}, + 93: {"mass": 92.95629, "composition": 0.}, + 94: {"mass": 93.96049, "composition": 0.}, + 95: {"mass": 94.9673, "composition": 0.}}, + 35: {67: {"mass": 66.96465, "composition": 0.}, + 68: {"mass": 67.95873, "composition": 0.}, + 69: {"mass": 68.950497, "composition": 0.}, + 70: {"mass": 69.944792, "composition": 0.}, + 71: {"mass": 70.9393422, "composition": 0.}, + 72: {"mass": 71.9365886, "composition": 0.}, + 73: {"mass": 72.9316715, "composition": 0.}, + 74: {"mass": 73.9299102, "composition": 0.}, + 75: {"mass": 74.9258105, "composition": 0.}, + 76: {"mass": 75.924542, "composition": 0.}, + 77: {"mass": 76.9213792, "composition": 0.}, + 78: {"mass": 77.9211459, "composition": 0.}, + 79: {"mass": 78.9183376, "composition": 0.5069}, + 80: {"mass": 79.9185298, "composition": 0.}, + 81: {"mass": 80.9162897, "composition": 0.4931}, + 82: {"mass": 81.9168032, "composition": 0.}, + 83: {"mass": 82.9151756, "composition": 0.}, + 84: {"mass": 83.916496, "composition": 0.}, + 85: {"mass": 84.9156458, "composition": 0.}, + 86: {"mass": 85.9188054, "composition": 0.}, + 87: {"mass": 86.920674, "composition": 0.}, + 88: {"mass": 87.9240833, "composition": 0.}, + 89: {"mass": 88.9267046, "composition": 0.}, + 90: {"mass": 89.9312928, "composition": 0.}, + 91: {"mass": 90.9343986, "composition": 0.}, + 92: {"mass": 91.9396316, "composition": 0.}, + 93: {"mass": 92.94313, "composition": 0.}, + 94: {"mass": 93.9489, "composition": 0.}, + 95: {"mass": 94.95301, "composition": 0.}, + 96: {"mass": 95.95903, "composition": 0.}, + 97: {"mass": 96.96344, "composition": 0.}, + 98: {"mass": 97.96946, "composition": 0.}}, + 36: {69: {"mass": 68.96518, "composition": 0.}, + 70: {"mass": 69.95604, "composition": 0.}, + 71: {"mass": 70.95027, "composition": 0.}, + 72: {"mass": 71.9420924, "composition": 0.}, + 73: {"mass": 72.9392892, "composition": 0.}, + 74: {"mass": 73.933084, "composition": 0.}, + 75: {"mass": 74.9309457, "composition": 0.}, + 76: {"mass": 75.9259103, "composition": 0.}, + 77: {"mass": 76.92467, "composition": 0.}, + 78: {"mass": 77.92036494, "composition": 0.00355}, + 79: {"mass": 78.9200829, "composition": 0.}, + 80: {"mass": 79.91637808, "composition": 0.02286}, + 81: {"mass": 80.9165912, "composition": 0.}, + 82: {"mass": 81.91348273, "composition": 0.11593}, + 83: {"mass": 82.91412716, "composition": 0.115}, + 84: {"mass": 83.9114977282, "composition": 0.56987}, + 85: {"mass": 84.9125273, "composition": 0.}, + 86: {"mass": 85.9106106269, "composition": 0.17279}, + 87: {"mass": 86.91335476, "composition": 0.}, + 88: {"mass": 87.9144479, "composition": 0.}, + 89: {"mass": 88.9178355, "composition": 0.}, + 90: {"mass": 89.9195279, "composition": 0.}, + 91: {"mass": 90.9238063, "composition": 0.}, + 92: {"mass": 91.9261731, "composition": 0.}, + 93: {"mass": 92.9311472, "composition": 0.}, + 94: {"mass": 93.93414, "composition": 0.}, + 95: {"mass": 94.939711, "composition": 0.}, + 96: {"mass": 95.943017, "composition": 0.}, + 97: {"mass": 96.94909, "composition": 0.}, + 98: {"mass": 97.95243, "composition": 0.}, + 99: {"mass": 98.95839, "composition": 0.}, + 100: {"mass": 99.96237, "composition": 0.}, + 101: {"mass": 100.96873, "composition": 0.}}, + 37: {71: {"mass": 70.96532, "composition": 0.}, + 72: {"mass": 71.95908, "composition": 0.}, + 73: {"mass": 72.95053, "composition": 0.}, + 74: {"mass": 73.9442659, "composition": 0.}, + 75: {"mass": 74.9385732, "composition": 0.}, + 76: {"mass": 75.935073, "composition": 0.}, + 77: {"mass": 76.9304016, "composition": 0.}, + 78: {"mass": 77.9281419, "composition": 0.}, + 79: {"mass": 78.9239899, "composition": 0.}, + 80: {"mass": 79.9225164, "composition": 0.}, + 81: {"mass": 80.9189939, "composition": 0.}, + 82: {"mass": 81.918209, "composition": 0.}, + 83: {"mass": 82.9151142, "composition": 0.}, + 84: {"mass": 83.9143752, "composition": 0.}, + 85: {"mass": 84.9117897379, "composition": 0.7217}, + 86: {"mass": 85.91116743, "composition": 0.}, + 87: {"mass": 86.909180531, "composition": 0.2783}, + 88: {"mass": 87.91131559, "composition": 0.}, + 89: {"mass": 88.9122783, "composition": 0.}, + 90: {"mass": 89.9147985, "composition": 0.}, + 91: {"mass": 90.9165372, "composition": 0.}, + 92: {"mass": 91.9197284, "composition": 0.}, + 93: {"mass": 92.9220393, "composition": 0.}, + 94: {"mass": 93.9263948, "composition": 0.}, + 95: {"mass": 94.92926, "composition": 0.}, + 96: {"mass": 95.9341334, "composition": 0.}, + 97: {"mass": 96.9371771, "composition": 0.}, + 98: {"mass": 97.9416869, "composition": 0.}, + 99: {"mass": 98.94503, "composition": 0.}, + 100: {"mass": 99.95003, "composition": 0.}, + 101: {"mass": 100.95404, "composition": 0.}, + 102: {"mass": 101.95952, "composition": 0.}, + 103: {"mass": 102.96392, "composition": 0.}}, + 38: {73: {"mass": 72.9657, "composition": 0.}, + 74: {"mass": 73.95617, "composition": 0.}, + 75: {"mass": 74.94995, "composition": 0.}, + 76: {"mass": 75.941763, "composition": 0.}, + 77: {"mass": 76.9379455, "composition": 0.}, + 78: {"mass": 77.93218, "composition": 0.}, + 79: {"mass": 78.9297077, "composition": 0.}, + 80: {"mass": 79.9245175, "composition": 0.}, + 81: {"mass": 80.9232114, "composition": 0.}, + 82: {"mass": 81.9183999, "composition": 0.}, + 83: {"mass": 82.9175544, "composition": 0.}, + 84: {"mass": 83.9134191, "composition": 0.0056}, + 85: {"mass": 84.912932, "composition": 0.}, + 86: {"mass": 85.9092606, "composition": 0.0986}, + 87: {"mass": 86.9088775, "composition": 0.07}, + 88: {"mass": 87.9056125, "composition": 0.8258}, + 89: {"mass": 88.9074511, "composition": 0.}, + 90: {"mass": 89.90773, "composition": 0.}, + 91: {"mass": 90.9101954, "composition": 0.}, + 92: {"mass": 91.9110382, "composition": 0.}, + 93: {"mass": 92.9140242, "composition": 0.}, + 94: {"mass": 93.9153556, "composition": 0.}, + 95: {"mass": 94.9193529, "composition": 0.}, + 96: {"mass": 95.9217066, "composition": 0.}, + 97: {"mass": 96.926374, "composition": 0.}, + 98: {"mass": 97.9286888, "composition": 0.}, + 99: {"mass": 98.9328907, "composition": 0.}, + 100: {"mass": 99.93577, "composition": 0.}, + 101: {"mass": 100.940352, "composition": 0.}, + 102: {"mass": 101.943791, "composition": 0.}, + 103: {"mass": 102.94909, "composition": 0.}, + 104: {"mass": 103.95265, "composition": 0.}, + 105: {"mass": 104.95855, "composition": 0.}, + 106: {"mass": 105.96265, "composition": 0.}, + 107: {"mass": 106.96897, "composition": 0.}}, + 39: {76: {"mass": 75.95856, "composition": 0.}, + 77: {"mass": 76.949781, "composition": 0.}, + 78: {"mass": 77.94361, "composition": 0.}, + 79: {"mass": 78.93735, "composition": 0.}, + 80: {"mass": 79.9343561, "composition": 0.}, + 81: {"mass": 80.9294556, "composition": 0.}, + 82: {"mass": 81.9269314, "composition": 0.}, + 83: {"mass": 82.922485, "composition": 0.}, + 84: {"mass": 83.9206721, "composition": 0.}, + 85: {"mass": 84.916433, "composition": 0.}, + 86: {"mass": 85.914886, "composition": 0.}, + 87: {"mass": 86.9108761, "composition": 0.}, + 88: {"mass": 87.9095016, "composition": 0.}, + 89: {"mass": 88.9058403, "composition": 1.}, + 90: {"mass": 89.9071439, "composition": 0.}, + 91: {"mass": 90.9072974, "composition": 0.}, + 92: {"mass": 91.9089451, "composition": 0.}, + 93: {"mass": 92.909578, "composition": 0.}, + 94: {"mass": 93.9115906, "composition": 0.}, + 95: {"mass": 94.9128161, "composition": 0.}, + 96: {"mass": 95.9158968, "composition": 0.}, + 97: {"mass": 96.9182741, "composition": 0.}, + 98: {"mass": 97.9223821, "composition": 0.}, + 99: {"mass": 98.924148, "composition": 0.}, + 100: {"mass": 99.927715, "composition": 0.}, + 101: {"mass": 100.9301477, "composition": 0.}, + 102: {"mass": 101.9343277, "composition": 0.}, + 103: {"mass": 102.937243, "composition": 0.}, + 104: {"mass": 103.94196, "composition": 0.}, + 105: {"mass": 104.94544, "composition": 0.}, + 106: {"mass": 105.95056, "composition": 0.}, + 107: {"mass": 106.95452, "composition": 0.}, + 108: {"mass": 107.95996, "composition": 0.}, + 109: {"mass": 108.96436, "composition": 0.}}, + 40: {78: {"mass": 77.95566, "composition": 0.}, + 79: {"mass": 78.94948, "composition": 0.}, + 80: {"mass": 79.9404, "composition": 0.}, + 81: {"mass": 80.93731, "composition": 0.}, + 82: {"mass": 81.93135, "composition": 0.}, + 83: {"mass": 82.9292421, "composition": 0.}, + 84: {"mass": 83.9233269, "composition": 0.}, + 85: {"mass": 84.9214444, "composition": 0.}, + 86: {"mass": 85.9162972, "composition": 0.}, + 87: {"mass": 86.914818, "composition": 0.}, + 88: {"mass": 87.9102213, "composition": 0.}, + 89: {"mass": 88.9088814, "composition": 0.}, + 90: {"mass": 89.9046977, "composition": 0.5145}, + 91: {"mass": 90.9056396, "composition": 0.1122}, + 92: {"mass": 91.9050347, "composition": 0.1715}, + 93: {"mass": 92.9064699, "composition": 0.}, + 94: {"mass": 93.9063108, "composition": 0.1738}, + 95: {"mass": 94.9080385, "composition": 0.}, + 96: {"mass": 95.9082714, "composition": 0.028}, + 97: {"mass": 96.9109512, "composition": 0.}, + 98: {"mass": 97.9127289, "composition": 0.}, + 99: {"mass": 98.916667, "composition": 0.}, + 100: {"mass": 99.9180006, "composition": 0.}, + 101: {"mass": 100.921448, "composition": 0.}, + 102: {"mass": 101.9231409, "composition": 0.}, + 103: {"mass": 102.927191, "composition": 0.}, + 104: {"mass": 103.929436, "composition": 0.}, + 105: {"mass": 104.934008, "composition": 0.}, + 106: {"mass": 105.93676, "composition": 0.}, + 107: {"mass": 106.94174, "composition": 0.}, + 108: {"mass": 107.94487, "composition": 0.}, + 109: {"mass": 108.95041, "composition": 0.}, + 110: {"mass": 109.95396, "composition": 0.}, + 111: {"mass": 110.95968, "composition": 0.}, + 112: {"mass": 111.9637, "composition": 0.}}, + 41: {81: {"mass": 80.9496, "composition": 0.}, + 82: {"mass": 81.94396, "composition": 0.}, + 83: {"mass": 82.93729, "composition": 0.}, + 84: {"mass": 83.93449, "composition": 0.}, + 85: {"mass": 84.9288458, "composition": 0.}, + 86: {"mass": 85.9257828, "composition": 0.}, + 87: {"mass": 86.9206937, "composition": 0.}, + 88: {"mass": 87.918222, "composition": 0.}, + 89: {"mass": 88.913445, "composition": 0.}, + 90: {"mass": 89.9112584, "composition": 0.}, + 91: {"mass": 90.9069897, "composition": 0.}, + 92: {"mass": 91.9071881, "composition": 0.}, + 93: {"mass": 92.906373, "composition": 1.}, + 94: {"mass": 93.9072788, "composition": 0.}, + 95: {"mass": 94.9068324, "composition": 0.}, + 96: {"mass": 95.9080973, "composition": 0.}, + 97: {"mass": 96.9080959, "composition": 0.}, + 98: {"mass": 97.9103265, "composition": 0.}, + 99: {"mass": 98.911613, "composition": 0.}, + 100: {"mass": 99.9143276, "composition": 0.}, + 101: {"mass": 100.9153103, "composition": 0.}, + 102: {"mass": 101.9180772, "composition": 0.}, + 103: {"mass": 102.9194572, "composition": 0.}, + 104: {"mass": 103.9228925, "composition": 0.}, + 105: {"mass": 104.9249465, "composition": 0.}, + 106: {"mass": 105.9289317, "composition": 0.}, + 107: {"mass": 106.9315937, "composition": 0.}, + 108: {"mass": 107.9360748, "composition": 0.}, + 109: {"mass": 108.93922, "composition": 0.}, + 110: {"mass": 109.94403, "composition": 0.}, + 111: {"mass": 110.94753, "composition": 0.}, + 112: {"mass": 111.95247, "composition": 0.}, + 113: {"mass": 112.95651, "composition": 0.}, + 114: {"mass": 113.96201, "composition": 0.}, + 115: {"mass": 114.96634, "composition": 0.}}, + 42: {83: {"mass": 82.94988, "composition": 0.}, + 84: {"mass": 83.94149, "composition": 0.}, + 85: {"mass": 84.938261, "composition": 0.}, + 86: {"mass": 85.9311748, "composition": 0.}, + 87: {"mass": 86.9281962, "composition": 0.}, + 88: {"mass": 87.9219678, "composition": 0.}, + 89: {"mass": 88.9194682, "composition": 0.}, + 90: {"mass": 89.9139309, "composition": 0.}, + 91: {"mass": 90.9117453, "composition": 0.}, + 92: {"mass": 91.90680796, "composition": 0.1453}, + 93: {"mass": 92.90680958, "composition": 0.}, + 94: {"mass": 93.9050849, "composition": 0.0915}, + 95: {"mass": 94.90583877, "composition": 0.1584}, + 96: {"mass": 95.90467612, "composition": 0.1667}, + 97: {"mass": 96.90601812, "composition": 0.096}, + 98: {"mass": 97.90540482, "composition": 0.2439}, + 99: {"mass": 98.90770851, "composition": 0.}, + 100: {"mass": 99.9074718, "composition": 0.0982}, + 101: {"mass": 100.9103414, "composition": 0.}, + 102: {"mass": 101.9102834, "composition": 0.}, + 103: {"mass": 102.913079, "composition": 0.}, + 104: {"mass": 103.9137344, "composition": 0.}, + 105: {"mass": 104.916969, "composition": 0.}, + 106: {"mass": 105.918259, "composition": 0.}, + 107: {"mass": 106.922106, "composition": 0.}, + 108: {"mass": 107.924033, "composition": 0.}, + 109: {"mass": 108.928424, "composition": 0.}, + 110: {"mass": 109.930704, "composition": 0.}, + 111: {"mass": 110.935654, "composition": 0.}, + 112: {"mass": 111.93831, "composition": 0.}, + 113: {"mass": 112.94335, "composition": 0.}, + 114: {"mass": 113.94653, "composition": 0.}, + 115: {"mass": 114.95196, "composition": 0.}, + 116: {"mass": 115.95545, "composition": 0.}, + 117: {"mass": 116.96117, "composition": 0.}}, + 43: {85: {"mass": 84.95058, "composition": 0.}, + 86: {"mass": 85.94493, "composition": 0.}, + 87: {"mass": 86.9380672, "composition": 0.}, + 88: {"mass": 87.93378, "composition": 0.}, + 89: {"mass": 88.9276487, "composition": 0.}, + 90: {"mass": 89.9240739, "composition": 0.}, + 91: {"mass": 90.9184254, "composition": 0.}, + 92: {"mass": 91.9152698, "composition": 0.}, + 93: {"mass": 92.910246, "composition": 0.}, + 94: {"mass": 93.9096536, "composition": 0.}, + 95: {"mass": 94.9076536, "composition": 0.}, + 96: {"mass": 95.907868, "composition": 0.}, + 97: {"mass": 96.9063667, "composition": 0.}, + 98: {"mass": 97.9072124, "composition": 0.}, + 99: {"mass": 98.9062508, "composition": 0.}, + 100: {"mass": 99.9076539, "composition": 0.}, + 101: {"mass": 100.907309, "composition": 0.}, + 102: {"mass": 101.9092097, "composition": 0.}, + 103: {"mass": 102.909176, "composition": 0.}, + 104: {"mass": 103.911425, "composition": 0.}, + 105: {"mass": 104.911655, "composition": 0.}, + 106: {"mass": 105.914358, "composition": 0.}, + 107: {"mass": 106.9154606, "composition": 0.}, + 108: {"mass": 107.9184957, "composition": 0.}, + 109: {"mass": 108.920256, "composition": 0.}, + 110: {"mass": 109.923744, "composition": 0.}, + 111: {"mass": 110.925901, "composition": 0.}, + 112: {"mass": 111.9299458, "composition": 0.}, + 113: {"mass": 112.932569, "composition": 0.}, + 114: {"mass": 113.93691, "composition": 0.}, + 115: {"mass": 114.93998, "composition": 0.}, + 116: {"mass": 115.94476, "composition": 0.}, + 117: {"mass": 116.94806, "composition": 0.}, + 118: {"mass": 117.95299, "composition": 0.}, + 119: {"mass": 118.95666, "composition": 0.}, + 120: {"mass": 119.96187, "composition": 0.}}, + 44: {87: {"mass": 86.95069, "composition": 0.}, + 88: {"mass": 87.9416, "composition": 0.}, + 89: {"mass": 88.93762, "composition": 0.}, + 90: {"mass": 89.9303444, "composition": 0.}, + 91: {"mass": 90.9267419, "composition": 0.}, + 92: {"mass": 91.9202344, "composition": 0.}, + 93: {"mass": 92.9171044, "composition": 0.}, + 94: {"mass": 93.9113429, "composition": 0.}, + 95: {"mass": 94.910406, "composition": 0.}, + 96: {"mass": 95.90759025, "composition": 0.0554}, + 97: {"mass": 96.9075471, "composition": 0.}, + 98: {"mass": 97.9052868, "composition": 0.0187}, + 99: {"mass": 98.9059341, "composition": 0.1276}, + 100: {"mass": 99.9042143, "composition": 0.126}, + 101: {"mass": 100.9055769, "composition": 0.1706}, + 102: {"mass": 101.9043441, "composition": 0.3155}, + 103: {"mass": 102.9063186, "composition": 0.}, + 104: {"mass": 103.9054275, "composition": 0.1862}, + 105: {"mass": 104.9077476, "composition": 0.}, + 106: {"mass": 105.9073291, "composition": 0.}, + 107: {"mass": 106.909972, "composition": 0.}, + 108: {"mass": 107.910188, "composition": 0.}, + 109: {"mass": 108.913326, "composition": 0.}, + 110: {"mass": 109.9140407, "composition": 0.}, + 111: {"mass": 110.91757, "composition": 0.}, + 112: {"mass": 111.918809, "composition": 0.}, + 113: {"mass": 112.922844, "composition": 0.}, + 114: {"mass": 113.9246136, "composition": 0.}, + 115: {"mass": 114.92882, "composition": 0.}, + 116: {"mass": 115.9312192, "composition": 0.}, + 117: {"mass": 116.9361, "composition": 0.}, + 118: {"mass": 117.93853, "composition": 0.}, + 119: {"mass": 118.94357, "composition": 0.}, + 120: {"mass": 119.94631, "composition": 0.}, + 121: {"mass": 120.95164, "composition": 0.}, + 122: {"mass": 121.95447, "composition": 0.}, + 123: {"mass": 122.95989, "composition": 0.}, + 124: {"mass": 123.96305, "composition": 0.}}, + 45: {89: {"mass": 88.95058, "composition": 0.}, + 90: {"mass": 89.94422, "composition": 0.}, + 91: {"mass": 90.93688, "composition": 0.}, + 92: {"mass": 91.9323677, "composition": 0.}, + 93: {"mass": 92.9259128, "composition": 0.}, + 94: {"mass": 93.9217305, "composition": 0.}, + 95: {"mass": 94.9158979, "composition": 0.}, + 96: {"mass": 95.914453, "composition": 0.}, + 97: {"mass": 96.911329, "composition": 0.}, + 98: {"mass": 97.910708, "composition": 0.}, + 99: {"mass": 98.9081282, "composition": 0.}, + 100: {"mass": 99.908117, "composition": 0.}, + 101: {"mass": 100.9061606, "composition": 0.}, + 102: {"mass": 101.9068374, "composition": 0.}, + 103: {"mass": 102.905498, "composition": 1.}, + 104: {"mass": 103.9066492, "composition": 0.}, + 105: {"mass": 104.9056885, "composition": 0.}, + 106: {"mass": 105.9072868, "composition": 0.}, + 107: {"mass": 106.906748, "composition": 0.}, + 108: {"mass": 107.908714, "composition": 0.}, + 109: {"mass": 108.9087488, "composition": 0.}, + 110: {"mass": 109.911079, "composition": 0.}, + 111: {"mass": 110.9116423, "composition": 0.}, + 112: {"mass": 111.914403, "composition": 0.}, + 113: {"mass": 112.9154393, "composition": 0.}, + 114: {"mass": 113.918718, "composition": 0.}, + 115: {"mass": 114.9203116, "composition": 0.}, + 116: {"mass": 115.924059, "composition": 0.}, + 117: {"mass": 116.9260354, "composition": 0.}, + 118: {"mass": 117.93034, "composition": 0.}, + 119: {"mass": 118.932557, "composition": 0.}, + 120: {"mass": 119.93686, "composition": 0.}, + 121: {"mass": 120.93942, "composition": 0.}, + 122: {"mass": 121.94399, "composition": 0.}, + 123: {"mass": 122.94685, "composition": 0.}, + 124: {"mass": 123.95151, "composition": 0.}, + 125: {"mass": 124.95469, "composition": 0.}, + 126: {"mass": 125.95946, "composition": 0.}}, + 46: {91: {"mass": 90.95032, "composition": 0.}, + 92: {"mass": 91.94088, "composition": 0.}, + 93: {"mass": 92.93651, "composition": 0.}, + 94: {"mass": 93.9290376, "composition": 0.}, + 95: {"mass": 94.9248898, "composition": 0.}, + 96: {"mass": 95.9182151, "composition": 0.}, + 97: {"mass": 96.916472, "composition": 0.}, + 98: {"mass": 97.9126983, "composition": 0.}, + 99: {"mass": 98.9117748, "composition": 0.}, + 100: {"mass": 99.908505, "composition": 0.}, + 101: {"mass": 100.9082864, "composition": 0.}, + 102: {"mass": 101.9056022, "composition": 0.0102}, + 103: {"mass": 102.9060809, "composition": 0.}, + 104: {"mass": 103.9040305, "composition": 0.1114}, + 105: {"mass": 104.9050796, "composition": 0.2233}, + 106: {"mass": 105.9034804, "composition": 0.2733}, + 107: {"mass": 106.9051282, "composition": 0.}, + 108: {"mass": 107.9038916, "composition": 0.2646}, + 109: {"mass": 108.9059504, "composition": 0.}, + 110: {"mass": 109.9051722, "composition": 0.1172}, + 111: {"mass": 110.90768968, "composition": 0.}, + 112: {"mass": 111.9073297, "composition": 0.}, + 113: {"mass": 112.910261, "composition": 0.}, + 114: {"mass": 113.9103686, "composition": 0.}, + 115: {"mass": 114.913659, "composition": 0.}, + 116: {"mass": 115.914297, "composition": 0.}, + 117: {"mass": 116.9179547, "composition": 0.}, + 118: {"mass": 117.9190667, "composition": 0.}, + 119: {"mass": 118.9233402, "composition": 0.}, + 120: {"mass": 119.9245511, "composition": 0.}, + 121: {"mass": 120.9289503, "composition": 0.}, + 122: {"mass": 121.930632, "composition": 0.}, + 123: {"mass": 122.93514, "composition": 0.}, + 124: {"mass": 123.93714, "composition": 0.}, + 125: {"mass": 124.94179, "composition": 0.}, + 126: {"mass": 125.94416, "composition": 0.}, + 127: {"mass": 126.94907, "composition": 0.}, + 128: {"mass": 127.95183, "composition": 0.}}, + 47: {93: {"mass": 92.95033, "composition": 0.}, + 94: {"mass": 93.94373, "composition": 0.}, + 95: {"mass": 94.93602, "composition": 0.}, + 96: {"mass": 95.930744, "composition": 0.}, + 97: {"mass": 96.92397, "composition": 0.}, + 98: {"mass": 97.92156, "composition": 0.}, + 99: {"mass": 98.9176458, "composition": 0.}, + 100: {"mass": 99.9161154, "composition": 0.}, + 101: {"mass": 100.912684, "composition": 0.}, + 102: {"mass": 101.9117047, "composition": 0.}, + 103: {"mass": 102.9089631, "composition": 0.}, + 104: {"mass": 103.9086239, "composition": 0.}, + 105: {"mass": 104.9065256, "composition": 0.}, + 106: {"mass": 105.9066636, "composition": 0.}, + 107: {"mass": 106.9050916, "composition": 0.51839}, + 108: {"mass": 107.9059503, "composition": 0.}, + 109: {"mass": 108.9047553, "composition": 0.48161}, + 110: {"mass": 109.9061102, "composition": 0.}, + 111: {"mass": 110.9052959, "composition": 0.}, + 112: {"mass": 111.9070486, "composition": 0.}, + 113: {"mass": 112.906573, "composition": 0.}, + 114: {"mass": 113.908823, "composition": 0.}, + 115: {"mass": 114.908767, "composition": 0.}, + 116: {"mass": 115.9113868, "composition": 0.}, + 117: {"mass": 116.911774, "composition": 0.}, + 118: {"mass": 117.9145955, "composition": 0.}, + 119: {"mass": 118.91557, "composition": 0.}, + 120: {"mass": 119.9187848, "composition": 0.}, + 121: {"mass": 120.920125, "composition": 0.}, + 122: {"mass": 121.923664, "composition": 0.}, + 123: {"mass": 122.925337, "composition": 0.}, + 124: {"mass": 123.92893, "composition": 0.}, + 125: {"mass": 124.93105, "composition": 0.}, + 126: {"mass": 125.93475, "composition": 0.}, + 127: {"mass": 126.93711, "composition": 0.}, + 128: {"mass": 127.94106, "composition": 0.}, + 129: {"mass": 128.94395, "composition": 0.}, + 130: {"mass": 129.9507, "composition": 0.}}, + 48: {95: {"mass": 94.94994, "composition": 0.}, + 96: {"mass": 95.94034, "composition": 0.}, + 97: {"mass": 96.9351, "composition": 0.}, + 98: {"mass": 97.927389, "composition": 0.}, + 99: {"mass": 98.9249258, "composition": 0.}, + 100: {"mass": 99.9203488, "composition": 0.}, + 101: {"mass": 100.9185862, "composition": 0.}, + 102: {"mass": 101.914482, "composition": 0.}, + 103: {"mass": 102.9134165, "composition": 0.}, + 104: {"mass": 103.9098564, "composition": 0.}, + 105: {"mass": 104.9094639, "composition": 0.}, + 106: {"mass": 105.9064599, "composition": 0.0125}, + 107: {"mass": 106.9066121, "composition": 0.}, + 108: {"mass": 107.9041834, "composition": 0.0089}, + 109: {"mass": 108.9049867, "composition": 0.}, + 110: {"mass": 109.90300661, "composition": 0.1249}, + 111: {"mass": 110.90418287, "composition": 0.128}, + 112: {"mass": 111.90276287, "composition": 0.2413}, + 113: {"mass": 112.90440813, "composition": 0.1222}, + 114: {"mass": 113.90336509, "composition": 0.2873}, + 115: {"mass": 114.90543751, "composition": 0.}, + 116: {"mass": 115.90476315, "composition": 0.0749}, + 117: {"mass": 116.907226, "composition": 0.}, + 118: {"mass": 117.906922, "composition": 0.}, + 119: {"mass": 118.909847, "composition": 0.}, + 120: {"mass": 119.9098681, "composition": 0.}, + 121: {"mass": 120.9129637, "composition": 0.}, + 122: {"mass": 121.9134591, "composition": 0.}, + 123: {"mass": 122.9168925, "composition": 0.}, + 124: {"mass": 123.9176574, "composition": 0.}, + 125: {"mass": 124.9212576, "composition": 0.}, + 126: {"mass": 125.9224291, "composition": 0.}, + 127: {"mass": 126.926472, "composition": 0.}, + 128: {"mass": 127.9278129, "composition": 0.}, + 129: {"mass": 128.93182, "composition": 0.}, + 130: {"mass": 129.93394, "composition": 0.}, + 131: {"mass": 130.9406, "composition": 0.}, + 132: {"mass": 131.94604, "composition": 0.}, + 133: {"mass": 132.95285, "composition": 0.}}, + 49: {97: {"mass": 96.94934, "composition": 0.}, + 98: {"mass": 97.94214, "composition": 0.}, + 99: {"mass": 98.93411, "composition": 0.}, + 100: {"mass": 99.93096, "composition": 0.}, + 101: {"mass": 100.92634, "composition": 0.}, + 102: {"mass": 101.9241071, "composition": 0.}, + 103: {"mass": 102.9198819, "composition": 0.}, + 104: {"mass": 103.9182145, "composition": 0.}, + 105: {"mass": 104.914502, "composition": 0.}, + 106: {"mass": 105.913464, "composition": 0.}, + 107: {"mass": 106.91029, "composition": 0.}, + 108: {"mass": 107.9096935, "composition": 0.}, + 109: {"mass": 108.9071514, "composition": 0.}, + 110: {"mass": 109.90717, "composition": 0.}, + 111: {"mass": 110.9051085, "composition": 0.}, + 112: {"mass": 111.9055377, "composition": 0.}, + 113: {"mass": 112.90406184, "composition": 0.0429}, + 114: {"mass": 113.90491791, "composition": 0.}, + 115: {"mass": 114.903878776, "composition": 0.9571}, + 116: {"mass": 115.90525999, "composition": 0.}, + 117: {"mass": 116.9045157, "composition": 0.}, + 118: {"mass": 117.9063566, "composition": 0.}, + 119: {"mass": 118.9058507, "composition": 0.}, + 120: {"mass": 119.907967, "composition": 0.}, + 121: {"mass": 120.907851, "composition": 0.}, + 122: {"mass": 121.910281, "composition": 0.}, + 123: {"mass": 122.910434, "composition": 0.}, + 124: {"mass": 123.913182, "composition": 0.}, + 125: {"mass": 124.913605, "composition": 0.}, + 126: {"mass": 125.916507, "composition": 0.}, + 127: {"mass": 126.917446, "composition": 0.}, + 128: {"mass": 127.9204, "composition": 0.}, + 129: {"mass": 128.9218053, "composition": 0.}, + 130: {"mass": 129.924977, "composition": 0.}, + 131: {"mass": 130.9269715, "composition": 0.}, + 132: {"mass": 131.933001, "composition": 0.}, + 133: {"mass": 132.93831, "composition": 0.}, + 134: {"mass": 133.94454, "composition": 0.}, + 135: {"mass": 134.95005, "composition": 0.}}, + 50: {99: {"mass": 98.94853, "composition": 0.}, + 100: {"mass": 99.9385, "composition": 0.}, + 101: {"mass": 100.93526, "composition": 0.}, + 102: {"mass": 101.93029, "composition": 0.}, + 103: {"mass": 102.928105, "composition": 0.}, + 104: {"mass": 103.9231052, "composition": 0.}, + 105: {"mass": 104.9212684, "composition": 0.}, + 106: {"mass": 105.9169574, "composition": 0.}, + 107: {"mass": 106.9157137, "composition": 0.}, + 108: {"mass": 107.9118943, "composition": 0.}, + 109: {"mass": 108.9112921, "composition": 0.}, + 110: {"mass": 109.907845, "composition": 0.}, + 111: {"mass": 110.9077401, "composition": 0.}, + 112: {"mass": 111.90482387, "composition": 0.0097}, + 113: {"mass": 112.9051757, "composition": 0.}, + 114: {"mass": 113.9027827, "composition": 0.0066}, + 115: {"mass": 114.903344699, "composition": 0.0034}, + 116: {"mass": 115.9017428, "composition": 0.1454}, + 117: {"mass": 116.90295398, "composition": 0.0768}, + 118: {"mass": 117.90160657, "composition": 0.2422}, + 119: {"mass": 118.90331117, "composition": 0.0859}, + 120: {"mass": 119.90220163, "composition": 0.3258}, + 121: {"mass": 120.9042426, "composition": 0.}, + 122: {"mass": 121.9034438, "composition": 0.0463}, + 123: {"mass": 122.9057252, "composition": 0.}, + 124: {"mass": 123.9052766, "composition": 0.0579}, + 125: {"mass": 124.9077864, "composition": 0.}, + 126: {"mass": 125.907659, "composition": 0.}, + 127: {"mass": 126.91039, "composition": 0.}, + 128: {"mass": 127.910507, "composition": 0.}, + 129: {"mass": 128.913465, "composition": 0.}, + 130: {"mass": 129.9139738, "composition": 0.}, + 131: {"mass": 130.917045, "composition": 0.}, + 132: {"mass": 131.9178267, "composition": 0.}, + 133: {"mass": 132.9239134, "composition": 0.}, + 134: {"mass": 133.9286821, "composition": 0.}, + 135: {"mass": 134.9349086, "composition": 0.}, + 136: {"mass": 135.93999, "composition": 0.}, + 137: {"mass": 136.94655, "composition": 0.}, + 138: {"mass": 137.95184, "composition": 0.}}, + 51: {103: {"mass": 102.93969, "composition": 0.}, + 104: {"mass": 103.93648, "composition": 0.}, + 105: {"mass": 104.931276, "composition": 0.}, + 106: {"mass": 105.928638, "composition": 0.}, + 107: {"mass": 106.9241506, "composition": 0.}, + 108: {"mass": 107.9222267, "composition": 0.}, + 109: {"mass": 108.9181411, "composition": 0.}, + 110: {"mass": 109.9168543, "composition": 0.}, + 111: {"mass": 110.9132182, "composition": 0.}, + 112: {"mass": 111.9124, "composition": 0.}, + 113: {"mass": 112.909375, "composition": 0.}, + 114: {"mass": 113.90929, "composition": 0.}, + 115: {"mass": 114.906598, "composition": 0.}, + 116: {"mass": 115.9067931, "composition": 0.}, + 117: {"mass": 116.9048415, "composition": 0.}, + 118: {"mass": 117.9055321, "composition": 0.}, + 119: {"mass": 118.9039455, "composition": 0.}, + 120: {"mass": 119.9050794, "composition": 0.}, + 121: {"mass": 120.903812, "composition": 0.5721}, + 122: {"mass": 121.9051699, "composition": 0.}, + 123: {"mass": 122.9042132, "composition": 0.4279}, + 124: {"mass": 123.905935, "composition": 0.}, + 125: {"mass": 124.905253, "composition": 0.}, + 126: {"mass": 125.907253, "composition": 0.}, + 127: {"mass": 126.9069243, "composition": 0.}, + 128: {"mass": 127.909146, "composition": 0.}, + 129: {"mass": 128.909147, "composition": 0.}, + 130: {"mass": 129.911662, "composition": 0.}, + 131: {"mass": 130.9119888, "composition": 0.}, + 132: {"mass": 131.9145077, "composition": 0.}, + 133: {"mass": 132.9152732, "composition": 0.}, + 134: {"mass": 133.9205357, "composition": 0.}, + 135: {"mass": 134.9251851, "composition": 0.}, + 136: {"mass": 135.9307459, "composition": 0.}, + 137: {"mass": 136.93555, "composition": 0.}, + 138: {"mass": 137.94145, "composition": 0.}, + 139: {"mass": 138.94655, "composition": 0.}, + 140: {"mass": 139.95283, "composition": 0.}}, + 52: {105: {"mass": 104.9433, "composition": 0.}, + 106: {"mass": 105.9375, "composition": 0.}, + 107: {"mass": 106.935012, "composition": 0.}, + 108: {"mass": 107.9293805, "composition": 0.}, + 109: {"mass": 108.9273045, "composition": 0.}, + 110: {"mass": 109.9224581, "composition": 0.}, + 111: {"mass": 110.9210006, "composition": 0.}, + 112: {"mass": 111.9167279, "composition": 0.}, + 113: {"mass": 112.915891, "composition": 0.}, + 114: {"mass": 113.912089, "composition": 0.}, + 115: {"mass": 114.911902, "composition": 0.}, + 116: {"mass": 115.90846, "composition": 0.}, + 117: {"mass": 116.908646, "composition": 0.}, + 118: {"mass": 117.905854, "composition": 0.}, + 119: {"mass": 118.9064071, "composition": 0.}, + 120: {"mass": 119.9040593, "composition": 0.0009}, + 121: {"mass": 120.904944, "composition": 0.}, + 122: {"mass": 121.9030435, "composition": 0.0255}, + 123: {"mass": 122.9042698, "composition": 0.0089}, + 124: {"mass": 123.9028171, "composition": 0.0474}, + 125: {"mass": 124.9044299, "composition": 0.0707}, + 126: {"mass": 125.9033109, "composition": 0.1884}, + 127: {"mass": 126.9052257, "composition": 0.}, + 128: {"mass": 127.90446128, "composition": 0.3174}, + 129: {"mass": 128.90659646, "composition": 0.}, + 130: {"mass": 129.906222748, "composition": 0.3408}, + 131: {"mass": 130.908522213, "composition": 0.}, + 132: {"mass": 131.9085467, "composition": 0.}, + 133: {"mass": 132.9109688, "composition": 0.}, + 134: {"mass": 133.911394, "composition": 0.}, + 135: {"mass": 134.9165557, "composition": 0.}, + 136: {"mass": 135.9201006, "composition": 0.}, + 137: {"mass": 136.9255989, "composition": 0.}, + 138: {"mass": 137.9294722, "composition": 0.}, + 139: {"mass": 138.9353672, "composition": 0.}, + 140: {"mass": 139.939499, "composition": 0.}, + 141: {"mass": 140.9458, "composition": 0.}, + 142: {"mass": 141.95022, "composition": 0.}, + 143: {"mass": 142.95676, "composition": 0.}}, + 53: {107: {"mass": 106.94678, "composition": 0.}, + 108: {"mass": 107.94348, "composition": 0.}, + 109: {"mass": 108.9380853, "composition": 0.}, + 110: {"mass": 109.935089, "composition": 0.}, + 111: {"mass": 110.9302692, "composition": 0.}, + 112: {"mass": 111.928005, "composition": 0.}, + 113: {"mass": 112.9236501, "composition": 0.}, + 114: {"mass": 113.92185, "composition": 0.}, + 115: {"mass": 114.918048, "composition": 0.}, + 116: {"mass": 115.91681, "composition": 0.}, + 117: {"mass": 116.913648, "composition": 0.}, + 118: {"mass": 117.913074, "composition": 0.}, + 119: {"mass": 118.910074, "composition": 0.}, + 120: {"mass": 119.910087, "composition": 0.}, + 121: {"mass": 120.9074051, "composition": 0.}, + 122: {"mass": 121.9075888, "composition": 0.}, + 123: {"mass": 122.9055885, "composition": 0.}, + 124: {"mass": 123.906209, "composition": 0.}, + 125: {"mass": 124.9046294, "composition": 0.}, + 126: {"mass": 125.9056233, "composition": 0.}, + 127: {"mass": 126.9044719, "composition": 1.}, + 128: {"mass": 127.9058086, "composition": 0.}, + 129: {"mass": 128.9049837, "composition": 0.}, + 130: {"mass": 129.9066702, "composition": 0.}, + 131: {"mass": 130.9061263, "composition": 0.}, + 132: {"mass": 131.9079935, "composition": 0.}, + 133: {"mass": 132.907797, "composition": 0.}, + 134: {"mass": 133.9097588, "composition": 0.}, + 135: {"mass": 134.9100488, "composition": 0.}, + 136: {"mass": 135.914604, "composition": 0.}, + 137: {"mass": 136.9180282, "composition": 0.}, + 138: {"mass": 137.9227264, "composition": 0.}, + 139: {"mass": 138.926506, "composition": 0.}, + 140: {"mass": 139.93173, "composition": 0.}, + 141: {"mass": 140.93569, "composition": 0.}, + 142: {"mass": 141.9412, "composition": 0.}, + 143: {"mass": 142.94565, "composition": 0.}, + 144: {"mass": 143.95139, "composition": 0.}, + 145: {"mass": 144.95605, "composition": 0.}}, + 54: {109: {"mass": 108.95043, "composition": 0.}, + 110: {"mass": 109.94426, "composition": 0.}, + 111: {"mass": 110.941607, "composition": 0.}, + 112: {"mass": 111.935559, "composition": 0.}, + 113: {"mass": 112.9332217, "composition": 0.}, + 114: {"mass": 113.92798, "composition": 0.}, + 115: {"mass": 114.926294, "composition": 0.}, + 116: {"mass": 115.921581, "composition": 0.}, + 117: {"mass": 116.920359, "composition": 0.}, + 118: {"mass": 117.916179, "composition": 0.}, + 119: {"mass": 118.915411, "composition": 0.}, + 120: {"mass": 119.911784, "composition": 0.}, + 121: {"mass": 120.911453, "composition": 0.}, + 122: {"mass": 121.908368, "composition": 0.}, + 123: {"mass": 122.908482, "composition": 0.}, + 124: {"mass": 123.905892, "composition": 0.000952}, + 125: {"mass": 124.9063944, "composition": 0.}, + 126: {"mass": 125.9042983, "composition": 0.00089}, + 127: {"mass": 126.9051829, "composition": 0.}, + 128: {"mass": 127.903531, "composition": 0.019102}, + 129: {"mass": 128.9047808611, "composition": 0.264006}, + 130: {"mass": 129.903509349, "composition": 0.04071}, + 131: {"mass": 130.90508406, "composition": 0.212324}, + 132: {"mass": 131.9041550856, "composition": 0.269086}, + 133: {"mass": 132.9059108, "composition": 0.}, + 134: {"mass": 133.90539466, "composition": 0.104357}, + 135: {"mass": 134.9072278, "composition": 0.}, + 136: {"mass": 135.907214484, "composition": 0.088573}, + 137: {"mass": 136.91155778, "composition": 0.}, + 138: {"mass": 137.9141463, "composition": 0.}, + 139: {"mass": 138.9187922, "composition": 0.}, + 140: {"mass": 139.9216458, "composition": 0.}, + 141: {"mass": 140.9267872, "composition": 0.}, + 142: {"mass": 141.9299731, "composition": 0.}, + 143: {"mass": 142.9353696, "composition": 0.}, + 144: {"mass": 143.9389451, "composition": 0.}, + 145: {"mass": 144.94472, "composition": 0.}, + 146: {"mass": 145.948518, "composition": 0.}, + 147: {"mass": 146.95426, "composition": 0.}, + 148: {"mass": 147.95813, "composition": 0.}}, + 55: {112: {"mass": 111.950309, "composition": 0.}, + 113: {"mass": 112.9444291, "composition": 0.}, + 114: {"mass": 113.941296, "composition": 0.}, + 115: {"mass": 114.93591, "composition": 0.}, + 116: {"mass": 115.93337, "composition": 0.}, + 117: {"mass": 116.928617, "composition": 0.}, + 118: {"mass": 117.92656, "composition": 0.}, + 119: {"mass": 118.922377, "composition": 0.}, + 120: {"mass": 119.920677, "composition": 0.}, + 121: {"mass": 120.917227, "composition": 0.}, + 122: {"mass": 121.916108, "composition": 0.}, + 123: {"mass": 122.912996, "composition": 0.}, + 124: {"mass": 123.9122578, "composition": 0.}, + 125: {"mass": 124.909728, "composition": 0.}, + 126: {"mass": 125.909446, "composition": 0.}, + 127: {"mass": 126.9074174, "composition": 0.}, + 128: {"mass": 127.9077487, "composition": 0.}, + 129: {"mass": 128.9060657, "composition": 0.}, + 130: {"mass": 129.9067093, "composition": 0.}, + 131: {"mass": 130.9054649, "composition": 0.}, + 132: {"mass": 131.9064339, "composition": 0.}, + 133: {"mass": 132.905451961, "composition": 1.}, + 134: {"mass": 133.906718503, "composition": 0.}, + 135: {"mass": 134.905977, "composition": 0.}, + 136: {"mass": 135.9073114, "composition": 0.}, + 137: {"mass": 136.90708923, "composition": 0.}, + 138: {"mass": 137.9110171, "composition": 0.}, + 139: {"mass": 138.9133638, "composition": 0.}, + 140: {"mass": 139.9172831, "composition": 0.}, + 141: {"mass": 140.9200455, "composition": 0.}, + 142: {"mass": 141.924296, "composition": 0.}, + 143: {"mass": 142.927349, "composition": 0.}, + 144: {"mass": 143.932076, "composition": 0.}, + 145: {"mass": 144.935527, "composition": 0.}, + 146: {"mass": 145.940344, "composition": 0.}, + 147: {"mass": 146.944156, "composition": 0.}, + 148: {"mass": 147.94923, "composition": 0.}, + 149: {"mass": 148.95302, "composition": 0.}, + 150: {"mass": 149.95833, "composition": 0.}, + 151: {"mass": 150.96258, "composition": 0.}}, + 56: {114: {"mass": 113.95066, "composition": 0.}, + 115: {"mass": 114.94737, "composition": 0.}, + 116: {"mass": 115.94128, "composition": 0.}, + 117: {"mass": 116.93814, "composition": 0.}, + 118: {"mass": 117.93306, "composition": 0.}, + 119: {"mass": 118.93066, "composition": 0.}, + 120: {"mass": 119.92605, "composition": 0.}, + 121: {"mass": 120.92405, "composition": 0.}, + 122: {"mass": 121.919904, "composition": 0.}, + 123: {"mass": 122.918781, "composition": 0.}, + 124: {"mass": 123.915094, "composition": 0.}, + 125: {"mass": 124.914472, "composition": 0.}, + 126: {"mass": 125.91125, "composition": 0.}, + 127: {"mass": 126.911091, "composition": 0.}, + 128: {"mass": 127.908342, "composition": 0.}, + 129: {"mass": 128.908681, "composition": 0.}, + 130: {"mass": 129.9063207, "composition": 0.00106}, + 131: {"mass": 130.906941, "composition": 0.}, + 132: {"mass": 131.9050611, "composition": 0.00101}, + 133: {"mass": 132.9060074, "composition": 0.}, + 134: {"mass": 133.90450818, "composition": 0.02417}, + 135: {"mass": 134.90568838, "composition": 0.06592}, + 136: {"mass": 135.90457573, "composition": 0.07854}, + 137: {"mass": 136.90582714, "composition": 0.11232}, + 138: {"mass": 137.905247, "composition": 0.71698}, + 139: {"mass": 138.9088411, "composition": 0.}, + 140: {"mass": 139.9106057, "composition": 0.}, + 141: {"mass": 140.9144033, "composition": 0.}, + 142: {"mass": 141.9164324, "composition": 0.}, + 143: {"mass": 142.9206253, "composition": 0.}, + 144: {"mass": 143.9229549, "composition": 0.}, + 145: {"mass": 144.9275184, "composition": 0.}, + 146: {"mass": 145.930284, "composition": 0.}, + 147: {"mass": 146.935304, "composition": 0.}, + 148: {"mass": 147.938171, "composition": 0.}, + 149: {"mass": 148.94308, "composition": 0.}, + 150: {"mass": 149.94605, "composition": 0.}, + 151: {"mass": 150.95127, "composition": 0.}, + 152: {"mass": 151.95481, "composition": 0.}, + 153: {"mass": 152.96036, "composition": 0.}}, + 57: {116: {"mass": 115.9563, "composition": 0.}, + 117: {"mass": 116.94999, "composition": 0.}, + 118: {"mass": 117.94673, "composition": 0.}, + 119: {"mass": 118.94099, "composition": 0.}, + 120: {"mass": 119.93807, "composition": 0.}, + 121: {"mass": 120.93315, "composition": 0.}, + 122: {"mass": 121.93071, "composition": 0.}, + 123: {"mass": 122.9263, "composition": 0.}, + 124: {"mass": 123.924574, "composition": 0.}, + 125: {"mass": 124.920816, "composition": 0.}, + 126: {"mass": 125.919513, "composition": 0.}, + 127: {"mass": 126.916375, "composition": 0.}, + 128: {"mass": 127.915592, "composition": 0.}, + 129: {"mass": 128.912694, "composition": 0.}, + 130: {"mass": 129.912369, "composition": 0.}, + 131: {"mass": 130.91007, "composition": 0.}, + 132: {"mass": 131.910119, "composition": 0.}, + 133: {"mass": 132.908218, "composition": 0.}, + 134: {"mass": 133.908514, "composition": 0.}, + 135: {"mass": 134.906984, "composition": 0.}, + 136: {"mass": 135.907635, "composition": 0.}, + 137: {"mass": 136.9064504, "composition": 0.}, + 138: {"mass": 137.9071149, "composition": 0.0008881}, + 139: {"mass": 138.9063563, "composition": 0.9991119}, + 140: {"mass": 139.9094806, "composition": 0.}, + 141: {"mass": 140.910966, "composition": 0.}, + 142: {"mass": 141.9140909, "composition": 0.}, + 143: {"mass": 142.9160795, "composition": 0.}, + 144: {"mass": 143.919646, "composition": 0.}, + 145: {"mass": 144.921808, "composition": 0.}, + 146: {"mass": 145.925875, "composition": 0.}, + 147: {"mass": 146.928418, "composition": 0.}, + 148: {"mass": 147.932679, "composition": 0.}, + 149: {"mass": 148.93535, "composition": 0.}, + 150: {"mass": 149.93947, "composition": 0.}, + 151: {"mass": 150.94232, "composition": 0.}, + 152: {"mass": 151.94682, "composition": 0.}, + 153: {"mass": 152.95036, "composition": 0.}, + 154: {"mass": 153.95517, "composition": 0.}, + 155: {"mass": 154.95901, "composition": 0.}}, + 58: {119: {"mass": 118.95271, "composition": 0.}, + 120: {"mass": 119.94654, "composition": 0.}, + 121: {"mass": 120.94335, "composition": 0.}, + 122: {"mass": 121.93787, "composition": 0.}, + 123: {"mass": 122.93528, "composition": 0.}, + 124: {"mass": 123.93031, "composition": 0.}, + 125: {"mass": 124.92844, "composition": 0.}, + 126: {"mass": 125.923971, "composition": 0.}, + 127: {"mass": 126.922727, "composition": 0.}, + 128: {"mass": 127.918911, "composition": 0.}, + 129: {"mass": 128.918102, "composition": 0.}, + 130: {"mass": 129.914736, "composition": 0.}, + 131: {"mass": 130.914429, "composition": 0.}, + 132: {"mass": 131.911464, "composition": 0.}, + 133: {"mass": 132.91152, "composition": 0.}, + 134: {"mass": 133.908928, "composition": 0.}, + 135: {"mass": 134.909161, "composition": 0.}, + 136: {"mass": 135.90712921, "composition": 0.00185}, + 137: {"mass": 136.90776236, "composition": 0.}, + 138: {"mass": 137.905991, "composition": 0.00251}, + 139: {"mass": 138.9066551, "composition": 0.}, + 140: {"mass": 139.9054431, "composition": 0.8845}, + 141: {"mass": 140.9082807, "composition": 0.}, + 142: {"mass": 141.9092504, "composition": 0.11114}, + 143: {"mass": 142.9123921, "composition": 0.}, + 144: {"mass": 143.9136529, "composition": 0.}, + 145: {"mass": 144.917265, "composition": 0.}, + 146: {"mass": 145.918802, "composition": 0.}, + 147: {"mass": 146.9226899, "composition": 0.}, + 148: {"mass": 147.924424, "composition": 0.}, + 149: {"mass": 148.928427, "composition": 0.}, + 150: {"mass": 149.930384, "composition": 0.}, + 151: {"mass": 150.934272, "composition": 0.}, + 152: {"mass": 151.9366, "composition": 0.}, + 153: {"mass": 152.94093, "composition": 0.}, + 154: {"mass": 153.9438, "composition": 0.}, + 155: {"mass": 154.94855, "composition": 0.}, + 156: {"mass": 155.95183, "composition": 0.}, + 157: {"mass": 156.95705, "composition": 0.}}, + 59: {121: {"mass": 120.95532, "composition": 0.}, + 122: {"mass": 121.95175, "composition": 0.}, + 123: {"mass": 122.94596, "composition": 0.}, + 124: {"mass": 123.94294, "composition": 0.}, + 125: {"mass": 124.9377, "composition": 0.}, + 126: {"mass": 125.93524, "composition": 0.}, + 127: {"mass": 126.93071, "composition": 0.}, + 128: {"mass": 127.928791, "composition": 0.}, + 129: {"mass": 128.925095, "composition": 0.}, + 130: {"mass": 129.92359, "composition": 0.}, + 131: {"mass": 130.920235, "composition": 0.}, + 132: {"mass": 131.919255, "composition": 0.}, + 133: {"mass": 132.916331, "composition": 0.}, + 134: {"mass": 133.915697, "composition": 0.}, + 135: {"mass": 134.913112, "composition": 0.}, + 136: {"mass": 135.912677, "composition": 0.}, + 137: {"mass": 136.9106792, "composition": 0.}, + 138: {"mass": 137.910754, "composition": 0.}, + 139: {"mass": 138.9089408, "composition": 0.}, + 140: {"mass": 139.9090803, "composition": 0.}, + 141: {"mass": 140.9076576, "composition": 1.}, + 142: {"mass": 141.9100496, "composition": 0.}, + 143: {"mass": 142.9108228, "composition": 0.}, + 144: {"mass": 143.9133109, "composition": 0.}, + 145: {"mass": 144.9145182, "composition": 0.}, + 146: {"mass": 145.91768, "composition": 0.}, + 147: {"mass": 146.919008, "composition": 0.}, + 148: {"mass": 147.92213, "composition": 0.}, + 149: {"mass": 148.923736, "composition": 0.}, + 150: {"mass": 149.9266765, "composition": 0.}, + 151: {"mass": 150.928309, "composition": 0.}, + 152: {"mass": 151.931553, "composition": 0.}, + 153: {"mass": 152.933904, "composition": 0.}, + 154: {"mass": 153.93753, "composition": 0.}, + 155: {"mass": 154.940509, "composition": 0.}, + 156: {"mass": 155.94464, "composition": 0.}, + 157: {"mass": 156.94789, "composition": 0.}, + 158: {"mass": 157.95241, "composition": 0.}, + 159: {"mass": 158.95589, "composition": 0.}}, + 60: {124: {"mass": 123.9522, "composition": 0.}, + 125: {"mass": 124.9489, "composition": 0.}, + 126: {"mass": 125.94311, "composition": 0.}, + 127: {"mass": 126.94038, "composition": 0.}, + 128: {"mass": 127.93525, "composition": 0.}, + 129: {"mass": 128.9331, "composition": 0.}, + 130: {"mass": 129.928506, "composition": 0.}, + 131: {"mass": 130.927248, "composition": 0.}, + 132: {"mass": 131.923321, "composition": 0.}, + 133: {"mass": 132.922348, "composition": 0.}, + 134: {"mass": 133.91879, "composition": 0.}, + 135: {"mass": 134.918181, "composition": 0.}, + 136: {"mass": 135.914976, "composition": 0.}, + 137: {"mass": 136.914562, "composition": 0.}, + 138: {"mass": 137.91195, "composition": 0.}, + 139: {"mass": 138.911954, "composition": 0.}, + 140: {"mass": 139.90955, "composition": 0.}, + 141: {"mass": 140.9096147, "composition": 0.}, + 142: {"mass": 141.907729, "composition": 0.27152}, + 143: {"mass": 142.90982, "composition": 0.12174}, + 144: {"mass": 143.910093, "composition": 0.23798}, + 145: {"mass": 144.9125793, "composition": 0.08293}, + 146: {"mass": 145.9131226, "composition": 0.17189}, + 147: {"mass": 146.9161061, "composition": 0.}, + 148: {"mass": 147.9168993, "composition": 0.05756}, + 149: {"mass": 148.9201548, "composition": 0.}, + 150: {"mass": 149.9209022, "composition": 0.05638}, + 151: {"mass": 150.9238403, "composition": 0.}, + 152: {"mass": 151.924692, "composition": 0.}, + 153: {"mass": 152.927718, "composition": 0.}, + 154: {"mass": 153.92948, "composition": 0.}, + 155: {"mass": 154.9331357, "composition": 0.}, + 156: {"mass": 155.93508, "composition": 0.}, + 157: {"mass": 156.939386, "composition": 0.}, + 158: {"mass": 157.94197, "composition": 0.}, + 159: {"mass": 158.94653, "composition": 0.}, + 160: {"mass": 159.9494, "composition": 0.}, + 161: {"mass": 160.95428, "composition": 0.}}, + 61: {126: {"mass": 125.95792, "composition": 0.}, + 127: {"mass": 126.95192, "composition": 0.}, + 128: {"mass": 127.9487, "composition": 0.}, + 129: {"mass": 128.94323, "composition": 0.}, + 130: {"mass": 129.94053, "composition": 0.}, + 131: {"mass": 130.93567, "composition": 0.}, + 132: {"mass": 131.93384, "composition": 0.}, + 133: {"mass": 132.929782, "composition": 0.}, + 134: {"mass": 133.928353, "composition": 0.}, + 135: {"mass": 134.924823, "composition": 0.}, + 136: {"mass": 135.923585, "composition": 0.}, + 137: {"mass": 136.92048, "composition": 0.}, + 138: {"mass": 137.919548, "composition": 0.}, + 139: {"mass": 138.9168, "composition": 0.}, + 140: {"mass": 139.91604, "composition": 0.}, + 141: {"mass": 140.913555, "composition": 0.}, + 142: {"mass": 141.91289, "composition": 0.}, + 143: {"mass": 142.9109383, "composition": 0.}, + 144: {"mass": 143.9125964, "composition": 0.}, + 145: {"mass": 144.9127559, "composition": 0.}, + 146: {"mass": 145.9147024, "composition": 0.}, + 147: {"mass": 146.915145, "composition": 0.}, + 148: {"mass": 147.9174819, "composition": 0.}, + 149: {"mass": 148.9183423, "composition": 0.}, + 150: {"mass": 149.920991, "composition": 0.}, + 151: {"mass": 150.9212175, "composition": 0.}, + 152: {"mass": 151.923506, "composition": 0.}, + 153: {"mass": 152.9241567, "composition": 0.}, + 154: {"mass": 153.926472, "composition": 0.}, + 155: {"mass": 154.928137, "composition": 0.}, + 156: {"mass": 155.9311175, "composition": 0.}, + 157: {"mass": 156.9331214, "composition": 0.}, + 158: {"mass": 157.936565, "composition": 0.}, + 159: {"mass": 158.939287, "composition": 0.}, + 160: {"mass": 159.9431, "composition": 0.}, + 161: {"mass": 160.94607, "composition": 0.}, + 162: {"mass": 161.95022, "composition": 0.}, + 163: {"mass": 162.95357, "composition": 0.}}, + 62: {128: {"mass": 127.95842, "composition": 0.}, + 129: {"mass": 128.95476, "composition": 0.}, + 130: {"mass": 129.949, "composition": 0.}, + 131: {"mass": 130.94618, "composition": 0.}, + 132: {"mass": 131.94087, "composition": 0.}, + 133: {"mass": 132.93856, "composition": 0.}, + 134: {"mass": 133.93411, "composition": 0.}, + 135: {"mass": 134.93252, "composition": 0.}, + 136: {"mass": 135.928276, "composition": 0.}, + 137: {"mass": 136.926971, "composition": 0.}, + 138: {"mass": 137.923244, "composition": 0.}, + 139: {"mass": 138.922297, "composition": 0.}, + 140: {"mass": 139.918995, "composition": 0.}, + 141: {"mass": 140.9184816, "composition": 0.}, + 142: {"mass": 141.9152044, "composition": 0.}, + 143: {"mass": 142.9146353, "composition": 0.}, + 144: {"mass": 143.9120065, "composition": 0.0307}, + 145: {"mass": 144.9134173, "composition": 0.}, + 146: {"mass": 145.913047, "composition": 0.}, + 147: {"mass": 146.9149044, "composition": 0.1499}, + 148: {"mass": 147.9148292, "composition": 0.1124}, + 149: {"mass": 148.9171921, "composition": 0.1382}, + 150: {"mass": 149.9172829, "composition": 0.0738}, + 151: {"mass": 150.9199398, "composition": 0.}, + 152: {"mass": 151.9197397, "composition": 0.2675}, + 153: {"mass": 152.9221047, "composition": 0.}, + 154: {"mass": 153.9222169, "composition": 0.2275}, + 155: {"mass": 154.9246477, "composition": 0.}, + 156: {"mass": 155.925536, "composition": 0.}, + 157: {"mass": 156.9284187, "composition": 0.}, + 158: {"mass": 157.929951, "composition": 0.}, + 159: {"mass": 158.9332172, "composition": 0.}, + 160: {"mass": 159.9353353, "composition": 0.}, + 161: {"mass": 160.9391602, "composition": 0.}, + 162: {"mass": 161.94146, "composition": 0.}, + 163: {"mass": 162.94555, "composition": 0.}, + 164: {"mass": 163.94836, "composition": 0.}, + 165: {"mass": 164.95297, "composition": 0.}}, + 63: {130: {"mass": 129.96369, "composition": 0.}, + 131: {"mass": 130.95784, "composition": 0.}, + 132: {"mass": 131.95467, "composition": 0.}, + 133: {"mass": 132.94929, "composition": 0.}, + 134: {"mass": 133.9464, "composition": 0.}, + 135: {"mass": 134.94187, "composition": 0.}, + 136: {"mass": 135.93962, "composition": 0.}, + 137: {"mass": 136.93546, "composition": 0.}, + 138: {"mass": 137.933709, "composition": 0.}, + 139: {"mass": 138.929792, "composition": 0.}, + 140: {"mass": 139.928088, "composition": 0.}, + 141: {"mass": 140.924932, "composition": 0.}, + 142: {"mass": 141.923442, "composition": 0.}, + 143: {"mass": 142.920299, "composition": 0.}, + 144: {"mass": 143.91882, "composition": 0.}, + 145: {"mass": 144.9162726, "composition": 0.}, + 146: {"mass": 145.917211, "composition": 0.}, + 147: {"mass": 146.9167527, "composition": 0.}, + 148: {"mass": 147.918089, "composition": 0.}, + 149: {"mass": 148.9179378, "composition": 0.}, + 150: {"mass": 149.9197077, "composition": 0.}, + 151: {"mass": 150.9198578, "composition": 0.4781}, + 152: {"mass": 151.9217522, "composition": 0.}, + 153: {"mass": 152.921238, "composition": 0.5219}, + 154: {"mass": 153.922987, "composition": 0.}, + 155: {"mass": 154.9229011, "composition": 0.}, + 156: {"mass": 155.9247605, "composition": 0.}, + 157: {"mass": 156.9254334, "composition": 0.}, + 158: {"mass": 157.927799, "composition": 0.}, + 159: {"mass": 158.9291001, "composition": 0.}, + 160: {"mass": 159.931851, "composition": 0.}, + 161: {"mass": 160.933664, "composition": 0.}, + 162: {"mass": 161.936989, "composition": 0.}, + 163: {"mass": 162.939196, "composition": 0.}, + 164: {"mass": 163.94274, "composition": 0.}, + 165: {"mass": 164.94559, "composition": 0.}, + 166: {"mass": 165.94962, "composition": 0.}, + 167: {"mass": 166.95289, "composition": 0.}}, + 64: {133: {"mass": 132.96133, "composition": 0.}, + 134: {"mass": 133.95566, "composition": 0.}, + 135: {"mass": 134.95245, "composition": 0.}, + 136: {"mass": 135.9473, "composition": 0.}, + 137: {"mass": 136.94502, "composition": 0.}, + 138: {"mass": 137.94025, "composition": 0.}, + 139: {"mass": 138.93813, "composition": 0.}, + 140: {"mass": 139.933674, "composition": 0.}, + 141: {"mass": 140.932126, "composition": 0.}, + 142: {"mass": 141.928116, "composition": 0.}, + 143: {"mass": 142.92675, "composition": 0.}, + 144: {"mass": 143.922963, "composition": 0.}, + 145: {"mass": 144.921713, "composition": 0.}, + 146: {"mass": 145.9183188, "composition": 0.}, + 147: {"mass": 146.9191014, "composition": 0.}, + 148: {"mass": 147.9181215, "composition": 0.}, + 149: {"mass": 148.9193481, "composition": 0.}, + 150: {"mass": 149.9186644, "composition": 0.}, + 151: {"mass": 150.920356, "composition": 0.}, + 152: {"mass": 151.9197995, "composition": 0.002}, + 153: {"mass": 152.921758, "composition": 0.}, + 154: {"mass": 153.9208741, "composition": 0.0218}, + 155: {"mass": 154.9226305, "composition": 0.148}, + 156: {"mass": 155.9221312, "composition": 0.2047}, + 157: {"mass": 156.9239686, "composition": 0.1565}, + 158: {"mass": 157.9241123, "composition": 0.2484}, + 159: {"mass": 158.926397, "composition": 0.}, + 160: {"mass": 159.9270624, "composition": 0.2186}, + 161: {"mass": 160.9296775, "composition": 0.}, + 162: {"mass": 161.930993, "composition": 0.}, + 163: {"mass": 162.9341769, "composition": 0.}, + 164: {"mass": 163.93583, "composition": 0.}, + 165: {"mass": 164.93936, "composition": 0.}, + 166: {"mass": 165.94146, "composition": 0.}, + 167: {"mass": 166.94545, "composition": 0.}, + 168: {"mass": 167.94808, "composition": 0.}, + 169: {"mass": 168.9526, "composition": 0.}}, + 65: {135: {"mass": 134.96476, "composition": 0.}, + 136: {"mass": 135.96129, "composition": 0.}, + 137: {"mass": 136.95602, "composition": 0.}, + 138: {"mass": 137.95312, "composition": 0.}, + 139: {"mass": 138.94833, "composition": 0.}, + 140: {"mass": 139.94581, "composition": 0.}, + 141: {"mass": 140.94145, "composition": 0.}, + 142: {"mass": 141.93928, "composition": 0.}, + 143: {"mass": 142.935137, "composition": 0.}, + 144: {"mass": 143.933045, "composition": 0.}, + 145: {"mass": 144.92882, "composition": 0.}, + 146: {"mass": 145.927253, "composition": 0.}, + 147: {"mass": 146.9240548, "composition": 0.}, + 148: {"mass": 147.924282, "composition": 0.}, + 149: {"mass": 148.9232535, "composition": 0.}, + 150: {"mass": 149.9236649, "composition": 0.}, + 151: {"mass": 150.9231096, "composition": 0.}, + 152: {"mass": 151.924083, "composition": 0.}, + 153: {"mass": 152.9234424, "composition": 0.}, + 154: {"mass": 153.924685, "composition": 0.}, + 155: {"mass": 154.923511, "composition": 0.}, + 156: {"mass": 155.9247552, "composition": 0.}, + 157: {"mass": 156.924033, "composition": 0.}, + 158: {"mass": 157.9254209, "composition": 0.}, + 159: {"mass": 158.9253547, "composition": 1.}, + 160: {"mass": 159.9271756, "composition": 0.}, + 161: {"mass": 160.9275778, "composition": 0.}, + 162: {"mass": 161.929495, "composition": 0.}, + 163: {"mass": 162.9306547, "composition": 0.}, + 164: {"mass": 163.93336, "composition": 0.}, + 165: {"mass": 164.93498, "composition": 0.}, + 166: {"mass": 165.93786, "composition": 0.}, + 167: {"mass": 166.93996, "composition": 0.}, + 168: {"mass": 167.9434, "composition": 0.}, + 169: {"mass": 168.94597, "composition": 0.}, + 170: {"mass": 169.94984, "composition": 0.}, + 171: {"mass": 170.95273, "composition": 0.}}, + 66: {138: {"mass": 137.9625, "composition": 0.}, + 139: {"mass": 138.95959, "composition": 0.}, + 140: {"mass": 139.95402, "composition": 0.}, + 141: {"mass": 140.95128, "composition": 0.}, + 142: {"mass": 141.94619, "composition": 0.}, + 143: {"mass": 142.943994, "composition": 0.}, + 144: {"mass": 143.9392695, "composition": 0.}, + 145: {"mass": 144.937474, "composition": 0.}, + 146: {"mass": 145.9328445, "composition": 0.}, + 147: {"mass": 146.9310827, "composition": 0.}, + 148: {"mass": 147.927157, "composition": 0.}, + 149: {"mass": 148.927322, "composition": 0.}, + 150: {"mass": 149.9255933, "composition": 0.}, + 151: {"mass": 150.9261916, "composition": 0.}, + 152: {"mass": 151.9247253, "composition": 0.}, + 153: {"mass": 152.9257724, "composition": 0.}, + 154: {"mass": 153.9244293, "composition": 0.}, + 155: {"mass": 154.925759, "composition": 0.}, + 156: {"mass": 155.9242847, "composition": 0.00056}, + 157: {"mass": 156.9254707, "composition": 0.}, + 158: {"mass": 157.9244159, "composition": 0.00095}, + 159: {"mass": 158.925747, "composition": 0.}, + 160: {"mass": 159.9252046, "composition": 0.02329}, + 161: {"mass": 160.9269405, "composition": 0.18889}, + 162: {"mass": 161.9268056, "composition": 0.25475}, + 163: {"mass": 162.9287383, "composition": 0.24896}, + 164: {"mass": 163.9291819, "composition": 0.2826}, + 165: {"mass": 164.9317105, "composition": 0.}, + 166: {"mass": 165.9328139, "composition": 0.}, + 167: {"mass": 166.935661, "composition": 0.}, + 168: {"mass": 167.93713, "composition": 0.}, + 169: {"mass": 168.94031, "composition": 0.}, + 170: {"mass": 169.94239, "composition": 0.}, + 171: {"mass": 170.94612, "composition": 0.}, + 172: {"mass": 171.94846, "composition": 0.}, + 173: {"mass": 172.95283, "composition": 0.}}, + 67: {140: {"mass": 139.96859, "composition": 0.}, + 141: {"mass": 140.96311, "composition": 0.}, + 142: {"mass": 141.96001, "composition": 0.}, + 143: {"mass": 142.95486, "composition": 0.}, + 144: {"mass": 143.9521097, "composition": 0.}, + 145: {"mass": 144.9472674, "composition": 0.}, + 146: {"mass": 145.9449935, "composition": 0.}, + 147: {"mass": 146.9401423, "composition": 0.}, + 148: {"mass": 147.937744, "composition": 0.}, + 149: {"mass": 148.933803, "composition": 0.}, + 150: {"mass": 149.933498, "composition": 0.}, + 151: {"mass": 150.9316983, "composition": 0.}, + 152: {"mass": 151.931724, "composition": 0.}, + 153: {"mass": 152.9302064, "composition": 0.}, + 154: {"mass": 153.9306068, "composition": 0.}, + 155: {"mass": 154.929104, "composition": 0.}, + 156: {"mass": 155.929706, "composition": 0.}, + 157: {"mass": 156.928254, "composition": 0.}, + 158: {"mass": 157.928946, "composition": 0.}, + 159: {"mass": 158.9277197, "composition": 0.}, + 160: {"mass": 159.928737, "composition": 0.}, + 161: {"mass": 160.9278615, "composition": 0.}, + 162: {"mass": 161.9291023, "composition": 0.}, + 163: {"mass": 162.928741, "composition": 0.}, + 164: {"mass": 163.9302403, "composition": 0.}, + 165: {"mass": 164.9303288, "composition": 1.}, + 166: {"mass": 165.9322909, "composition": 0.}, + 167: {"mass": 166.9331385, "composition": 0.}, + 168: {"mass": 167.935522, "composition": 0.}, + 169: {"mass": 168.936878, "composition": 0.}, + 170: {"mass": 169.939625, "composition": 0.}, + 171: {"mass": 170.94147, "composition": 0.}, + 172: {"mass": 171.94473, "composition": 0.}, + 173: {"mass": 172.94702, "composition": 0.}, + 174: {"mass": 173.95095, "composition": 0.}, + 175: {"mass": 174.95362, "composition": 0.}}, + 68: {142: {"mass": 141.9701, "composition": 0.}, + 143: {"mass": 142.96662, "composition": 0.}, + 144: {"mass": 143.9607, "composition": 0.}, + 145: {"mass": 144.95805, "composition": 0.}, + 146: {"mass": 145.9524184, "composition": 0.}, + 147: {"mass": 146.949964, "composition": 0.}, + 148: {"mass": 147.944735, "composition": 0.}, + 149: {"mass": 148.942306, "composition": 0.}, + 150: {"mass": 149.937916, "composition": 0.}, + 151: {"mass": 150.937449, "composition": 0.}, + 152: {"mass": 151.935057, "composition": 0.}, + 153: {"mass": 152.93508, "composition": 0.}, + 154: {"mass": 153.9327908, "composition": 0.}, + 155: {"mass": 154.9332159, "composition": 0.}, + 156: {"mass": 155.931067, "composition": 0.}, + 157: {"mass": 156.931949, "composition": 0.}, + 158: {"mass": 157.929893, "composition": 0.}, + 159: {"mass": 158.9306918, "composition": 0.}, + 160: {"mass": 159.929077, "composition": 0.}, + 161: {"mass": 160.9300046, "composition": 0.}, + 162: {"mass": 161.9287884, "composition": 0.00139}, + 163: {"mass": 162.9300408, "composition": 0.}, + 164: {"mass": 163.9292088, "composition": 0.01601}, + 165: {"mass": 164.9307345, "composition": 0.}, + 166: {"mass": 165.9302995, "composition": 0.33503}, + 167: {"mass": 166.9320546, "composition": 0.22869}, + 168: {"mass": 167.9323767, "composition": 0.26978}, + 169: {"mass": 168.9345968, "composition": 0.}, + 170: {"mass": 169.9354702, "composition": 0.1491}, + 171: {"mass": 170.9380357, "composition": 0.}, + 172: {"mass": 171.9393619, "composition": 0.}, + 173: {"mass": 172.9424, "composition": 0.}, + 174: {"mass": 173.94423, "composition": 0.}, + 175: {"mass": 174.94777, "composition": 0.}, + 176: {"mass": 175.94994, "composition": 0.}, + 177: {"mass": 176.95399, "composition": 0.}}, + 69: {144: {"mass": 143.97628, "composition": 0.}, + 145: {"mass": 144.97039, "composition": 0.}, + 146: {"mass": 145.96684, "composition": 0.}, + 147: {"mass": 146.9613799, "composition": 0.}, + 148: {"mass": 147.958384, "composition": 0.}, + 149: {"mass": 148.95289, "composition": 0.}, + 150: {"mass": 149.95009, "composition": 0.}, + 151: {"mass": 150.945488, "composition": 0.}, + 152: {"mass": 151.944422, "composition": 0.}, + 153: {"mass": 152.94204, "composition": 0.}, + 154: {"mass": 153.94157, "composition": 0.}, + 155: {"mass": 154.93921, "composition": 0.}, + 156: {"mass": 155.938992, "composition": 0.}, + 157: {"mass": 156.936944, "composition": 0.}, + 158: {"mass": 157.93698, "composition": 0.}, + 159: {"mass": 158.934975, "composition": 0.}, + 160: {"mass": 159.935263, "composition": 0.}, + 161: {"mass": 160.933549, "composition": 0.}, + 162: {"mass": 161.934002, "composition": 0.}, + 163: {"mass": 162.9326592, "composition": 0.}, + 164: {"mass": 163.933544, "composition": 0.}, + 165: {"mass": 164.9324431, "composition": 0.}, + 166: {"mass": 165.933561, "composition": 0.}, + 167: {"mass": 166.9328562, "composition": 0.}, + 168: {"mass": 167.9341774, "composition": 0.}, + 169: {"mass": 168.9342179, "composition": 1.}, + 170: {"mass": 169.935806, "composition": 0.}, + 171: {"mass": 170.9364339, "composition": 0.}, + 172: {"mass": 171.9384055, "composition": 0.}, + 173: {"mass": 172.9396084, "composition": 0.}, + 174: {"mass": 173.942173, "composition": 0.}, + 175: {"mass": 174.943841, "composition": 0.}, + 176: {"mass": 175.947, "composition": 0.}, + 177: {"mass": 176.94904, "composition": 0.}, + 178: {"mass": 177.95264, "composition": 0.}, + 179: {"mass": 178.95534, "composition": 0.}}, + 70: {148: {"mass": 147.96758, "composition": 0.}, + 149: {"mass": 148.96436, "composition": 0.}, + 150: {"mass": 149.95852, "composition": 0.}, + 151: {"mass": 150.9554, "composition": 0.}, + 152: {"mass": 151.95027, "composition": 0.}, + 153: {"mass": 152.94932, "composition": 0.}, + 154: {"mass": 153.946396, "composition": 0.}, + 155: {"mass": 154.945783, "composition": 0.}, + 156: {"mass": 155.942825, "composition": 0.}, + 157: {"mass": 156.942645, "composition": 0.}, + 158: {"mass": 157.9398705, "composition": 0.}, + 159: {"mass": 158.940055, "composition": 0.}, + 160: {"mass": 159.937557, "composition": 0.}, + 161: {"mass": 160.937907, "composition": 0.}, + 162: {"mass": 161.935774, "composition": 0.}, + 163: {"mass": 162.93634, "composition": 0.}, + 164: {"mass": 163.934495, "composition": 0.}, + 165: {"mass": 164.93527, "composition": 0.}, + 166: {"mass": 165.9338747, "composition": 0.}, + 167: {"mass": 166.934953, "composition": 0.}, + 168: {"mass": 167.9338896, "composition": 0.00123}, + 169: {"mass": 168.9351825, "composition": 0.}, + 170: {"mass": 169.9347664, "composition": 0.02982}, + 171: {"mass": 170.9363302, "composition": 0.1409}, + 172: {"mass": 171.9363859, "composition": 0.2168}, + 173: {"mass": 172.9382151, "composition": 0.16103}, + 174: {"mass": 173.9388664, "composition": 0.32026}, + 175: {"mass": 174.9412808, "composition": 0.}, + 176: {"mass": 175.9425764, "composition": 0.12996}, + 177: {"mass": 176.9452656, "composition": 0.}, + 178: {"mass": 177.946651, "composition": 0.}, + 179: {"mass": 178.95004, "composition": 0.}, + 180: {"mass": 179.95212, "composition": 0.}, + 181: {"mass": 180.95589, "composition": 0.}}, + 71: {150: {"mass": 149.97355, "composition": 0.}, + 151: {"mass": 150.96768, "composition": 0.}, + 152: {"mass": 151.96412, "composition": 0.}, + 153: {"mass": 152.95875, "composition": 0.}, + 154: {"mass": 153.95736, "composition": 0.}, + 155: {"mass": 154.954321, "composition": 0.}, + 156: {"mass": 155.953033, "composition": 0.}, + 157: {"mass": 156.950127, "composition": 0.}, + 158: {"mass": 157.949316, "composition": 0.}, + 159: {"mass": 158.946636, "composition": 0.}, + 160: {"mass": 159.946033, "composition": 0.}, + 161: {"mass": 160.943572, "composition": 0.}, + 162: {"mass": 161.943283, "composition": 0.}, + 163: {"mass": 162.941179, "composition": 0.}, + 164: {"mass": 163.941339, "composition": 0.}, + 165: {"mass": 164.939407, "composition": 0.}, + 166: {"mass": 165.939859, "composition": 0.}, + 167: {"mass": 166.93827, "composition": 0.}, + 168: {"mass": 167.938736, "composition": 0.}, + 169: {"mass": 168.9376441, "composition": 0.}, + 170: {"mass": 169.938478, "composition": 0.}, + 171: {"mass": 170.937917, "composition": 0.}, + 172: {"mass": 171.9390891, "composition": 0.}, + 173: {"mass": 172.938934, "composition": 0.}, + 174: {"mass": 173.9403409, "composition": 0.}, + 175: {"mass": 174.9407752, "composition": 0.97401}, + 176: {"mass": 175.9426897, "composition": 0.02599}, + 177: {"mass": 176.9437615, "composition": 0.}, + 178: {"mass": 177.945958, "composition": 0.}, + 179: {"mass": 178.9473309, "composition": 0.}, + 180: {"mass": 179.949888, "composition": 0.}, + 181: {"mass": 180.95191, "composition": 0.}, + 182: {"mass": 181.95504, "composition": 0.}, + 183: {"mass": 182.957363, "composition": 0.}, + 184: {"mass": 183.96091, "composition": 0.}, + 185: {"mass": 184.96362, "composition": 0.}}, + 72: {153: {"mass": 152.97069, "composition": 0.}, + 154: {"mass": 153.96486, "composition": 0.}, + 155: {"mass": 154.96311, "composition": 0.}, + 156: {"mass": 155.95935, "composition": 0.}, + 157: {"mass": 156.95824, "composition": 0.}, + 158: {"mass": 157.954801, "composition": 0.}, + 159: {"mass": 158.953996, "composition": 0.}, + 160: {"mass": 159.950691, "composition": 0.}, + 161: {"mass": 160.950278, "composition": 0.}, + 162: {"mass": 161.9472148, "composition": 0.}, + 163: {"mass": 162.947113, "composition": 0.}, + 164: {"mass": 163.944371, "composition": 0.}, + 165: {"mass": 164.944567, "composition": 0.}, + 166: {"mass": 165.94218, "composition": 0.}, + 167: {"mass": 166.9426, "composition": 0.}, + 168: {"mass": 167.940568, "composition": 0.}, + 169: {"mass": 168.941259, "composition": 0.}, + 170: {"mass": 169.939609, "composition": 0.}, + 171: {"mass": 170.940492, "composition": 0.}, + 172: {"mass": 171.93945, "composition": 0.}, + 173: {"mass": 172.940513, "composition": 0.}, + 174: {"mass": 173.9400461, "composition": 0.0016}, + 175: {"mass": 174.9415092, "composition": 0.}, + 176: {"mass": 175.9414076, "composition": 0.0526}, + 177: {"mass": 176.9432277, "composition": 0.186}, + 178: {"mass": 177.9437058, "composition": 0.2728}, + 179: {"mass": 178.9458232, "composition": 0.1362}, + 180: {"mass": 179.946557, "composition": 0.3508}, + 181: {"mass": 180.9491083, "composition": 0.}, + 182: {"mass": 181.9505612, "composition": 0.}, + 183: {"mass": 182.95353, "composition": 0.}, + 184: {"mass": 183.955446, "composition": 0.}, + 185: {"mass": 184.958862, "composition": 0.}, + 186: {"mass": 185.960897, "composition": 0.}, + 187: {"mass": 186.96477, "composition": 0.}, + 188: {"mass": 187.96685, "composition": 0.}, + 189: {"mass": 188.97084, "composition": 0.}}, + 73: {155: {"mass": 154.97424, "composition": 0.}, + 156: {"mass": 155.97203, "composition": 0.}, + 157: {"mass": 156.96818, "composition": 0.}, + 158: {"mass": 157.96654, "composition": 0.}, + 159: {"mass": 158.963023, "composition": 0.}, + 160: {"mass": 159.961488, "composition": 0.}, + 161: {"mass": 160.958452, "composition": 0.}, + 162: {"mass": 161.957294, "composition": 0.}, + 163: {"mass": 162.954337, "composition": 0.}, + 164: {"mass": 163.953534, "composition": 0.}, + 165: {"mass": 164.950781, "composition": 0.}, + 166: {"mass": 165.950512, "composition": 0.}, + 167: {"mass": 166.948093, "composition": 0.}, + 168: {"mass": 167.948047, "composition": 0.}, + 169: {"mass": 168.946011, "composition": 0.}, + 170: {"mass": 169.946175, "composition": 0.}, + 171: {"mass": 170.944476, "composition": 0.}, + 172: {"mass": 171.944895, "composition": 0.}, + 173: {"mass": 172.94375, "composition": 0.}, + 174: {"mass": 173.944454, "composition": 0.}, + 175: {"mass": 174.943737, "composition": 0.}, + 176: {"mass": 175.944857, "composition": 0.}, + 177: {"mass": 176.9444795, "composition": 0.}, + 178: {"mass": 177.945678, "composition": 0.}, + 179: {"mass": 178.9459366, "composition": 0.}, + 180: {"mass": 179.9474648, "composition": 0.0001201}, + 181: {"mass": 180.9479958, "composition": 0.9998799}, + 182: {"mass": 181.9501519, "composition": 0.}, + 183: {"mass": 182.9513726, "composition": 0.}, + 184: {"mass": 183.954008, "composition": 0.}, + 185: {"mass": 184.955559, "composition": 0.}, + 186: {"mass": 185.958551, "composition": 0.}, + 187: {"mass": 186.960386, "composition": 0.}, + 188: {"mass": 187.963916, "composition": 0.}, + 189: {"mass": 188.96583, "composition": 0.}, + 190: {"mass": 189.96939, "composition": 0.}, + 191: {"mass": 190.97156, "composition": 0.}, + 192: {"mass": 191.97514, "composition": 0.}}, + 74: {157: {"mass": 156.97884, "composition": 0.}, + 158: {"mass": 157.97456, "composition": 0.}, + 159: {"mass": 158.97264, "composition": 0.}, + 160: {"mass": 159.96846, "composition": 0.}, + 161: {"mass": 160.9672, "composition": 0.}, + 162: {"mass": 161.963499, "composition": 0.}, + 163: {"mass": 162.962524, "composition": 0.}, + 164: {"mass": 163.958961, "composition": 0.}, + 165: {"mass": 164.958281, "composition": 0.}, + 166: {"mass": 165.955031, "composition": 0.}, + 167: {"mass": 166.954805, "composition": 0.}, + 168: {"mass": 167.951806, "composition": 0.}, + 169: {"mass": 168.951779, "composition": 0.}, + 170: {"mass": 169.949232, "composition": 0.}, + 171: {"mass": 170.949451, "composition": 0.}, + 172: {"mass": 171.947292, "composition": 0.}, + 173: {"mass": 172.947689, "composition": 0.}, + 174: {"mass": 173.946079, "composition": 0.}, + 175: {"mass": 174.946717, "composition": 0.}, + 176: {"mass": 175.945634, "composition": 0.}, + 177: {"mass": 176.946643, "composition": 0.}, + 178: {"mass": 177.945883, "composition": 0.}, + 179: {"mass": 178.947077, "composition": 0.}, + 180: {"mass": 179.9467108, "composition": 0.0012}, + 181: {"mass": 180.9481978, "composition": 0.}, + 182: {"mass": 181.94820394, "composition": 0.265}, + 183: {"mass": 182.95022275, "composition": 0.1431}, + 184: {"mass": 183.95093092, "composition": 0.3064}, + 185: {"mass": 184.95341897, "composition": 0.}, + 186: {"mass": 185.9543628, "composition": 0.2843}, + 187: {"mass": 186.9571588, "composition": 0.}, + 188: {"mass": 187.9584862, "composition": 0.}, + 189: {"mass": 188.961763, "composition": 0.}, + 190: {"mass": 189.963091, "composition": 0.}, + 191: {"mass": 190.966531, "composition": 0.}, + 192: {"mass": 191.96817, "composition": 0.}, + 193: {"mass": 192.97178, "composition": 0.}, + 194: {"mass": 193.97367, "composition": 0.}}, + 75: {159: {"mass": 158.98418, "composition": 0.}, + 160: {"mass": 159.98182, "composition": 0.}, + 161: {"mass": 160.97757, "composition": 0.}, + 162: {"mass": 161.97584, "composition": 0.}, + 163: {"mass": 162.97208, "composition": 0.}, + 164: {"mass": 163.970453, "composition": 0.}, + 165: {"mass": 164.967103, "composition": 0.}, + 166: {"mass": 165.965761, "composition": 0.}, + 167: {"mass": 166.962595, "composition": 0.}, + 168: {"mass": 167.961573, "composition": 0.}, + 169: {"mass": 168.958766, "composition": 0.}, + 170: {"mass": 169.95822, "composition": 0.}, + 171: {"mass": 170.955716, "composition": 0.}, + 172: {"mass": 171.95542, "composition": 0.}, + 173: {"mass": 172.953243, "composition": 0.}, + 174: {"mass": 173.953115, "composition": 0.}, + 175: {"mass": 174.951381, "composition": 0.}, + 176: {"mass": 175.951623, "composition": 0.}, + 177: {"mass": 176.950328, "composition": 0.}, + 178: {"mass": 177.950989, "composition": 0.}, + 179: {"mass": 178.949989, "composition": 0.}, + 180: {"mass": 179.950792, "composition": 0.}, + 181: {"mass": 180.950058, "composition": 0.}, + 182: {"mass": 181.95121, "composition": 0.}, + 183: {"mass": 182.9508196, "composition": 0.}, + 184: {"mass": 183.9525228, "composition": 0.}, + 185: {"mass": 184.9529545, "composition": 0.374}, + 186: {"mass": 185.9549856, "composition": 0.}, + 187: {"mass": 186.9557501, "composition": 0.626}, + 188: {"mass": 187.9581115, "composition": 0.}, + 189: {"mass": 188.959226, "composition": 0.}, + 190: {"mass": 189.961744, "composition": 0.}, + 191: {"mass": 190.963122, "composition": 0.}, + 192: {"mass": 191.966088, "composition": 0.}, + 193: {"mass": 192.967541, "composition": 0.}, + 194: {"mass": 193.97076, "composition": 0.}, + 195: {"mass": 194.97254, "composition": 0.}, + 196: {"mass": 195.9758, "composition": 0.}, + 197: {"mass": 196.97799, "composition": 0.}, + 198: {"mass": 197.9816, "composition": 0.}}, + 76: {161: {"mass": 160.98903, "composition": 0.}, + 162: {"mass": 161.98443, "composition": 0.}, + 163: {"mass": 162.98241, "composition": 0.}, + 164: {"mass": 163.97802, "composition": 0.}, + 165: {"mass": 164.9766, "composition": 0.}, + 166: {"mass": 165.972692, "composition": 0.}, + 167: {"mass": 166.971549, "composition": 0.}, + 168: {"mass": 167.967808, "composition": 0.}, + 169: {"mass": 168.967018, "composition": 0.}, + 170: {"mass": 169.963578, "composition": 0.}, + 171: {"mass": 170.963174, "composition": 0.}, + 172: {"mass": 171.960017, "composition": 0.}, + 173: {"mass": 172.959808, "composition": 0.}, + 174: {"mass": 173.957064, "composition": 0.}, + 175: {"mass": 174.956945, "composition": 0.}, + 176: {"mass": 175.954806, "composition": 0.}, + 177: {"mass": 176.954966, "composition": 0.}, + 178: {"mass": 177.953254, "composition": 0.}, + 179: {"mass": 178.953817, "composition": 0.}, + 180: {"mass": 179.952375, "composition": 0.}, + 181: {"mass": 180.953247, "composition": 0.}, + 182: {"mass": 181.95211, "composition": 0.}, + 183: {"mass": 182.953125, "composition": 0.}, + 184: {"mass": 183.9524885, "composition": 0.0002}, + 185: {"mass": 184.9540417, "composition": 0.}, + 186: {"mass": 185.953835, "composition": 0.0159}, + 187: {"mass": 186.9557474, "composition": 0.0196}, + 188: {"mass": 187.9558352, "composition": 0.1324}, + 189: {"mass": 188.9581442, "composition": 0.1615}, + 190: {"mass": 189.9584437, "composition": 0.2626}, + 191: {"mass": 190.9609264, "composition": 0.}, + 192: {"mass": 191.961477, "composition": 0.4078}, + 193: {"mass": 192.9641479, "composition": 0.}, + 194: {"mass": 193.9651772, "composition": 0.}, + 195: {"mass": 194.968318, "composition": 0.}, + 196: {"mass": 195.969641, "composition": 0.}, + 197: {"mass": 196.97283, "composition": 0.}, + 198: {"mass": 197.97441, "composition": 0.}, + 199: {"mass": 198.97801, "composition": 0.}, + 200: {"mass": 199.97984, "composition": 0.}, + 201: {"mass": 200.98364, "composition": 0.}, + 202: {"mass": 201.98595, "composition": 0.}}, + 77: {164: {"mass": 163.99191, "composition": 0.}, + 165: {"mass": 164.9875, "composition": 0.}, + 166: {"mass": 165.98566, "composition": 0.}, + 167: {"mass": 166.981666, "composition": 0.}, + 168: {"mass": 167.979907, "composition": 0.}, + 169: {"mass": 168.976298, "composition": 0.}, + 170: {"mass": 169.974922, "composition": 0.}, + 171: {"mass": 170.97164, "composition": 0.}, + 172: {"mass": 171.970607, "composition": 0.}, + 173: {"mass": 172.967506, "composition": 0.}, + 174: {"mass": 173.966861, "composition": 0.}, + 175: {"mass": 174.96415, "composition": 0.}, + 176: {"mass": 175.96365, "composition": 0.}, + 177: {"mass": 176.961301, "composition": 0.}, + 178: {"mass": 177.961082, "composition": 0.}, + 179: {"mass": 178.95912, "composition": 0.}, + 180: {"mass": 179.959229, "composition": 0.}, + 181: {"mass": 180.957625, "composition": 0.}, + 182: {"mass": 181.958076, "composition": 0.}, + 183: {"mass": 182.95684, "composition": 0.}, + 184: {"mass": 183.957476, "composition": 0.}, + 185: {"mass": 184.956698, "composition": 0.}, + 186: {"mass": 185.957944, "composition": 0.}, + 187: {"mass": 186.957542, "composition": 0.}, + 188: {"mass": 187.958828, "composition": 0.}, + 189: {"mass": 188.958715, "composition": 0.}, + 190: {"mass": 189.9605412, "composition": 0.}, + 191: {"mass": 190.9605893, "composition": 0.373}, + 192: {"mass": 191.9626002, "composition": 0.}, + 193: {"mass": 192.9629216, "composition": 0.627}, + 194: {"mass": 193.9650735, "composition": 0.}, + 195: {"mass": 194.9659747, "composition": 0.}, + 196: {"mass": 195.968397, "composition": 0.}, + 197: {"mass": 196.969655, "composition": 0.}, + 198: {"mass": 197.97228, "composition": 0.}, + 199: {"mass": 198.973805, "composition": 0.}, + 200: {"mass": 199.9768, "composition": 0.}, + 201: {"mass": 200.97864, "composition": 0.}, + 202: {"mass": 201.98199, "composition": 0.}, + 203: {"mass": 202.98423, "composition": 0.}, + 204: {"mass": 203.9896, "composition": 0.}}, + 78: {166: {"mass": 165.99486, "composition": 0.}, + 167: {"mass": 166.99269, "composition": 0.}, + 168: {"mass": 167.98813, "composition": 0.}, + 169: {"mass": 168.98657, "composition": 0.}, + 170: {"mass": 169.982496, "composition": 0.}, + 171: {"mass": 170.981245, "composition": 0.}, + 172: {"mass": 171.977351, "composition": 0.}, + 173: {"mass": 172.976443, "composition": 0.}, + 174: {"mass": 173.97282, "composition": 0.}, + 175: {"mass": 174.97241, "composition": 0.}, + 176: {"mass": 175.968938, "composition": 0.}, + 177: {"mass": 176.96847, "composition": 0.}, + 178: {"mass": 177.96565, "composition": 0.}, + 179: {"mass": 178.965359, "composition": 0.}, + 180: {"mass": 179.963032, "composition": 0.}, + 181: {"mass": 180.963098, "composition": 0.}, + 182: {"mass": 181.961172, "composition": 0.}, + 183: {"mass": 182.961597, "composition": 0.}, + 184: {"mass": 183.959915, "composition": 0.}, + 185: {"mass": 184.960614, "composition": 0.}, + 186: {"mass": 185.959351, "composition": 0.}, + 187: {"mass": 186.960617, "composition": 0.}, + 188: {"mass": 187.9593889, "composition": 0.}, + 189: {"mass": 188.960831, "composition": 0.}, + 190: {"mass": 189.9599297, "composition": 0.00012}, + 191: {"mass": 190.9616729, "composition": 0.}, + 192: {"mass": 191.9610387, "composition": 0.00782}, + 193: {"mass": 192.9629824, "composition": 0.}, + 194: {"mass": 193.9626809, "composition": 0.3286}, + 195: {"mass": 194.9647917, "composition": 0.3378}, + 196: {"mass": 195.96495209, "composition": 0.2521}, + 197: {"mass": 196.96734069, "composition": 0.}, + 198: {"mass": 197.9678949, "composition": 0.07356}, + 199: {"mass": 198.9705952, "composition": 0.}, + 200: {"mass": 199.971443, "composition": 0.}, + 201: {"mass": 200.974513, "composition": 0.}, + 202: {"mass": 201.975639, "composition": 0.}, + 203: {"mass": 202.97893, "composition": 0.}, + 204: {"mass": 203.98076, "composition": 0.}, + 205: {"mass": 204.98608, "composition": 0.}, + 206: {"mass": 205.98966, "composition": 0.}}, + 79: {169: {"mass": 168.99808, "composition": 0.}, + 170: {"mass": 169.99597, "composition": 0.}, + 171: {"mass": 170.991876, "composition": 0.}, + 172: {"mass": 171.989942, "composition": 0.}, + 173: {"mass": 172.986241, "composition": 0.}, + 174: {"mass": 173.984717, "composition": 0.}, + 175: {"mass": 174.981304, "composition": 0.}, + 176: {"mass": 175.98025, "composition": 0.}, + 177: {"mass": 176.97687, "composition": 0.}, + 178: {"mass": 177.976032, "composition": 0.}, + 179: {"mass": 178.973174, "composition": 0.}, + 180: {"mass": 179.972523, "composition": 0.}, + 181: {"mass": 180.970079, "composition": 0.}, + 182: {"mass": 181.969618, "composition": 0.}, + 183: {"mass": 182.967591, "composition": 0.}, + 184: {"mass": 183.967452, "composition": 0.}, + 185: {"mass": 184.96579, "composition": 0.}, + 186: {"mass": 185.965953, "composition": 0.}, + 187: {"mass": 186.964543, "composition": 0.}, + 188: {"mass": 187.965349, "composition": 0.}, + 189: {"mass": 188.963948, "composition": 0.}, + 190: {"mass": 189.964698, "composition": 0.}, + 191: {"mass": 190.963702, "composition": 0.}, + 192: {"mass": 191.964814, "composition": 0.}, + 193: {"mass": 192.9641373, "composition": 0.}, + 194: {"mass": 193.9654178, "composition": 0.}, + 195: {"mass": 194.9650352, "composition": 0.}, + 196: {"mass": 195.9665699, "composition": 0.}, + 197: {"mass": 196.96656879, "composition": 1.}, + 198: {"mass": 197.96824242, "composition": 0.}, + 199: {"mass": 198.96876528, "composition": 0.}, + 200: {"mass": 199.970756, "composition": 0.}, + 201: {"mass": 200.9716575, "composition": 0.}, + 202: {"mass": 201.973856, "composition": 0.}, + 203: {"mass": 202.9751544, "composition": 0.}, + 204: {"mass": 203.97783, "composition": 0.}, + 205: {"mass": 204.97985, "composition": 0.}, + 206: {"mass": 205.98474, "composition": 0.}, + 207: {"mass": 206.9884, "composition": 0.}, + 208: {"mass": 207.99345, "composition": 0.}, + 209: {"mass": 208.99735, "composition": 0.}, + 210: {"mass": 210.0025, "composition": 0.}}, + 80: {171: {"mass": 171.00353, "composition": 0.}, + 172: {"mass": 171.99881, "composition": 0.}, + 173: {"mass": 172.99709, "composition": 0.}, + 174: {"mass": 173.992865, "composition": 0.}, + 175: {"mass": 174.991441, "composition": 0.}, + 176: {"mass": 175.987361, "composition": 0.}, + 177: {"mass": 176.986277, "composition": 0.}, + 178: {"mass": 177.982484, "composition": 0.}, + 179: {"mass": 178.981831, "composition": 0.}, + 180: {"mass": 179.97826, "composition": 0.}, + 181: {"mass": 180.977819, "composition": 0.}, + 182: {"mass": 181.974689, "composition": 0.}, + 183: {"mass": 182.9744448, "composition": 0.}, + 184: {"mass": 183.971714, "composition": 0.}, + 185: {"mass": 184.971899, "composition": 0.}, + 186: {"mass": 185.969362, "composition": 0.}, + 187: {"mass": 186.969814, "composition": 0.}, + 188: {"mass": 187.967567, "composition": 0.}, + 189: {"mass": 188.968195, "composition": 0.}, + 190: {"mass": 189.966323, "composition": 0.}, + 191: {"mass": 190.967157, "composition": 0.}, + 192: {"mass": 191.965635, "composition": 0.}, + 193: {"mass": 192.966653, "composition": 0.}, + 194: {"mass": 193.9654491, "composition": 0.}, + 195: {"mass": 194.966721, "composition": 0.}, + 196: {"mass": 195.9658326, "composition": 0.0015}, + 197: {"mass": 196.9672128, "composition": 0.}, + 198: {"mass": 197.9667686, "composition": 0.0997}, + 199: {"mass": 198.96828064, "composition": 0.1687}, + 200: {"mass": 199.96832659, "composition": 0.231}, + 201: {"mass": 200.97030284, "composition": 0.1318}, + 202: {"mass": 201.9706434, "composition": 0.2986}, + 203: {"mass": 202.9728728, "composition": 0.}, + 204: {"mass": 203.97349398, "composition": 0.0687}, + 205: {"mass": 204.9760734, "composition": 0.}, + 206: {"mass": 205.977514, "composition": 0.}, + 207: {"mass": 206.9823, "composition": 0.}, + 208: {"mass": 207.985759, "composition": 0.}, + 209: {"mass": 208.99072, "composition": 0.}, + 210: {"mass": 209.99424, "composition": 0.}, + 211: {"mass": 210.99933, "composition": 0.}, + 212: {"mass": 212.00296, "composition": 0.}, + 213: {"mass": 213.00823, "composition": 0.}, + 214: {"mass": 214.012, "composition": 0.}, + 215: {"mass": 215.0174, "composition": 0.}, + 216: {"mass": 216.02132, "composition": 0.}}, + 81: {176: {"mass": 176.000624, "composition": 0.}, + 177: {"mass": 176.996431, "composition": 0.}, + 178: {"mass": 177.99485, "composition": 0.}, + 179: {"mass": 178.991111, "composition": 0.}, + 180: {"mass": 179.990057, "composition": 0.}, + 181: {"mass": 180.98626, "composition": 0.}, + 182: {"mass": 181.985713, "composition": 0.}, + 183: {"mass": 182.982193, "composition": 0.}, + 184: {"mass": 183.981886, "composition": 0.}, + 185: {"mass": 184.978789, "composition": 0.}, + 186: {"mass": 185.978651, "composition": 0.}, + 187: {"mass": 186.9759063, "composition": 0.}, + 188: {"mass": 187.976021, "composition": 0.}, + 189: {"mass": 188.973588, "composition": 0.}, + 190: {"mass": 189.973828, "composition": 0.}, + 191: {"mass": 190.9717842, "composition": 0.}, + 192: {"mass": 191.972225, "composition": 0.}, + 193: {"mass": 192.970502, "composition": 0.}, + 194: {"mass": 193.971081, "composition": 0.}, + 195: {"mass": 194.969774, "composition": 0.}, + 196: {"mass": 195.970481, "composition": 0.}, + 197: {"mass": 196.969576, "composition": 0.}, + 198: {"mass": 197.970483, "composition": 0.}, + 199: {"mass": 198.969877, "composition": 0.}, + 200: {"mass": 199.9709633, "composition": 0.}, + 201: {"mass": 200.970822, "composition": 0.}, + 202: {"mass": 201.972102, "composition": 0.}, + 203: {"mass": 202.9723446, "composition": 0.2952}, + 204: {"mass": 203.9738639, "composition": 0.}, + 205: {"mass": 204.9744278, "composition": 0.7048}, + 206: {"mass": 205.9761106, "composition": 0.}, + 207: {"mass": 206.9774197, "composition": 0.}, + 208: {"mass": 207.982019, "composition": 0.}, + 209: {"mass": 208.9853594, "composition": 0.}, + 210: {"mass": 209.990074, "composition": 0.}, + 211: {"mass": 210.993475, "composition": 0.}, + 212: {"mass": 211.99834, "composition": 0.}, + 213: {"mass": 213.001915, "composition": 0.}, + 214: {"mass": 214.00694, "composition": 0.}, + 215: {"mass": 215.01064, "composition": 0.}, + 216: {"mass": 216.0158, "composition": 0.}, + 217: {"mass": 217.01966, "composition": 0.}, + 218: {"mass": 218.02479, "composition": 0.}}, + 82: {178: {"mass": 178.003831, "composition": 0.}, + 179: {"mass": 179.002201, "composition": 0.}, + 180: {"mass": 179.997928, "composition": 0.}, + 181: {"mass": 180.996653, "composition": 0.}, + 182: {"mass": 181.992672, "composition": 0.}, + 183: {"mass": 182.991872, "composition": 0.}, + 184: {"mass": 183.988136, "composition": 0.}, + 185: {"mass": 184.98761, "composition": 0.}, + 186: {"mass": 185.984238, "composition": 0.}, + 187: {"mass": 186.9839109, "composition": 0.}, + 188: {"mass": 187.980875, "composition": 0.}, + 189: {"mass": 188.980807, "composition": 0.}, + 190: {"mass": 189.978082, "composition": 0.}, + 191: {"mass": 190.978276, "composition": 0.}, + 192: {"mass": 191.975775, "composition": 0.}, + 193: {"mass": 192.976173, "composition": 0.}, + 194: {"mass": 193.974012, "composition": 0.}, + 195: {"mass": 194.974543, "composition": 0.}, + 196: {"mass": 195.972774, "composition": 0.}, + 197: {"mass": 196.9734312, "composition": 0.}, + 198: {"mass": 197.972034, "composition": 0.}, + 199: {"mass": 198.972913, "composition": 0.}, + 200: {"mass": 199.971819, "composition": 0.}, + 201: {"mass": 200.972883, "composition": 0.}, + 202: {"mass": 201.972152, "composition": 0.}, + 203: {"mass": 202.9733911, "composition": 0.}, + 204: {"mass": 203.973044, "composition": 0.014}, + 205: {"mass": 204.9744822, "composition": 0.}, + 206: {"mass": 205.9744657, "composition": 0.241}, + 207: {"mass": 206.9758973, "composition": 0.221}, + 208: {"mass": 207.9766525, "composition": 0.524}, + 209: {"mass": 208.9810905, "composition": 0.}, + 210: {"mass": 209.9841889, "composition": 0.}, + 211: {"mass": 210.9887371, "composition": 0.}, + 212: {"mass": 211.9918977, "composition": 0.}, + 213: {"mass": 212.9965629, "composition": 0.}, + 214: {"mass": 213.9998059, "composition": 0.}, + 215: {"mass": 215.00474, "composition": 0.}, + 216: {"mass": 216.00803, "composition": 0.}, + 217: {"mass": 217.01314, "composition": 0.}, + 218: {"mass": 218.01659, "composition": 0.}, + 219: {"mass": 219.02177, "composition": 0.}, + 220: {"mass": 220.02541, "composition": 0.}}, + 83: {184: {"mass": 184.001275, "composition": 0.}, + 185: {"mass": 184.9976, "composition": 0.}, + 186: {"mass": 185.996644, "composition": 0.}, + 187: {"mass": 186.993147, "composition": 0.}, + 188: {"mass": 187.992287, "composition": 0.}, + 189: {"mass": 188.989195, "composition": 0.}, + 190: {"mass": 189.988622, "composition": 0.}, + 191: {"mass": 190.9857866, "composition": 0.}, + 192: {"mass": 191.985469, "composition": 0.}, + 193: {"mass": 192.98296, "composition": 0.}, + 194: {"mass": 193.982785, "composition": 0.}, + 195: {"mass": 194.9806488, "composition": 0.}, + 196: {"mass": 195.980667, "composition": 0.}, + 197: {"mass": 196.9788651, "composition": 0.}, + 198: {"mass": 197.979206, "composition": 0.}, + 199: {"mass": 198.977673, "composition": 0.}, + 200: {"mass": 199.978131, "composition": 0.}, + 201: {"mass": 200.97701, "composition": 0.}, + 202: {"mass": 201.977734, "composition": 0.}, + 203: {"mass": 202.976893, "composition": 0.}, + 204: {"mass": 203.9778361, "composition": 0.}, + 205: {"mass": 204.9773867, "composition": 0.}, + 206: {"mass": 205.9784993, "composition": 0.}, + 207: {"mass": 206.978471, "composition": 0.}, + 208: {"mass": 207.9797425, "composition": 0.}, + 209: {"mass": 208.9803991, "composition": 1.}, + 210: {"mass": 209.9841207, "composition": 0.}, + 211: {"mass": 210.9872697, "composition": 0.}, + 212: {"mass": 211.991286, "composition": 0.}, + 213: {"mass": 212.9943851, "composition": 0.}, + 214: {"mass": 213.998712, "composition": 0.}, + 215: {"mass": 215.00177, "composition": 0.}, + 216: {"mass": 216.006306, "composition": 0.}, + 217: {"mass": 217.009372, "composition": 0.}, + 218: {"mass": 218.014188, "composition": 0.}, + 219: {"mass": 219.01748, "composition": 0.}, + 220: {"mass": 220.02235, "composition": 0.}, + 221: {"mass": 221.02587, "composition": 0.}, + 222: {"mass": 222.03078, "composition": 0.}, + 223: {"mass": 223.0345, "composition": 0.}, + 224: {"mass": 224.03947, "composition": 0.}}, + 84: {186: {"mass": 186.004393, "composition": 0.}, + 187: {"mass": 187.003041, "composition": 0.}, + 188: {"mass": 187.999416, "composition": 0.}, + 189: {"mass": 188.998473, "composition": 0.}, + 190: {"mass": 189.995101, "composition": 0.}, + 191: {"mass": 190.9945585, "composition": 0.}, + 192: {"mass": 191.991336, "composition": 0.}, + 193: {"mass": 192.991026, "composition": 0.}, + 194: {"mass": 193.988186, "composition": 0.}, + 195: {"mass": 194.988126, "composition": 0.}, + 196: {"mass": 195.985526, "composition": 0.}, + 197: {"mass": 196.98566, "composition": 0.}, + 198: {"mass": 197.983389, "composition": 0.}, + 199: {"mass": 198.983667, "composition": 0.}, + 200: {"mass": 199.981799, "composition": 0.}, + 201: {"mass": 200.9822598, "composition": 0.}, + 202: {"mass": 201.980758, "composition": 0.}, + 203: {"mass": 202.9814161, "composition": 0.}, + 204: {"mass": 203.98031, "composition": 0.}, + 205: {"mass": 204.981203, "composition": 0.}, + 206: {"mass": 205.980474, "composition": 0.}, + 207: {"mass": 206.9815938, "composition": 0.}, + 208: {"mass": 207.9812461, "composition": 0.}, + 209: {"mass": 208.9824308, "composition": 0.}, + 210: {"mass": 209.9828741, "composition": 0.}, + 211: {"mass": 210.9866536, "composition": 0.}, + 212: {"mass": 211.9888684, "composition": 0.}, + 213: {"mass": 212.9928576, "composition": 0.}, + 214: {"mass": 213.9952017, "composition": 0.}, + 215: {"mass": 214.9994201, "composition": 0.}, + 216: {"mass": 216.0019152, "composition": 0.}, + 217: {"mass": 217.0063182, "composition": 0.}, + 218: {"mass": 218.0089735, "composition": 0.}, + 219: {"mass": 219.013614, "composition": 0.}, + 220: {"mass": 220.016386, "composition": 0.}, + 221: {"mass": 221.021228, "composition": 0.}, + 222: {"mass": 222.02414, "composition": 0.}, + 223: {"mass": 223.02907, "composition": 0.}, + 224: {"mass": 224.03211, "composition": 0.}, + 225: {"mass": 225.03707, "composition": 0.}, + 226: {"mass": 226.04031, "composition": 0.}, + 227: {"mass": 227.04539, "composition": 0.}}, + 85: {191: {"mass": 191.004148, "composition": 0.}, + 192: {"mass": 192.003152, "composition": 0.}, + 193: {"mass": 192.999927, "composition": 0.}, + 194: {"mass": 193.999236, "composition": 0.}, + 195: {"mass": 194.9962685, "composition": 0.}, + 196: {"mass": 195.9958, "composition": 0.}, + 197: {"mass": 196.993189, "composition": 0.}, + 198: {"mass": 197.992784, "composition": 0.}, + 199: {"mass": 198.9905277, "composition": 0.}, + 200: {"mass": 199.990351, "composition": 0.}, + 201: {"mass": 200.9884171, "composition": 0.}, + 202: {"mass": 201.98863, "composition": 0.}, + 203: {"mass": 202.986943, "composition": 0.}, + 204: {"mass": 203.987251, "composition": 0.}, + 205: {"mass": 204.986076, "composition": 0.}, + 206: {"mass": 205.986657, "composition": 0.}, + 207: {"mass": 206.9858, "composition": 0.}, + 208: {"mass": 207.9866133, "composition": 0.}, + 209: {"mass": 208.9861702, "composition": 0.}, + 210: {"mass": 209.9871479, "composition": 0.}, + 211: {"mass": 210.9874966, "composition": 0.}, + 212: {"mass": 211.9907377, "composition": 0.}, + 213: {"mass": 212.992937, "composition": 0.}, + 214: {"mass": 213.9963721, "composition": 0.}, + 215: {"mass": 214.9986528, "composition": 0.}, + 216: {"mass": 216.0024236, "composition": 0.}, + 217: {"mass": 217.0047192, "composition": 0.}, + 218: {"mass": 218.008695, "composition": 0.}, + 219: {"mass": 219.0111618, "composition": 0.}, + 220: {"mass": 220.015433, "composition": 0.}, + 221: {"mass": 221.018017, "composition": 0.}, + 222: {"mass": 222.022494, "composition": 0.}, + 223: {"mass": 223.025151, "composition": 0.}, + 224: {"mass": 224.029749, "composition": 0.}, + 225: {"mass": 225.03263, "composition": 0.}, + 226: {"mass": 226.03716, "composition": 0.}, + 227: {"mass": 227.04024, "composition": 0.}, + 228: {"mass": 228.04475, "composition": 0.}, + 229: {"mass": 229.04812, "composition": 0.}}, + 86: {193: {"mass": 193.009708, "composition": 0.}, + 194: {"mass": 194.006144, "composition": 0.}, + 195: {"mass": 195.005422, "composition": 0.}, + 196: {"mass": 196.002116, "composition": 0.}, + 197: {"mass": 197.001585, "composition": 0.}, + 198: {"mass": 197.998679, "composition": 0.}, + 199: {"mass": 198.99839, "composition": 0.}, + 200: {"mass": 199.99569, "composition": 0.}, + 201: {"mass": 200.995628, "composition": 0.}, + 202: {"mass": 201.993264, "composition": 0.}, + 203: {"mass": 202.993388, "composition": 0.}, + 204: {"mass": 203.99143, "composition": 0.}, + 205: {"mass": 204.991719, "composition": 0.}, + 206: {"mass": 205.990214, "composition": 0.}, + 207: {"mass": 206.9907303, "composition": 0.}, + 208: {"mass": 207.989635, "composition": 0.}, + 209: {"mass": 208.990415, "composition": 0.}, + 210: {"mass": 209.9896891, "composition": 0.}, + 211: {"mass": 210.9906011, "composition": 0.}, + 212: {"mass": 211.9907039, "composition": 0.}, + 213: {"mass": 212.9938831, "composition": 0.}, + 214: {"mass": 213.995363, "composition": 0.}, + 215: {"mass": 214.9987459, "composition": 0.}, + 216: {"mass": 216.0002719, "composition": 0.}, + 217: {"mass": 217.003928, "composition": 0.}, + 218: {"mass": 218.0056016, "composition": 0.}, + 219: {"mass": 219.0094804, "composition": 0.}, + 220: {"mass": 220.0113941, "composition": 0.}, + 221: {"mass": 221.0155371, "composition": 0.}, + 222: {"mass": 222.0175782, "composition": 0.}, + 223: {"mass": 223.0218893, "composition": 0.}, + 224: {"mass": 224.024096, "composition": 0.}, + 225: {"mass": 225.028486, "composition": 0.}, + 226: {"mass": 226.030861, "composition": 0.}, + 227: {"mass": 227.035304, "composition": 0.}, + 228: {"mass": 228.037835, "composition": 0.}, + 229: {"mass": 229.042257, "composition": 0.}, + 230: {"mass": 230.04514, "composition": 0.}, + 231: {"mass": 231.04987, "composition": 0.}}, + 87: {199: {"mass": 199.007259, "composition": 0.}, + 200: {"mass": 200.006586, "composition": 0.}, + 201: {"mass": 201.003867, "composition": 0.}, + 202: {"mass": 202.00332, "composition": 0.}, + 203: {"mass": 203.0009407, "composition": 0.}, + 204: {"mass": 204.000652, "composition": 0.}, + 205: {"mass": 204.9985939, "composition": 0.}, + 206: {"mass": 205.998666, "composition": 0.}, + 207: {"mass": 206.996946, "composition": 0.}, + 208: {"mass": 207.997138, "composition": 0.}, + 209: {"mass": 208.995955, "composition": 0.}, + 210: {"mass": 209.996422, "composition": 0.}, + 211: {"mass": 210.995556, "composition": 0.}, + 212: {"mass": 211.9962257, "composition": 0.}, + 213: {"mass": 212.996186, "composition": 0.}, + 214: {"mass": 213.9989713, "composition": 0.}, + 215: {"mass": 215.0003418, "composition": 0.}, + 216: {"mass": 216.0031899, "composition": 0.}, + 217: {"mass": 217.0046323, "composition": 0.}, + 218: {"mass": 218.0075787, "composition": 0.}, + 219: {"mass": 219.0092524, "composition": 0.}, + 220: {"mass": 220.0123277, "composition": 0.}, + 221: {"mass": 221.0142552, "composition": 0.}, + 222: {"mass": 222.017552, "composition": 0.}, + 223: {"mass": 223.019736, "composition": 0.}, + 224: {"mass": 224.023398, "composition": 0.}, + 225: {"mass": 225.025573, "composition": 0.}, + 226: {"mass": 226.029566, "composition": 0.}, + 227: {"mass": 227.031869, "composition": 0.}, + 228: {"mass": 228.035823, "composition": 0.}, + 229: {"mass": 229.038298, "composition": 0.}, + 230: {"mass": 230.042416, "composition": 0.}, + 231: {"mass": 231.045158, "composition": 0.}, + 232: {"mass": 232.04937, "composition": 0.}, + 233: {"mass": 233.05264, "composition": 0.}}, + 88: {201: {"mass": 201.01271, "composition": 0.}, + 202: {"mass": 202.00976, "composition": 0.}, + 203: {"mass": 203.009304, "composition": 0.}, + 204: {"mass": 204.006492, "composition": 0.}, + 205: {"mass": 205.006268, "composition": 0.}, + 206: {"mass": 206.003828, "composition": 0.}, + 207: {"mass": 207.003799, "composition": 0.}, + 208: {"mass": 208.001841, "composition": 0.}, + 209: {"mass": 209.00199, "composition": 0.}, + 210: {"mass": 210.000494, "composition": 0.}, + 211: {"mass": 211.0008932, "composition": 0.}, + 212: {"mass": 211.999787, "composition": 0.}, + 213: {"mass": 213.000384, "composition": 0.}, + 214: {"mass": 214.0000997, "composition": 0.}, + 215: {"mass": 215.0027204, "composition": 0.}, + 216: {"mass": 216.0035334, "composition": 0.}, + 217: {"mass": 217.0063207, "composition": 0.}, + 218: {"mass": 218.007141, "composition": 0.}, + 219: {"mass": 219.0100855, "composition": 0.}, + 220: {"mass": 220.0110259, "composition": 0.}, + 221: {"mass": 221.0139177, "composition": 0.}, + 222: {"mass": 222.0153748, "composition": 0.}, + 223: {"mass": 223.0185023, "composition": 0.}, + 224: {"mass": 224.020212, "composition": 0.}, + 225: {"mass": 225.0236119, "composition": 0.}, + 226: {"mass": 226.0254103, "composition": 0.}, + 227: {"mass": 227.0291783, "composition": 0.}, + 228: {"mass": 228.0310707, "composition": 0.}, + 229: {"mass": 229.034942, "composition": 0.}, + 230: {"mass": 230.037055, "composition": 0.}, + 231: {"mass": 231.041027, "composition": 0.}, + 232: {"mass": 232.0434753, "composition": 0.}, + 233: {"mass": 233.047582, "composition": 0.}, + 234: {"mass": 234.050342, "composition": 0.}, + 235: {"mass": 235.05497, "composition": 0.}}, + 89: {206: {"mass": 206.014452, "composition": 0.}, + 207: {"mass": 207.011966, "composition": 0.}, + 208: {"mass": 208.01155, "composition": 0.}, + 209: {"mass": 209.009495, "composition": 0.}, + 210: {"mass": 210.009436, "composition": 0.}, + 211: {"mass": 211.007732, "composition": 0.}, + 212: {"mass": 212.007813, "composition": 0.}, + 213: {"mass": 213.006609, "composition": 0.}, + 214: {"mass": 214.006918, "composition": 0.}, + 215: {"mass": 215.006475, "composition": 0.}, + 216: {"mass": 216.008743, "composition": 0.}, + 217: {"mass": 217.009344, "composition": 0.}, + 218: {"mass": 218.011642, "composition": 0.}, + 219: {"mass": 219.012421, "composition": 0.}, + 220: {"mass": 220.0147549, "composition": 0.}, + 221: {"mass": 221.015592, "composition": 0.}, + 222: {"mass": 222.0178442, "composition": 0.}, + 223: {"mass": 223.0191377, "composition": 0.}, + 224: {"mass": 224.0217232, "composition": 0.}, + 225: {"mass": 225.02323, "composition": 0.}, + 226: {"mass": 226.0260984, "composition": 0.}, + 227: {"mass": 227.0277523, "composition": 0.}, + 228: {"mass": 228.0310215, "composition": 0.}, + 229: {"mass": 229.032956, "composition": 0.}, + 230: {"mass": 230.036327, "composition": 0.}, + 231: {"mass": 231.038393, "composition": 0.}, + 232: {"mass": 232.042034, "composition": 0.}, + 233: {"mass": 233.044346, "composition": 0.}, + 234: {"mass": 234.048139, "composition": 0.}, + 235: {"mass": 235.05084, "composition": 0.}, + 236: {"mass": 236.054988, "composition": 0.}, + 237: {"mass": 237.05827, "composition": 0.}}, + 90: {208: {"mass": 208.0179, "composition": 0.}, + 209: {"mass": 209.017753, "composition": 0.}, + 210: {"mass": 210.015094, "composition": 0.}, + 211: {"mass": 211.014929, "composition": 0.}, + 212: {"mass": 212.012988, "composition": 0.}, + 213: {"mass": 213.013009, "composition": 0.}, + 214: {"mass": 214.0115, "composition": 0.}, + 215: {"mass": 215.0117248, "composition": 0.}, + 216: {"mass": 216.011056, "composition": 0.}, + 217: {"mass": 217.013117, "composition": 0.}, + 218: {"mass": 218.013276, "composition": 0.}, + 219: {"mass": 219.015537, "composition": 0.}, + 220: {"mass": 220.015748, "composition": 0.}, + 221: {"mass": 221.018184, "composition": 0.}, + 222: {"mass": 222.018469, "composition": 0.}, + 223: {"mass": 223.0208119, "composition": 0.}, + 224: {"mass": 224.021464, "composition": 0.}, + 225: {"mass": 225.0239514, "composition": 0.}, + 226: {"mass": 226.0249034, "composition": 0.}, + 227: {"mass": 227.0277042, "composition": 0.}, + 228: {"mass": 228.0287413, "composition": 0.}, + 229: {"mass": 229.0317627, "composition": 0.}, + 230: {"mass": 230.0331341, "composition": 0.}, + 231: {"mass": 231.0363046, "composition": 0.}, + 232: {"mass": 232.0380558, "composition": 1.}, + 233: {"mass": 233.0415823, "composition": 0.}, + 234: {"mass": 234.0436014, "composition": 0.}, + 235: {"mass": 235.047255, "composition": 0.}, + 236: {"mass": 236.049657, "composition": 0.}, + 237: {"mass": 237.053629, "composition": 0.}, + 238: {"mass": 238.0565, "composition": 0.}, + 239: {"mass": 239.06077, "composition": 0.}}, + 91: {212: {"mass": 212.023203, "composition": 0.}, + 213: {"mass": 213.021109, "composition": 0.}, + 214: {"mass": 214.020918, "composition": 0.}, + 215: {"mass": 215.019183, "composition": 0.}, + 216: {"mass": 216.019109, "composition": 0.}, + 217: {"mass": 217.018325, "composition": 0.}, + 218: {"mass": 218.020059, "composition": 0.}, + 219: {"mass": 219.019904, "composition": 0.}, + 220: {"mass": 220.021705, "composition": 0.}, + 221: {"mass": 221.021875, "composition": 0.}, + 222: {"mass": 222.023784, "composition": 0.}, + 223: {"mass": 223.023963, "composition": 0.}, + 224: {"mass": 224.0256176, "composition": 0.}, + 225: {"mass": 225.026131, "composition": 0.}, + 226: {"mass": 226.027948, "composition": 0.}, + 227: {"mass": 227.0288054, "composition": 0.}, + 228: {"mass": 228.0310517, "composition": 0.}, + 229: {"mass": 229.0320972, "composition": 0.}, + 230: {"mass": 230.034541, "composition": 0.}, + 231: {"mass": 231.0358842, "composition": 1.}, + 232: {"mass": 232.0385917, "composition": 0.}, + 233: {"mass": 233.0402472, "composition": 0.}, + 234: {"mass": 234.0433072, "composition": 0.}, + 235: {"mass": 235.045399, "composition": 0.}, + 236: {"mass": 236.048668, "composition": 0.}, + 237: {"mass": 237.051023, "composition": 0.}, + 238: {"mass": 238.054637, "composition": 0.}, + 239: {"mass": 239.05726, "composition": 0.}, + 240: {"mass": 240.06098, "composition": 0.}, + 241: {"mass": 241.06408, "composition": 0.}}, + 92: {217: {"mass": 217.02466, "composition": 0.}, + 218: {"mass": 218.023523, "composition": 0.}, + 219: {"mass": 219.024999, "composition": 0.}, + 220: {"mass": 220.02462, "composition": 0.}, + 221: {"mass": 221.02628, "composition": 0.}, + 222: {"mass": 222.026, "composition": 0.}, + 223: {"mass": 223.027739, "composition": 0.}, + 224: {"mass": 224.027605, "composition": 0.}, + 225: {"mass": 225.029391, "composition": 0.}, + 226: {"mass": 226.029339, "composition": 0.}, + 227: {"mass": 227.031157, "composition": 0.}, + 228: {"mass": 228.031371, "composition": 0.}, + 229: {"mass": 229.0335063, "composition": 0.}, + 230: {"mass": 230.0339401, "composition": 0.}, + 231: {"mass": 231.0362939, "composition": 0.}, + 232: {"mass": 232.0371563, "composition": 0.}, + 233: {"mass": 233.0396355, "composition": 0.}, + 234: {"mass": 234.0409523, "composition": 5.4e-05}, + 235: {"mass": 235.0439301, "composition": 0.007204}, + 236: {"mass": 236.0455682, "composition": 0.}, + 237: {"mass": 237.0487304, "composition": 0.}, + 238: {"mass": 238.0507884, "composition": 0.992742}, + 239: {"mass": 239.0542935, "composition": 0.}, + 240: {"mass": 240.0565934, "composition": 0.}, + 241: {"mass": 241.06033, "composition": 0.}, + 242: {"mass": 242.06293, "composition": 0.}, + 243: {"mass": 243.06699, "composition": 0.}}, + 93: {219: {"mass": 219.03143, "composition": 0.}, + 220: {"mass": 220.03254, "composition": 0.}, + 221: {"mass": 221.03204, "composition": 0.}, + 222: {"mass": 222.0333, "composition": 0.}, + 223: {"mass": 223.03285, "composition": 0.}, + 224: {"mass": 224.03422, "composition": 0.}, + 225: {"mass": 225.033911, "composition": 0.}, + 226: {"mass": 226.035188, "composition": 0.}, + 227: {"mass": 227.034957, "composition": 0.}, + 228: {"mass": 228.036067, "composition": 0.}, + 229: {"mass": 229.036264, "composition": 0.}, + 230: {"mass": 230.037828, "composition": 0.}, + 231: {"mass": 231.038245, "composition": 0.}, + 232: {"mass": 232.04011, "composition": 0.}, + 233: {"mass": 233.040741, "composition": 0.}, + 234: {"mass": 234.0428953, "composition": 0.}, + 235: {"mass": 235.0440635, "composition": 0.}, + 236: {"mass": 236.04657, "composition": 0.}, + 237: {"mass": 237.0481736, "composition": 0.}, + 238: {"mass": 238.0509466, "composition": 0.}, + 239: {"mass": 239.0529392, "composition": 0.}, + 240: {"mass": 240.056165, "composition": 0.}, + 241: {"mass": 241.058253, "composition": 0.}, + 242: {"mass": 242.06164, "composition": 0.}, + 243: {"mass": 243.06428, "composition": 0.}, + 244: {"mass": 244.06785, "composition": 0.}, + 245: {"mass": 245.0708, "composition": 0.}}, + 94: {228: {"mass": 228.038732, "composition": 0.}, + 229: {"mass": 229.040144, "composition": 0.}, + 230: {"mass": 230.03965, "composition": 0.}, + 231: {"mass": 231.041102, "composition": 0.}, + 232: {"mass": 232.041185, "composition": 0.}, + 233: {"mass": 233.042998, "composition": 0.}, + 234: {"mass": 234.0433174, "composition": 0.}, + 235: {"mass": 235.045286, "composition": 0.}, + 236: {"mass": 236.0460581, "composition": 0.}, + 237: {"mass": 237.0484098, "composition": 0.}, + 238: {"mass": 238.0495601, "composition": 0.}, + 239: {"mass": 239.0521636, "composition": 0.}, + 240: {"mass": 240.0538138, "composition": 0.}, + 241: {"mass": 241.0568517, "composition": 0.}, + 242: {"mass": 242.0587428, "composition": 0.}, + 243: {"mass": 243.0620036, "composition": 0.}, + 244: {"mass": 244.0642053, "composition": 0.}, + 245: {"mass": 245.067826, "composition": 0.}, + 246: {"mass": 246.070205, "composition": 0.}, + 247: {"mass": 247.07419, "composition": 0.}}, + 95: {230: {"mass": 230.04609, "composition": 0.}, + 231: {"mass": 231.04556, "composition": 0.}, + 232: {"mass": 232.04645, "composition": 0.}, + 233: {"mass": 233.04644, "composition": 0.}, + 234: {"mass": 234.04773, "composition": 0.}, + 235: {"mass": 235.047908, "composition": 0.}, + 236: {"mass": 236.04943, "composition": 0.}, + 237: {"mass": 237.049996, "composition": 0.}, + 238: {"mass": 238.051985, "composition": 0.}, + 239: {"mass": 239.0530247, "composition": 0.}, + 240: {"mass": 240.0553, "composition": 0.}, + 241: {"mass": 241.0568293, "composition": 0.}, + 242: {"mass": 242.0595494, "composition": 0.}, + 243: {"mass": 243.0613813, "composition": 0.}, + 244: {"mass": 244.0642851, "composition": 0.}, + 245: {"mass": 245.0664548, "composition": 0.}, + 246: {"mass": 246.069775, "composition": 0.}, + 247: {"mass": 247.07209, "composition": 0.}, + 248: {"mass": 248.07575, "composition": 0.}, + 249: {"mass": 249.07848, "composition": 0.}}, + 96: {232: {"mass": 232.04982, "composition": 0.}, + 233: {"mass": 233.05077, "composition": 0.}, + 234: {"mass": 234.05016, "composition": 0.}, + 235: {"mass": 235.05154, "composition": 0.}, + 236: {"mass": 236.051374, "composition": 0.}, + 237: {"mass": 237.052869, "composition": 0.}, + 238: {"mass": 238.053081, "composition": 0.}, + 239: {"mass": 239.05491, "composition": 0.}, + 240: {"mass": 240.0555297, "composition": 0.}, + 241: {"mass": 241.0576532, "composition": 0.}, + 242: {"mass": 242.058836, "composition": 0.}, + 243: {"mass": 243.0613893, "composition": 0.}, + 244: {"mass": 244.0627528, "composition": 0.}, + 245: {"mass": 245.0654915, "composition": 0.}, + 246: {"mass": 246.0672238, "composition": 0.}, + 247: {"mass": 247.0703541, "composition": 0.}, + 248: {"mass": 248.0723499, "composition": 0.}, + 249: {"mass": 249.0759548, "composition": 0.}, + 250: {"mass": 250.078358, "composition": 0.}, + 251: {"mass": 251.082286, "composition": 0.}, + 252: {"mass": 252.08487, "composition": 0.}}, + 97: {234: {"mass": 234.05727, "composition": 0.}, + 235: {"mass": 235.05658, "composition": 0.}, + 236: {"mass": 236.05748, "composition": 0.}, + 237: {"mass": 237.0571, "composition": 0.}, + 238: {"mass": 238.0582, "composition": 0.}, + 239: {"mass": 239.05824, "composition": 0.}, + 240: {"mass": 240.05976, "composition": 0.}, + 241: {"mass": 241.06016, "composition": 0.}, + 242: {"mass": 242.06198, "composition": 0.}, + 243: {"mass": 243.0630078, "composition": 0.}, + 244: {"mass": 244.065181, "composition": 0.}, + 245: {"mass": 245.0663618, "composition": 0.}, + 246: {"mass": 246.068673, "composition": 0.}, + 247: {"mass": 247.0703073, "composition": 0.}, + 248: {"mass": 248.073088, "composition": 0.}, + 249: {"mass": 249.0749877, "composition": 0.}, + 250: {"mass": 250.0783167, "composition": 0.}, + 251: {"mass": 251.080762, "composition": 0.}, + 252: {"mass": 252.08431, "composition": 0.}, + 253: {"mass": 253.08688, "composition": 0.}, + 254: {"mass": 254.0906, "composition": 0.}}, + 98: {237: {"mass": 237.062198, "composition": 0.}, + 238: {"mass": 238.06149, "composition": 0.}, + 239: {"mass": 239.06253, "composition": 0.}, + 240: {"mass": 240.062256, "composition": 0.}, + 241: {"mass": 241.06369, "composition": 0.}, + 242: {"mass": 242.063754, "composition": 0.}, + 243: {"mass": 243.06548, "composition": 0.}, + 244: {"mass": 244.0660008, "composition": 0.}, + 245: {"mass": 245.0680487, "composition": 0.}, + 246: {"mass": 246.0688055, "composition": 0.}, + 247: {"mass": 247.070965, "composition": 0.}, + 248: {"mass": 248.0721851, "composition": 0.}, + 249: {"mass": 249.0748539, "composition": 0.}, + 250: {"mass": 250.0764062, "composition": 0.}, + 251: {"mass": 251.0795886, "composition": 0.}, + 252: {"mass": 252.0816272, "composition": 0.}, + 253: {"mass": 253.0851345, "composition": 0.}, + 254: {"mass": 254.087324, "composition": 0.}, + 255: {"mass": 255.09105, "composition": 0.}, + 256: {"mass": 256.09344, "composition": 0.}}, + 99: {239: {"mass": 239.06823, "composition": 0.}, + 240: {"mass": 240.06892, "composition": 0.}, + 241: {"mass": 241.06856, "composition": 0.}, + 242: {"mass": 242.06957, "composition": 0.}, + 243: {"mass": 243.06951, "composition": 0.}, + 244: {"mass": 244.07088, "composition": 0.}, + 245: {"mass": 245.07125, "composition": 0.}, + 246: {"mass": 246.0729, "composition": 0.}, + 247: {"mass": 247.073622, "composition": 0.}, + 248: {"mass": 248.075471, "composition": 0.}, + 249: {"mass": 249.076411, "composition": 0.}, + 250: {"mass": 250.07861, "composition": 0.}, + 251: {"mass": 251.0799936, "composition": 0.}, + 252: {"mass": 252.08298, "composition": 0.}, + 253: {"mass": 253.0848257, "composition": 0.}, + 254: {"mass": 254.0880222, "composition": 0.}, + 255: {"mass": 255.090275, "composition": 0.}, + 256: {"mass": 256.0936, "composition": 0.}, + 257: {"mass": 257.09598, "composition": 0.}, + 258: {"mass": 258.09952, "composition": 0.}}, + 100: {241: {"mass": 241.07421, "composition": 0.}, + 242: {"mass": 242.07343, "composition": 0.}, + 243: {"mass": 243.07446, "composition": 0.}, + 244: {"mass": 244.07404, "composition": 0.}, + 245: {"mass": 245.07535, "composition": 0.}, + 246: {"mass": 246.07535, "composition": 0.}, + 247: {"mass": 247.07694, "composition": 0.}, + 248: {"mass": 248.0771865, "composition": 0.}, + 249: {"mass": 249.0789275, "composition": 0.}, + 250: {"mass": 250.079521, "composition": 0.}, + 251: {"mass": 251.08154, "composition": 0.}, + 252: {"mass": 252.0824671, "composition": 0.}, + 253: {"mass": 253.0851846, "composition": 0.}, + 254: {"mass": 254.0868544, "composition": 0.}, + 255: {"mass": 255.089964, "composition": 0.}, + 256: {"mass": 256.0917745, "composition": 0.}, + 257: {"mass": 257.0951061, "composition": 0.}, + 258: {"mass": 258.09708, "composition": 0.}, + 259: {"mass": 259.1006, "composition": 0.}, + 260: {"mass": 260.10281, "composition": 0.}}, + 101: {245: {"mass": 245.08081, "composition": 0.}, + 246: {"mass": 246.08171, "composition": 0.}, + 247: {"mass": 247.08152, "composition": 0.}, + 248: {"mass": 248.08282, "composition": 0.}, + 249: {"mass": 249.08291, "composition": 0.}, + 250: {"mass": 250.08441, "composition": 0.}, + 251: {"mass": 251.084774, "composition": 0.}, + 252: {"mass": 252.08643, "composition": 0.}, + 253: {"mass": 253.087144, "composition": 0.}, + 254: {"mass": 254.08959, "composition": 0.}, + 255: {"mass": 255.0910841, "composition": 0.}, + 256: {"mass": 256.09389, "composition": 0.}, + 257: {"mass": 257.0955424, "composition": 0.}, + 258: {"mass": 258.0984315, "composition": 0.}, + 259: {"mass": 259.10051, "composition": 0.}, + 260: {"mass": 260.10365, "composition": 0.}, + 261: {"mass": 261.10583, "composition": 0.}, + 262: {"mass": 262.1091, "composition": 0.}}, + 102: {248: {"mass": 248.08655, "composition": 0.}, + 249: {"mass": 249.0878, "composition": 0.}, + 250: {"mass": 250.08756, "composition": 0.}, + 251: {"mass": 251.08894, "composition": 0.}, + 252: {"mass": 252.088967, "composition": 0.}, + 253: {"mass": 253.0905641, "composition": 0.}, + 254: {"mass": 254.090956, "composition": 0.}, + 255: {"mass": 255.093191, "composition": 0.}, + 256: {"mass": 256.0942829, "composition": 0.}, + 257: {"mass": 257.0968878, "composition": 0.}, + 258: {"mass": 258.09821, "composition": 0.}, + 259: {"mass": 259.10103, "composition": 0.}, + 260: {"mass": 260.10264, "composition": 0.}, + 261: {"mass": 261.1057, "composition": 0.}, + 262: {"mass": 262.10746, "composition": 0.}, + 263: {"mass": 263.11071, "composition": 0.}, + 264: {"mass": 264.11273, "composition": 0.}}, + 103: {251: {"mass": 251.09418, "composition": 0.}, + 252: {"mass": 252.09526, "composition": 0.}, + 253: {"mass": 253.09509, "composition": 0.}, + 254: {"mass": 254.09648, "composition": 0.}, + 255: {"mass": 255.096562, "composition": 0.}, + 256: {"mass": 256.098494, "composition": 0.}, + 257: {"mass": 257.099418, "composition": 0.}, + 258: {"mass": 258.10176, "composition": 0.}, + 259: {"mass": 259.102902, "composition": 0.}, + 260: {"mass": 260.1055, "composition": 0.}, + 261: {"mass": 261.10688, "composition": 0.}, + 262: {"mass": 262.10961, "composition": 0.}, + 263: {"mass": 263.11136, "composition": 0.}, + 264: {"mass": 264.1142, "composition": 0.}, + 265: {"mass": 265.11619, "composition": 0.}, + 266: {"mass": 266.11983, "composition": 0.}}, + 104: {253: {"mass": 253.10044, "composition": 0.}, + 254: {"mass": 254.10005, "composition": 0.}, + 255: {"mass": 255.10127, "composition": 0.}, + 256: {"mass": 256.101152, "composition": 0.}, + 257: {"mass": 257.102918, "composition": 0.}, + 258: {"mass": 258.103428, "composition": 0.}, + 259: {"mass": 259.105596, "composition": 0.}, + 260: {"mass": 260.10644, "composition": 0.}, + 261: {"mass": 261.108773, "composition": 0.}, + 262: {"mass": 262.10992, "composition": 0.}, + 263: {"mass": 263.11249, "composition": 0.}, + 264: {"mass": 264.11388, "composition": 0.}, + 265: {"mass": 265.11668, "composition": 0.}, + 266: {"mass": 266.11817, "composition": 0.}, + 267: {"mass": 267.12179, "composition": 0.}, + 268: {"mass": 268.12397, "composition": 0.}}, + 105: {255: {"mass": 255.10707, "composition": 0.}, + 256: {"mass": 256.10789, "composition": 0.}, + 257: {"mass": 257.10758, "composition": 0.}, + 258: {"mass": 258.10928, "composition": 0.}, + 259: {"mass": 259.109492, "composition": 0.}, + 260: {"mass": 260.1113, "composition": 0.}, + 261: {"mass": 261.11192, "composition": 0.}, + 262: {"mass": 262.11407, "composition": 0.}, + 263: {"mass": 263.11499, "composition": 0.}, + 264: {"mass": 264.11741, "composition": 0.}, + 265: {"mass": 265.11861, "composition": 0.}, + 266: {"mass": 266.12103, "composition": 0.}, + 267: {"mass": 267.12247, "composition": 0.}, + 268: {"mass": 268.12567, "composition": 0.}, + 269: {"mass": 269.12791, "composition": 0.}, + 270: {"mass": 270.13136, "composition": 0.}}, + 106: {258: {"mass": 258.11298, "composition": 0.}, + 259: {"mass": 259.1144, "composition": 0.}, + 260: {"mass": 260.114384, "composition": 0.}, + 261: {"mass": 261.115949, "composition": 0.}, + 262: {"mass": 262.116337, "composition": 0.}, + 263: {"mass": 263.11829, "composition": 0.}, + 264: {"mass": 264.11893, "composition": 0.}, + 265: {"mass": 265.12109, "composition": 0.}, + 266: {"mass": 266.12198, "composition": 0.}, + 267: {"mass": 267.12436, "composition": 0.}, + 268: {"mass": 268.12539, "composition": 0.}, + 269: {"mass": 269.12863, "composition": 0.}, + 270: {"mass": 270.13043, "composition": 0.}, + 271: {"mass": 271.13393, "composition": 0.}, + 272: {"mass": 272.13589, "composition": 0.}, + 273: {"mass": 273.13958, "composition": 0.}}, + 107: {260: {"mass": 260.12166, "composition": 0.}, + 261: {"mass": 261.12145, "composition": 0.}, + 262: {"mass": 262.12297, "composition": 0.}, + 263: {"mass": 263.12292, "composition": 0.}, + 264: {"mass": 264.12459, "composition": 0.}, + 265: {"mass": 265.12491, "composition": 0.}, + 266: {"mass": 266.12679, "composition": 0.}, + 267: {"mass": 267.1275, "composition": 0.}, + 268: {"mass": 268.12969, "composition": 0.}, + 269: {"mass": 269.13042, "composition": 0.}, + 270: {"mass": 270.13336, "composition": 0.}, + 271: {"mass": 271.13526, "composition": 0.}, + 272: {"mass": 272.13826, "composition": 0.}, + 273: {"mass": 273.14024, "composition": 0.}, + 274: {"mass": 274.14355, "composition": 0.}, + 275: {"mass": 275.14567, "composition": 0.}}, + 108: {263: {"mass": 263.12852, "composition": 0.}, + 264: {"mass": 264.128357, "composition": 0.}, + 265: {"mass": 265.129793, "composition": 0.}, + 266: {"mass": 266.130046, "composition": 0.}, + 267: {"mass": 267.13167, "composition": 0.}, + 268: {"mass": 268.13186, "composition": 0.}, + 269: {"mass": 269.13375, "composition": 0.}, + 270: {"mass": 270.13429, "composition": 0.}, + 271: {"mass": 271.13717, "composition": 0.}, + 272: {"mass": 272.1385, "composition": 0.}, + 273: {"mass": 273.14168, "composition": 0.}, + 274: {"mass": 274.1433, "composition": 0.}, + 275: {"mass": 275.14667, "composition": 0.}, + 276: {"mass": 276.14846, "composition": 0.}, + 277: {"mass": 277.1519, "composition": 0.}}, + 109: {265: {"mass": 265.136, "composition": 0.}, + 266: {"mass": 266.13737, "composition": 0.}, + 267: {"mass": 267.13719, "composition": 0.}, + 268: {"mass": 268.13865, "composition": 0.}, + 269: {"mass": 269.13882, "composition": 0.}, + 270: {"mass": 270.14033, "composition": 0.}, + 271: {"mass": 271.14074, "composition": 0.}, + 272: {"mass": 272.14341, "composition": 0.}, + 273: {"mass": 273.1444, "composition": 0.}, + 274: {"mass": 274.14724, "composition": 0.}, + 275: {"mass": 275.14882, "composition": 0.}, + 276: {"mass": 276.15159, "composition": 0.}, + 277: {"mass": 277.15327, "composition": 0.}, + 278: {"mass": 278.15631, "composition": 0.}, + 279: {"mass": 279.15808, "composition": 0.}}, + 110: {267: {"mass": 267.14377, "composition": 0.}, + 268: {"mass": 268.14348, "composition": 0.}, + 269: {"mass": 269.144752, "composition": 0.}, + 270: {"mass": 270.144584, "composition": 0.}, + 271: {"mass": 271.14595, "composition": 0.}, + 272: {"mass": 272.14602, "composition": 0.}, + 273: {"mass": 273.14856, "composition": 0.}, + 274: {"mass": 274.14941, "composition": 0.}, + 275: {"mass": 275.15203, "composition": 0.}, + 276: {"mass": 276.15303, "composition": 0.}, + 277: {"mass": 277.15591, "composition": 0.}, + 278: {"mass": 278.15704, "composition": 0.}, + 279: {"mass": 279.1601, "composition": 0.}, + 280: {"mass": 280.16131, "composition": 0.}, + 281: {"mass": 281.16451, "composition": 0.}}, + 111: {272: {"mass": 272.15327, "composition": 0.}, + 273: {"mass": 273.15313, "composition": 0.}, + 274: {"mass": 274.15525, "composition": 0.}, + 275: {"mass": 275.15594, "composition": 0.}, + 276: {"mass": 276.15833, "composition": 0.}, + 277: {"mass": 277.15907, "composition": 0.}, + 278: {"mass": 278.16149, "composition": 0.}, + 279: {"mass": 279.16272, "composition": 0.}, + 280: {"mass": 280.16514, "composition": 0.}, + 281: {"mass": 281.16636, "composition": 0.}, + 282: {"mass": 282.16912, "composition": 0.}, + 283: {"mass": 283.17054, "composition": 0.}}, + 112: {276: {"mass": 276.16141, "composition": 0.}, + 277: {"mass": 277.16364, "composition": 0.}, + 278: {"mass": 278.16416, "composition": 0.}, + 279: {"mass": 279.16654, "composition": 0.}, + 280: {"mass": 280.16715, "composition": 0.}, + 281: {"mass": 281.16975, "composition": 0.}, + 282: {"mass": 282.1705, "composition": 0.}, + 283: {"mass": 283.17327, "composition": 0.}, + 284: {"mass": 284.17416, "composition": 0.}, + 285: {"mass": 285.17712, "composition": 0.}}, + 113: {278: {"mass": 278.17058, "composition": 0.}, + 279: {"mass": 279.17095, "composition": 0.}, + 280: {"mass": 280.17293, "composition": 0.}, + 281: {"mass": 281.17348, "composition": 0.}, + 282: {"mass": 282.17567, "composition": 0.}, + 283: {"mass": 283.17657, "composition": 0.}, + 284: {"mass": 284.17873, "composition": 0.}, + 285: {"mass": 285.17973, "composition": 0.}, + 286: {"mass": 286.18221, "composition": 0.}, + 287: {"mass": 287.18339, "composition": 0.}}, + 114: {285: {"mass": 285.18364, "composition": 0.}, + 286: {"mass": 286.18423, "composition": 0.}, + 287: {"mass": 287.18678, "composition": 0.}, + 288: {"mass": 288.18757, "composition": 0.}, + 289: {"mass": 289.19042, "composition": 0.}}, + 115: {287: {"mass": 287.1907, "composition": 0.}, + 288: {"mass": 288.19274, "composition": 0.}, + 289: {"mass": 289.19363, "composition": 0.}, + 290: {"mass": 290.19598, "composition": 0.}, + 291: {"mass": 291.19707, "composition": 0.}}, + 116: {289: {"mass": 289.19816, "composition": 0.}, + 290: {"mass": 290.19864, "composition": 0.}, + 291: {"mass": 291.20108, "composition": 0.}, + 292: {"mass": 292.20174, "composition": 0.}, + 293: {"mass": 293.20449, "composition": 0.}}, + 117: {291: {"mass": 291.20553, "composition": 0.}, + 292: {"mass": 292.20746, "composition": 0.}, + 293: {"mass": 293.20824, "composition": 0.}, + 294: {"mass": 294.21046, "composition": 0.}}, + 118: {293: {"mass": 293.21356, "composition": 0.}, + 294: {"mass": 294.21392, "composition": 0.}, + 295: {"mass": 295.21624, "composition": 0.}}} diff --git a/ifes_apt_tc_data_modeling/utils/string_handling.py b/ifes_apt_tc_data_modeling/utils/string_handling.py index 8a75f3e..2294a9a 100644 --- a/ifes_apt_tc_data_modeling/utils/string_handling.py +++ b/ifes_apt_tc_data_modeling/utils/string_handling.py @@ -1,4 +1,3 @@ -# Utility string mangling when parsing data in atom probe microscopy. # # Also convenience functions are included which translate human-readable ion # names into the isotope_vector description proposed by Kuehbach et al. in @@ -22,6 +21,8 @@ # limitations under the License. # +"""Utility string mangling when parsing data in atom probe microscopy.""" + def rchop(string: str = "", suffix: str = "") -> str: """Right-chop a string.""" diff --git a/ifes_apt_tc_data_modeling/utils/utils.py b/ifes_apt_tc_data_modeling/utils/utils.py index c9c2835..fd92002 100644 --- a/ifes_apt_tc_data_modeling/utils/utils.py +++ b/ifes_apt_tc_data_modeling/utils/utils.py @@ -1,9 +1,3 @@ -# Utilities for parsing data and molecular ions in atom probe microscopy. -# -# Also convenience functions are included which translate human-readable ion -# names into the isotope_vector description proposed by Kuehbach et al. in -# DOI: 10.1017/S1431927621012241 to the human-readable ion names which are use -# in P. Felfer et al.'s atom probe toolbox # # Copyright The NOMAD Authors. # @@ -22,8 +16,15 @@ # limitations under the License. # +"""Utilities for parsing data and molecular ions in atom probe microscopy.""" + # pylint: disable=no-member,duplicate-code +# Also convenience functions are included which translate human-readable ion +# names into the isotope_vector description proposed by Kuehbach et al. in +# DOI: 10.1017/S1431927621012241 to the human-readable ion names which are use +# in P. Felfer et al.'s atom probe toolbox + from typing import Tuple import numpy as np @@ -38,9 +39,9 @@ def isotope_to_hash(proton_number: int = 0, """Encode an isotope to a hashvalue.""" n_protons = np.uint16(proton_number) n_neutrons = np.uint16(neutron_number) - assert (n_protons >= np.uint16(0)) and (n_protons < np.uint16(256)), \ + assert np.uint16(0) <= n_protons < np.uint16(256), \ "Argument proton number on [0, 256) needed!" - assert (n_neutrons >= np.uint16(0)) and (n_neutrons < np.uint16(256)), \ + assert np.uint(0) <= n_neutrons < np.uint16(256), \ "Argument neutron number on [0, 256) needed!" hashvalue = int(n_protons + (np.uint16(256) * n_neutrons)) return hashvalue @@ -85,23 +86,23 @@ def create_isotope_vector(building_blocks: list) -> np.ndarray: "Argument block has to be a non-empty string!" if block.count("-") == 0: assert (block in symbol_to_proton_number) and (block != "X"), \ - block + " is not a valid chemical symbol!" + f"{block} is not a valid chemical symbol!" proton_number = symbol_to_proton_number[block] neutron_number = 0 hashvector.append(isotope_to_hash(proton_number, neutron_number)) elif block.count("-") == 1: symb_mass = block.split("-") assert len(symb_mass) == 2, \ - block + " is not properly formatted -!" + f"{block} is not properly formatted -!" assert (symb_mass[0] in symbol_to_proton_number) and (symb_mass[0] != "X"), \ - symb_mass[0] + " is not a valid chemical symbol!" + f"{symb_mass[0]} is not a valid chemical symbol!" proton_number = symbol_to_proton_number[symb_mass[0]] mass_number = int(symb_mass[1]) neutron_number = mass_number - proton_number - assert proton_number in isotopes.keys(), \ - "No isotopes for proton_number " + str(proton_number) + " via ase!" + assert proton_number in isotopes, \ + f"No isotopes for proton_number {proton_number} via ase!" assert mass_number in isotopes[proton_number], \ - "No isotope for mass_number " + str(mass_number) + " via ase!" + f"No isotope for mass_number {mass_number} via ase!" hashvector.append(isotope_to_hash(proton_number, neutron_number)) else: print(f"WARNING: {block} does not specify a unique element name!") From 8c4609135d4ffb61d0d6045e69e5f8810ebd1747 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Fri, 29 Dec 2023 12:59:22 +0100 Subject: [PATCH 04/20] Further styling and linting --- ifes_apt_tc_data_modeling/apt/apt6_reader.py | 43 +++----- .../apt/apt6_sections.py | 100 +++++------------- ifes_apt_tc_data_modeling/apt/apt6_utils.py | 21 ++-- ifes_apt_tc_data_modeling/env/env_reader.py | 2 +- ifes_apt_tc_data_modeling/nexus/nx_field.py | 2 +- ifes_apt_tc_data_modeling/nexus/nx_ion.py | 11 +- .../pyccapt/pyccapt_reader.py | 6 +- ifes_apt_tc_data_modeling/rng/rng_reader.py | 2 +- ifes_apt_tc_data_modeling/rrng/rrng_reader.py | 29 +++-- .../utils/definitions.py | 3 - ifes_apt_tc_data_modeling/utils/utils.py | 11 +- linting.sh | 8 ++ tests/TestsForDevelopers.ipynb | 14 ++- 13 files changed, 95 insertions(+), 157 deletions(-) create mode 100755 linting.sh diff --git a/ifes_apt_tc_data_modeling/apt/apt6_reader.py b/ifes_apt_tc_data_modeling/apt/apt6_reader.py index 23c231a..a88c94a 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_reader.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_reader.py @@ -36,13 +36,12 @@ class ReadAptFileFormat(): """Read AMETEK's open exchange *.apt file format.""" def __init__(self, filename: str): - assert len(filename) > 4, 'APT file incorrect filename ending!' - assert filename.lower().endswith('.apt'), \ - 'APT file incorrect file type!' + if (len(filename) <= 4) or (filename.lower().endswith(".apt") is False): + raise ImportError("WARNING::APT file incorrect filename ending or file type!") self.filename = filename self.filesize = os.path.getsize(self.filename) - print('Reading ' + self.filename + ' which is ' + str(self.filesize) + ' bytes') + print(f"Reading {self.filename} which is {self.filesize} B") self.header_section = None self.byte_offsets: dict = {} @@ -81,10 +80,9 @@ def parse_file_structure(self): count=1) assert self.dummy_header.matches(found_header), \ - 'Found an unexpectedly formatted/versioned header! \ - Please contact the development team to help us inspect \ - the matter.' - print('File describes ' + str(found_header['llIonCount'][0]) + ' ions') + f"Found an unexpectedly formatted/versioned header." \ + f"Create an issue to help us fix this!" + print(f"File describes {found_header['llIonCount'][0]} ions") self.header_section = found_header self.byte_offsets['header'] = np.uint64(file_handle.tell()) @@ -97,7 +95,7 @@ def parse_file_structure(self): if end_of_file_not_reached != b'': file_handle.seek(-1, os.SEEK_CUR) else: - print('End of file at ' + str(file_handle.tell()) + ' bytes') + print(f"End of file at {file_handle.tell()} B") break dummy_section = AptFileSectionMetadata() @@ -110,16 +108,13 @@ def parse_file_structure(self): print(keyword) print(found_section) assert keyword not in self.available_sections, \ - 'Found a duplicate of an already parsed section! Please \ - contact the development team as we have never encountered \ - an example of such a section duplication and here seems \ - to be an example to inspect the matter.' + f"Found a duplicate of an already parsed section!" \ + f"Create an issue to help us fix this!" if keyword not in ['Delta Pulse', 'Epos ToF']: assert keyword in EXPECTED_SECTIONS, \ - 'Found an unknown section, seems like an unknown/new \ - branch! Please contact the development team to enable us \ - to contact AMETEK and discuss the situation.' + f"Found an unknown section, seems like an unknown/new branch!" \ + f"Create an issue to help us fix this!" metadata_section = EXPECTED_SECTIONS[keyword] if metadata_section.matches(found_section) is True: @@ -128,12 +123,9 @@ def parse_file_structure(self): # development team to help us fixing this.' self.available_sections[keyword] = metadata_section else: - print('WARNING:: Found an uninterpretable section!') - print('WARNING:: This section was not be registered!') - print('WARNING:: Please contact the development team!') - print('WARNING:: to help us improving this!') - print('WARNING:: Try to continue parsing though...!') - print('llByteCount ' + str(found_section['llByteCount'][0])) + print(f"Found an uninterpretable non-registered section." + f"Create an issue to help us fix this!, Parsing continues" + f"llByteCount {found_section['llByteCount'][0]} B") self.byte_offsets[keyword] = np.uint64(file_handle.tell()) if keyword == 'Position': @@ -141,8 +133,8 @@ def parse_file_structure(self): self.byte_offsets[keyword] += np.uint64(6 * 4) self.byte_offsets[keyword] += np.uint64( found_section['llByteCount'][0]) - print('Byte offset for reading data for section: ' + keyword) - print(self.byte_offsets[keyword]) + print(f"Byte offset for reading data for section: {keyword}" + f" {self.byte_offsets[keyword]} B") # print(file_handle.tell()) file_handle.seek(self.byte_offsets[keyword], os.SEEK_SET) # print(file_handle.tell()) @@ -182,8 +174,7 @@ def get_metadata_table(self): """Create table from all metadata for each section.""" column_names = ['section'] # header assert 'Mass' in self.available_sections, \ - 'Cannot create table, Mass section not available to guide \ - the creation of the table header!' + "Mass section not available to guide creation of the table header!" for key in self.available_sections['Mass'].get_metadata().keys(): column_names.append(key) data_frame = pd.DataFrame(columns=column_names) diff --git a/ifes_apt_tc_data_modeling/apt/apt6_sections.py b/ifes_apt_tc_data_modeling/apt/apt6_sections.py index 6f70e93..baa00bf 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_sections.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_sections.py @@ -275,7 +275,7 @@ def get_ametek_type(self) -> str: + ' get_ametek_type() detected unsupported real type!' # return real_dtypes[byte_length] return ' np.uint64: """Interpret how many quantities from AMETEK defs.""" @@ -299,73 +299,46 @@ def matches(self, found_section: np.ndarray) -> bool: # check if the parsed section's metadata are matching # AMETEK expectations, i.e. meeting manufacturers definitions? assert np.array_equal(self.meta['c_signature'], found_section['cSignature'][0], - equal_nan=True), 'Section cSignature differs, \ - is ' + np_uint16_to_string(found_section['cSignature'][0]) \ - + ' but should be ' + np_uint16_to_string(self.meta['c_signature']) - + equal_nan=True), \ + f"Section cSignature differs, is {np_uint16_to_string(found_section['cSignature'][0])}" \ + f" but should be {np_uint16_to_string(self.meta['c_signature'])}" assert found_section['iHeaderSize'][0] == self.meta['i_header_size'], \ - 'Section iHeaderSize differs, is ' \ - + str(found_section['iHeaderSize'][0]) \ - + ' but should be ' + str(self.meta['i_header_size']) - + f"Section iHeaderSize differs, is {found_section['iHeaderSize'][0]}" \ + f" but should be {self.meta['i_header_size']}" assert found_section['iHeaderVersion'][0] == self.meta['i_header_version'], \ - 'Section iHeaderVersion differs, is ' \ - + str(found_section['iHeaderVersion'][0]) \ - + ' but should be ' + str(self.meta['i_header_version']) - + f"Section iHeaderVersion differs, is {found_section['iHeaderVersion'][0]}" \ + f" but should be {self.meta['i_header_version']}" assert found_section['iSectionVersion'][0] == self.meta['i_section_version'], \ - 'Section iSectionVersion differs, is ' \ - + str(found_section['iSectionVersion'][0]) \ - + ' but should be ' + str(self.meta['i_section_version']) - - assert found_section['eRelationshipType'][0] \ - == self.meta['e_relationship_type'], \ - 'Section eRelationshipType differs, is ' \ - + str(found_section['eRelationshipType'][0]) \ - + ' but should be ' + str(self.meta['e_relationship_type']) - + f"Section iSectionVersion differs, is {found_section['iSectionVersion'][0]}" \ + f" but should be {self.meta['i_section_version']}" + assert found_section['eRelationshipType'][0] == self.meta['e_relationship_type'], \ + f"Section eRelationshipType differs, is {found_section['eRelationshipType'][0]}" \ + f" but should be {self.meta['e_relationship_type']}" assert found_section['eRecordType'][0] == self.meta['e_record_type'], \ - 'Section eRecordType differs, is ' \ - + str(found_section['eRecordType'][0]) \ - + ' but should be ' + str(self.meta['e_record_type']) - - assert found_section['eRecordDataType'][0] \ - == self.meta['e_record_data_type'], \ - 'Section eRecordDataType differs, is ' \ - + str(found_section['eRecordDataType'][0]) \ - + ' but should be ' + str(self.meta['e_record_data_type']) - + f"Section eRecordType differs, is {found_section['eRecordType'][0]}" \ + f" but should be {self.meta['e_record_type']}" + assert found_section['eRecordDataType'][0] == self.meta['e_record_data_type'], \ + f"Section eRecordDataType differs, is {found_section['eRecordDataType'][0]}" \ + f" but should be {self.meta['e_record_data_type']}" assert found_section['iDataTypeSize'][0] == self.meta['i_data_type_size'], \ - 'Section iDataTypeSize differs, is ' \ - + str(found_section['iDataTypeSize'][0]) + ' but should be ' \ - + str(self.meta['i_data_type_size']) - + f"Section iDataTypeSize differs, is {found_section['iDataTypeSize'][0]}" \ + f" but should be {self.meta['i_data_type_size']}" assert found_section['iRecordSize'][0] == self.meta['i_record_size'], \ - 'Section iRecordSize differs, is ' \ - + str(found_section['iRecordSize'][0]) + ' but should be ' \ - + str(self.meta['i_record_size']) - + f"Section iRecordSize differs, is {found_section['iRecordSize'][0]}" \ + f" but should be {self.meta['i_record_size']}" # ureg = UnitRegistry() # ureg.define('da = Da = amu') - # check if wcDataUnit is of correct quantity - assert np_uint16_to_string(found_section['wcDataUnit'][0]) \ - in self.accepted_units, 'Section wcDataUnit differs, is ' \ - + np_uint16_to_string(found_section['wcDataUnit'][0]) \ - + ' but should be from accepted_units: ' \ - + ', '.join(self.accepted_units) + assert np_uint16_to_string(found_section['wcDataUnit'][0]) in self.accepted_units, \ + f"Section wcDataUnit differs, is {np_uint16_to_string(found_section['wcDataUnit'][0])}" \ + f" but should be from accepted_units: {', '.join(self.accepted_units)}" # Q = ureg.Quantity(1, 'amu') # use pint for checking compatible base unit - # check also special cases which this parser currently cannot handle - # i.e. meeting what we as the community know about the format - # and thus can handle only assert found_section['llByteCount'][0] > 0, \ - 'Section llByteCount indicates llByteCount is not > 0 !' - + "Section llByteCount indicates llByteCount is not > 0 !" # modify dynamic quanities that can only be inferred from the file self.meta['ll_record_count'] = found_section['llRecordCount'][0] self.meta['ll_byte_count'] = found_section['llByteCount'][0] - return True def get_metadata(self) -> dict: @@ -388,24 +361,5 @@ def get_metadata(self) -> dict: 'AmetekSize': self.get_ametek_size(), 'AmetekType': self.get_ametek_type(), 'AmetekCount': self.get_ametek_count(), - 'AmetekShape': ', '.join([str(x) - for x in self.get_ametek_shape()]) + 'AmetekShape': ', '.join([f"{x}" for x in self.get_ametek_shape()]) } - - # def set_ll_record_count(self, value: int): - # assert isinstance(value, int), \ - # 'llRecordCount needs to be an int!' - # assert value >= 0, \ - # 'llRecordCount needs to be at least zero!' - # assert value <= np.iinfo(np.int64).max, 'llRecordCount needs to be \ - # at most '+(str(np.iinfo(np.int64).max))+'!' - # self.meta['ll_record_count'] = np.int64(0) - - # def set_ll_byte_count(self, value: int): - # assert isinstance(value, int), \ - # 'llByteCount needs to be an int!' - # assert value >= 0, \ - # 'llByteCount needs to be at least zero!' - # assert value <= np.iinfo(np.int64).max, 'llRecordCount needs to be \ - # at most '+(str(np.iinfo(np.int64).max))+'!' - # self.meta['ll_byte_count'] = np.int64(0) diff --git a/ifes_apt_tc_data_modeling/apt/apt6_utils.py b/ifes_apt_tc_data_modeling/apt/apt6_utils.py index 0a8dc9c..45edbe4 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_utils.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_utils.py @@ -29,16 +29,15 @@ def np_uint16_to_string(uint16_array: np.ndarray) -> str: for value in uint16_array: if value != 0: # '\x00' str_parsed += chr(value) - return str(str_parsed) + return f"{str_parsed}" -def string_to_typed_nparray(string: str, length: int, - dtype: type) -> np.ndarray: - """Create fixed length np.uint16 numpy array from string.""" - assert dtype is not None, 'dtype must not be None!' - assert len(string) <= length, 'Input string is longer than \ - number of array elements !' - nparray = np.zeros(length, dtype) - for value in np.arange(0, len(string)): - nparray[value] = ord(string[value]) - return nparray +def string_to_typed_nparray(string: str, length: int, dtyp: type) -> np.ndarray: + """Create length long specifically typed numpy array from string.""" + if (isinstance(dtyp, type) is True) and (len(string) <= length): + nparr = np.zeros(length, dtype=dtyp) # type: ignore + for value in np.arange(0, len(string)): + nparr[value] = ord(string[value]) + return nparr + else: + raise ValueError(f"{dtyp} is either not a type or {string} is not <= {length}!") diff --git a/ifes_apt_tc_data_modeling/env/env_reader.py b/ifes_apt_tc_data_modeling/env/env_reader.py index f1fe1e3..5afd359 100644 --- a/ifes_apt_tc_data_modeling/env/env_reader.py +++ b/ifes_apt_tc_data_modeling/env/env_reader.py @@ -44,7 +44,7 @@ def get_smart_chemical_symbols(): return priority_queue -def evaluate_env_range_line(line: str) -> dict: +def evaluate_env_range_line(line: str): """Represent information content of a single range line.""" # example line: ". 107.7240 108.0960 1 0 0 0 0 0 0 0 0 0 3 0 0 0" info: dict = {} diff --git a/ifes_apt_tc_data_modeling/nexus/nx_field.py b/ifes_apt_tc_data_modeling/nexus/nx_field.py index 8fb4aff..52ad007 100644 --- a/ifes_apt_tc_data_modeling/nexus/nx_field.py +++ b/ifes_apt_tc_data_modeling/nexus/nx_field.py @@ -27,7 +27,7 @@ class NxField(): """Representative of a NeXus field.""" - def __init__(self, typed_value=None, unit: str = None): + def __init__(self, typed_value=None, unit: str = ""): self.parent = None self.is_a = None # ontology reference concept ID e.g. self.typed_value = typed_value diff --git a/ifes_apt_tc_data_modeling/nexus/nx_ion.py b/ifes_apt_tc_data_modeling/nexus/nx_ion.py index e23ea10..1705b53 100644 --- a/ifes_apt_tc_data_modeling/nexus/nx_ion.py +++ b/ifes_apt_tc_data_modeling/nexus/nx_ion.py @@ -52,12 +52,10 @@ def __init__(self, *args, **kwargs): elif "isotope_vector" in kwargs: assert isinstance(kwargs["isotope_vector"], np.ndarray), \ "kwargs isotope_vector needs to be an np.ndarray !" - assert np.shape(kwargs["isotope_vector"]) \ - == (MAX_NUMBER_OF_ATOMS_PER_ION,), \ - "kwargs isotope_vector needs be a " \ - + "(" + str(MAX_NUMBER_OF_ATOMS_PER_ION) + ",) array!" - self.isotope_vector \ - = NxField(np.asarray(kwargs["isotope_vector"], np.uint16), "") + assert np.shape(kwargs["isotope_vector"]) == (MAX_NUMBER_OF_ATOMS_PER_ION,), \ + f"kwargs isotope_vector needs be a ({MAX_NUMBER_OF_ATOMS_PER_ION},) array!" + self.isotope_vector = NxField(np.asarray(kwargs["isotope_vector"], + np.uint16), "") else: # the default UNKNOWN IONTYPE self.isotope_vector = NxField(create_isotope_vector([]), "") @@ -139,7 +137,6 @@ def add_charge_state_model(self, if key not in self.charge_state_model: self.charge_state_model[key] = val n_cand = len(candidates) - # print("n_cand " + str(n_cand)) if n_cand > 0: self.charge_state_model["isotope_matrix"] = np.zeros( (n_cand, MAX_NUMBER_OF_ATOMS_PER_ION), np.uint16) diff --git a/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py b/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py index 0c276f1..690fd4f 100644 --- a/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py +++ b/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py @@ -92,11 +92,10 @@ def __init__(self, filename: str): assert filename.lower().endswith(".h5") or filename.lower().endswith(".hdf5"), \ "HDF5 file incorrect file type!" self.filename = filename - self.filesize = os.path.getsize(self.filename) self.number_of_events = None self.version = "e955beb4f2627befb8b4d26f2e74e4c52e00394e" - self.df = None + self.df: dict = {} with h5py.File(self.filename, "r") as h5r: self.supported = 0 # voting-based @@ -114,7 +113,7 @@ def __init__(self, filename: str): return self.df = pd.read_hdf(self.filename) - self.number_of_events = np.shape(self.df)[0] + self.number_of_events = len(self.df) def get_named_quantities(self, term: str): if term in self.df.keys(): @@ -123,7 +122,6 @@ def get_named_quantities(self, term: str): def get_reconstructed_positions(self): """Read xyz columns.""" - xyz = NxField() xyz.typed_value = np.zeros( [self.number_of_events, 3], np.float32) diff --git a/ifes_apt_tc_data_modeling/rng/rng_reader.py b/ifes_apt_tc_data_modeling/rng/rng_reader.py index 68aa136..26ca9f1 100644 --- a/ifes_apt_tc_data_modeling/rng/rng_reader.py +++ b/ifes_apt_tc_data_modeling/rng/rng_reader.py @@ -42,7 +42,7 @@ def evaluate_rng_range_line( """Represent information content of a single range line.""" # example line: ". 107.7240 108.0960 1 0 0 0 0 0 0 0 0 0 3 0 0 0" info: dict = {} - info["identifier"] = "Range" + str(i) + info["identifier"] = f"Range{i}" info["range"] = np.asarray([0., MQ_EPSILON], np.float64) info["atoms"] = [] info["volume"] = np.float64(0.) diff --git a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py index 05b85e7..66b3422 100644 --- a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py +++ b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py @@ -42,7 +42,7 @@ def evaluate_rrng_range_line(i: int, line: str) -> dict: # mqmin, mqmax, vol, ion composition is required, # name and color fields are optional info: dict = {} - info["identifier"] = "Range" + str(i) + info["identifier"] = f"Range{i}" info["range"] = np.asarray([0., MQ_EPSILON], np.float64) info["atoms"] = [] info["volume"] = np.float64(0.) @@ -50,13 +50,13 @@ def evaluate_rrng_range_line(i: int, line: str) -> dict: info["name"] = "" tmp = re.split(r"[\s=]+", line) - assert len(tmp) >= 6, "Line " + line + \ - " does not contain all required fields!" - assert tmp[0] == "Range" + str(i), "Line " + line + \ - " has inconsistent line prefix!" + assert len(tmp) >= 6, \ + f"Line {line} does not contain all required fields!" + assert tmp[0] == f"Range{i}" \ + f"Line {line} has inconsistent line prefix!" assert is_range_significant(np.float64(tmp[1]), np.float64(tmp[2])), \ - "Line " + line + " insignificant range!" + f"Line {line} insignificant range!" info["range"] = np.asarray([tmp[1], tmp[2]], np.float64) if tmp[3].lower().startswith("vol:"): @@ -75,7 +75,7 @@ def evaluate_rrng_range_line(i: int, line: str) -> dict: "Element multiplicity is incorrectly formatted!" # skip vol, name, and color information if element_multiplicity[0].lower() == "name": - info["name"] = str(element_multiplicity[1]) + info["name"] = f"{element_multiplicity[1]}" # this captures properly formatted ranges with keyword # name whose name value is then however not a chemical # symbol but some user-defined string @@ -84,11 +84,11 @@ def evaluate_rrng_range_line(i: int, line: str) -> dict: # pick up what is an element name symbol = element_multiplicity[0] assert (symbol in chemical_symbols) and (symbol != "X"), \ - "Line " + line + " contains an invalid chemical symbol!" + f"Line {line} contains an invalid chemical symbol!" assert np.uint32(element_multiplicity[1]) > 0, \ - "Line " + line + " zero or negative multiplicity!" + f"Line {line} zero or negative multiplicity!" assert np.uint32(element_multiplicity[1]) < 256, \ - "Line " + line + " unsupport high multiplicity!" + f"Line {line} unsupported high multiplicity!" info["atoms"] = np.append( info["atoms"], [symbol] * int(element_multiplicity[1])) return info @@ -102,7 +102,6 @@ def __init__(self, filename: str): if (len(filename) <= 5) or (filename.lower().endswith(".rrng") is False): raise ImportError("WARNING::RRNG file incorrect filename ending or file type!") self.filename = filename - self.rrng: dict = {} self.rrng["ionnames"] = [] self.rrng["ranges"] = {} @@ -145,10 +144,9 @@ def read_rrng(self): for i in np.arange(0, number_of_ion_names): tmp = re.split(r"[\s=]+", txt_stripped[current_line_id + i]) assert len(tmp) == 2, "[Ions]/Ion line corrupted!" - assert tmp[0] == "Ion" + str(i + 1), \ - "[Ions]/Ion incorrectly formatted!" + assert tmp[0] == f"Ion{i + 1}", "[Ions]/Ion incorrectly formatted!" assert isinstance(tmp[1], str), "[Ions]/Name not a string!" - self.rrng["ionnames"].append(tmp[1]) # [tmp[0]] = tmp[1] + self.rrng["ionnames"].append(tmp[1]) # second, parse [Ranges] section where = [idx for idx, element in @@ -167,8 +165,7 @@ def read_rrng(self): for i in np.arange(0, number_of_ranges): dct = evaluate_rrng_range_line(i + 1, txt_stripped[current_line_id + i]) - assert dct, \ - "Line " + txt_stripped[current_line_id + i] + " is corrupted!" + assert dct, f"Line {txt_stripped[current_line_id + i]} is corrupted!" m_ion = NxIon(isotope_vector=create_isotope_vector( dct["atoms"]), charge_state=0) diff --git a/ifes_apt_tc_data_modeling/utils/definitions.py b/ifes_apt_tc_data_modeling/utils/definitions.py index c5e65bb..a59d41e 100644 --- a/ifes_apt_tc_data_modeling/utils/definitions.py +++ b/ifes_apt_tc_data_modeling/utils/definitions.py @@ -23,11 +23,8 @@ """Generic definitions when parsing molecular ions in atom probe microscopy.""" -# pylint: disable=no-member,duplicate-code - import numpy as np - # restrict the number distinguished ion types MAX_NUMBER_OF_ION_SPECIES = 256 # restrict number of atoms for molecular ion fragments diff --git a/ifes_apt_tc_data_modeling/utils/utils.py b/ifes_apt_tc_data_modeling/utils/utils.py index fd92002..6720428 100644 --- a/ifes_apt_tc_data_modeling/utils/utils.py +++ b/ifes_apt_tc_data_modeling/utils/utils.py @@ -133,8 +133,8 @@ def isotope_vector_to_dict_keyword(ivec: np.ndarray) -> str: lst = [] for hashvalue in ivec: if hashvalue != 0: - lst.append(str(hashvalue)) - if lst != []: + lst.append(f"{hashvalue}") + if len(lst) > 0: return "_".join(lst) return "0" # "_".join(np.asarray(np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,)), np.uint16)) @@ -149,10 +149,9 @@ def isotope_vector_to_human_readable_name(ivec: np.ndarray, charge_state: np.int if hashvalue != 0: protons, neutrons = hash_to_isotope(int(hashvalue)) if neutrons > 0: - human_readable += str(protons + neutrons) \ - + chemical_symbols[protons] + human_readable += f"{protons + neutrons}{chemical_symbols[protons]}" else: - human_readable += chemical_symbols[protons] + human_readable += f"{chemical_symbols[protons]}" human_readable += " " if 0 < charge_state < 8: human_readable += "+" * charge_state @@ -165,7 +164,7 @@ def isotope_vector_to_human_readable_name(ivec: np.ndarray, charge_state: np.int def is_range_overlapping(interval: np.ndarray, - interval_set: np.float64) -> bool: + interval_set: np.ndarray) -> bool: """Check if interval overlaps within with members of interval set.""" assert np.shape(interval) == (2,), "Interval needs to have two columns!" assert np.shape(interval_set)[1] == 2, \ diff --git a/linting.sh b/linting.sh new file mode 100755 index 0000000..31d2c74 --- /dev/null +++ b/linting.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# execute within a local python virtual environment or within a conda environment +# in both cases the ifes_apt_tc_data_modeling module should have been installed in developer mode + +python -m pycodestyle --ignore=E501 ifes_apt_tc_data_modeling +python -m pylint ifes_apt_tc_data_modeling --ignore build +python -m mypy --ignore-missing-imports ifes_apt_tc_data_modeling \ No newline at end of file diff --git a/tests/TestsForDevelopers.ipynb b/tests/TestsForDevelopers.ipynb index c52717c..77fd7f3 100644 --- a/tests/TestsForDevelopers.ipynb +++ b/tests/TestsForDevelopers.ipynb @@ -20,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "fc6c2ca9-ba62-4580-8eed-223467c58b22", "metadata": { "tags": [] @@ -61,7 +61,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "d239daae-b751-4f18-96c9-1f1e87ffacb6", "metadata": {}, "outputs": [], @@ -72,7 +72,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 4, "id": "ae40fca2-f0d3-49c9-8563-faddcc5b924c", "metadata": {}, "outputs": [ @@ -80,14 +80,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "[2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]\n" + "True\n" ] } ], "source": [ - "lst = [2]\n", - "lst.extend([3] * 10)\n", - "print(lst)" + "print(isinstance(np.uint16, type))" ] }, { @@ -640,7 +638,7 @@ " h5w.create_group(\"/entry\")\n", " i = 1\n", " for ion in a.rng[\"molecular_ions\"]:\n", - " trg = \"/entry/ion\" + str(i)\n", + " trg = f\"/entry/ion{i}\"\n", " grp = h5w.create_group(trg)\n", " grp.attrs[\"NXclass\"] = \"NXion\"\n", " dst = h5w.create_dataset(f\"{trg}/comment\", data=ion.comment.typed_value)\n", From 77e6c2e686be6dad48654af6acbe607662ff1b92 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Fri, 29 Dec 2023 13:32:21 +0100 Subject: [PATCH 05/20] Updated README.md --- README.md | 136 ++++++++++++++++++++++++------------------------------ 1 file changed, 61 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index f68b3fb..43f51b3 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,29 @@ -# atomprobe-data-modeling +# ifes_apt_tc_data_modeling ## Mission: -Foster exchange about data models and work towards specifications -of file formats from the research field of atom probe microscopy. +Foster exchange in the community of atom probe research to exchange about and +document information content and formatting in their research field. +Work towards ideally semantically specified file formats and data models. -# Getting started -You should create a virtual environment. We tested on Ubuntu with Python 3.8 and newer version. -In what follows the version (tag) 3.8 is a placeholder whereby we show how to proceed when using -Python 3.8. Using newer versions of Python should work the same by replacing 3.8 with the respective -version (tag). +## Getting started: + +### Create an environment +To use this library create a conda or a virtual environment. We tested on Ubuntu with Python 3.8 and newer version. +In what follows the version (tag) 3.8 is a placeholder whereby we show how to proceed when using e.g. Python version 3.8. +Using newer versions of Python should work the same by replacing 3.8 with the respective version (tag). As of 2024, +using Python in versions higher than 3.9 becomes more and more common. The support for users to install modern +Python version has also improved. Therefore, the following commands typically enable you to create a +specifically-versioned virtual environment: + +mkdir +cd +pip install virtualenv +virtualenv --python=python3.8 .py38 +source .py38/bin/activate + +If you wish to use or still demand to use older versions of Python, like 3.8 or 3.9, you can conveniently install them +via the deadsnakes repository (or via conda). For using deadsnakes proceed with the following commands: -Older versions of Python like 3.8 and 3.9 are available e.g. via the deadsnakes repository or via -conda. For using deadsnakes proceed with the following commands: ``` sudo add-apt-repository ppa:deadsnakes/ppa sudo apt install python3.8 python3-dev libpython3.8-dev python3.8-venv @@ -19,15 +31,12 @@ sudo apt install python3.8 python3-dev libpython3.8-dev python3.8-venv In some cases when using Python3.8, it was necessary to install python-numpy. Please consider this if you run into issues when continuing with this manual. -The following steps will install the ifes_apt_tc_data_modeling module in the -latest version. + +### Install the ifes_apt_tc_data_modeling modules as a user + +This is how to achieve this: ``` -mkdir -cd -pip install virtualenv -virtualenv --python=python3.8 .py38 -source .py38/bin/activate git clone git@github.com:atomprobe-tc/ifes_apt_tc_data_modeling.git cd ifes_apt_tc_data_modeling @@ -37,76 +46,53 @@ python -m pip install -e . python -m pip list ``` -## Additional steps to do when working with jupyter notebooks -By default the functionalities are offered as a library for Python programmers. -For developers and users who would like to try using the library a convenient -way is via jupyter notebooks. You can find instructions about how to use this tool -in the tests/data jupyter notebook. This notebook can be started from the command -line inside the ifes_apt_tc_data_modeling directory simply by calling. -If you would like to use a jupyter notebook jupyter has to be installed as -it will not be installed by default. To achieve this perform the following actions: +### Additional steps to perform when you are a developer or wish to work with jupyter notebooks ``` python -m pip install -e ".[dev]" python -m pip list - jupyter-lab ``` ## Documentation of file formats and data models in atom probe status quo -Detailed technical specifications of the file formats and data models are not available for -most formats in the field of atom probe microscopy. A practical solution to address this -limitation has been so far that scientists collect example files formatted in respective formats. - -These so-called instances were inspected and shared with colleagues. In summary, individual -atom probers have contributed to formulate what can be considered likely candidates -of specifications for several file formats via reverse engineering. -This worked especially well for the POS and ePOS formats. - -Pieces of information about file formats were reported in the literature (e.g. -the books by D. Larson et al. and B. Gault et al.). Atom probers like D. Haley have contributed -substantially to make the community aware of existent limitations and these reverse engineering -practices. AMETEK/Cameca is the key technology partner in atom probe. They have developed -an open file format called APT which improves the accessibility of specific numerical data and -some metadata. Individuals like M. Kühbach have driven the implementation and communication of -parsers for this APT file format. - -Nowadays there is an increased interest and demand placed on atom probers by the funding agencies -that researchers should or even have to make their research data management and data stewardship -better matching and more completely aligned to the aims and practices of the F.A.I.R. -principles of data stewardship. Therefore, it is useful to exchange more details about -data models and file formats. Otherwise, it is not foreseeable how atom probe data can be made -really interoperable with electronic lab notebooks, research data management -systems (RDMS), and related software tools for data analyses. - -In light of these challenges, the idea of understanding formats just by examples, showed to be a -slow and error-prone route as e.g. source code and workflows which have been useed to write such -files, and the associated input, workflow, and provenance information has typically not been captured. -Or the specific software tool(s) used might not have been shared or made accessible for review -by the atom probe community. - -## Benefit and Next Steps -You can easily imagine that the more people will support this work the more complete a public -understanding and knowledge about the available file formats in atom probe microscopy will become. -This can help all of us in the long run to build software tools which are more reliable, yield -thrustworthy results and are technically more robust when it comes to parsing research data. -Irrespective from which tools these data and metadata come or how one would like to used these data. - -The Python parsers in this repository are meant as a motivation to offer immediate benefit for users. -The collection of examples and technical discussions via issues serves the more long-term aim. -This is to arrive at a detailed technical specification rather than having more robust parsers only -so that atom probe data can be exchanged across tools irrespective of their formatting. - -## Support us with this work -Thank you very much for supporting this activity and your time. +Lack of detailed technical specifications of the file formats and a lack of usage of magic numbers as identifiers for specific file formats +are a key blocker to parsing and semantic interpretation of information content stored in current file formats within the research field of +atom probe microscopy. A practical solution to raise at least awareness of this problem has been that scientists collect examples (instances) +of files in respective formats. Pieces of information about the content and formatting of atom probe file formats were reported in the literature +(e.g. in the books by D. Larson et al. https://doi.org/10.1007/978-1-4614-8721-0 or B. Gault et al. http://dx.doi.org/10.1007/978-1-4614-3436-8 ). +Atom probers like D. Haley have contributed substantially in that he raised awareness of the issue within the community. +AMETEK/Cameca is the key technology partner in atom probe. AMETEK has developed an open file format called APT which has improved +the accessibility of specific numerical data and some metadata. Individuals like M. Kühbach have driven the implementation and +communication of parsers for this APT file format. + +Nowadays, there is a global desire, a push by research funding agencies, and an increased interest of atom probers +to make their research data and knowledge generation process better matching and more completely aligned to the aims +and practices of the F.A.I.R. principles of research data stewardship and FAIR4RS research software development. +Therefore, it is useful to exchange more details about data models and file formats. Otherwise, it is not foreseeable +how atom probe data can be made really interoperable with electronic lab notebooks, research data management +systems (RDMS), and related software tools for data analyses, especially not if these tools ever should work +with solutions from the stack of semantic web technologies to enable more substantiated, better reproducible, and +more automatically contextualized atom probe research with computational agents. + +In light of these challenges, the idea of understanding formats just by examples, showed to be a slow and error-prone route +as e.g. source code and workflows which have been used to write such files lack provenance information. As an example, +the POS files only store a table of number quadruples which mostly are interpreted as reconstructed position and mass-to-charge- +state ratio values but often are hijacked to report conceptually different quantities like identifier used to distinguish clusters of +atoms. Nowhere in the POS file the file has a magic number that identifies it as a POS file. Nowhere does the POS file +document from which content and which tools it was generated. The situation similarly poor for RRNG range files: +These merely store the resulting ranging definitions but no details based on which peak finding algorithm or even which +mass-to-charge-state-ratio value array they were defined with. M. Kühbach et al. have summarized a more detailed discussion +about these limitations https://doi.org/10.1017/S1431927621012241. + +## How can you support this work? +As a user with contacting us and providing examples of file formats. As a member of a company by documenting your file format +and getting in contact to work together on improving the situation. Thank you very much for supporting this activity and your time. ## Feedback, questions -Feel free to drop us a message via creating an issue or commenting on one. -Feel invited to use the resources in this repository. +Feel free to drop us a message via creating an issue or commenting on one. ## Where to place your examples? -There is a *examples_with_provenance* and *examples_without_provenance* -sub-directory for each file format. +There is a *examples_with_provenance* and *examples_without_provenance* sub-directory for each file format. When you do know with which software and measured dataset you have created a file, you should share the file and these pieces of information (software version). Do so by From 34fa19bea6205e8ed399d1af707c579b4465043c Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Fri, 29 Dec 2023 13:47:33 +0100 Subject: [PATCH 06/20] Further editing of README.md --- README.md | 101 +++++++++++++++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 43f51b3..8810c94 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,13 @@ using Python in versions higher than 3.9 becomes more and more common. The suppo Python version has also improved. Therefore, the following commands typically enable you to create a specifically-versioned virtual environment: +``` mkdir cd pip install virtualenv virtualenv --python=python3.8 .py38 source .py38/bin/activate +``` If you wish to use or still demand to use older versions of Python, like 3.8 or 3.9, you can conveniently install them via the deadsnakes repository (or via conda). For using deadsnakes proceed with the following commands: @@ -34,10 +36,7 @@ Please consider this if you run into issues when continuing with this manual. ### Install the ifes_apt_tc_data_modeling modules as a user -This is how to achieve this: - ``` - git clone git@github.com:atomprobe-tc/ifes_apt_tc_data_modeling.git cd ifes_apt_tc_data_modeling python -m pip install --upgrade pip @@ -46,7 +45,7 @@ python -m pip install -e . python -m pip list ``` -### Additional steps to perform when you are a developer or wish to work with jupyter notebooks +### Additional steps to perform when you are a developer ``` python -m pip install -e ".[dev]" @@ -54,33 +53,43 @@ python -m pip list jupyter-lab ``` -## Documentation of file formats and data models in atom probe status quo -Lack of detailed technical specifications of the file formats and a lack of usage of magic numbers as identifiers for specific file formats +## Context, status quo, file formats used for atom probe research +A lack of detailed technical specifications of the file formats and a lack of usage of magic numbers as identifiers for specific file formats are a key blocker to parsing and semantic interpretation of information content stored in current file formats within the research field of -atom probe microscopy. A practical solution to raise at least awareness of this problem has been that scientists collect examples (instances) +atom probe microscopy. + +A practical solution to raise at least awareness of this problem has been that scientists collect examples (instances) of files in respective formats. Pieces of information about the content and formatting of atom probe file formats were reported in the literature (e.g. in the books by D. Larson et al. https://doi.org/10.1007/978-1-4614-8721-0 or B. Gault et al. http://dx.doi.org/10.1007/978-1-4614-3436-8 ). -Atom probers like D. Haley have contributed substantially in that he raised awareness of the issue within the community. +Atom probers like D. Haley have contributed substantially through raising awareness of the issue within the community. + AMETEK/Cameca is the key technology partner in atom probe. AMETEK has developed an open file format called APT which has improved the accessibility of specific numerical data and some metadata. Individuals like M. Kühbach have driven the implementation and -communication of parsers for this APT file format. +communication of parsers for this APT file format. There are ongoing efforts by both AMETEK and the scientific community to extent the APT file format +with additional metadata. The main motivation behind these newer efforts is to improve the interoperability between research data collected +within the IVAS/APSuite software and third-party software including research data management systems. +Currently, most metadata have to be entered manually via e.g. electronic lab notebooks if one were to use or register atom probe +data in solutions other than those developed by AMETEK. Nowadays, there is a global desire, a push by research funding agencies, and an increased interest of atom probers to make their research data and knowledge generation process better matching and more completely aligned to the aims and practices of the F.A.I.R. principles of research data stewardship and FAIR4RS research software development. + Therefore, it is useful to exchange more details about data models and file formats. Otherwise, it is not foreseeable how atom probe data can be made really interoperable with electronic lab notebooks, research data management -systems (RDMS), and related software tools for data analyses, especially not if these tools ever should work -with solutions from the stack of semantic web technologies to enable more substantiated, better reproducible, and -more automatically contextualized atom probe research with computational agents. +systems (RDMS), and related software tools for data analyses, especially not if these tools should ever work with +solutions from the stack of semantic web technologies. We are convinced there are substantial opportunities with making +atom probe research communication more substantiated, the research itself better reproducible, and with enabling +automated contextualization of atom probe research via computational agents. In light of these challenges, the idea of understanding formats just by examples, showed to be a slow and error-prone route as e.g. source code and workflows which have been used to write such files lack provenance information. As an example, the POS files only store a table of number quadruples which mostly are interpreted as reconstructed position and mass-to-charge- state ratio values but often are hijacked to report conceptually different quantities like identifier used to distinguish clusters of -atoms. Nowhere in the POS file the file has a magic number that identifies it as a POS file. Nowhere does the POS file -document from which content and which tools it was generated. The situation similarly poor for RRNG range files: -These merely store the resulting ranging definitions but no details based on which peak finding algorithm or even which +atoms. Nowhere in a POS file a magic number could identify the file as to be truely a POS file and no something else based on +which software tools and human could make a substantiated assumption. Nowhere does the POS file document from which +content and which tools it was generated. The situation is currently still similarly poor for ranging definitions files such as RRNG, RNG, +or ENV: These merely store the resulting ranging definitions but no details based on which peak finding algorithm or even which mass-to-charge-state-ratio value array they were defined with. M. Kühbach et al. have summarized a more detailed discussion about these limitations https://doi.org/10.1017/S1431927621012241. @@ -91,6 +100,37 @@ and getting in contact to work together on improving the situation. Thank you ve ## Feedback, questions Feel free to drop us a message via creating an issue or commenting on one. +## Background information +File formats, data models, in (almost every) research field may not be fully documented. +A checklist of the necessary pieces of information and documentation required to call a +data model, data schema, and/or file format fully documented in accordance with the +FAIR data and research software stewardship principles is given below: + +1. Each piece of information (bit/byte) is documented. +2. This documentation fulfills the FAIR principles, i.e. + [Wilkinson et al., 2016](https://doi.org/10.1038/sdata.2016.18) and + [Barker et al., 2022](https://doi.org/10.1038/s41597-022-01710-x) + For binary files, tools like [kaitai struct](https://kaitai.io/) offer a + solution to describe the exact binary information content in a data + item. This can be a file but also the storage of a database entry or the + response of a call to an API. + Let alone the binary structure is insufficient tough. +3. To each piece of information there has to exist also a parameterized description, + what this piece of information conceptually means. One way to arrive at such + description is to use a data schema or ontology. + It is important to mention that the concepts in this schema/ontology have + unique identifier so that each data item/piece of information is identifiable + as an instance of an entry in a database or a knowledge graph. + This holds independently of which research data management system + or electronic lab notebook is used. +4. In addition, it is very useful if timestamps are associated with each data item + (ISO8061 including time zone information) so that it is possible to create a + timeline of the context in which and when the e.g. file was created. + +The first and second point is known as a specification, while the third and fourth +point emphasize that the contextualization and provenance is key to make a +specification complete and useful. + ## Where to place your examples? There is a *examples_with_provenance* and *examples_without_provenance* sub-directory for each file format. @@ -126,34 +166,3 @@ While these examples are stripped of the context in which they were created and used (provenance information), these examples can still be very useful to run the file formats parsers against to make the parsers more robust, i.e. that these can pick up formatting issues and act accordingly. - -# Background information -File formats, data models, in (almost every) research field may not be fully documented. -A checklist of the necessary pieces of information and documentation required to call a -data model, data schema, and/or file format fully documented in accordance with the -FAIR data and research software stewardship principles is given below: - -1. Each piece of information (bit/byte) is documented. -2. This documentation fulfills the FAIR principles, i.e. - [Wilkinson et al., 2016](https://doi.org/10.1038/sdata.2016.18) and - [Barker et al., 2022](https://doi.org/10.1038/s41597-022-01710-x) - For binary files, tools like [kaitai struct](https://kaitai.io/) offer a - solution to describe the exact binary information content in a data - item. This can be a file but also the storage of a database entry or the - response of a call to an API. - Let alone the binary structure is insufficient tough. -3. To each piece of information there has to exist also a parameterized description, - what this piece of information conceptually means. One way to arrive at such - description is to use a data schema or ontology. - It is important to mention that the concepts in this schema/ontology have - unique identifier so that each data item/piece of information is identifiable - as an instance of an entry in a database or a knowledge graph. - This holds independently of which research data management system - or electronic lab notebook is used. -4. In addition, it is very useful if timestamps are associated with each data item - (ISO8061 including time zone information) so that it is possible to create a - timeline of the context in which and when the e.g. file was created. - -The first and second point is known as a specification, while the third and fourth -point emphasize that the contextualization and provenance is key to make a -specification complete and useful. From a3fabdecb501b59b273cf2df63c6abb4a5222aaf Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Fri, 29 Dec 2023 14:12:58 +0100 Subject: [PATCH 07/20] Updating and cleaning the jupyter notebook which can be used for testing and developing further functionalities offered by the ifes_apt_tc_data_modeling library --- tests/TestsForDevelopers.ipynb | 594 +++++++++++---------------------- 1 file changed, 188 insertions(+), 406 deletions(-) diff --git a/tests/TestsForDevelopers.ipynb b/tests/TestsForDevelopers.ipynb index 77fd7f3..101fed4 100644 --- a/tests/TestsForDevelopers.ipynb +++ b/tests/TestsForDevelopers.ipynb @@ -7,7 +7,7 @@ "tags": [] }, "source": [ - "## How to use the ifes_apt_tc_data_modeling library" + "# How to use the ifes_apt_tc_data_modeling library" ] }, { @@ -20,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "fc6c2ca9-ba62-4580-8eed-223467c58b22", "metadata": { "tags": [] @@ -45,10 +45,89 @@ }, { "cell_type": "markdown", - "id": "523ccf70-b115-4717-9007-bd13ff86a2a5", + "id": "3d5fc61d-8ebe-49d2-9e75-908497c4c492", "metadata": {}, "source": [ - "## GPM Rouen ENV system" + "Utility function for exporting (molecular) ions into a simple HDF5 file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "393923ae-0736-4de9-94cc-9a0b1a47b56c", + "metadata": { + "jupyter": { + "source_hidden": true + }, + "tags": [] + }, + "outputs": [], + "source": [ + "def simple_hfive_file(fpw, idx, mion):\n", + " \"\"\"Write specific content in existent and opened HDF5 file pointed to by fpw with write access.\"\"\"\n", + " trg = f\"/entry1/ion{idx}\"\n", + " grp = fpw.create_group(trg)\n", + " grp.attrs[\"NX_class\"] = \"NXion\"\n", + " dst = fpw.create_dataset(f\"{trg}/comment\", data=ion.comment.typed_value)\n", + " dst = fpw.create_dataset(f\"{trg}/color\", data=ion.color.typed_value)\n", + " # dst = fpw.create_dataset(f\"{trg}/volume\", dtype=np.float32, data=0.)\n", + " # dst.attrs[\"unit\"] = \"nm^3\"\n", + " dst = fpw.create_dataset(f\"{trg}/isotope_vector\", dtype=np.uint16,\n", + " data=ion.isotope_vector.typed_value, \n", + " chunks=True, compression=\"gzip\", compression_opts=1)\n", + " dst = fpw.create_dataset(f\"{trg}/nuclid_list\", dtype=np.uint16,\n", + " data=ion.nuclid_list.typed_value,\n", + " chunks=True, compression=\"gzip\", compression_opts=1)\n", + " dst = fpw.create_dataset(f\"{trg}/charge_state\", dtype=np.int8,\n", + " data=ion.charge_state.typed_value)\n", + " dst = fpw.create_dataset(f\"{trg}/name\", data=ion.name.typed_value)\n", + " dst = fpw.create_dataset(trg+ \"/mass_to_charge_range\", dtype=np.float32,\n", + " data=ion.ranges.typed_value)\n", + " dst.attrs[\"unit\"] = \"Da\"\n", + " subgrpnm = f\"{trg}/charge_state_model\"\n", + " subgrp = fpw.create_group(subgrpnm)\n", + " subgrp.attrs[\"NX_class\"] = \"NXprocess\"\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/min_abundance\", dtype=np.float64,\n", + " data=ion.charge_state_model[\"min_abundance\"])\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/min_abundance_product\", dtype=np.float64,\n", + " data=ion.charge_state_model[\"min_abundance_product\"])\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/min_half_life\", dtype=np.float64,\n", + " data=ion.charge_state_model[\"min_half_life\"])\n", + " dst.attrs[\"unit\"] = \"s\"\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/sacrifice_isotopic_uniqueness\", dtype=np.uint8,\n", + " data=ion.charge_state_model[\"sacrifice_isotopic_uniqueness\"])\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/isotope_matrix\", dtype=np.uint16,\n", + " data=ion.charge_state_model[\"isotope_matrix\"],\n", + " chunks=True, compression=\"gzip\", compression_opts=1)\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/charge_state_vector\", dtype=np.int8,\n", + " data=ion.charge_state_model[\"charge_state_vector\"])\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/mass_vector\", dtype=np.float64,\n", + " data=ion.charge_state_model[\"mass_vector\"])\n", + " dst.attrs[\"unit\"] = \"Da\"\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/nat_abun_prod_vector\", dtype=np.float64,\n", + " data=ion.charge_state_model[\"nat_abun_prod_vector\"])\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/min_half_life_vector\", dtype=np.float64,\n", + " data=ion.charge_state_model[\"min_half_life_vector\"])\n", + " dst.attrs[\"unit\"] = \"s\"" + ] + }, + { + "cell_type": "markdown", + "id": "f3564971-4163-464a-a49e-264a79602a37", + "metadata": {}, + "source": [ + "***" + ] + }, + { + "cell_type": "markdown", + "id": "523ccf70-b115-4717-9007-bd13ff86a2a5", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "## GPM/Rouen ENV system files" ] }, { @@ -61,7 +140,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "d239daae-b751-4f18-96c9-1f1e87ffacb6", "metadata": {}, "outputs": [], @@ -70,24 +149,6 @@ "fnm = [\"ErMnO.env\"]" ] }, - { - "cell_type": "code", - "execution_count": 4, - "id": "ae40fca2-f0d3-49c9-8563-faddcc5b924c", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(isinstance(np.uint16, type))" - ] - }, { "cell_type": "code", "execution_count": null, @@ -110,89 +171,15 @@ " m_ion.report()" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "9dd0fa4d-650d-4978-982c-6f9b2253d614", - "metadata": {}, - "outputs": [], - "source": [ - "def get_smart_chemical_symbols():\n", - " priority_queue = []\n", - " for symbol in chemical_symbols:\n", - " if len(symbol) == 2:\n", - " priority_queue.append(symbol)\n", - " for symbol in chemical_symbols:\n", - " if symbol != \"X\" and len(symbol) == 1:\n", - " priority_queue.append(symbol)\n", - " return priority_queue\n", - "\n", - "\n", - "with open(f\"{prefix}/{fnm[0]}\", mode=\"r\", encoding=\"utf-8\") as envf:\n", - " txt = envf.read()\n", - " txt = txt.replace(\"\\r\\n\", \"\\n\") # windows to unix EOL conversion\n", - " txt = txt.replace(\",\", \".\") # use decimal dots instead of comma\n", - " txt_stripped = [line for line in txt.split(\"\\n\") if line.strip() != \"\"] # and line.startswith(\"#\") is False\n", - " for line in txt_stripped:\n", - " print(line)\n", - " # search for ranging definitions \"# Definition of\"\n", - " rng_s = None\n", - " rng_e = None\n", - " for idx in np.arange(0, len(txt_stripped)):\n", - " if txt_stripped[idx].startswith(\"# Definition of\") is False:\n", - " continue\n", - " else:\n", - " rng_s = idx\n", - " break\n", - " for idx in np.arange(rng_s + 1, len(txt_stripped)):\n", - " if txt_stripped[idx].startswith(\"# Atom probe definition\") is False:\n", - " continue\n", - " else:\n", - " rng_e = idx\n", - " break\n", - " # print(f\"{txt_stripped[rng_s]}\\n{txt_stripped[rng_e]}\")\n", - " for idx in np.arange(rng_s + 1, rng_e):\n", - " tmp = txt_stripped[idx].split()\n", - " # interpret zeroth token into a list of chemical symbols\n", - " print(f\"---->{tmp}\")\n", - " lst = []\n", - " if tmp[0] == \"Hyd\":\n", - " lst = []\n", - " elif tmp[0] in get_smart_chemical_symbols():\n", - " lst.append(tmp[0])\n", - " else: \n", - " tokens = re.split(r'(\\d+)', tmp[0])\n", - " for jdx in np.arange(0, len(tokens)):\n", - " kdx = 0\n", - " for sym in get_smart_chemical_symbols():\n", - " if tokens[jdx][kdx:].startswith(sym) is True:\n", - " mult = 1\n", - " if jdx < len(tokens) - 1:\n", - " if (tokens[jdx][kdx:] == sym) and (tokens[jdx + 1].isdigit() is True):\n", - " mult = int(tokens[jdx + 1])\n", - " kdx += len(tokens[jdx + 1])\n", - " # else:\n", - " # print(\"jdx >\")\n", - " for cnt in np.arange(0, mult):\n", - " lst.append(sym)\n", - " kdx += len(sym)\n", - " print(lst)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "97ed82d1-26e7-46f2-ad4a-8b8625fb46c9", - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "id": "e680a9d0-4005-40b0-ab45-a8f5fb215273", - "metadata": {}, + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, "source": [ - "## FAU/Erlangen pyccapt control/calibration/ranging module" + "## FAU/Erlangen pyccapt control/calibration/ranging HDF5 files" ] }, { @@ -205,13 +192,10 @@ "outputs": [], "source": [ "# eventually change needed point to the location of the files to analyze\n", - "prefix = f\"{os.getcwd()}/../../../../../paper_paper_paper/joss_nomad_apt/bb_analysis/data\"\n", - "fnm = [\"1748_Nov-14-2023_13-31_Al.h5\",\n", - " \"1748_Al.h5\",\n", - " \"1748_Al_range_.h5\"]\n", - "# df = pd.read_hdf(f\"{prefix}/ger_erlangen_pyccapt_format/{fnm[1]}\")\n", - "# H5Web(f\"{prefix}/ger_erlangen_pyccapt_format/{fnm[1]}\")\n", - "# df" + "prefix = f\"{os.getcwd()}/data/env/examples_without_provenance\"\n", + "fnm = [\"1748_Nov-14-2023_13-31_Al.h5\", \"1748_Al.h5\", \"1748_Al_range_.h5\"]\n", + "# df = pd.read_hdf(f\"{prefix}/{fnm[1]}\")\n", + "# H5Web(f\"{prefix}/{fnm[1]}\")" ] }, { @@ -232,47 +216,30 @@ "outputs": [], "source": [ "# the actual measurement (comparable to LEAP's STR/RRAW/RHIT/HITS)\n", - "pyc_m = ReadPyccaptControlFileFormat(f\"{prefix}/ger_erlangen_pyccapt_format/{fnm[0]}\")\n", + "pyc_m = ReadPyccaptControlFileFormat(f\"{prefix}/{fnm[0]}\")\n", "\n", "# the calibrations (voltage, bowl, m/q, comparable to LEAP's ROOT and POS/EPOS)\n", - "pyc_c = ReadPyccaptCalibrationFileFormat(f\"{prefix}/ger_erlangen_pyccapt_format/{fnm[1]}\")\n", + "pyc_c = ReadPyccaptCalibrationFileFormat(f\"{prefix}/{fnm[1]}\")\n", "xyz = pyc_c.get_reconstructed_positions()\n", "print(xyz.typed_value)\n", "m_q = pyc_c.get_mass_to_charge_state_ratio()\n", "print(m_q.typed_value)\n", "\n", "# the ranging definitions (comparable to RNG/RRNG)\n", - "pyc_r = ReadPyccaptRangingFileFormat(f\"{prefix}/ger_erlangen_pyccapt_format/{fnm[2]}\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c1f1c4d8-75fe-4884-b81a-338a6c5eab94", - "metadata": {}, - "outputs": [], - "source": [ - "\n" + "pyc_r = ReadPyccaptRangingFileFormat(f\"{prefix}/{fnm[2]}\")" ] }, { "cell_type": "markdown", "id": "52294143-78c7-47bf-b39e-9e40eec3999d", - "metadata": {}, + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, "source": [ "## ATO" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "f1c42976-c225-40f4-9797-bfcc0d566012", - "metadata": {}, - "outputs": [], - "source": [ - "from ifes_apt_tc_data_modeling.ato.ato_reader import ReadAtoFileFormat" - ] - }, { "cell_type": "code", "execution_count": null, @@ -280,36 +247,20 @@ "metadata": {}, "outputs": [], "source": [ - "prefix = f\"{os.getcwd()}/../../../../../paper_paper_paper/joss_nomad_apt/bb_analysis/data\"" + "prefix = f\"{os.getcwd()}/data/ato/examples_without_provenance\"\n", + "fnm = [\"Si.epos.v3.ATO\", \"Si.epos.v5.ATO\"]\n", + "for fpath in fnm:\n", + " print(os.path.getsize(f\"{prefix}/{fpath}\"))" ] }, { "cell_type": "code", "execution_count": null, - "id": "084d2bb0-5a52-49fa-af88-d9851db48521", + "id": "f1c42976-c225-40f4-9797-bfcc0d566012", "metadata": {}, "outputs": [], "source": [ - "directory = f\"{prefix}/usa_cameca_ato_format\"\n", - "fnm = [\"Si.epos.v3.ATO\",\n", - " \"Si.epos.v5.ATO\"]\n", - "# directory = f\"{prefix}/bel_leuven_imec/dataverse_files/correlative-APT-EM\"\n", - "# fnm = [\"finfet/finfet_system.ato\",\n", - "# \"multilayer/multilayer_system.ato\"]\n", - "# directory = f\"{prefix}/fra_rouen_karam\"\n", - "# fnm = [\"Experimental Analysis of LaB6 ; Negative Pulse ; DC Voltage 6.6 kV ; Amplitudes 2.5 kV and 3 kV.ato\",\n", - "# \"Experimental Analysis of LaB6 ; Positive Pulse ; Amplitude 15 kV ; DC Voltage 3.2 kV and 5 kV.ato\",\n", - "# \"Experimental Analysis of LaB6 ; Positive Pulse ; DC Voltage 2.5 kV ; Amplirudes 13.5 kV and 15 kV.ato\",\n", - "# \"Experimental Analysis of LaB6 ; Positive Pulse ; DC Voltage 7 kV ; Amplitudes 6.5 kV and 7.5 kV.ato\"]\n", - "# directory = f\"{prefix}/usa_richland_kruska/kruska/APT\"\n", - "# fnm = [\"R31_11378-v01.ato\",\n", - "# \"R31_11381-v02.ato\",\n", - "# \"R31_11553-v01.ato\",\n", - "# \"R31_11554-v01.ato\",\n", - "# \"R31_11556-v01.ato\"]\n", - "print(directory)\n", - "for filename in fnm:\n", - " print(os.path.getsize(f\"{directory}/{filename}\"))" + "from ifes_apt_tc_data_modeling.ato.ato_reader import ReadAtoFileFormat" ] }, { @@ -319,9 +270,9 @@ "metadata": {}, "outputs": [], "source": [ - "for filename in fnm:\n", - " print(f\"{directory}/{filename}\")\n", - " ato = ReadAtoFileFormat(f\"{directory}/{filename}\")\n", + "for fpath in fnm:\n", + " print(f\"{prefix}/{fpath}\")\n", + " ato = ReadAtoFileFormat(f\"{prefix}/{fpath}\")\n", " \n", " xyz = ato.get_reconstructed_positions()\n", " print(xyz.typed_value)\n", @@ -333,7 +284,6 @@ "cell_type": "markdown", "id": "83369dab-5ce9-4c9e-810e-58e9f8bb93cc", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -341,34 +291,32 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "0baf8109-e03a-4141-91d1-38da86f05df5", + "cell_type": "markdown", + "id": "befb0874-1c4a-4967-b2f2-88d57df2aef9", "metadata": {}, - "outputs": [], "source": [ - "from ifes_apt_tc_data_modeling.fig.fig_reader import ReadFigTxtFileFormat" + "
A Matlab FIG has to be first processed using the matlab_fig_to_txt.m script for this reader to function!
" ] }, { "cell_type": "code", "execution_count": null, - "id": "856ebd71-8b84-402e-868a-66e756e7b8c2", + "id": "67356936-1f5e-4363-9b3e-2e9b849aeb32", "metadata": {}, "outputs": [], "source": [ + "prefix = f\"{os.getcwd()}/data/fig/examples_without_provenance/ger_erlangen_felfer\"\n", "fnm = [\"R56_01769.rng.fig.txt\"]" ] }, { "cell_type": "code", "execution_count": null, - "id": "67356936-1f5e-4363-9b3e-2e9b849aeb32", + "id": "0baf8109-e03a-4141-91d1-38da86f05df5", "metadata": {}, "outputs": [], "source": [ - "directory = f\"{os.getcwd()}/data/fig/examples_without_provenance/ger_erlangen_felfer\"\n", - "print(directory)" + "from ifes_apt_tc_data_modeling.fig.fig_reader import ReadFigTxtFileFormat" ] }, { @@ -380,66 +328,24 @@ }, "outputs": [], "source": [ - "# for filename in os.listdir(directory):\n", - "for filename in fnm:\n", - " if filename.lower().endswith(\".fig.txt\"):\n", - " print(filename)\n", - " if True is True: # if filename in []:\n", - " a = ReadFigTxtFileFormat(f\"{directory}/{filename}\")\n", - " # a.fig[\"molecular_ions\"]\n", - "\n", - " h5w = h5py.File(f\"{directory}/{filename}.nxs\", \"w\")\n", + "for fpath in fnm:\n", + " if fpath.lower().endswith(\".fig.txt\"):\n", + " print(fpath)\n", + " figtxt = ReadFigTxtFileFormat(f\"{prefix}/{fpath}\")\n", + " with h5py.File(f\"{prefix}/{fpath}.nxs\", \"w\") as h5w:\n", " h5w.create_group(\"/entry1\")\n", - " i = 1\n", - " for ion in a.fig[\"molecular_ions\"]:\n", - " trg = f\"/entry1/ion{i}\"\n", - " grp = h5w.create_group(trg)\n", - " grp.attrs[\"NXclass\"] = \"NXion\"\n", - " dst = h5w.create_dataset(f\"{trg}/comment\", data=ion.comment.typed_value)\n", - " dst = h5w.create_dataset(f\"{trg}/color\", data=ion.color.typed_value)\n", - " # dst = h5w.create_dataset(f\"{trg}/volume\", dtype=np.float32, data=0.)\n", - " # dst.attrs[\"unit\"] = \"nm^3\"\n", - " dst = h5w.create_dataset(f\"{trg}/isotope_vector\", dtype=np.uint16,\n", - " data=ion.isotope_vector.typed_value, \n", - " chunks=True, compression=\"gzip\", compression_opts=1)\n", - " dst = h5w.create_dataset(f\"{trg}/nuclid_list\", dtype=np.uint16,\n", - " data=ion.nuclid_list.typed_value,\n", - " chunks=True, compression=\"gzip\", compression_opts=1)\n", - " dst = h5w.create_dataset(f\"{trg}/charge_state\", dtype=np.int8,\n", - " data=ion.charge_state.typed_value)\n", - " dst = h5w.create_dataset(f\"{trg}/name\", data=ion.name.typed_value)\n", - " dst = h5w.create_dataset(trg+ \"/mass_to_charge_range\", dtype=np.float32,\n", - " data=ion.ranges.typed_value)\n", - " dst.attrs[\"unit\"] = \"Da\"\n", - "\n", - " subgrpnm = f\"{trg}/charge_state_model\"\n", - " subgrp = h5w.create_group(subgrpnm)\n", - " subgrp.attrs[\"NXclass\"] = \"NXprocess\"\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/min_abundance\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_abundance\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/min_abundance_product\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_abundance_product\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/min_half_life\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_half_life\"])\n", - " dst.attrs[\"unit\"] = \"s\"\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/sacrifice_isotopic_uniqueness\", dtype=np.uint8,\n", - " data=ion.charge_state_model[\"sacrifice_isotopic_uniqueness\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/isotope_matrix\", dtype=np.uint16,\n", - " data=ion.charge_state_model[\"isotope_matrix\"],\n", - " chunks=True, compression=\"gzip\", compression_opts=1)\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/charge_state_vector\", dtype=np.int8,\n", - " data=ion.charge_state_model[\"charge_state_vector\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/mass_vector\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"mass_vector\"])\n", - " dst.attrs[\"unit\"] = \"Da\"\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/nat_abun_prod_vector\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"nat_abun_prod_vector\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/min_half_life_vector\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_half_life_vector\"])\n", - " dst.attrs[\"unit\"] = \"s\"\n", - "\n", - " i += 1\n", - " h5w.close()" + " idx = 1\n", + " for ion in figtxt.fig[\"molecular_ions\"]:\n", + " simple_hfive_file(h5w, idx, ion)\n", + " idx += 1" + ] + }, + { + "cell_type": "markdown", + "id": "3df01841-cfb6-410f-8af8-3dc1cd200987", + "metadata": {}, + "source": [ + "Display generated HDF5 file using H5Web." ] }, { @@ -449,14 +355,13 @@ "metadata": {}, "outputs": [], "source": [ - "H5Web(f\"{directory}/{filename}.nxs\")" + "H5Web(f\"{prefix}/{fpath}.nxs\")" ] }, { "cell_type": "markdown", "id": "e045474d-0801-4686-abf3-1463771e2ddf", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -466,32 +371,22 @@ { "cell_type": "code", "execution_count": null, - "id": "9298da11-00d1-45c9-9bb1-d17737c20c49", - "metadata": {}, - "outputs": [], - "source": [ - "from ifes_apt_tc_data_modeling.rrng.rrng_reader import ReadRrngFileFormat" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a278233b-0891-4627-8b40-312600aa59d0", + "id": "511fa6d8-de91-413c-af9b-71723c1b2ec9", "metadata": {}, "outputs": [], "source": [ + "prefix = f\"{os.getcwd()}/data/rrng/examples_without_provenance/ger_duesseldorf_kuehbach\"\n", "fnm = [\"R31_06365-v02.rrng\"]" ] }, { "cell_type": "code", "execution_count": null, - "id": "511fa6d8-de91-413c-af9b-71723c1b2ec9", + "id": "9298da11-00d1-45c9-9bb1-d17737c20c49", "metadata": {}, "outputs": [], "source": [ - "directory = f\"{os.getcwd()}/data/rrng/examples_without_provenance/ger_duesseldorf_kuehbach\"\n", - "print(directory)" + "from ifes_apt_tc_data_modeling.rrng.rrng_reader import ReadRrngFileFormat" ] }, { @@ -503,67 +398,16 @@ }, "outputs": [], "source": [ - "# for filename in os.listdir(directory):\n", - "for filename in fnm:\n", - " if filename.lower().endswith(\".rrng\"):\n", - " print(filename)\n", - " if True is True: # if filename in []:\n", - " a = ReadRrngFileFormat(f\"{directory}/{filename}\")\n", - " # a.rrng[\"molecular_ions\"]\n", - "\n", - " h5w = h5py.File(f\"{directory}/{filename}.nxs\", \"w\")\n", + "for fpath in fnm:\n", + " if fpath.lower().endswith(\".rrng\"):\n", + " print(fpath)\n", + " rrng = ReadRrngFileFormat(f\"{prefix}/{fpath}\")\n", + " with h5py.File(f\"{prefix}/{fpath}.nxs\", \"w\") as h5w:\n", " h5w.create_group(\"/entry1\")\n", - " i = 1\n", - " for ion in a.rrng[\"molecular_ions\"]:\n", - " trg = f\"/entry1/ion{i}\"\n", - " grp = h5w.create_group(trg)\n", - " grp.attrs[\"NXclass\"] = \"NXion\"\n", - " dst = h5w.create_dataset(f\"{trg}/comment\", data=ion.comment.typed_value)\n", - " dst = h5w.create_dataset(f\"{trg}/color\", data=ion.color.typed_value)\n", - " dst = h5w.create_dataset(f\"{trg}/volume\", dtype=np.float32,\n", - " data=ion.volume.typed_value)\n", - " dst.attrs[\"unit\"] = \"nm^3\"\n", - " dst = h5w.create_dataset(f\"{trg}/isotope_vector\", dtype=np.uint16,\n", - " data=ion.isotope_vector.typed_value, \n", - " chunks=True, compression=\"gzip\", compression_opts=1)\n", - " dst = h5w.create_dataset(f\"{trg}/nuclid_list\", dtype=np.uint16,\n", - " data=ion.nuclid_list.typed_value,\n", - " chunks=True, compression=\"gzip\", compression_opts=1)\n", - " dst = h5w.create_dataset(f\"{trg}/charge_state\", dtype=np.int8,\n", - " data=ion.charge_state.typed_value)\n", - " dst = h5w.create_dataset(f\"{trg}/name\", data=ion.name.typed_value)\n", - " # print(ion.name.typed_value)\n", - " dst = h5w.create_dataset(trg+ \"/mass_to_charge_range\", dtype=np.float32,\n", - " data=ion.ranges.typed_value)\n", - " dst.attrs[\"unit\"] = \"Da\"\n", - "\n", - " subgrpnm = f\"{trg}/charge_state_model\"\n", - " subgrp = h5w.create_group(subgrpnm)\n", - " subgrp.attrs[\"NXclass\"] = \"NXprocess\"\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/min_abundance\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_abundance\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/min_abundance_product\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_abundance_product\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/min_half_life\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_half_life\"])\n", - " dst.attrs[\"unit\"] = \"s\"\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/sacrifice_isotopic_uniqueness\", dtype=np.uint8,\n", - " data=ion.charge_state_model[\"sacrifice_isotopic_uniqueness\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/isotope_matrix\", dtype=np.uint16,\n", - " data=ion.charge_state_model[\"isotope_matrix\"],\n", - " chunks=True, compression=\"gzip\", compression_opts=1)\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/charge_state_vector\", dtype=np.int8,\n", - " data=ion.charge_state_model[\"charge_state_vector\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/mass_vector\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"mass_vector\"])\n", - " dst.attrs[\"unit\"] = \"Da\"\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/nat_abun_prod_vector\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"nat_abun_prod_vector\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/min_half_life_vector\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_half_life_vector\"])\n", - " dst.attrs[\"unit\"] = \"s\"\n", - " i += 1\n", - " h5w.close()" + " idx = 1\n", + " for ion in rrng.rrng[\"molecular_ions\"]:\n", + " simple_hfive_file(h5w, idx, ion)\n", + " idx += 1" ] }, { @@ -573,7 +417,7 @@ "metadata": {}, "outputs": [], "source": [ - "H5Web(f\"{directory}/{filename}.nxs\")" + "H5Web(f\"{prefix}/{fpath}.nxs\")" ] }, { @@ -589,32 +433,22 @@ { "cell_type": "code", "execution_count": null, - "id": "7dbf60e5-6c02-40d6-a2d7-72a8c96bda87", - "metadata": {}, - "outputs": [], - "source": [ - "from ifes_apt_tc_data_modeling.rng.rng_reader import ReadRngFileFormat" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "203470c0-5ee2-4483-b986-df3b7057c940", + "id": "07e2fb8e-1953-4780-90ba-1c8e69d8989a", "metadata": {}, "outputs": [], "source": [ + "prefix = f\"{os.getcwd()}/data/rng/examples_without_provenance/ger_duesseldorf_kuehbach\"\n", "fnm = [\"SeHoKim_R5076_44076_v02.rng\"]" ] }, { "cell_type": "code", "execution_count": null, - "id": "07e2fb8e-1953-4780-90ba-1c8e69d8989a", + "id": "7dbf60e5-6c02-40d6-a2d7-72a8c96bda87", "metadata": {}, "outputs": [], "source": [ - "directory = f\"{os.getcwd()}/data/rng/examples_without_provenance/ger_duesseldorf_kuehbach\"\n", - "print(directory)" + "from ifes_apt_tc_data_modeling.rng.rng_reader import ReadRngFileFormat" ] }, { @@ -626,66 +460,16 @@ }, "outputs": [], "source": [ - "# for filename in os.listdir(directory):\n", - "for filename in fnm:\n", - " if filename.lower().endswith(\".rng\"):\n", - " print(filename)\n", - " if True is True: # if filename in []:\n", - " a = ReadRngFileFormat(f\"{directory}/{filename}\")\n", - " # a.rng[\"molecular_ions\"]\n", - " \n", - " h5w = h5py.File(f\"{directory}/{filename}.nxs\", \"w\")\n", + "for fpath in fnm:\n", + " if fpath.lower().endswith(\".rng\"):\n", + " print(fpath)\n", + " rng = ReadRngFileFormat(f\"{prefix}/{fpath}\")\n", + " with h5py.File(f\"{directory}/{filename}.nxs\", \"w\") as h5w:\n", " h5w.create_group(\"/entry\")\n", - " i = 1\n", - " for ion in a.rng[\"molecular_ions\"]:\n", - " trg = f\"/entry/ion{i}\"\n", - " grp = h5w.create_group(trg)\n", - " grp.attrs[\"NXclass\"] = \"NXion\"\n", - " dst = h5w.create_dataset(f\"{trg}/comment\", data=ion.comment.typed_value)\n", - " dst = h5w.create_dataset(f\"{trg}/color\", data=ion.color.typed_value)\n", - " dst = h5w.create_dataset(f\"{trg}/volume\", dtype=np.float32,\n", - " data=ion.volume.typed_value)\n", - " dst.attrs[\"unit\"] = \"nm^3\"\n", - " dst = h5w.create_dataset(f\"{trg}/isotope_vector\", dtype=np.uint16,\n", - " data=ion.isotope_vector.typed_value, \n", - " chunks=True, compression=\"gzip\", compression_opts=1)\n", - " dst = h5w.create_dataset(f\"{trg}/nuclid_list\", dtype=np.uint16,\n", - " data=ion.nuclid_list.typed_value,\n", - " chunks=True, compression=\"gzip\", compression_opts=1)\n", - " dst = h5w.create_dataset(f\"{trg}/charge_state\", dtype=np.int8,\n", - " data=ion.charge_state.typed_value)\n", - " dst = h5w.create_dataset(f\"{trg}/name\", data=ion.name.typed_value)\n", - " dst = h5w.create_dataset(trg+ \"/mass_to_charge_range\", dtype=np.float32,\n", - " data=ion.ranges.typed_value)\n", - " dst.attrs[\"unit\"] = \"Da\"\n", - "\n", - " subgrpnm = f\"{trg}/charge_state_model\"\n", - " subgrp = h5w.create_group(subgrpnm)\n", - " subgrp.attrs[\"NXclass\"] = \"NXprocess\"\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/min_abundance\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_abundance\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/min_abundance_product\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_abundance_product\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/min_half_life\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_half_life\"])\n", - " dst.attrs[\"unit\"] = \"s\"\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/sacrifice_isotopic_uniqueness\", dtype=np.uint8,\n", - " data=ion.charge_state_model[\"sacrifice_isotopic_uniqueness\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/isotope_matrix\", dtype=np.uint16,\n", - " data=ion.charge_state_model[\"isotope_matrix\"],\n", - " chunks=True, compression=\"gzip\", compression_opts=1)\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/charge_state_vector\", dtype=np.int8,\n", - " data=ion.charge_state_model[\"charge_state_vector\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/mass_vector\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"mass_vector\"])\n", - " dst.attrs[\"unit\"] = \"Da\"\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/nat_abun_prod_vector\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"nat_abun_prod_vector\"])\n", - " dst = h5w.create_dataset(f\"{subgrpnm}/min_half_life_vector\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_half_life_vector\"])\n", - " dst.attrs[\"unit\"] = \"s\"\n", - " i += 1\n", - " h5w.close()" + " idx = 1\n", + " for ion in rng.rng[\"molecular_ions\"]:\n", + " simple_hfive_file(h5w, idx, ion)\n", + " idx += 1" ] }, { @@ -695,7 +479,7 @@ "metadata": {}, "outputs": [], "source": [ - "H5Web(f\"{directory}/{filename}.nxs\")" + "H5Web(f\"{prefix}/{fpath}.nxs\")" ] }, { @@ -711,23 +495,22 @@ { "cell_type": "code", "execution_count": null, - "id": "4d2e7622-ea40-4055-921d-5a36cc1a6081", + "id": "2aa99006-ec67-4a67-a06a-e0417a6e4bf3", "metadata": {}, "outputs": [], "source": [ - "from ifes_apt_tc_data_modeling.pos.pos_reader import ReadPosFileFormat" + "prefix = f\"{os.getcwd()}/data/pos/examples_without_provenance\"\n", + "fnm = [\"R31_06365-v02.pos\"]" ] }, { "cell_type": "code", "execution_count": null, - "id": "2aa99006-ec67-4a67-a06a-e0417a6e4bf3", + "id": "4d2e7622-ea40-4055-921d-5a36cc1a6081", "metadata": {}, "outputs": [], "source": [ - "fnm = [\"R31_06365-v02.pos\"]\n", - "directory = f\"{os.getcwd()}/data/pos/examples_without_provenance\"\n", - "print(directory)" + "from ifes_apt_tc_data_modeling.pos.pos_reader import ReadPosFileFormat" ] }, { @@ -737,8 +520,8 @@ "metadata": {}, "outputs": [], "source": [ - "for filename in fnm:\n", - " pos = ReadPosFileFormat(f\"{directory}/{filename}\")\n", + "for fpath in fnm:\n", + " pos = ReadPosFileFormat(f\"{prefix}/{fpath}\")\n", " print(pos.filename)\n", " print(pos.filesize)\n", " xyz = pos.get_reconstructed_positions()\n", @@ -751,7 +534,6 @@ "cell_type": "markdown", "id": "6c15a0a4-b22e-4d97-9ba1-b58d38fa84d9", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -761,23 +543,22 @@ { "cell_type": "code", "execution_count": null, - "id": "b76a25f7-f87a-4c50-aa08-8a620da466cc", + "id": "4b4e8c10-4b69-492e-ab21-e6f81cce91be", "metadata": {}, "outputs": [], "source": [ - "from ifes_apt_tc_data_modeling.epos.epos_reader import ReadEposFileFormat" + "prefix = f\"{os.getcwd()}/data/epos/examples_without_provenance\"\n", + "fnm = [\"R18_58152-v02.epos\"]" ] }, { "cell_type": "code", "execution_count": null, - "id": "4b4e8c10-4b69-492e-ab21-e6f81cce91be", + "id": "b76a25f7-f87a-4c50-aa08-8a620da466cc", "metadata": {}, "outputs": [], "source": [ - "fnm = [\"R18_58152-v02.epos\"]\n", - "directory = f\"{os.getcwd()}/data/epos/examples_without_provenance\"\n", - "print(directory)" + "from ifes_apt_tc_data_modeling.epos.epos_reader import ReadEposFileFormat" ] }, { @@ -787,8 +568,8 @@ "metadata": {}, "outputs": [], "source": [ - "for filename in fnm:\n", - " epos = ReadEposFileFormat(f\"{directory}/{filename}\")\n", + "for fpath in fnm:\n", + " epos = ReadEposFileFormat(f\"{prefix}/{fpath}\")\n", " print(epos.filename)\n", " print(epos.filesize)\n", " xyz = epos.get_reconstructed_positions()\n", @@ -822,23 +603,22 @@ { "cell_type": "code", "execution_count": null, - "id": "420ca252-0566-48c0-bf0e-82303c0f8eff", + "id": "1d9ff170-6dea-4e4f-affc-3e3ad3a73c62", "metadata": {}, "outputs": [], "source": [ - "from ifes_apt_tc_data_modeling.apt.apt6_reader import ReadAptFileFormat" + "prefix = f\"{os.getcwd()}/data/apt/examples_without_provenance\"\n", + "fnm = [\"70_50_50.apt\"]" ] }, { "cell_type": "code", "execution_count": null, - "id": "1d9ff170-6dea-4e4f-affc-3e3ad3a73c62", + "id": "420ca252-0566-48c0-bf0e-82303c0f8eff", "metadata": {}, "outputs": [], "source": [ - "fnm = [\"70_50_50.apt\"]\n", - "directory = f\"{os.getcwd()}/data/apt/examples_without_provenance\"\n", - "print(directory)" + "from ifes_apt_tc_data_modeling.apt.apt6_reader import ReadAptFileFormat" ] }, { @@ -848,8 +628,8 @@ "metadata": {}, "outputs": [], "source": [ - "for filename in fnm:\n", - " apt = ReadAptFileFormat(f\"{directory}/{filename}\")\n", + "for fpath in fnm:\n", + " apt = ReadAptFileFormat(f\"{prefix}/{fpath}\")\n", " print(apt.get_metadata_table())\n", " xyz = apt.get_reconstructed_positions()\n", " print(np.shape(xyz.typed_value))\n", @@ -861,7 +641,6 @@ "cell_type": "markdown", "id": "deefbfcf-ab9a-4ced-a470-09b972b769af", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -960,13 +739,16 @@ "metadata": {}, "source": [ "***\n", - "Markus Kühbach 2023/05" + "Markus Kühbach, 2023/12/29
\n", + "
\n", + "FAIRmat is a consortium on research data management which is part of the German NFDI.
\n", + "The project is funded by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) – project 460197019." ] }, { "cell_type": "code", "execution_count": null, - "id": "513a176a-c354-4ef2-95fa-d598b08f42af", + "id": "d0019086-a921-4a46-9cf0-d32439dea968", "metadata": {}, "outputs": [], "source": [] From 108e7ed94da22d8b6a2d6a80e61b246d7e25b483 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Fri, 29 Dec 2023 14:33:12 +0100 Subject: [PATCH 08/20] Clean up, license and init files plus add context for each file format/reader --- ifes_apt_tc_data_modeling/apt/README.md | 3 ++ ifes_apt_tc_data_modeling/apt/__init__.py | 1 - ifes_apt_tc_data_modeling/apt/apt6_headers.py | 2 -- ifes_apt_tc_data_modeling/apt/apt6_reader.py | 2 -- .../apt/apt6_sections.py | 8 ++--- .../apt/apt6_sections_branches.py | 3 -- ifes_apt_tc_data_modeling/apt/apt6_utils.py | 2 -- ifes_apt_tc_data_modeling/ato/README.md | 3 ++ ifes_apt_tc_data_modeling/ato/__init__.py | 17 ++++++++++ ifes_apt_tc_data_modeling/ato/ato_reader.py | 2 -- .../{utils/dev/ato => ato/matlab}/ato.m | 0 ifes_apt_tc_data_modeling/env/README.md | 3 ++ ifes_apt_tc_data_modeling/env/__init__.py | 17 ++++++++++ ifes_apt_tc_data_modeling/epos/README.md | 2 ++ ifes_apt_tc_data_modeling/epos/__init__.py | 1 - ifes_apt_tc_data_modeling/epos/epos_reader.py | 2 -- ifes_apt_tc_data_modeling/fig/README.md | 10 +++--- ifes_apt_tc_data_modeling/fig/__init__.py | 1 - ifes_apt_tc_data_modeling/fig/fig_reader.py | 3 -- ifes_apt_tc_data_modeling/nexus/__init__.py | 1 - ifes_apt_tc_data_modeling/nexus/nx_ion.py | 31 ++++++------------- ifes_apt_tc_data_modeling/pos/README.md | 2 ++ ifes_apt_tc_data_modeling/pos/__init__.py | 1 - ifes_apt_tc_data_modeling/pos/pos_reader.py | 2 -- ifes_apt_tc_data_modeling/pyccapt/README.md | 3 ++ ifes_apt_tc_data_modeling/pyccapt/__init__.py | 17 ++++++++++ .../pyccapt/pyccapt_reader.py | 2 -- ifes_apt_tc_data_modeling/rng/README.md | 2 ++ ifes_apt_tc_data_modeling/rng/__init__.py | 1 - ifes_apt_tc_data_modeling/rng/rng_reader.py | 2 -- ifes_apt_tc_data_modeling/rrng/README.md | 2 ++ ifes_apt_tc_data_modeling/rrng/__init__.py | 1 - ifes_apt_tc_data_modeling/rrng/rrng_reader.py | 2 -- ifes_apt_tc_data_modeling/utils/__init__.py | 1 - ifes_apt_tc_data_modeling/utils/mmapped_io.py | 3 -- .../utils/molecular_ions.py | 2 -- .../utils/nist_isotope_data.py | 2 -- ifes_apt_tc_data_modeling/utils/utils.py | 2 -- 38 files changed, 88 insertions(+), 73 deletions(-) create mode 100644 ifes_apt_tc_data_modeling/apt/README.md create mode 100644 ifes_apt_tc_data_modeling/ato/README.md create mode 100644 ifes_apt_tc_data_modeling/ato/__init__.py rename ifes_apt_tc_data_modeling/{utils/dev/ato => ato/matlab}/ato.m (100%) create mode 100644 ifes_apt_tc_data_modeling/env/README.md create mode 100644 ifes_apt_tc_data_modeling/epos/README.md create mode 100644 ifes_apt_tc_data_modeling/pos/README.md create mode 100644 ifes_apt_tc_data_modeling/pyccapt/README.md create mode 100644 ifes_apt_tc_data_modeling/pyccapt/__init__.py create mode 100644 ifes_apt_tc_data_modeling/rng/README.md create mode 100644 ifes_apt_tc_data_modeling/rrng/README.md diff --git a/ifes_apt_tc_data_modeling/apt/README.md b/ifes_apt_tc_data_modeling/apt/README.md new file mode 100644 index 0000000..d33e950 --- /dev/null +++ b/ifes_apt_tc_data_modeling/apt/README.md @@ -0,0 +1,3 @@ +## Getting started +AMETEK/Cameca APT file format used in IVAS/APSuite. +https://github.com/CamecaAPT/cameca-customanalysis-interface/wiki/IonData:-Sections \ No newline at end of file diff --git a/ifes_apt_tc_data_modeling/apt/__init__.py b/ifes_apt_tc_data_modeling/apt/__init__.py index 45f7b33..db96892 100644 --- a/ifes_apt_tc_data_modeling/apt/__init__.py +++ b/ifes_apt_tc_data_modeling/apt/__init__.py @@ -1,4 +1,3 @@ -# Init file # # Copyright The NOMAD Authors. # diff --git a/ifes_apt_tc_data_modeling/apt/apt6_headers.py b/ifes_apt_tc_data_modeling/apt/apt6_headers.py index b4c3785..7597e84 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_headers.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_headers.py @@ -18,8 +18,6 @@ """AMETEK APT(6) data exchange file reader used by atom probe microscopists.""" -# pylint: disable=no-member,duplicate-code - import numpy as np from ifes_apt_tc_data_modeling.apt.apt6_utils import string_to_typed_nparray diff --git a/ifes_apt_tc_data_modeling/apt/apt6_reader.py b/ifes_apt_tc_data_modeling/apt/apt6_reader.py index a88c94a..91a7236 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_reader.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_reader.py @@ -18,8 +18,6 @@ """AMETEK APT(6) data exchange file reader used by atom probe microscopists.""" -# pylint: disable=no-member,duplicate-code - import os import numpy as np import pandas as pd diff --git a/ifes_apt_tc_data_modeling/apt/apt6_sections.py b/ifes_apt_tc_data_modeling/apt/apt6_sections.py index baa00bf..5db039f 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_sections.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_sections.py @@ -18,12 +18,10 @@ """AMETEK APT(6) data exchange file reader used by atom probe microscopists.""" -# pylint: disable=no-member,duplicate-code - import numpy as np -from ifes_apt_tc_data_modeling.apt.apt6_utils import np_uint16_to_string -from ifes_apt_tc_data_modeling.apt.apt6_utils import string_to_typed_nparray +from ifes_apt_tc_data_modeling.apt.apt6_utils import \ + np_uint16_to_string, string_to_typed_nparray class AptFileSectionMetadata(): @@ -250,7 +248,7 @@ def get_ametek_type(self) -> str: + ' get_ametek_type() unsupported e_record_data_type!' if self.meta['e_record_data_type'] == 1: integer_dtypes = {2: ' Date: Fri, 29 Dec 2023 16:06:05 +0100 Subject: [PATCH 09/20] Added simplistic reader for CSV using the assumption that these files are such written out from POS --- ifes_apt_tc_data_modeling/apt/apt6_reader.py | 9 +-- ifes_apt_tc_data_modeling/apt/apt6_utils.py | 3 +- ifes_apt_tc_data_modeling/ato/ato_reader.py | 2 +- ifes_apt_tc_data_modeling/csv/README.md | 2 + ifes_apt_tc_data_modeling/csv/__init__.py | 17 +++++ ifes_apt_tc_data_modeling/csv/csv_reader.py | 73 +++++++++++++++++++ ifes_apt_tc_data_modeling/fig/fig_reader.py | 4 +- ifes_apt_tc_data_modeling/nexus/nx_ion.py | 16 ++-- .../pyccapt/pyccapt_reader.py | 14 ++-- ifes_apt_tc_data_modeling/rng/rng_reader.py | 4 +- .../utils/molecular_ions.py | 7 +- .../utils/nist_isotope_data.py | 2 + tests/TestsForDevelopers.ipynb | 37 +++++++++- 13 files changed, 160 insertions(+), 30 deletions(-) create mode 100644 ifes_apt_tc_data_modeling/csv/README.md create mode 100644 ifes_apt_tc_data_modeling/csv/__init__.py create mode 100644 ifes_apt_tc_data_modeling/csv/csv_reader.py diff --git a/ifes_apt_tc_data_modeling/apt/apt6_reader.py b/ifes_apt_tc_data_modeling/apt/apt6_reader.py index 91a7236..9c6ae02 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_reader.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_reader.py @@ -78,8 +78,7 @@ def parse_file_structure(self): count=1) assert self.dummy_header.matches(found_header), \ - f"Found an unexpectedly formatted/versioned header." \ - f"Create an issue to help us fix this!" + "Found an unexpectedly formatted header. Create an issue to help us fix this!" print(f"File describes {found_header['llIonCount'][0]} ions") self.header_section = found_header @@ -106,13 +105,11 @@ def parse_file_structure(self): print(keyword) print(found_section) assert keyword not in self.available_sections, \ - f"Found a duplicate of an already parsed section!" \ - f"Create an issue to help us fix this!" + "Found a duplicate of an already parsed section! Create an issue to help us fix this!" if keyword not in ['Delta Pulse', 'Epos ToF']: assert keyword in EXPECTED_SECTIONS, \ - f"Found an unknown section, seems like an unknown/new branch!" \ - f"Create an issue to help us fix this!" + "Found an unknown section, seems like an unknown/new branch! Create an issue to help us fix this!" metadata_section = EXPECTED_SECTIONS[keyword] if metadata_section.matches(found_section) is True: diff --git a/ifes_apt_tc_data_modeling/apt/apt6_utils.py b/ifes_apt_tc_data_modeling/apt/apt6_utils.py index 099cf8f..5ea24b3 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_utils.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_utils.py @@ -37,5 +37,4 @@ def string_to_typed_nparray(string: str, length: int, dtyp: type) -> np.ndarray: for value in np.arange(0, len(string)): nparr[value] = ord(string[value]) return nparr - else: - raise ValueError(f"{dtyp} is either not a type or {string} is not <= {length}!") + raise ValueError(f"{dtyp} is either not a type or {string} is not <= {length}!") diff --git a/ifes_apt_tc_data_modeling/ato/ato_reader.py b/ifes_apt_tc_data_modeling/ato/ato_reader.py index fdaa966..d71f2a7 100644 --- a/ifes_apt_tc_data_modeling/ato/ato_reader.py +++ b/ifes_apt_tc_data_modeling/ato/ato_reader.py @@ -30,7 +30,7 @@ class ReadAtoFileFormat(): def __init__(self, filename: str): if (len(filename) <= 4) or (filename.lower().endswith(".ato") is False): - raise ImportError(f"WARNING::ATO file incorrect filename ending or file type!") + raise ImportError("WARNING::ATO file incorrect filename ending or file type!") self.filename = filename self.filesize = os.path.getsize(self.filename) diff --git a/ifes_apt_tc_data_modeling/csv/README.md b/ifes_apt_tc_data_modeling/csv/README.md new file mode 100644 index 0000000..b62d95f --- /dev/null +++ b/ifes_apt_tc_data_modeling/csv/README.md @@ -0,0 +1,2 @@ +## Getting started +CSV reader assuming CSV is formatted like a POS file. \ No newline at end of file diff --git a/ifes_apt_tc_data_modeling/csv/__init__.py b/ifes_apt_tc_data_modeling/csv/__init__.py new file mode 100644 index 0000000..db96892 --- /dev/null +++ b/ifes_apt_tc_data_modeling/csv/__init__.py @@ -0,0 +1,17 @@ +# +# 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. +# diff --git a/ifes_apt_tc_data_modeling/csv/csv_reader.py b/ifes_apt_tc_data_modeling/csv/csv_reader.py new file mode 100644 index 0000000..98df8d6 --- /dev/null +++ b/ifes_apt_tc_data_modeling/csv/csv_reader.py @@ -0,0 +1,73 @@ +# +# 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. +# + +"""CSV file format reader as sometimes used for reporting POS file content.""" + +import os +import numpy as np +import pandas as pd + +from ifes_apt_tc_data_modeling.nexus.nx_field import NxField + + +class ReadCsvFileFormat(): + """Read CSV file assuming (n_ions, 4) like in POS.""" + + def __init__(self, filename: str): + if (len(filename) <= 4) or (filename.lower().endswith(".csv") is False): + raise ImportError("WARNING::CSV file incorrect filename ending or file type!") + self.filename = filename + + self.filesize = os.path.getsize(self.filename) + self.number_of_events = None + self.version = None + + shp = np.shape(pd.read_csv(self.filename)) + if shp[0] > 0 and shp[1] == 4: + self.number_of_events = shp[0] + else: + raise ImportError("CSV file unsupported version because not formatted like POS!") + + def get_reconstructed_positions(self): + """Read xyz columns.""" + + xyz = NxField() + xyz.typed_value = np.zeros([self.number_of_events, 3], np.float32) + xyz.unit = "nm" + # there are too many assumption made here as to the content + # in the csv file sure one could pass some configuration hints but + # frankly there are nowadays much! better strategies to report + # atom probe data than CSV, NeXus is one such, also csv files have + # no magic number, de facto this works only because users know what + # to expect in advance but how should a machine know this? + for dim in [0, 1, 2]: + xyz.typed_value[:, dim] = pd.read_csv(self.filename).iloc[:, dim] + 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" + # again such a strong assumption! + # why reported in Da? + # why in the third column + # why at all a mass-to-charge-state-ratio value array? + m_n.typed_value[:, 0] = pd.read_csv(self.filename).iloc[:, 3] + return m_n diff --git a/ifes_apt_tc_data_modeling/fig/fig_reader.py b/ifes_apt_tc_data_modeling/fig/fig_reader.py index ca0460a..a19bc41 100644 --- a/ifes_apt_tc_data_modeling/fig/fig_reader.py +++ b/ifes_apt_tc_data_modeling/fig/fig_reader.py @@ -26,7 +26,7 @@ from ifes_apt_tc_data_modeling.utils.definitions import \ MAX_NUMBER_OF_ATOMS_PER_ION from ifes_apt_tc_data_modeling.utils.molecular_ions import \ - isotope_to_hash, MolecularIonBuilder, \ + get_chemical_symbols, isotope_to_hash, MolecularIonBuilder, \ PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ PRACTICAL_MIN_HALF_LIFE, VERBOSE, SACRIFICE_ISOTOPIC_UNIQUENESS @@ -86,7 +86,7 @@ def read_fig_txt(self): multiplier = int(suffix[0]) symbol = isotope.replace( f"{mass_number}", "").replace(f"{multiplier}", "").replace(" ", "") - if (symbol != "X") and (symbol in chemical_symbols): + if symbol in get_chemical_symbols(): proton_number = atomic_numbers[symbol] neutron_number = mass_number - proton_number ivec.extend([isotope_to_hash(proton_number, neutron_number)] * multiplier) diff --git a/ifes_apt_tc_data_modeling/nexus/nx_ion.py b/ifes_apt_tc_data_modeling/nexus/nx_ion.py index 16808fc..68d3b8d 100644 --- a/ifes_apt_tc_data_modeling/nexus/nx_ion.py +++ b/ifes_apt_tc_data_modeling/nexus/nx_ion.py @@ -91,14 +91,14 @@ def update_human_readable_name(self): def report(self): """Report values.""" - print(f"ion_type: {self.ion_type.typed_value}\n" \ - f"isotope_vector: {self.isotope_vector.typed_value}\n" \ - f"nuclid_list: {self.nuclid_list.typed_value}\n" \ - f"human-readable name: {self.name.typed_value}\n" \ - f"charge_state: {self.charge_state.typed_value}\n" \ - f"ranges: {self.ranges.typed_value}\n" \ - f"comment: {self.comment.typed_value}\n" \ - f"color: {self.color.typed_value}\n" \ + print(f"ion_type: {self.ion_type.typed_value}\n" + f"isotope_vector: {self.isotope_vector.typed_value}\n" + f"nuclid_list: {self.nuclid_list.typed_value}\n" + f"human-readable name: {self.name.typed_value}\n" + f"charge_state: {self.charge_state.typed_value}\n" + f"ranges: {self.ranges.typed_value}\n" + f"comment: {self.comment.typed_value}\n" + f"color: {self.color.typed_value}\n" f"volume: {self.volume.typed_value}\n") def add_charge_state_model(self, diff --git a/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py b/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py index fda07cb..a7f349f 100644 --- a/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py +++ b/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py @@ -18,17 +18,18 @@ """Reader for FAU/Erlangen's HDF5-based formats introduced with the pyccapt library.""" +from typing import Dict import os import h5py import numpy as np import pandas as pd -from typing import Dict from ase.data import atomic_numbers, chemical_symbols from ifes_apt_tc_data_modeling.nexus.nx_ion import NxIon from ifes_apt_tc_data_modeling.nexus.nx_field import NxField -from ifes_apt_tc_data_modeling.utils.utils import \ - isotope_to_hash, isotope_vector_to_nuclid_list, MAX_NUMBER_OF_ATOMS_PER_ION +from ifes_apt_tc_data_modeling.utils.utils import isotope_to_hash, \ + isotope_vector_to_nuclid_list, MAX_NUMBER_OF_ATOMS_PER_ION +from ifes_apt_tc_data_modeling.utils.molecular_ions import get_chemical_symbols # this implementation focuses on the following state of the pyccapt repository # https://github.com/mmonajem/pyccapt/commit/e955beb4f2627befb8b4d26f2e74e4c52e00394e @@ -187,14 +188,13 @@ def __init__(self, filename: str): isotopes = self.df.iloc[idx, 8] # assertions ivec = np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,), np.uint16) - hashvector = [] + hashvector: list = [] for idxj in np.arange(0, len(elements)): symbol = elements[idxj] - if symbol in chemical_symbols and symbol != "X": + if symbol in get_chemical_symbols(): proton_number = atomic_numbers[symbol] neutron_number = isotopes[idxj] - proton_number - for mult in np.arange(0, complexs[idxj]): - hashvector.append(isotope_to_hash(proton_number, neutron_number)) + hashvector.extend([isotope_to_hash(proton_number, neutron_number)] * complexs[idxj]) ivec[0:len(hashvector)] = np.sort(np.asarray(hashvector, np.uint16), kind="stable")[::-1] m_ion = NxIon() diff --git a/ifes_apt_tc_data_modeling/rng/rng_reader.py b/ifes_apt_tc_data_modeling/rng/rng_reader.py index 17fb1fd..66ce8bb 100644 --- a/ifes_apt_tc_data_modeling/rng/rng_reader.py +++ b/ifes_apt_tc_data_modeling/rng/rng_reader.py @@ -27,7 +27,7 @@ create_isotope_vector, is_range_significant from ifes_apt_tc_data_modeling.utils.definitions import MQ_EPSILON from ifes_apt_tc_data_modeling.utils.molecular_ions import MolecularIonBuilder, \ - PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ + get_chemical_symbols, PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ PRACTICAL_MIN_HALF_LIFE, VERBOSE, SACRIFICE_ISOTOPIC_UNIQUENESS @@ -67,7 +67,7 @@ def evaluate_rng_range_line( f"Line {line} no negative element counts!" if element_multiplicity[j] > 0: symbol = column_id_to_label[j + 1] - if (symbol in chemical_symbols) and (symbol != "X"): + if symbol in get_chemical_symbols(): info["atoms"] = np.append(info["atoms"], [column_id_to_label[j + 1]] * int(element_multiplicity[j])) else: diff --git a/ifes_apt_tc_data_modeling/utils/molecular_ions.py b/ifes_apt_tc_data_modeling/utils/molecular_ions.py index c0c0e3b..914c8d5 100644 --- a/ifes_apt_tc_data_modeling/utils/molecular_ions.py +++ b/ifes_apt_tc_data_modeling/utils/molecular_ions.py @@ -21,7 +21,7 @@ import numpy as np import radioactivedecay as rd -from ase.data import atomic_numbers +from ase.data import atomic_numbers, chemical_symbols from ifes_apt_tc_data_modeling.utils.utils import \ isotope_to_hash, hash_to_isotope, isotope_vector_to_dict_keyword from ifes_apt_tc_data_modeling.utils.nist_isotope_data import isotopes @@ -46,6 +46,11 @@ VERBOSE = False +def get_chemical_symbols(): + """"Report only valid chemical symbols""" + return chemical_symbols[1:] + + class MolecularIonCandidate: """Define """ def __init__(self, diff --git a/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py b/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py index c56a5c0..8332c4f 100644 --- a/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py +++ b/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py @@ -18,6 +18,8 @@ """Look-up table of stable and radioactive nuclids for all elements.""" +# pylint: disable:too-many-lines + # this is a copy of downloadable data from ase # from ase.data.isotopes import download_isotope_data # isotopes = download_isotope_data() diff --git a/tests/TestsForDevelopers.ipynb b/tests/TestsForDevelopers.ipynb index 101fed4..c14b031 100644 --- a/tests/TestsForDevelopers.ipynb +++ b/tests/TestsForDevelopers.ipynb @@ -119,11 +119,46 @@ "***" ] }, + { + "cell_type": "markdown", + "id": "8fd557cb-0fd5-404a-9893-416861913e73", + "metadata": {}, + "source": [ + "## CSV reader" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8809a05e-5634-4def-89a4-278f40813e11", + "metadata": {}, + "outputs": [], + "source": [ + "prefix = f\"{os.getcwd()}/data/csv/examples_without_provenance\"\n", + "fnm = [\"Annealed CoCrNi_100.csv\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fdfa9b5a-356e-453c-8040-0335f8b64507", + "metadata": {}, + "outputs": [], + "source": [ + "from ifes_apt_tc_data_modeling.csv.csv_reader import ReadCsvFileFormat\n", + "csv = ReadCsvFileFormat(f\"{prefix}/{fnm[0]}\")\n", + "print(csv.filename)\n", + "print(csv.filesize)\n", + "xyz = csv.get_reconstructed_positions()\n", + "print(np.shape(xyz.typed_value))\n", + "mq = csv.get_mass_to_charge_state_ratio()\n", + "print(np.shape(mq.typed_value))" + ] + }, { "cell_type": "markdown", "id": "523ccf70-b115-4717-9007-bd13ff86a2a5", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ From 87c76b734c02011e83503e5cc31d621d218241ce Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Sat, 30 Dec 2023 18:30:23 +0100 Subject: [PATCH 10/20] Refactoring utils, code cleaning, complete linting --- ifes_apt_tc_data_modeling/__init__.py | 1 - .../utils/definitions.py | 26 +- ifes_apt_tc_data_modeling/utils/mmapped_io.py | 11 +- .../utils/molecular_ions.py | 150 ++--- .../utils/string_handling.py | 5 - ifes_apt_tc_data_modeling/utils/utils.py | 160 ++--- linting.sh | 2 +- pylintrc.rc | 637 ++++++++++++++++++ tests/TestsForDevelopers.ipynb | 2 +- 9 files changed, 791 insertions(+), 203 deletions(-) create mode 100644 pylintrc.rc diff --git a/ifes_apt_tc_data_modeling/__init__.py b/ifes_apt_tc_data_modeling/__init__.py index 45f7b33..db96892 100644 --- a/ifes_apt_tc_data_modeling/__init__.py +++ b/ifes_apt_tc_data_modeling/__init__.py @@ -1,4 +1,3 @@ -# Init file # # Copyright The NOMAD Authors. # diff --git a/ifes_apt_tc_data_modeling/utils/definitions.py b/ifes_apt_tc_data_modeling/utils/definitions.py index a59d41e..628340a 100644 --- a/ifes_apt_tc_data_modeling/utils/definitions.py +++ b/ifes_apt_tc_data_modeling/utils/definitions.py @@ -1,9 +1,4 @@ # -# Also convenience functions are included which translate human-readable ion -# names into the isotope_vector description proposed by Kuehbach et al. in -# DOI: 10.1017/S1431927621012241 to the human-readable ion names which are use -# in P. Felfer et al.'s atom probe toolbox -# # Copyright The NOMAD Authors. # # This file is part of NOMAD. See https://nomad-lab.eu for further info. @@ -21,7 +16,7 @@ # limitations under the License. # -"""Generic definitions when parsing molecular ions in atom probe microscopy.""" +"""Generic definitions when working with molecular ions useful for atom probe.""" import numpy as np @@ -31,3 +26,22 @@ MAX_NUMBER_OF_ATOMS_PER_ION = 32 # practical and required minimum mass-resolution Da or atomic mass unit (amu) MQ_EPSILON = np.float64(1. / 2000.) + + +# do not consider isotopes with a very low natural abundance +PRACTICAL_ABUNDANCE = 1.e-6 # 0. # 1.0e-6 +# do not consider candidate isotopically different molecular ions +# if their natural abundance product is too low +PRACTICAL_ABUNDANCE_PRODUCT = 1.e-6 # 0. # 1.0e-12 +# do consider too shortliving isotopes +PRACTICAL_MIN_HALF_LIFE = np.inf +# many examples of ranges are not constrainted strongly enough so that +# there are many isotopes (many of which admittedly hypothetical) ones +# which are within the range, this option lifts the constraint that +# there should be only one set of isotopically different molecular ions +# and if these have all these same charge it is assumed this is the +# charge of the molecular ion +# strictly speaking however one would have to rule out every possible +# molecular ion candidate (which is non-trivial and maybe not even +# with first principles theory possible... +SACRIFICE_ISOTOPIC_UNIQUENESS = True diff --git a/ifes_apt_tc_data_modeling/utils/mmapped_io.py b/ifes_apt_tc_data_modeling/utils/mmapped_io.py index e448704..dbb583f 100644 --- a/ifes_apt_tc_data_modeling/utils/mmapped_io.py +++ b/ifes_apt_tc_data_modeling/utils/mmapped_io.py @@ -29,14 +29,15 @@ @typing.no_type_check -def get_memory_mapped_data(file_name: str, data_type: str, oset: int, +def get_memory_mapped_data(fpath: str, + dtyp: str, oset: int, strd: int, shp: int): - """Memory-maps file plus offset strided read of typed data.""" + """Read typed data from memory-mapped file from offset with stride.""" # https://stackoverflow.com/questions/60493766/ \ # read-binary-flatfile-and-skip-bytes for I/O access details - with open(file_name, "rb") as file_handle, \ - mmap.mmap(file_handle.fileno(), length=0, access=mmap.ACCESS_READ) as memory_mapped: - return np.ndarray(buffer=memory_mapped, dtype=data_type, + with open(fpath, "rb") as fp, \ + mmap.mmap(fp.fileno(), length=0, access=mmap.ACCESS_READ) as memory_mapped: + return np.ndarray(buffer=memory_mapped, dtype=dtyp, offset=oset, strides=strd, shape=shp).copy() return None diff --git a/ifes_apt_tc_data_modeling/utils/molecular_ions.py b/ifes_apt_tc_data_modeling/utils/molecular_ions.py index 914c8d5..87dd4cc 100644 --- a/ifes_apt_tc_data_modeling/utils/molecular_ions.py +++ b/ifes_apt_tc_data_modeling/utils/molecular_ions.py @@ -16,7 +16,9 @@ # limitations under the License. # -"""Utility tool to work with molecular ions in atom probe microscopy.""" +"""Utility tool, analyze and combinatorics for (molecular) ions.""" + +# pylint: disable=too-many-arguments,too-many-instance-attributes,too-many-locals,too-many-nested-blocks,too-many-branches import numpy as np import radioactivedecay as rd @@ -25,24 +27,9 @@ from ifes_apt_tc_data_modeling.utils.utils import \ isotope_to_hash, hash_to_isotope, isotope_vector_to_dict_keyword from ifes_apt_tc_data_modeling.utils.nist_isotope_data import isotopes - -# do not consider isotopes with a very low natural abundance -PRACTICAL_ABUNDANCE = 0. # 1.0e-6 -# do not consider candidate isotopically different molecular ions -# if their natural abundance product is too low -PRACTICAL_ABUNDANCE_PRODUCT = 0. # 1.0e-12 -# do consider too shortliving isotopes -PRACTICAL_MIN_HALF_LIFE = np.inf -# many examples of ranges are not constrainted strongly enough so that -# there are many isotopes (many of which admittedly hypothetical) ones -# which are within the range, this option lifts the constraint that -# there should be only one set of isotopically different molecular ions -# and if these have all these same charge it is assumed this is the -# charge of the molecular ion -# strictly speaking however one would have to rule out every possible -# molecular ion candidate (which is non-trivial and maybe not even -# with first principles theory possible... -SACRIFICE_ISOTOPIC_UNIQUENESS = True +from ifes_apt_tc_data_modeling.utils.definitions import \ + PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ + PRACTICAL_MIN_HALF_LIFE, SACRIFICE_ISOTOPIC_UNIQUENESS VERBOSE = False @@ -52,9 +39,10 @@ def get_chemical_symbols(): class MolecularIonCandidate: - """Define """ + """Define (molecular) ion build from nuclids.""" + def __init__(self, - ivec=[], + ivec, charge_state=0, mass_sum=0., nat_abun_prod=0., @@ -75,11 +63,11 @@ class MolecularIonBuilder: """Class for holding properties of constructed molecular ions.""" def __init__(self, - min_abundance=1.0e-6, - min_abundance_product=1.0e-6, - min_half_life=np.inf, - sacrifice_uniqueness=True, - verbose=False): + min_abundance=PRACTICAL_ABUNDANCE, + min_abundance_product=PRACTICAL_ABUNDANCE_PRODUCT, + min_half_life=PRACTICAL_MIN_HALF_LIFE, + sacrifice_uniqueness=SACRIFICE_ISOTOPIC_UNIQUENESS, + verbose=VERBOSE): self.nuclids = np.asarray([], np.uint16) self.element_isotopes = {} self.nuclid_mass = {} @@ -88,19 +76,17 @@ def __init__(self, self.nuclid_unclear = {} # unclear halflife self.nuclid_halflife = {} self.candidates = [] - self.parms = {} - self.parms["min_abundance"] = min_abundance - self.parms["min_abundance_product"] = min_abundance_product - self.parms["min_half_life"] = min_half_life - self.parms["sacrifice_isotopic_uniqueness"] = sacrifice_uniqueness - self.parms["verbose"] = verbose - self.relevant = {} + self.parms = {"min_abundance": min_abundance, + "min_abundance_product": min_abundance_product, + "min_half_life": min_half_life, + "sacrifice_isotopic_uniqueness": sacrifice_uniqueness, + "verbose": verbose} for symbol, atomic_number in atomic_numbers.items(): if symbol != "X": # assume that data from ase take preference - # if half-life data are available in rd take these if not mark - # the isotope that it unclear_half_life == True + # if half-life data are available in radioactive decay library + # take these instead, if all fails mark an unclear_half_life == True element_isotopes = [] for mass_number in isotopes[atomic_number]: half_life = np.inf @@ -137,22 +123,15 @@ def __init__(self, n_neutrons = mass_number - n_protons mass = isotopes[atomic_numbers[symbol]][mass_number]["mass"] abundance = isotopes[atomic_numbers[symbol]][mass_number]["composition"] - # self.nuclids.append( - # Isotope(mass, - # abundance, - # n_protons, n_neutrons, - # observationally_stable, - # unclear_half_life)) hashvalue = isotope_to_hash(int(n_protons), int(n_neutrons)) - self.nuclids = np.asarray(np.append(self.nuclids, hashvalue), np.uint16) - self.nuclid_mass[hashvalue] = np.float64(mass) - self.nuclid_abundance[hashvalue] = np.float64(abundance) - self.nuclid_stable[hashvalue] = observationally_stable - self.nuclid_unclear[hashvalue] = unclear_half_life - self.nuclid_halflife[hashvalue] = half_life - assert np.uint16(0) not in self.nuclid_mass, \ - "0 must not be a key in nuclid_mass dict!" - element_isotopes = np.append(element_isotopes, hashvalue) + if hashvalue != 0: + self.nuclids = np.append(self.nuclids, hashvalue) + self.nuclid_mass[hashvalue] = np.float64(mass) + self.nuclid_abundance[hashvalue] = np.float64(abundance) + self.nuclid_stable[hashvalue] = observationally_stable + self.nuclid_unclear[hashvalue] = unclear_half_life + self.nuclid_halflife[hashvalue] = half_life + element_isotopes = np.append(element_isotopes, hashvalue) self.element_isotopes[atomic_number] = np.sort( np.asarray(element_isotopes, np.uint16), kind="stable")[::-1] self.nuclids = np.sort(self.nuclids, kind="stable")[::-1] @@ -161,19 +140,9 @@ def __init__(self, def get_element_isotopes(self, hashvalue): """List of hashvalues all isotopes of element specified by hashvalue.""" - # nuclids = np.asarray([], np.uint16) - target_p, target_n = hash_to_isotope(hashvalue) - return self.element_isotopes[target_p] - # for source_hashvalue in self.nuclids: - # # naive search for now - # source_p, source_n = hash_to_isotope(source_hashvalue) - # if source_p != target_p: - # continue - # else: - # nuclids = np.append(nuclids, source_hashvalue) - # return nuclids + return self.element_isotopes[hash_to_isotope(hashvalue)[0]] - def get_isotope_mass_sum(self, nuclid_arr=[]): + def get_isotope_mass_sum(self, nuclid_arr): """Evaluate cumulated atomic_mass of isotopes in ivec.""" # assuming no relativistic effects or other quantum effects # mass loss due to charge_state considered insignificant @@ -181,11 +150,9 @@ def get_isotope_mass_sum(self, nuclid_arr=[]): for hashvalue in nuclid_arr: if hashvalue != 0: mass += self.nuclid_mass[hashvalue] - # else: # because ivec are systematically filled sorted in descending order ! - # break return mass - def get_natural_abundance_product(self, nuclid_arr=[]): + def get_natural_abundance_product(self, nuclid_arr): """Get natural abundance product.""" abun_prod = 1. for hashvalue in nuclid_arr: @@ -193,7 +160,7 @@ def get_natural_abundance_product(self, nuclid_arr=[]): abun_prod *= self.nuclid_abundance[hashvalue] return abun_prod - def get_shortest_half_life(self, nuclid_arr=[]): + def get_shortest_half_life(self, nuclid_arr): """Get shortest half life for set of nuclids.""" min_half_life = self.parms["min_half_life"] for hashvalue in nuclid_arr: @@ -208,14 +175,16 @@ def get_shortest_half_life(self, nuclid_arr=[]): # time and this might possibly hint that studying this molecular is tricky else: # if we do not information about the half-life it is very likely that - # this is an exotic nuclids likely never found in the wild + # this is an exotic nuclid likely never found in the wild return np.nan return min_half_life def combinatorics(self, element_arr, low, high): """Combinatorial analysis which (molecular) elements match within [low, high].""" - # RNG/RRNG range files do store element information for each range - # BUT not isotope information, correspondingly this can yield + # RNG/RRNG/ENV range files store (molecular) ion information for each range + # BUT neither nuclid not charge state information, here we try to recover + # both if possible or list all possible combinations + # correspondingly this allows yield # only an isotope_vector whose hashvalues have ALL in common # that the number of neutrons is 0, i.e. their hashvalue is the atomic_number # element_arr is an isotope_vector/ivec with such hashvalues @@ -249,7 +218,6 @@ def iterate_molecular_ion(self, """Recursive analysis of combinatorics on molecular ions.""" if i < (max_n - 1): for nuclid in jth_nuclids: - ixxth_nuclids = self.get_element_isotopes(element_arr[i + 1]) cand_arr_curr = np.append(cand_arr_prev, nuclid) self.iterate_molecular_ion( @@ -294,51 +262,55 @@ def iterate_molecular_ion(self, # break the recursion return - def try_to_reduce_to_unique_solution(self): - """Heuristics to identify if current candidates are unique.""" - if self.parms["verbose"] is True: - print(f"Reduce set of {len(self.candidates)} candidates to a unique...") - self.relevant = {} + def get_relevant(self): + """Identify relevant candidates.""" + relevant = {} for cand in self.candidates: if cand.abundance_product >= self.parms["min_abundance_product"]: if np.isnan(cand.shortest_half_life) is False: if cand.shortest_half_life >= self.parms["min_half_life"]: keyword = cand.unique_keyword() - if keyword not in self.relevant: - self.relevant[keyword] = cand - relevant_candidates = [] + if keyword not in relevant: + relevant[keyword] = cand + if self.parms["verbose"] is True: - print(f"Reduced set to {len(self.relevant.keys())} relevant candidates...") - for key, val in self.relevant.items(): + print(f"Reduced set to {len(relevant.keys())} relevant candidates...") + for key in relevant: print(key) - for key, obj in self.relevant.items(): + relevant_candidates = [] + for key, obj in relevant.items(): relevant_candidates.append(obj) - # print(type(relevant_candidates)) + return relevant, relevant_candidates - if len(self.relevant) == 0: + def try_to_reduce_to_unique_solution(self): + """Heuristics to identify if current candidates are unique.""" + if self.parms["verbose"] is True: + print(f"Reduce set of {len(self.candidates)} candidates to a unique...") + relevant, relevant_candidates = self.get_relevant() + if len(relevant) == 0: if self.parms["verbose"] is True: print("WARNING::No relevant candidate meets all criteria!") print("WARNING::No solution possible for given criteria!") return (0, relevant_candidates) - if len(self.relevant) == 1: + if len(relevant) == 1: if self.parms["verbose"] is True: print("One relevant candidate which meets all criteria") keywords = [] - for key in self.relevant: + for key in relevant: if isinstance(key, str): keywords.append(key) assert len(keywords) >= 1, "List of relevant keywords is empty!" - return (self.relevant[keywords[0]].charge_state, relevant_candidates) + return (relevant[keywords[0]].charge_state, relevant_candidates) if self.parms["verbose"] is True: print("Multiple relevant candidates meet all selection criteria") keywords = [] - for key in self.relevant: + for key in relevant: if isinstance(key, str): keywords.append(key) assert len(keywords) >= 1, "List of relevant keywords is empty!" - charge_state = self.relevant[keywords[0]].charge_state - for key, val in self.relevant.items(): + charge_state = relevant[keywords[0]].charge_state + for key, val in relevant.items(): if val.charge_state == charge_state: continue if self.parms["verbose"] is True: diff --git a/ifes_apt_tc_data_modeling/utils/string_handling.py b/ifes_apt_tc_data_modeling/utils/string_handling.py index 2294a9a..7192535 100644 --- a/ifes_apt_tc_data_modeling/utils/string_handling.py +++ b/ifes_apt_tc_data_modeling/utils/string_handling.py @@ -1,9 +1,4 @@ # -# Also convenience functions are included which translate human-readable ion -# names into the isotope_vector description proposed by Kuehbach et al. in -# DOI: 10.1017/S1431927621012241 to the human-readable ion names which are use -# in P. Felfer et al.'s atom probe toolbox -# # Copyright The NOMAD Authors. # # This file is part of NOMAD. See https://nomad-lab.eu for further info. diff --git a/ifes_apt_tc_data_modeling/utils/utils.py b/ifes_apt_tc_data_modeling/utils/utils.py index d113d5f..fdaeef6 100644 --- a/ifes_apt_tc_data_modeling/utils/utils.py +++ b/ifes_apt_tc_data_modeling/utils/utils.py @@ -16,12 +16,11 @@ # limitations under the License. # -"""Utilities for parsing data and molecular ions in atom probe microscopy.""" +"""Utilities for working with molecular ions in atom probe microscopy.""" -# Also convenience functions are included which translate human-readable ion -# names into the isotope_vector description proposed by Kuehbach et al. in -# DOI: 10.1017/S1431927621012241 to the human-readable ion names which are use -# in P. Felfer et al.'s atom probe toolbox +# including convenience functions for translating human-readable ion names +# into the isotope_vector description proposed by Kühbach et al. in +# DOI: 10.1017/S1431927621012241 from typing import Tuple import numpy as np @@ -35,114 +34,88 @@ def isotope_to_hash(proton_number: int = 0, neutron_number: int = 0) -> int: """Encode an isotope to a hashvalue.""" - n_protons = np.uint16(proton_number) - n_neutrons = np.uint16(neutron_number) - assert np.uint16(0) <= n_protons < np.uint16(256), \ - "Argument proton number on [0, 256) needed!" - assert np.uint(0) <= n_neutrons < np.uint16(256), \ - "Argument neutron number on [0, 256) needed!" - hashvalue = int(n_protons + (np.uint16(256) * n_neutrons)) - return hashvalue + if (0 <= proton_number < 256) and (0 <= neutron_number < 256): + return int(np.uint16(proton_number) + (np.uint16(256) * np.uint16(neutron_number))) + return 0 def hash_to_isotope(hashvalue: int = 0) -> Tuple[int, int]: """Decode a hashvalue to an isotope.""" # assert isinstance(hashvalue, int), \ # "Argument hashvalue needs to be integer!" - val = np.uint16(hashvalue) - assert val >= np.uint16(0), \ - "Argument hashvalue needs to be an unsigned integer!" - assert val <= np.iinfo(np.uint16).max, \ - "Argument hashvalue needs to map on an uint16!" - neutron_number = np.uint16(val / np.uint16(256)) - proton_number = np.uint16(val - neutron_number * np.uint16(256)) - return (int(proton_number), int(neutron_number)) + if 0 <= hashvalue <= int(np.iinfo(np.uint16).max): + neutron_number = np.uint16(np.uint16(hashvalue) / np.uint16(256)) + proton_number = np.uint16(np.uint16(hashvalue) - neutron_number * np.uint16(256)) + return (int(proton_number), int(neutron_number)) + return (0, 0) def create_isotope_vector(building_blocks: list) -> np.ndarray: """Create specifically-shaped array of isotope hashvalues.""" - # building_blocks are usually names of elements in the periodic tables - # if not we assume the ion is special, a user type - - # test cases: + # building_blocks are usually names of elements in the periodic table + # if not we assume the ion is special such as user type or plain words + # a typical expected test case is # create_isotope_vector(["Fe", "Fe", "O", "O", "O"]) - symbol_to_proton_number = atomic_numbers - ivec = np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,), np.uint16) - hashvector = [] - assert len(building_blocks) <= MAX_NUMBER_OF_ATOMS_PER_ION, \ - "Faced an ion with an unsupported high complexity!" - # MAX_NUMBER_OF_ATOMS_PER_ION can be modified to describe large fragments - - if len(building_blocks) == 0: # special case unknown ion type - return ivec - - for block in building_blocks: - assert isinstance(block, str), \ - "Argument block has to be a string, symbol for an element like K or isotope K-40!" - assert block != "", \ - "Argument block has to be a non-empty string!" - if block.count("-") == 0: - assert (block in symbol_to_proton_number) and (block != "X"), \ - f"{block} is not a valid chemical symbol!" - proton_number = symbol_to_proton_number[block] - neutron_number = 0 - hashvector.append(isotope_to_hash(proton_number, neutron_number)) - elif block.count("-") == 1: - symb_mass = block.split("-") - assert len(symb_mass) == 2, \ - f"{block} is not properly formatted -!" - assert (symb_mass[0] in symbol_to_proton_number) and (symb_mass[0] != "X"), \ - f"{symb_mass[0]} is not a valid chemical symbol!" - proton_number = symbol_to_proton_number[symb_mass[0]] - mass_number = int(symb_mass[1]) - neutron_number = mass_number - proton_number - assert proton_number in isotopes, \ - f"No isotopes for proton_number {proton_number} via ase!" - assert mass_number in isotopes[proton_number], \ - f"No isotope for mass_number {mass_number} via ase!" - hashvector.append(isotope_to_hash(proton_number, neutron_number)) - else: - print(f"WARNING: {block} does not specify a unique element name!") - return ivec - - ivec[0:len(hashvector)] = np.sort( - np.asarray(hashvector, np.uint16), kind="stable")[::-1] + if 0 < len(building_blocks) <= MAX_NUMBER_OF_ATOMS_PER_ION: + symbol_to_proton_number = atomic_numbers + hashvector = [] + for block in building_blocks: + if isinstance(block, str) and block != "": + if block.count("-") == 0: # an element + if (block not in symbol_to_proton_number) or (block == "X"): + return ivec + hashvector.append(isotope_to_hash( + symbol_to_proton_number[block], 0)) + elif block.count("-") == 1: + symb_mass = block.split("-") + if (len(symb_mass) != 2) or (symb_mass[0] not in symbol_to_proton_number) or (symb_mass[0] == "X"): + print(f"WARNING:: {block} is not properly formatted -!") + return ivec + proton_number = symbol_to_proton_number[symb_mass[0]] + mass_number = int(symb_mass[1]) + neutron_number = mass_number - proton_number + if (proton_number in isotopes) and (mass_number in isotopes[proton_number]): + hashvector.append(isotope_to_hash(proton_number, neutron_number)) + return ivec + return ivec + + ivec[0:len(hashvector)] = np.sort( + np.asarray(hashvector, np.uint16), kind="stable")[::-1] return ivec def isotope_vector_to_nuclid_list(ivec: np.ndarray) -> np.ndarray: """Create a NeXus NXion nuclid list.""" - assert np.shape(ivec) == (MAX_NUMBER_OF_ATOMS_PER_ION,), \ - "Argument isotope_vector needs to be shaped (MAX_NUMBER_OF_ATOMS_PER_ION,) !" nuclid_list = np.zeros((2, MAX_NUMBER_OF_ATOMS_PER_ION), np.uint16) - for idx in np.arange(0, MAX_NUMBER_OF_ATOMS_PER_ION): - if ivec[idx] != 0: - protons, neutrons = hash_to_isotope(int(ivec[idx])) - nuclid_list[0, idx] = protons + neutrons - nuclid_list[1, idx] = protons + if np.shape(ivec) == (MAX_NUMBER_OF_ATOMS_PER_ION,): + for idx in np.arange(0, MAX_NUMBER_OF_ATOMS_PER_ION): + if ivec[idx] != 0: + protons, neutrons = hash_to_isotope(int(ivec[idx])) + nuclid_list[0, idx] = protons + neutrons + nuclid_list[1, idx] = protons + return nuclid_list + print(f"WARNING:: Argument isotope_vector needs to be " + f"shaped {MAX_NUMBER_OF_ATOMS_PER_ION},) !") return nuclid_list def isotope_vector_to_dict_keyword(ivec: np.ndarray) -> str: """Create keyword for dictionary from isotope_vector.""" - assert len(ivec) <= MAX_NUMBER_OF_ATOMS_PER_ION, \ - "Argument isotope_vector len <= MAX_NUMBER_OF_ATOMS_PER_ION !" - lst = [] - for hashvalue in ivec: - if hashvalue != 0: - lst.append(f"{hashvalue}") - if len(lst) > 0: - return "_".join(lst) + if len(ivec) <= MAX_NUMBER_OF_ATOMS_PER_ION: + lst = [] + for hashvalue in ivec: + if hashvalue != 0: + lst.append(f"{hashvalue}") + if len(lst) > 0: + return "_".join(lst) return "0" # "_".join(np.asarray(np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,)), np.uint16)) def isotope_vector_to_human_readable_name(ivec: np.ndarray, charge_state: np.int8) -> str: """Get human-readable name from an isotope_vector.""" - assert len(ivec) <= MAX_NUMBER_OF_ATOMS_PER_ION, \ - "Argument isotope_vector len <= MAX_NUMBER_OF_ATOMS_PER_ION !" - human_readable = "" - if np.sum(ivec) != 0: + if len(ivec) <= MAX_NUMBER_OF_ATOMS_PER_ION: + human_readable = "" for hashvalue in ivec: if hashvalue != 0: protons, neutrons = hash_to_isotope(int(hashvalue)) @@ -164,12 +137,10 @@ def isotope_vector_to_human_readable_name(ivec: np.ndarray, charge_state: np.int def is_range_overlapping(interval: np.ndarray, interval_set: np.ndarray) -> bool: """Check if interval overlaps within with members of interval set.""" - assert np.shape(interval) == (2,), "Interval needs to have two columns!" - assert np.shape(interval_set)[1] == 2, \ - "Interval_set needs to have two columns!" - # interval = np.array([53.789, 54.343]) - # interval_set = np.array([[27.778, 28.33]]) # for testing purposes - if np.shape(interval_set)[0] >= 1: + if (np.shape(interval) == (2,)) and (np.shape(interval_set)[0] >= 1) \ + and (np.shape(interval_set)[1] == 2): + # interval = np.array([53.789, 54.343]) + # interval_set = np.array([[27.778, 28.33]]) # for testing purposes left_and_right_delta = np.zeros([np.shape(interval_set)[0], 2], bool) left_and_right_delta[:, 0] = (interval_set[:, 0] - interval[1]) \ > MQ_EPSILON @@ -184,8 +155,7 @@ def is_range_overlapping(interval: np.ndarray, def is_range_significant(left: np.float64, right: np.float64) -> bool: """Check if inclusive interval bounds [left, right] span a finite range.""" - assert left >= np.float64(0.) and right >= np.float64(0.), \ - "Left and right bound have to be positive!" - if (right - left) > MQ_EPSILON: - return True + if (np.float64(0.) <= left) and (np.float64(0.) <= right): + if (right - left) > MQ_EPSILON: + return True return False diff --git a/linting.sh b/linting.sh index 31d2c74..652d843 100755 --- a/linting.sh +++ b/linting.sh @@ -4,5 +4,5 @@ # in both cases the ifes_apt_tc_data_modeling module should have been installed in developer mode python -m pycodestyle --ignore=E501 ifes_apt_tc_data_modeling -python -m pylint ifes_apt_tc_data_modeling --ignore build +python -m pylint --rcfile=pylintrc.rc ifes_apt_tc_data_modeling --ignore build python -m mypy --ignore-missing-imports ifes_apt_tc_data_modeling \ No newline at end of file diff --git a/pylintrc.rc b/pylintrc.rc new file mode 100644 index 0000000..3b1cdae --- /dev/null +++ b/pylintrc.rc @@ -0,0 +1,637 @@ +[MAIN] + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Clear in-memory caches upon conclusion of linting. Useful if running pylint +# in a server-like mode. +clear-cache-post-run=no + +# Load and enable all available extensions. Use --list-extensions to see a list +# all available extensions. +#enable-all-extensions= + +# In error mode, messages with a category besides ERROR or FATAL are +# suppressed, and no reports are done by default. Error mode is compatible with +# disabling specific errors. +#errors-only= + +# Always return a 0 (non-error) status code, even if lint errors are found. +# This is primarily useful in continuous integration scripts. +#exit-zero= + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code. +extension-pkg-allow-list= + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code. (This is an alternative name to extension-pkg-allow-list +# for backward compatibility.) +extension-pkg-whitelist= + +# Return non-zero exit code if any of these messages/categories are detected, +# even if score is above --fail-under value. Syntax same as enable. Messages +# specified are enabled, while categories only check already-enabled messages. +fail-on= + +# Specify a score threshold under which the program will exit with error. +fail-under=10 + +# Interpret the stdin as a python script, whose filename needs to be passed as +# the module_or_package argument. +#from-stdin= + +# Files or directories to be skipped. They should be base names, not paths. +ignore=CVS + +# Add files or directories matching the regular expressions patterns to the +# ignore-list. The regex matches against paths and can be in Posix or Windows +# format. Because '\\' represents the directory delimiter on Windows systems, +# it can't be used as an escape character. +ignore-paths= + +# Files or directories matching the regular expression patterns are skipped. +# The regex matches against base names, not paths. The default value ignores +# Emacs file locks +ignore-patterns=^\.# + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis). It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the +# number of processors available to use, and will cap the count on Windows to +# avoid hangs. +jobs=1 + +# Control the amount of potential inferred values when inferring a single +# object. This can help the performance when dealing with large functions or +# complex, nested conditions. +limit-inference-results=100 + +# List of plugins (as comma separated values of python module names) to load, +# usually to register additional checkers. +load-plugins= + +# Pickle collected data for later comparisons. +persistent=yes + +# Minimum Python version to use for version dependent checks. Will default to +# the version used to run pylint. +py-version=3.11 + +# Discover python modules and packages in the file system subtree. +recursive=no + +# Add paths to the list of the source roots. Supports globbing patterns. The +# source root is an absolute path or a path relative to the current working +# directory used to determine a package namespace for modules located under the +# source root. +source-roots= + +# When enabled, pylint would attempt to guess common misconfiguration and emit +# user-friendly hints instead of false-positive error messages. +suggestion-mode=yes + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + +# In verbose mode, extra non-checker-related info will be displayed. +#verbose= + + +[BASIC] + +# Naming style matching correct argument names. +argument-naming-style=snake_case + +# Regular expression matching correct argument names. Overrides argument- +# naming-style. If left empty, argument names will be checked with the set +# naming style. +#argument-rgx= + +# Naming style matching correct attribute names. +attr-naming-style=snake_case + +# Regular expression matching correct attribute names. Overrides attr-naming- +# style. If left empty, attribute names will be checked with the set naming +# style. +#attr-rgx= + +# Bad variable names which should always be refused, separated by a comma. +bad-names=foo, + bar, + baz, + toto, + tutu, + tata + +# Bad variable names regexes, separated by a comma. If names match any regex, +# they will always be refused +bad-names-rgxs= + +# Naming style matching correct class attribute names. +class-attribute-naming-style=any + +# Regular expression matching correct class attribute names. Overrides class- +# attribute-naming-style. If left empty, class attribute names will be checked +# with the set naming style. +#class-attribute-rgx= + +# Naming style matching correct class constant names. +class-const-naming-style=UPPER_CASE + +# Regular expression matching correct class constant names. Overrides class- +# const-naming-style. If left empty, class constant names will be checked with +# the set naming style. +#class-const-rgx= + +# Naming style matching correct class names. +class-naming-style=PascalCase + +# Regular expression matching correct class names. Overrides class-naming- +# style. If left empty, class names will be checked with the set naming style. +#class-rgx= + +# Naming style matching correct constant names. +const-naming-style=UPPER_CASE + +# Regular expression matching correct constant names. Overrides const-naming- +# style. If left empty, constant names will be checked with the set naming +# style. +#const-rgx= + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + +# Naming style matching correct function names. +function-naming-style=snake_case + +# Regular expression matching correct function names. Overrides function- +# naming-style. If left empty, function names will be checked with the set +# naming style. +#function-rgx= + +# Good variable names which should always be accepted, separated by a comma. +good-names=i, + j, + k, + ex, + Run, + _ + +# Good variable names regexes, separated by a comma. If names match any regex, +# they will always be accepted +good-names-rgxs= + +# Include a hint for the correct naming format with invalid-name. +include-naming-hint=no + +# Naming style matching correct inline iteration names. +inlinevar-naming-style=any + +# Regular expression matching correct inline iteration names. Overrides +# inlinevar-naming-style. If left empty, inline iteration names will be checked +# with the set naming style. +#inlinevar-rgx= + +# Naming style matching correct method names. +method-naming-style=snake_case + +# Regular expression matching correct method names. Overrides method-naming- +# style. If left empty, method names will be checked with the set naming style. +#method-rgx= + +# Naming style matching correct module names. +module-naming-style=snake_case + +# Regular expression matching correct module names. Overrides module-naming- +# style. If left empty, module names will be checked with the set naming style. +#module-rgx= + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +# These decorators are taken in consideration only for invalid-name. +property-classes=abc.abstractproperty + +# Regular expression matching correct type alias names. If left empty, type +# alias names will be checked with the set naming style. +#typealias-rgx= + +# Regular expression matching correct type variable names. If left empty, type +# variable names will be checked with the set naming style. +#typevar-rgx= + +# Naming style matching correct variable names. +variable-naming-style=snake_case + +# Regular expression matching correct variable names. Overrides variable- +# naming-style. If left empty, variable names will be checked with the set +# naming style. +#variable-rgx= + + +[CLASSES] + +# Warn about protected attribute access inside special methods +check-protected-access-in-special-methods=no + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp, + asyncSetUp, + __post_init__ + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[DESIGN] + +# List of regular expressions of class ancestor names to ignore when counting +# public methods (see R0903) +exclude-too-few-public-methods= + +# List of qualified class names to ignore when counting class parents (see +# R0901) +ignored-parents= + +# Maximum number of arguments for function / method. +max-args=5 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Maximum number of boolean expressions in an if statement (see R0916). +max-bool-expr=5 + +# Maximum number of branch for function / method body. +max-branches=12 + +# Maximum number of locals for function / method body. +max-locals=15 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body. +max-returns=6 + +# Maximum number of statements in function / method body. +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when caught. +overgeneral-exceptions=builtins.BaseException,builtins.Exception + + +[FORMAT] + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module. +max-module-lines=1000 + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + + +[IMPORTS] + +# List of modules that can be imported at any level, not just the top level +# one. +allow-any-import-level= + +# Allow explicit reexports by alias from a package __init__. +allow-reexport-from-package=no + +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# Deprecated modules which should not be used, separated by a comma. +deprecated-modules= + +# Output a graph (.gv or any supported image format) of external dependencies +# to the given file (report RP0402 must not be disabled). +ext-import-graph= + +# Output a graph (.gv or any supported image format) of all (i.e. internal and +# external) dependencies to the given file (report RP0402 must not be +# disabled). +import-graph= + +# Output a graph (.gv or any supported image format) of internal dependencies +# to the given file (report RP0402 must not be disabled). +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + +# Couples of modules and preferred modules, separated by a comma. +preferred-modules= + + +[LOGGING] + +# The type of string formatting that logging methods do. `old` means using % +# formatting, `new` is for `{}` formatting. +logging-format-style=old + +# Logging modules to check that the string format arguments are in logging +# function parameter format. +logging-modules=logging + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE, +# UNDEFINED. +confidence=HIGH, + CONTROL_FLOW, + INFERENCE, + INFERENCE_FAILURE, + UNDEFINED + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once). You can also use "--disable=all" to +# disable everything first and then re-enable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use "--disable=all --enable=classes +# --disable=W". +disable=raw-checker-failed, + bad-inline-option, + locally-disabled, + file-ignored, + suppressed-message, + useless-suppression, + deprecated-pragma, + use-symbolic-message-instead, + use-implicit-booleaness-not-comparison-to-string, + use-implicit-booleaness-not-comparison-to-zero, + line-too-long, + too-many-lines, + too-few-public-methods + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable= + + +[METHOD_ARGS] + +# List of qualified names (i.e., library.method) which require a timeout +# parameter e.g. 'requests.api.get,requests.api.post' +timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME, + XXX, + TODO + +# Regular expression of note tags to take in consideration. +notes-rgx= + + +[REFACTORING] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + +# Complete name of functions that never returns. When checking for +# inconsistent-return-statements if a never returning function is called then +# it will be considered as an explicit return statement and no message will be +# printed. +never-returning-functions=sys.exit,argparse.parse_error + + +[REPORTS] + +# Python expression which should return a score less than or equal to 10. You +# have access to the variables 'fatal', 'error', 'warning', 'refactor', +# 'convention', and 'info' which contain the number of messages in each +# category, as well as 'statement' which is the total number of statements +# analyzed. This score is used by the global evaluation report (RP0004). +evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details. +msg-template= + +# Set the output format. Available formats are: text, parseable, colorized, +# json2 (improved json format), json (old json format) and msvs (visual +# studio). You can also give a reporter class, e.g. +# mypackage.mymodule.MyReporterClass. +#output-format= + +# Tells whether to display a full report or only the messages. +reports=no + +# Activate the evaluation score. +score=yes + + +[SIMILARITIES] + +# Comments are removed from the similarity computation +ignore-comments=yes + +# Docstrings are removed from the similarity computation +ignore-docstrings=yes + +# Imports are removed from the similarity computation +ignore-imports=yes + +# Signatures are removed from the similarity computation +ignore-signatures=yes + +# Minimum lines number of a similarity. +min-similarity-lines=4 + + +[SPELLING] + +# Limits count of emitted suggestions for spelling mistakes. +max-spelling-suggestions=4 + +# Spelling dictionary name. No available dictionaries : You need to install +# both the python package and the system dependency for enchant to work. +spelling-dict= + +# List of comma separated words that should be considered directives if they +# appear at the beginning of a comment and should not be checked. +spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy: + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains the private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to the private dictionary (see the +# --spelling-private-dict-file option) instead of raising a message. +spelling-store-unknown-words=no + + +[STRING] + +# This flag controls whether inconsistent-quotes generates a warning when the +# character used as a quote delimiter is used inconsistently within a module. +check-quote-consistency=no + +# This flag controls whether the implicit-str-concat should generate a warning +# on implicit string concatenation in sequences defined over several lines. +check-str-concat-over-line-jumps=no + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + +# Tells whether to warn about missing members when the owner of the attribute +# is inferred to be None. +ignore-none=yes + +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes + +# List of symbolic message names to ignore for Mixin members. +ignored-checks-for-mixins=no-member, + not-async-context-manager, + not-context-manager, + attribute-defined-outside-init + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace + +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 + +# Regex pattern to define which classes are considered mixins. +mixin-class-rgx=.*[Mm]ixin + +# List of decorators that change the signature of a decorated function. +signature-mutators= + + +[VARIABLES] + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid defining new builtins when possible. +additional-builtins= + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# List of names allowed to shadow builtins +allowed-redefined-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_, + _cb + +# A regular expression matching the name of dummy variables (i.e. expected to +# not be used). +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ + +# Argument names that match this expression will be ignored. +ignored-argument-names=_.*|^ignored_|^unused_ + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io diff --git a/tests/TestsForDevelopers.ipynb b/tests/TestsForDevelopers.ipynb index c14b031..70af70c 100644 --- a/tests/TestsForDevelopers.ipynb +++ b/tests/TestsForDevelopers.ipynb @@ -805,7 +805,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.11.5" } }, "nbformat": 4, From 06a20876cc79c0cba5b9740149f14e259e6ce47b Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Sat, 30 Dec 2023 20:23:16 +0100 Subject: [PATCH 11/20] Further refactoring and code cleaning, pyccapt and apt reader remains --- ifes_apt_tc_data_modeling/ato/ato_reader.py | 55 ++++--- ifes_apt_tc_data_modeling/csv/csv_reader.py | 20 +-- ifes_apt_tc_data_modeling/env/env_reader.py | 60 +++---- ifes_apt_tc_data_modeling/epos/epos_reader.py | 88 +++++------ ifes_apt_tc_data_modeling/fig/fig_reader.py | 53 ++----- ifes_apt_tc_data_modeling/nexus/nx_field.py | 6 +- ifes_apt_tc_data_modeling/nexus/nx_ion.py | 119 +++++++------- ifes_apt_tc_data_modeling/pos/pos_reader.py | 42 +++-- .../pyccapt/pyccapt_reader.py | 17 +- ifes_apt_tc_data_modeling/rng/rng_reader.py | 123 ++++++--------- ifes_apt_tc_data_modeling/rrng/rrng_reader.py | 149 ++++++++---------- .../utils/combinatorics.py | 50 ++++++ ifes_apt_tc_data_modeling/utils/utils.py | 12 ++ tests/TestsForDevelopers.ipynb | 84 +++++----- 14 files changed, 430 insertions(+), 448 deletions(-) create mode 100644 ifes_apt_tc_data_modeling/utils/combinatorics.py diff --git a/ifes_apt_tc_data_modeling/ato/ato_reader.py b/ifes_apt_tc_data_modeling/ato/ato_reader.py index d71f2a7..61bf800 100644 --- a/ifes_apt_tc_data_modeling/ato/ato_reader.py +++ b/ifes_apt_tc_data_modeling/ato/ato_reader.py @@ -28,12 +28,12 @@ class ReadAtoFileFormat(): """Read Rouen group *.ato file format.""" - def __init__(self, filename: str): - if (len(filename) <= 4) or (filename.lower().endswith(".ato") is False): - raise ImportError("WARNING::ATO file incorrect filename ending or file type!") - self.filename = filename + def __init__(self, file_path: str): + if (len(file_path) <= 4) or (file_path.lower().endswith(".ato") is False): + raise ImportError("WARNING::ATO file incorrect file_path ending or file type!") + self.file_path = file_path - self.filesize = os.path.getsize(self.filename) + self.file_size = os.path.getsize(self.file_path) self.number_of_events = None self.version = None retval = self.get_ato_version() @@ -42,14 +42,14 @@ def __init__(self, filename: str): 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)) + assert (self.file_size - 2 * 4) % 14 * 4 == 0, \ + "ATO v3 file_size not integer multiple of 14*4B!" + self.number_of_events = np.uint32((self.file_size - 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) + assert (self.file_size - 5000) % 40 == 0, \ + "ATO v5 file_size not integer multiple of 40B!" + self.number_of_events = np.uint32((self.file_size - 5000) / 40) print(f"ATO file contains {self.number_of_events} entries") else: raise ImportError("ATO file unsupported version!") @@ -64,7 +64,8 @@ def __init__(self, filename: str): # suggests that additional polishing of results is needed def get_ato_version(self): - header = get_memory_mapped_data(self.filename, " x, wpy -> y, fpz -> z @@ -90,16 +90,16 @@ def get_reconstructed_positions(self): # the resulting x, y coordinates suggests that v5 ATO stores in angstroem, while fpz is stored in nm? # however https://zenodo.org/records/8382828 reports the reconstructed positions to be named # not at all wpx, wpy and fpz but x, y, z instead and here claims the nm - 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 @@ -107,16 +107,15 @@ 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.values = 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, " 0 and shp[1] == 4: self.number_of_events = shp[0] else: @@ -47,7 +47,7 @@ def get_reconstructed_positions(self): """Read xyz columns.""" xyz = NxField() - xyz.typed_value = np.zeros([self.number_of_events, 3], np.float32) + xyz.values = np.zeros([self.number_of_events, 3], np.float32) xyz.unit = "nm" # there are too many assumption made here as to the content # in the csv file sure one could pass some configuration hints but @@ -56,18 +56,18 @@ def get_reconstructed_positions(self): # no magic number, de facto this works only because users know what # to expect in advance but how should a machine know this? for dim in [0, 1, 2]: - xyz.typed_value[:, dim] = pd.read_csv(self.filename).iloc[:, dim] + xyz.values[:, dim] = pd.read_csv(self.file_path).iloc[:, dim] 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.values = np.zeros([self.number_of_events, 1], np.float32) m_n.unit = "Da" # again such a strong assumption! # why reported in Da? # why in the third column # why at all a mass-to-charge-state-ratio value array? - m_n.typed_value[:, 0] = pd.read_csv(self.filename).iloc[:, 3] + m_n.values[:, 0] = pd.read_csv(self.file_path).iloc[:, 3] return m_n diff --git a/ifes_apt_tc_data_modeling/env/env_reader.py b/ifes_apt_tc_data_modeling/env/env_reader.py index 5afd359..d1b0f13 100644 --- a/ifes_apt_tc_data_modeling/env/env_reader.py +++ b/ifes_apt_tc_data_modeling/env/env_reader.py @@ -18,13 +18,13 @@ """ENV file format reader for GPM/Rouen ENV system configuration and range files""" +# pylint: disable=too-many-nested-blocks import re import numpy as np -from ase.data import chemical_symbols from ifes_apt_tc_data_modeling.nexus.nx_ion import NxField, NxIon from ifes_apt_tc_data_modeling.utils.utils import \ - create_isotope_vector, is_range_significant + create_isotope_vector, is_range_significant, get_smart_chemical_symbols from ifes_apt_tc_data_modeling.utils.definitions import MQ_EPSILON from ifes_apt_tc_data_modeling.utils.molecular_ions import MolecularIonBuilder from ifes_apt_tc_data_modeling.utils.molecular_ions import \ @@ -32,43 +32,28 @@ PRACTICAL_MIN_HALF_LIFE, VERBOSE, SACRIFICE_ISOTOPIC_UNIQUENESS -def get_smart_chemical_symbols(): - """Organize element symbols such that search H does not match He.""" - priority_queue = [] - for symbol in chemical_symbols: - if len(symbol) == 2: - priority_queue.append(symbol) - for symbol in chemical_symbols: - if symbol != "X" and len(symbol) == 1: - priority_queue.append(symbol) - return priority_queue - - def evaluate_env_range_line(line: str): """Represent information content of a single range line.""" # example line: ". 107.7240 108.0960 1 0 0 0 0 0 0 0 0 0 3 0 0 0" - info: dict = {} - info["identifier"] = None - info["range"] = np.asarray([0., MQ_EPSILON], np.float64) - info["atoms"] = [] - info["volume"] = np.float64(0.) - info["color"] = "" - info["name"] = "" + info: dict = {"identifier": None, + "range": np.asarray([0., MQ_EPSILON], np.float64), + "atoms": [], + "volume": np.float64(0.), + "color": "", + "name": ""} tmp = line.split() - # interpret zeroth token into a list of chemical symbols # interpret first token as inclusive left of m/q interval # interpret second token as inclusive right bound of m/q interval if len(tmp) < 3: print(f"WARNING::ENV file ranging definition {line} has insufficient information!") return None - if is_range_significant(np.float64(tmp[1]), np.float64(tmp[2])) is True: - info["range"] = np.asarray([tmp[1], tmp[2]], np.float64) - else: + if is_range_significant(np.float64(tmp[1]), np.float64(tmp[2])) is False: print(f"WARNING::ENV file ranging definition {line} has insignificant range!") return None + info["range"] = np.asarray([tmp[1], tmp[2]], np.float64) lst: list = [] if tmp[0] == "Hyd": lst = [] @@ -94,20 +79,19 @@ def evaluate_env_range_line(line: str): class ReadEnvFileFormat(): """Read GPM/Rouen *.env file format.""" - def __init__(self, filename: str): - if (len(filename) <= 4) or (filename.lower().endswith(".env") is False): - raise ImportError("WARNING::ENV file incorrect filename ending or file type!") - self.filename = filename - self.env: dict = {} - self.env["ranges"] = {} - self.env["ions"] = {} - self.env["molecular_ions"] = [] + def __init__(self, file_path: str): + if (len(file_path) <= 4) or (file_path.lower().endswith(".env") is False): + raise ImportError("WARNING::ENV file incorrect file_path ending or file type!") + self.file_path = file_path + self.env: dict = {"ranges": {}, + "ions": {}, + "molecular_ions": []} self.read_env() def read_env(self): """Read ENV system configuration and ranging definitions.""" # GPM/Rouen ENV file format is neither standardized nor uses magic number - with open(self.filename, mode="r", encoding="utf-8") as envf: + with open(self.file_path, mode="r", encoding="utf-8") as envf: txt = envf.read() txt = txt.replace("\r\n", "\n") # windows to unix EOL conversion txt = txt.replace(",", ".") # use decimal dots instead of comma @@ -149,9 +133,9 @@ def read_env(self): sacrifice_uniqueness=SACRIFICE_ISOTOPIC_UNIQUENESS, verbose=VERBOSE) recovered_charge_state, m_ion_candidates = crawler.combinatorics( - m_ion.isotope_vector.typed_value, - m_ion.ranges.typed_value[0, 0], - m_ion.ranges.typed_value[0, 1]) + m_ion.isotope_vector.values, + m_ion.ranges.values[0, 0], + m_ion.ranges.values[0, 1]) # print(f"{recovered_charge_state}") m_ion.charge_state = NxField(np.int8(recovered_charge_state), "") m_ion.update_human_readable_name() @@ -162,4 +146,4 @@ def read_env(self): m_ion_candidates) self.env["molecular_ions"].append(m_ion) - print(f"{self.filename} parsed successfully") + print(f"{self.file_path} parsed successfully") diff --git a/ifes_apt_tc_data_modeling/epos/epos_reader.py b/ifes_apt_tc_data_modeling/epos/epos_reader.py index 96978c9..83b4073 100644 --- a/ifes_apt_tc_data_modeling/epos/epos_reader.py +++ b/ifes_apt_tc_data_modeling/epos/epos_reader.py @@ -28,18 +28,16 @@ class ReadEposFileFormat(): """Read *.epos file format.""" - def __init__(self, filename: str): - assert len(filename) > 5, "ePOS file incorrect filename ending!" - assert filename.lower().endswith(".epos"), \ - "ePOS file incorrect file type!" - self.filename = filename - - self.filesize = os.path.getsize(self.filename) - assert self.filesize % 11 * 4 == 0, \ - "ePOS filesize not integer multiple of 11*4B!" - assert np.uint32(self.filesize / (11 * 4)) < np.iinfo(np.uint32).max, \ + def __init__(self, file_path: str): + if (len(file_path) <= 5) or (file_path.lower().endswith(".epos") is False): + raise ImportError("WARNING::ePOS file incorrect file_path ending or file type!") + self.file_path = file_path + self.file_size = os.path.getsize(self.file_path) + assert self.file_size % 11 * 4 == 0, \ + "ePOS file_size not integer multiple of 11*4B!" + assert np.uint32(self.file_size / (11 * 4)) < np.iinfo(np.uint32).max, \ "ePOS file is too large, currently only 2*32 supported!" - self.number_of_events = np.uint32(self.filesize / (11 * 4)) + self.number_of_events = np.uint32(self.file_size / (11 * 4)) # https://doi.org/10.1007/978-1-4614-3436-8 for file format details # dtyp_names = ["Reconstructed position along the x-axis (nm)", @@ -60,46 +58,43 @@ def get_reconstructed_positions(self): """Read xyz columns.""" xyz = NxField() - xyz.typed_value = np.zeros( - [self.number_of_events, 3], np.float32) + xyz.values = np.zeros([self.number_of_events, 3], np.float32) xyz.unit = "nm" - xyz.typed_value[:, 0] = \ - get_memory_mapped_data(self.filename, ">f4", + xyz.values[:, 0] = \ + get_memory_mapped_data(self.file_path, ">f4", 0 * 4, 11 * 4, self.number_of_events) # x - xyz.typed_value[:, 1] = \ - get_memory_mapped_data(self.filename, ">f4", + xyz.values[:, 1] = \ + get_memory_mapped_data(self.file_path, ">f4", 1 * 4, 11 * 4, self.number_of_events) # y - xyz.typed_value[:, 2] = \ - get_memory_mapped_data(self.filename, ">f4", + xyz.values[:, 2] = \ + get_memory_mapped_data(self.file_path, ">f4", 2 * 4, 11 * 4, self.number_of_events) # 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.values = np.zeros([self.number_of_events, 1], np.float32) m_n.unit = "Da" - m_n.typed_value[:, 0] = \ - get_memory_mapped_data(self.filename, ">f4", + m_n.values[:, 0] = \ + get_memory_mapped_data(self.file_path, ">f4", 3 * 4, 11 * 4, self.number_of_events) return m_n def get_raw_time_of_flight(self): """Read raw (uncorrected) time-of-flight.""" raw_tof = NxField() - raw_tof.typed_value = np.zeros( - [self.number_of_events, 1], np.float32) + raw_tof.values = np.zeros([self.number_of_events, 1], np.float32) raw_tof.unit = "ns" # according to DOI: 10.1007/978-1-4899-7430-3 raw time-of-flight # i.e. this is an uncorrected time-of-flight # for which effects uncorrect? # Only the proprietary IVAS/APSuite source code knows for sure - raw_tof.typed_value[:, 0] = \ - get_memory_mapped_data(self.filename, ">f4", + raw_tof.values[:, 0] = \ + get_memory_mapped_data(self.file_path, ">f4", 4 * 4, 11 * 4, self.number_of_events) return raw_tof @@ -109,14 +104,13 @@ def get_standing_voltage(self): # standing voltage on the specimen # according to DOI: 10.1007/978-1-4614-8721-0 also-known as DC voltage dc_voltage = NxField() - dc_voltage.typed_value = np.zeros( - [self.number_of_events, 1], np.float32) + dc_voltage.values = np.zeros([self.number_of_events, 1], np.float32) dc_voltage.unit = "kV" # different to the above-mentioned references Gault et al. state # that standing and pulse_voltage are in V instead of kV - dc_voltage.typed_value[:, 0] = \ - get_memory_mapped_data(self.filename, ">f4", + dc_voltage.values[:, 0] = \ + get_memory_mapped_data(self.file_path, ">f4", 5 * 4, 11 * 4, self.number_of_events) return dc_voltage @@ -126,27 +120,25 @@ def get_pulse_voltage(self): # additional voltage to trigger field evaporation in case # of high-voltage pulsing, 0 for laser pulsing pu_voltage = NxField() - pu_voltage.typed_value = np.zeros( - [self.number_of_events, 1], np.float32) + pu_voltage.values = np.zeros([self.number_of_events, 1], np.float32) pu_voltage.unit = "kV" - pu_voltage.typed_value[:, 0] = \ - get_memory_mapped_data(self.filename, ">f4", + pu_voltage.values[:, 0] = \ + get_memory_mapped_data(self.file_path, ">f4", 6 * 4, 11 * 4, self.number_of_events) return pu_voltage def get_hit_positions(self): """Read ion impact positions on detector.""" hit_positions = NxField() - hit_positions.typed_value = np.zeros( - [self.number_of_events, 2], np.float32) + hit_positions.values = np.zeros([self.number_of_events, 2], np.float32) hit_positions.unit = "mm" - hit_positions.typed_value[:, 0] = \ - get_memory_mapped_data(self.filename, ">f4", + hit_positions.values[:, 0] = \ + get_memory_mapped_data(self.file_path, ">f4", 7 * 4, 11 * 4, self.number_of_events) # x - hit_positions.typed_value[:, 1] = \ - get_memory_mapped_data(self.filename, ">f4", + hit_positions.values[:, 1] = \ + get_memory_mapped_data(self.file_path, ">f4", 8 * 4, 11 * 4, self.number_of_events) # y return hit_positions @@ -157,12 +149,11 @@ def get_number_of_pulses(self): # 0 after the first ion per pulse # also known as $\Delta Pulse$ npulses = NxField() - npulses.typed_value = np.zeros( - [self.number_of_events, 1], np.uint32) + npulses.values = np.zeros([self.number_of_events, 1], np.uint32) npulses.unit = "" - npulses.typed_value[:, 0] = \ - get_memory_mapped_data(self.filename, ">u4", + npulses.values[:, 0] = \ + get_memory_mapped_data(self.file_path, ">u4", 9 * 4, 11 * 4, self.number_of_events) return npulses @@ -171,11 +162,10 @@ def get_ions_per_pulse(self): # according to DOI: 10.1007/978-1-4899-7430-3 # ions per pulse, 0 after the first ion ions_per_pulse = NxField() - ions_per_pulse.typed_value = np.zeros( - [self.number_of_events, 1], np.uint32) + ions_per_pulse.values = np.zeros([self.number_of_events, 1], np.uint32) ions_per_pulse.unit = "" - ions_per_pulse.typed_value[:, 0] = \ - get_memory_mapped_data(self.filename, ">u4", + ions_per_pulse.values[:, 0] = \ + get_memory_mapped_data(self.file_path, ">u4", 10 * 4, 11 * 4, self.number_of_events) return ions_per_pulse diff --git a/ifes_apt_tc_data_modeling/fig/fig_reader.py b/ifes_apt_tc_data_modeling/fig/fig_reader.py index a19bc41..3fe2483 100644 --- a/ifes_apt_tc_data_modeling/fig/fig_reader.py +++ b/ifes_apt_tc_data_modeling/fig/fig_reader.py @@ -18,36 +18,36 @@ """Reader for ranging defs extracted from FAU/Erlangen Atom Probe Toolbox Matlab figures FIG.TXT.""" +# pylint: disable=too-many-locals + import re import numpy as np -from ase.data import atomic_numbers, chemical_symbols +from ase.data import atomic_numbers from ifes_apt_tc_data_modeling.nexus.nx_ion import NxField, NxIon from ifes_apt_tc_data_modeling.utils.definitions import \ MAX_NUMBER_OF_ATOMS_PER_ION from ifes_apt_tc_data_modeling.utils.molecular_ions import \ - get_chemical_symbols, isotope_to_hash, MolecularIonBuilder, \ - PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ - PRACTICAL_MIN_HALF_LIFE, VERBOSE, SACRIFICE_ISOTOPIC_UNIQUENESS + get_chemical_symbols, isotope_to_hash +from ifes_apt_tc_data_modeling.utils.combinatorics import \ + apply_combinatorics class ReadFigTxtFileFormat(): """Read *.fig.txt file format.""" - def __init__(self, filename: str): - if (len(filename) <= 7) or (filename.lower().endswith(".fig.txt") is False): - raise ImportError("WARNING::FIG.TXT file incorrect filename ending or file type!") - self.filename = filename - - self.fig: dict = {} - self.fig["ranges"] = {} - self.fig["ions"] = {} - self.fig["molecular_ions"] = [] + def __init__(self, file_path: str): + if (len(file_path) <= 8) or (file_path.lower().endswith(".fig.txt") is False): + raise ImportError("WARNING::FIG.TXT file incorrect file_path ending or file type!") + self.file_path = file_path + self.fig: dict = {"ranges": {}, + "ions": {}, + "molecular_ions": []} self.read_fig_txt() def read_fig_txt(self): """Read FIG.TXT range file content.""" - with open(self.filename, mode="r", encoding="utf8") as figf: + with open(self.file_path, mode="r", encoding="utf8") as figf: txt = figf.read() txt = txt.replace("\r\n", "\n") # windows to unix EOL conversion @@ -93,32 +93,13 @@ def read_fig_txt(self): ivec = np.sort(np.asarray(ivec, np.uint16))[::-1] ivector = np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,), np.uint16) ivector[0:len(ivec)] = ivec - # print(ivector) m_ion = NxIon(isotope_vector=ivector, charge_state=charge_state) m_ion.add_range(mqmin, mqmax) m_ion.comment = NxField(ionname, "") + apply_combinatorics(m_ion) # m_ion.report() - crawler = MolecularIonBuilder( - min_abundance=PRACTICAL_ABUNDANCE, - min_abundance_product=PRACTICAL_ABUNDANCE_PRODUCT, - min_half_life=PRACTICAL_MIN_HALF_LIFE, - sacrifice_uniqueness=SACRIFICE_ISOTOPIC_UNIQUENESS, - verbose=VERBOSE) - recovered_charge_state, m_ion_candidates = crawler.combinatorics( - m_ion.isotope_vector.typed_value, - m_ion.ranges.typed_value[0, 0], - m_ion.ranges.typed_value[0, 1]) - # print(f"{recovered_charge_state}") - m_ion.charge_state = NxField(np.int8(recovered_charge_state), "") - m_ion.update_human_readable_name() - m_ion.add_charge_state_model( - {"min_abundance": PRACTICAL_ABUNDANCE, - "min_abundance_product": PRACTICAL_ABUNDANCE_PRODUCT, - "min_half_life": PRACTICAL_MIN_HALF_LIFE, - "sacrifice_isotopic_uniqueness": SACRIFICE_ISOTOPIC_UNIQUENESS}, - m_ion_candidates) - self.fig["molecular_ions"].append(m_ion) - print(f"{self.filename} parsed successfully") + + print(f"{self.file_path} parsed successfully") diff --git a/ifes_apt_tc_data_modeling/nexus/nx_field.py b/ifes_apt_tc_data_modeling/nexus/nx_field.py index 52ad007..6e51ad5 100644 --- a/ifes_apt_tc_data_modeling/nexus/nx_field.py +++ b/ifes_apt_tc_data_modeling/nexus/nx_field.py @@ -27,17 +27,17 @@ class NxField(): """Representative of a NeXus field.""" - def __init__(self, typed_value=None, unit: str = ""): + def __init__(self, values=None, unit: str = ""): self.parent = None self.is_a = None # ontology reference concept ID e.g. - self.typed_value = typed_value + self.values = values self.unit_category = None self.unit = unit self.attributes = None def get_value(self): """Get value.""" - return self.typed_value + return self.values def get_unit(self): """Get unit.""" diff --git a/ifes_apt_tc_data_modeling/nexus/nx_ion.py b/ifes_apt_tc_data_modeling/nexus/nx_ion.py index 68d3b8d..9fbd88a 100644 --- a/ifes_apt_tc_data_modeling/nexus/nx_ion.py +++ b/ifes_apt_tc_data_modeling/nexus/nx_ion.py @@ -23,6 +23,8 @@ """Set of utility tools for parsing file formats used by atom probe.""" +# pylint: disable=too-many-instance-attributes + import numpy as np from ifes_apt_tc_data_modeling.utils.definitions import \ @@ -42,21 +44,22 @@ def __init__(self, *args, **kwargs): self.color = NxField("", "") # color used by software which created the dataset self.volume = NxField("", "") # volume value in range files self.ion_type = NxField("", "") + self.charge_state_model = {} if len(args) >= 1: - assert isinstance(args[0], list), "args[0] needs to be a list !" + if isinstance(args[0], list) is False: + raise ValueError("args[0] needs to be a list!") self.isotope_vector = NxField(create_isotope_vector(args[0]), "") elif "isotope_vector" in kwargs: - assert isinstance(kwargs["isotope_vector"], np.ndarray), \ - "kwargs isotope_vector needs to be an np.ndarray !" - assert np.shape(kwargs["isotope_vector"]) == (MAX_NUMBER_OF_ATOMS_PER_ION,), \ - f"kwargs isotope_vector needs be a ({MAX_NUMBER_OF_ATOMS_PER_ION},) array!" - self.isotope_vector = NxField(np.asarray(kwargs["isotope_vector"], - np.uint16), "") + if isinstance(kwargs["isotope_vector"], np.ndarray) is False: + raise ValueError("kwargs isotope_vector needs to be an np.ndarray!") + if np.shape(kwargs["isotope_vector"]) != (MAX_NUMBER_OF_ATOMS_PER_ION,): + raise ValueError( + f"kwargs isotope_vector needs be a ({MAX_NUMBER_OF_ATOMS_PER_ION},) array!") + self.isotope_vector = NxField(np.asarray(kwargs["isotope_vector"], np.uint16), "") else: # the default UNKNOWN IONTYPE self.isotope_vector = NxField(create_isotope_vector([]), "") - self.nuclid_list = NxField( - isotope_vector_to_nuclid_list(self.isotope_vector.typed_value), "") + self.nuclid_list = NxField(isotope_vector_to_nuclid_list(self.isotope_vector.values), "") if "charge_state" in kwargs: if isinstance(kwargs["charge_state"], int) \ and (-8 < kwargs["charge_state"] < +8): @@ -67,87 +70,83 @@ def __init__(self, *args, **kwargs): # is not matching the theoretically expect peak location self.charge_state = NxField(np.int8(0), "") self.name = NxField(isotope_vector_to_human_readable_name( - self.isotope_vector.typed_value, self.charge_state.typed_value)) + self.isotope_vector.values, self.charge_state.values)) self.ranges = NxField(np.empty((0, 2), np.float64), "amu") def add_range(self, mqmin: np.float64, mqmax: np.float64): """Adding mass-to-charge-state ratio interval.""" - assert is_range_significant(mqmin, mqmax) is True, \ - "Refusing to add epsilon range!" + if is_range_significant(mqmin, mqmax) is False: + raise ValueError(f"Refusing to add epsilon range [{mqmin}, {mqmax}] !") # the following example shows that is_range_overlapping should not be checked for # like it was in the past # ion.add_range(10.0, 12.0), ion.add_range(12.0, 13.3) # is equivalent to ion.add_range(10.0, 13.3) # assert is_range_overlapping(np.asarray([mqmin, mqmax]), - # self.ranges.typed_value) is False, \ + # self.ranges.values) is False, \ # "Refusing overlapping range!" - self.ranges.typed_value = np.vstack( - (self.ranges.typed_value, np.array([mqmin, mqmax]))) + self.ranges.values = np.vstack((self.ranges.values, np.array([mqmin, mqmax]))) def update_human_readable_name(self): - """Reevaluate charge and isotope_vector for name.""" + """Re-evaluate charge and isotope_vector for name.""" self.name = NxField(isotope_vector_to_human_readable_name( - self.isotope_vector.typed_value, self.charge_state.typed_value)) + self.isotope_vector.values, self.charge_state.values)) def report(self): """Report values.""" - print(f"ion_type: {self.ion_type.typed_value}\n" - f"isotope_vector: {self.isotope_vector.typed_value}\n" - f"nuclid_list: {self.nuclid_list.typed_value}\n" - f"human-readable name: {self.name.typed_value}\n" - f"charge_state: {self.charge_state.typed_value}\n" - f"ranges: {self.ranges.typed_value}\n" - f"comment: {self.comment.typed_value}\n" - f"color: {self.color.typed_value}\n" - f"volume: {self.volume.typed_value}\n") + print(f"ion_type: {self.ion_type.values}\n" + f"isotope_vector: {self.isotope_vector.values}\n" + f"nuclid_list: {self.nuclid_list.values}\n" + f"human-readable name: {self.name.values}\n" + f"charge_state: {self.charge_state.values}\n" + f"ranges: {self.ranges.values}\n" + f"comment: {self.comment.values}\n" + f"color: {self.color.values}\n" + f"volume: {self.volume.values}\n") def add_charge_state_model(self, - parameters={}, - candidates=[]): + parameters, + candidates): """Add details about the model how self.charge_state was defined.""" self.charge_state_model = {} - assert "min_abundance" in parameters.keys(), \ - "Parameter min_abundance not defined!" - assert "min_abundance_product" in parameters.keys(), \ - "Parameter min_abundance_product not defined!" - assert "min_half_life" in parameters.keys(), \ - "Parameter min_half_life not defined!" - assert "sacrifice_isotopic_uniqueness" in parameters.keys(), \ - "Parameter sacrifice_isotopic_uniqueness not defined!" - self.charge_state_model = { - "isotope_matrix": [], - "charge_state_vector": [], - "mass_vector": [], - "nat_abun_prod_vector": [], - "min_half_life_vector": []} + req_parms = ["min_abundance", "min_abundance_product", + "min_half_life", "sacrifice_isotopic_uniqueness"] + for req in req_parms: + if req in parameters: + continue + raise ValueError(f"Parameter {req} not defined in parameters dict!") + self.charge_state_model = {"isotope_matrix": [], + "charge_state_vector": [], + "mass_vector": [], + "nat_abun_prod_vector": [], + "min_half_life_vector": []} for key, val in parameters.items(): if key not in self.charge_state_model: self.charge_state_model[key] = val n_cand = len(candidates) if n_cand > 0: - self.charge_state_model["isotope_matrix"] = np.zeros( - (n_cand, MAX_NUMBER_OF_ATOMS_PER_ION), np.uint16) - self.charge_state_model["charge_state_vector"] = np.zeros( - (n_cand, ), np.int8) - self.charge_state_model["mass_vector"] = np.zeros( - (n_cand, ), np.float64) - self.charge_state_model["nat_abun_prod_vector"] = np.zeros( - (n_cand, ), np.float64) - self.charge_state_model["min_half_life_vector"] = np.zeros( - (n_cand, ), np.float64) - row = 0 + self.charge_state_model["isotope_matrix"] \ + = np.zeros((n_cand, MAX_NUMBER_OF_ATOMS_PER_ION), np.uint16) + self.charge_state_model["charge_state_vector"] \ + = np.zeros((n_cand, ), np.int8) + self.charge_state_model["mass_vector"] \ + = np.zeros((n_cand, ), np.float64) + self.charge_state_model["nat_abun_prod_vector"] \ + = np.zeros((n_cand, ), np.float64) + self.charge_state_model["min_half_life_vector"] \ + = np.zeros((n_cand, ), np.float64) + row_idx = 0 for cand in candidates: if isinstance(cand, MolecularIonCandidate): - self.charge_state_model["isotope_matrix"][row, 0:len(cand.isotope_vector)] \ + self.charge_state_model["isotope_matrix"][row_idx, 0:len(cand.isotope_vector)] \ = cand.isotope_vector - self.charge_state_model["charge_state_vector"][row] = cand.charge_state - self.charge_state_model["mass_vector"][row] = cand.mass - self.charge_state_model["nat_abun_prod_vector"][row] \ + self.charge_state_model["charge_state_vector"][row_idx] = cand.charge_state + self.charge_state_model["mass_vector"][row_idx] = cand.mass + self.charge_state_model["nat_abun_prod_vector"][row_idx] \ = cand.abundance_product - self.charge_state_model["min_half_life_vector"][row] \ + self.charge_state_model["min_half_life_vector"][row_idx] \ = cand.shortest_half_life - row += 1 + row_idx += 1 else: - print(__name__ + " found cand which is not a MolecularIonCandidate!") + print(f"{__name__} found cand which is not a MolecularIonCandidate!") # else: # print("Not enough candidates to report as a charge_state model") diff --git a/ifes_apt_tc_data_modeling/pos/pos_reader.py b/ifes_apt_tc_data_modeling/pos/pos_reader.py index 3ca955a..0d78810 100644 --- a/ifes_apt_tc_data_modeling/pos/pos_reader.py +++ b/ifes_apt_tc_data_modeling/pos/pos_reader.py @@ -28,19 +28,19 @@ class ReadPosFileFormat(): """Read *.pos file format.""" - def __init__(self, filename: str): + def __init__(self, file_path: str): """Initialize the reader.""" - if (len(filename) <= 4) or (filename.lower().endswith(".pos") is False): - raise ImportError("WARNING::POS file incorrect filename ending or file type!") - self.filename = filename + if (len(file_path) <= 4) or (file_path.lower().endswith(".pos") is False): + raise ImportError("WARNING::POS file incorrect file_path ending or file type!") + self.file_path = file_path - self.filesize = os.path.getsize(self.filename) - assert self.filesize % 4 * 4 == 0, \ - "POS filesize not integer multiple of 4*4B!" - assert np.uint32(self.filesize / (4 * 4)) < np.iinfo(np.uint32).max, \ + self.file_size = os.path.getsize(self.file_path) + assert self.file_size % 4 * 4 == 0, \ + "POS file_size not integer multiple of 4*4B!" + assert np.uint32(self.file_size / (4 * 4)) < np.iinfo(np.uint32).max, \ "POS file is too large, currently only 2*32 supported!" - self.number_of_events = np.uint32(self.filesize / (4 * 4)) - # print("Initialized access to " + self.filename + " successfully") + self.number_of_events = np.uint32(self.file_size / (4 * 4)) + # print("Initialized access to " + self.file_path + " successfully") # https://doi.org/10.1007/978-1-4614-3436-8 for file format details # dtyp_names = ["Reconstructed position along the x-axis (nm)", @@ -52,18 +52,17 @@ def get_reconstructed_positions(self): """Read xyz columns.""" xyz = NxField() - xyz.typed_value = np.zeros( - [self.number_of_events, 3], np.float32) + xyz.values = np.zeros([self.number_of_events, 3], np.float32) xyz.unit = "nm" - xyz.typed_value[:, 0] = \ - get_memory_mapped_data(self.filename, ">f4", + xyz.values[:, 0] = \ + get_memory_mapped_data(self.file_path, ">f4", 0 * 4, 4 * 4, self.number_of_events) # x - xyz.typed_value[:, 1] = \ - get_memory_mapped_data(self.filename, ">f4", + xyz.values[:, 1] = \ + get_memory_mapped_data(self.file_path, ">f4", 1 * 4, 4 * 4, self.number_of_events) # y - xyz.typed_value[:, 2] = \ - get_memory_mapped_data(self.filename, ">f4", + xyz.values[:, 2] = \ + get_memory_mapped_data(self.file_path, ">f4", 2 * 4, 4 * 4, self.number_of_events) # z return xyz @@ -71,11 +70,10 @@ 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.values = np.zeros([self.number_of_events, 1], np.float32) m_n.unit = "Da" - m_n.typed_value[:, 0] = \ - get_memory_mapped_data(self.filename, ">f4", + m_n.values[:, 0] = \ + get_memory_mapped_data(self.file_path, ">f4", 3 * 4, 4 * 4, self.number_of_events) return m_n diff --git a/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py b/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py index a7f349f..6c7b89c 100644 --- a/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py +++ b/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py @@ -24,7 +24,7 @@ import numpy as np import pandas as pd -from ase.data import atomic_numbers, chemical_symbols +from ase.data import atomic_numbers from ifes_apt_tc_data_modeling.nexus.nx_ion import NxIon from ifes_apt_tc_data_modeling.nexus.nx_field import NxField from ifes_apt_tc_data_modeling.utils.utils import isotope_to_hash, \ @@ -115,6 +115,7 @@ def __init__(self, filename: str): self.number_of_events = len(self.df) def get_named_quantities(self, term: str): + """Get named quantities from dataframe.""" if term in self.df.keys(): return self.df[term] return None @@ -122,13 +123,13 @@ def get_named_quantities(self, term: str): def get_reconstructed_positions(self): """Read xyz columns.""" xyz = NxField() - xyz.typed_value = np.zeros( + xyz.values = np.zeros( [self.number_of_events, 3], np.float32) xyz.unit = "nm" dim = 0 for quant in ["x (nm)", "y (nm)", "z (nm)"]: - xyz.typed_value[:, dim] = np.asarray(self.get_named_quantities(quant), np.float32) + xyz.values[:, dim] = np.asarray(self.get_named_quantities(quant), np.float32) dim += 1 return xyz @@ -136,11 +137,11 @@ def get_mass_to_charge_state_ratio(self): """Read (calibrated) mass-to-charge-state-ratio column.""" m_n = NxField() - m_n.typed_value = np.zeros( + m_n.values = np.zeros( [self.number_of_events, 1], np.float32) m_n.unit = "Da" - m_n.typed_value[:, 0] = np.asarray(self.get_named_quantities("mc_c (Da)"), np.float32) + m_n.values[:, 0] = np.asarray(self.get_named_quantities("mc_c (Da)"), np.float32) return m_n @@ -198,9 +199,9 @@ def __init__(self, filename: str): ivec[0:len(hashvector)] = np.sort(np.asarray(hashvector, np.uint16), kind="stable")[::-1] m_ion = NxIon() - m_ion.isotope_vector.typed_value = ivec - m_ion.nuclid_list.typed_value = isotope_vector_to_nuclid_list(ivec) - m_ion.charge_state.typed_value = np.int8(self.df.iloc[idx, 9]) + m_ion.isotope_vector.values = ivec + m_ion.nuclid_list.values = isotope_vector_to_nuclid_list(ivec) + m_ion.charge_state.values = np.int8(self.df.iloc[idx, 9]) m_ion.add_range(self.df.iloc[idx, 3], self.df.iloc[idx, 4]) m_ion.update_human_readable_name() # m_ion.report() diff --git a/ifes_apt_tc_data_modeling/rng/rng_reader.py b/ifes_apt_tc_data_modeling/rng/rng_reader.py index 66ce8bb..cc63e1d 100644 --- a/ifes_apt_tc_data_modeling/rng/rng_reader.py +++ b/ifes_apt_tc_data_modeling/rng/rng_reader.py @@ -21,14 +21,12 @@ import re import numpy as np -from ase.data import chemical_symbols from ifes_apt_tc_data_modeling.nexus.nx_ion import NxField, NxIon from ifes_apt_tc_data_modeling.utils.utils import \ create_isotope_vector, is_range_significant from ifes_apt_tc_data_modeling.utils.definitions import MQ_EPSILON -from ifes_apt_tc_data_modeling.utils.molecular_ions import MolecularIonBuilder, \ - get_chemical_symbols, PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ - PRACTICAL_MIN_HALF_LIFE, VERBOSE, SACRIFICE_ISOTOPIC_UNIQUENESS +from ifes_apt_tc_data_modeling.utils.molecular_ions import get_chemical_symbols +from ifes_apt_tc_data_modeling.utils.combinatorics import apply_combinatorics # there are specific examples for unusual range files here: @@ -39,37 +37,35 @@ def evaluate_rng_range_line( i: int, line: str, column_id_to_label: dict, n_columns: int) -> dict: """Represent information content of a single range line.""" # example line: ". 107.7240 108.0960 1 0 0 0 0 0 0 0 0 0 3 0 0 0" - info: dict = {} - info["identifier"] = f"Range{i}" - info["range"] = np.asarray([0., MQ_EPSILON], np.float64) - info["atoms"] = [] - info["volume"] = np.float64(0.) - info["color"] = "" - info["name"] = "" + info: dict = {"identifier": f"Range{i}", + "range": np.asarray([0., MQ_EPSILON], np.float64), + "atoms": [], + "volume": np.float64(0.), + "color": "", + "name": ""} tmp = re.split(r"\s+", line) - assert len(tmp) is n_columns, "Line " + line \ - + " inconsistent number columns!" - assert tmp[0] == ".", "Line " + line \ - + " has inconsistent line prefix!" - - assert is_range_significant(np.float64(tmp[1]), np.float64(tmp[2])), \ - "Line " + line + " insignificant range!" + if len(tmp) != n_columns: + raise ValueError(f"Line {line} inconsistent number columns!") + if tmp[0] != ".": + raise ValueError(f"Line {line} has inconsistent line prefix!") + if is_range_significant(np.float64(tmp[1]), np.float64(tmp[2])) is False: + raise ValueError(f"Line {line} insignificant range!") info["range"] = np.asarray([tmp[1], tmp[2]], np.float64) # line encodes multiplicity of element via array of multiplicity counts element_multiplicity = np.asarray(tmp[3:len(tmp)], np.uint32) - assert np.sum(element_multiplicity) > 0, \ - "Line " + line + " no element counts!" + if np.sum(element_multiplicity) < 0: + raise ValueError(f"Line {line} no element counts!") if np.sum(element_multiplicity) > 0: - for j in np.arange(0, len(element_multiplicity)): - assert element_multiplicity[j] >= 0, \ - f"Line {line} no negative element counts!" - if element_multiplicity[j] > 0: - symbol = column_id_to_label[j + 1] + for jdx in np.arange(0, len(element_multiplicity)): + if element_multiplicity[jdx] < 0: + raise ValueError(f"Line {line} no negative element counts!") + if element_multiplicity[jdx] > 0: + symbol = column_id_to_label[jdx + 1] if symbol in get_chemical_symbols(): info["atoms"] = np.append(info["atoms"], - [column_id_to_label[j + 1]] * int(element_multiplicity[j])) + [column_id_to_label[jdx + 1]] * int(element_multiplicity[jdx])) else: info["name"] = symbol info["atoms"] = [] # will map to unknown type @@ -87,32 +83,30 @@ def evaluate_rng_ion_type_header(line: str) -> dict: # line = "------------------- Fe Mg Al Mn Si V C Ga Ti Ca O Na Co H" # line = "---- a" # line = "----------------- Sc Fe O C Al Si Cr H unknown" - info: dict = {} - info["column_id_to_label"] = {} + info: dict = {"column_id_to_label": {}} tmp = re.split(r"\s+", line) - assert len(tmp) > 1, "RNG file does not contain iontype labels!" - for i in np.arange(1, len(tmp)): - info["column_id_to_label"][i] = tmp[i] + if len(tmp) == 0: + raise ValueError(f"Line {line} does not contain iontype labels!") + for idx in np.arange(1, len(tmp)): + info["column_id_to_label"][idx] = tmp[idx] return info class ReadRngFileFormat(): """Read *.rng file format.""" - def __init__(self, filename: str): - if (len(filename) <= 4) or (filename.lower().endswith(".rng") is False): - raise ImportError("WARNING::RNG file incorrect filename ending or file type!") - self.filename = filename - - self.rng: dict = {} - self.rng["ranges"] = {} - self.rng["ions"] = {} - self.rng["molecular_ions"] = [] + def __init__(self, file_path: str): + if (len(file_path) <= 4) or (file_path.lower().endswith(".rng") is False): + raise ImportError("WARNING::RNG file incorrect file_path ending or file type!") + self.file_path = file_path + self.rng: dict = {"ranges": {}, + "ions": {}, + "molecular_ions": []} self.read_rng() def read_rng(self): """Read RNG range file content.""" - with open(self.filename, mode="r", encoding="utf8") as rngf: + with open(self.file_path, mode="r", encoding="utf8") as rngf: txt = rngf.read() txt = txt.replace("\r\n", "\n") # windows to unix EOL conversion @@ -136,55 +130,38 @@ def read_rng(self): current_line_id += int(1) else: break - assert tmp is not None, "RNG file does not contain key header line!" + if tmp is None: + raise ValueError("RNG file does not contain key header line!") header = evaluate_rng_ion_type_header(txt_stripped[current_line_id]) tmp = re.split(r"\s+", txt_stripped[0]) - assert tmp[0].isnumeric() is True, "Number of species corrupted!" + if tmp[0].isnumeric() is False: + raise ValueError(f"Line {txt_stripped[0]} number of species corrupted!") n_element_symbols = int(tmp[0]) - assert n_element_symbols >= 0, "No species defined!" - assert tmp[1].isnumeric() is True, "Number of ranges corrupted!" + if n_element_symbols < 0: + raise ValueError(f"Line {txt_stripped[0]} no species defined!") + if tmp[1].isnumeric() is False: + raise ValueError(f"Line {txt_stripped[0]} number of ranges corrupted!") n_ranges = int(tmp[1]) - assert n_ranges >= 0, "No ranges defined!" + if n_ranges < 0: + raise ValueError(f"Line {txt_stripped[0]} no ranges defined!") - for i in np.arange(current_line_id + 1, - current_line_id + 1 + n_ranges): + for idx in np.arange(current_line_id + 1, current_line_id + 1 + n_ranges): dct = evaluate_rng_range_line( - i - current_line_id, txt_stripped[i], + idx - current_line_id, txt_stripped[idx], header["column_id_to_label"], n_element_symbols + 3) if dct is None: - print("WARNING::RNG line {txt_stripped[i]} is corrupted!") + print(f"WARNING::RNG line {txt_stripped[idx]} is corrupted!") continue m_ion = NxIon(isotope_vector=create_isotope_vector( dct["atoms"]), charge_state=0) m_ion.add_range(dct["range"][0], dct["range"][1]) m_ion.comment = NxField(dct["name"], "") - m_ion.color = NxField(dct["color"], "") - m_ion.volume = NxField(dct["volume"], "") + apply_combinatorics(m_ion) # m_ion.report() - crawler = MolecularIonBuilder( - min_abundance=PRACTICAL_ABUNDANCE, - min_abundance_product=PRACTICAL_ABUNDANCE_PRODUCT, - min_half_life=PRACTICAL_MIN_HALF_LIFE, - sacrifice_uniqueness=SACRIFICE_ISOTOPIC_UNIQUENESS, - verbose=VERBOSE) - recovered_charge_state, m_ion_candidates = crawler.combinatorics( - m_ion.isotope_vector.typed_value, - m_ion.ranges.typed_value[0, 0], - m_ion.ranges.typed_value[0, 1]) - # print(f"{recovered_charge_state}") - m_ion.charge_state = NxField(np.int8(recovered_charge_state), "") - m_ion.update_human_readable_name() - m_ion.add_charge_state_model( - {"min_abundance": PRACTICAL_ABUNDANCE, - "min_abundance_product": PRACTICAL_ABUNDANCE_PRODUCT, - "min_half_life": PRACTICAL_MIN_HALF_LIFE, - "sacrifice_isotopic_uniqueness": SACRIFICE_ISOTOPIC_UNIQUENESS}, - m_ion_candidates) - self.rng["molecular_ions"].append(m_ion) - print(f"{self.filename} parsed successfully") + print(f"{self.file_path} parsed successfully") diff --git a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py index ae45708..073cbae 100644 --- a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py +++ b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py @@ -18,6 +18,8 @@ """RRNG range file reader used by atom probe microscopists.""" +# pylint: disable=too-many-branches,too-many-statements + import re import numpy as np @@ -26,10 +28,7 @@ from ifes_apt_tc_data_modeling.utils.utils import \ create_isotope_vector, is_range_significant from ifes_apt_tc_data_modeling.utils.definitions import MQ_EPSILON -from ifes_apt_tc_data_modeling.utils.molecular_ions import MolecularIonBuilder -from ifes_apt_tc_data_modeling.utils.molecular_ions import \ - PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ - PRACTICAL_MIN_HALF_LIFE, VERBOSE, SACRIFICE_ISOTOPIC_UNIQUENESS +from ifes_apt_tc_data_modeling.utils.combinatorics import apply_combinatorics def evaluate_rrng_range_line(i: int, line: str) -> dict: @@ -39,22 +38,20 @@ def evaluate_rrng_range_line(i: int, line: str) -> dict: # according to DOI: 10.1007/978-1-4614-8721-0 # mqmin, mqmax, vol, ion composition is required, # name and color fields are optional - info: dict = {} - info["identifier"] = f"Range{i}" - info["range"] = np.asarray([0., MQ_EPSILON], np.float64) - info["atoms"] = [] - info["volume"] = np.float64(0.) - info["color"] = "" - info["name"] = "" + info: dict = {"identifier": f"Range{i}", + "range": np.asarray([0., MQ_EPSILON], np.float64), + "atoms": [], + "volume": np.float64(0.), + "color": "", + "name": ""} tmp = re.split(r"[\s=]+", line) - assert len(tmp) >= 6, \ - f"Line {line} does not contain all required fields!" - assert tmp[0] == f"Range{i}" \ - f"Line {line} has inconsistent line prefix!" - - assert is_range_significant(np.float64(tmp[1]), np.float64(tmp[2])), \ - f"Line {line} insignificant range!" + if len(tmp) < 6: + raise ValueError(f"Line {line} does not contain all required fields!") + if tmp[0] != f"Range{i}": + raise ValueError(f"Line {line} has inconsistent line prefix!") + if is_range_significant(np.float64(tmp[1]), np.float64(tmp[2])) is False: + raise ValueError(f"Line {line} insignificant range!") info["range"] = np.asarray([tmp[1], tmp[2]], np.float64) if tmp[3].lower().startswith("vol:"): @@ -69,8 +66,8 @@ def evaluate_rrng_range_line(i: int, line: str) -> dict: for information in tmp[4:-1]: element_multiplicity = re.split(r":+", information) - assert len(element_multiplicity) == 2, \ - "Element multiplicity is incorrectly formatted!" + if len(element_multiplicity) != 2: + raise ValueError(f"Line {line}, element multiplicity is incorrectly formatted!") # skip vol, name, and color information if element_multiplicity[0].lower() == "name": info["name"] = f"{element_multiplicity[1]}" @@ -81,35 +78,33 @@ def evaluate_rrng_range_line(i: int, line: str) -> dict: elif element_multiplicity[0].lower() not in ["vol", "color"]: # pick up what is an element name symbol = element_multiplicity[0] - assert (symbol in chemical_symbols) and (symbol != "X"), \ - f"Line {line} contains an invalid chemical symbol!" - assert np.uint32(element_multiplicity[1]) > 0, \ - f"Line {line} zero or negative multiplicity!" - assert np.uint32(element_multiplicity[1]) < 256, \ - f"Line {line} unsupported high multiplicity!" - info["atoms"] = np.append( - info["atoms"], [symbol] * int(element_multiplicity[1])) + if (symbol not in chemical_symbols) or (symbol == "X"): + raise ValueError(f"Line {line} contains an invalid chemical symbol!") + if np.uint32(element_multiplicity[1]) <= 0: + raise ValueError(f"Line {line} zero or negative multiplicity!") + if np.uint32(element_multiplicity[1]) >= 256: + raise ValueError(f"Line {line} unsupported high multiplicity!") + info["atoms"] = np.append(info["atoms"], [symbol] * int(element_multiplicity[1])) return info class ReadRrngFileFormat(): """Read *.rrng file format.""" - def __init__(self, filename: str): + def __init__(self, file_path: str): """Initialize the class.""" - if (len(filename) <= 5) or (filename.lower().endswith(".rrng") is False): - raise ImportError("WARNING::RRNG file incorrect filename ending or file type!") - self.filename = filename - self.rrng: dict = {} - self.rrng["ionnames"] = [] - self.rrng["ranges"] = {} - self.rrng["ions"] = {} - self.rrng["molecular_ions"] = [] + if (len(file_path) <= 5) or (file_path.lower().endswith(".rrng") is False): + raise ImportError("WARNING::RRNG file incorrect file_path ending or file type!") + self.file_path = file_path + self.rrng: dict = {"ionnames": [], + "ranges": {}, + "ions": {}, + "molecular_ions": []} self.read_rrng() def read_rrng(self): """Read content of an RRNG range file.""" - with open(self.filename, mode="r", encoding="utf8") as rrngf: + with open(self.file_path, mode="r", encoding="utf8") as rrngf: txt = rrngf.read() txt = txt.replace("\r\n", "\n") # windows to unix EOL conversion @@ -128,70 +123,66 @@ def read_rrng(self): # with isotope_vector np.iinfo(np.uint16).max where = [idx for idx, element in enumerate(txt_stripped) if element == "[Ions]"] - assert isinstance(where, list), "Section [Ions] not found!" - assert len(where) == 1, "Section [Ions] not found or ambiguous!" + if isinstance(where, list) is False: + raise ValueError("Section [Ions] not found!") + if len(where) != 1: + raise ValueError("Section [Ions] not found or ambiguous!") current_line_id = where[0] + 1 tmp = re.split(r"[\s=]+", txt_stripped[current_line_id]) - assert len(tmp) == 2, "[Ions]/Number line corrupted!" - assert tmp[0] == "Number", "[Ions]/Number incorrectly formatted!" - assert tmp[1].isnumeric(), "[Ions]/Number not a number!" + if len(tmp) != 2: + raise ValueError(f"Line {txt_stripped[current_line_id]} [Ions]/Number line corrupted!") + if tmp[0] != "Number": + raise ValueError(f"Line {txt_stripped[current_line_id]} [Ions]/Number incorrectly formatted!") + if tmp[1].isnumeric() is False: + raise ValueError(f"Line {txt_stripped[current_line_id]} [Ions]/Number not a number!") number_of_ion_names = int(tmp[1]) - assert number_of_ion_names > 0, "No ion names defined!" + if number_of_ion_names <= 0: + raise ValueError(f"Line {txt_stripped[current_line_id]} no ion names defined!") current_line_id += 1 for i in np.arange(0, number_of_ion_names): tmp = re.split(r"[\s=]+", txt_stripped[current_line_id + i]) - assert len(tmp) == 2, "[Ions]/Ion line corrupted!" - assert tmp[0] == f"Ion{i + 1}", "[Ions]/Ion incorrectly formatted!" - assert isinstance(tmp[1], str), "[Ions]/Name not a string!" + if len(tmp) == 2: + raise ValueError(f"Line {txt_stripped[current_line_id + i]} [Ions]/Ion line corrupted!") + if tmp[0] != f"Ion{i + 1}": + raise ValueError(f"Line {txt_stripped[current_line_id + i]} [Ions]/Ion incorrectly formatted!") + if isinstance(tmp[1], str) is False: + raise ValueError(f"Line {txt_stripped[current_line_id + i]} [Ions]/Name not a string!") self.rrng["ionnames"].append(tmp[1]) # second, parse [Ranges] section where = [idx for idx, element in enumerate(txt_stripped) if element == "[Ranges]"] - assert isinstance(where, list), "Section [Ranges] not found!" - assert len(where) == 1, "Section [Ranges] not found or ambiguous!" + if isinstance(where, list) is False: + raise ValueError("Section [Ranges] not found!") + if len(where) != 1: + raise ValueError("Section [Ranges] not found or ambiguous!") current_line_id = where[0] + 1 tmp = re.split(r"[\s=]+", txt_stripped[current_line_id]) - assert len(tmp) == 2, "[Ranges]/Number line corrupted!" - assert tmp[0] == "Number", "[Ranges]/Number incorrectly formatted!" - assert tmp[1].isnumeric(), "[Ranges]/Number not a number!" + if len(tmp) != 2: + raise ValueError(f"Line {txt_stripped[current_line_id]} [Ranges]/Number line corrupted!") + if tmp[0] != "Number": + raise ValueError(f"Line {txt_stripped[current_line_id]} [Ranges]/Number incorrectly formatted!") + if tmp[1].isnumeric() is False: + raise ValueError(f"Line {txt_stripped[current_line_id]} [Ranges]/Number not a number!") number_of_ranges = int(tmp[1]) - assert number_of_ranges > 0, "No ranges defined!" + if number_of_ranges <= 0: + raise ValueError(f"Line {txt_stripped[current_line_id]} No ranges defined!") current_line_id += 1 - for i in np.arange(0, number_of_ranges): - dct = evaluate_rrng_range_line(i + 1, txt_stripped[current_line_id + i]) - assert dct, f"Line {txt_stripped[current_line_id + i]} is corrupted!" + for jdx in np.arange(0, number_of_ranges): + dct = evaluate_rrng_range_line(jdx + 1, txt_stripped[current_line_id + jdx]) + if dct is None: + print(f"WARNING::RNG line {txt_stripped[current_line_id + jdx]} is corrupted!") + continue m_ion = NxIon(isotope_vector=create_isotope_vector( dct["atoms"]), charge_state=0) m_ion.add_range(dct["range"][0], dct["range"][1]) m_ion.comment = NxField(dct["name"], "") - m_ion.color = NxField(dct["color"], "") - m_ion.volume = NxField(dct["volume"], "") + apply_combinatorics(m_ion) # m_ion.report() - crawler = MolecularIonBuilder( - min_abundance=PRACTICAL_ABUNDANCE, - min_abundance_product=PRACTICAL_ABUNDANCE_PRODUCT, - min_half_life=PRACTICAL_MIN_HALF_LIFE, - sacrifice_uniqueness=SACRIFICE_ISOTOPIC_UNIQUENESS, - verbose=VERBOSE) - recovered_charge_state, m_ion_candidates = crawler.combinatorics( - m_ion.isotope_vector.typed_value, - m_ion.ranges.typed_value[0, 0], - m_ion.ranges.typed_value[0, 1]) - # print(f"{recovered_charge_state}") - m_ion.charge_state = NxField(np.int8(recovered_charge_state), "") - m_ion.update_human_readable_name() - m_ion.add_charge_state_model( - {"min_abundance": PRACTICAL_ABUNDANCE, - "min_abundance_product": PRACTICAL_ABUNDANCE_PRODUCT, - "min_half_life": PRACTICAL_MIN_HALF_LIFE, - "sacrifice_isotopic_uniqueness": SACRIFICE_ISOTOPIC_UNIQUENESS}, - m_ion_candidates) - self.rrng["molecular_ions"].append(m_ion) - print(self.filename + " parsed successfully") + print(f"{self.file_path} parsed successfully") diff --git a/ifes_apt_tc_data_modeling/utils/combinatorics.py b/ifes_apt_tc_data_modeling/utils/combinatorics.py new file mode 100644 index 0000000..d030fdf --- /dev/null +++ b/ifes_apt_tc_data_modeling/utils/combinatorics.py @@ -0,0 +1,50 @@ +# +# 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. +# + +"""Function implementing combinatorial analysis for all ranging definitions.""" + +# shared functionality used for RNG/RRNG/ENV + +import numpy as np + +from ifes_apt_tc_data_modeling.nexus.nx_ion import NxField, NxIon +from ifes_apt_tc_data_modeling.utils.molecular_ions import \ + MolecularIonBuilder, PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ + PRACTICAL_MIN_HALF_LIFE, VERBOSE, SACRIFICE_ISOTOPIC_UNIQUENESS + + +def apply_combinatorics(m_ion: NxIon): + """Apply specifically constrainted combinatorial analysis.""" + crawler = MolecularIonBuilder(min_abundance=PRACTICAL_ABUNDANCE, + min_abundance_product=PRACTICAL_ABUNDANCE_PRODUCT, + min_half_life=PRACTICAL_MIN_HALF_LIFE, + sacrifice_uniqueness=SACRIFICE_ISOTOPIC_UNIQUENESS, + verbose=VERBOSE) + recovered_charge_state, m_ion_candidates \ + = crawler.combinatorics(m_ion.isotope_vector.values, + m_ion.ranges.values[0, 0], + m_ion.ranges.values[0, 1]) + # print(f"{recovered_charge_state}") + m_ion.charge_state = NxField(np.int8(recovered_charge_state), "") + m_ion.update_human_readable_name() + m_ion.add_charge_state_model({"min_abundance": PRACTICAL_ABUNDANCE, + "min_abundance_product": PRACTICAL_ABUNDANCE_PRODUCT, + "min_half_life": PRACTICAL_MIN_HALF_LIFE, + "sacrifice_isotopic_uniqueness": SACRIFICE_ISOTOPIC_UNIQUENESS}, + m_ion_candidates) + return m_ion diff --git a/ifes_apt_tc_data_modeling/utils/utils.py b/ifes_apt_tc_data_modeling/utils/utils.py index fdaeef6..0d968ca 100644 --- a/ifes_apt_tc_data_modeling/utils/utils.py +++ b/ifes_apt_tc_data_modeling/utils/utils.py @@ -31,6 +31,18 @@ MAX_NUMBER_OF_ATOMS_PER_ION, MQ_EPSILON +def get_smart_chemical_symbols(): + """Organize element symbols such that search H does not match He.""" + priority_queue = [] + for symbol in chemical_symbols: + if len(symbol) == 2: + priority_queue.append(symbol) + for symbol in chemical_symbols: + if symbol != "X" and len(symbol) == 1: + priority_queue.append(symbol) + return priority_queue + + def isotope_to_hash(proton_number: int = 0, neutron_number: int = 0) -> int: """Encode an isotope to a hashvalue.""" diff --git a/tests/TestsForDevelopers.ipynb b/tests/TestsForDevelopers.ipynb index 70af70c..656e357 100644 --- a/tests/TestsForDevelopers.ipynb +++ b/tests/TestsForDevelopers.ipynb @@ -68,46 +68,46 @@ " trg = f\"/entry1/ion{idx}\"\n", " grp = fpw.create_group(trg)\n", " grp.attrs[\"NX_class\"] = \"NXion\"\n", - " dst = fpw.create_dataset(f\"{trg}/comment\", data=ion.comment.typed_value)\n", - " dst = fpw.create_dataset(f\"{trg}/color\", data=ion.color.typed_value)\n", + " dst = fpw.create_dataset(f\"{trg}/comment\", data=mion.comment.values)\n", + " dst = fpw.create_dataset(f\"{trg}/color\", data=mion.color.values)\n", " # dst = fpw.create_dataset(f\"{trg}/volume\", dtype=np.float32, data=0.)\n", " # dst.attrs[\"unit\"] = \"nm^3\"\n", " dst = fpw.create_dataset(f\"{trg}/isotope_vector\", dtype=np.uint16,\n", - " data=ion.isotope_vector.typed_value, \n", + " data=mion.isotope_vector.values, \n", " chunks=True, compression=\"gzip\", compression_opts=1)\n", " dst = fpw.create_dataset(f\"{trg}/nuclid_list\", dtype=np.uint16,\n", - " data=ion.nuclid_list.typed_value,\n", + " data=mion.nuclid_list.values,\n", " chunks=True, compression=\"gzip\", compression_opts=1)\n", " dst = fpw.create_dataset(f\"{trg}/charge_state\", dtype=np.int8,\n", - " data=ion.charge_state.typed_value)\n", - " dst = fpw.create_dataset(f\"{trg}/name\", data=ion.name.typed_value)\n", + " data=mion.charge_state.values)\n", + " dst = fpw.create_dataset(f\"{trg}/name\", data=mion.name.values)\n", " dst = fpw.create_dataset(trg+ \"/mass_to_charge_range\", dtype=np.float32,\n", - " data=ion.ranges.typed_value)\n", + " data=mion.ranges.values)\n", " dst.attrs[\"unit\"] = \"Da\"\n", " subgrpnm = f\"{trg}/charge_state_model\"\n", " subgrp = fpw.create_group(subgrpnm)\n", " subgrp.attrs[\"NX_class\"] = \"NXprocess\"\n", " dst = fpw.create_dataset(f\"{subgrpnm}/min_abundance\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_abundance\"])\n", + " data=mion.charge_state_model[\"min_abundance\"])\n", " dst = fpw.create_dataset(f\"{subgrpnm}/min_abundance_product\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_abundance_product\"])\n", + " data=mion.charge_state_model[\"min_abundance_product\"])\n", " dst = fpw.create_dataset(f\"{subgrpnm}/min_half_life\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_half_life\"])\n", + " data=mion.charge_state_model[\"min_half_life\"])\n", " dst.attrs[\"unit\"] = \"s\"\n", " dst = fpw.create_dataset(f\"{subgrpnm}/sacrifice_isotopic_uniqueness\", dtype=np.uint8,\n", - " data=ion.charge_state_model[\"sacrifice_isotopic_uniqueness\"])\n", + " data=mion.charge_state_model[\"sacrifice_isotopic_uniqueness\"])\n", " dst = fpw.create_dataset(f\"{subgrpnm}/isotope_matrix\", dtype=np.uint16,\n", - " data=ion.charge_state_model[\"isotope_matrix\"],\n", + " data=mion.charge_state_model[\"isotope_matrix\"],\n", " chunks=True, compression=\"gzip\", compression_opts=1)\n", " dst = fpw.create_dataset(f\"{subgrpnm}/charge_state_vector\", dtype=np.int8,\n", - " data=ion.charge_state_model[\"charge_state_vector\"])\n", + " data=mion.charge_state_model[\"charge_state_vector\"])\n", " dst = fpw.create_dataset(f\"{subgrpnm}/mass_vector\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"mass_vector\"])\n", + " data=mion.charge_state_model[\"mass_vector\"])\n", " dst.attrs[\"unit\"] = \"Da\"\n", " dst = fpw.create_dataset(f\"{subgrpnm}/nat_abun_prod_vector\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"nat_abun_prod_vector\"])\n", + " data=mion.charge_state_model[\"nat_abun_prod_vector\"])\n", " dst = fpw.create_dataset(f\"{subgrpnm}/min_half_life_vector\", dtype=np.float64,\n", - " data=ion.charge_state_model[\"min_half_life_vector\"])\n", + " data=mion.charge_state_model[\"min_half_life_vector\"])\n", " dst.attrs[\"unit\"] = \"s\"" ] }, @@ -147,12 +147,12 @@ "source": [ "from ifes_apt_tc_data_modeling.csv.csv_reader import ReadCsvFileFormat\n", "csv = ReadCsvFileFormat(f\"{prefix}/{fnm[0]}\")\n", - "print(csv.filename)\n", + "print(csv.file_path)\n", "print(csv.filesize)\n", "xyz = csv.get_reconstructed_positions()\n", - "print(np.shape(xyz.typed_value))\n", + "print(np.shape(xyz.values))\n", "mq = csv.get_mass_to_charge_state_ratio()\n", - "print(np.shape(mq.typed_value))" + "print(np.shape(mq.values))" ] }, { @@ -256,9 +256,9 @@ "# the calibrations (voltage, bowl, m/q, comparable to LEAP's ROOT and POS/EPOS)\n", "pyc_c = ReadPyccaptCalibrationFileFormat(f\"{prefix}/{fnm[1]}\")\n", "xyz = pyc_c.get_reconstructed_positions()\n", - "print(xyz.typed_value)\n", + "print(xyz.values)\n", "m_q = pyc_c.get_mass_to_charge_state_ratio()\n", - "print(m_q.typed_value)\n", + "print(m_q.values)\n", "\n", "# the ranging definitions (comparable to RNG/RRNG)\n", "pyc_r = ReadPyccaptRangingFileFormat(f\"{prefix}/{fnm[2]}\")" @@ -310,9 +310,9 @@ " ato = ReadAtoFileFormat(f\"{prefix}/{fpath}\")\n", " \n", " xyz = ato.get_reconstructed_positions()\n", - " print(xyz.typed_value)\n", + " print(xyz.values)\n", " m_q = ato.get_mass_to_charge_state_ratio()\n", - " print(m_q.typed_value)" + " print(m_q.values)" ] }, { @@ -499,7 +499,7 @@ " if fpath.lower().endswith(\".rng\"):\n", " print(fpath)\n", " rng = ReadRngFileFormat(f\"{prefix}/{fpath}\")\n", - " with h5py.File(f\"{directory}/{filename}.nxs\", \"w\") as h5w:\n", + " with h5py.File(f\"{prefix}/{fpath}.nxs\", \"w\") as h5w:\n", " h5w.create_group(\"/entry\")\n", " idx = 1\n", " for ion in rng.rng[\"molecular_ions\"]:\n", @@ -557,12 +557,12 @@ "source": [ "for fpath in fnm:\n", " pos = ReadPosFileFormat(f\"{prefix}/{fpath}\")\n", - " print(pos.filename)\n", + " print(pos.file_path)\n", " print(pos.filesize)\n", " xyz = pos.get_reconstructed_positions()\n", - " print(np.shape(xyz.typed_value))\n", + " print(np.shape(xyz.values))\n", " mq = pos.get_mass_to_charge_state_ratio()\n", - " print(np.shape(mq.typed_value))" + " print(np.shape(mq.values))" ] }, { @@ -605,24 +605,24 @@ "source": [ "for fpath in fnm:\n", " epos = ReadEposFileFormat(f\"{prefix}/{fpath}\")\n", - " print(epos.filename)\n", - " print(epos.filesize)\n", + " print(epos.file_path)\n", + " print(epos.file_size)\n", " xyz = epos.get_reconstructed_positions()\n", - " print(np.shape(xyz.typed_value))\n", + " print(np.shape(xyz.values))\n", " mq = epos.get_mass_to_charge_state_ratio()\n", - " print(np.shape(mq.typed_value))\n", + " print(np.shape(mq.values))\n", " raw_tof = epos.get_raw_time_of_flight()\n", - " print(np.shape(raw_tof.typed_value))\n", + " print(np.shape(raw_tof.values))\n", " st_v = epos.get_standing_voltage()\n", - " print(np.shape(st_v.typed_value))\n", + " print(np.shape(st_v.values))\n", " p_v = epos.get_pulse_voltage()\n", - " print(np.shape(p_v.typed_value))\n", + " print(np.shape(p_v.values))\n", " det_xy = epos.get_hit_positions()\n", - " print(np.shape(det_xy.typed_value))\n", + " print(np.shape(det_xy.values))\n", " n_p = epos.get_number_of_pulses()\n", - " print(np.shape(n_p.typed_value))\n", + " print(np.shape(n_p.values))\n", " h_p = epos.get_ions_per_pulse()\n", - " print(np.shape(h_p.typed_value))" + " print(np.shape(h_p.values))" ] }, { @@ -667,9 +667,9 @@ " apt = ReadAptFileFormat(f\"{prefix}/{fpath}\")\n", " print(apt.get_metadata_table())\n", " xyz = apt.get_reconstructed_positions()\n", - " print(np.shape(xyz.typed_value))\n", + " print(np.shape(xyz.values))\n", " mq = apt.get_mass_to_charge_state_ratio()\n", - " print(np.shape(mq.typed_value))" + " print(np.shape(mq.values))" ] }, { @@ -752,9 +752,9 @@ " sacrifice_uniqueness=True,\n", " verbose=True)\n", "mion.combinatorics(\n", - " ion.isotope_vector.typed_value,\n", - " ion.ranges.typed_value[0, 0],\n", - " ion.ranges.typed_value[0, 1])" + " ion.isotope_vector.values,\n", + " ion.ranges.values[0, 0],\n", + " ion.ranges.values[0, 1])" ] }, { From ad0a9dfa56dfa50502826379bf8723219404666e Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Sat, 30 Dec 2023 21:39:12 +0100 Subject: [PATCH 12/20] More linting and styling pyccapt and apt, only apt6_reader remains --- ifes_apt_tc_data_modeling/apt/apt6_headers.py | 51 +- .../apt/apt6_sections.py | 384 ++--- .../apt/apt6_sections_branches.py | 1268 ++++++++--------- ifes_apt_tc_data_modeling/apt/apt6_utils.py | 3 + .../pyccapt/pyccapt_reader.py | 124 +- 5 files changed, 919 insertions(+), 911 deletions(-) diff --git a/ifes_apt_tc_data_modeling/apt/apt6_headers.py b/ifes_apt_tc_data_modeling/apt/apt6_headers.py index 7597e84..e964002 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_headers.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_headers.py @@ -31,13 +31,13 @@ class AptFileHeaderMetadata(): # when developing the parser for their vendor file format def __init__(self): # file format signature - self.c_signature = string_to_typed_nparray('APT\0', 4, np.uint8) + self.c_signature = string_to_typed_nparray("APT\0", 4, np.uint8) # byte length of the file header self.i_header_size = np.int32(540) # version number of the file header, currently expecting 2 self.i_header_version = np.int32(2) # original filename, i.e. *.apt filename, null-terminated UTF-16 ! - self.wc_filename = string_to_typed_nparray('', 256, np.uint16) + self.wc_filename = string_to_typed_nparray("", 256, np.uint16) # file creation time # according to AMETEK is implemented as a VisualStudio C++ FILETIME # 64-bit value, which represents the number of 100-nanosecond intervals @@ -49,39 +49,34 @@ def __init__(self): @classmethod def get_numpy_struct(cls) -> np.dtype: """Create customized numpy struct to read a file header at once.""" - return np.dtype([('cSignature', np.uint8, (4,)), - ('iHeaderSize', np.int32), - ('iHeaderVersion', np.int32), - ('wcFilename', np.uint16, 256), - ('ftCreationTime', np.uint64), - ('llIonCount', np.uint64)]) + return np.dtype([("cSignature", np.uint8, (4,)), + ("iHeaderSize", np.int32), + ("iHeaderVersion", np.int32), + ("wcFilename", np.uint16, 256), + ("ftCreationTime", np.uint64), + ("llIonCount", np.uint64)]) def set_ll_ion_count(self, value: np.uint64): """Check and set total ion count.""" - assert isinstance(value, np.uint64), \ - 'llIonCount needs to be an int!' - assert value > 0, \ - 'llIonCount needs to be positive and not zero!' - assert value <= np.iinfo(np.uint64).max, \ - 'llIonCount is too large, needs to map to np.uint64!' + if isinstance(value, np.uint64) is False: + raise ValueError(f"llIonCount {value} needs to be an uint64!") + if value <= 0: + raise ValueError(f"llIonCount {value} needs to be positive and not zero!") + if value > np.iinfo(np.uint64).max: + raise ValueError(f"llIonCount is too large {value}, needs to map to np.uint64!") self.ll_ion_count = np.uint64(value) def matches(self, found_header: np.ndarray) -> bool: """Compare a read header against expectation.""" - assert np.array_equal(self.c_signature, - found_header['cSignature'][0], - equal_nan=True), \ - 'Header cSignature differs!' - assert self.i_header_size \ - == found_header['iHeaderSize'][0], \ - 'Header iHeaderSize differs!' - assert self.i_header_version \ - == found_header['iHeaderVersion'][0], \ - 'Header iHeaderVersion differs!' - assert found_header['llIonCount'][0] > 0, \ - 'Header indicates there are no ions in the file!' - - self.set_ll_ion_count(found_header['llIonCount'][0]) + if np.array_equal(self.c_signature, found_header["cSignature"][0], equal_nan=True) is False: + raise ValueError("Header cSignature differs!") + if self.i_header_size != found_header["iHeaderSize"][0]: + raise ValueError("Header iHeaderSize differs!") + if self.i_header_version != found_header["iHeaderVersion"][0]: + raise ValueError("Header iHeaderVersion differs!") + if found_header["llIonCount"][0] <= 0: + raise ValueError("Header indicates there are no ions in the file!") + self.set_ll_ion_count(found_header["llIonCount"][0]) return True diff --git a/ifes_apt_tc_data_modeling/apt/apt6_sections.py b/ifes_apt_tc_data_modeling/apt/apt6_sections.py index 5db039f..74a4d09 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_sections.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_sections.py @@ -21,7 +21,8 @@ import numpy as np from ifes_apt_tc_data_modeling.apt.apt6_utils import \ - np_uint16_to_string, string_to_typed_nparray + np_uint16_to_string, string_to_typed_nparray, \ + APT_SECTION_NAME_MAX_LENGTH, APT_SECTION_TYPE_MAX_LENGTH class AptFileSectionMetadata(): @@ -30,30 +31,30 @@ class AptFileSectionMetadata(): def __init__(self): # resolved name of the section self.meta = {} - self.meta['section_name'] = '' + self.meta["section_name"] = "" # section format signature # or is the c_signature really uint16 ? - self.meta['c_signature'] = string_to_typed_nparray('SEC\0', 4, np.uint8) + self.meta["c_signature"] = string_to_typed_nparray("SEC\0", 4, np.uint8) # byte length of the section header - self.meta['i_header_size'] = np.int32(0) + self.meta["i_header_size"] = np.int32(0) # version number of the section header - self.meta['i_header_version'] = np.int32(0) + self.meta["i_header_version"] = np.int32(0) # string header/title representation of info content in the section - self.meta['wc_section_type'] = string_to_typed_nparray('', 32, np.uint16) + self.meta["wc_section_type"] = string_to_typed_nparray("", 32, np.uint16) # version of this section data - self.meta['i_section_version'] = np.int32(0) + self.meta["i_section_version"] = np.int32(0) # enum value specifying how the records relate to ion # 0 (unknown) # 1 (one-to-one mapping) # 2 (sparse 64bit ion index as first element) # 3 (unrelated) # 4 (first element is # of indices, then a list, then the record itself - self.meta['e_relationship_type'] = np.uint32(0) + self.meta["e_relationship_type"] = np.uint32(0) # enum value specifying type of record # 0 (unknown) # 1 (variable size) # 2 (variable indexed) - self.meta['e_record_type'] = np.uint32(0) + self.meta["e_record_type"] = np.uint32(0) # enum value specifying data type of records # 0 (unknown) # 1 (int, iDataTypeSize 8, 16, 32, or 64) @@ -63,22 +64,22 @@ def __init__(self): # iRecordSize of 0 is null terminated # iRecordSize > 0 is fixed length # 5 (other)) - self.meta['e_record_data_type'] = np.uint32(0) + self.meta["e_record_data_type"] = np.uint32(0) # size in bits of data type - self.meta['i_data_type_size'] = np.int32(0) + self.meta["i_data_type_size"] = np.int32(0) # size of the record (bytes) # this must be a multiple of iDataTypeSize/8 # or 0 for variable length - self.meta['i_record_size'] = np.int32(0) + self.meta["i_record_size"] = np.int32(0) # string representation the unit of the data - self.meta['wc_data_unit'] = string_to_typed_nparray('', 16, np.uint16) - self.accepted_units = [''] + self.meta["wc_data_unit"] = string_to_typed_nparray("", 16, np.uint16) + self.accepted_units = [""] # number of records following this header # do not use for seeking to next section, use llByteCount instead! - self.meta['ll_record_count'] = np.int64(0) + self.meta["ll_record_count"] = np.int64(0) # number of bytes following the header # this may be > llRecordCount * iRecordSize to allow for padding! - self.meta['ll_byte_count'] = np.int64(0) + self.meta["ll_byte_count"] = np.int64(0) # we define setters here to implement type checks and thereby # remove type and consistency checks out of the main code @@ -88,131 +89,137 @@ def __init__(self): def set_section_name(self, value: str): """Check and set section name.""" - assert isinstance(value, str), 'SectionName must be a string!' - assert value != '', 'SectionName must not be an empty string!' - assert len(value) <= 32, \ - 'SectionName must not contain more than 32 characters!' + if isinstance(value, str) is False: + raise ValueError(f"SectionName {value} must be a string!") + if value == "": + raise ValueError(f"SectionName {value} must not be an empty string!") + if len(value) > APT_SECTION_NAME_MAX_LENGTH: + raise ValueError(f"SectionName {value} must not contain more than " + f"{APT_SECTION_NAME_MAX_LENGTH} characters!") # SectionName is not null-terminated! - self.meta['section_name'] = value + self.meta["section_name"] = value def set_c_signature(self): """Check and set c_signature.""" # assert isinstance(value, str), \ - # 'cSignature needs to be a string!' - # assert value is not '', \ - # 'cSignature must not be an empty string!' + # "cSignature needs to be a string!" + # assert value is not "", \ + # "cSignature must not be an empty string!" # assert len(value) <= 4, \ - # 'cSignature must not contain more than 4 characters!' - # assert value[-1] == '\0', \ - # 'cSignature needs to include the null-terminator! - # assert value == 'SEC\0', \ - # 'cSignature must be SEC\0 which is a string!' - # so far all example file indicated AMETEK implemented 'SEC\0' hard - self.meta['c_signature'] = string_to_typed_nparray('SEC\0', 4, np.uint8) + # "cSignature must not contain more than 4 characters!" + # assert value[-1] == "\0", \ + # "cSignature needs to include the null-terminator! + # assert value == "SEC\0", \ + # "cSignature must be SEC\0 which is a string!" + # so far all example file indicated AMETEK implemented "SEC\0" hard + self.meta["c_signature"] = string_to_typed_nparray("SEC\0", 4, np.uint8) def set_i_header_size(self, value: int): """Check and set i_header_size.""" - # assert isinstance(value, int), \ - # 'iHeaderSize needs to be an int!' - assert value >= 0, \ - 'iHeaderSize needs to be positive or zero!' - assert value <= np.iinfo(np.int32).max, \ - 'iHeaderSize too large, needs to map to np.int32!' - self.meta['i_header_size'] = np.int32(value) + if isinstance(value, int) is False: + raise ValueError(f"iHeaderSize {value} needs to be an int!") + if value < 0: + raise ValueError(f"iHeaderSize {value} needs to be positive or zero!") + if value > np.iinfo(np.int32).max: + raise ValueError(f"iHeaderSize too large {value}, needs to map to np.int32!") + self.meta["i_header_size"] = np.int32(value) def set_i_header_version(self, value: int): """Check and size i_header_version.""" - # assert isinstance(value, int), \ - # 'iHeaderVersion needs to be an int!' - assert value >= 0, \ - 'iHeaderVersion needs to be positive or zero!' - assert value <= np.iinfo(np.int32).max, \ - 'iHeaderVersion too large, needs to map to np.int32!' - self.meta['i_header_version'] = np.int32(value) + if isinstance(value, int) is False: + raise ValueError(f"iHeaderVersion {value} needs to be an int!") + if value < 0: + raise ValueError(f"iHeaderVersion {value} needs to be positive or zero!") + if value > np.iinfo(np.int32).max: + raise ValueError(f"iHeaderVersion too large {value}, needs to map to np.int32!") + self.meta["i_header_version"] = np.int32(value) def set_wc_section_type(self, value: str): """Check and set wc_section_type.""" - assert isinstance(value, str), \ - 'wcSectionType needs to be a string!' - assert value != '', \ - 'cSignature must not be an empty string!' - assert len(value) <= 32, \ - 'wcSectionType string must not contain more than 32 characters!' - # assert value[-1] == '\0', \ - # 'wcSectionType needs to include the null-terminator!' - self.meta['wc_section_type'] = string_to_typed_nparray(value, 32, np.uint16) + if isinstance(value, str) is False: + raise ValueError(f"wcSectionType {value} needs to be a string!") + if value == "": + raise ValueError(f"wcSectionType {value} must not be an empty string!") + if len(value) > APT_SECTION_TYPE_MAX_LENGTH: + raise ValueError(f"wcSectionType string {value} must not contain more than 32 characters!") + # if value[-1] != "\0": + # raise ValueError(f"wcSectionType needs to include the null-terminator!") + self.meta["wc_section_type"] = string_to_typed_nparray(value, 32, np.uint16) def set_i_section_version(self, value: int): """Check and set i_section_version.""" - # assert isinstance(value, int), \ - # 'iSectionVersion needs to be an int!' - assert value >= 0, \ - 'iSectionVersion needs to be positive or zero!' - assert value <= np.iinfo(np.int32).max, \ - 'iiSectionVersion too large, needs to map to np.int32!' - self.meta['i_section_version'] = np.int32(value) + if isinstance(value, int) is False: + raise ValueError(f"iSectionVersion {value} needs to be an int!") + if value < 0: + raise ValueError(f"iSectionVersion {value} needs to be positive or zero!") + if value > np.iinfo(np.int32).max: + raise ValueError(f"iSectionVersion too large {value}, needs to map to np.int32!") + self.meta["i_section_version"] = np.int32(value) def set_e_relationship_type(self, value: int): """Check and set e_relationship_type.""" - # assert isinstance(value, int), \ - # 'eRelationShipType needs to be an int!' - assert value in [0, 1, 2, 3, 4], \ - 'eRelationShipType needs to be from [0, 1, 2, 3, 4]!' - assert value == 1, \ - 'eRelationShipType cannot process 2, 3, and 4, lacking examples!' - self.meta['e_relationship_type'] = np.uint32(value) + if isinstance(value, int) is False: + raise ValueError(f"eRelationShipType {value} needs to be an int!") + if value not in [0, 1, 2, 3, 4]: + raise ValueError(f"eRelationShipType {value} needs to be from [0, 1, 2, 3, 4]!") + if value != 1: + raise ValueError(f"eRelationShipType {value}, this reader cannot process " + f"2, 3, 4 because of lacking examples!") + self.meta["e_relationship_type"] = np.uint32(value) def set_e_record_type(self, value: int): """Check and set e_record_type.""" - # assert isinstance(value, int), \ - # 'eRecordType needs to be an int!' - assert value in [0, 1, 2], \ - 'eRecordType needs to be from [0, 1, 2]!' - # assert value != 1, \ - # 'eRecordType cannot process 2, 3, and 4, lacking examples!' - self.meta['e_record_type'] = np.uint32(value) + if isinstance(value, int) is False: + raise ValueError(f"eRecordType {value} needs to be an int!") + if value not in [0, 1, 2]: + raise ValueError(f"eRecordType {value} needs to be from [0, 1, 2]!") + if value != 1: + raise ValueError(f"eRecordType is {value}, is reader cannot " + f"process 2, 3, 4 because of lacking examples!") + self.meta["e_record_type"] = np.uint32(value) def set_e_record_data_type(self, value: int): """Check and set e_record_data_type.""" - # assert isinstance(value, int), \ - # 'e_record_data_type needs to be an int!' - assert value in [0, 1, 2, 3, 4, 5], \ - 'eRecordDataType needs to be from [0, 1, 2, 3, 4, 5]!' - assert value != 5, \ - 'eRecordDataType cannot process 5 due to lacking examples!' - self.meta['e_record_data_type'] = np.uint32(value) + if isinstance(value, int) is False: + raise ValueError(f"e_record_data_type {value} needs to be an int!") + if value not in [0, 1, 2, 3, 4, 5]: + raise ValueError(f"eRecordDataType {value} needs to be from [0, 1, 2, 3, 4, 5]!") + if value == 5: + raise ValueError(f"eRecordDataType is {value}, this reader cannot " + f"process 5 because of lacking examples!") + self.meta["e_record_data_type"] = np.uint32(value) def set_i_data_type_size(self, value: int): """Check and set i_data_type_size.""" - # assert isinstance(value, int), \ - # 'iDataTypeSize needs to be an int!' - assert value > 0, \ - 'iDataTypeSize needs to be positive and not zero!' - assert value <= np.iinfo(np.int32).max, \ - 'iDataTypeSize too large, needs to map to np.int32!' - self.meta['i_data_type_size'] = np.int32(value) + if isinstance(value, int) is False: + raise ValueError(f"iDataTypeSize {value} needs to be an int!") + if value <= 0: + raise ValueError(f"iDataTypeSize {value} needs to be positive and not zero!") + if value > np.iinfo(np.int32).max: + raise ValueError(f"iDataTypeSize too large {value}, needs to map to np.int32!") + self.meta["i_data_type_size"] = np.int32(value) def set_i_record_size(self, value: int): """Check and set i_record_size.""" - assert isinstance(value, int), \ - 'iDataTypeSize needs to be an int!' - assert value > 0, \ - 'iHeaderVersion needs to be positive and not zero!' - assert value <= np.iinfo(np.int32).max, \ - 'iHeaderVersion too large, needs to map to np.int32!' - self.meta['i_record_size'] = np.int32(value) + if isinstance(value, int) is False: + raise ValueError(f"iRecordSize {value} needs to be an int!") + if value <= 0: + raise ValueError(f"iRecordSize {value} needs to be positive and not zero!") + if value > np.iinfo(np.int32).max: + raise ValueError(f"iRecordSize too large {value}, needs to map to np.int32!") + self.meta["i_record_size"] = np.int32(value) def set_wc_data_unit(self, value: str): """Check and set wc_data_unit.""" - assert isinstance(value, str), \ - 'wcDataUnit needs to be a string!' + if isinstance(value, str) is False: + raise ValueError(f"wcDataUnit {value} to be a string!") # can be the empty string is NX_UNITLESS or NX_DIMENSIONLESS - assert len(value) <= 16, \ - 'wcDataUnit must not contain more than 16 characters!' - # assert value[-1] == '\0', \ - # 'wcDataUnit needs to include the null-terminator!' - # so far all example file indicated AMETEK implemented 'SEC\0' hard - self.meta['wc_data_unit'] = string_to_typed_nparray(value, 16, np.uint16) + if len(value) > 16: + raise ValueError(f"wcDataUnit {value} must not contain more than 16 characters!") + # assert value[-1] == "\0", \ + # "wcDataUnit needs to include the null-terminator!" + # so far all example file indicated AMETEK implemented "SEC\0" hard + self.meta["wc_data_unit"] = string_to_typed_nparray(value, 16, np.uint16) def set_accepted_units(self, value: list): """Set which unit strings are accepted.""" @@ -222,35 +229,35 @@ def set_accepted_units(self, value: list): @classmethod def get_numpy_struct(cls) -> np.dtype: """Create customized numpy struct to read a section header at once.""" - return np.dtype([('cSignature', np.uint8, (4,)), - ('iHeaderSize', np.int32), - ('iHeaderVersion', np.int32), - ('wcSectionType', np.uint16, 32), - ('iSectionVersion', np.int32), - ('eRelationshipType', np.uint32), - ('eRecordType', np.uint32), - ('eRecordDataType', np.uint32), - ('iDataTypeSize', np.int32), - ('iRecordSize', np.int32), - ('wcDataUnit', np.uint16, 16), - ('llRecordCount', np.uint64), - ('llByteCount', np.uint64)]) + return np.dtype([("cSignature", np.uint8, (4,)), + ("iHeaderSize", np.int32), + ("iHeaderVersion", np.int32), + ("wcSectionType", np.uint16, 32), + ("iSectionVersion", np.int32), + ("eRelationshipType", np.uint32), + ("eRecordType", np.uint32), + ("eRecordDataType", np.uint32), + ("iDataTypeSize", np.int32), + ("iRecordSize", np.int32), + ("wcDataUnit", np.uint16, 16), + ("llRecordCount", np.uint64), + ("llByteCount", np.uint64)]) def get_ametek_size(self) -> np.uint64: """Compute how many byte raw data in bytes to read from AMETEK defs.""" - return np.uint64(self.meta['ll_byte_count']) + return np.uint64(self.meta["ll_byte_count"]) def get_ametek_type(self) -> str: """Interpret numpy endianess/datatype from AMETEK defs.""" - byte_length = self.meta['i_data_type_size'] / 8 - assert self.meta['e_record_data_type'] in [1, 2, 3], 'Section ' \ - + np_uint16_to_string(self.meta['wc_section_type']) \ - + ' get_ametek_type() unsupported e_record_data_type!' + byte_length = self.meta["i_data_type_size"] / 8 + if self.meta["e_record_data_type"] not in [1, 2, 3]: + raise ValueError(f"Section {np_uint16_to_string(self.meta['wc_section_type'])}" + f" get_ametek_type() unsupported e_record_data_type!") if self.meta['e_record_data_type'] == 1: integer_dtypes = {2: ' str: # 'Section ' + np_uint16_to_string(self.meta['wc_section_type']) \ # + ' get_ametek_type() detected \ # unsupported unsigned integer type!' - assert byte_length == 2, 'Section ' \ - + np_uint16_to_string(self.meta['wc_section_type']) \ - + ' get_ametek_type() detected unsupported uint type!' + if byte_length != 2: + raise ValueError(f"Section {np_uint16_to_string(self.meta['wc_section_type'])}" + f" get_ametek_type() detected unsupported uint type!") # return uinteger_dtypes[byte_length] - return ' np.uint64: @@ -280,8 +287,8 @@ def get_ametek_count(self) -> np.uint64: # this works only for one-to-one mapping ! # AMETEK has not communicated if the designed adaptive storage layout # for *.apt files has ever been implemented - return self.meta['ll_record_count'] \ - * np.uint64(self.meta['i_record_size'] / (self.meta['i_data_type_size'] / 8)) + return self.meta["ll_record_count"] \ + * np.uint64(self.meta["i_record_size"] / (self.meta["i_data_type_size"] / 8)) def get_ametek_shape(self) -> list: """Interpret final numpy shape to use from AMETEK defs.""" @@ -289,75 +296,74 @@ def get_ametek_shape(self) -> list: # AMETEK has not communicated if the designed adaptive storage layout # for *.apt files has ever been implemented return [ - np.uint64(self.meta['ll_record_count']), - np.uint64(np.uint64(self.meta['i_record_size']) / (self.meta['i_data_type_size'] / 8))] + np.uint64(self.meta["ll_record_count"]), + np.uint64(np.uint64(self.meta["i_record_size"]) / (self.meta["i_data_type_size"] / 8))] def matches(self, found_section: np.ndarray) -> bool: """Compare a read section against expected versioning.""" # check if the parsed section's metadata are matching # AMETEK expectations, i.e. meeting manufacturers definitions? - assert np.array_equal(self.meta['c_signature'], found_section['cSignature'][0], - equal_nan=True), \ - f"Section cSignature differs, is {np_uint16_to_string(found_section['cSignature'][0])}" \ - f" but should be {np_uint16_to_string(self.meta['c_signature'])}" - assert found_section['iHeaderSize'][0] == self.meta['i_header_size'], \ - f"Section iHeaderSize differs, is {found_section['iHeaderSize'][0]}" \ - f" but should be {self.meta['i_header_size']}" - assert found_section['iHeaderVersion'][0] == self.meta['i_header_version'], \ - f"Section iHeaderVersion differs, is {found_section['iHeaderVersion'][0]}" \ - f" but should be {self.meta['i_header_version']}" - assert found_section['iSectionVersion'][0] == self.meta['i_section_version'], \ - f"Section iSectionVersion differs, is {found_section['iSectionVersion'][0]}" \ - f" but should be {self.meta['i_section_version']}" - assert found_section['eRelationshipType'][0] == self.meta['e_relationship_type'], \ - f"Section eRelationshipType differs, is {found_section['eRelationshipType'][0]}" \ - f" but should be {self.meta['e_relationship_type']}" - assert found_section['eRecordType'][0] == self.meta['e_record_type'], \ - f"Section eRecordType differs, is {found_section['eRecordType'][0]}" \ - f" but should be {self.meta['e_record_type']}" - assert found_section['eRecordDataType'][0] == self.meta['e_record_data_type'], \ - f"Section eRecordDataType differs, is {found_section['eRecordDataType'][0]}" \ - f" but should be {self.meta['e_record_data_type']}" - assert found_section['iDataTypeSize'][0] == self.meta['i_data_type_size'], \ - f"Section iDataTypeSize differs, is {found_section['iDataTypeSize'][0]}" \ - f" but should be {self.meta['i_data_type_size']}" - assert found_section['iRecordSize'][0] == self.meta['i_record_size'], \ - f"Section iRecordSize differs, is {found_section['iRecordSize'][0]}" \ - f" but should be {self.meta['i_record_size']}" + if np.array_equal(self.meta['c_signature'], found_section['cSignature'][0], equal_nan=True) is False: + print(f"Section cSignature differs, is {np_uint16_to_string(found_section['cSignature'][0])}" + f" but should be {np_uint16_to_string(self.meta['c_signature'])}") + if found_section['iHeaderSize'][0] != self.meta['i_header_size']: + print(f"Section iHeaderSize differs, is {found_section['iHeaderSize'][0]}" + f" but should be {self.meta['i_header_size']}") + if found_section['iHeaderVersion'][0] != self.meta['i_header_version']: + print(f"Section iHeaderVersion differs, is {found_section['iHeaderVersion'][0]}" + f" but should be {self.meta['i_header_version']}") + if found_section['iSectionVersion'][0] != self.meta['i_section_version']: + print(f"Section iSectionVersion differs, is {found_section['iSectionVersion'][0]}" + f" but should be {self.meta['i_section_version']}") + if found_section['eRelationshipType'][0] != self.meta['e_relationship_type']: + print(f"Section eRelationshipType differs, is {found_section['eRelationshipType'][0]}" + f" but should be {self.meta['e_relationship_type']}") + if found_section['eRecordType'][0] != self.meta['e_record_type']: + print(f"Section eRecordType differs, is {found_section['eRecordType'][0]}" + f" but should be {self.meta['e_record_type']}") + if found_section['eRecordDataType'][0] != self.meta['e_record_data_type']: + print(f"Section eRecordDataType differs, is {found_section['eRecordDataType'][0]}" + f" but should be {self.meta['e_record_data_type']}") + if found_section['iDataTypeSize'][0] != self.meta['i_data_type_size']: + print(f"Section iDataTypeSize differs, is {found_section['iDataTypeSize'][0]}" + f" but should be {self.meta['i_data_type_size']}") + if found_section['iRecordSize'][0] != self.meta['i_record_size']: + print(f"Section iRecordSize differs, is {found_section['iRecordSize'][0]}" + f" but should be {self.meta['i_record_size']}") # ureg = UnitRegistry() # ureg.define('da = Da = amu') - assert np_uint16_to_string(found_section['wcDataUnit'][0]) in self.accepted_units, \ - f"Section wcDataUnit differs, is {np_uint16_to_string(found_section['wcDataUnit'][0])}" \ - f" but should be from accepted_units: {', '.join(self.accepted_units)}" + if np_uint16_to_string(found_section['wcDataUnit'][0]) not in self.accepted_units: + print(f"Section wcDataUnit differs, is {np_uint16_to_string(found_section['wcDataUnit'][0])}" + f" but should be from accepted_units: {', '.join(self.accepted_units)}") # Q = ureg.Quantity(1, 'amu') # use pint for checking compatible base unit - assert found_section['llByteCount'][0] > 0, \ - "Section llByteCount indicates llByteCount is not > 0 !" + if found_section['llByteCount'][0] <= 0: + raise ValueError("Section llByteCount indicates llByteCount is not > 0 !") # modify dynamic quanities that can only be inferred from the file - self.meta['ll_record_count'] = found_section['llRecordCount'][0] - self.meta['ll_byte_count'] = found_section['llByteCount'][0] + self.meta["ll_record_count"] = found_section["llRecordCount"][0] + self.meta["ll_byte_count"] = found_section["llByteCount"][0] return True def get_metadata(self) -> dict: """Create dictionary of all AMETEK metadata of the section.""" return \ { - 'cSignature': np_uint16_to_string(self.meta['c_signature']), - 'iHeaderSize': self.meta['i_header_size'], - 'iHeaderVersion': self.meta['i_header_version'], - 'wcSectionType': np_uint16_to_string(self.meta['wc_section_type']), - 'iSectionVersion': self.meta['i_section_version'], - 'eRelationshipType': self.meta['e_relationship_type'], - 'eRecordType': self.meta['e_record_type'], - 'eRecordDataType': self.meta['e_record_data_type'], - 'iDataTypeSize': self.meta['i_data_type_size'], - 'iRecordSize': self.meta['i_record_size'], - 'wcDataUnit': np_uint16_to_string(self.meta['wc_data_unit']), - 'llRecordCount': self.meta['ll_record_count'], - 'llByteCount': self.meta['ll_byte_count'], - 'AmetekSize': self.get_ametek_size(), - 'AmetekType': self.get_ametek_type(), - 'AmetekCount': self.get_ametek_count(), - 'AmetekShape': ', '.join([f"{x}" for x in self.get_ametek_shape()]) + "cSignature": np_uint16_to_string(self.meta["c_signature"]), + "iHeaderSize": self.meta["i_header_size"], + "iHeaderVersion": self.meta["i_header_version"], + "wcSectionType": np_uint16_to_string(self.meta["wc_section_type"]), + "iSectionVersion": self.meta["i_section_version"], + "eRelationshipType": self.meta["e_relationship_type"], + "eRecordType": self.meta["e_record_type"], + "eRecordDataType": self.meta["e_record_data_type"], + "iDataTypeSize": self.meta["i_data_type_size"], + "iRecordSize": self.meta["i_record_size"], + "wcDataUnit": np_uint16_to_string(self.meta["wc_data_unit"]), + "llRecordCount": self.meta["ll_record_count"], + "llByteCount": self.meta["ll_byte_count"], + "AmetekSize": self.get_ametek_size(), + "AmetekType": self.get_ametek_type(), + "AmetekCount": self.get_ametek_count(), + "AmetekShape": ", ".join([f"{x}" for x in self.get_ametek_shape()]) } diff --git a/ifes_apt_tc_data_modeling/apt/apt6_sections_branches.py b/ifes_apt_tc_data_modeling/apt/apt6_sections_branches.py index 61f24da..26aad6d 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_sections_branches.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_sections_branches.py @@ -37,37 +37,37 @@ # most tested sections -EXPECTED_SECTIONS['Position'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['Position'].set_section_name('Position') -EXPECTED_SECTIONS['Position'].set_c_signature() -EXPECTED_SECTIONS['Position'].set_i_header_size(148 + 6 * 4) -# six 4 byte IEEE 32-bit floats are following immediately after a 'Position' +EXPECTED_SECTIONS["Position"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["Position"].set_section_name("Position") +EXPECTED_SECTIONS["Position"].set_c_signature() +EXPECTED_SECTIONS["Position"].set_i_header_size(148 + 6 * 4) +# six 4 byte IEEE 32-bit floats are following immediately after a "Position" # section trailing the actual position value array -EXPECTED_SECTIONS['Position'].set_i_header_version(2) -EXPECTED_SECTIONS['Position'].set_wc_section_type('Position') -EXPECTED_SECTIONS['Position'].set_i_section_version(1) -EXPECTED_SECTIONS['Position'].set_e_relationship_type(1) -EXPECTED_SECTIONS['Position'].set_e_record_type(1) -EXPECTED_SECTIONS['Position'].set_e_record_data_type(3) -EXPECTED_SECTIONS['Position'].set_i_data_type_size(32) -EXPECTED_SECTIONS['Position'].set_i_record_size(12) -EXPECTED_SECTIONS['Position'].set_wc_data_unit('nm') -EXPECTED_SECTIONS['Position'].set_accepted_units(['nm']) - -EXPECTED_SECTIONS['Mass'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['Mass'].set_section_name('Mass') -EXPECTED_SECTIONS['Mass'].set_c_signature() -EXPECTED_SECTIONS['Mass'].set_i_header_size(148) -EXPECTED_SECTIONS['Mass'].set_i_header_version(2) -EXPECTED_SECTIONS['Mass'].set_wc_section_type('Mass') -EXPECTED_SECTIONS['Mass'].set_i_section_version(1) -EXPECTED_SECTIONS['Mass'].set_e_relationship_type(1) -EXPECTED_SECTIONS['Mass'].set_e_record_type(1) -EXPECTED_SECTIONS['Mass'].set_e_record_data_type(3) -EXPECTED_SECTIONS['Mass'].set_i_data_type_size(32) -EXPECTED_SECTIONS['Mass'].set_i_record_size(4) -EXPECTED_SECTIONS['Mass'].set_wc_data_unit('Da') -EXPECTED_SECTIONS['Mass'].set_accepted_units(['da', 'Da', 'amu']) +EXPECTED_SECTIONS["Position"].set_i_header_version(2) +EXPECTED_SECTIONS["Position"].set_wc_section_type("Position") +EXPECTED_SECTIONS["Position"].set_i_section_version(1) +EXPECTED_SECTIONS["Position"].set_e_relationship_type(1) +EXPECTED_SECTIONS["Position"].set_e_record_type(1) +EXPECTED_SECTIONS["Position"].set_e_record_data_type(3) +EXPECTED_SECTIONS["Position"].set_i_data_type_size(32) +EXPECTED_SECTIONS["Position"].set_i_record_size(12) +EXPECTED_SECTIONS["Position"].set_wc_data_unit("nm") +EXPECTED_SECTIONS["Position"].set_accepted_units(["nm"]) + +EXPECTED_SECTIONS["Mass"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["Mass"].set_section_name("Mass") +EXPECTED_SECTIONS["Mass"].set_c_signature() +EXPECTED_SECTIONS["Mass"].set_i_header_size(148) +EXPECTED_SECTIONS["Mass"].set_i_header_version(2) +EXPECTED_SECTIONS["Mass"].set_wc_section_type("Mass") +EXPECTED_SECTIONS["Mass"].set_i_section_version(1) +EXPECTED_SECTIONS["Mass"].set_e_relationship_type(1) +EXPECTED_SECTIONS["Mass"].set_e_record_type(1) +EXPECTED_SECTIONS["Mass"].set_e_record_data_type(3) +EXPECTED_SECTIONS["Mass"].set_i_data_type_size(32) +EXPECTED_SECTIONS["Mass"].set_i_record_size(4) +EXPECTED_SECTIONS["Mass"].set_wc_data_unit("Da") +EXPECTED_SECTIONS["Mass"].set_accepted_units(["da", "Da", "amu"]) # M. K\"uhbach detected there are at least APSuite versions which write # files with Da and some with da as wcDataUnits argument, it seems there @@ -75,619 +75,619 @@ # sections which demand more testing with the parser -EXPECTED_SECTIONS['z'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['z'].set_section_name('z') -EXPECTED_SECTIONS['z'].set_c_signature() -EXPECTED_SECTIONS['z'].set_i_header_size(148) -EXPECTED_SECTIONS['z'].set_i_header_version(2) -EXPECTED_SECTIONS['z'].set_wc_section_type('z') -EXPECTED_SECTIONS['z'].set_i_section_version(1) -EXPECTED_SECTIONS['z'].set_e_relationship_type(1) -EXPECTED_SECTIONS['z'].set_e_record_type(1) -EXPECTED_SECTIONS['z'].set_e_record_data_type(1) -EXPECTED_SECTIONS['z'].set_i_data_type_size(64) -EXPECTED_SECTIONS['z'].set_i_record_size(8) -EXPECTED_SECTIONS['z'].set_wc_data_unit('ions') -EXPECTED_SECTIONS['z'].set_accepted_units(['ions']) - -EXPECTED_SECTIONS['tof'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['tof'].set_section_name('tof') -EXPECTED_SECTIONS['tof'].set_c_signature() -EXPECTED_SECTIONS['tof'].set_i_header_size(148) -EXPECTED_SECTIONS['tof'].set_i_header_version(2) -EXPECTED_SECTIONS['tof'].set_wc_section_type('tof') -EXPECTED_SECTIONS['tof'].set_i_section_version(1) -EXPECTED_SECTIONS['tof'].set_e_relationship_type(1) -EXPECTED_SECTIONS['tof'].set_e_record_type(1) -EXPECTED_SECTIONS['tof'].set_e_record_data_type(3) -EXPECTED_SECTIONS['tof'].set_i_data_type_size(32) -EXPECTED_SECTIONS['tof'].set_i_record_size(4) -EXPECTED_SECTIONS['tof'].set_wc_data_unit('ns') -EXPECTED_SECTIONS['tof'].set_accepted_units(['ns']) - -EXPECTED_SECTIONS['Voltage'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['Voltage'].set_section_name('Voltage') -EXPECTED_SECTIONS['Voltage'].set_c_signature() -EXPECTED_SECTIONS['Voltage'].set_i_header_size(148) -EXPECTED_SECTIONS['Voltage'].set_i_header_version(2) -EXPECTED_SECTIONS['Voltage'].set_wc_section_type('Voltage') -EXPECTED_SECTIONS['Voltage'].set_i_section_version(1) -EXPECTED_SECTIONS['Voltage'].set_e_relationship_type(1) -EXPECTED_SECTIONS['Voltage'].set_e_record_type(1) -EXPECTED_SECTIONS['Voltage'].set_e_record_data_type(3) -EXPECTED_SECTIONS['Voltage'].set_i_data_type_size(32) -EXPECTED_SECTIONS['Voltage'].set_i_record_size(4) -EXPECTED_SECTIONS['Voltage'].set_wc_data_unit('') - -EXPECTED_SECTIONS['pulse'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['pulse'].set_section_name('pulse') -EXPECTED_SECTIONS['pulse'].set_c_signature() -EXPECTED_SECTIONS['pulse'].set_i_header_size(148) -EXPECTED_SECTIONS['pulse'].set_i_header_version(2) -EXPECTED_SECTIONS['pulse'].set_wc_section_type('pulse') -EXPECTED_SECTIONS['pulse'].set_i_section_version(1) -EXPECTED_SECTIONS['pulse'].set_e_relationship_type(1) -EXPECTED_SECTIONS['pulse'].set_e_record_type(1) -EXPECTED_SECTIONS['pulse'].set_e_record_data_type(3) -EXPECTED_SECTIONS['pulse'].set_i_data_type_size(32) -EXPECTED_SECTIONS['pulse'].set_i_record_size(4) -EXPECTED_SECTIONS['pulse'].set_wc_data_unit('') - -EXPECTED_SECTIONS['freq'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['freq'].set_section_name('freq') -EXPECTED_SECTIONS['freq'].set_c_signature() -EXPECTED_SECTIONS['freq'].set_i_header_size(148) -EXPECTED_SECTIONS['freq'].set_i_header_version(2) -EXPECTED_SECTIONS['freq'].set_wc_section_type('freq') -EXPECTED_SECTIONS['freq'].set_i_section_version(1) -EXPECTED_SECTIONS['freq'].set_e_relationship_type(1) -EXPECTED_SECTIONS['freq'].set_e_record_type(1) -EXPECTED_SECTIONS['freq'].set_e_record_data_type(3) -EXPECTED_SECTIONS['freq'].set_i_data_type_size(32) -EXPECTED_SECTIONS['freq'].set_i_record_size(4) -EXPECTED_SECTIONS['freq'].set_wc_data_unit('Hz') -EXPECTED_SECTIONS['freq'].set_accepted_units(['Hz']) - -EXPECTED_SECTIONS['tElapsed'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['tElapsed'].set_section_name('tElapsed') -EXPECTED_SECTIONS['tElapsed'].set_c_signature() -EXPECTED_SECTIONS['tElapsed'].set_i_header_size(148) -EXPECTED_SECTIONS['tElapsed'].set_i_header_version(2) -EXPECTED_SECTIONS['tElapsed'].set_wc_section_type('tElapsed') -EXPECTED_SECTIONS['tElapsed'].set_i_section_version(1) -EXPECTED_SECTIONS['tElapsed'].set_e_relationship_type(1) -EXPECTED_SECTIONS['tElapsed'].set_e_record_type(1) -EXPECTED_SECTIONS['tElapsed'].set_e_record_data_type(3) -EXPECTED_SECTIONS['tElapsed'].set_i_data_type_size(32) -EXPECTED_SECTIONS['tElapsed'].set_i_record_size(4) -EXPECTED_SECTIONS['tElapsed'].set_wc_data_unit('') - -EXPECTED_SECTIONS['erate'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['erate'].set_section_name('erate') -EXPECTED_SECTIONS['erate'].set_c_signature() -EXPECTED_SECTIONS['erate'].set_i_header_size(148) -EXPECTED_SECTIONS['erate'].set_i_header_version(2) -EXPECTED_SECTIONS['erate'].set_wc_section_type('erate') -EXPECTED_SECTIONS['erate'].set_i_section_version(1) -EXPECTED_SECTIONS['erate'].set_e_relationship_type(1) -EXPECTED_SECTIONS['erate'].set_e_record_type(1) -EXPECTED_SECTIONS['erate'].set_e_record_data_type(3) -EXPECTED_SECTIONS['erate'].set_i_data_type_size(32) -EXPECTED_SECTIONS['erate'].set_i_record_size(4) -EXPECTED_SECTIONS['erate'].set_wc_data_unit('%/100') -EXPECTED_SECTIONS['erate'].set_accepted_units(['%/100']) - -EXPECTED_SECTIONS['xstage'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['xstage'].set_section_name('xstage') -EXPECTED_SECTIONS['xstage'].set_c_signature() -EXPECTED_SECTIONS['xstage'].set_i_header_size(148) -EXPECTED_SECTIONS['xstage'].set_i_header_version(2) -EXPECTED_SECTIONS['xstage'].set_wc_section_type('xstage') -EXPECTED_SECTIONS['xstage'].set_i_section_version(1) -EXPECTED_SECTIONS['xstage'].set_e_relationship_type(1) -EXPECTED_SECTIONS['xstage'].set_e_record_type(1) -EXPECTED_SECTIONS['xstage'].set_e_record_data_type(1) -EXPECTED_SECTIONS['xstage'].set_i_data_type_size(32) -EXPECTED_SECTIONS['xstage'].set_i_record_size(4) -EXPECTED_SECTIONS['xstage'].set_wc_data_unit('') - -EXPECTED_SECTIONS['ystage'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['ystage'].set_section_name('ystage') -EXPECTED_SECTIONS['ystage'].set_c_signature() -EXPECTED_SECTIONS['ystage'].set_i_header_size(148) -EXPECTED_SECTIONS['ystage'].set_i_header_version(2) -EXPECTED_SECTIONS['ystage'].set_wc_section_type('ystage') -EXPECTED_SECTIONS['ystage'].set_i_section_version(1) -EXPECTED_SECTIONS['ystage'].set_e_relationship_type(1) -EXPECTED_SECTIONS['ystage'].set_e_record_type(1) -EXPECTED_SECTIONS['ystage'].set_e_record_data_type(1) -EXPECTED_SECTIONS['ystage'].set_i_data_type_size(32) -EXPECTED_SECTIONS['ystage'].set_i_record_size(4) -EXPECTED_SECTIONS['ystage'].set_wc_data_unit('') - -EXPECTED_SECTIONS['zstage'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['zstage'].set_section_name('zstage') -EXPECTED_SECTIONS['zstage'].set_c_signature() -EXPECTED_SECTIONS['zstage'].set_i_header_size(148) -EXPECTED_SECTIONS['zstage'].set_i_header_version(2) -EXPECTED_SECTIONS['zstage'].set_wc_section_type('zstage') -EXPECTED_SECTIONS['zstage'].set_i_section_version(1) -EXPECTED_SECTIONS['zstage'].set_e_relationship_type(1) -EXPECTED_SECTIONS['zstage'].set_e_record_type(1) -EXPECTED_SECTIONS['zstage'].set_e_record_data_type(1) -EXPECTED_SECTIONS['zstage'].set_i_data_type_size(32) -EXPECTED_SECTIONS['zstage'].set_i_record_size(4) -EXPECTED_SECTIONS['zstage'].set_wc_data_unit('') - -EXPECTED_SECTIONS['tstage'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['tstage'].set_section_name('tstage') -EXPECTED_SECTIONS['tstage'].set_c_signature() -EXPECTED_SECTIONS['tstage'].set_i_header_size(148) -EXPECTED_SECTIONS['tstage'].set_i_header_version(2) -EXPECTED_SECTIONS['tstage'].set_wc_section_type('tstage') -EXPECTED_SECTIONS['tstage'].set_i_section_version(1) -EXPECTED_SECTIONS['tstage'].set_e_relationship_type(1) -EXPECTED_SECTIONS['tstage'].set_e_record_type(1) -EXPECTED_SECTIONS['tstage'].set_e_record_data_type(2) -EXPECTED_SECTIONS['tstage'].set_i_data_type_size(16) -EXPECTED_SECTIONS['tstage'].set_i_record_size(2) -EXPECTED_SECTIONS['tstage'].set_wc_data_unit('') - -EXPECTED_SECTIONS['TargetErate'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['TargetErate'].set_section_name('TargetErate') -EXPECTED_SECTIONS['TargetErate'].set_c_signature() -EXPECTED_SECTIONS['TargetErate'].set_i_header_size(148) -EXPECTED_SECTIONS['TargetErate'].set_i_header_version(2) -EXPECTED_SECTIONS['TargetErate'].set_wc_section_type('TargetErate') -EXPECTED_SECTIONS['TargetErate'].set_i_section_version(1) -EXPECTED_SECTIONS['TargetErate'].set_e_relationship_type(1) -EXPECTED_SECTIONS['TargetErate'].set_e_record_type(1) -EXPECTED_SECTIONS['TargetErate'].set_e_record_data_type(3) -EXPECTED_SECTIONS['TargetErate'].set_i_data_type_size(32) -EXPECTED_SECTIONS['TargetErate'].set_i_record_size(4) -EXPECTED_SECTIONS['TargetErate'].set_wc_data_unit('%/100') -EXPECTED_SECTIONS['TargetErate'].set_accepted_units(['%/100']) - -EXPECTED_SECTIONS['TargetFlux'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['TargetFlux'].set_section_name('TargetFlux') -EXPECTED_SECTIONS['TargetFlux'].set_c_signature() -EXPECTED_SECTIONS['TargetFlux'].set_i_header_size(148) -EXPECTED_SECTIONS['TargetFlux'].set_i_header_version(2) -EXPECTED_SECTIONS['TargetFlux'].set_wc_section_type('TargetFlux') -EXPECTED_SECTIONS['TargetFlux'].set_i_section_version(1) -EXPECTED_SECTIONS['TargetFlux'].set_e_relationship_type(1) -EXPECTED_SECTIONS['TargetFlux'].set_e_record_type(1) -EXPECTED_SECTIONS['TargetFlux'].set_e_record_data_type(3) -EXPECTED_SECTIONS['TargetFlux'].set_i_data_type_size(32) -EXPECTED_SECTIONS['TargetFlux'].set_i_record_size(4) -EXPECTED_SECTIONS['TargetFlux'].set_wc_data_unit('') - -EXPECTED_SECTIONS['pulseDelta'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['pulseDelta'].set_section_name('pulseDelta') -EXPECTED_SECTIONS['pulseDelta'].set_c_signature() -EXPECTED_SECTIONS['pulseDelta'].set_i_header_size(148) -EXPECTED_SECTIONS['pulseDelta'].set_i_header_version(2) -EXPECTED_SECTIONS['pulseDelta'].set_wc_section_type('pulseDelta') -EXPECTED_SECTIONS['pulseDelta'].set_i_section_version(1) -EXPECTED_SECTIONS['pulseDelta'].set_e_relationship_type(1) -EXPECTED_SECTIONS['pulseDelta'].set_e_record_type(1) -EXPECTED_SECTIONS['pulseDelta'].set_e_record_data_type(1) -EXPECTED_SECTIONS['pulseDelta'].set_i_data_type_size(16) -EXPECTED_SECTIONS['pulseDelta'].set_i_record_size(2) -EXPECTED_SECTIONS['pulseDelta'].set_wc_data_unit('') - -EXPECTED_SECTIONS['Pres'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['Pres'].set_section_name('Pres') -EXPECTED_SECTIONS['Pres'].set_c_signature() -EXPECTED_SECTIONS['Pres'].set_i_header_size(148) -EXPECTED_SECTIONS['Pres'].set_i_header_version(2) -EXPECTED_SECTIONS['Pres'].set_wc_section_type('Pres') -EXPECTED_SECTIONS['Pres'].set_i_section_version(1) -EXPECTED_SECTIONS['Pres'].set_e_relationship_type(1) -EXPECTED_SECTIONS['Pres'].set_e_record_type(1) -EXPECTED_SECTIONS['Pres'].set_e_record_data_type(3) -EXPECTED_SECTIONS['Pres'].set_i_data_type_size(32) -EXPECTED_SECTIONS['Pres'].set_i_record_size(4) -EXPECTED_SECTIONS['Pres'].set_wc_data_unit('torr') -EXPECTED_SECTIONS['Pres'].set_accepted_units(['torr']) - -EXPECTED_SECTIONS['VAnodeMon'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['VAnodeMon'].set_section_name('VAnodeMon') -EXPECTED_SECTIONS['VAnodeMon'].set_c_signature() -EXPECTED_SECTIONS['VAnodeMon'].set_i_header_size(148) -EXPECTED_SECTIONS['VAnodeMon'].set_i_header_version(2) -EXPECTED_SECTIONS['VAnodeMon'].set_wc_section_type('VAnodeMon') -EXPECTED_SECTIONS['VAnodeMon'].set_i_section_version(1) -EXPECTED_SECTIONS['VAnodeMon'].set_e_relationship_type(1) -EXPECTED_SECTIONS['VAnodeMon'].set_e_record_type(1) -EXPECTED_SECTIONS['VAnodeMon'].set_e_record_data_type(3) -EXPECTED_SECTIONS['VAnodeMon'].set_i_data_type_size(32) -EXPECTED_SECTIONS['VAnodeMon'].set_i_record_size(4) -EXPECTED_SECTIONS['VAnodeMon'].set_wc_data_unit('') - -EXPECTED_SECTIONS['Temp'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['Temp'].set_section_name('Temp') -EXPECTED_SECTIONS['Temp'].set_c_signature() -EXPECTED_SECTIONS['Temp'].set_i_header_size(148) -EXPECTED_SECTIONS['Temp'].set_i_header_version(2) -EXPECTED_SECTIONS['Temp'].set_wc_section_type('Temp') -EXPECTED_SECTIONS['Temp'].set_i_section_version(1) -EXPECTED_SECTIONS['Temp'].set_e_relationship_type(1) -EXPECTED_SECTIONS['Temp'].set_e_record_type(1) -EXPECTED_SECTIONS['Temp'].set_e_record_data_type(3) -EXPECTED_SECTIONS['Temp'].set_i_data_type_size(32) -EXPECTED_SECTIONS['Temp'].set_i_record_size(4) -EXPECTED_SECTIONS['Temp'].set_wc_data_unit('K') -EXPECTED_SECTIONS['Temp'].set_accepted_units(['K']) - - -EXPECTED_SECTIONS['AmbTemp'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['AmbTemp'].set_section_name('AmbTemp') -EXPECTED_SECTIONS['AmbTemp'].set_c_signature() -EXPECTED_SECTIONS['AmbTemp'].set_i_header_size(148) -EXPECTED_SECTIONS['AmbTemp'].set_i_header_version(2) -EXPECTED_SECTIONS['AmbTemp'].set_wc_section_type('AmbTemp') -EXPECTED_SECTIONS['AmbTemp'].set_i_section_version(1) -EXPECTED_SECTIONS['AmbTemp'].set_e_relationship_type(1) -EXPECTED_SECTIONS['AmbTemp'].set_e_record_type(1) -EXPECTED_SECTIONS['AmbTemp'].set_e_record_data_type(3) -EXPECTED_SECTIONS['AmbTemp'].set_i_data_type_size(32) -EXPECTED_SECTIONS['AmbTemp'].set_i_record_size(4) -EXPECTED_SECTIONS['AmbTemp'].set_wc_data_unit('C') -EXPECTED_SECTIONS['AmbTemp'].set_accepted_units(['C']) - -EXPECTED_SECTIONS['laserx'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['laserx'].set_section_name('laserx') -EXPECTED_SECTIONS['laserx'].set_c_signature() -EXPECTED_SECTIONS['laserx'].set_i_header_size(148) -EXPECTED_SECTIONS['laserx'].set_i_header_version(2) -EXPECTED_SECTIONS['laserx'].set_wc_section_type('laserx') -EXPECTED_SECTIONS['laserx'].set_i_section_version(1) -EXPECTED_SECTIONS['laserx'].set_e_relationship_type(1) -EXPECTED_SECTIONS['laserx'].set_e_record_type(1) -EXPECTED_SECTIONS['laserx'].set_e_record_data_type(1) -EXPECTED_SECTIONS['laserx'].set_i_data_type_size(32) -EXPECTED_SECTIONS['laserx'].set_i_record_size(4) -EXPECTED_SECTIONS['laserx'].set_wc_data_unit('') - -EXPECTED_SECTIONS['lasery'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['lasery'].set_section_name('lasery') -EXPECTED_SECTIONS['lasery'].set_c_signature() -EXPECTED_SECTIONS['lasery'].set_i_header_size(148) -EXPECTED_SECTIONS['lasery'].set_i_header_version(2) -EXPECTED_SECTIONS['lasery'].set_wc_section_type('lasery') -EXPECTED_SECTIONS['lasery'].set_i_section_version(1) -EXPECTED_SECTIONS['lasery'].set_e_relationship_type(1) -EXPECTED_SECTIONS['lasery'].set_e_record_type(1) -EXPECTED_SECTIONS['lasery'].set_e_record_data_type(1) -EXPECTED_SECTIONS['lasery'].set_i_data_type_size(32) -EXPECTED_SECTIONS['lasery'].set_i_record_size(4) -EXPECTED_SECTIONS['lasery'].set_wc_data_unit('') - -EXPECTED_SECTIONS['laserz'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['laserz'].set_section_name('laserz') -EXPECTED_SECTIONS['laserz'].set_c_signature() -EXPECTED_SECTIONS['laserz'].set_i_header_size(148) -EXPECTED_SECTIONS['laserz'].set_i_header_version(2) -EXPECTED_SECTIONS['laserz'].set_wc_section_type('laserz') -EXPECTED_SECTIONS['laserz'].set_i_section_version(1) -EXPECTED_SECTIONS['laserz'].set_e_relationship_type(1) -EXPECTED_SECTIONS['laserz'].set_e_record_type(1) -EXPECTED_SECTIONS['laserz'].set_e_record_data_type(1) -EXPECTED_SECTIONS['laserz'].set_i_data_type_size(32) -EXPECTED_SECTIONS['laserz'].set_i_record_size(4) -EXPECTED_SECTIONS['laserz'].set_wc_data_unit('') - -EXPECTED_SECTIONS['laserpower'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['laserpower'].set_section_name('laserpower') -EXPECTED_SECTIONS['laserpower'].set_c_signature() -EXPECTED_SECTIONS['laserpower'].set_i_header_size(148) -EXPECTED_SECTIONS['laserpower'].set_i_header_version(2) -EXPECTED_SECTIONS['laserpower'].set_wc_section_type('laserpower') -EXPECTED_SECTIONS['laserpower'].set_i_section_version(1) -EXPECTED_SECTIONS['laserpower'].set_e_relationship_type(1) -EXPECTED_SECTIONS['laserpower'].set_e_record_type(1) -EXPECTED_SECTIONS['laserpower'].set_e_record_data_type(3) -EXPECTED_SECTIONS['laserpower'].set_i_data_type_size(32) -EXPECTED_SECTIONS['laserpower'].set_i_record_size(4) -EXPECTED_SECTIONS['laserpower'].set_wc_data_unit('') - -EXPECTED_SECTIONS['FractureGuard'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['FractureGuard'].set_section_name('FractureGuard') -EXPECTED_SECTIONS['FractureGuard'].set_c_signature() -EXPECTED_SECTIONS['FractureGuard'].set_i_header_size(148) -EXPECTED_SECTIONS['FractureGuard'].set_i_header_version(2) -EXPECTED_SECTIONS['FractureGuard'].set_wc_section_type('FractureGuard') -EXPECTED_SECTIONS['FractureGuard'].set_i_section_version(1) -EXPECTED_SECTIONS['FractureGuard'].set_e_relationship_type(1) -EXPECTED_SECTIONS['FractureGuard'].set_e_record_type(1) -EXPECTED_SECTIONS['FractureGuard'].set_e_record_data_type(2) -EXPECTED_SECTIONS['FractureGuard'].set_i_data_type_size(16) -EXPECTED_SECTIONS['FractureGuard'].set_i_record_size(2) -EXPECTED_SECTIONS['FractureGuard'].set_wc_data_unit('') - -EXPECTED_SECTIONS['Noise'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['Noise'].set_section_name('Noise') -EXPECTED_SECTIONS['Noise'].set_c_signature() -EXPECTED_SECTIONS['Noise'].set_i_header_size(148) -EXPECTED_SECTIONS['Noise'].set_i_header_version(2) -EXPECTED_SECTIONS['Noise'].set_wc_section_type('Noise') -EXPECTED_SECTIONS['Noise'].set_i_section_version(1) -EXPECTED_SECTIONS['Noise'].set_e_relationship_type(1) -EXPECTED_SECTIONS['Noise'].set_e_record_type(1) -EXPECTED_SECTIONS['Noise'].set_e_record_data_type(3) -EXPECTED_SECTIONS['Noise'].set_i_data_type_size(32) -EXPECTED_SECTIONS['Noise'].set_i_record_size(4) -EXPECTED_SECTIONS['Noise'].set_wc_data_unit('ions') -EXPECTED_SECTIONS['Noise'].set_accepted_units(['', 'ions']) - -EXPECTED_SECTIONS['Uniformity'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['Uniformity'].set_section_name('Uniformity') -EXPECTED_SECTIONS['Uniformity'].set_c_signature() -EXPECTED_SECTIONS['Uniformity'].set_i_header_size(148) -EXPECTED_SECTIONS['Uniformity'].set_i_header_version(2) -EXPECTED_SECTIONS['Uniformity'].set_wc_section_type('Uniformity') -EXPECTED_SECTIONS['Uniformity'].set_i_section_version(1) -EXPECTED_SECTIONS['Uniformity'].set_e_relationship_type(1) -EXPECTED_SECTIONS['Uniformity'].set_e_record_type(1) -EXPECTED_SECTIONS['Uniformity'].set_e_record_data_type(3) -EXPECTED_SECTIONS['Uniformity'].set_i_data_type_size(32) -EXPECTED_SECTIONS['Uniformity'].set_i_record_size(4) -EXPECTED_SECTIONS['Uniformity'].set_wc_data_unit('') - -EXPECTED_SECTIONS['tofc'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['tofc'].set_section_name('tofc') -EXPECTED_SECTIONS['tofc'].set_c_signature() -EXPECTED_SECTIONS['tofc'].set_i_header_size(148) -EXPECTED_SECTIONS['tofc'].set_i_header_version(2) -EXPECTED_SECTIONS['tofc'].set_wc_section_type('tofc') -EXPECTED_SECTIONS['tofc'].set_i_section_version(1) -EXPECTED_SECTIONS['tofc'].set_e_relationship_type(1) -EXPECTED_SECTIONS['tofc'].set_e_record_type(1) -EXPECTED_SECTIONS['tofc'].set_e_record_data_type(3) -EXPECTED_SECTIONS['tofc'].set_i_data_type_size(32) -EXPECTED_SECTIONS['tofc'].set_i_record_size(4) -EXPECTED_SECTIONS['tofc'].set_wc_data_unit('ns') -EXPECTED_SECTIONS['tofc'].set_accepted_units(['ns']) - -EXPECTED_SECTIONS['tofb'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['tofb'].set_section_name('tofb') -EXPECTED_SECTIONS['tofb'].set_c_signature() -EXPECTED_SECTIONS['tofb'].set_i_header_size(148) -EXPECTED_SECTIONS['tofb'].set_i_header_version(2) -EXPECTED_SECTIONS['tofb'].set_wc_section_type('tofb') -EXPECTED_SECTIONS['tofb'].set_i_section_version(1) -EXPECTED_SECTIONS['tofb'].set_e_relationship_type(1) -EXPECTED_SECTIONS['tofb'].set_e_record_type(1) -EXPECTED_SECTIONS['tofb'].set_e_record_data_type(3) -EXPECTED_SECTIONS['tofb'].set_i_data_type_size(32) -EXPECTED_SECTIONS['tofb'].set_i_record_size(4) -EXPECTED_SECTIONS['tofb'].set_wc_data_unit('ns') -EXPECTED_SECTIONS['tofb'].set_accepted_units(['ns']) - -EXPECTED_SECTIONS['xs'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['xs'].set_section_name('xs') -EXPECTED_SECTIONS['xs'].set_c_signature() -EXPECTED_SECTIONS['xs'].set_i_header_size(148) -EXPECTED_SECTIONS['xs'].set_i_header_version(2) -EXPECTED_SECTIONS['xs'].set_wc_section_type('xs') -EXPECTED_SECTIONS['xs'].set_i_section_version(1) -EXPECTED_SECTIONS['xs'].set_e_relationship_type(1) -EXPECTED_SECTIONS['xs'].set_e_record_type(1) -EXPECTED_SECTIONS['xs'].set_e_record_data_type(3) -EXPECTED_SECTIONS['xs'].set_i_data_type_size(32) -EXPECTED_SECTIONS['xs'].set_i_record_size(4) -EXPECTED_SECTIONS['xs'].set_wc_data_unit('nm') -EXPECTED_SECTIONS['xs'].set_accepted_units(['nm']) - -EXPECTED_SECTIONS['ys'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['ys'].set_section_name('ys') -EXPECTED_SECTIONS['ys'].set_c_signature() -EXPECTED_SECTIONS['ys'].set_i_header_size(148) -EXPECTED_SECTIONS['ys'].set_i_header_version(2) -EXPECTED_SECTIONS['ys'].set_wc_section_type('ys') -EXPECTED_SECTIONS['ys'].set_i_section_version(1) -EXPECTED_SECTIONS['ys'].set_e_relationship_type(1) -EXPECTED_SECTIONS['ys'].set_e_record_type(1) -EXPECTED_SECTIONS['ys'].set_e_record_data_type(3) -EXPECTED_SECTIONS['ys'].set_i_data_type_size(32) -EXPECTED_SECTIONS['ys'].set_i_record_size(4) -EXPECTED_SECTIONS['ys'].set_wc_data_unit('nm') -EXPECTED_SECTIONS['ys'].set_accepted_units(['nm']) - -EXPECTED_SECTIONS['zs'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['zs'].set_section_name('zs') -EXPECTED_SECTIONS['zs'].set_c_signature() -EXPECTED_SECTIONS['zs'].set_i_header_size(148) -EXPECTED_SECTIONS['zs'].set_i_header_version(2) -EXPECTED_SECTIONS['zs'].set_wc_section_type('zs') -EXPECTED_SECTIONS['zs'].set_i_section_version(1) -EXPECTED_SECTIONS['zs'].set_e_relationship_type(1) -EXPECTED_SECTIONS['zs'].set_e_record_type(1) -EXPECTED_SECTIONS['zs'].set_e_record_data_type(3) -EXPECTED_SECTIONS['zs'].set_i_data_type_size(32) -EXPECTED_SECTIONS['zs'].set_i_record_size(4) -EXPECTED_SECTIONS['zs'].set_wc_data_unit('nm') -EXPECTED_SECTIONS['zs'].set_accepted_units(['nm']) - -EXPECTED_SECTIONS['rTip'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['rTip'].set_section_name('rTip') -EXPECTED_SECTIONS['rTip'].set_c_signature() -EXPECTED_SECTIONS['rTip'].set_i_header_size(148) -EXPECTED_SECTIONS['rTip'].set_i_header_version(2) -EXPECTED_SECTIONS['rTip'].set_wc_section_type('rTip') -EXPECTED_SECTIONS['rTip'].set_i_section_version(1) -EXPECTED_SECTIONS['rTip'].set_e_relationship_type(1) -EXPECTED_SECTIONS['rTip'].set_e_record_type(1) -EXPECTED_SECTIONS['rTip'].set_e_record_data_type(3) -EXPECTED_SECTIONS['rTip'].set_i_data_type_size(32) -EXPECTED_SECTIONS['rTip'].set_i_record_size(4) -EXPECTED_SECTIONS['rTip'].set_wc_data_unit('nm') -EXPECTED_SECTIONS['rTip'].set_accepted_units(['nm']) - -EXPECTED_SECTIONS['zApex'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['zApex'].set_section_name('zApex') -EXPECTED_SECTIONS['zApex'].set_c_signature() -EXPECTED_SECTIONS['zApex'].set_i_header_size(148) -EXPECTED_SECTIONS['zApex'].set_i_header_version(2) -EXPECTED_SECTIONS['zApex'].set_wc_section_type('zApex') -EXPECTED_SECTIONS['zApex'].set_i_section_version(1) -EXPECTED_SECTIONS['zApex'].set_e_relationship_type(1) -EXPECTED_SECTIONS['zApex'].set_e_record_type(1) -EXPECTED_SECTIONS['zApex'].set_e_record_data_type(3) -EXPECTED_SECTIONS['zApex'].set_i_data_type_size(32) -EXPECTED_SECTIONS['zApex'].set_i_record_size(4) -EXPECTED_SECTIONS['zApex'].set_wc_data_unit('nm') -EXPECTED_SECTIONS['zApex'].set_accepted_units(['nm']) - -EXPECTED_SECTIONS['zSphereCorr'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['zSphereCorr'].set_section_name('zSphereCorr') -EXPECTED_SECTIONS['zSphereCorr'].set_c_signature() -EXPECTED_SECTIONS['zSphereCorr'].set_i_header_size(148) -EXPECTED_SECTIONS['zSphereCorr'].set_i_header_version(2) -EXPECTED_SECTIONS['zSphereCorr'].set_wc_section_type('zSphereCorr') -EXPECTED_SECTIONS['zSphereCorr'].set_i_section_version(1) -EXPECTED_SECTIONS['zSphereCorr'].set_e_relationship_type(1) -EXPECTED_SECTIONS['zSphereCorr'].set_e_record_type(1) -EXPECTED_SECTIONS['zSphereCorr'].set_e_record_data_type(3) -EXPECTED_SECTIONS['zSphereCorr'].set_i_data_type_size(32) -EXPECTED_SECTIONS['zSphereCorr'].set_i_record_size(4) -EXPECTED_SECTIONS['zSphereCorr'].set_wc_data_unit('nm') -EXPECTED_SECTIONS['zSphereCorr'].set_accepted_units(['nm']) +EXPECTED_SECTIONS["z"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["z"].set_section_name("z") +EXPECTED_SECTIONS["z"].set_c_signature() +EXPECTED_SECTIONS["z"].set_i_header_size(148) +EXPECTED_SECTIONS["z"].set_i_header_version(2) +EXPECTED_SECTIONS["z"].set_wc_section_type("z") +EXPECTED_SECTIONS["z"].set_i_section_version(1) +EXPECTED_SECTIONS["z"].set_e_relationship_type(1) +EXPECTED_SECTIONS["z"].set_e_record_type(1) +EXPECTED_SECTIONS["z"].set_e_record_data_type(1) +EXPECTED_SECTIONS["z"].set_i_data_type_size(64) +EXPECTED_SECTIONS["z"].set_i_record_size(8) +EXPECTED_SECTIONS["z"].set_wc_data_unit("ions") +EXPECTED_SECTIONS["z"].set_accepted_units(["ions"]) + +EXPECTED_SECTIONS["tof"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["tof"].set_section_name("tof") +EXPECTED_SECTIONS["tof"].set_c_signature() +EXPECTED_SECTIONS["tof"].set_i_header_size(148) +EXPECTED_SECTIONS["tof"].set_i_header_version(2) +EXPECTED_SECTIONS["tof"].set_wc_section_type("tof") +EXPECTED_SECTIONS["tof"].set_i_section_version(1) +EXPECTED_SECTIONS["tof"].set_e_relationship_type(1) +EXPECTED_SECTIONS["tof"].set_e_record_type(1) +EXPECTED_SECTIONS["tof"].set_e_record_data_type(3) +EXPECTED_SECTIONS["tof"].set_i_data_type_size(32) +EXPECTED_SECTIONS["tof"].set_i_record_size(4) +EXPECTED_SECTIONS["tof"].set_wc_data_unit("ns") +EXPECTED_SECTIONS["tof"].set_accepted_units(["ns"]) + +EXPECTED_SECTIONS["Voltage"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["Voltage"].set_section_name("Voltage") +EXPECTED_SECTIONS["Voltage"].set_c_signature() +EXPECTED_SECTIONS["Voltage"].set_i_header_size(148) +EXPECTED_SECTIONS["Voltage"].set_i_header_version(2) +EXPECTED_SECTIONS["Voltage"].set_wc_section_type("Voltage") +EXPECTED_SECTIONS["Voltage"].set_i_section_version(1) +EXPECTED_SECTIONS["Voltage"].set_e_relationship_type(1) +EXPECTED_SECTIONS["Voltage"].set_e_record_type(1) +EXPECTED_SECTIONS["Voltage"].set_e_record_data_type(3) +EXPECTED_SECTIONS["Voltage"].set_i_data_type_size(32) +EXPECTED_SECTIONS["Voltage"].set_i_record_size(4) +EXPECTED_SECTIONS["Voltage"].set_wc_data_unit("") + +EXPECTED_SECTIONS["pulse"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["pulse"].set_section_name("pulse") +EXPECTED_SECTIONS["pulse"].set_c_signature() +EXPECTED_SECTIONS["pulse"].set_i_header_size(148) +EXPECTED_SECTIONS["pulse"].set_i_header_version(2) +EXPECTED_SECTIONS["pulse"].set_wc_section_type("pulse") +EXPECTED_SECTIONS["pulse"].set_i_section_version(1) +EXPECTED_SECTIONS["pulse"].set_e_relationship_type(1) +EXPECTED_SECTIONS["pulse"].set_e_record_type(1) +EXPECTED_SECTIONS["pulse"].set_e_record_data_type(3) +EXPECTED_SECTIONS["pulse"].set_i_data_type_size(32) +EXPECTED_SECTIONS["pulse"].set_i_record_size(4) +EXPECTED_SECTIONS["pulse"].set_wc_data_unit("") + +EXPECTED_SECTIONS["freq"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["freq"].set_section_name("freq") +EXPECTED_SECTIONS["freq"].set_c_signature() +EXPECTED_SECTIONS["freq"].set_i_header_size(148) +EXPECTED_SECTIONS["freq"].set_i_header_version(2) +EXPECTED_SECTIONS["freq"].set_wc_section_type("freq") +EXPECTED_SECTIONS["freq"].set_i_section_version(1) +EXPECTED_SECTIONS["freq"].set_e_relationship_type(1) +EXPECTED_SECTIONS["freq"].set_e_record_type(1) +EXPECTED_SECTIONS["freq"].set_e_record_data_type(3) +EXPECTED_SECTIONS["freq"].set_i_data_type_size(32) +EXPECTED_SECTIONS["freq"].set_i_record_size(4) +EXPECTED_SECTIONS["freq"].set_wc_data_unit("Hz") +EXPECTED_SECTIONS["freq"].set_accepted_units(["Hz"]) + +EXPECTED_SECTIONS["tElapsed"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["tElapsed"].set_section_name("tElapsed") +EXPECTED_SECTIONS["tElapsed"].set_c_signature() +EXPECTED_SECTIONS["tElapsed"].set_i_header_size(148) +EXPECTED_SECTIONS["tElapsed"].set_i_header_version(2) +EXPECTED_SECTIONS["tElapsed"].set_wc_section_type("tElapsed") +EXPECTED_SECTIONS["tElapsed"].set_i_section_version(1) +EXPECTED_SECTIONS["tElapsed"].set_e_relationship_type(1) +EXPECTED_SECTIONS["tElapsed"].set_e_record_type(1) +EXPECTED_SECTIONS["tElapsed"].set_e_record_data_type(3) +EXPECTED_SECTIONS["tElapsed"].set_i_data_type_size(32) +EXPECTED_SECTIONS["tElapsed"].set_i_record_size(4) +EXPECTED_SECTIONS["tElapsed"].set_wc_data_unit("") + +EXPECTED_SECTIONS["erate"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["erate"].set_section_name("erate") +EXPECTED_SECTIONS["erate"].set_c_signature() +EXPECTED_SECTIONS["erate"].set_i_header_size(148) +EXPECTED_SECTIONS["erate"].set_i_header_version(2) +EXPECTED_SECTIONS["erate"].set_wc_section_type("erate") +EXPECTED_SECTIONS["erate"].set_i_section_version(1) +EXPECTED_SECTIONS["erate"].set_e_relationship_type(1) +EXPECTED_SECTIONS["erate"].set_e_record_type(1) +EXPECTED_SECTIONS["erate"].set_e_record_data_type(3) +EXPECTED_SECTIONS["erate"].set_i_data_type_size(32) +EXPECTED_SECTIONS["erate"].set_i_record_size(4) +EXPECTED_SECTIONS["erate"].set_wc_data_unit("%/100") +EXPECTED_SECTIONS["erate"].set_accepted_units(["%/100"]) + +EXPECTED_SECTIONS["xstage"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["xstage"].set_section_name("xstage") +EXPECTED_SECTIONS["xstage"].set_c_signature() +EXPECTED_SECTIONS["xstage"].set_i_header_size(148) +EXPECTED_SECTIONS["xstage"].set_i_header_version(2) +EXPECTED_SECTIONS["xstage"].set_wc_section_type("xstage") +EXPECTED_SECTIONS["xstage"].set_i_section_version(1) +EXPECTED_SECTIONS["xstage"].set_e_relationship_type(1) +EXPECTED_SECTIONS["xstage"].set_e_record_type(1) +EXPECTED_SECTIONS["xstage"].set_e_record_data_type(1) +EXPECTED_SECTIONS["xstage"].set_i_data_type_size(32) +EXPECTED_SECTIONS["xstage"].set_i_record_size(4) +EXPECTED_SECTIONS["xstage"].set_wc_data_unit("") + +EXPECTED_SECTIONS["ystage"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["ystage"].set_section_name("ystage") +EXPECTED_SECTIONS["ystage"].set_c_signature() +EXPECTED_SECTIONS["ystage"].set_i_header_size(148) +EXPECTED_SECTIONS["ystage"].set_i_header_version(2) +EXPECTED_SECTIONS["ystage"].set_wc_section_type("ystage") +EXPECTED_SECTIONS["ystage"].set_i_section_version(1) +EXPECTED_SECTIONS["ystage"].set_e_relationship_type(1) +EXPECTED_SECTIONS["ystage"].set_e_record_type(1) +EXPECTED_SECTIONS["ystage"].set_e_record_data_type(1) +EXPECTED_SECTIONS["ystage"].set_i_data_type_size(32) +EXPECTED_SECTIONS["ystage"].set_i_record_size(4) +EXPECTED_SECTIONS["ystage"].set_wc_data_unit("") + +EXPECTED_SECTIONS["zstage"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["zstage"].set_section_name("zstage") +EXPECTED_SECTIONS["zstage"].set_c_signature() +EXPECTED_SECTIONS["zstage"].set_i_header_size(148) +EXPECTED_SECTIONS["zstage"].set_i_header_version(2) +EXPECTED_SECTIONS["zstage"].set_wc_section_type("zstage") +EXPECTED_SECTIONS["zstage"].set_i_section_version(1) +EXPECTED_SECTIONS["zstage"].set_e_relationship_type(1) +EXPECTED_SECTIONS["zstage"].set_e_record_type(1) +EXPECTED_SECTIONS["zstage"].set_e_record_data_type(1) +EXPECTED_SECTIONS["zstage"].set_i_data_type_size(32) +EXPECTED_SECTIONS["zstage"].set_i_record_size(4) +EXPECTED_SECTIONS["zstage"].set_wc_data_unit("") + +EXPECTED_SECTIONS["tstage"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["tstage"].set_section_name("tstage") +EXPECTED_SECTIONS["tstage"].set_c_signature() +EXPECTED_SECTIONS["tstage"].set_i_header_size(148) +EXPECTED_SECTIONS["tstage"].set_i_header_version(2) +EXPECTED_SECTIONS["tstage"].set_wc_section_type("tstage") +EXPECTED_SECTIONS["tstage"].set_i_section_version(1) +EXPECTED_SECTIONS["tstage"].set_e_relationship_type(1) +EXPECTED_SECTIONS["tstage"].set_e_record_type(1) +EXPECTED_SECTIONS["tstage"].set_e_record_data_type(2) +EXPECTED_SECTIONS["tstage"].set_i_data_type_size(16) +EXPECTED_SECTIONS["tstage"].set_i_record_size(2) +EXPECTED_SECTIONS["tstage"].set_wc_data_unit("") + +EXPECTED_SECTIONS["TargetErate"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["TargetErate"].set_section_name("TargetErate") +EXPECTED_SECTIONS["TargetErate"].set_c_signature() +EXPECTED_SECTIONS["TargetErate"].set_i_header_size(148) +EXPECTED_SECTIONS["TargetErate"].set_i_header_version(2) +EXPECTED_SECTIONS["TargetErate"].set_wc_section_type("TargetErate") +EXPECTED_SECTIONS["TargetErate"].set_i_section_version(1) +EXPECTED_SECTIONS["TargetErate"].set_e_relationship_type(1) +EXPECTED_SECTIONS["TargetErate"].set_e_record_type(1) +EXPECTED_SECTIONS["TargetErate"].set_e_record_data_type(3) +EXPECTED_SECTIONS["TargetErate"].set_i_data_type_size(32) +EXPECTED_SECTIONS["TargetErate"].set_i_record_size(4) +EXPECTED_SECTIONS["TargetErate"].set_wc_data_unit("%/100") +EXPECTED_SECTIONS["TargetErate"].set_accepted_units(["%/100"]) + +EXPECTED_SECTIONS["TargetFlux"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["TargetFlux"].set_section_name("TargetFlux") +EXPECTED_SECTIONS["TargetFlux"].set_c_signature() +EXPECTED_SECTIONS["TargetFlux"].set_i_header_size(148) +EXPECTED_SECTIONS["TargetFlux"].set_i_header_version(2) +EXPECTED_SECTIONS["TargetFlux"].set_wc_section_type("TargetFlux") +EXPECTED_SECTIONS["TargetFlux"].set_i_section_version(1) +EXPECTED_SECTIONS["TargetFlux"].set_e_relationship_type(1) +EXPECTED_SECTIONS["TargetFlux"].set_e_record_type(1) +EXPECTED_SECTIONS["TargetFlux"].set_e_record_data_type(3) +EXPECTED_SECTIONS["TargetFlux"].set_i_data_type_size(32) +EXPECTED_SECTIONS["TargetFlux"].set_i_record_size(4) +EXPECTED_SECTIONS["TargetFlux"].set_wc_data_unit("") + +EXPECTED_SECTIONS["pulseDelta"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["pulseDelta"].set_section_name("pulseDelta") +EXPECTED_SECTIONS["pulseDelta"].set_c_signature() +EXPECTED_SECTIONS["pulseDelta"].set_i_header_size(148) +EXPECTED_SECTIONS["pulseDelta"].set_i_header_version(2) +EXPECTED_SECTIONS["pulseDelta"].set_wc_section_type("pulseDelta") +EXPECTED_SECTIONS["pulseDelta"].set_i_section_version(1) +EXPECTED_SECTIONS["pulseDelta"].set_e_relationship_type(1) +EXPECTED_SECTIONS["pulseDelta"].set_e_record_type(1) +EXPECTED_SECTIONS["pulseDelta"].set_e_record_data_type(1) +EXPECTED_SECTIONS["pulseDelta"].set_i_data_type_size(16) +EXPECTED_SECTIONS["pulseDelta"].set_i_record_size(2) +EXPECTED_SECTIONS["pulseDelta"].set_wc_data_unit("") + +EXPECTED_SECTIONS["Pres"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["Pres"].set_section_name("Pres") +EXPECTED_SECTIONS["Pres"].set_c_signature() +EXPECTED_SECTIONS["Pres"].set_i_header_size(148) +EXPECTED_SECTIONS["Pres"].set_i_header_version(2) +EXPECTED_SECTIONS["Pres"].set_wc_section_type("Pres") +EXPECTED_SECTIONS["Pres"].set_i_section_version(1) +EXPECTED_SECTIONS["Pres"].set_e_relationship_type(1) +EXPECTED_SECTIONS["Pres"].set_e_record_type(1) +EXPECTED_SECTIONS["Pres"].set_e_record_data_type(3) +EXPECTED_SECTIONS["Pres"].set_i_data_type_size(32) +EXPECTED_SECTIONS["Pres"].set_i_record_size(4) +EXPECTED_SECTIONS["Pres"].set_wc_data_unit("torr") +EXPECTED_SECTIONS["Pres"].set_accepted_units(["torr"]) + +EXPECTED_SECTIONS["VAnodeMon"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["VAnodeMon"].set_section_name("VAnodeMon") +EXPECTED_SECTIONS["VAnodeMon"].set_c_signature() +EXPECTED_SECTIONS["VAnodeMon"].set_i_header_size(148) +EXPECTED_SECTIONS["VAnodeMon"].set_i_header_version(2) +EXPECTED_SECTIONS["VAnodeMon"].set_wc_section_type("VAnodeMon") +EXPECTED_SECTIONS["VAnodeMon"].set_i_section_version(1) +EXPECTED_SECTIONS["VAnodeMon"].set_e_relationship_type(1) +EXPECTED_SECTIONS["VAnodeMon"].set_e_record_type(1) +EXPECTED_SECTIONS["VAnodeMon"].set_e_record_data_type(3) +EXPECTED_SECTIONS["VAnodeMon"].set_i_data_type_size(32) +EXPECTED_SECTIONS["VAnodeMon"].set_i_record_size(4) +EXPECTED_SECTIONS["VAnodeMon"].set_wc_data_unit("") + +EXPECTED_SECTIONS["Temp"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["Temp"].set_section_name("Temp") +EXPECTED_SECTIONS["Temp"].set_c_signature() +EXPECTED_SECTIONS["Temp"].set_i_header_size(148) +EXPECTED_SECTIONS["Temp"].set_i_header_version(2) +EXPECTED_SECTIONS["Temp"].set_wc_section_type("Temp") +EXPECTED_SECTIONS["Temp"].set_i_section_version(1) +EXPECTED_SECTIONS["Temp"].set_e_relationship_type(1) +EXPECTED_SECTIONS["Temp"].set_e_record_type(1) +EXPECTED_SECTIONS["Temp"].set_e_record_data_type(3) +EXPECTED_SECTIONS["Temp"].set_i_data_type_size(32) +EXPECTED_SECTIONS["Temp"].set_i_record_size(4) +EXPECTED_SECTIONS["Temp"].set_wc_data_unit("K") +EXPECTED_SECTIONS["Temp"].set_accepted_units(["K"]) + + +EXPECTED_SECTIONS["AmbTemp"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["AmbTemp"].set_section_name("AmbTemp") +EXPECTED_SECTIONS["AmbTemp"].set_c_signature() +EXPECTED_SECTIONS["AmbTemp"].set_i_header_size(148) +EXPECTED_SECTIONS["AmbTemp"].set_i_header_version(2) +EXPECTED_SECTIONS["AmbTemp"].set_wc_section_type("AmbTemp") +EXPECTED_SECTIONS["AmbTemp"].set_i_section_version(1) +EXPECTED_SECTIONS["AmbTemp"].set_e_relationship_type(1) +EXPECTED_SECTIONS["AmbTemp"].set_e_record_type(1) +EXPECTED_SECTIONS["AmbTemp"].set_e_record_data_type(3) +EXPECTED_SECTIONS["AmbTemp"].set_i_data_type_size(32) +EXPECTED_SECTIONS["AmbTemp"].set_i_record_size(4) +EXPECTED_SECTIONS["AmbTemp"].set_wc_data_unit("C") +EXPECTED_SECTIONS["AmbTemp"].set_accepted_units(["C"]) + +EXPECTED_SECTIONS["laserx"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["laserx"].set_section_name("laserx") +EXPECTED_SECTIONS["laserx"].set_c_signature() +EXPECTED_SECTIONS["laserx"].set_i_header_size(148) +EXPECTED_SECTIONS["laserx"].set_i_header_version(2) +EXPECTED_SECTIONS["laserx"].set_wc_section_type("laserx") +EXPECTED_SECTIONS["laserx"].set_i_section_version(1) +EXPECTED_SECTIONS["laserx"].set_e_relationship_type(1) +EXPECTED_SECTIONS["laserx"].set_e_record_type(1) +EXPECTED_SECTIONS["laserx"].set_e_record_data_type(1) +EXPECTED_SECTIONS["laserx"].set_i_data_type_size(32) +EXPECTED_SECTIONS["laserx"].set_i_record_size(4) +EXPECTED_SECTIONS["laserx"].set_wc_data_unit("") + +EXPECTED_SECTIONS["lasery"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["lasery"].set_section_name("lasery") +EXPECTED_SECTIONS["lasery"].set_c_signature() +EXPECTED_SECTIONS["lasery"].set_i_header_size(148) +EXPECTED_SECTIONS["lasery"].set_i_header_version(2) +EXPECTED_SECTIONS["lasery"].set_wc_section_type("lasery") +EXPECTED_SECTIONS["lasery"].set_i_section_version(1) +EXPECTED_SECTIONS["lasery"].set_e_relationship_type(1) +EXPECTED_SECTIONS["lasery"].set_e_record_type(1) +EXPECTED_SECTIONS["lasery"].set_e_record_data_type(1) +EXPECTED_SECTIONS["lasery"].set_i_data_type_size(32) +EXPECTED_SECTIONS["lasery"].set_i_record_size(4) +EXPECTED_SECTIONS["lasery"].set_wc_data_unit("") + +EXPECTED_SECTIONS["laserz"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["laserz"].set_section_name("laserz") +EXPECTED_SECTIONS["laserz"].set_c_signature() +EXPECTED_SECTIONS["laserz"].set_i_header_size(148) +EXPECTED_SECTIONS["laserz"].set_i_header_version(2) +EXPECTED_SECTIONS["laserz"].set_wc_section_type("laserz") +EXPECTED_SECTIONS["laserz"].set_i_section_version(1) +EXPECTED_SECTIONS["laserz"].set_e_relationship_type(1) +EXPECTED_SECTIONS["laserz"].set_e_record_type(1) +EXPECTED_SECTIONS["laserz"].set_e_record_data_type(1) +EXPECTED_SECTIONS["laserz"].set_i_data_type_size(32) +EXPECTED_SECTIONS["laserz"].set_i_record_size(4) +EXPECTED_SECTIONS["laserz"].set_wc_data_unit("") + +EXPECTED_SECTIONS["laserpower"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["laserpower"].set_section_name("laserpower") +EXPECTED_SECTIONS["laserpower"].set_c_signature() +EXPECTED_SECTIONS["laserpower"].set_i_header_size(148) +EXPECTED_SECTIONS["laserpower"].set_i_header_version(2) +EXPECTED_SECTIONS["laserpower"].set_wc_section_type("laserpower") +EXPECTED_SECTIONS["laserpower"].set_i_section_version(1) +EXPECTED_SECTIONS["laserpower"].set_e_relationship_type(1) +EXPECTED_SECTIONS["laserpower"].set_e_record_type(1) +EXPECTED_SECTIONS["laserpower"].set_e_record_data_type(3) +EXPECTED_SECTIONS["laserpower"].set_i_data_type_size(32) +EXPECTED_SECTIONS["laserpower"].set_i_record_size(4) +EXPECTED_SECTIONS["laserpower"].set_wc_data_unit("") + +EXPECTED_SECTIONS["FractureGuard"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["FractureGuard"].set_section_name("FractureGuard") +EXPECTED_SECTIONS["FractureGuard"].set_c_signature() +EXPECTED_SECTIONS["FractureGuard"].set_i_header_size(148) +EXPECTED_SECTIONS["FractureGuard"].set_i_header_version(2) +EXPECTED_SECTIONS["FractureGuard"].set_wc_section_type("FractureGuard") +EXPECTED_SECTIONS["FractureGuard"].set_i_section_version(1) +EXPECTED_SECTIONS["FractureGuard"].set_e_relationship_type(1) +EXPECTED_SECTIONS["FractureGuard"].set_e_record_type(1) +EXPECTED_SECTIONS["FractureGuard"].set_e_record_data_type(2) +EXPECTED_SECTIONS["FractureGuard"].set_i_data_type_size(16) +EXPECTED_SECTIONS["FractureGuard"].set_i_record_size(2) +EXPECTED_SECTIONS["FractureGuard"].set_wc_data_unit("") + +EXPECTED_SECTIONS["Noise"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["Noise"].set_section_name("Noise") +EXPECTED_SECTIONS["Noise"].set_c_signature() +EXPECTED_SECTIONS["Noise"].set_i_header_size(148) +EXPECTED_SECTIONS["Noise"].set_i_header_version(2) +EXPECTED_SECTIONS["Noise"].set_wc_section_type("Noise") +EXPECTED_SECTIONS["Noise"].set_i_section_version(1) +EXPECTED_SECTIONS["Noise"].set_e_relationship_type(1) +EXPECTED_SECTIONS["Noise"].set_e_record_type(1) +EXPECTED_SECTIONS["Noise"].set_e_record_data_type(3) +EXPECTED_SECTIONS["Noise"].set_i_data_type_size(32) +EXPECTED_SECTIONS["Noise"].set_i_record_size(4) +EXPECTED_SECTIONS["Noise"].set_wc_data_unit("ions") +EXPECTED_SECTIONS["Noise"].set_accepted_units(["", "ions"]) + +EXPECTED_SECTIONS["Uniformity"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["Uniformity"].set_section_name("Uniformity") +EXPECTED_SECTIONS["Uniformity"].set_c_signature() +EXPECTED_SECTIONS["Uniformity"].set_i_header_size(148) +EXPECTED_SECTIONS["Uniformity"].set_i_header_version(2) +EXPECTED_SECTIONS["Uniformity"].set_wc_section_type("Uniformity") +EXPECTED_SECTIONS["Uniformity"].set_i_section_version(1) +EXPECTED_SECTIONS["Uniformity"].set_e_relationship_type(1) +EXPECTED_SECTIONS["Uniformity"].set_e_record_type(1) +EXPECTED_SECTIONS["Uniformity"].set_e_record_data_type(3) +EXPECTED_SECTIONS["Uniformity"].set_i_data_type_size(32) +EXPECTED_SECTIONS["Uniformity"].set_i_record_size(4) +EXPECTED_SECTIONS["Uniformity"].set_wc_data_unit("") + +EXPECTED_SECTIONS["tofc"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["tofc"].set_section_name("tofc") +EXPECTED_SECTIONS["tofc"].set_c_signature() +EXPECTED_SECTIONS["tofc"].set_i_header_size(148) +EXPECTED_SECTIONS["tofc"].set_i_header_version(2) +EXPECTED_SECTIONS["tofc"].set_wc_section_type("tofc") +EXPECTED_SECTIONS["tofc"].set_i_section_version(1) +EXPECTED_SECTIONS["tofc"].set_e_relationship_type(1) +EXPECTED_SECTIONS["tofc"].set_e_record_type(1) +EXPECTED_SECTIONS["tofc"].set_e_record_data_type(3) +EXPECTED_SECTIONS["tofc"].set_i_data_type_size(32) +EXPECTED_SECTIONS["tofc"].set_i_record_size(4) +EXPECTED_SECTIONS["tofc"].set_wc_data_unit("ns") +EXPECTED_SECTIONS["tofc"].set_accepted_units(["ns"]) + +EXPECTED_SECTIONS["tofb"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["tofb"].set_section_name("tofb") +EXPECTED_SECTIONS["tofb"].set_c_signature() +EXPECTED_SECTIONS["tofb"].set_i_header_size(148) +EXPECTED_SECTIONS["tofb"].set_i_header_version(2) +EXPECTED_SECTIONS["tofb"].set_wc_section_type("tofb") +EXPECTED_SECTIONS["tofb"].set_i_section_version(1) +EXPECTED_SECTIONS["tofb"].set_e_relationship_type(1) +EXPECTED_SECTIONS["tofb"].set_e_record_type(1) +EXPECTED_SECTIONS["tofb"].set_e_record_data_type(3) +EXPECTED_SECTIONS["tofb"].set_i_data_type_size(32) +EXPECTED_SECTIONS["tofb"].set_i_record_size(4) +EXPECTED_SECTIONS["tofb"].set_wc_data_unit("ns") +EXPECTED_SECTIONS["tofb"].set_accepted_units(["ns"]) + +EXPECTED_SECTIONS["xs"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["xs"].set_section_name("xs") +EXPECTED_SECTIONS["xs"].set_c_signature() +EXPECTED_SECTIONS["xs"].set_i_header_size(148) +EXPECTED_SECTIONS["xs"].set_i_header_version(2) +EXPECTED_SECTIONS["xs"].set_wc_section_type("xs") +EXPECTED_SECTIONS["xs"].set_i_section_version(1) +EXPECTED_SECTIONS["xs"].set_e_relationship_type(1) +EXPECTED_SECTIONS["xs"].set_e_record_type(1) +EXPECTED_SECTIONS["xs"].set_e_record_data_type(3) +EXPECTED_SECTIONS["xs"].set_i_data_type_size(32) +EXPECTED_SECTIONS["xs"].set_i_record_size(4) +EXPECTED_SECTIONS["xs"].set_wc_data_unit("nm") +EXPECTED_SECTIONS["xs"].set_accepted_units(["nm"]) + +EXPECTED_SECTIONS["ys"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["ys"].set_section_name("ys") +EXPECTED_SECTIONS["ys"].set_c_signature() +EXPECTED_SECTIONS["ys"].set_i_header_size(148) +EXPECTED_SECTIONS["ys"].set_i_header_version(2) +EXPECTED_SECTIONS["ys"].set_wc_section_type("ys") +EXPECTED_SECTIONS["ys"].set_i_section_version(1) +EXPECTED_SECTIONS["ys"].set_e_relationship_type(1) +EXPECTED_SECTIONS["ys"].set_e_record_type(1) +EXPECTED_SECTIONS["ys"].set_e_record_data_type(3) +EXPECTED_SECTIONS["ys"].set_i_data_type_size(32) +EXPECTED_SECTIONS["ys"].set_i_record_size(4) +EXPECTED_SECTIONS["ys"].set_wc_data_unit("nm") +EXPECTED_SECTIONS["ys"].set_accepted_units(["nm"]) + +EXPECTED_SECTIONS["zs"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["zs"].set_section_name("zs") +EXPECTED_SECTIONS["zs"].set_c_signature() +EXPECTED_SECTIONS["zs"].set_i_header_size(148) +EXPECTED_SECTIONS["zs"].set_i_header_version(2) +EXPECTED_SECTIONS["zs"].set_wc_section_type("zs") +EXPECTED_SECTIONS["zs"].set_i_section_version(1) +EXPECTED_SECTIONS["zs"].set_e_relationship_type(1) +EXPECTED_SECTIONS["zs"].set_e_record_type(1) +EXPECTED_SECTIONS["zs"].set_e_record_data_type(3) +EXPECTED_SECTIONS["zs"].set_i_data_type_size(32) +EXPECTED_SECTIONS["zs"].set_i_record_size(4) +EXPECTED_SECTIONS["zs"].set_wc_data_unit("nm") +EXPECTED_SECTIONS["zs"].set_accepted_units(["nm"]) + +EXPECTED_SECTIONS["rTip"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["rTip"].set_section_name("rTip") +EXPECTED_SECTIONS["rTip"].set_c_signature() +EXPECTED_SECTIONS["rTip"].set_i_header_size(148) +EXPECTED_SECTIONS["rTip"].set_i_header_version(2) +EXPECTED_SECTIONS["rTip"].set_wc_section_type("rTip") +EXPECTED_SECTIONS["rTip"].set_i_section_version(1) +EXPECTED_SECTIONS["rTip"].set_e_relationship_type(1) +EXPECTED_SECTIONS["rTip"].set_e_record_type(1) +EXPECTED_SECTIONS["rTip"].set_e_record_data_type(3) +EXPECTED_SECTIONS["rTip"].set_i_data_type_size(32) +EXPECTED_SECTIONS["rTip"].set_i_record_size(4) +EXPECTED_SECTIONS["rTip"].set_wc_data_unit("nm") +EXPECTED_SECTIONS["rTip"].set_accepted_units(["nm"]) + +EXPECTED_SECTIONS["zApex"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["zApex"].set_section_name("zApex") +EXPECTED_SECTIONS["zApex"].set_c_signature() +EXPECTED_SECTIONS["zApex"].set_i_header_size(148) +EXPECTED_SECTIONS["zApex"].set_i_header_version(2) +EXPECTED_SECTIONS["zApex"].set_wc_section_type("zApex") +EXPECTED_SECTIONS["zApex"].set_i_section_version(1) +EXPECTED_SECTIONS["zApex"].set_e_relationship_type(1) +EXPECTED_SECTIONS["zApex"].set_e_record_type(1) +EXPECTED_SECTIONS["zApex"].set_e_record_data_type(3) +EXPECTED_SECTIONS["zApex"].set_i_data_type_size(32) +EXPECTED_SECTIONS["zApex"].set_i_record_size(4) +EXPECTED_SECTIONS["zApex"].set_wc_data_unit("nm") +EXPECTED_SECTIONS["zApex"].set_accepted_units(["nm"]) + +EXPECTED_SECTIONS["zSphereCorr"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["zSphereCorr"].set_section_name("zSphereCorr") +EXPECTED_SECTIONS["zSphereCorr"].set_c_signature() +EXPECTED_SECTIONS["zSphereCorr"].set_i_header_size(148) +EXPECTED_SECTIONS["zSphereCorr"].set_i_header_version(2) +EXPECTED_SECTIONS["zSphereCorr"].set_wc_section_type("zSphereCorr") +EXPECTED_SECTIONS["zSphereCorr"].set_i_section_version(1) +EXPECTED_SECTIONS["zSphereCorr"].set_e_relationship_type(1) +EXPECTED_SECTIONS["zSphereCorr"].set_e_record_type(1) +EXPECTED_SECTIONS["zSphereCorr"].set_e_record_data_type(3) +EXPECTED_SECTIONS["zSphereCorr"].set_i_data_type_size(32) +EXPECTED_SECTIONS["zSphereCorr"].set_i_record_size(4) +EXPECTED_SECTIONS["zSphereCorr"].set_wc_data_unit("nm") +EXPECTED_SECTIONS["zSphereCorr"].set_accepted_units(["nm"]) # the next three seem to (have been /were used for AMETEK development purposes -EXPECTED_SECTIONS['Position_0'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['Position_0'].set_section_name('Position_0') -EXPECTED_SECTIONS['Position_0'].set_c_signature() -EXPECTED_SECTIONS['Position_0'].set_i_header_size(148 + 6 * 4) -EXPECTED_SECTIONS['Position_0'].set_i_header_version(2) -EXPECTED_SECTIONS['Position_0'].set_wc_section_type('Position_0') -EXPECTED_SECTIONS['Position_0'].set_i_section_version(1) -EXPECTED_SECTIONS['Position_0'].set_e_relationship_type(1) -EXPECTED_SECTIONS['Position_0'].set_e_record_type(1) -EXPECTED_SECTIONS['Position_0'].set_e_record_data_type(3) -EXPECTED_SECTIONS['Position_0'].set_i_data_type_size(32) -EXPECTED_SECTIONS['Position_0'].set_i_record_size(12) -EXPECTED_SECTIONS['Position_0'].set_wc_data_unit('') - -EXPECTED_SECTIONS['Position_1'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['Position_1'].set_section_name('Position_1') -EXPECTED_SECTIONS['Position_1'].set_c_signature() -EXPECTED_SECTIONS['Position_1'].set_i_header_size(148 + 6 * 4) -EXPECTED_SECTIONS['Position_1'].set_i_header_version(2) -EXPECTED_SECTIONS['Position_1'].set_wc_section_type('Position_1') -EXPECTED_SECTIONS['Position_1'].set_i_section_version(1) -EXPECTED_SECTIONS['Position_1'].set_e_relationship_type(1) -EXPECTED_SECTIONS['Position_1'].set_e_record_type(1) -EXPECTED_SECTIONS['Position_1'].set_e_record_data_type(3) -EXPECTED_SECTIONS['Position_1'].set_i_data_type_size(32) -EXPECTED_SECTIONS['Position_1'].set_i_record_size(12) -EXPECTED_SECTIONS['Position_1'].set_wc_data_unit('') - -EXPECTED_SECTIONS['Position_2'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['Position_2'].set_section_name('Position_2') -EXPECTED_SECTIONS['Position_2'].set_c_signature() -EXPECTED_SECTIONS['Position_2'].set_i_header_size(148 + 6 * 4) -EXPECTED_SECTIONS['Position_2'].set_i_header_version(2) -EXPECTED_SECTIONS['Position_2'].set_wc_section_type('Position_2') -EXPECTED_SECTIONS['Position_2'].set_i_section_version(1) -EXPECTED_SECTIONS['Position_2'].set_e_relationship_type(1) -EXPECTED_SECTIONS['Position_2'].set_e_record_type(1) -EXPECTED_SECTIONS['Position_2'].set_e_record_data_type(3) -EXPECTED_SECTIONS['Position_2'].set_i_data_type_size(32) -EXPECTED_SECTIONS['Position_2'].set_i_record_size(12) -EXPECTED_SECTIONS['Position_2'].set_wc_data_unit('') - -EXPECTED_SECTIONS['XDet_mm'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['XDet_mm'].set_section_name('XDet_mm') -EXPECTED_SECTIONS['XDet_mm'].set_c_signature() -EXPECTED_SECTIONS['XDet_mm'].set_i_header_size(148) -EXPECTED_SECTIONS['XDet_mm'].set_i_header_version(2) -EXPECTED_SECTIONS['XDet_mm'].set_wc_section_type('XDet_mm') -EXPECTED_SECTIONS['XDet_mm'].set_i_section_version(1) -EXPECTED_SECTIONS['XDet_mm'].set_e_relationship_type(1) -EXPECTED_SECTIONS['XDet_mm'].set_e_record_type(1) -EXPECTED_SECTIONS['XDet_mm'].set_e_record_data_type(3) -EXPECTED_SECTIONS['XDet_mm'].set_i_data_type_size(32) -EXPECTED_SECTIONS['XDet_mm'].set_i_record_size(4) -EXPECTED_SECTIONS['XDet_mm'].set_wc_data_unit('mm') -EXPECTED_SECTIONS['XDet_mm'].set_accepted_units(['mm']) - -EXPECTED_SECTIONS['YDet_mm'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['YDet_mm'].set_section_name('YDet_mm') -EXPECTED_SECTIONS['YDet_mm'].set_c_signature() -EXPECTED_SECTIONS['YDet_mm'].set_i_header_size(148) -EXPECTED_SECTIONS['YDet_mm'].set_i_header_version(2) -EXPECTED_SECTIONS['YDet_mm'].set_wc_section_type('YDet_mm') -EXPECTED_SECTIONS['YDet_mm'].set_i_section_version(1) -EXPECTED_SECTIONS['YDet_mm'].set_e_relationship_type(1) -EXPECTED_SECTIONS['YDet_mm'].set_e_record_type(1) -EXPECTED_SECTIONS['YDet_mm'].set_e_record_data_type(3) -EXPECTED_SECTIONS['YDet_mm'].set_i_data_type_size(32) -EXPECTED_SECTIONS['YDet_mm'].set_i_record_size(4) -EXPECTED_SECTIONS['YDet_mm'].set_wc_data_unit('mm') -EXPECTED_SECTIONS['YDet_mm'].set_accepted_units(['mm']) - -EXPECTED_SECTIONS['Multiplicity'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['Multiplicity'].set_section_name('Multiplicity') -EXPECTED_SECTIONS['Multiplicity'].set_c_signature() -EXPECTED_SECTIONS['Multiplicity'].set_i_header_size(148) -EXPECTED_SECTIONS['Multiplicity'].set_i_header_version(2) -EXPECTED_SECTIONS['Multiplicity'].set_wc_section_type('Multiplicity') -EXPECTED_SECTIONS['Multiplicity'].set_i_section_version(1) -EXPECTED_SECTIONS['Multiplicity'].set_e_relationship_type(1) -EXPECTED_SECTIONS['Multiplicity'].set_e_record_type(1) -EXPECTED_SECTIONS['Multiplicity'].set_e_record_data_type(1) -EXPECTED_SECTIONS['Multiplicity'].set_i_data_type_size(32) -EXPECTED_SECTIONS['Multiplicity'].set_i_record_size(4) -EXPECTED_SECTIONS['Multiplicity'].set_wc_data_unit('') - -EXPECTED_SECTIONS['Vap'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['Vap'].set_section_name('Vap') -EXPECTED_SECTIONS['Vap'].set_c_signature() -EXPECTED_SECTIONS['Vap'].set_i_header_size(148) -EXPECTED_SECTIONS['Vap'].set_i_header_version(2) -EXPECTED_SECTIONS['Vap'].set_wc_section_type('Vap') -EXPECTED_SECTIONS['Vap'].set_i_section_version(1) -EXPECTED_SECTIONS['Vap'].set_e_relationship_type(1) -EXPECTED_SECTIONS['Vap'].set_e_record_type(1) -EXPECTED_SECTIONS['Vap'].set_e_record_data_type(3) -EXPECTED_SECTIONS['Vap'].set_i_data_type_size(32) -EXPECTED_SECTIONS['Vap'].set_i_record_size(4) -EXPECTED_SECTIONS['Vap'].set_wc_data_unit('V') -EXPECTED_SECTIONS['Vap'].set_accepted_units(['V']) - -EXPECTED_SECTIONS['Detector Coordinates'] = AptFileSectionMetadata() -EXPECTED_SECTIONS['Detector Coordinates'].set_section_name( - 'Detector Coordinates') -EXPECTED_SECTIONS['Detector Coordinates'].set_c_signature() -EXPECTED_SECTIONS['Detector Coordinates'].set_i_header_size(148) -EXPECTED_SECTIONS['Detector Coordinates'].set_i_header_version(2) -EXPECTED_SECTIONS['Detector Coordinates'].set_wc_section_type( - 'Detector Coordinates') -EXPECTED_SECTIONS['Detector Coordinates'].set_i_section_version(1) -EXPECTED_SECTIONS['Detector Coordinates'].set_e_relationship_type(1) -EXPECTED_SECTIONS['Detector Coordinates'].set_e_record_type(1) -EXPECTED_SECTIONS['Detector Coordinates'].set_e_record_data_type(3) -EXPECTED_SECTIONS['Detector Coordinates'].set_i_data_type_size(32) -EXPECTED_SECTIONS['Detector Coordinates'].set_i_record_size(8) -EXPECTED_SECTIONS['Detector Coordinates'].set_wc_data_unit('mm') -EXPECTED_SECTIONS['Detector Coordinates'].set_accepted_units(['mm']) - -# there is at least a hint that some time ago this section's wcDataUnit was '' +EXPECTED_SECTIONS["Position_0"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["Position_0"].set_section_name("Position_0") +EXPECTED_SECTIONS["Position_0"].set_c_signature() +EXPECTED_SECTIONS["Position_0"].set_i_header_size(148 + 6 * 4) +EXPECTED_SECTIONS["Position_0"].set_i_header_version(2) +EXPECTED_SECTIONS["Position_0"].set_wc_section_type("Position_0") +EXPECTED_SECTIONS["Position_0"].set_i_section_version(1) +EXPECTED_SECTIONS["Position_0"].set_e_relationship_type(1) +EXPECTED_SECTIONS["Position_0"].set_e_record_type(1) +EXPECTED_SECTIONS["Position_0"].set_e_record_data_type(3) +EXPECTED_SECTIONS["Position_0"].set_i_data_type_size(32) +EXPECTED_SECTIONS["Position_0"].set_i_record_size(12) +EXPECTED_SECTIONS["Position_0"].set_wc_data_unit("") + +EXPECTED_SECTIONS["Position_1"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["Position_1"].set_section_name("Position_1") +EXPECTED_SECTIONS["Position_1"].set_c_signature() +EXPECTED_SECTIONS["Position_1"].set_i_header_size(148 + 6 * 4) +EXPECTED_SECTIONS["Position_1"].set_i_header_version(2) +EXPECTED_SECTIONS["Position_1"].set_wc_section_type("Position_1") +EXPECTED_SECTIONS["Position_1"].set_i_section_version(1) +EXPECTED_SECTIONS["Position_1"].set_e_relationship_type(1) +EXPECTED_SECTIONS["Position_1"].set_e_record_type(1) +EXPECTED_SECTIONS["Position_1"].set_e_record_data_type(3) +EXPECTED_SECTIONS["Position_1"].set_i_data_type_size(32) +EXPECTED_SECTIONS["Position_1"].set_i_record_size(12) +EXPECTED_SECTIONS["Position_1"].set_wc_data_unit("") + +EXPECTED_SECTIONS["Position_2"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["Position_2"].set_section_name("Position_2") +EXPECTED_SECTIONS["Position_2"].set_c_signature() +EXPECTED_SECTIONS["Position_2"].set_i_header_size(148 + 6 * 4) +EXPECTED_SECTIONS["Position_2"].set_i_header_version(2) +EXPECTED_SECTIONS["Position_2"].set_wc_section_type("Position_2") +EXPECTED_SECTIONS["Position_2"].set_i_section_version(1) +EXPECTED_SECTIONS["Position_2"].set_e_relationship_type(1) +EXPECTED_SECTIONS["Position_2"].set_e_record_type(1) +EXPECTED_SECTIONS["Position_2"].set_e_record_data_type(3) +EXPECTED_SECTIONS["Position_2"].set_i_data_type_size(32) +EXPECTED_SECTIONS["Position_2"].set_i_record_size(12) +EXPECTED_SECTIONS["Position_2"].set_wc_data_unit("") + +EXPECTED_SECTIONS["XDet_mm"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["XDet_mm"].set_section_name("XDet_mm") +EXPECTED_SECTIONS["XDet_mm"].set_c_signature() +EXPECTED_SECTIONS["XDet_mm"].set_i_header_size(148) +EXPECTED_SECTIONS["XDet_mm"].set_i_header_version(2) +EXPECTED_SECTIONS["XDet_mm"].set_wc_section_type("XDet_mm") +EXPECTED_SECTIONS["XDet_mm"].set_i_section_version(1) +EXPECTED_SECTIONS["XDet_mm"].set_e_relationship_type(1) +EXPECTED_SECTIONS["XDet_mm"].set_e_record_type(1) +EXPECTED_SECTIONS["XDet_mm"].set_e_record_data_type(3) +EXPECTED_SECTIONS["XDet_mm"].set_i_data_type_size(32) +EXPECTED_SECTIONS["XDet_mm"].set_i_record_size(4) +EXPECTED_SECTIONS["XDet_mm"].set_wc_data_unit("mm") +EXPECTED_SECTIONS["XDet_mm"].set_accepted_units(["mm"]) + +EXPECTED_SECTIONS["YDet_mm"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["YDet_mm"].set_section_name("YDet_mm") +EXPECTED_SECTIONS["YDet_mm"].set_c_signature() +EXPECTED_SECTIONS["YDet_mm"].set_i_header_size(148) +EXPECTED_SECTIONS["YDet_mm"].set_i_header_version(2) +EXPECTED_SECTIONS["YDet_mm"].set_wc_section_type("YDet_mm") +EXPECTED_SECTIONS["YDet_mm"].set_i_section_version(1) +EXPECTED_SECTIONS["YDet_mm"].set_e_relationship_type(1) +EXPECTED_SECTIONS["YDet_mm"].set_e_record_type(1) +EXPECTED_SECTIONS["YDet_mm"].set_e_record_data_type(3) +EXPECTED_SECTIONS["YDet_mm"].set_i_data_type_size(32) +EXPECTED_SECTIONS["YDet_mm"].set_i_record_size(4) +EXPECTED_SECTIONS["YDet_mm"].set_wc_data_unit("mm") +EXPECTED_SECTIONS["YDet_mm"].set_accepted_units(["mm"]) + +EXPECTED_SECTIONS["Multiplicity"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["Multiplicity"].set_section_name("Multiplicity") +EXPECTED_SECTIONS["Multiplicity"].set_c_signature() +EXPECTED_SECTIONS["Multiplicity"].set_i_header_size(148) +EXPECTED_SECTIONS["Multiplicity"].set_i_header_version(2) +EXPECTED_SECTIONS["Multiplicity"].set_wc_section_type("Multiplicity") +EXPECTED_SECTIONS["Multiplicity"].set_i_section_version(1) +EXPECTED_SECTIONS["Multiplicity"].set_e_relationship_type(1) +EXPECTED_SECTIONS["Multiplicity"].set_e_record_type(1) +EXPECTED_SECTIONS["Multiplicity"].set_e_record_data_type(1) +EXPECTED_SECTIONS["Multiplicity"].set_i_data_type_size(32) +EXPECTED_SECTIONS["Multiplicity"].set_i_record_size(4) +EXPECTED_SECTIONS["Multiplicity"].set_wc_data_unit("") + +EXPECTED_SECTIONS["Vap"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["Vap"].set_section_name("Vap") +EXPECTED_SECTIONS["Vap"].set_c_signature() +EXPECTED_SECTIONS["Vap"].set_i_header_size(148) +EXPECTED_SECTIONS["Vap"].set_i_header_version(2) +EXPECTED_SECTIONS["Vap"].set_wc_section_type("Vap") +EXPECTED_SECTIONS["Vap"].set_i_section_version(1) +EXPECTED_SECTIONS["Vap"].set_e_relationship_type(1) +EXPECTED_SECTIONS["Vap"].set_e_record_type(1) +EXPECTED_SECTIONS["Vap"].set_e_record_data_type(3) +EXPECTED_SECTIONS["Vap"].set_i_data_type_size(32) +EXPECTED_SECTIONS["Vap"].set_i_record_size(4) +EXPECTED_SECTIONS["Vap"].set_wc_data_unit("V") +EXPECTED_SECTIONS["Vap"].set_accepted_units(["V"]) + +EXPECTED_SECTIONS["Detector Coordinates"] = AptFileSectionMetadata() +EXPECTED_SECTIONS["Detector Coordinates"].set_section_name( + "Detector Coordinates") +EXPECTED_SECTIONS["Detector Coordinates"].set_c_signature() +EXPECTED_SECTIONS["Detector Coordinates"].set_i_header_size(148) +EXPECTED_SECTIONS["Detector Coordinates"].set_i_header_version(2) +EXPECTED_SECTIONS["Detector Coordinates"].set_wc_section_type( + "Detector Coordinates") +EXPECTED_SECTIONS["Detector Coordinates"].set_i_section_version(1) +EXPECTED_SECTIONS["Detector Coordinates"].set_e_relationship_type(1) +EXPECTED_SECTIONS["Detector Coordinates"].set_e_record_type(1) +EXPECTED_SECTIONS["Detector Coordinates"].set_e_record_data_type(3) +EXPECTED_SECTIONS["Detector Coordinates"].set_i_data_type_size(32) +EXPECTED_SECTIONS["Detector Coordinates"].set_i_record_size(8) +EXPECTED_SECTIONS["Detector Coordinates"].set_wc_data_unit("mm") +EXPECTED_SECTIONS["Detector Coordinates"].set_accepted_units(["mm"]) + +# there is at least a hint that some time ago this section"s wcDataUnit was "" # sections whose formatting and purpose is completely unclear # Var44 ? magic-in-action? M. K\"uhbach, could well for AMETEK development only -# EXPECTED_SECTIONS['Var44'].set_section_name('Var44') +# EXPECTED_SECTIONS["Var44"].set_section_name("Var44") # deprecated sections or sections with detected inconsistencies across versions # Vref vs Voltage branch issue -EXPECTED_SECTIONS['Vref'] = EXPECTED_SECTIONS['Voltage'] -EXPECTED_SECTIONS['Vref'].set_wc_data_unit('V') -EXPECTED_SECTIONS['Vref'].set_accepted_units(['V']) +EXPECTED_SECTIONS["Vref"] = EXPECTED_SECTIONS["Voltage"] +EXPECTED_SECTIONS["Vref"].set_wc_data_unit("V") +EXPECTED_SECTIONS["Vref"].set_accepted_units(["V"]) # pulseDelta vs Delta Pulse issue # at least in one case a section Delta Pulse appeared @@ -695,5 +695,5 @@ # other comments and issues # Need to check APSuite version and build number -# 'Voltage' section, M. K\"uhbach: expect to have units but example *.apt files -# from flat test do not encode a unit in the 'Voltage' section +# "Voltage" section, M. K\"uhbach: expect to have units but example *.apt files +# from flat test do not encode a unit in the "Voltage" section diff --git a/ifes_apt_tc_data_modeling/apt/apt6_utils.py b/ifes_apt_tc_data_modeling/apt/apt6_utils.py index 5ea24b3..d1e3289 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_utils.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_utils.py @@ -20,6 +20,9 @@ import numpy as np +APT_SECTION_NAME_MAX_LENGTH = 32 +APT_SECTION_TYPE_MAX_LENGTH = 32 + def np_uint16_to_string(uint16_array: np.ndarray) -> str: """Create string from array of uint16 numbers (UTF-16).""" diff --git a/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py b/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py index 6c7b89c..6fc710d 100644 --- a/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py +++ b/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py @@ -18,6 +18,8 @@ """Reader for FAU/Erlangen's HDF5-based formats introduced with the pyccapt library.""" +# pylint: disable=fixme + from typing import Dict import os import h5py @@ -30,17 +32,19 @@ from ifes_apt_tc_data_modeling.utils.utils import isotope_to_hash, \ isotope_vector_to_nuclid_list, MAX_NUMBER_OF_ATOMS_PER_ION from ifes_apt_tc_data_modeling.utils.molecular_ions import get_chemical_symbols +# from ifes_apt_tc_data_modeling.utils.combinatorics import apply_combinatorics # this implementation focuses on the following state of the pyccapt repository # https://github.com/mmonajem/pyccapt/commit/e955beb4f2627befb8b4d26f2e74e4c52e00394e # during the course of an atom probe measurement and analysis with FAU/Erlangen's Oxcart instrument # several HDF5 files are generated with essentially two software tools. One is pyccapt which has a -# a control module, a calibration module (where the voltage/bowl calibration and reconstruction is performed), -# and a module/functionalities to document ranging i.e. ion type identification made -# The other software typically used by the FAU/Erlangen atom probe group is Atom Probe Toolbox; -# instructed as a set of Matlab live scripts this toolbox offers data analysis functionalities, -# results are stored via an HDF5 file +# a control module plus a calibration module (whereby the voltage/bowl calibration and reconstruction +# is performed), the other one is a module/functionality to document ranging i.e. made ion type +# definitions. These results can be processed further with the FAU/Erlangen Matlab Atom Probe Toolbox; +# instructed as a set of Matlab live scripts this toolbox offers data analysis functionalities. +# Results obtained with this Atom Probe Toolbox are stored via an HDF5 file but currently not parsed +# by this pyccapt parser # specific comments # pyccapt/control @@ -48,55 +52,69 @@ # pyccapt/calibration # unfortunately the generated HDF5 file has internally no provenance information -# with which pyccapt version it was generated, therefore developers of pyccapt should -# rather write the content of the HDF5 file explicitly dset by dset e.g. using h5py instead +# with which pyccapt version it was generated. Therefore, developers of pyccapt should rather +# write the content of the HDF5 file explicitly dset by dset e.g. using h5py instead # of the pandas HDF5 dump convenience functionality # of course pandas stores its own version but that is not conclusive enough to infer with # which pyccapt version and most importantly from which other context the file was generated # this is an aspect of the FAIR RDM principles which the pyccapt approach currently ignores +SUPPORTED_PYCCAPT_VERSION = "e955beb4f2627befb8b4d26f2e74e4c52e00394e" + + +def get_isotope_vector_from_fau_list(elements, complexs, isotopes) -> np.ndarray: + """Compute isotope_vector from specific representation used at FAU/Erlangen.""" + # TODO:: add raise ValueError checks + ivec = np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,), np.uint16) + hashvector: list = [] + for idxj in np.arange(0, len(elements)): + symbol = elements[idxj] + if symbol in get_chemical_symbols(): + proton_number = atomic_numbers[symbol] + neutron_number = isotopes[idxj] - proton_number + hashvector.extend([isotope_to_hash(proton_number, neutron_number)] * complexs[idxj]) + ivec[0:len(hashvector)] = np.sort(np.asarray(hashvector, np.uint16), kind="stable")[::-1] + return ivec class ReadPyccaptControlFileFormat(): """Read FAU/Erlangen pyccapt (controle module) HDF5 file format.""" - def __init__(self, filename: str): - assert len(filename) > 2, "H5 file incorrect filename ending!" - assert filename.lower().endswith(".h5") or filename.lower().endswith(".hdf5"), \ - "HDF5 file incorrect file type!" - self.filename = filename - - self.filesize = os.path.getsize(self.filename) + def __init__(self, file_path: str): + if (file_path.lower().endswith(".h5") is False) and (file_path.lower().endswith(".hdf5") is False): + raise ImportError("WARNING::HDF5 file incorrect file_path ending or file type!") + self.file_path = file_path + self.file_size = os.path.getsize(self.file_path) self.number_of_events = None - self.version = "e955beb4f2627befb8b4d26f2e74e4c52e00394e" + self.version = SUPPORTED_PYCCAPT_VERSION # check that the formatting matches that of an pyccapt control module output HDF5 file - with h5py.File(self.filename, "r") as h5r: + with h5py.File(self.file_path, "r") as h5r: self.supported = 0 # voting-based required_groups = ["apt", "dld", "tdc"] for req_grpnm in required_groups: if req_grpnm in h5r.keys(): self.supported += 1 if self.supported == 3: - print(f"{self.filename} is a supported pyccapt/control HDF5 file!") + print(f"{self.file_path} is a supported pyccapt/control HDF5 file!") else: - print(f"{self.filename} is not a supported pyccapt/control HDF5 file!") + print(f"{self.file_path} is not a supported pyccapt/control HDF5 file!") return + # parse out relevant pieces of information class ReadPyccaptCalibrationFileFormat(): """Read FAU/Erlangen pyccapt (calibration module) HDF5 file format.""" - def __init__(self, filename: str): - assert len(filename) > 2, "H5 file incorrect filename ending!" - assert filename.lower().endswith(".h5") or filename.lower().endswith(".hdf5"), \ - "HDF5 file incorrect file type!" - self.filename = filename - self.filesize = os.path.getsize(self.filename) + def __init__(self, file_path: str): + if (file_path.lower().endswith(".h5") is False) and (file_path.lower().endswith(".hdf5") is False): + raise ImportError("WARNING::HDF5 file incorrect file_path ending or file type!") + self.file_path = file_path + self.file_size = os.path.getsize(self.file_path) self.number_of_events = None - self.version = "e955beb4f2627befb8b4d26f2e74e4c52e00394e" + self.version = SUPPORTED_PYCCAPT_VERSION self.df: dict = {} - with h5py.File(self.filename, "r") as h5r: + with h5py.File(self.file_path, "r") as h5r: self.supported = 0 # voting-based required_entries = ["df", "df/axis0", "df/axis1", @@ -106,12 +124,12 @@ def __init__(self, filename: str): if entry in h5r.keys(): self.supported += 1 if self.supported == 7: - print(f"{self.filename} is a supported pyccapt/calibration HDF5 file!") + print(f"{self.file_path} is a supported pyccapt/calibration HDF5 file!") else: - print(f"{self.filename} is not a supported pyccapt/calibration HDF5 file!") + print(f"{self.file_path} is not a supported pyccapt/calibration HDF5 file!") return - self.df = pd.read_hdf(self.filename) + self.df = pd.read_hdf(self.file_path) self.number_of_events = len(self.df) def get_named_quantities(self, term: str): @@ -123,8 +141,7 @@ def get_named_quantities(self, term: str): def get_reconstructed_positions(self): """Read xyz columns.""" xyz = NxField() - xyz.values = np.zeros( - [self.number_of_events, 3], np.float32) + xyz.values = np.zeros([self.number_of_events, 3], np.float32) xyz.unit = "nm" dim = 0 @@ -137,8 +154,7 @@ def get_mass_to_charge_state_ratio(self): """Read (calibrated) mass-to-charge-state-ratio column.""" m_n = NxField() - m_n.values = np.zeros( - [self.number_of_events, 1], np.float32) + m_n.values = np.zeros([self.number_of_events, 1], np.float32) m_n.unit = "Da" m_n.values[:, 0] = np.asarray(self.get_named_quantities("mc_c (Da)"), np.float32) @@ -148,18 +164,16 @@ def get_mass_to_charge_state_ratio(self): class ReadPyccaptRangingFileFormat(): """Read FAU/Erlangen pyccapt (ranging module) HDF5 file format.""" - def __init__(self, filename: str): - assert len(filename) > 2, "H5 file incorrect filename ending!" - assert filename.lower().endswith(".h5") or filename.lower().endswith(".hdf5"), \ - "HDF5 file incorrect file type!" - self.filename = filename - - self.filesize = os.path.getsize(self.filename) + def __init__(self, file_path: str): + if (file_path.lower().endswith(".h5") is False) and (file_path.lower().endswith(".hdf5") is False): + raise ImportError("WARNING::HDF5 file incorrect file_path ending or file type!") + self.file_path = file_path + self.file_size = os.path.getsize(self.file_path) self.number_of_events = None - self.version = "e955beb4f2627befb8b4d26f2e74e4c52e00394e" + self.version = SUPPORTED_PYCCAPT_VERSION self.df = None - with h5py.File(self.filename, "r") as h5r: + with h5py.File(self.file_path, "r") as h5r: self.supported = 0 # voting-based required_entries = ["df", "df/axis0", "df/axis1", @@ -170,12 +184,12 @@ def __init__(self, filename: str): if entry in h5r.keys(): self.supported += 1 if self.supported == 9: - print(f"{self.filename} is a supported pyccapt/ranging HDF5 file!") + print(f"{self.file_path} is a supported pyccapt/ranging HDF5 file!") else: - print(f"{self.filename} is not a supported pyccapt/ranging HDF5 file!") + print(f"{self.file_path} is not a supported pyccapt/ranging HDF5 file!") return - self.df = pd.read_hdf(self.filename) + self.df = pd.read_hdf(self.file_path) self.rng: Dict = {} self.rng["molecular_ions"] = [] print(np.shape(self.df)[0]) @@ -184,26 +198,16 @@ def __init__(self, filename: str): if self.df.iloc[idx, 6] == "unranged": continue - elements = self.df.iloc[idx, 6] - complexs = self.df.iloc[idx, 7] - isotopes = self.df.iloc[idx, 8] - # assertions - ivec = np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,), np.uint16) - hashvector: list = [] - for idxj in np.arange(0, len(elements)): - symbol = elements[idxj] - if symbol in get_chemical_symbols(): - proton_number = atomic_numbers[symbol] - neutron_number = isotopes[idxj] - proton_number - hashvector.extend([isotope_to_hash(proton_number, neutron_number)] * complexs[idxj]) - ivec[0:len(hashvector)] = np.sort(np.asarray(hashvector, np.uint16), kind="stable")[::-1] - + ivec = get_isotope_vector_from_fau_list(elements=self.df.iloc[idx, 6], + complexs=self.df.iloc[idx, 7], + isotopes=self.df.iloc[idx, 8]) m_ion = NxIon() m_ion.isotope_vector.values = ivec m_ion.nuclid_list.values = isotope_vector_to_nuclid_list(ivec) m_ion.charge_state.values = np.int8(self.df.iloc[idx, 9]) m_ion.add_range(self.df.iloc[idx, 3], self.df.iloc[idx, 4]) m_ion.update_human_readable_name() + # apply_combinatorics(m_ion) # m_ion.report() self.rng["molecular_ions"].append(m_ion) - print(f"{self.filename} parsed successfully") + print(f"{self.file_path} parsed successfully") From 155c97620448748fe661107ae6be62f988044b6d Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Sun, 31 Dec 2023 14:07:46 +0100 Subject: [PATCH 13/20] Refactoring completed, now testing remains using pynxtools --- ifes_apt_tc_data_modeling/apt/apt6_reader.py | 159 +++++++----------- ifes_apt_tc_data_modeling/csv/csv_reader.py | 2 + ifes_apt_tc_data_modeling/env/env_reader.py | 2 +- ifes_apt_tc_data_modeling/epos/epos_reader.py | 2 + ifes_apt_tc_data_modeling/pos/pos_reader.py | 2 + ifes_apt_tc_data_modeling/rng/rng_reader.py | 2 + ifes_apt_tc_data_modeling/rrng/rrng_reader.py | 2 +- 7 files changed, 75 insertions(+), 96 deletions(-) diff --git a/ifes_apt_tc_data_modeling/apt/apt6_reader.py b/ifes_apt_tc_data_modeling/apt/apt6_reader.py index 9c6ae02..627ce4d 100644 --- a/ifes_apt_tc_data_modeling/apt/apt6_reader.py +++ b/ifes_apt_tc_data_modeling/apt/apt6_reader.py @@ -33,13 +33,12 @@ class ReadAptFileFormat(): """Read AMETEK's open exchange *.apt file format.""" - def __init__(self, filename: str): - if (len(filename) <= 4) or (filename.lower().endswith(".apt") is False): - raise ImportError("WARNING::APT file incorrect filename ending or file type!") - self.filename = filename - - self.filesize = os.path.getsize(self.filename) - print(f"Reading {self.filename} which is {self.filesize} B") + def __init__(self, file_path: str): + if (len(file_path) <= 4) or (file_path.lower().endswith(".apt") is False): + raise ImportError("WARNING::APT file incorrect file_path ending or file type!") + self.file_path = file_path + self.file_size = os.path.getsize(self.file_path) + print(f"Reading {self.file_path} which is {self.file_size} B") self.header_section = None self.byte_offsets: dict = {} @@ -52,16 +51,16 @@ def __init__(self, filename: str): def parse_file_structure(self): """Parse APT file header plus flat collection of metadata/data pairs. - Each pair has a so-called section header and a corresponding raw data - block. Section headers detail the content of the immediately trailing - raw data block. + Each pair has a so-called section header and a corresponding data block. + Section headers detail the content of the immediately trailing data block. An APT file can store none, some, or all of the possible sections. - Furthermore the file can contain additional pieces of information - which this parser cannot read-out because the APT format is maintained - by AMETEK. The AMETEK source code is the only reliable source of - information about which content the sections encode and how these - get formatted when exporting an APT file from APSuite for a specific - version and build number and type of experiment plus + Furthermore, the file can contain additional pieces of information + which this parser currently cannot read-out because the APT format as + not yet all details of the APT file format specification have been shared + by AMETEK/Cameca. Indeed, the IVAS/APSuite source code is currently the only + reliable source of information about which content the sections encode + and how these get formatted when exporting an APT file from APSuite + for a specific version and build number and type of experiment plus combinations of settings. Parse header of the file and check which parsable sections the file contains get the byte offsets of the sections from the beginning @@ -71,9 +70,9 @@ def parse_file_structure(self): self.header_section = None self.available_sections = {} - with open(self.filename, 'rb') as file_handle: + with open(self.file_path, "rb") as fp: self.dummy_header = AptFileHeaderMetadata() - found_header = np.fromfile(file_handle, + found_header = np.fromfile(fp, self.dummy_header.get_numpy_struct(), count=1) @@ -82,57 +81,48 @@ def parse_file_structure(self): print(f"File describes {found_header['llIonCount'][0]} ions") self.header_section = found_header - self.byte_offsets['header'] = np.uint64(file_handle.tell()) - print(self.byte_offsets['header']) + self.byte_offsets["header"] = np.uint64(fp.tell()) + print(f"Currently at byte_offset {self.byte_offsets['header']} B") - end_of_file_not_reached = b'yes' - while end_of_file_not_reached != b'': + end_of_file_not_reached = b"yes" + while end_of_file_not_reached != b"": # probe for end of file - end_of_file_not_reached = file_handle.read(1) - if end_of_file_not_reached != b'': - file_handle.seek(-1, os.SEEK_CUR) + end_of_file_not_reached = fp.read(1) + if end_of_file_not_reached != b"": + fp.seek(-1, os.SEEK_CUR) else: - print(f"End of file at {file_handle.tell()} B") + print(f"End of file at {fp.tell()} B") break dummy_section = AptFileSectionMetadata() - found_section = np.fromfile(file_handle, - dummy_section.get_numpy_struct(), - count=1) - keyword = np_uint16_to_string( - found_section['wcSectionType'][0]) - - print(keyword) - print(found_section) - assert keyword not in self.available_sections, \ - "Found a duplicate of an already parsed section! Create an issue to help us fix this!" - - if keyword not in ['Delta Pulse', 'Epos ToF']: - assert keyword in EXPECTED_SECTIONS, \ - "Found an unknown section, seems like an unknown/new branch! Create an issue to help us fix this!" - + found_section = np.fromfile(fp, dummy_section.get_numpy_struct(), count=1) + keyword = np_uint16_to_string(found_section["wcSectionType"][0]) + + print(f"keyword: {keyword}, found_section: {found_section}") + if keyword in self.available_sections: + raise ValueError("Found a duplicate of an already parsed section! " + "Create an issue to help us fix this!") + + if keyword not in ["Delta Pulse", "Epos ToF"]: + if keyword not in EXPECTED_SECTIONS: + raise ValueError("Found an unknown section, seems like an unknown/new " + "branch! Create an issue to help us fix this!") metadata_section = EXPECTED_SECTIONS[keyword] if metadata_section.matches(found_section) is True: - # assert metadata_section.matches(found_section), \ - # 'Found an uninterpretable section! Please contact the \ - # development team to help us fixing this.' self.available_sections[keyword] = metadata_section else: print(f"Found an uninterpretable non-registered section." f"Create an issue to help us fix this!, Parsing continues" f"llByteCount {found_section['llByteCount'][0]} B") - self.byte_offsets[keyword] = np.uint64(file_handle.tell()) - if keyword == 'Position': + self.byte_offsets[keyword] = np.uint64(fp.tell()) + if keyword == "Position": # special case six IEEE 32-bit floats preceeding raw data self.byte_offsets[keyword] += np.uint64(6 * 4) - self.byte_offsets[keyword] += np.uint64( - found_section['llByteCount'][0]) + self.byte_offsets[keyword] += np.uint64(found_section["llByteCount"][0]) print(f"Byte offset for reading data for section: {keyword}" f" {self.byte_offsets[keyword]} B") - # print(file_handle.tell()) - file_handle.seek(self.byte_offsets[keyword], os.SEEK_SET) - # print(file_handle.tell()) + fp.seek(self.byte_offsets[keyword], os.SEEK_SET) # one convenience reader function for every known section # is useful because it structures the parsers, enables reading the file @@ -140,18 +130,18 @@ def parse_file_structure(self): def get_header(self): """Report metadata in the header.""" metadata_dict = { - 'cSignature': - np_uint16_to_string(self.header_section['cSignature'][0]), - 'iHeaderSize': - np.int32(self.header_section['iHeaderSize'][0]), - 'iHeaderVersion': - np.int32(self.header_section['iHeaderVersion'][0]), - 'wcFilename': - np_uint16_to_string(self.header_section['wcFilename'][0]), - 'ftCreationTime': - np.uint64(self.header_section['ftCreationTime'][0]), - 'llIonCount': - np.uint64(self.header_section['llIonCount'][0])} + "cSignature": + np_uint16_to_string(self.header_section["cSignature"][0]), + "iHeaderSize": + np.int32(self.header_section["iHeaderSize"][0]), + "iHeaderVersion": + np.int32(self.header_section["iHeaderVersion"][0]), + "wcFilename": + np_uint16_to_string(self.header_section["wcFilename"][0]), + "ftCreationTime": + np.uint64(self.header_section["ftCreationTime"][0]), + "llIonCount": + np.uint64(self.header_section["llIonCount"][0])} # check e.g. https://gist.github.com/Mostafa-Hamdy-Elgiar/ # 9714475f1b3bc224ea063af81566d873 repo # for converting Windows/MSDN time to Python time @@ -167,20 +157,19 @@ def get_metadata(self, keyword: str): def get_metadata_table(self): """Create table from all metadata for each section.""" - column_names = ['section'] # header - assert 'Mass' in self.available_sections, \ - "Mass section not available to guide creation of the table header!" - for key in self.available_sections['Mass'].get_metadata().keys(): + column_names = ["section"] # header + if "Mass" not in self.available_sections: + raise ValueError("Mass section not available to guide " + " creation of the table header!") + for key in self.available_sections["Mass"].get_metadata().keys(): column_names.append(key) data_frame = pd.DataFrame(columns=column_names) for keyword, value in self.available_sections.items(): - row_dct = {'section': keyword} - # print(f"{keyword}") + row_dct = {"section": keyword} row_dct = {**row_dct, **value.get_metadata()} # print(value.get_metadata()) row_df = pd.DataFrame(row_dct, index=[0]) - # print(row_df) data_frame = pd.concat([data_frame, row_df], ignore_index=True) data_frame.style.format(precision=3, thousands=",", decimal=".") \ @@ -196,37 +185,19 @@ def get_named_quantity(self, keyword: str): dtype = self.available_sections[keyword].get_ametek_type() offset = byte_position_start - stride = np.uint64( - self.available_sections[keyword].meta['i_data_type_size'] / 8) + stride = np.uint64(self.available_sections[keyword].meta["i_data_type_size"] / 8) count = self.available_sections[keyword].get_ametek_count() - - data = get_memory_mapped_data( - self.filename, dtype, offset, stride, count) - + data = get_memory_mapped_data(self.file_path, dtype, offset, stride, count) shape = tuple(self.available_sections[keyword].get_ametek_shape()) - unit = self.available_sections[keyword].meta['wc_data_unit'] - - return NxField( - np.reshape(data, newshape=shape), np_uint16_to_string(unit)) + unit = self.available_sections[keyword].meta["wc_data_unit"] + return NxField(np.reshape(data, newshape=shape), np_uint16_to_string(unit)) return NxField() def get_mass_to_charge_state_ratio(self): """Read mass-to-charge.""" - return self.get_named_quantity('Mass') + return self.get_named_quantity("Mass") def get_reconstructed_positions(self): """Read reconstructed positions.""" - return self.get_named_quantity('Position') - -# test cases how to use the parser -# TEST_FILE_NAME = '70_50_50.apt' # Xuyang Zhou's (MPIE) \ -# apt = ReadAptFileFormat(TEST_FILE_NAME) -# print(apt.get_metadata_table()) -# print(apt.get_header()) -# xyz = apt.get_reconstructed_positions() -# equivalent to -# xyz = apt.get_metadata('Position') -# mq = apt.get_mass_to_charge_state_ratios() -# equivalent to -# mq = parsedFile.get_named_quantity('Mass') + return self.get_named_quantity("Position") diff --git a/ifes_apt_tc_data_modeling/csv/csv_reader.py b/ifes_apt_tc_data_modeling/csv/csv_reader.py index 2e0f127..307c34b 100644 --- a/ifes_apt_tc_data_modeling/csv/csv_reader.py +++ b/ifes_apt_tc_data_modeling/csv/csv_reader.py @@ -18,6 +18,8 @@ """CSV file format reader as sometimes used for reporting POS file content.""" +# pylint: disable=duplicate-code + import os import numpy as np import pandas as pd diff --git a/ifes_apt_tc_data_modeling/env/env_reader.py b/ifes_apt_tc_data_modeling/env/env_reader.py index d1b0f13..caa1697 100644 --- a/ifes_apt_tc_data_modeling/env/env_reader.py +++ b/ifes_apt_tc_data_modeling/env/env_reader.py @@ -18,7 +18,7 @@ """ENV file format reader for GPM/Rouen ENV system configuration and range files""" -# pylint: disable=too-many-nested-blocks +# pylint: disable=too-many-nested-blocks,duplicate-code import re import numpy as np diff --git a/ifes_apt_tc_data_modeling/epos/epos_reader.py b/ifes_apt_tc_data_modeling/epos/epos_reader.py index 83b4073..75c5698 100644 --- a/ifes_apt_tc_data_modeling/epos/epos_reader.py +++ b/ifes_apt_tc_data_modeling/epos/epos_reader.py @@ -18,6 +18,8 @@ """ePOS file format reader used by atom probe microscopists.""" +# pylint: disable=duplicate-code + import os import numpy as np diff --git a/ifes_apt_tc_data_modeling/pos/pos_reader.py b/ifes_apt_tc_data_modeling/pos/pos_reader.py index 0d78810..2abf697 100644 --- a/ifes_apt_tc_data_modeling/pos/pos_reader.py +++ b/ifes_apt_tc_data_modeling/pos/pos_reader.py @@ -18,6 +18,8 @@ """POS file format reader used by atom probe microscopists.""" +# pylint: disable=duplicate-code + import os import numpy as np diff --git a/ifes_apt_tc_data_modeling/rng/rng_reader.py b/ifes_apt_tc_data_modeling/rng/rng_reader.py index cc63e1d..5e67125 100644 --- a/ifes_apt_tc_data_modeling/rng/rng_reader.py +++ b/ifes_apt_tc_data_modeling/rng/rng_reader.py @@ -18,6 +18,8 @@ """RNG range file reader used by atom probe microscopists.""" +# pylint: disable=duplicate-code + import re import numpy as np diff --git a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py index 073cbae..5e5bf8f 100644 --- a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py +++ b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py @@ -18,7 +18,7 @@ """RRNG range file reader used by atom probe microscopists.""" -# pylint: disable=too-many-branches,too-many-statements +# pylint: disable=too-many-branches,too-many-statements,duplicate-code import re import numpy as np From 4f1c63f09157469b1b50c72ca777805b002f89be Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Tue, 2 Jan 2024 02:09:46 +0100 Subject: [PATCH 14/20] Unlinted but successfully working fixes for bugs detected during running the large case study with 176 datasets --- ifes_apt_tc_data_modeling/env/env_reader.py | 26 +----- ifes_apt_tc_data_modeling/fig/fig_reader.py | 4 +- ifes_apt_tc_data_modeling/nexus/nx_ion.py | 80 +++++++++++++------ ifes_apt_tc_data_modeling/rng/rng_reader.py | 7 +- ifes_apt_tc_data_modeling/rrng/rrng_reader.py | 9 +-- .../utils/combinatorics.py | 50 ------------ .../utils/definitions.py | 4 +- .../utils/molecular_ions.py | 9 ++- ifes_apt_tc_data_modeling/utils/utils.py | 6 +- 9 files changed, 74 insertions(+), 121 deletions(-) delete mode 100644 ifes_apt_tc_data_modeling/utils/combinatorics.py diff --git a/ifes_apt_tc_data_modeling/env/env_reader.py b/ifes_apt_tc_data_modeling/env/env_reader.py index caa1697..f91cf84 100644 --- a/ifes_apt_tc_data_modeling/env/env_reader.py +++ b/ifes_apt_tc_data_modeling/env/env_reader.py @@ -118,32 +118,12 @@ def read_env(self): if dct is None: continue - m_ion = NxIon(isotope_vector=create_isotope_vector( - dct["atoms"]), charge_state=0) + m_ion = NxIon(isotope_vector=create_isotope_vector(dct["atoms"]), + charge_state=0) m_ion.add_range(dct["range"][0], dct["range"][1]) m_ion.comment = NxField(dct["name"], "") - m_ion.color = NxField(dct["color"], "") - m_ion.volume = NxField(dct["volume"], "") + m_ion.apply_combinatorics() # m_ion.report() - crawler = MolecularIonBuilder( - min_abundance=PRACTICAL_ABUNDANCE, - min_abundance_product=PRACTICAL_ABUNDANCE_PRODUCT, - min_half_life=PRACTICAL_MIN_HALF_LIFE, - sacrifice_uniqueness=SACRIFICE_ISOTOPIC_UNIQUENESS, - verbose=VERBOSE) - recovered_charge_state, m_ion_candidates = crawler.combinatorics( - m_ion.isotope_vector.values, - m_ion.ranges.values[0, 0], - m_ion.ranges.values[0, 1]) - # print(f"{recovered_charge_state}") - m_ion.charge_state = NxField(np.int8(recovered_charge_state), "") - m_ion.update_human_readable_name() - m_ion.add_charge_state_model({"min_abundance": PRACTICAL_ABUNDANCE, - "min_abundance_product": PRACTICAL_ABUNDANCE_PRODUCT, - "min_half_life": PRACTICAL_MIN_HALF_LIFE, - "sacrifice_isotopic_uniqueness": SACRIFICE_ISOTOPIC_UNIQUENESS}, - m_ion_candidates) - self.env["molecular_ions"].append(m_ion) print(f"{self.file_path} parsed successfully") diff --git a/ifes_apt_tc_data_modeling/fig/fig_reader.py b/ifes_apt_tc_data_modeling/fig/fig_reader.py index 3fe2483..822745e 100644 --- a/ifes_apt_tc_data_modeling/fig/fig_reader.py +++ b/ifes_apt_tc_data_modeling/fig/fig_reader.py @@ -29,8 +29,6 @@ MAX_NUMBER_OF_ATOMS_PER_ION from ifes_apt_tc_data_modeling.utils.molecular_ions import \ get_chemical_symbols, isotope_to_hash -from ifes_apt_tc_data_modeling.utils.combinatorics import \ - apply_combinatorics class ReadFigTxtFileFormat(): @@ -97,7 +95,7 @@ def read_fig_txt(self): m_ion = NxIon(isotope_vector=ivector, charge_state=charge_state) m_ion.add_range(mqmin, mqmax) m_ion.comment = NxField(ionname, "") - apply_combinatorics(m_ion) + m_ion.apply_combinatorics() # m_ion.report() self.fig["molecular_ions"].append(m_ion) diff --git a/ifes_apt_tc_data_modeling/nexus/nx_ion.py b/ifes_apt_tc_data_modeling/nexus/nx_ion.py index 9fbd88a..454caa3 100644 --- a/ifes_apt_tc_data_modeling/nexus/nx_ion.py +++ b/ifes_apt_tc_data_modeling/nexus/nx_ion.py @@ -32,7 +32,10 @@ from ifes_apt_tc_data_modeling.utils.utils import \ create_isotope_vector, isotope_vector_to_nuclid_list, \ isotope_vector_to_human_readable_name, is_range_significant -from ifes_apt_tc_data_modeling.utils.molecular_ions import MolecularIonCandidate +from ifes_apt_tc_data_modeling.utils.molecular_ions import \ + MolecularIonCandidate, MolecularIonBuilder, \ + PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ + PRACTICAL_MIN_HALF_LIFE, VERBOSE, SACRIFICE_ISOTOPIC_UNIQUENESS from ifes_apt_tc_data_modeling.nexus.nx_field import NxField @@ -103,6 +106,28 @@ def report(self): f"color: {self.color.values}\n" f"volume: {self.volume.values}\n") + def apply_combinatorics(self): + """Apply specifically constrainted combinatorial analysis.""" + crawler = MolecularIonBuilder( + min_abundance=PRACTICAL_ABUNDANCE, + min_abundance_product=PRACTICAL_ABUNDANCE_PRODUCT, + min_half_life=PRACTICAL_MIN_HALF_LIFE, + sacrifice_uniqueness=SACRIFICE_ISOTOPIC_UNIQUENESS, + verbose=VERBOSE) + recovered_charge_state, m_ion_candidates = crawler.combinatorics( + self.isotope_vector.values, + self.ranges.values[0, 0], + self.ranges.values[0, 1]) + # print(f"{recovered_charge_state}") + self.charge_state = NxField(np.int8(recovered_charge_state), "") + self.update_human_readable_name() + self.add_charge_state_model( + {"min_abundance": PRACTICAL_ABUNDANCE, + "min_abundance_product": PRACTICAL_ABUNDANCE_PRODUCT, + "min_half_life": PRACTICAL_MIN_HALF_LIFE, + "sacrifice_isotopic_uniqueness": SACRIFICE_ISOTOPIC_UNIQUENESS}, + crawler.candidates) + def add_charge_state_model(self, parameters, candidates): @@ -114,39 +139,42 @@ def add_charge_state_model(self, if req in parameters: continue raise ValueError(f"Parameter {req} not defined in parameters dict!") - self.charge_state_model = {"isotope_matrix": [], - "charge_state_vector": [], - "mass_vector": [], - "nat_abun_prod_vector": [], - "min_half_life_vector": []} + self.charge_state_model = {"n_cand": 0} for key, val in parameters.items(): if key not in self.charge_state_model: self.charge_state_model[key] = val - n_cand = len(candidates) - if n_cand > 0: + n_cand = 0 + for cand in candidates: + if isinstance(cand, MolecularIonCandidate): + n_cand += 1 + if n_cand == 0: + return + self.charge_state_model["n_cand"] = n_cand + if n_cand == 1: + self.charge_state_model["isotope_matrix"] = candidates[0].isotope_vector + self.charge_state_model["charge_state_vector"] = candidates[0].charge_state + self.charge_state_model["mass_vector"] = candidates[0].mass + self.charge_state_model["nat_abun_prod_vector"] = candidates[0].abundance_product + self.charge_state_model["min_half_life_vector"] = candidates[0].shortest_half_life + else: self.charge_state_model["isotope_matrix"] \ = np.zeros((n_cand, MAX_NUMBER_OF_ATOMS_PER_ION), np.uint16) self.charge_state_model["charge_state_vector"] \ - = np.zeros((n_cand, ), np.int8) + = np.zeros((n_cand,), np.int8) self.charge_state_model["mass_vector"] \ - = np.zeros((n_cand, ), np.float64) + = np.zeros((n_cand,), np.float64) self.charge_state_model["nat_abun_prod_vector"] \ - = np.zeros((n_cand, ), np.float64) + = np.zeros((n_cand,), np.float64) self.charge_state_model["min_half_life_vector"] \ - = np.zeros((n_cand, ), np.float64) + = np.zeros((n_cand,), np.float64) row_idx = 0 for cand in candidates: - if isinstance(cand, MolecularIonCandidate): - self.charge_state_model["isotope_matrix"][row_idx, 0:len(cand.isotope_vector)] \ - = cand.isotope_vector - self.charge_state_model["charge_state_vector"][row_idx] = cand.charge_state - self.charge_state_model["mass_vector"][row_idx] = cand.mass - self.charge_state_model["nat_abun_prod_vector"][row_idx] \ - = cand.abundance_product - self.charge_state_model["min_half_life_vector"][row_idx] \ - = cand.shortest_half_life - row_idx += 1 - else: - print(f"{__name__} found cand which is not a MolecularIonCandidate!") - # else: - # print("Not enough candidates to report as a charge_state model") + self.charge_state_model["isotope_matrix"][row_idx, 0:len(cand.isotope_vector)] \ + = cand.isotope_vector + self.charge_state_model["charge_state_vector"][row_idx] = cand.charge_state + self.charge_state_model["mass_vector"][row_idx] = cand.mass + self.charge_state_model["nat_abun_prod_vector"][row_idx] \ + = cand.abundance_product + self.charge_state_model["min_half_life_vector"][row_idx] \ + = cand.shortest_half_life + row_idx += 1 diff --git a/ifes_apt_tc_data_modeling/rng/rng_reader.py b/ifes_apt_tc_data_modeling/rng/rng_reader.py index 5e67125..a4cc700 100644 --- a/ifes_apt_tc_data_modeling/rng/rng_reader.py +++ b/ifes_apt_tc_data_modeling/rng/rng_reader.py @@ -28,7 +28,6 @@ create_isotope_vector, is_range_significant from ifes_apt_tc_data_modeling.utils.definitions import MQ_EPSILON from ifes_apt_tc_data_modeling.utils.molecular_ions import get_chemical_symbols -from ifes_apt_tc_data_modeling.utils.combinatorics import apply_combinatorics # there are specific examples for unusual range files here: @@ -158,11 +157,11 @@ def read_rng(self): print(f"WARNING::RNG line {txt_stripped[idx]} is corrupted!") continue - m_ion = NxIon(isotope_vector=create_isotope_vector( - dct["atoms"]), charge_state=0) + m_ion = NxIon(isotope_vector=create_isotope_vector(dct["atoms"]), + charge_state=0) m_ion.add_range(dct["range"][0], dct["range"][1]) m_ion.comment = NxField(dct["name"], "") - apply_combinatorics(m_ion) + m_ion.apply_combinatorics() # m_ion.report() self.rng["molecular_ions"].append(m_ion) diff --git a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py index 5e5bf8f..bd18273 100644 --- a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py +++ b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py @@ -28,7 +28,6 @@ from ifes_apt_tc_data_modeling.utils.utils import \ create_isotope_vector, is_range_significant from ifes_apt_tc_data_modeling.utils.definitions import MQ_EPSILON -from ifes_apt_tc_data_modeling.utils.combinatorics import apply_combinatorics def evaluate_rrng_range_line(i: int, line: str) -> dict: @@ -142,7 +141,7 @@ def read_rrng(self): current_line_id += 1 for i in np.arange(0, number_of_ion_names): tmp = re.split(r"[\s=]+", txt_stripped[current_line_id + i]) - if len(tmp) == 2: + if len(tmp) != 2: raise ValueError(f"Line {txt_stripped[current_line_id + i]} [Ions]/Ion line corrupted!") if tmp[0] != f"Ion{i + 1}": raise ValueError(f"Line {txt_stripped[current_line_id + i]} [Ions]/Ion incorrectly formatted!") @@ -177,11 +176,11 @@ def read_rrng(self): print(f"WARNING::RNG line {txt_stripped[current_line_id + jdx]} is corrupted!") continue - m_ion = NxIon(isotope_vector=create_isotope_vector( - dct["atoms"]), charge_state=0) + m_ion = NxIon(isotope_vector=create_isotope_vector(dct["atoms"]), + charge_state=0) m_ion.add_range(dct["range"][0], dct["range"][1]) m_ion.comment = NxField(dct["name"], "") - apply_combinatorics(m_ion) + m_ion.apply_combinatorics() # m_ion.report() self.rrng["molecular_ions"].append(m_ion) diff --git a/ifes_apt_tc_data_modeling/utils/combinatorics.py b/ifes_apt_tc_data_modeling/utils/combinatorics.py deleted file mode 100644 index d030fdf..0000000 --- a/ifes_apt_tc_data_modeling/utils/combinatorics.py +++ /dev/null @@ -1,50 +0,0 @@ -# -# 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. -# - -"""Function implementing combinatorial analysis for all ranging definitions.""" - -# shared functionality used for RNG/RRNG/ENV - -import numpy as np - -from ifes_apt_tc_data_modeling.nexus.nx_ion import NxField, NxIon -from ifes_apt_tc_data_modeling.utils.molecular_ions import \ - MolecularIonBuilder, PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ - PRACTICAL_MIN_HALF_LIFE, VERBOSE, SACRIFICE_ISOTOPIC_UNIQUENESS - - -def apply_combinatorics(m_ion: NxIon): - """Apply specifically constrainted combinatorial analysis.""" - crawler = MolecularIonBuilder(min_abundance=PRACTICAL_ABUNDANCE, - min_abundance_product=PRACTICAL_ABUNDANCE_PRODUCT, - min_half_life=PRACTICAL_MIN_HALF_LIFE, - sacrifice_uniqueness=SACRIFICE_ISOTOPIC_UNIQUENESS, - verbose=VERBOSE) - recovered_charge_state, m_ion_candidates \ - = crawler.combinatorics(m_ion.isotope_vector.values, - m_ion.ranges.values[0, 0], - m_ion.ranges.values[0, 1]) - # print(f"{recovered_charge_state}") - m_ion.charge_state = NxField(np.int8(recovered_charge_state), "") - m_ion.update_human_readable_name() - m_ion.add_charge_state_model({"min_abundance": PRACTICAL_ABUNDANCE, - "min_abundance_product": PRACTICAL_ABUNDANCE_PRODUCT, - "min_half_life": PRACTICAL_MIN_HALF_LIFE, - "sacrifice_isotopic_uniqueness": SACRIFICE_ISOTOPIC_UNIQUENESS}, - m_ion_candidates) - return m_ion diff --git a/ifes_apt_tc_data_modeling/utils/definitions.py b/ifes_apt_tc_data_modeling/utils/definitions.py index 628340a..5264dff 100644 --- a/ifes_apt_tc_data_modeling/utils/definitions.py +++ b/ifes_apt_tc_data_modeling/utils/definitions.py @@ -29,10 +29,10 @@ # do not consider isotopes with a very low natural abundance -PRACTICAL_ABUNDANCE = 1.e-6 # 0. # 1.0e-6 +PRACTICAL_ABUNDANCE = 1.0e-6 # 0. # 1.0e-6 # do not consider candidate isotopically different molecular ions # if their natural abundance product is too low -PRACTICAL_ABUNDANCE_PRODUCT = 1.e-6 # 0. # 1.0e-12 +PRACTICAL_ABUNDANCE_PRODUCT = 0. # 1.0e-6 # 0. # 1.0e-12 # do consider too shortliving isotopes PRACTICAL_MIN_HALF_LIFE = np.inf # many examples of ranges are not constrainted strongly enough so that diff --git a/ifes_apt_tc_data_modeling/utils/molecular_ions.py b/ifes_apt_tc_data_modeling/utils/molecular_ions.py index 87dd4cc..4ebbe89 100644 --- a/ifes_apt_tc_data_modeling/utils/molecular_ions.py +++ b/ifes_apt_tc_data_modeling/utils/molecular_ions.py @@ -208,6 +208,8 @@ def combinatorics(self, element_arr, low, high): depth, max_depth, low, high) if self.parms["verbose"] is True: print(f"Found {len(self.candidates)} candidates!") + for obj in self.candidates: + print(f"{obj.isotope_vector}, {obj.charge_state}, {obj.shortest_half_life}") return self.try_to_reduce_to_unique_solution() # will return a tuple of charge_state and list of relevant_candidates return (0, []) @@ -267,10 +269,11 @@ def get_relevant(self): relevant = {} for cand in self.candidates: if cand.abundance_product >= self.parms["min_abundance_product"]: - if np.isnan(cand.shortest_half_life) is False: + if np.isnan(cand.shortest_half_life) == False: + # don't dare to test np.isnan(cand.shortest_half_life) is False if cand.shortest_half_life >= self.parms["min_half_life"]: keyword = cand.unique_keyword() - if keyword not in relevant: + if keyword not in relevant.keys(): relevant[keyword] = cand if self.parms["verbose"] is True: @@ -280,7 +283,7 @@ def get_relevant(self): relevant_candidates = [] for key, obj in relevant.items(): relevant_candidates.append(obj) - return relevant, relevant_candidates + return (relevant, relevant_candidates) def try_to_reduce_to_unique_solution(self): """Heuristics to identify if current candidates are unique.""" diff --git a/ifes_apt_tc_data_modeling/utils/utils.py b/ifes_apt_tc_data_modeling/utils/utils.py index 0d968ca..f264431 100644 --- a/ifes_apt_tc_data_modeling/utils/utils.py +++ b/ifes_apt_tc_data_modeling/utils/utils.py @@ -77,8 +77,7 @@ def create_isotope_vector(building_blocks: list) -> np.ndarray: if block.count("-") == 0: # an element if (block not in symbol_to_proton_number) or (block == "X"): return ivec - hashvector.append(isotope_to_hash( - symbol_to_proton_number[block], 0)) + hashvector.append(isotope_to_hash(symbol_to_proton_number[block], 0)) elif block.count("-") == 1: symb_mass = block.split("-") if (len(symb_mass) != 2) or (symb_mass[0] not in symbol_to_proton_number) or (symb_mass[0] == "X"): @@ -89,9 +88,6 @@ def create_isotope_vector(building_blocks: list) -> np.ndarray: neutron_number = mass_number - proton_number if (proton_number in isotopes) and (mass_number in isotopes[proton_number]): hashvector.append(isotope_to_hash(proton_number, neutron_number)) - return ivec - return ivec - ivec[0:len(hashvector)] = np.sort( np.asarray(hashvector, np.uint16), kind="stable")[::-1] return ivec From 10203fc7665d36b516ad62622c1674a526059c9b Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Tue, 2 Jan 2024 17:02:44 +0100 Subject: [PATCH 15/20] Last changes introduced to fix the library funs such that all 176 examples were successfully processable, next steps: i) check with refactored NXapm, ii) make a new release --- .../pyccapt/pyccapt_reader.py | 3 +- ifes_apt_tc_data_modeling/rng/rng_reader.py | 13 +++++---- ifes_apt_tc_data_modeling/rrng/rrng_reader.py | 28 ++++++++++++------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py b/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py index 6fc710d..3c71cde 100644 --- a/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py +++ b/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py @@ -206,8 +206,7 @@ def __init__(self, file_path: str): m_ion.nuclid_list.values = isotope_vector_to_nuclid_list(ivec) m_ion.charge_state.values = np.int8(self.df.iloc[idx, 9]) m_ion.add_range(self.df.iloc[idx, 3], self.df.iloc[idx, 4]) - m_ion.update_human_readable_name() - # apply_combinatorics(m_ion) + m_ion.apply_combinatorics() # m_ion.report() self.rng["molecular_ions"].append(m_ion) print(f"{self.file_path} parsed successfully") diff --git a/ifes_apt_tc_data_modeling/rng/rng_reader.py b/ifes_apt_tc_data_modeling/rng/rng_reader.py index a4cc700..8537bc6 100644 --- a/ifes_apt_tc_data_modeling/rng/rng_reader.py +++ b/ifes_apt_tc_data_modeling/rng/rng_reader.py @@ -47,21 +47,24 @@ def evaluate_rng_range_line( tmp = re.split(r"\s+", line) if len(tmp) != n_columns: - raise ValueError(f"Line {line} inconsistent number columns!") + raise ValueError(f"Line {line} inconsistent number columns {len(tmp)}!") if tmp[0] != ".": raise ValueError(f"Line {line} has inconsistent line prefix!") if is_range_significant(np.float64(tmp[1]), np.float64(tmp[2])) is False: - raise ValueError(f"Line {line} insignificant range!") + # raise ValueError(f"Line {line} insignificant range!") + return None info["range"] = np.asarray([tmp[1], tmp[2]], np.float64) # line encodes multiplicity of element via array of multiplicity counts element_multiplicity = np.asarray(tmp[3:len(tmp)], np.uint32) if np.sum(element_multiplicity) < 0: - raise ValueError(f"Line {line} no element counts!") + # raise ValueError(f"Line {line} no element counts!") + return None if np.sum(element_multiplicity) > 0: for jdx in np.arange(0, len(element_multiplicity)): if element_multiplicity[jdx] < 0: - raise ValueError(f"Line {line} no negative element counts!") + # raise ValueError(f"Line {line} no negative element counts!") + return None if element_multiplicity[jdx] > 0: symbol = column_id_to_label[jdx + 1] if symbol in get_chemical_symbols(): @@ -87,7 +90,7 @@ def evaluate_rng_ion_type_header(line: str) -> dict: info: dict = {"column_id_to_label": {}} tmp = re.split(r"\s+", line) if len(tmp) == 0: - raise ValueError(f"Line {line} does not contain iontype labels!") + raise ValueError(f"Line {line} does not contain iontype labels {len(tmp)}!") for idx in np.arange(1, len(tmp)): info["column_id_to_label"][idx] = tmp[idx] return info diff --git a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py index bd18273..31498f2 100644 --- a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py +++ b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py @@ -46,11 +46,14 @@ def evaluate_rrng_range_line(i: int, line: str) -> dict: tmp = re.split(r"[\s=]+", line) if len(tmp) < 6: - raise ValueError(f"Line {line} does not contain all required fields!") + # raise ValueError(f"Line {line} does not contain all required fields {len(tmp)}!") + return None if tmp[0] != f"Range{i}": - raise ValueError(f"Line {line} has inconsistent line prefix!") + # raise ValueError(f"Line {line} has inconsistent line prefix {tmp[0]}!") + return None if is_range_significant(np.float64(tmp[1]), np.float64(tmp[2])) is False: - raise ValueError(f"Line {line} insignificant range!") + # raise ValueError(f"Line {line} insignificant range!") + return None info["range"] = np.asarray([tmp[1], tmp[2]], np.float64) if tmp[3].lower().startswith("vol:"): @@ -66,7 +69,8 @@ def evaluate_rrng_range_line(i: int, line: str) -> dict: for information in tmp[4:-1]: element_multiplicity = re.split(r":+", information) if len(element_multiplicity) != 2: - raise ValueError(f"Line {line}, element multiplicity is incorrectly formatted!") + raise ValueError(f"Line {line}, element multiplicity is not " + f"correctly formatted {len(element_multiplicity)}!") # skip vol, name, and color information if element_multiplicity[0].lower() == "name": info["name"] = f"{element_multiplicity[1]}" @@ -78,12 +82,16 @@ def evaluate_rrng_range_line(i: int, line: str) -> dict: # pick up what is an element name symbol = element_multiplicity[0] if (symbol not in chemical_symbols) or (symbol == "X"): - raise ValueError(f"Line {line} contains an invalid chemical symbol!") - if np.uint32(element_multiplicity[1]) <= 0: - raise ValueError(f"Line {line} zero or negative multiplicity!") + # raise ValueError(f"WARNING::Line {line} contains an invalid chemical symbol {symbol}!") + return None + # if np.uint32(element_multiplicity[1]) <= 0: + # raise ValueError(f"Line {line} zero or negative multiplicity !") if np.uint32(element_multiplicity[1]) >= 256: - raise ValueError(f"Line {line} unsupported high multiplicity!") - info["atoms"] = np.append(info["atoms"], [symbol] * int(element_multiplicity[1])) + # raise ValueError(f"Line {line} unsupported high multiplicity " + # f"{np.uint32(element_multiplicity)}!") + return None + info["atoms"] = np.append(info["atoms"], + [symbol] * int(element_multiplicity[1])) return info @@ -173,7 +181,7 @@ def read_rrng(self): for jdx in np.arange(0, number_of_ranges): dct = evaluate_rrng_range_line(jdx + 1, txt_stripped[current_line_id + jdx]) if dct is None: - print(f"WARNING::RNG line {txt_stripped[current_line_id + jdx]} is corrupted!") + print(f"WARNING::RRNG line {txt_stripped[current_line_id + jdx]} is corrupted!") continue m_ion = NxIon(isotope_vector=create_isotope_vector(dct["atoms"]), From 871ee83c2c41039aa6b22b4b97eaedac935f1bee Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 11 Jan 2024 10:15:56 +0100 Subject: [PATCH 16/20] Final styling, linting, mypy --- ifes_apt_tc_data_modeling/env/env_reader.py | 4 ---- ifes_apt_tc_data_modeling/nexus/nx_ion.py | 13 ++++++------- ifes_apt_tc_data_modeling/utils/molecular_ions.py | 4 ++-- linting.sh | 4 ++-- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/ifes_apt_tc_data_modeling/env/env_reader.py b/ifes_apt_tc_data_modeling/env/env_reader.py index f91cf84..99f15d1 100644 --- a/ifes_apt_tc_data_modeling/env/env_reader.py +++ b/ifes_apt_tc_data_modeling/env/env_reader.py @@ -26,10 +26,6 @@ from ifes_apt_tc_data_modeling.utils.utils import \ create_isotope_vector, is_range_significant, get_smart_chemical_symbols from ifes_apt_tc_data_modeling.utils.definitions import MQ_EPSILON -from ifes_apt_tc_data_modeling.utils.molecular_ions import MolecularIonBuilder -from ifes_apt_tc_data_modeling.utils.molecular_ions import \ - PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ - PRACTICAL_MIN_HALF_LIFE, VERBOSE, SACRIFICE_ISOTOPIC_UNIQUENESS def evaluate_env_range_line(line: str): diff --git a/ifes_apt_tc_data_modeling/nexus/nx_ion.py b/ifes_apt_tc_data_modeling/nexus/nx_ion.py index 454caa3..831e4e8 100644 --- a/ifes_apt_tc_data_modeling/nexus/nx_ion.py +++ b/ifes_apt_tc_data_modeling/nexus/nx_ion.py @@ -23,7 +23,7 @@ """Set of utility tools for parsing file formats used by atom probe.""" -# pylint: disable=too-many-instance-attributes +# pylint: disable=too-many-instance-attributes,unused-variable import numpy as np @@ -121,12 +121,11 @@ def apply_combinatorics(self): # print(f"{recovered_charge_state}") self.charge_state = NxField(np.int8(recovered_charge_state), "") self.update_human_readable_name() - self.add_charge_state_model( - {"min_abundance": PRACTICAL_ABUNDANCE, - "min_abundance_product": PRACTICAL_ABUNDANCE_PRODUCT, - "min_half_life": PRACTICAL_MIN_HALF_LIFE, - "sacrifice_isotopic_uniqueness": SACRIFICE_ISOTOPIC_UNIQUENESS}, - crawler.candidates) + self.add_charge_state_model({"min_abundance": PRACTICAL_ABUNDANCE, + "min_abundance_product": PRACTICAL_ABUNDANCE_PRODUCT, + "min_half_life": PRACTICAL_MIN_HALF_LIFE, + "sacrifice_isotopic_uniqueness": SACRIFICE_ISOTOPIC_UNIQUENESS}, + crawler.candidates) def add_charge_state_model(self, parameters, diff --git a/ifes_apt_tc_data_modeling/utils/molecular_ions.py b/ifes_apt_tc_data_modeling/utils/molecular_ions.py index 4ebbe89..f8d189a 100644 --- a/ifes_apt_tc_data_modeling/utils/molecular_ions.py +++ b/ifes_apt_tc_data_modeling/utils/molecular_ions.py @@ -269,11 +269,11 @@ def get_relevant(self): relevant = {} for cand in self.candidates: if cand.abundance_product >= self.parms["min_abundance_product"]: - if np.isnan(cand.shortest_half_life) == False: + if not np.isnan(cand.shortest_half_life): # don't dare to test np.isnan(cand.shortest_half_life) is False if cand.shortest_half_life >= self.parms["min_half_life"]: keyword = cand.unique_keyword() - if keyword not in relevant.keys(): + if keyword not in relevant: relevant[keyword] = cand if self.parms["verbose"] is True: diff --git a/linting.sh b/linting.sh index 652d843..632204a 100755 --- a/linting.sh +++ b/linting.sh @@ -3,6 +3,6 @@ # execute within a local python virtual environment or within a conda environment # in both cases the ifes_apt_tc_data_modeling module should have been installed in developer mode -python -m pycodestyle --ignore=E501 ifes_apt_tc_data_modeling +python -m pycodestyle --ignore=E501,E712 ifes_apt_tc_data_modeling python -m pylint --rcfile=pylintrc.rc ifes_apt_tc_data_modeling --ignore build -python -m mypy --ignore-missing-imports ifes_apt_tc_data_modeling \ No newline at end of file +python -m mypy --ignore-missing-imports ifes_apt_tc_data_modeling From 993835ab414e68c130df1d167ae13289561a28aa Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Mon, 22 Jan 2024 13:25:37 +0100 Subject: [PATCH 17/20] Added an example how to load ranging definitions from Imago's IVAS XML-serialized state object --- dev-requirements.txt | 15 +- ifes_apt_tc_data_modeling/fig/fig_reader.py | 4 +- ifes_apt_tc_data_modeling/imago/__init__.py | 17 ++ .../imago/imago_reader.py | 150 ++++++++++++++++++ pyproject.toml | 8 +- tests/TestsForDevelopers.ipynb | 86 ++++++++-- 6 files changed, 254 insertions(+), 26 deletions(-) create mode 100644 ifes_apt_tc_data_modeling/imago/__init__.py create mode 100644 ifes_apt_tc_data_modeling/imago/imago_reader.py diff --git a/dev-requirements.txt b/dev-requirements.txt index 78aa550..69069a1 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.10 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile --extra=dev --output-file=dev-requirements.txt pyproject.toml @@ -63,6 +63,8 @@ executing==1.2.0 # via stack-data fastjsonschema==2.16.3 # via nbformat +flatdict==4.0.1 + # via ifes_apt_tc_data_modeling (pyproject.toml) fonttools==4.39.3 # via matplotlib h5grove==1.3.0 @@ -360,10 +362,7 @@ tifffile==2023.4.12 tinycss2==1.2.1 # via nbconvert tomli==2.0.1 - # via - # jupyterlab - # mypy - # pylint + # via jupyterlab tomlkit==0.12.3 # via pylint tornado==6.3.1 @@ -392,9 +391,7 @@ traitlets==5.9.0 twine==4.0.2 # via ifes_apt_tc_data_modeling (pyproject.toml) typing-extensions==4.9.0 - # via - # astroid - # mypy + # via mypy tzdata==2023.3 # via pandas urllib3==1.26.15 @@ -409,6 +406,8 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.5.1 # via jupyter-server +xmltodict==0.13.0 + # via ifes_apt_tc_data_modeling (pyproject.toml) zipp==3.15.0 # via importlib-metadata diff --git a/ifes_apt_tc_data_modeling/fig/fig_reader.py b/ifes_apt_tc_data_modeling/fig/fig_reader.py index 822745e..6da0212 100644 --- a/ifes_apt_tc_data_modeling/fig/fig_reader.py +++ b/ifes_apt_tc_data_modeling/fig/fig_reader.py @@ -86,7 +86,9 @@ def read_fig_txt(self): f"{mass_number}", "").replace(f"{multiplier}", "").replace(" ", "") if symbol in get_chemical_symbols(): proton_number = atomic_numbers[symbol] - neutron_number = mass_number - proton_number + neutron_number = 0 + if mass_number != 0: + neutron_number = mass_number - proton_number ivec.extend([isotope_to_hash(proton_number, neutron_number)] * multiplier) ivec = np.sort(np.asarray(ivec, np.uint16))[::-1] ivector = np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,), np.uint16) diff --git a/ifes_apt_tc_data_modeling/imago/__init__.py b/ifes_apt_tc_data_modeling/imago/__init__.py new file mode 100644 index 0000000..db96892 --- /dev/null +++ b/ifes_apt_tc_data_modeling/imago/__init__.py @@ -0,0 +1,17 @@ +# +# 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. +# diff --git a/ifes_apt_tc_data_modeling/imago/imago_reader.py b/ifes_apt_tc_data_modeling/imago/imago_reader.py new file mode 100644 index 0000000..5f5a380 --- /dev/null +++ b/ifes_apt_tc_data_modeling/imago/imago_reader.py @@ -0,0 +1,150 @@ +# +# 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. +# + +"""Reader for *.analysis JSON-serialized objects from IVAS/Imago.""" + +# This is an example how to extract pieces of information from *.analysis files +# of Imago's IVAS analysis. Imago is the forerunner company of AMETEK/Cameca +# The example below shows how to extract ranging definitions. + +import re +import xmltodict +import flatdict as fd +import numpy as np + +from ase.data import atomic_numbers, chemical_symbols +from ifes_apt_tc_data_modeling.nexus.nx_ion import NxField, NxIon +from ifes_apt_tc_data_modeling.utils.definitions import \ + MAX_NUMBER_OF_ATOMS_PER_ION +from ifes_apt_tc_data_modeling.utils.molecular_ions import \ + get_chemical_symbols, isotope_to_hash + + +class ReadImagoAnalysisFileFormat(): + """Read *.analysis file (format), extract ranging definitions as an example.""" + + def __init__(self, file_path: str): + if (len(file_path) <= 9) or (file_path.lower().endswith(".analysis") is False): + raise ImportError("WARNING::ANALYSIS file incorrect file_path ending or file type!") + self.file_path = file_path + self.imago: dict = {"ranges": {}, + "ions": {}, + "molecular_ions": []} + self.read_imago_analysis_ranging_definitions() + + def read_imago_analysis_ranging_definitions(self): + """Read *.analysis range file content.""" + # https://wilfried-grupe.de/Java_XMLEncoder.html + # IVAS, the integrated visualization and analysis software/suite for + # atom probe was a forerunner of the product that is now called APSuite + # IVAS is a java application that uses JSON/XML object serialization + # to store state files, many atom probe groups have still the resultant + # state files within their projects, this function shows an example + # how one can extract information from these files + + # unfortunately the serialized XML is in a format that when represented + # in python mixes recurrent nested lists within dictionaries. Such a data + # structure is not directly flattenable and hence many checks are required + # I expect that this parser does not work out of the box for many + # examples given that the formatting of object serialized content + # depends heavily on the implementation of the host application (IVAS) + # the main idea behind the example is to show that information can + # be extracted and to motivate that nowadays one should use data + # structures that are more conveniently parsable + with open(self.file_path, "r", encoding="utf-8") as xmlf: + xml = xmltodict.parse(xmlf.read()) + flt = fd.FlatDict(xml, "/") + for entry in flt["java/object/void"]: + # strategy is, walk the data structure and try to discard non-ranging content as early as possible + for key, val in fd.FlatDict(entry, "/").items(): + if (not isinstance(val, list)) or (key != "object/void"): + continue + for member in val: + if (not isinstance(member, dict)) \ + or ("@method" not in member.keys()) \ + or (member["@method"] != "add"): + continue + # print(">>>>>>>>>>>At the level of a molecular ion that can be so simple that it is just an element ion") + cand_dct = fd.FlatDict(member, "/") + # print(f">>>>> {cand_dct}") + all_reqs_exist = True + reqs = ["@method", "object/@id", "object/@class", "object/string", "object/boolean", "object/void"] + for req in reqs: + if req not in cand_dct.keys(): + all_reqs_exist = False + if all_reqs_exist == False: + continue + + if (not cand_dct["object/@id"].startswith("AtomDataRealRange")) \ + or (cand_dct["object/@class"] != "com.imago.core.atomdata.AtomDataRealRange") \ + or (not isinstance(cand_dct["object/void"], list)): + continue + for lst in cand_dct["object/void"]: + rng = fd.FlatDict(lst, "/") + element_symbol = [] + mq = [] + if "object/void/string" in rng.keys(): + if rng["object/void/string"] in get_chemical_symbols(): + if "object/double" in rng.keys(): + mq = rng["object/double"][0:2] + element_symbol.append(rng["object/void/string"]) # assuming multiplicity is one ! + else: + if "object/void" in rng.keys(): + if isinstance(rng["object/void"], list): + mq = rng["object/double"][0:2] + element_symbol = [] + for block in rng["object/void"]: + if isinstance(block, dict): + if "@method" in block.keys() and "string" in block.keys() and "double" in block.keys(): + if block["string"] in chemical_symbols: + for mult in np.arange(0, int(block["double"].split('.')[0])): + element_symbol.append(block["string"]) + if (len(element_symbol) >= 1) and (len(mq) == 2): + # print(f"------------>{element_symbol}, {mq}") + ivec = [] + for isotope in element_symbol: + if isotope != "": + prefix = re.findall("^[0-9]+", isotope) + mass_number = 0 + if len(prefix) == 1: + if int(prefix[0]) > 0: + mass_number = int(prefix[0]) + suffix = re.findall("[0-9]+$", isotope) + multiplier = 1 + if len(suffix) == 1: + multiplier = int(suffix[0]) + symbol = isotope.replace( + f"{mass_number}", "").replace(f"{multiplier}", "").replace(" ", "") + if symbol in get_chemical_symbols(): + proton_number = atomic_numbers[symbol] + neutron_number = 0 + if mass_number != 0: + neutron_number = mass_number - proton_number + ivec.extend([isotope_to_hash(proton_number, neutron_number)] * multiplier) + ivec = np.sort(np.asarray(ivec, np.uint16))[::-1] + ivector = np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,), np.uint16) + ivector[0:len(ivec)] = ivec + + m_ion = NxIon(isotope_vector=ivector, charge_state=0) + m_ion.add_range(float(mq[0]), float(mq[1])) + m_ion.comment = NxField(" ".join(element_symbol), "") + m_ion.apply_combinatorics() + m_ion.report() + + self.imago["molecular_ions"].append(m_ion) + print(f"{self.file_path} parsed successfully") diff --git a/pyproject.toml b/pyproject.toml index 0a9acc4..c0d4bd5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "ifes_apt_tc_data_modeling" -version = "0.1" +version = "0.2" authors = [ { name = "The NOMAD Authors" }, ] @@ -27,7 +27,9 @@ dependencies = [ "pandas", "tables", "ase>=3.19.0", - "radioactivedecay>=0.4.16" + "radioactivedecay>=0.4.16", + "flatdict", + "xmltodict" ] [project.optional-dependencies] @@ -41,4 +43,4 @@ dev = [ ] # [tool.setuptools] -# packages = ["apt", "ato", "epos", "fig", "nexus", "pos", "pyccapt", "rng", "rrng", "utils"] +# packages = ["apt", "ato", "epos", "fig", "imago", "nexus", "pos", "pyccapt", "rng", "rrng", "utils"] diff --git a/tests/TestsForDevelopers.ipynb b/tests/TestsForDevelopers.ipynb index 656e357..3d5828b 100644 --- a/tests/TestsForDevelopers.ipynb +++ b/tests/TestsForDevelopers.ipynb @@ -96,19 +96,25 @@ " dst.attrs[\"unit\"] = \"s\"\n", " dst = fpw.create_dataset(f\"{subgrpnm}/sacrifice_isotopic_uniqueness\", dtype=np.uint8,\n", " data=mion.charge_state_model[\"sacrifice_isotopic_uniqueness\"])\n", - " dst = fpw.create_dataset(f\"{subgrpnm}/isotope_matrix\", dtype=np.uint16,\n", - " data=mion.charge_state_model[\"isotope_matrix\"],\n", - " chunks=True, compression=\"gzip\", compression_opts=1)\n", - " dst = fpw.create_dataset(f\"{subgrpnm}/charge_state_vector\", dtype=np.int8,\n", - " data=mion.charge_state_model[\"charge_state_vector\"])\n", - " dst = fpw.create_dataset(f\"{subgrpnm}/mass_vector\", dtype=np.float64,\n", - " data=mion.charge_state_model[\"mass_vector\"])\n", - " dst.attrs[\"unit\"] = \"Da\"\n", - " dst = fpw.create_dataset(f\"{subgrpnm}/nat_abun_prod_vector\", dtype=np.float64,\n", - " data=mion.charge_state_model[\"nat_abun_prod_vector\"])\n", - " dst = fpw.create_dataset(f\"{subgrpnm}/min_half_life_vector\", dtype=np.float64,\n", - " data=mion.charge_state_model[\"min_half_life_vector\"])\n", - " dst.attrs[\"unit\"] = \"s\"" + " opt_field_names = [\"isotope_matrix\", \"charge_state_vector\", \"mass_vector\", \"nat_abun_prod_vector\", \"min_half_life_vector\"]\n", + " all_opt_available = True\n", + " for opt_field_name in opt_field_names:\n", + " if not opt_field_name in mion.charge_state_model:\n", + " all_opt_available = False\n", + " if all_opt_available == True:\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/isotope_matrix\", dtype=np.uint16,\n", + " data=mion.charge_state_model[\"isotope_matrix\"],\n", + " chunks=True, compression=\"gzip\", compression_opts=1) \n", + " dst = fpw.create_dataset(f\"{subgrpnm}/charge_state_vector\", dtype=np.int8,\n", + " data=mion.charge_state_model[\"charge_state_vector\"])\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/mass_vector\", dtype=np.float64,\n", + " data=mion.charge_state_model[\"mass_vector\"])\n", + " dst.attrs[\"unit\"] = \"Da\"\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/nat_abun_prod_vector\", dtype=np.float64,\n", + " data=mion.charge_state_model[\"nat_abun_prod_vector\"])\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/min_half_life_vector\", dtype=np.float64,\n", + " data=mion.charge_state_model[\"min_half_life_vector\"])\n", + " dst.attrs[\"unit\"] = \"s\"" ] }, { @@ -121,8 +127,51 @@ }, { "cell_type": "markdown", - "id": "8fd557cb-0fd5-404a-9893-416861913e73", + "id": "43671179-ab4f-411b-a275-0a99e9c4b5bd", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "## Imago *.analysis reader" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5086e1d3-5d85-4cab-9a15-d76ac6fb7f2c", "metadata": {}, + "outputs": [], + "source": [ + "prefix = f\"{os.getcwd()}/data/imago/examples_without_provenance\"\n", + "fnm = [\"default.analysis\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "156f0a3e-88dc-4c9e-a3f6-bc79bb54adf9", + "metadata": {}, + "outputs": [], + "source": [ + "from ifes_apt_tc_data_modeling.imago.imago_reader import ReadImagoAnalysisFileFormat\n", + "for fpath in fnm:\n", + " if fpath.lower().endswith(\".analysis\"):\n", + " print(fpath)\n", + " imago = ReadImagoAnalysisFileFormat(f\"{prefix}/{fpath}\")\n", + " with h5py.File(f\"{prefix}/{fpath}.nxs\", \"w\") as h5w:\n", + " h5w.create_group(\"/entry1\")\n", + " idx = 1\n", + " for ion in imago.imago[\"molecular_ions\"]:\n", + " simple_hfive_file(h5w, idx, ion)\n", + " idx += 1" + ] + }, + { + "cell_type": "markdown", + "id": "8fd557cb-0fd5-404a-9893-416861913e73", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, "source": [ "## CSV reader" ] @@ -159,6 +208,7 @@ "cell_type": "markdown", "id": "523ccf70-b115-4717-9007-bd13ff86a2a5", "metadata": { + "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -319,6 +369,7 @@ "cell_type": "markdown", "id": "83369dab-5ce9-4c9e-810e-58e9f8bb93cc", "metadata": { + "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -397,6 +448,7 @@ "cell_type": "markdown", "id": "e045474d-0801-4686-abf3-1463771e2ddf", "metadata": { + "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -459,6 +511,7 @@ "cell_type": "markdown", "id": "9ea7c00f-e3f4-4ac1-bfd5-449303a702a1", "metadata": { + "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -521,6 +574,7 @@ "cell_type": "markdown", "id": "0ab488b6-ddb3-4507-8f4e-de1c425106d6", "metadata": { + "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -569,6 +623,7 @@ "cell_type": "markdown", "id": "6c15a0a4-b22e-4d97-9ba1-b58d38fa84d9", "metadata": { + "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -629,6 +684,7 @@ "cell_type": "markdown", "id": "8783c551-27b2-4902-93c4-2187b1ba0fab", "metadata": { + "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -676,6 +732,7 @@ "cell_type": "markdown", "id": "deefbfcf-ab9a-4ced-a470-09b972b769af", "metadata": { + "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -707,6 +764,7 @@ "cell_type": "markdown", "id": "94015e81-cd8a-4f00-806f-bdf77251ea5c", "metadata": { + "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ From 91bcb44f2764914c4c0a921bfb6c45817c6ffc6c Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Tue, 23 Jan 2024 13:41:07 +0100 Subject: [PATCH 18/20] Refactoring of deprecated and unphysical use of the term isotope where nuclide is the correct one --- CHANGELOG.md | 6 +- ifes_apt_tc_data_modeling/env/env_reader.py | 4 +- ifes_apt_tc_data_modeling/fig/fig_reader.py | 2 +- .../imago/imago_reader.py | 2 +- ifes_apt_tc_data_modeling/nexus/nx_field.py | 5 - ifes_apt_tc_data_modeling/nexus/nx_ion.py | 81 +++++++--------- .../pyccapt/pyccapt_reader.py | 16 ++-- ifes_apt_tc_data_modeling/rng/rng_reader.py | 5 +- ifes_apt_tc_data_modeling/rrng/rrng_reader.py | 7 +- ifes_apt_tc_data_modeling/utils/mmapped_io.py | 5 - .../utils/molecular_ions.py | 96 +++++++++---------- .../utils/nist_isotope_data.py | 2 +- ifes_apt_tc_data_modeling/utils/utils.py | 39 ++++---- tests/TestsForDevelopers.ipynb | 80 +++++++--------- 14 files changed, 158 insertions(+), 192 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 998d58d..8ecedc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,4 @@ ## Changelog -**v0.0.7** -- Added Matlab code for extracting ranging definitions from Matlab figures to text -- Added FIG parser for creating proper molecular ion class instances of from these ranging definitions -- Fixed bug that the nuclid list did not show the mass number of isotopes +**v0.2** + diff --git a/ifes_apt_tc_data_modeling/env/env_reader.py b/ifes_apt_tc_data_modeling/env/env_reader.py index 99f15d1..601f4ab 100644 --- a/ifes_apt_tc_data_modeling/env/env_reader.py +++ b/ifes_apt_tc_data_modeling/env/env_reader.py @@ -24,7 +24,7 @@ import numpy as np from ifes_apt_tc_data_modeling.nexus.nx_ion import NxField, NxIon from ifes_apt_tc_data_modeling.utils.utils import \ - create_isotope_vector, is_range_significant, get_smart_chemical_symbols + create_nuclide_hash, is_range_significant, get_smart_chemical_symbols from ifes_apt_tc_data_modeling.utils.definitions import MQ_EPSILON @@ -114,7 +114,7 @@ def read_env(self): if dct is None: continue - m_ion = NxIon(isotope_vector=create_isotope_vector(dct["atoms"]), + m_ion = NxIon(nuclide_hash=create_nuclide_hash(dct["atoms"]), charge_state=0) m_ion.add_range(dct["range"][0], dct["range"][1]) m_ion.comment = NxField(dct["name"], "") diff --git a/ifes_apt_tc_data_modeling/fig/fig_reader.py b/ifes_apt_tc_data_modeling/fig/fig_reader.py index 6da0212..4ce0b23 100644 --- a/ifes_apt_tc_data_modeling/fig/fig_reader.py +++ b/ifes_apt_tc_data_modeling/fig/fig_reader.py @@ -94,7 +94,7 @@ def read_fig_txt(self): ivector = np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,), np.uint16) ivector[0:len(ivec)] = ivec - m_ion = NxIon(isotope_vector=ivector, charge_state=charge_state) + m_ion = NxIon(nuclide_hash=ivector, charge_state=charge_state) m_ion.add_range(mqmin, mqmax) m_ion.comment = NxField(ionname, "") m_ion.apply_combinatorics() diff --git a/ifes_apt_tc_data_modeling/imago/imago_reader.py b/ifes_apt_tc_data_modeling/imago/imago_reader.py index 5f5a380..34ea4dc 100644 --- a/ifes_apt_tc_data_modeling/imago/imago_reader.py +++ b/ifes_apt_tc_data_modeling/imago/imago_reader.py @@ -140,7 +140,7 @@ def read_imago_analysis_ranging_definitions(self): ivector = np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,), np.uint16) ivector[0:len(ivec)] = ivec - m_ion = NxIon(isotope_vector=ivector, charge_state=0) + m_ion = NxIon(nuclide_hash=ivector, charge_state=0) m_ion.add_range(float(mq[0]), float(mq[1])) m_ion.comment = NxField(" ".join(element_symbol), "") m_ion.apply_combinatorics() diff --git a/ifes_apt_tc_data_modeling/nexus/nx_field.py b/ifes_apt_tc_data_modeling/nexus/nx_field.py index 6e51ad5..cfd62ce 100644 --- a/ifes_apt_tc_data_modeling/nexus/nx_field.py +++ b/ifes_apt_tc_data_modeling/nexus/nx_field.py @@ -1,9 +1,4 @@ # -# Also convenience functions are included which translate human-readable ion -# names into the isotope_vector description proposed by Kuehbach et al. in -# DOI: 10.1017/S1431927621012241 to the human-readable ion names which are use -# in P. Felfer et al.'s atom probe toolbox -# # Copyright The NOMAD Authors. # # This file is part of NOMAD. See https://nomad-lab.eu for further info. diff --git a/ifes_apt_tc_data_modeling/nexus/nx_ion.py b/ifes_apt_tc_data_modeling/nexus/nx_ion.py index 831e4e8..463497f 100644 --- a/ifes_apt_tc_data_modeling/nexus/nx_ion.py +++ b/ifes_apt_tc_data_modeling/nexus/nx_ion.py @@ -1,9 +1,4 @@ # -# Also convenience functions are included which translate human-readable ion -# names into the isotope_vector description proposed by Kuehbach et al. in -# DOI: 10.1017/S1431927621012241 to the human-readable ion names which are use -# in P. Felfer et al.'s atom probe toolbox -# # Copyright The NOMAD Authors. # # This file is part of NOMAD. See https://nomad-lab.eu for further info. @@ -30,8 +25,8 @@ from ifes_apt_tc_data_modeling.utils.definitions import \ MAX_NUMBER_OF_ATOMS_PER_ION from ifes_apt_tc_data_modeling.utils.utils import \ - create_isotope_vector, isotope_vector_to_nuclid_list, \ - isotope_vector_to_human_readable_name, is_range_significant + create_nuclide_hash, nuclide_hash_to_nuclide_list, \ + nuclide_hash_to_human_readable_name, is_range_significant from ifes_apt_tc_data_modeling.utils.molecular_ions import \ MolecularIonCandidate, MolecularIonBuilder, \ PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ @@ -51,18 +46,18 @@ def __init__(self, *args, **kwargs): if len(args) >= 1: if isinstance(args[0], list) is False: raise ValueError("args[0] needs to be a list!") - self.isotope_vector = NxField(create_isotope_vector(args[0]), "") - elif "isotope_vector" in kwargs: - if isinstance(kwargs["isotope_vector"], np.ndarray) is False: - raise ValueError("kwargs isotope_vector needs to be an np.ndarray!") - if np.shape(kwargs["isotope_vector"]) != (MAX_NUMBER_OF_ATOMS_PER_ION,): + self.nuclide_hash = NxField(create_nuclide_hash(args[0]), "") + elif "nuclide_hash" in kwargs: + if isinstance(kwargs["nuclide_hash"], np.ndarray) is False: + raise ValueError("kwargs nuclide_hash needs to be an np.ndarray!") + if np.shape(kwargs["nuclide_hash"]) != (MAX_NUMBER_OF_ATOMS_PER_ION,): raise ValueError( - f"kwargs isotope_vector needs be a ({MAX_NUMBER_OF_ATOMS_PER_ION},) array!") - self.isotope_vector = NxField(np.asarray(kwargs["isotope_vector"], np.uint16), "") + f"kwargs nuclide_hash needs be a ({MAX_NUMBER_OF_ATOMS_PER_ION},) array!") + self.nuclide_hash = NxField(np.asarray(kwargs["nuclide_hash"], np.uint16), "") else: # the default UNKNOWN IONTYPE - self.isotope_vector = NxField(create_isotope_vector([]), "") - self.nuclid_list = NxField(isotope_vector_to_nuclid_list(self.isotope_vector.values), "") + self.nuclide_hash = NxField(create_nuclide_hash([]), "") + self.nuclide_list = NxField(nuclide_hash_to_nuclide_list(self.nuclide_hash.values), "") if "charge_state" in kwargs: if isinstance(kwargs["charge_state"], int) \ and (-8 < kwargs["charge_state"] < +8): @@ -72,8 +67,8 @@ def __init__(self, *args, **kwargs): # the relevant charge which is usually a sign that the range # is not matching the theoretically expect peak location self.charge_state = NxField(np.int8(0), "") - self.name = NxField(isotope_vector_to_human_readable_name( - self.isotope_vector.values, self.charge_state.values)) + self.name = NxField(nuclide_hash_to_human_readable_name( + self.nuclide_hash.values, self.charge_state.values)) self.ranges = NxField(np.empty((0, 2), np.float64), "amu") def add_range(self, mqmin: np.float64, mqmax: np.float64): @@ -90,15 +85,15 @@ def add_range(self, mqmin: np.float64, mqmax: np.float64): self.ranges.values = np.vstack((self.ranges.values, np.array([mqmin, mqmax]))) def update_human_readable_name(self): - """Re-evaluate charge and isotope_vector for name.""" - self.name = NxField(isotope_vector_to_human_readable_name( - self.isotope_vector.values, self.charge_state.values)) + """Re-evaluate charge and nuclide_hash for name.""" + self.name = NxField(nuclide_hash_to_human_readable_name( + self.nuclide_hash.values, self.charge_state.values)) def report(self): """Report values.""" print(f"ion_type: {self.ion_type.values}\n" - f"isotope_vector: {self.isotope_vector.values}\n" - f"nuclid_list: {self.nuclid_list.values}\n" + f"nuclide_hash: {self.nuclide_hash.values}\n" + f"nuclide_list: {self.nuclide_list.values}\n" f"human-readable name: {self.name.values}\n" f"charge_state: {self.charge_state.values}\n" f"ranges: {self.ranges.values}\n" @@ -115,7 +110,7 @@ def apply_combinatorics(self): sacrifice_uniqueness=SACRIFICE_ISOTOPIC_UNIQUENESS, verbose=VERBOSE) recovered_charge_state, m_ion_candidates = crawler.combinatorics( - self.isotope_vector.values, + self.nuclide_hash.values, self.ranges.values[0, 0], self.ranges.values[0, 1]) # print(f"{recovered_charge_state}") @@ -150,30 +145,28 @@ def add_charge_state_model(self, return self.charge_state_model["n_cand"] = n_cand if n_cand == 1: - self.charge_state_model["isotope_matrix"] = candidates[0].isotope_vector - self.charge_state_model["charge_state_vector"] = candidates[0].charge_state - self.charge_state_model["mass_vector"] = candidates[0].mass - self.charge_state_model["nat_abun_prod_vector"] = candidates[0].abundance_product - self.charge_state_model["min_half_life_vector"] = candidates[0].shortest_half_life + self.charge_state_model["nuclide_hash"] = candidates[0].nuclide_hash + self.charge_state_model["charge_state"] = candidates[0].charge_state + self.charge_state_model["mass"] = candidates[0].mass + self.charge_state_model["natural_abundance_product"] = candidates[0].abundance_product + self.charge_state_model["shortest_half_life"] = candidates[0].shortest_half_life else: - self.charge_state_model["isotope_matrix"] \ + self.charge_state_model["nuclide_hash"] \ = np.zeros((n_cand, MAX_NUMBER_OF_ATOMS_PER_ION), np.uint16) - self.charge_state_model["charge_state_vector"] \ - = np.zeros((n_cand,), np.int8) - self.charge_state_model["mass_vector"] \ - = np.zeros((n_cand,), np.float64) - self.charge_state_model["nat_abun_prod_vector"] \ - = np.zeros((n_cand,), np.float64) - self.charge_state_model["min_half_life_vector"] \ - = np.zeros((n_cand,), np.float64) + self.charge_state_model["charge_state"] = np.zeros((n_cand,), np.int8) + self.charge_state_model["mass"] = np.zeros((n_cand,), np.float64) + self.charge_state_model["natural_abundance_product"] = np.zeros((n_cand,), np.float64) + self.charge_state_model["shortest_half_life"] = np.zeros((n_cand,), np.float64) row_idx = 0 for cand in candidates: - self.charge_state_model["isotope_matrix"][row_idx, 0:len(cand.isotope_vector)] \ - = cand.isotope_vector - self.charge_state_model["charge_state_vector"][row_idx] = cand.charge_state - self.charge_state_model["mass_vector"][row_idx] = cand.mass - self.charge_state_model["nat_abun_prod_vector"][row_idx] \ + self.charge_state_model["nuclide_hash"][row_idx, 0:len(cand.nuclide_hash)] \ + = cand.nuclide_hash + self.charge_state_model["charge_state"][row_idx] \ + = cand.charge_state + self.charge_state_model["mass"][row_idx] \ + = cand.mass + self.charge_state_model["natural_abundance_product"][row_idx] \ = cand.abundance_product - self.charge_state_model["min_half_life_vector"][row_idx] \ + self.charge_state_model["shortest_half_life"][row_idx] \ = cand.shortest_half_life row_idx += 1 diff --git a/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py b/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py index 3c71cde..34f8486 100644 --- a/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py +++ b/ifes_apt_tc_data_modeling/pyccapt/pyccapt_reader.py @@ -30,7 +30,7 @@ from ifes_apt_tc_data_modeling.nexus.nx_ion import NxIon from ifes_apt_tc_data_modeling.nexus.nx_field import NxField from ifes_apt_tc_data_modeling.utils.utils import isotope_to_hash, \ - isotope_vector_to_nuclid_list, MAX_NUMBER_OF_ATOMS_PER_ION + nuclide_hash_to_nuclide_list, MAX_NUMBER_OF_ATOMS_PER_ION from ifes_apt_tc_data_modeling.utils.molecular_ions import get_chemical_symbols # from ifes_apt_tc_data_modeling.utils.combinatorics import apply_combinatorics @@ -61,8 +61,8 @@ SUPPORTED_PYCCAPT_VERSION = "e955beb4f2627befb8b4d26f2e74e4c52e00394e" -def get_isotope_vector_from_fau_list(elements, complexs, isotopes) -> np.ndarray: - """Compute isotope_vector from specific representation used at FAU/Erlangen.""" +def get_nuclide_hash_from_fau_list(elements, complexs, isotopes) -> np.ndarray: + """Compute nuclide_hash from specific representation used at FAU/Erlangen.""" # TODO:: add raise ValueError checks ivec = np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,), np.uint16) hashvector: list = [] @@ -198,12 +198,12 @@ def __init__(self, file_path: str): if self.df.iloc[idx, 6] == "unranged": continue - ivec = get_isotope_vector_from_fau_list(elements=self.df.iloc[idx, 6], - complexs=self.df.iloc[idx, 7], - isotopes=self.df.iloc[idx, 8]) + ivec = get_nuclide_hash_from_fau_list(elements=self.df.iloc[idx, 6], + complexs=self.df.iloc[idx, 7], + isotopes=self.df.iloc[idx, 8]) m_ion = NxIon() - m_ion.isotope_vector.values = ivec - m_ion.nuclid_list.values = isotope_vector_to_nuclid_list(ivec) + m_ion.nuclide_hash.values = ivec + m_ion.nuclide_list.values = nuclide_hash_to_nuclide_list(ivec) m_ion.charge_state.values = np.int8(self.df.iloc[idx, 9]) m_ion.add_range(self.df.iloc[idx, 3], self.df.iloc[idx, 4]) m_ion.apply_combinatorics() diff --git a/ifes_apt_tc_data_modeling/rng/rng_reader.py b/ifes_apt_tc_data_modeling/rng/rng_reader.py index 8537bc6..f834724 100644 --- a/ifes_apt_tc_data_modeling/rng/rng_reader.py +++ b/ifes_apt_tc_data_modeling/rng/rng_reader.py @@ -25,7 +25,7 @@ from ifes_apt_tc_data_modeling.nexus.nx_ion import NxField, NxIon from ifes_apt_tc_data_modeling.utils.utils import \ - create_isotope_vector, is_range_significant + create_nuclide_hash, is_range_significant from ifes_apt_tc_data_modeling.utils.definitions import MQ_EPSILON from ifes_apt_tc_data_modeling.utils.molecular_ions import get_chemical_symbols @@ -160,8 +160,7 @@ def read_rng(self): print(f"WARNING::RNG line {txt_stripped[idx]} is corrupted!") continue - m_ion = NxIon(isotope_vector=create_isotope_vector(dct["atoms"]), - charge_state=0) + m_ion = NxIon(nuclide_hash=create_nuclide_hash(dct["atoms"]), charge_state=0) m_ion.add_range(dct["range"][0], dct["range"][1]) m_ion.comment = NxField(dct["name"], "") m_ion.apply_combinatorics() diff --git a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py index 31498f2..3973327 100644 --- a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py +++ b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py @@ -26,7 +26,7 @@ from ase.data import chemical_symbols from ifes_apt_tc_data_modeling.nexus.nx_ion import NxField, NxIon from ifes_apt_tc_data_modeling.utils.utils import \ - create_isotope_vector, is_range_significant + create_nuclide_hash, is_range_significant from ifes_apt_tc_data_modeling.utils.definitions import MQ_EPSILON @@ -127,7 +127,7 @@ def read_rrng(self): # there are documented cases where experimentalists add custom strings # to specify ranges they consider special # these are loaded as user types - # with isotope_vector np.iinfo(np.uint16).max + # with nuclide_hash np.iinfo(np.uint16).max where = [idx for idx, element in enumerate(txt_stripped) if element == "[Ions]"] if isinstance(where, list) is False: @@ -184,8 +184,7 @@ def read_rrng(self): print(f"WARNING::RRNG line {txt_stripped[current_line_id + jdx]} is corrupted!") continue - m_ion = NxIon(isotope_vector=create_isotope_vector(dct["atoms"]), - charge_state=0) + m_ion = NxIon(nuclide_hash=create_nuclide_hash(dct["atoms"]), charge_state=0) m_ion.add_range(dct["range"][0], dct["range"][1]) m_ion.comment = NxField(dct["name"], "") m_ion.apply_combinatorics() diff --git a/ifes_apt_tc_data_modeling/utils/mmapped_io.py b/ifes_apt_tc_data_modeling/utils/mmapped_io.py index dbb583f..0bbc0eb 100644 --- a/ifes_apt_tc_data_modeling/utils/mmapped_io.py +++ b/ifes_apt_tc_data_modeling/utils/mmapped_io.py @@ -1,9 +1,4 @@ # -# Also convenience functions are included which translate human-readable ion -# names into the isotope_vector description proposed by Kuehbach et al. in -# DOI: 10.1017/S1431927621012241 to the human-readable ion names which are use -# in P. Felfer et al.'s atom probe toolbox -# # Copyright The NOMAD Authors. # # This file is part of NOMAD. See https://nomad-lab.eu for further info. diff --git a/ifes_apt_tc_data_modeling/utils/molecular_ions.py b/ifes_apt_tc_data_modeling/utils/molecular_ions.py index f8d189a..f906013 100644 --- a/ifes_apt_tc_data_modeling/utils/molecular_ions.py +++ b/ifes_apt_tc_data_modeling/utils/molecular_ions.py @@ -25,7 +25,7 @@ from ase.data import atomic_numbers, chemical_symbols from ifes_apt_tc_data_modeling.utils.utils import \ - isotope_to_hash, hash_to_isotope, isotope_vector_to_dict_keyword + isotope_to_hash, hash_to_isotope, nuclide_hash_to_dict_keyword from ifes_apt_tc_data_modeling.utils.nist_isotope_data import isotopes from ifes_apt_tc_data_modeling.utils.definitions import \ PRACTICAL_ABUNDANCE, PRACTICAL_ABUNDANCE_PRODUCT, \ @@ -39,7 +39,7 @@ def get_chemical_symbols(): class MolecularIonCandidate: - """Define (molecular) ion build from nuclids.""" + """Define (molecular) ion build from nuclides.""" def __init__(self, ivec, @@ -47,7 +47,7 @@ def __init__(self, mass_sum=0., nat_abun_prod=0., min_half_life=np.inf): - self.isotope_vector = np.asarray(np.atleast_1d(ivec), np.uint16) + self.nuclide_hash = np.asarray(ivec, np.uint16) self.charge_state = np.int8(charge_state) self.mass = np.float64(mass_sum) self.abundance_product = np.float64(nat_abun_prod) @@ -55,7 +55,7 @@ def __init__(self, def unique_keyword(self): """Generate unique keyword.""" - keyword = f"{isotope_vector_to_dict_keyword(np.sort(np.asarray(self.isotope_vector, np.uint16), kind='stable')[::-1])}__{self.charge_state}" + keyword = f"{nuclide_hash_to_dict_keyword(np.sort(np.asarray(self.nuclide_hash, np.uint16), kind='stable')[::-1])}__{self.charge_state}" return keyword @@ -68,13 +68,13 @@ def __init__(self, min_half_life=PRACTICAL_MIN_HALF_LIFE, sacrifice_uniqueness=SACRIFICE_ISOTOPIC_UNIQUENESS, verbose=VERBOSE): - self.nuclids = np.asarray([], np.uint16) + self.nuclides = np.asarray([], np.uint16) self.element_isotopes = {} - self.nuclid_mass = {} - self.nuclid_abundance = {} - self.nuclid_stable = {} # observationally stable - self.nuclid_unclear = {} # unclear halflife - self.nuclid_halflife = {} + self.nuclide_mass = {} + self.nuclide_abundance = {} + self.nuclide_stable = {} # observationally stable + self.nuclide_unclear = {} # unclear halflife + self.nuclide_halflife = {} self.candidates = [] self.parms = {"min_abundance": min_abundance, "min_abundance_product": min_abundance_product, @@ -94,9 +94,9 @@ def __init__(self, unclear_half_life = False # test if half-life data available - trial_nuclid_name = f"{symbol}-{mass_number}" + trial_nuclide_name = f"{symbol}-{mass_number}" try: - tmp = rd.Nuclide(trial_nuclid_name) + tmp = rd.Nuclide(trial_nuclide_name) except ValueError: tmp = None if tmp is not None: @@ -125,69 +125,69 @@ def __init__(self, abundance = isotopes[atomic_numbers[symbol]][mass_number]["composition"] hashvalue = isotope_to_hash(int(n_protons), int(n_neutrons)) if hashvalue != 0: - self.nuclids = np.append(self.nuclids, hashvalue) - self.nuclid_mass[hashvalue] = np.float64(mass) - self.nuclid_abundance[hashvalue] = np.float64(abundance) - self.nuclid_stable[hashvalue] = observationally_stable - self.nuclid_unclear[hashvalue] = unclear_half_life - self.nuclid_halflife[hashvalue] = half_life + self.nuclides = np.append(self.nuclides, hashvalue) + self.nuclide_mass[hashvalue] = np.float64(mass) + self.nuclide_abundance[hashvalue] = np.float64(abundance) + self.nuclide_stable[hashvalue] = observationally_stable + self.nuclide_unclear[hashvalue] = unclear_half_life + self.nuclide_halflife[hashvalue] = half_life element_isotopes = np.append(element_isotopes, hashvalue) self.element_isotopes[atomic_number] = np.sort( np.asarray(element_isotopes, np.uint16), kind="stable")[::-1] - self.nuclids = np.sort(self.nuclids, kind="stable")[::-1] + self.nuclides = np.sort(self.nuclides, kind="stable")[::-1] if self.parms["verbose"] is True: - print(f"MolecularIonBuilder initialized with {len(self.nuclids)}") + print(f"MolecularIonBuilder initialized with {len(self.nuclides)}") def get_element_isotopes(self, hashvalue): """List of hashvalues all isotopes of element specified by hashvalue.""" return self.element_isotopes[hash_to_isotope(hashvalue)[0]] - def get_isotope_mass_sum(self, nuclid_arr): + def get_isotope_mass_sum(self, nuclide_arr): """Evaluate cumulated atomic_mass of isotopes in ivec.""" # assuming no relativistic effects or other quantum effects # mass loss due to charge_state considered insignificant mass = 0. - for hashvalue in nuclid_arr: + for hashvalue in nuclide_arr: if hashvalue != 0: - mass += self.nuclid_mass[hashvalue] + mass += self.nuclide_mass[hashvalue] return mass - def get_natural_abundance_product(self, nuclid_arr): + def get_natural_abundance_product(self, nuclide_arr): """Get natural abundance product.""" abun_prod = 1. - for hashvalue in nuclid_arr: + for hashvalue in nuclide_arr: if hashvalue != 0: - abun_prod *= self.nuclid_abundance[hashvalue] + abun_prod *= self.nuclide_abundance[hashvalue] return abun_prod - def get_shortest_half_life(self, nuclid_arr): - """Get shortest half life for set of nuclids.""" + def get_shortest_half_life(self, nuclide_arr): + """Get shortest half life for set of nuclides.""" min_half_life = self.parms["min_half_life"] - for hashvalue in nuclid_arr: + for hashvalue in nuclide_arr: if hashvalue != 0: - if self.nuclid_halflife[hashvalue] != np.nan: - min_half_life = np.min((min_half_life, self.nuclid_halflife[hashvalue])) - # if the min_half_life is np.inf than we know that every nuclid in the + if self.nuclide_halflife[hashvalue] != np.nan: + min_half_life = np.min((min_half_life, self.nuclide_halflife[hashvalue])) + # if the min_half_life is np.inf than we know that every nuclide in the # molecular ion is observationally stable # if not we know that considering this molecular ion might not be a good # idea or only necessary in very few cases because even if we were - # to find such a combination of nuclids at least one would decay in observable + # to find such a combination of nuclides at least one would decay in observable # time and this might possibly hint that studying this molecular is tricky else: # if we do not information about the half-life it is very likely that - # this is an exotic nuclid likely never found in the wild + # this is an exotic nuclide likely never found in the wild return np.nan return min_half_life def combinatorics(self, element_arr, low, high): """Combinatorial analysis which (molecular) elements match within [low, high].""" # RNG/RRNG/ENV range files store (molecular) ion information for each range - # BUT neither nuclid not charge state information, here we try to recover + # BUT neither nuclide not charge state information, here we try to recover # both if possible or list all possible combinations # correspondingly this allows yield - # only an isotope_vector whose hashvalues have ALL in common + # only an nuclide_hash whose hashvalues have ALL in common # that the number of neutrons is 0, i.e. their hashvalue is the atomic_number - # element_arr is an isotope_vector/ivec with such hashvalues + # element_arr is an nuclide_hash/ivec with such hashvalues # as an example the molecular ion C:2 H:1 will map to 6, 6, 1 max_depth = 0 # number of non-zero entries in element_arr for hashvalue in element_arr: @@ -201,33 +201,33 @@ def combinatorics(self, element_arr, low, high): if max_depth > 0: depth = 0 - ith_nuclids = self.get_element_isotopes(element_arr[depth]) - cand_arr_curr = [] # combinatorially add nuclids while recursing deeper + ith_nuclides = self.get_element_isotopes(element_arr[depth]) + cand_arr_curr = [] # combinatorially add nuclides while recursing deeper self.iterate_molecular_ion( - element_arr, ith_nuclids, cand_arr_curr, + element_arr, ith_nuclides, cand_arr_curr, depth, max_depth, low, high) if self.parms["verbose"] is True: print(f"Found {len(self.candidates)} candidates!") for obj in self.candidates: - print(f"{obj.isotope_vector}, {obj.charge_state}, {obj.shortest_half_life}") + print(f"{obj.nuclide_hash}, {obj.charge_state}, {obj.shortest_half_life}") return self.try_to_reduce_to_unique_solution() # will return a tuple of charge_state and list of relevant_candidates return (0, []) def iterate_molecular_ion(self, - element_arr, jth_nuclids, cand_arr_prev, + element_arr, jth_nuclides, cand_arr_prev, i, max_n, low, high): """Recursive analysis of combinatorics on molecular ions.""" if i < (max_n - 1): - for nuclid in jth_nuclids: - ixxth_nuclids = self.get_element_isotopes(element_arr[i + 1]) - cand_arr_curr = np.append(cand_arr_prev, nuclid) + for nuclide in jth_nuclides: + ixxth_nuclides = self.get_element_isotopes(element_arr[i + 1]) + cand_arr_curr = np.append(cand_arr_prev, nuclide) self.iterate_molecular_ion( - element_arr, ixxth_nuclids, cand_arr_curr, + element_arr, ixxth_nuclides, cand_arr_curr, i + 1, max_n, low, high) elif i == (max_n - 1): - for nuclid in jth_nuclids: - cand_arr_curr = np.append(cand_arr_prev, nuclid) + for nuclide in jth_nuclides: + cand_arr_curr = np.append(cand_arr_prev, nuclide) # by this design the ivec does not necessarily remain ordered new_mass = self.get_isotope_mass_sum(cand_arr_curr) diff --git a/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py b/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py index 8332c4f..3050756 100644 --- a/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py +++ b/ifes_apt_tc_data_modeling/utils/nist_isotope_data.py @@ -16,7 +16,7 @@ # limitations under the License. # -"""Look-up table of stable and radioactive nuclids for all elements.""" +"""Look-up table of stable and radioactive nuclides for all elements.""" # pylint: disable:too-many-lines diff --git a/ifes_apt_tc_data_modeling/utils/utils.py b/ifes_apt_tc_data_modeling/utils/utils.py index f264431..509972c 100644 --- a/ifes_apt_tc_data_modeling/utils/utils.py +++ b/ifes_apt_tc_data_modeling/utils/utils.py @@ -18,10 +18,6 @@ """Utilities for working with molecular ions in atom probe microscopy.""" -# including convenience functions for translating human-readable ion names -# into the isotope_vector description proposed by Kühbach et al. in -# DOI: 10.1017/S1431927621012241 - from typing import Tuple import numpy as np @@ -62,12 +58,12 @@ def hash_to_isotope(hashvalue: int = 0) -> Tuple[int, int]: return (0, 0) -def create_isotope_vector(building_blocks: list) -> np.ndarray: +def create_nuclide_hash(building_blocks: list) -> np.ndarray: """Create specifically-shaped array of isotope hashvalues.""" # building_blocks are usually names of elements in the periodic table # if not we assume the ion is special such as user type or plain words # a typical expected test case is - # create_isotope_vector(["Fe", "Fe", "O", "O", "O"]) + # create_nuclide_hash(["Fe", "Fe", "O", "O", "O"]) ivec = np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,), np.uint16) if 0 < len(building_blocks) <= MAX_NUMBER_OF_ATOMS_PER_ION: symbol_to_proton_number = atomic_numbers @@ -88,28 +84,27 @@ def create_isotope_vector(building_blocks: list) -> np.ndarray: neutron_number = mass_number - proton_number if (proton_number in isotopes) and (mass_number in isotopes[proton_number]): hashvector.append(isotope_to_hash(proton_number, neutron_number)) - ivec[0:len(hashvector)] = np.sort( - np.asarray(hashvector, np.uint16), kind="stable")[::-1] + ivec[0:len(hashvector)] = np.sort(np.asarray(hashvector, np.uint16), kind="stable")[::-1] return ivec -def isotope_vector_to_nuclid_list(ivec: np.ndarray) -> np.ndarray: - """Create a NeXus NXion nuclid list.""" - nuclid_list = np.zeros((2, MAX_NUMBER_OF_ATOMS_PER_ION), np.uint16) +def nuclide_hash_to_nuclide_list(ivec: np.ndarray) -> np.ndarray: + """Create a NeXus NXion nuclide list.""" + nuclide_list = np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION, 2), np.uint16) if np.shape(ivec) == (MAX_NUMBER_OF_ATOMS_PER_ION,): for idx in np.arange(0, MAX_NUMBER_OF_ATOMS_PER_ION): if ivec[idx] != 0: - protons, neutrons = hash_to_isotope(int(ivec[idx])) - nuclid_list[0, idx] = protons + neutrons - nuclid_list[1, idx] = protons - return nuclid_list - print(f"WARNING:: Argument isotope_vector needs to be " - f"shaped {MAX_NUMBER_OF_ATOMS_PER_ION},) !") - return nuclid_list + n_protons, n_neutrons = hash_to_isotope(int(ivec[idx])) + if n_neutrons != 0: + nuclide_list[idx, 0] = n_protons + n_neutrons + nuclide_list[idx, 1] = n_protons + return nuclide_list + print(f"WARNING:: Argument nuclide_hash needs to be shaped ({MAX_NUMBER_OF_ATOMS_PER_ION},) !") + return nuclide_list -def isotope_vector_to_dict_keyword(ivec: np.ndarray) -> str: - """Create keyword for dictionary from isotope_vector.""" +def nuclide_hash_to_dict_keyword(ivec: np.ndarray) -> str: + """Create keyword for dictionary from nuclide_hash.""" if len(ivec) <= MAX_NUMBER_OF_ATOMS_PER_ION: lst = [] for hashvalue in ivec: @@ -120,8 +115,8 @@ def isotope_vector_to_dict_keyword(ivec: np.ndarray) -> str: return "0" # "_".join(np.asarray(np.zeros((MAX_NUMBER_OF_ATOMS_PER_ION,)), np.uint16)) -def isotope_vector_to_human_readable_name(ivec: np.ndarray, charge_state: np.int8) -> str: - """Get human-readable name from an isotope_vector.""" +def nuclide_hash_to_human_readable_name(ivec: np.ndarray, charge_state: np.int8) -> str: + """Get human-readable name from an nuclide_hash.""" if len(ivec) <= MAX_NUMBER_OF_ATOMS_PER_ION: human_readable = "" for hashvalue in ivec: diff --git a/tests/TestsForDevelopers.ipynb b/tests/TestsForDevelopers.ipynb index 3d5828b..b48c930 100644 --- a/tests/TestsForDevelopers.ipynb +++ b/tests/TestsForDevelopers.ipynb @@ -33,8 +33,8 @@ "import h5py\n", "import pandas as pd\n", "from jupyterlab_h5web import H5Web\n", - "from ifes_apt_tc_data_modeling.utils.utils import create_isotope_vector, \\\n", - " isotope_vector_to_dict_keyword, isotope_vector_to_human_readable_name, \\\n", + "from ifes_apt_tc_data_modeling.utils.utils import create_nuclide_hash, \\\n", + " nuclide_hash_to_dict_keyword, nuclide_hash_to_human_readable_name, \\\n", " isotope_to_hash, hash_to_isotope\n", "from ifes_apt_tc_data_modeling.nexus.nx_ion import NxIon\n", "from ifes_apt_tc_data_modeling.utils.molecular_ions import MolecularIonBuilder\n", @@ -56,9 +56,6 @@ "execution_count": null, "id": "393923ae-0736-4de9-94cc-9a0b1a47b56c", "metadata": { - "jupyter": { - "source_hidden": true - }, "tags": [] }, "outputs": [], @@ -72,11 +69,11 @@ " dst = fpw.create_dataset(f\"{trg}/color\", data=mion.color.values)\n", " # dst = fpw.create_dataset(f\"{trg}/volume\", dtype=np.float32, data=0.)\n", " # dst.attrs[\"unit\"] = \"nm^3\"\n", - " dst = fpw.create_dataset(f\"{trg}/isotope_vector\", dtype=np.uint16,\n", - " data=mion.isotope_vector.values, \n", + " dst = fpw.create_dataset(f\"{trg}/nuclide_hash\", dtype=np.uint16,\n", + " data=mion.nuclide_hash.values, \n", " chunks=True, compression=\"gzip\", compression_opts=1)\n", - " dst = fpw.create_dataset(f\"{trg}/nuclid_list\", dtype=np.uint16,\n", - " data=mion.nuclid_list.values,\n", + " dst = fpw.create_dataset(f\"{trg}/nuclide_list\", dtype=np.uint16,\n", + " data=mion.nuclide_list.values,\n", " chunks=True, compression=\"gzip\", compression_opts=1)\n", " dst = fpw.create_dataset(f\"{trg}/charge_state\", dtype=np.int8,\n", " data=mion.charge_state.values)\n", @@ -84,36 +81,37 @@ " dst = fpw.create_dataset(trg+ \"/mass_to_charge_range\", dtype=np.float32,\n", " data=mion.ranges.values)\n", " dst.attrs[\"unit\"] = \"Da\"\n", - " subgrpnm = f\"{trg}/charge_state_model\"\n", + " subgrpnm = f\"{trg}/charge_state_analysis\"\n", " subgrp = fpw.create_group(subgrpnm)\n", - " subgrp.attrs[\"NX_class\"] = \"NXprocess\"\n", + " subgrp.attrs[\"NX_class\"] = \"NXcharge_state_analysis\"\n", + " # config\n", " dst = fpw.create_dataset(f\"{subgrpnm}/min_abundance\", dtype=np.float64,\n", " data=mion.charge_state_model[\"min_abundance\"])\n", - " dst = fpw.create_dataset(f\"{subgrpnm}/min_abundance_product\", dtype=np.float64,\n", - " data=mion.charge_state_model[\"min_abundance_product\"])\n", + " # dst = fpw.create_dataset(f\"{subgrpnm}/min_abundance_product\", dtype=np.float64,\n", + " # data=mion.charge_state_model[\"min_abundance_product\"])\n", " dst = fpw.create_dataset(f\"{subgrpnm}/min_half_life\", dtype=np.float64,\n", " data=mion.charge_state_model[\"min_half_life\"])\n", " dst.attrs[\"unit\"] = \"s\"\n", " dst = fpw.create_dataset(f\"{subgrpnm}/sacrifice_isotopic_uniqueness\", dtype=np.uint8,\n", " data=mion.charge_state_model[\"sacrifice_isotopic_uniqueness\"])\n", - " opt_field_names = [\"isotope_matrix\", \"charge_state_vector\", \"mass_vector\", \"nat_abun_prod_vector\", \"min_half_life_vector\"]\n", + " opt_field_names = [\"nuclide_hash\", \"charge_state\", \"mass\", \"natural_abundance_product\", \"shortest_half_life\"]\n", " all_opt_available = True\n", " for opt_field_name in opt_field_names:\n", " if not opt_field_name in mion.charge_state_model:\n", " all_opt_available = False\n", " if all_opt_available == True:\n", - " dst = fpw.create_dataset(f\"{subgrpnm}/isotope_matrix\", dtype=np.uint16,\n", - " data=mion.charge_state_model[\"isotope_matrix\"],\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/nuclide_hash\", dtype=np.uint16,\n", + " data=mion.charge_state_model[\"nuclide_hash\"],\n", " chunks=True, compression=\"gzip\", compression_opts=1) \n", - " dst = fpw.create_dataset(f\"{subgrpnm}/charge_state_vector\", dtype=np.int8,\n", - " data=mion.charge_state_model[\"charge_state_vector\"])\n", - " dst = fpw.create_dataset(f\"{subgrpnm}/mass_vector\", dtype=np.float64,\n", - " data=mion.charge_state_model[\"mass_vector\"])\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/charge_state\", dtype=np.int8,\n", + " data=mion.charge_state_model[\"charge_state\"])\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/mass\", dtype=np.float64,\n", + " data=mion.charge_state_model[\"mass\"])\n", " dst.attrs[\"unit\"] = \"Da\"\n", - " dst = fpw.create_dataset(f\"{subgrpnm}/nat_abun_prod_vector\", dtype=np.float64,\n", - " data=mion.charge_state_model[\"nat_abun_prod_vector\"])\n", - " dst = fpw.create_dataset(f\"{subgrpnm}/min_half_life_vector\", dtype=np.float64,\n", - " data=mion.charge_state_model[\"min_half_life_vector\"])\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/natural_abundance_product\", dtype=np.float64,\n", + " data=mion.charge_state_model[\"natural_abundance_product\"])\n", + " dst = fpw.create_dataset(f\"{subgrpnm}/shortest_half_life\", dtype=np.float64,\n", + " data=mion.charge_state_model[\"shortest_half_life\"])\n", " dst.attrs[\"unit\"] = \"s\"" ] }, @@ -128,9 +126,7 @@ { "cell_type": "markdown", "id": "43671179-ab4f-411b-a275-0a99e9c4b5bd", - "metadata": { - "jp-MarkdownHeadingCollapsed": true - }, + "metadata": {}, "source": [ "## Imago *.analysis reader" ] @@ -169,9 +165,7 @@ { "cell_type": "markdown", "id": "8fd557cb-0fd5-404a-9893-416861913e73", - "metadata": { - "jp-MarkdownHeadingCollapsed": true - }, + "metadata": {}, "source": [ "## CSV reader" ] @@ -732,7 +726,6 @@ "cell_type": "markdown", "id": "deefbfcf-ab9a-4ced-a470-09b972b769af", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -748,23 +741,22 @@ }, "outputs": [], "source": [ - "# ivec = create_isotope_vector(['K-40', 'Xe-126']) # , 'U', 'H'])\n", - "# ivec = create_isotope_vector(['Tc', 'H', 'H']) # 'C'])\n", - "# ivec = create_isotope_vector(['B', 'B', 'B', 'N', 'N', 'Ti']) # 'N', 'N'])\n", - "# ivec = create_isotope_vector([])\n", - "ivec = create_isotope_vector(['O', 'O', 'O', 'O'])\n", - "ivec = create_isotope_vector(['Fe', 'Fe', 'O', 'O', 'O', 'O', 'O'])\n", - "# ivec = create_isotope_vector(['X'])\n", + "# ivec = create_nuclide_hash(['K-40', 'Xe-126']) # , 'U', 'H'])\n", + "# ivec = create_nuclide_hash(['Tc', 'H', 'H']) # 'C'])\n", + "# ivec = create_nuclide_hash(['B', 'B', 'B', 'N', 'N', 'Ti']) # 'N', 'N'])\n", + "# ivec = create_nuclide_hash([])\n", + "ivec = create_nuclide_hash(['O', 'O', 'O', 'O'])\n", + "ivec = create_nuclide_hash(['Fe', 'Fe', 'O', 'O', 'O', 'O', 'O'])\n", + "# ivec = create_nuclide_hash(['X'])\n", "print(ivec)\n", - "# print(isotope_vector_to_dict_keyword(ivec))\n", - "# print(isotope_vector_to_human_readable_name(ivec, +4))" + "# print(nuclide_hash_to_dict_keyword(ivec))\n", + "# print(nuclide_hash_to_human_readable_name(ivec, +4))" ] }, { "cell_type": "markdown", "id": "94015e81-cd8a-4f00-806f-bdf77251ea5c", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -780,7 +772,7 @@ }, "outputs": [], "source": [ - "ion = NxIon(isotope_vector=ivec, charge=0)\n", + "ion = NxIon(nuclide_hash=ivec, charge=0)\n", "# ion.add_range((np.floor(atomic_masses[43]) - 2.)*0.5, (np.floor(atomic_masses[43]) + 4.)*0.5)\n", "# ion.add_range(20.2840, 20.3680)\n", "# ion.add_range(54.9540, 54.9630)\n", @@ -810,7 +802,7 @@ " sacrifice_uniqueness=True,\n", " verbose=True)\n", "mion.combinatorics(\n", - " ion.isotope_vector.values,\n", + " ion.nuclide_hash.values,\n", " ion.ranges.values[0, 0],\n", " ion.ranges.values[0, 1])" ] @@ -832,7 +824,7 @@ "metadata": {}, "source": [ "***\n", - "Markus Kühbach, 2023/12/29
\n", + "Markus Kühbach, 2024/01/23
\n", "
\n", "FAIRmat is a consortium on research data management which is part of the German NFDI.
\n", "The project is funded by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) – project 460197019." From 499639cfc1544d8d05fa503db25d545938116c97 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Mon, 26 Feb 2024 09:24:36 +0100 Subject: [PATCH 19/20] Moved remaining duplicate code from paraprobe-toolbox such that the paraprobe-toolbox can from now on just use this library instead of duplicating again function definitions --- ifes_apt_tc_data_modeling/utils/utils.py | 104 +++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/ifes_apt_tc_data_modeling/utils/utils.py b/ifes_apt_tc_data_modeling/utils/utils.py index 509972c..9963949 100644 --- a/ifes_apt_tc_data_modeling/utils/utils.py +++ b/ifes_apt_tc_data_modeling/utils/utils.py @@ -19,6 +19,7 @@ """Utilities for working with molecular ions in atom probe microscopy.""" from typing import Tuple +import re import numpy as np from ase.data import atomic_numbers, chemical_symbols @@ -162,3 +163,106 @@ def is_range_significant(left: np.float64, right: np.float64) -> bool: if (right - left) > MQ_EPSILON: return True return False + + +def is_convertible_to_isotope_hash(symbol: str): + """Check if human_readable symbol is convertible into nuclide hash tribool.""" + case = re.search("^([A-Z])([a-z])?(-)([0-9]+)$", symbol) + if case is None: # eventually element case e.g. "K" + if not isinstance(symbol, str): + raise ValueError("Argument symbol needs to be a string !") + if symbol not in get_smart_chemical_symbols(): + raise ValueError(f"Symbol needs to be in {get_smart_chemical_symbols()}!") + return 1 + # alternative case eventually specific nuclide e.g. "K-40" + symb_mass = symbol.split("-") + if len(symb_mass) != 2: + raise TypeError("Argument symbol is not properly formatted -!") + if len(symb_mass[0]) != 1 and len(symb_mass[0]) != 2: + raise ValueError("Argument symbol is not properly formatted -!") + if len(symb_mass[1]) <= 0: + raise ValueError(f"Argument symbol {symb_mass[1]} needs to be a physical mass number!") + if symb_mass[0] not in get_smart_chemical_symbols(): + raise ValueError(f"{symb_mass[0]} is not a symbol in {get_smart_chemical_symbols()}!") + if int(symb_mass[1]) not in isotopes[atomic_numbers[symb_mass[0]]].keys(): + raise ValueError(f"No value for isotopes[atomic_numbers[{symb_mass[0]}][{int(symb_mass[1])}] exists!") + return 2 + + +def element_or_nuclide_to_hash(symbol: str): + """Converts an element symbol (e.g. K) or nuclide (K-40) to nuclide hash.""" + # consider moving this to the ifes_apt_tc_data_modeling library + case = is_convertible_to_isotope_hash(symbol) + if case == 1: + return isotope_to_hash(atomic_numbers[symbol], 0) + if case == 2: + symb_mass = symbol.split("-") + return isotope_to_hash(atomic_numbers[symb_mass[0]], + int(symb_mass[1]) - atomic_numbers[symb_mass[0]]) + return isotope_to_hash(0, 0) + + +def symbol_lst_to_matrix_of_nuclide_vector(method: str = "resolve_all", + symbol_lst: list = [], + **kwargs): + """Parse human-readable element/isotope names to paraprobe.""" + # method = "resolve_all" + # method = "resolve_unknown" + # method = "resolve_element" + # method = "resolve_isotope" + # method = "resolve_ion" + # symbol_lst = [["K", "C"], ["U-238", "H-2"]] + # symbol_lst = [["K-40", "C-14"], ["U-238", "H-2"]] # one list per mol. ion + # kwargs_charge_lst = [+1, +3] # one charge per ion + # resolve_all and resolve_unknown are the special cases + # where we do not need to specify a matrix of isotope vectors + if method in ("resolve_all", "resolve_unknown"): + return (None, None, None) + + supported = ("resolve_element", "resolve_ion", "resolve_isotope") + if method not in supported: + raise ValueError(f"Argument method needs to be in {supported} !") + if not isinstance(symbol_lst, list) and all(isinstance(lst, list) for lst in symbol_lst): + raise TypeError("Argument symbol_lst must be a list of lists!") + if not all(len(np.shape(lst)) == 1 for lst in symbol_lst): + "One list in argument symbol_lst is not a 1d list or an empty list!" + if not all(np.shape(lst)[0] >= 1 for lst in symbol_lst): + "One list in argument symbol_lst is not a 1d list or an empty list!" + matrix = np.zeros([len(symbol_lst), MAX_NUMBER_OF_ATOMS_PER_ION]) + charge = [] + if (method == "resolve_ion") and ("charge_lst" in kwargs): + if not isinstance(kwargs["charge_lst"], list): + raise TypeError("Keyword argument charge_lst must be a list of lists!") + if not all(isinstance(val, int) for val in kwargs["charge_lst"]): + raise ValueError("Keyword argument charge_lst needs to be a list of int !") + if np.shape(symbol_lst)[0] != np.shape(kwargs["charge_lst"])[0]: + raise ValueError("Argument symbol_lst and keyword argument charge_lst need to have the same length !") + for idx, lst in enumerate(symbol_lst): + ivec = np.zeros([1, MAX_NUMBER_OF_ATOMS_PER_ION]) + if lst == []: + raise ValueError("Argument molecular ion must not be an empty list!") + if len(lst) > MAX_NUMBER_OF_ATOMS_PER_ION: + raise ValueError(f"Argument molecular ion must not contain more than " + f"{MAX_NUMBER_OF_ATOMS_PER_ION} entries!") + jdx = 0 + for symbol in lst: + if method == "resolve_element": + if symbol in atomic_numbers: + ivec[0, jdx] = isotope_to_hash(atomic_numbers[symbol], 0) # do not encode isotope information + jdx += 1 + else: + # it might be that we have a specific nuclide e.g. K-40 try to parse element symbol + candidate = symbol.split("-", 1)[0] + if candidate not in atomic_numbers: + raise KeyError(f"symbol_lst[{idx}] candidate does not specify an element!") + ivec[0, jdx] = isotope_to_hash(atomic_numbers[candidate], 0) + jdx += 1 + else: # "resolve_isotope", "resolve_ion": + ivec[0, jdx] = element_or_nuclide_to_hash(symbol) + jdx += 1 + matrix[idx, :] = ivec[0, :] + if method == "resolve_ion": + charge.append(kwargs["charge_lst"][idx]) + if charge == []: + return (method, np.asarray(matrix, np.uint16), None) + return (method, np.asarray(matrix, np.uint16), np.asarray(charge, np.int8)) From 384fe89d25e85696abb2bea105ea30a7e56570a3 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Mon, 26 Feb 2024 09:32:03 +0100 Subject: [PATCH 20/20] Linting --- ifes_apt_tc_data_modeling/rng/rng_reader.py | 6 +++--- ifes_apt_tc_data_modeling/rrng/rrng_reader.py | 10 +++++----- ifes_apt_tc_data_modeling/utils/utils.py | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ifes_apt_tc_data_modeling/rng/rng_reader.py b/ifes_apt_tc_data_modeling/rng/rng_reader.py index f834724..3befe30 100644 --- a/ifes_apt_tc_data_modeling/rng/rng_reader.py +++ b/ifes_apt_tc_data_modeling/rng/rng_reader.py @@ -52,19 +52,19 @@ def evaluate_rng_range_line( raise ValueError(f"Line {line} has inconsistent line prefix!") if is_range_significant(np.float64(tmp[1]), np.float64(tmp[2])) is False: # raise ValueError(f"Line {line} insignificant range!") - return None + return info info["range"] = np.asarray([tmp[1], tmp[2]], np.float64) # line encodes multiplicity of element via array of multiplicity counts element_multiplicity = np.asarray(tmp[3:len(tmp)], np.uint32) if np.sum(element_multiplicity) < 0: # raise ValueError(f"Line {line} no element counts!") - return None + return info if np.sum(element_multiplicity) > 0: for jdx in np.arange(0, len(element_multiplicity)): if element_multiplicity[jdx] < 0: # raise ValueError(f"Line {line} no negative element counts!") - return None + raise ValueError(f"element_multiplicity[jdx] {element_multiplicity[jdx]} needs to be positive!") if element_multiplicity[jdx] > 0: symbol = column_id_to_label[jdx + 1] if symbol in get_chemical_symbols(): diff --git a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py index 3973327..2d011a8 100644 --- a/ifes_apt_tc_data_modeling/rrng/rrng_reader.py +++ b/ifes_apt_tc_data_modeling/rrng/rrng_reader.py @@ -47,13 +47,13 @@ def evaluate_rrng_range_line(i: int, line: str) -> dict: tmp = re.split(r"[\s=]+", line) if len(tmp) < 6: # raise ValueError(f"Line {line} does not contain all required fields {len(tmp)}!") - return None + return info if tmp[0] != f"Range{i}": # raise ValueError(f"Line {line} has inconsistent line prefix {tmp[0]}!") - return None + return info if is_range_significant(np.float64(tmp[1]), np.float64(tmp[2])) is False: # raise ValueError(f"Line {line} insignificant range!") - return None + return info info["range"] = np.asarray([tmp[1], tmp[2]], np.float64) if tmp[3].lower().startswith("vol:"): @@ -83,13 +83,13 @@ def evaluate_rrng_range_line(i: int, line: str) -> dict: symbol = element_multiplicity[0] if (symbol not in chemical_symbols) or (symbol == "X"): # raise ValueError(f"WARNING::Line {line} contains an invalid chemical symbol {symbol}!") - return None + return info # if np.uint32(element_multiplicity[1]) <= 0: # raise ValueError(f"Line {line} zero or negative multiplicity !") if np.uint32(element_multiplicity[1]) >= 256: # raise ValueError(f"Line {line} unsupported high multiplicity " # f"{np.uint32(element_multiplicity)}!") - return None + return info info["atoms"] = np.append(info["atoms"], [symbol] * int(element_multiplicity[1])) return info diff --git a/ifes_apt_tc_data_modeling/utils/utils.py b/ifes_apt_tc_data_modeling/utils/utils.py index 9963949..b9a0ea7 100644 --- a/ifes_apt_tc_data_modeling/utils/utils.py +++ b/ifes_apt_tc_data_modeling/utils/utils.py @@ -225,9 +225,9 @@ def symbol_lst_to_matrix_of_nuclide_vector(method: str = "resolve_all", if not isinstance(symbol_lst, list) and all(isinstance(lst, list) for lst in symbol_lst): raise TypeError("Argument symbol_lst must be a list of lists!") if not all(len(np.shape(lst)) == 1 for lst in symbol_lst): - "One list in argument symbol_lst is not a 1d list or an empty list!" + raise ValueError("One list in argument symbol_lst is not a 1d list or an empty list!") if not all(np.shape(lst)[0] >= 1 for lst in symbol_lst): - "One list in argument symbol_lst is not a 1d list or an empty list!" + raise ValueError("One list in argument symbol_lst is not a 1d list or an empty list!") matrix = np.zeros([len(symbol_lst), MAX_NUMBER_OF_ATOMS_PER_ION]) charge = [] if (method == "resolve_ion") and ("charge_lst" in kwargs):