From 6ab9571230916bb548d16973a4ea1c63b966742d Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Tue, 14 Feb 2023 15:35:01 +0100 Subject: [PATCH 01/11] Remove typesystem decorator from Table class --- ubermagtable/table.py | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/ubermagtable/table.py b/ubermagtable/table.py index a1995e3..d801e99 100644 --- a/ubermagtable/table.py +++ b/ubermagtable/table.py @@ -2,15 +2,11 @@ import matplotlib.pyplot as plt import numpy as np import pandas as pd -import ubermagutil.typesystem as ts import ubermagutil.units import ubermagtable.util as uu -@ts.typesystem( - data=ts.Typed(expected_type=pd.DataFrame), units=ts.Typed(expected_type=dict) -) class Table: """Tabular data class. @@ -111,6 +107,40 @@ def fromfile(cls, filename, /, x=None, rename=True): x=x, ) + @property + def data(self): + """Scalar data of the drive. + + Returns + ------- + pd.DataFrame + """ + return self._data + + @data.setter + def data(self, data): + if not isinstance(data, pd.DataFrame): + raise TypeError(f"Invalid {type(data)=}; expected 'pandas.DataFrame'.") + self._data = data + + @property + def units(self): + """Units of the scalar data. + + Returns + ------- + dict + + Keys are the columns in the ``data`` property, values the respective units. + """ + return self._units + + @units.setter + def units(self, units): + if not isinstance(units, dict): + raise TypeError(f"Invalid {type(units)=}; 'expected dict'.") + self._units = units + @property def x(self): """Independent variable. From fe7cadc7a518783a7538216828f454a2c3385219 Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Thu, 16 Feb 2023 16:52:25 +0100 Subject: [PATCH 02/11] Re-write reading tabular data --- ubermagtable/table.py | 229 +++++++++++++++++++++++- ubermagtable/util/__init__.py | 2 - ubermagtable/util/util.py | 317 ---------------------------------- 3 files changed, 221 insertions(+), 327 deletions(-) delete mode 100644 ubermagtable/util/util.py diff --git a/ubermagtable/table.py b/ubermagtable/table.py index d801e99..a82e5f2 100644 --- a/ubermagtable/table.py +++ b/ubermagtable/table.py @@ -1,11 +1,11 @@ +import re + import ipywidgets import matplotlib.pyplot as plt import numpy as np import pandas as pd import ubermagutil.units -import ubermagtable.util as uu - class Table: """Tabular data class. @@ -47,6 +47,139 @@ class Table: """ + # The OOMMF columns are renamed according to this dictionary. + _OOMMF_DICT = { + "RungeKuttaEvolve:evolver:Total energy": "E", + "RungeKuttaEvolve:evolver:Energy calc count": "E_calc_count", + "RungeKuttaEvolve:evolver:Max dm/dt": "max_dm/dt", + "RungeKuttaEvolve:evolver:dE/dt": "dE/dt", + "RungeKuttaEvolve:evolver:Delta E": "delta_E", + "RungeKuttaEvolve::Total energy": "E", + "RungeKuttaEvolve::Energy calc count": "E_calc_count", + "RungeKuttaEvolve::Max dm/dt": "max_dm/dt", + "RungeKuttaEvolve::dE/dt": "dE/dt", + "RungeKuttaEvolve::Delta E": "delta_E", + "EulerEvolve:evolver:Total energy": "E", + "EulerEvolve:evolver:Energy calc count": "E_calc_count", + "EulerEvolve:evolver:Max dm/dt": "max_dmdt", + "EulerEvolve:evolver:dE/dt": "dE/dt", + "EulerEvolve:evolver:Delta E": "delta_E", + "TimeDriver::Iteration": "iteration", + "TimeDriver::Stage iteration": "stage_iteration", + "TimeDriver::Stage": "stage", + "TimeDriver::mx": "mx", + "TimeDriver::my": "my", + "TimeDriver::mz": "mz", + "TimeDriver::Last time step": "last_time_step", + "TimeDriver::Simulation time": "t", + "CGEvolve:evolver:Max mxHxm": "max_mxHxm", + "CGEvolve:evolver:Total energy": "E", + "CGEvolve:evolver:Delta E": "delta_E", + "CGEvolve:evolver:Bracket count": "bracket_count", + "CGEvolve:evolver:Line min count": "line_min_count", + "CGEvolve:evolver:Conjugate cycle count": "conjugate_cycle_count", + "CGEvolve:evolver:Cycle count": "cycle_count", + "CGEvolve:evolver:Cycle sub count": "cycle_sub_count", + "CGEvolve:evolver:Energy calc count": "energy_calc_count", + "CGEvolve::Max mxHxm": "max_mxHxm", + "CGEvolve::Total energy": "E", + "CGEvolve::Delta E": "delta_E", + "CGEvolve::Bracket count": "bracket_count", + "CGEvolve::Line min count": "line_min_count", + "CGEvolve::Conjugate cycle count": "conjugate_cycle_count", + "CGEvolve::Cycle count": "cycle_count", + "CGEvolve::Cycle sub count": "cycle_sub_count", + "CGEvolve::Energy calc count": "energy_calc_count", + "FixedMEL::Energy": "MEL_E", + "FixedMEL:magnetoelastic:Energy": "MEL_E", + "SpinTEvolve:evolver:Total energy": "E", + "SpinTEvolve:evolver:Energy calc count": "E_calc_count", + "SpinTEvolve:evolver:Max dm/dt": "max_dmdt", + "SpinTEvolve:evolver:dE/dt": "dE/dt", + "SpinTEvolve:evolver:Delta E": "delta_E", + "SpinTEvolve:evolver:average u": "average_u", + "SpinXferEvolve:evolver:Total energy": "E", + "SpinXferEvolve:evolver:Energy calc count": "E_calc_count", + "SpinXferEvolve:evolver:Max dm/dt": "max_dmdt", + "SpinXferEvolve:evolver:dE/dt": "dE/dt", + "SpinXferEvolve:evolver:Delta E": "delta_E", + "SpinXferEvolve:evolver:average u": "average_u", + "SpinXferEvolve:evolver:average J": "average_J", + "ThetaEvolve:evolver:Total energy": "E", + "ThetaEvolve:evolver:Energy calc count": "E_calc_count", + "ThetaEvolve:evolver:Max dm/dt": "max_dmdt", + "ThetaEvolve:evolver:dE/dt": "dE/dt", + "ThetaEvolve:evolver:Delta E": "delta_E", + "ThetaEvolve:evolver:Temperature": "T", + "ThermHeunEvolve:evolver:Total energy": "E", + "ThermHeunEvolve:evolver:Energy calc count": "E_calc_count", + "ThermHeunEvolve:evolver:Max dm/dt": "max_dmdt", + "ThermHeunEvolve:evolver:dE/dt": "dE/dt", + "ThermHeunEvolve:evolver:Delta E": "delta_E", + "ThermHeunEvolve:evolver:Temperature": "T", + "ThermSpinXferEvolve:evolver:Total energy": "E", + "ThermSpinXferEvolve:evolver:Energy calc count": "E_calc_count", + "ThermSpinXferEvolve:evolver:Max dm/dt": "max_dmdt", + "ThermSpinXferEvolve:evolver:dE/dt": "dE/dt", + "ThermSpinXferEvolve:evolver:Delta E": "delta_E", + "ThermSpinXferEvolve:evolver:Temperature": "T", + "MinDriver::Iteration": "iteration", + "MinDriver::Stage iteration": "stage_iteration", + "MinDriver::Stage": "stage", + "MinDriver::mx": "mx", + "MinDriver::my": "my", + "MinDriver::mz": "mz", + "UniformExchange::Max Spin Ang": "max_spin_ang", + "UniformExchange::Stage Max Spin Ang": "stage_max_spin_ang", + "UniformExchange::Run Max Spin Ang": "run_max_spin_ang", + "UniformExchange::Energy": "E_exchange", + "DMExchange6Ngbr::Energy": "E", + "DMI_Cnv::Energy": "E", + "DMI_T::Energy": "E", + "DMI_D2d::Energy": "E", + "Demag::Energy": "E", + "FixedZeeman::Energy": "E_zeeman", + "UZeeman::Energy": "E_zeeman", + "UZeeman::B": "B", + "UZeeman::Bx": "Bx", + "UZeeman::By": "By", + "UZeeman::Bz": "Bz", + "ScriptUZeeman::Energy": "E", + "ScriptUZeeman::B": "B", + "ScriptUZeeman::Bx": "Bx", + "ScriptUZeeman::By": "By", + "ScriptUZeeman::Bz": "Bz", + "TransformZeeman::Energy": "E", + "CubicAnisotropy::Energy": "E", + "UniaxialAnisotropy::Energy": "E", + "UniaxialAnisotropy4::Energy": "E", + "Southampton_UniaxialAnisotropy4::Energy": "E", + "Exchange6Ngbr::Energy": "E", + "Exchange6Ngbr::Max Spin Ang": "max_spin_ang", + "Exchange6Ngbr::Stage Max Spin Ang": "stage_max_spin_ang", + "Exchange6Ngbr::Run Max Spin Ang": "run_max_spin_ang", + "ExchangePtwise::Energy": "E", + "ExchangePtwise::Max Spin Ang": "max_spin_ang", + "ExchangePtwise::Stage Max Spin Ang": "stage_max_spin_ang", + "ExchangePtwise::Run Max Spin Ang": "run_max_spin_ang", + "TwoSurfaceExchange::Energy": "E", + } + + # The mumax3 columns are renamed according to this dictionary. + _MUMAX3_DICT = { + "t": "t", + "mx": "mx", + "my": "my", + "mz": "mz", + "E_total": "E", + "E_exch": "E_totalexchange", + "E_demag": "E_demag", + "E_Zeeman": "E_zeeman", + "E_anis": "E_totalanisotropy", + "dt": "dt", + "maxTorque": "maxtorque", + } + def __init__(self, data, units, x=None, attributes=None): self.data = data self.units = units @@ -99,13 +232,93 @@ def fromfile(cls, filename, /, x=None, rename=True): >>> table = ut.Table.fromfile(odtfile, x='t') """ - cols = uu.columns(filename, rename=rename) - - return cls( - data=pd.DataFrame(uu.data(filename), columns=cols), - units=uu.units(filename, rename=rename), - x=x, + quantities = cls._read_header(filename, rename=rename) + data = pd.read_csv( + filename, + sep=r"\s+", + comment="#", + header=None, + names=list(quantities.keys()), ) + return cls(data=data, units=quantities, x=x) + + @classmethod + def _read_header(cls, filename, rename=True): + """Extracts quantities for individual columns from a table file. + + This method extracts both column names and units and returns a dictionary, + where keys are column names and values are the units. + + Parameters + ---------- + filename : str + + OOMMF ``.odt`` or mumax3 ``.txt`` file. + + rename : bool + + If ``rename=True``, the column names are renamed with their shorter + versions. Defaults to ``True``. + + Returns + ------- + dict + + Dictionary of column names and units. + """ + + with open(filename) as f: + if (header_line_1 := f.readline()).startswith("# ODT"): # OOMMF odt file + cols_dict = cls._OOMMF_DICT + # COLUMN NAMES + while not (cline := f.readline()).startswith("# Columns"): + pass + columns = cline.lstrip("# Columns:").rstrip() + cols = [ + re.sub(r"Oxs_|Anv_|Southampton_|My_|YY_|UHH_|Xf_", "", col) + for col in re.findall(r"(?<={)[^}]+|[^ {}]+", columns) + ] + # UNITS + uline = f.readline() + assert uline.startswith("# Units:") + units = uline.split()[2:] # [2:] to remove ["#", "Units:"] + units = [re.sub(r"[{}]", "", unit) for unit in units] + else: # mumax3 txt file + cols_dict = cls._MUMAX3_DICT + header_line_1 = header_line_1[len("# ") :].rstrip().split("\t") + # COLUMN NAMES + cols = [elem.split()[0] for elem in header_line_1] + # UNITS + units = [re.sub(r"[()]", "", elem.split()[1]) for elem in header_line_1] + + if rename: + cols = [cls._rename_column(col, cols_dict) for col in cols] + print(len(cols)) + print(len(set(cols))) + + return dict(zip(cols, units)) + + @staticmethod + def _rename_column(name, cols_dict): + """Rename columns to get shorter names without spaces. + + Renaming is based on _OOMMF_DICT or _MUMAX3_DICT. + """ + if name in cols_dict: + return cols_dict[name] + + for key in cols_dict: + if len(key.split("::")) == 2: + start, end = key.split("::") + name_split = name.split(":") + if name_split[0] == start and name_split[-1] == end: + term_name = name_split[1] + type_name = cols_dict[key] + # required for E_exchange in old and new OOMMF odt files + if not type_name.endswith(term_name): + type_name = f"{type_name}_{term_name}" + return type_name + return name # name cannot be found in dictionary @property def data(self): diff --git a/ubermagtable/util/__init__.py b/ubermagtable/util/__init__.py index 79f451e..e69de29 100644 --- a/ubermagtable/util/__init__.py +++ b/ubermagtable/util/__init__.py @@ -1,2 +0,0 @@ -"""Utility tools""" -from .util import columns, data, units diff --git a/ubermagtable/util/util.py b/ubermagtable/util/util.py deleted file mode 100644 index 4a9cff4..0000000 --- a/ubermagtable/util/util.py +++ /dev/null @@ -1,317 +0,0 @@ -import re - -# The OOMMF columns are renamed according to this dictionary. -oommf_dict = { - "RungeKuttaEvolve:evolver:Total energy": "E", - "RungeKuttaEvolve:evolver:Energy calc count": "E_calc_count", - "RungeKuttaEvolve:evolver:Max dm/dt": "max_dm/dt", - "RungeKuttaEvolve:evolver:dE/dt": "dE/dt", - "RungeKuttaEvolve:evolver:Delta E": "delta_E", - "RungeKuttaEvolve::Total energy": "E", - "RungeKuttaEvolve::Energy calc count": "E_calc_count", - "RungeKuttaEvolve::Max dm/dt": "max_dm/dt", - "RungeKuttaEvolve::dE/dt": "dE/dt", - "RungeKuttaEvolve::Delta E": "delta_E", - "EulerEvolve:evolver:Total energy": "E", - "EulerEvolve:evolver:Energy calc count": "E_calc_count", - "EulerEvolve:evolver:Max dm/dt": "max_dmdt", - "EulerEvolve:evolver:dE/dt": "dE/dt", - "EulerEvolve:evolver:Delta E": "delta_E", - "TimeDriver::Iteration": "iteration", - "TimeDriver::Stage iteration": "stage_iteration", - "TimeDriver::Stage": "stage", - "TimeDriver::mx": "mx", - "TimeDriver::my": "my", - "TimeDriver::mz": "mz", - "TimeDriver::Last time step": "last_time_step", - "TimeDriver::Simulation time": "t", - "CGEvolve:evolver:Max mxHxm": "max_mxHxm", - "CGEvolve:evolver:Total energy": "E", - "CGEvolve:evolver:Delta E": "delta_E", - "CGEvolve:evolver:Bracket count": "bracket_count", - "CGEvolve:evolver:Line min count": "line_min_count", - "CGEvolve:evolver:Conjugate cycle count": "conjugate_cycle_count", - "CGEvolve:evolver:Cycle count": "cycle_count", - "CGEvolve:evolver:Cycle sub count": "cycle_sub_count", - "CGEvolve:evolver:Energy calc count": "energy_calc_count", - "CGEvolve::Max mxHxm": "max_mxHxm", - "CGEvolve::Total energy": "E", - "CGEvolve::Delta E": "delta_E", - "CGEvolve::Bracket count": "bracket_count", - "CGEvolve::Line min count": "line_min_count", - "CGEvolve::Conjugate cycle count": "conjugate_cycle_count", - "CGEvolve::Cycle count": "cycle_count", - "CGEvolve::Cycle sub count": "cycle_sub_count", - "CGEvolve::Energy calc count": "energy_calc_count", - "FixedMEL::Energy": "MEL_E", - "FixedMEL:magnetoelastic:Energy": "MEL_E", - "SpinTEvolve:evolver:Total energy": "E", - "SpinTEvolve:evolver:Energy calc count": "E_calc_count", - "SpinTEvolve:evolver:Max dm/dt": "max_dmdt", - "SpinTEvolve:evolver:dE/dt": "dE/dt", - "SpinTEvolve:evolver:Delta E": "delta_E", - "SpinTEvolve:evolver:average u": "average_u", - "SpinXferEvolve:evolver:Total energy": "E", - "SpinXferEvolve:evolver:Energy calc count": "E_calc_count", - "SpinXferEvolve:evolver:Max dm/dt": "max_dmdt", - "SpinXferEvolve:evolver:dE/dt": "dE/dt", - "SpinXferEvolve:evolver:Delta E": "delta_E", - "SpinXferEvolve:evolver:average u": "average_u", - "SpinXferEvolve:evolver:average J": "average_J", - "ThetaEvolve:evolver:Total energy": "E", - "ThetaEvolve:evolver:Energy calc count": "E_calc_count", - "ThetaEvolve:evolver:Max dm/dt": "max_dmdt", - "ThetaEvolve:evolver:dE/dt": "dE/dt", - "ThetaEvolve:evolver:Delta E": "delta_E", - "ThetaEvolve:evolver:Temperature": "T", - "ThermHeunEvolve:evolver:Total energy": "E", - "ThermHeunEvolve:evolver:Energy calc count": "E_calc_count", - "ThermHeunEvolve:evolver:Max dm/dt": "max_dmdt", - "ThermHeunEvolve:evolver:dE/dt": "dE/dt", - "ThermHeunEvolve:evolver:Delta E": "delta_E", - "ThermHeunEvolve:evolver:Temperature": "T", - "ThermSpinXferEvolve:evolver:Total energy": "E", - "ThermSpinXferEvolve:evolver:Energy calc count": "E_calc_count", - "ThermSpinXferEvolve:evolver:Max dm/dt": "max_dmdt", - "ThermSpinXferEvolve:evolver:dE/dt": "dE/dt", - "ThermSpinXferEvolve:evolver:Delta E": "delta_E", - "ThermSpinXferEvolve:evolver:Temperature": "T", - "MinDriver::Iteration": "iteration", - "MinDriver::Stage iteration": "stage_iteration", - "MinDriver::Stage": "stage", - "MinDriver::mx": "mx", - "MinDriver::my": "my", - "MinDriver::mz": "mz", - "UniformExchange::Max Spin Ang": "max_spin_ang", - "UniformExchange::Stage Max Spin Ang": "stage_max_spin_ang", - "UniformExchange::Run Max Spin Ang": "run_max_spin_ang", - "UniformExchange::Energy": "E_exchange", - "DMExchange6Ngbr::Energy": "E", - "DMI_Cnv::Energy": "E", - "DMI_T::Energy": "E", - "DMI_D2d::Energy": "E", - "Demag::Energy": "E", - "FixedZeeman::Energy": "E_zeeman", - "UZeeman::Energy": "E_zeeman", - "UZeeman::B": "B", - "UZeeman::Bx": "Bx", - "UZeeman::By": "By", - "UZeeman::Bz": "Bz", - "ScriptUZeeman::Energy": "E", - "ScriptUZeeman::B": "B", - "ScriptUZeeman::Bx": "Bx", - "ScriptUZeeman::By": "By", - "ScriptUZeeman::Bz": "Bz", - "TransformZeeman::Energy": "E", - "CubicAnisotropy::Energy": "E", - "UniaxialAnisotropy::Energy": "E", - "UniaxialAnisotropy4::Energy": "E", - "Southampton_UniaxialAnisotropy4::Energy": "E", - "Exchange6Ngbr::Energy": "E", - "Exchange6Ngbr::Max Spin Ang": "max_spin_ang", - "Exchange6Ngbr::Stage Max Spin Ang": "stage_max_spin_ang", - "Exchange6Ngbr::Run Max Spin Ang": "run_max_spin_ang", - "ExchangePtwise::Energy": "E", - "ExchangePtwise::Max Spin Ang": "max_spin_ang", - "ExchangePtwise::Stage Max Spin Ang": "stage_max_spin_ang", - "ExchangePtwise::Run Max Spin Ang": "run_max_spin_ang", - "TwoSurfaceExchange::Energy": "E", -} - -# The mumax3 columns are renamed according to this dictionary. -mumax3_dict = { - "t": "t", - "mx": "mx", - "my": "my", - "mz": "mz", - "E_total": "E", - "E_exch": "E_totalexchange", - "E_demag": "E_demag", - "E_Zeeman": "E_zeeman", - "E_anis": "E_totalanisotropy", - "dt": "dt", - "maxTorque": "maxtorque", -} - - -def rename_column(name, cols_dict): - if name in cols_dict.keys(): - return cols_dict[name] - - for key in cols_dict.keys(): - if len(key.split("::")) == 2: - start, end = key.split("::") - name_split = name.split(":") - if name_split[0] == start and name_split[-1] == end: - term_name = name.split(":")[1] - type_name = cols_dict[key] - # required for E_exchange in old and new OOMMF odt files - if not type_name.endswith(term_name): - type_name = f"{type_name}_{term_name}" - return type_name - else: - return name # name cannot be found in dictionary - - -def columns(filename, rename=True): - """Extracts column names from a table file. - - Parameters - ---------- - filename : str - - OOMMF ``.odt`` or mumax3 ``.txt`` file. - - rename : bool - - If ``rename=True``, the column names are renamed with their shorter - versions. Defaults to ``True``. - - Returns - ------- - list - - List of column names. - - Examples - -------- - 1. Extracting the column names from an OOMMF `.odt` file. - - >>> import os - >>> import ubermagtable.util as uu - ... - >>> odtfile = os.path.join(os.path.dirname(__file__), '..', - ... 'tests', 'test_sample', 'oommf-new-file1.odt') - >>> uu.columns(odtfile) - [...] - - 2. Extracting the names of columns from a mumax3 `.txt` file. - - >>> odtfile = os.path.join(os.path.dirname(__file__), '..', - ... 'tests', 'test_sample', 'mumax3-file1.txt') - >>> uu.columns(odtfile) - [...] - - """ - with open(filename) as f: - lines = f.readlines() - - if lines[0].startswith("# ODT"): # OOMMF odt file - cline = list(filter(lambda line: line.startswith("# Columns:"), lines))[0] - cline = re.split(r"Oxs_|Anv_|Southampton_|My_|YY_|UHH_|Xf_", cline)[1:] - cline = list(map(lambda col: re.sub(r"[{}]", "", col), cline)) - cols = list(map(lambda s: s.strip(), cline)) - cols_dict = oommf_dict - else: # mumax3 txt file - cline = lines[0][2:].rstrip().split("\t") - cols = list(map(lambda s: s.split(" ")[0], cline)) - cols_dict = mumax3_dict - - if rename: - return [rename_column(col, cols_dict) for col in cols] - else: - return cols - - -def units(filename, rename=True): - """Extracts units for individual columns from a table file. - - This method extracts both column names and units and returns a dictionary, - where keys are column names and values are the units. - - Parameters - ---------- - filename : str - - OOMMF ``.odt`` or mumax3 ``.txt`` file. - - rename : bool - - If ``rename=True``, the column names are renamed with their shorter - versions. Defaults to ``True``. - - Returns - ------- - dict - - Dictionary of column names and units. - - Examples - -------- - 1. Extracting units for individual columns from an OOMMF ``.odt`` file. - - >>> import os - >>> import ubermagtable.util as uu - ... - >>> odtfile = os.path.join(os.path.dirname(__file__), '..', - ... 'tests', 'test_sample', 'oommf-new-file2.odt') - >>> uu.units(odtfile) - {...} - - 2. Extracting units for individual columns from a mumax3 ``.txt`` file. - - >>> odtfile = os.path.join(os.path.dirname(__file__), '..', - ... 'tests', 'test_sample', 'mumax3-file1.txt') - >>> uu.units(odtfile) - {...} - - """ - with open(filename) as f: - lines = f.readlines() - - if lines[0].startswith("# ODT"): # OOMMF odt file - uline = list(filter(lambda line: line.startswith("# Units:"), lines))[0] - units = uline.split()[2:] - units = list(map(lambda s: re.sub(r"[{}]", "", s), units)) - else: # mumax3 txt file - uline = lines[0][2:].rstrip().split("\t") - units = list(map(lambda s: s.split()[1], uline)) - units = list(map(lambda s: re.sub(r"[()]", "", s), units)) - - return dict(zip(columns(filename, rename=rename), units)) - - -def data(filename): - """Extracts numerical data from a table file. - - Parameters - ---------- - filename : str - - OOMMF ``.odt`` or mumax3 ``.txt`` file. - - Returns - ------- - list - - List of numerical data. - - Examples - -------- - 1. Reading data from an OOMMF ``.odt`` file. - - >>> import os - >>> import ubermagtable.util as uu - ... - >>> odtfile = os.path.join(os.path.dirname(__file__), '..', - ... 'tests', 'test_sample', 'oommf-new-file3.odt') - >>> uu.data(odtfile) - [...] - - 2. Reading data from a mumax3 ``.txt`` file. - - >>> odtfile = os.path.join(os.path.dirname(__file__), '..', - ... 'tests', 'test_sample', 'mumax3-file1.txt') - >>> uu.data(odtfile) - [...] - - """ - with open(filename) as f: - lines = f.readlines() - - values = [] - for line in lines: - if not line.startswith("#"): - values.append(list(map(float, line.split()))) - - return values From 5cb42d98509c57ab4da21b30340cb71c7d0976d3 Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Thu, 16 Feb 2023 16:54:16 +0100 Subject: [PATCH 03/11] Explain problem in test --- ubermagtable/tests/test_table.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ubermagtable/tests/test_table.py b/ubermagtable/tests/test_table.py index d1d3e69..305a1a7 100644 --- a/ubermagtable/tests/test_table.py +++ b/ubermagtable/tests/test_table.py @@ -178,6 +178,11 @@ def test_oommf_mel(self): assert len(columns) == 16 def test_oommf_issue1(self): + """The odt file contains columns ``Oxs_Exchange6Ngbr:...`` and + ``My_Exchange6Ngbr:...``. During processing we remove the ``Oxs_`` or ``My_`` + prefix and subsequently loose the "duplicated" columns in the pandas dataframe. + + """ table = ut.Table.fromfile(self.odtfiles[-1]) columns = table.data.columns.to_list() assert len(columns) == 30 From a8e4a063ca8c4069937f13995cc761037134c184 Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Fri, 17 Feb 2023 12:22:17 +0100 Subject: [PATCH 04/11] Detect and remove duplication in the data. --- ubermagtable/table.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ubermagtable/table.py b/ubermagtable/table.py index a82e5f2..1b252b8 100644 --- a/ubermagtable/table.py +++ b/ubermagtable/table.py @@ -186,6 +186,16 @@ def __init__(self, data, units, x=None, attributes=None): self.x = x self.attributes = attributes if attributes is not None else {} self.attributes.setdefault("fourierspace", False) + # Detect duplicated lines as a last step to make use of the checks when + # assigning 'x' as independent variable. + self._duplicated_lines = any(self.data.duplicated(subset=self.x, keep="last")) + if self._duplicated_lines: + self.data.drop_duplicates( + subset=self.x, + keep="last", + inplace=True, + ignore_index=True, # reset the index to 0, 1, ..., n-1 + ) @classmethod def fromfile(cls, filename, /, x=None, rename=True): @@ -442,6 +452,11 @@ def xmax(self): """ return self.data[self.x].iloc[-1] + @property + def deduplicated(self): + """Indicate if the table on disk contains duplicated steps.""" + return self._duplicated_lines + def apply(self, func, columns=None, args=(), **kwargs): r"""Apply function. From 62a687e2357f7922ef884ded45b1adc14bebbfbe Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Fri, 17 Feb 2023 12:29:04 +0100 Subject: [PATCH 05/11] Remove left-over print --- ubermagtable/table.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/ubermagtable/table.py b/ubermagtable/table.py index 1b252b8..f96d7e4 100644 --- a/ubermagtable/table.py +++ b/ubermagtable/table.py @@ -303,8 +303,6 @@ def _read_header(cls, filename, rename=True): if rename: cols = [cls._rename_column(col, cols_dict) for col in cols] - print(len(cols)) - print(len(set(cols))) return dict(zip(cols, units)) From cd9f7caf15896a126e2dbd9a529cf39f124e5f80 Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Mon, 20 Feb 2023 12:05:36 +0100 Subject: [PATCH 06/11] Update _OOMMF_DICT (add prefix) --- ubermagtable/table.py | 232 +++++++++++++++++++++--------------------- 1 file changed, 114 insertions(+), 118 deletions(-) diff --git a/ubermagtable/table.py b/ubermagtable/table.py index f96d7e4..63fcaa3 100644 --- a/ubermagtable/table.py +++ b/ubermagtable/table.py @@ -49,120 +49,119 @@ class Table: # The OOMMF columns are renamed according to this dictionary. _OOMMF_DICT = { - "RungeKuttaEvolve:evolver:Total energy": "E", - "RungeKuttaEvolve:evolver:Energy calc count": "E_calc_count", - "RungeKuttaEvolve:evolver:Max dm/dt": "max_dm/dt", - "RungeKuttaEvolve:evolver:dE/dt": "dE/dt", - "RungeKuttaEvolve:evolver:Delta E": "delta_E", - "RungeKuttaEvolve::Total energy": "E", - "RungeKuttaEvolve::Energy calc count": "E_calc_count", - "RungeKuttaEvolve::Max dm/dt": "max_dm/dt", - "RungeKuttaEvolve::dE/dt": "dE/dt", - "RungeKuttaEvolve::Delta E": "delta_E", - "EulerEvolve:evolver:Total energy": "E", - "EulerEvolve:evolver:Energy calc count": "E_calc_count", - "EulerEvolve:evolver:Max dm/dt": "max_dmdt", - "EulerEvolve:evolver:dE/dt": "dE/dt", - "EulerEvolve:evolver:Delta E": "delta_E", - "TimeDriver::Iteration": "iteration", - "TimeDriver::Stage iteration": "stage_iteration", - "TimeDriver::Stage": "stage", - "TimeDriver::mx": "mx", - "TimeDriver::my": "my", - "TimeDriver::mz": "mz", - "TimeDriver::Last time step": "last_time_step", - "TimeDriver::Simulation time": "t", - "CGEvolve:evolver:Max mxHxm": "max_mxHxm", - "CGEvolve:evolver:Total energy": "E", - "CGEvolve:evolver:Delta E": "delta_E", - "CGEvolve:evolver:Bracket count": "bracket_count", - "CGEvolve:evolver:Line min count": "line_min_count", - "CGEvolve:evolver:Conjugate cycle count": "conjugate_cycle_count", - "CGEvolve:evolver:Cycle count": "cycle_count", - "CGEvolve:evolver:Cycle sub count": "cycle_sub_count", - "CGEvolve:evolver:Energy calc count": "energy_calc_count", - "CGEvolve::Max mxHxm": "max_mxHxm", - "CGEvolve::Total energy": "E", - "CGEvolve::Delta E": "delta_E", - "CGEvolve::Bracket count": "bracket_count", - "CGEvolve::Line min count": "line_min_count", - "CGEvolve::Conjugate cycle count": "conjugate_cycle_count", - "CGEvolve::Cycle count": "cycle_count", - "CGEvolve::Cycle sub count": "cycle_sub_count", - "CGEvolve::Energy calc count": "energy_calc_count", - "FixedMEL::Energy": "MEL_E", - "FixedMEL:magnetoelastic:Energy": "MEL_E", - "SpinTEvolve:evolver:Total energy": "E", - "SpinTEvolve:evolver:Energy calc count": "E_calc_count", - "SpinTEvolve:evolver:Max dm/dt": "max_dmdt", - "SpinTEvolve:evolver:dE/dt": "dE/dt", - "SpinTEvolve:evolver:Delta E": "delta_E", - "SpinTEvolve:evolver:average u": "average_u", - "SpinXferEvolve:evolver:Total energy": "E", - "SpinXferEvolve:evolver:Energy calc count": "E_calc_count", - "SpinXferEvolve:evolver:Max dm/dt": "max_dmdt", - "SpinXferEvolve:evolver:dE/dt": "dE/dt", - "SpinXferEvolve:evolver:Delta E": "delta_E", - "SpinXferEvolve:evolver:average u": "average_u", - "SpinXferEvolve:evolver:average J": "average_J", - "ThetaEvolve:evolver:Total energy": "E", - "ThetaEvolve:evolver:Energy calc count": "E_calc_count", - "ThetaEvolve:evolver:Max dm/dt": "max_dmdt", - "ThetaEvolve:evolver:dE/dt": "dE/dt", - "ThetaEvolve:evolver:Delta E": "delta_E", - "ThetaEvolve:evolver:Temperature": "T", - "ThermHeunEvolve:evolver:Total energy": "E", - "ThermHeunEvolve:evolver:Energy calc count": "E_calc_count", - "ThermHeunEvolve:evolver:Max dm/dt": "max_dmdt", - "ThermHeunEvolve:evolver:dE/dt": "dE/dt", - "ThermHeunEvolve:evolver:Delta E": "delta_E", - "ThermHeunEvolve:evolver:Temperature": "T", - "ThermSpinXferEvolve:evolver:Total energy": "E", - "ThermSpinXferEvolve:evolver:Energy calc count": "E_calc_count", - "ThermSpinXferEvolve:evolver:Max dm/dt": "max_dmdt", - "ThermSpinXferEvolve:evolver:dE/dt": "dE/dt", - "ThermSpinXferEvolve:evolver:Delta E": "delta_E", - "ThermSpinXferEvolve:evolver:Temperature": "T", - "MinDriver::Iteration": "iteration", - "MinDriver::Stage iteration": "stage_iteration", - "MinDriver::Stage": "stage", - "MinDriver::mx": "mx", - "MinDriver::my": "my", - "MinDriver::mz": "mz", - "UniformExchange::Max Spin Ang": "max_spin_ang", - "UniformExchange::Stage Max Spin Ang": "stage_max_spin_ang", - "UniformExchange::Run Max Spin Ang": "run_max_spin_ang", - "UniformExchange::Energy": "E_exchange", - "DMExchange6Ngbr::Energy": "E", - "DMI_Cnv::Energy": "E", - "DMI_T::Energy": "E", - "DMI_D2d::Energy": "E", - "Demag::Energy": "E", - "FixedZeeman::Energy": "E_zeeman", - "UZeeman::Energy": "E_zeeman", - "UZeeman::B": "B", - "UZeeman::Bx": "Bx", - "UZeeman::By": "By", - "UZeeman::Bz": "Bz", - "ScriptUZeeman::Energy": "E", - "ScriptUZeeman::B": "B", - "ScriptUZeeman::Bx": "Bx", - "ScriptUZeeman::By": "By", - "ScriptUZeeman::Bz": "Bz", - "TransformZeeman::Energy": "E", - "CubicAnisotropy::Energy": "E", - "UniaxialAnisotropy::Energy": "E", - "UniaxialAnisotropy4::Energy": "E", - "Southampton_UniaxialAnisotropy4::Energy": "E", - "Exchange6Ngbr::Energy": "E", - "Exchange6Ngbr::Max Spin Ang": "max_spin_ang", - "Exchange6Ngbr::Stage Max Spin Ang": "stage_max_spin_ang", - "Exchange6Ngbr::Run Max Spin Ang": "run_max_spin_ang", - "ExchangePtwise::Energy": "E", - "ExchangePtwise::Max Spin Ang": "max_spin_ang", - "ExchangePtwise::Stage Max Spin Ang": "stage_max_spin_ang", - "ExchangePtwise::Run Max Spin Ang": "run_max_spin_ang", - "TwoSurfaceExchange::Energy": "E", + "Oxs_RungeKuttaEvolve:evolver:Total energy": "E", + "Oxs_RungeKuttaEvolve:evolver:Energy calc count": "E_calc_count", + "Oxs_RungeKuttaEvolve:evolver:Max dm/dt": "max_dm/dt", + "Oxs_RungeKuttaEvolve:evolver:dE/dt": "dE/dt", + "Oxs_RungeKuttaEvolve:evolver:Delta E": "delta_E", + "Oxs_RungeKuttaEvolve::Total energy": "E", + "Oxs_RungeKuttaEvolve::Energy calc count": "E_calc_count", + "Oxs_RungeKuttaEvolve::Max dm/dt": "max_dm/dt", + "Oxs_RungeKuttaEvolve::dE/dt": "dE/dt", + "Oxs_RungeKuttaEvolve::Delta E": "delta_E", + "Oxs_EulerEvolve:evolver:Total energy": "E", + "Oxs_EulerEvolve:evolver:Energy calc count": "E_calc_count", + "Oxs_EulerEvolve:evolver:Max dm/dt": "max_dmdt", + "Oxs_EulerEvolve:evolver:dE/dt": "dE/dt", + "Oxs_EulerEvolve:evolver:Delta E": "delta_E", + "Oxs_TimeDriver::Iteration": "iteration", + "Oxs_TimeDriver::Stage iteration": "stage_iteration", + "Oxs_TimeDriver::Stage": "stage", + "Oxs_TimeDriver::mx": "mx", + "Oxs_TimeDriver::my": "my", + "Oxs_TimeDriver::mz": "mz", + "Oxs_TimeDriver::Last time step": "last_time_step", + "Oxs_TimeDriver::Simulation time": "t", + "Oxs_CGEvolve:evolver:Max mxHxm": "max_mxHxm", + "Oxs_CGEvolve:evolver:Total energy": "E", + "Oxs_CGEvolve:evolver:Delta E": "delta_E", + "Oxs_CGEvolve:evolver:Bracket count": "bracket_count", + "Oxs_CGEvolve:evolver:Line min count": "line_min_count", + "Oxs_CGEvolve:evolver:Conjugate cycle count": "conjugate_cycle_count", + "Oxs_CGEvolve:evolver:Cycle count": "cycle_count", + "Oxs_CGEvolve:evolver:Cycle sub count": "cycle_sub_count", + "Oxs_CGEvolve:evolver:Energy calc count": "energy_calc_count", + "Oxs_CGEvolve::Max mxHxm": "max_mxHxm", + "Oxs_CGEvolve::Total energy": "E", + "Oxs_CGEvolve::Delta E": "delta_E", + "Oxs_CGEvolve::Bracket count": "bracket_count", + "Oxs_CGEvolve::Line min count": "line_min_count", + "Oxs_CGEvolve::Conjugate cycle count": "conjugate_cycle_count", + "Oxs_CGEvolve::Cycle count": "cycle_count", + "Oxs_CGEvolve::Cycle sub count": "cycle_sub_count", + "Oxs_CGEvolve::Energy calc count": "energy_calc_count", + "YY_FixedMEL::Energy": "MEL_E", + "YY_FixedMEL:magnetoelastic:Energy": "MEL_E", # NO SAMPLE, TODO DELETE? + "Anv_SpinTEvolve:evolver:Total energy": "E", + "Anv_SpinTEvolve:evolver:Energy calc count": "E_calc_count", + "Anv_SpinTEvolve:evolver:Max dm/dt": "max_dmdt", + "Anv_SpinTEvolve:evolver:dE/dt": "dE/dt", + "Anv_SpinTEvolve:evolver:Delta E": "delta_E", + "Anv_SpinTEvolve:evolver:average u": "average_u", + "Oxs_SpinXferEvolve:evolver:Total energy": "E", # NO SAMPLE + "Oxs_SpinXferEvolve:evolver:Energy calc count": "E_calc_count", # NO SAMPLE + "Oxs_SpinXferEvolve:evolver:Max dm/dt": "max_dmdt", # NO SAMPLE + "Oxs_SpinXferEvolve:evolver:dE/dt": "dE/dt", # NO SAMPLE + "Oxs_SpinXferEvolve:evolver:Delta E": "delta_E", # NO SAMPLE + "Oxs_SpinXferEvolve:evolver:average u": "average_u", # NO SAMPLE + "Oxs_SpinXferEvolve:evolver:average J": "average_J", # NO SAMPLE + "UHH_ThetaEvolve:evolver:Total energy": "E", # NO SAMPLE + "UHH_ThetaEvolve:evolver:Energy calc count": "E_calc_count", # NO SAMPLE + "UHH_ThetaEvolve:evolver:Max dm/dt": "max_dmdt", # NO SAMPLE + "UHH_ThetaEvolve:evolver:dE/dt": "dE/dt", # NO SAMPLE + "UHH_ThetaEvolve:evolver:Delta E": "delta_E", # NO SAMPLE + "UHH_ThetaEvolve:evolver:Temperature": "T", # NO SAMPLE + "Xf_ThermHeunEvolve:evolver:Total energy": "E", # NO SAMPLE + "Xf_ThermHeunEvolve:evolver:Energy calc count": "E_calc_count", # NO SAMPLE + "Xf_ThermHeunEvolve:evolver:Max dm/dt": "max_dmdt", # NO SAMPLE + "Xf_ThermHeunEvolve:evolver:dE/dt": "dE/dt", # NO SAMPLE + "Xf_ThermHeunEvolve:evolver:Delta E": "delta_E", # NO SAMPLE + "Xf_ThermHeunEvolve:evolver:Temperature": "T", # NO SAMPLE + "Xf_ThermSpinXferEvolve:evolver:Total energy": "E", # NO SAMPLE + "Xf_ThermSpinXferEvolve:evolver:Energy calc count": "E_calc_count", # NO SAMPLE + "Xf_ThermSpinXferEvolve:evolver:Max dm/dt": "max_dmdt", # NO SAMPLE + "Xf_ThermSpinXferEvolve:evolver:dE/dt": "dE/dt", # NO SAMPLE + "Xf_ThermSpinXferEvolve:evolver:Delta E": "delta_E", # NO SAMPLE + "Xf_ThermSpinXferEvolve:evolver:Temperature": "T", # NO SAMPLE + "Oxs_MinDriver::Iteration": "iteration", + "Oxs_MinDriver::Stage iteration": "stage_iteration", + "Oxs_MinDriver::Stage": "stage", + "Oxs_MinDriver::mx": "mx", + "Oxs_MinDriver::my": "my", + "Oxs_MinDriver::mz": "mz", + "Oxs_UniformExchange::Max Spin Ang": "max_spin_ang", + "Oxs_UniformExchange::Stage Max Spin Ang": "stage_max_spin_ang", + "Oxs_UniformExchange::Run Max Spin Ang": "run_max_spin_ang", + "Oxs_UniformExchange::Energy": "E_exchange", + "Oxs_DMExchange6Ngbr::Energy": "E", # NO SAMPLE + "Oxs_DMI_Cnv::Energy": "E", # TODO: PREFIX + "Oxs_DMI_T::Energy": "E", # NO SAMPLE, TODO: PREFIX + "Oxs_DMI_D2d::Energy": "E", # NO SAMPLE, TODO: PREFIX + "Oxs_Demag::Energy": "E", + "Oxs_FixedZeeman::Energy": "E_zeeman", + "Oxs_UZeeman::Energy": "E_zeeman", + "Oxs_UZeeman::B": "B", + "Oxs_UZeeman::Bx": "Bx", + "Oxs_UZeeman::By": "By", + "Oxs_UZeeman::Bz": "Bz", + "Oxs_ScriptUZeeman::Energy": "E", # NO SAMPLE + "Oxs_ScriptUZeeman::B": "B", # NO SAMPLE + "Oxs_ScriptUZeeman::Bx": "Bx", # NO SAMPLE + "Oxs_ScriptUZeeman::By": "By", # NO SAMPLE + "Oxs_ScriptUZeeman::Bz": "Bz", # NO SAMPLE + "Oxs_TransformZeeman::Energy": "E", # NO SAMPLE + "Oxs_CubicAnisotropy::Energy": "E", + "Oxs_UniaxialAnisotropy::Energy": "E", + "Southampton_UniaxialAnisotropy4::Energy": "E", # NO SAMPLE + "Oxs_Exchange6Ngbr::Energy": "E", + "Oxs_Exchange6Ngbr::Max Spin Ang": "max_spin_ang", + "Oxs_Exchange6Ngbr::Stage Max Spin Ang": "stage_max_spin_ang", + "Oxs_Exchange6Ngbr::Run Max Spin Ang": "run_max_spin_ang", + "Oxs_ExchangePtwise::Energy": "E", # NO SAMPLE + "Oxs_ExchangePtwise::Max Spin Ang": "max_spin_ang", # NO SAMPLE + "Oxs_ExchangePtwise::Stage Max Spin Ang": "stage_max_spin_ang", # NO SAMPLE + "Oxs_ExchangePtwise::Run Max Spin Ang": "run_max_spin_ang", # NO SAMPLE + "Oxs_TwoSurfaceExchange::Energy": "E", # NO SAMPLE } # The mumax3 columns are renamed according to this dictionary. @@ -284,10 +283,7 @@ def _read_header(cls, filename, rename=True): while not (cline := f.readline()).startswith("# Columns"): pass columns = cline.lstrip("# Columns:").rstrip() - cols = [ - re.sub(r"Oxs_|Anv_|Southampton_|My_|YY_|UHH_|Xf_", "", col) - for col in re.findall(r"(?<={)[^}]+|[^ {}]+", columns) - ] + cols = re.findall(r"(?<={)[^}]+|[^ {}]+", columns) # UNITS uline = f.readline() assert uline.startswith("# Units:") From 19348349665619d6ba4b7576d1541612924cc34d Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Mon, 20 Feb 2023 12:45:54 +0100 Subject: [PATCH 07/11] Re-write renaming functionality --- ubermagtable/table.py | 270 ++++++++++++++++++++++-------------------- 1 file changed, 142 insertions(+), 128 deletions(-) diff --git a/ubermagtable/table.py b/ubermagtable/table.py index 63fcaa3..b212408 100644 --- a/ubermagtable/table.py +++ b/ubermagtable/table.py @@ -49,119 +49,134 @@ class Table: # The OOMMF columns are renamed according to this dictionary. _OOMMF_DICT = { - "Oxs_RungeKuttaEvolve:evolver:Total energy": "E", - "Oxs_RungeKuttaEvolve:evolver:Energy calc count": "E_calc_count", - "Oxs_RungeKuttaEvolve:evolver:Max dm/dt": "max_dm/dt", - "Oxs_RungeKuttaEvolve:evolver:dE/dt": "dE/dt", - "Oxs_RungeKuttaEvolve:evolver:Delta E": "delta_E", - "Oxs_RungeKuttaEvolve::Total energy": "E", - "Oxs_RungeKuttaEvolve::Energy calc count": "E_calc_count", - "Oxs_RungeKuttaEvolve::Max dm/dt": "max_dm/dt", - "Oxs_RungeKuttaEvolve::dE/dt": "dE/dt", - "Oxs_RungeKuttaEvolve::Delta E": "delta_E", - "Oxs_EulerEvolve:evolver:Total energy": "E", - "Oxs_EulerEvolve:evolver:Energy calc count": "E_calc_count", - "Oxs_EulerEvolve:evolver:Max dm/dt": "max_dmdt", - "Oxs_EulerEvolve:evolver:dE/dt": "dE/dt", - "Oxs_EulerEvolve:evolver:Delta E": "delta_E", - "Oxs_TimeDriver::Iteration": "iteration", - "Oxs_TimeDriver::Stage iteration": "stage_iteration", - "Oxs_TimeDriver::Stage": "stage", - "Oxs_TimeDriver::mx": "mx", - "Oxs_TimeDriver::my": "my", - "Oxs_TimeDriver::mz": "mz", - "Oxs_TimeDriver::Last time step": "last_time_step", - "Oxs_TimeDriver::Simulation time": "t", - "Oxs_CGEvolve:evolver:Max mxHxm": "max_mxHxm", - "Oxs_CGEvolve:evolver:Total energy": "E", - "Oxs_CGEvolve:evolver:Delta E": "delta_E", - "Oxs_CGEvolve:evolver:Bracket count": "bracket_count", - "Oxs_CGEvolve:evolver:Line min count": "line_min_count", - "Oxs_CGEvolve:evolver:Conjugate cycle count": "conjugate_cycle_count", - "Oxs_CGEvolve:evolver:Cycle count": "cycle_count", - "Oxs_CGEvolve:evolver:Cycle sub count": "cycle_sub_count", - "Oxs_CGEvolve:evolver:Energy calc count": "energy_calc_count", - "Oxs_CGEvolve::Max mxHxm": "max_mxHxm", - "Oxs_CGEvolve::Total energy": "E", - "Oxs_CGEvolve::Delta E": "delta_E", - "Oxs_CGEvolve::Bracket count": "bracket_count", - "Oxs_CGEvolve::Line min count": "line_min_count", - "Oxs_CGEvolve::Conjugate cycle count": "conjugate_cycle_count", - "Oxs_CGEvolve::Cycle count": "cycle_count", - "Oxs_CGEvolve::Cycle sub count": "cycle_sub_count", - "Oxs_CGEvolve::Energy calc count": "energy_calc_count", - "YY_FixedMEL::Energy": "MEL_E", - "YY_FixedMEL:magnetoelastic:Energy": "MEL_E", # NO SAMPLE, TODO DELETE? - "Anv_SpinTEvolve:evolver:Total energy": "E", - "Anv_SpinTEvolve:evolver:Energy calc count": "E_calc_count", - "Anv_SpinTEvolve:evolver:Max dm/dt": "max_dmdt", - "Anv_SpinTEvolve:evolver:dE/dt": "dE/dt", - "Anv_SpinTEvolve:evolver:Delta E": "delta_E", - "Anv_SpinTEvolve:evolver:average u": "average_u", - "Oxs_SpinXferEvolve:evolver:Total energy": "E", # NO SAMPLE - "Oxs_SpinXferEvolve:evolver:Energy calc count": "E_calc_count", # NO SAMPLE - "Oxs_SpinXferEvolve:evolver:Max dm/dt": "max_dmdt", # NO SAMPLE - "Oxs_SpinXferEvolve:evolver:dE/dt": "dE/dt", # NO SAMPLE - "Oxs_SpinXferEvolve:evolver:Delta E": "delta_E", # NO SAMPLE - "Oxs_SpinXferEvolve:evolver:average u": "average_u", # NO SAMPLE - "Oxs_SpinXferEvolve:evolver:average J": "average_J", # NO SAMPLE - "UHH_ThetaEvolve:evolver:Total energy": "E", # NO SAMPLE - "UHH_ThetaEvolve:evolver:Energy calc count": "E_calc_count", # NO SAMPLE - "UHH_ThetaEvolve:evolver:Max dm/dt": "max_dmdt", # NO SAMPLE - "UHH_ThetaEvolve:evolver:dE/dt": "dE/dt", # NO SAMPLE - "UHH_ThetaEvolve:evolver:Delta E": "delta_E", # NO SAMPLE - "UHH_ThetaEvolve:evolver:Temperature": "T", # NO SAMPLE - "Xf_ThermHeunEvolve:evolver:Total energy": "E", # NO SAMPLE - "Xf_ThermHeunEvolve:evolver:Energy calc count": "E_calc_count", # NO SAMPLE - "Xf_ThermHeunEvolve:evolver:Max dm/dt": "max_dmdt", # NO SAMPLE - "Xf_ThermHeunEvolve:evolver:dE/dt": "dE/dt", # NO SAMPLE - "Xf_ThermHeunEvolve:evolver:Delta E": "delta_E", # NO SAMPLE - "Xf_ThermHeunEvolve:evolver:Temperature": "T", # NO SAMPLE - "Xf_ThermSpinXferEvolve:evolver:Total energy": "E", # NO SAMPLE - "Xf_ThermSpinXferEvolve:evolver:Energy calc count": "E_calc_count", # NO SAMPLE - "Xf_ThermSpinXferEvolve:evolver:Max dm/dt": "max_dmdt", # NO SAMPLE - "Xf_ThermSpinXferEvolve:evolver:dE/dt": "dE/dt", # NO SAMPLE - "Xf_ThermSpinXferEvolve:evolver:Delta E": "delta_E", # NO SAMPLE - "Xf_ThermSpinXferEvolve:evolver:Temperature": "T", # NO SAMPLE - "Oxs_MinDriver::Iteration": "iteration", - "Oxs_MinDriver::Stage iteration": "stage_iteration", - "Oxs_MinDriver::Stage": "stage", - "Oxs_MinDriver::mx": "mx", - "Oxs_MinDriver::my": "my", - "Oxs_MinDriver::mz": "mz", - "Oxs_UniformExchange::Max Spin Ang": "max_spin_ang", - "Oxs_UniformExchange::Stage Max Spin Ang": "stage_max_spin_ang", - "Oxs_UniformExchange::Run Max Spin Ang": "run_max_spin_ang", - "Oxs_UniformExchange::Energy": "E_exchange", - "Oxs_DMExchange6Ngbr::Energy": "E", # NO SAMPLE - "Oxs_DMI_Cnv::Energy": "E", # TODO: PREFIX - "Oxs_DMI_T::Energy": "E", # NO SAMPLE, TODO: PREFIX - "Oxs_DMI_D2d::Energy": "E", # NO SAMPLE, TODO: PREFIX - "Oxs_Demag::Energy": "E", - "Oxs_FixedZeeman::Energy": "E_zeeman", - "Oxs_UZeeman::Energy": "E_zeeman", - "Oxs_UZeeman::B": "B", - "Oxs_UZeeman::Bx": "Bx", - "Oxs_UZeeman::By": "By", - "Oxs_UZeeman::Bz": "Bz", - "Oxs_ScriptUZeeman::Energy": "E", # NO SAMPLE - "Oxs_ScriptUZeeman::B": "B", # NO SAMPLE - "Oxs_ScriptUZeeman::Bx": "Bx", # NO SAMPLE - "Oxs_ScriptUZeeman::By": "By", # NO SAMPLE - "Oxs_ScriptUZeeman::Bz": "Bz", # NO SAMPLE - "Oxs_TransformZeeman::Energy": "E", # NO SAMPLE - "Oxs_CubicAnisotropy::Energy": "E", - "Oxs_UniaxialAnisotropy::Energy": "E", - "Southampton_UniaxialAnisotropy4::Energy": "E", # NO SAMPLE - "Oxs_Exchange6Ngbr::Energy": "E", - "Oxs_Exchange6Ngbr::Max Spin Ang": "max_spin_ang", - "Oxs_Exchange6Ngbr::Stage Max Spin Ang": "stage_max_spin_ang", - "Oxs_Exchange6Ngbr::Run Max Spin Ang": "run_max_spin_ang", - "Oxs_ExchangePtwise::Energy": "E", # NO SAMPLE - "Oxs_ExchangePtwise::Max Spin Ang": "max_spin_ang", # NO SAMPLE - "Oxs_ExchangePtwise::Stage Max Spin Ang": "stage_max_spin_ang", # NO SAMPLE - "Oxs_ExchangePtwise::Run Max Spin Ang": "run_max_spin_ang", # NO SAMPLE - "Oxs_TwoSurfaceExchange::Energy": "E", # NO SAMPLE + "Oxs_RungeKuttaEvolve": { + "Total energy": "E", + "Energy calc count": "E_calc_count", + "Max dm/dt": "max_dm/dt", + "dE/dt": "dE/dt", + "Delta E": "delta_E", + }, + "Oxs_EulerEvolve": { + "Total energy": "E", + "Energy calc count": "E_calc_count", + "Max dm/dt": "max_dmdt", + "dE/dt": "dE/dt", + "Delta E": "delta_E", + }, + "Oxs_TimeDriver": { + "Iteration": "iteration", + "Stage iteration": "stage_iteration", + "Stage": "stage", + "mx": "mx", + "my": "my", + "mz": "mz", + "Last time step": "last_time_step", + "Simulation time": "t", + }, + "Oxs_CGEvolve": { + "Max mxHxm": "max_mxHxm", + "Total energy": "E", + "Delta E": "delta_E", + "Bracket count": "bracket_count", + "Line min count": "line_min_count", + "Conjugate cycle count": "conjugate_cycle_count", + "Cycle count": "cycle_count", + "Cycle sub count": "cycle_sub_count", + "Energy calc count": "energy_calc_count", + }, + "YY_FixedMEL": {"Energy": "MEL_E"}, + "Anv_SpinTEvolve": { + "Total energy": "E", + "Energy calc count": "E_calc_count", + "Max dm/dt": "max_dmdt", + "dE/dt": "dE/dt", + "Delta E": "delta_E", + "average u": "average_u", + }, + "Oxs_SpinXferEvolve": { + "Total energy": "E", # NO SAMPLE + "Energy calc count": "E_calc_count", # NO SAMPLE + "Max dm/dt": "max_dmdt", # NO SAMPLE + "dE/dt": "dE/dt", # NO SAMPLE + "Delta E": "delta_E", # NO SAMPLE + "average u": "average_u", # NO SAMPLE + "average J": "average_J", # NO SAMPLE + }, + "UHH_ThetaEvolve": { + "Total energy": "E", # NO SAMPLE + "Energy calc count": "E_calc_count", # NO SAMPLE + "Max dm/dt": "max_dmdt", # NO SAMPLE + "dE/dt": "dE/dt", # NO SAMPLE + "Delta E": "delta_E", # NO SAMPLE + "Temperature": "T", # NO SAMPLE + }, + "Xf_ThermHeunEvolve": { + "Total energy": "E", # NO SAMPLE + "Energy calc count": "E_calc_count", # NO SAMPLE + "Max dm/dt": "max_dmdt", # NO SAMPLE + "dE/dt": "dE/dt", # NO SAMPLE + "Delta E": "delta_E", # NO SAMPLE + "Temperature": "T", # NO SAMPLE + }, + "Xf_ThermSpinXferEvolve": { + "Total energy": "E", # NO SAMPLE + "Energy calc count": "E_calc_count", # NO SAMPLE + "Max dm/dt": "max_dmdt", # NO SAMPLE + "dE/dt": "dE/dt", # NO SAMPLE + "Delta E": "delta_E", # NO SAMPLE + "Temperature": "T", # NO SAMPLE + }, + "Oxs_MinDriver": { + "Iteration": "iteration", + "Stage iteration": "stage_iteration", + "Stage": "stage", + "mx": "mx", + "my": "my", + "mz": "mz", + }, + "Oxs_UniformExchange": { + "Max Spin Ang": "max_spin_ang", + "Stage Max Spin Ang": "stage_max_spin_ang", + "Run Max Spin Ang": "run_max_spin_ang", + "Energy": "E_exchange", + }, + "Oxs_DMExchange6Ngbr": {"Energy": "E_DM_exchange6ngbr"}, # NO SAMPLE + "Oxs_DMI_Cnv": {"Energy": "E_DMI_Cnv"}, # TODO: PREFIX + "Oxs_DMI_T": {"Energy": "E_DMI_T"}, # NO SAMPLE, TODO: PREFIX + "Oxs_DMI_D2d": {"Energy": "E_DMI_Dd"}, # NO SAMPLE, TODO: PREFIX + "Oxs_Demag": {"Energy": "E_demag"}, + "Oxs_FixedZeeman": {"Energy": "E_zeeman"}, + "Oxs_UZeeman": { + "Energy": "E_zeeman", + "B": "B", + "Bx": "Bx", + "By": "By", + "Bz": "Bz", + }, + "Oxs_ScriptUZeeman": { + "Energy": "E_zeeman", # NO SAMPLE + "B": "B", # NO SAMPLE + "Bx": "Bx", # NO SAMPLE + "By": "By", # NO SAMPLE + "Bz": "Bz", # NO SAMPLE + }, + "Oxs_TransformZeeman": {"Energy": "E_zeeman"}, # NO SAMPLE + "Oxs_CubicAnisotropy": {"Energy": "E_zeeman"}, + "Oxs_UniaxialAnisotropy": {"Energy": "E_zeeman"}, + "Southampton_UniaxialAnisotropy4": {"Energy": "E_zeeman"}, # NO SAMPLE + "Oxs_Exchange6Ngbr": { + "Energy": "E_exchange6ngbr", + "Max Spin Ang": "max_spin_ang", + "Stage Max Spin Ang": "stage_max_spin_ang", + "Run Max Spin Ang": "run_max_spin_ang", + }, + "Oxs_ExchangePtwise": { + "Energy": "E_exchange_ptwise", # NO SAMPLE + "Max Spin Ang": "max_spin_ang", # NO SAMPLE + "Stage Max Spin Ang": "stage_max_spin_ang", # NO SAMPLE + "Run Max Spin Ang": "run_max_spin_ang", # NO SAMPLE + }, + "Oxs_TwoSurfaceExchange": {"Energy": "E_two_surface_exchange"}, # NO SAMPLE } # The mumax3 columns are renamed according to this dictionary. @@ -308,21 +323,20 @@ def _rename_column(name, cols_dict): Renaming is based on _OOMMF_DICT or _MUMAX3_DICT. """ - if name in cols_dict: - return cols_dict[name] - - for key in cols_dict: - if len(key.split("::")) == 2: - start, end = key.split("::") - name_split = name.split(":") - if name_split[0] == start and name_split[-1] == end: - term_name = name_split[1] - type_name = cols_dict[key] - # required for E_exchange in old and new OOMMF odt files - if not type_name.endswith(term_name): - type_name = f"{type_name}_{term_name}" - return type_name - return name # name cannot be found in dictionary + name_split = name.split(":") + try: + group = cols_dict[name_split[0]] + if isinstance(group, str): # Mumax3 keys + return group + quantity = group[name_split[-1]] + term_name = name_split[1] + if not quantity.endswith(term_name): + # unique names if the same quantity is present multiple times + # e.g. multiple Zeeman fields + quantity = f"{quantity}_{term_name}" + return quantity + except KeyError: + return name @property def data(self): From 154a47163a2ffd87f49fc327cbcd682d04403f5c Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Mon, 20 Feb 2023 12:48:05 +0100 Subject: [PATCH 08/11] Re-order _OOMMF_DICT --- ubermagtable/table.py | 50 +++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/ubermagtable/table.py b/ubermagtable/table.py index b212408..1011bd9 100644 --- a/ubermagtable/table.py +++ b/ubermagtable/table.py @@ -63,16 +63,6 @@ class Table: "dE/dt": "dE/dt", "Delta E": "delta_E", }, - "Oxs_TimeDriver": { - "Iteration": "iteration", - "Stage iteration": "stage_iteration", - "Stage": "stage", - "mx": "mx", - "my": "my", - "mz": "mz", - "Last time step": "last_time_step", - "Simulation time": "t", - }, "Oxs_CGEvolve": { "Max mxHxm": "max_mxHxm", "Total energy": "E", @@ -84,7 +74,6 @@ class Table: "Cycle sub count": "cycle_sub_count", "Energy calc count": "energy_calc_count", }, - "YY_FixedMEL": {"Energy": "MEL_E"}, "Anv_SpinTEvolve": { "Total energy": "E", "Energy calc count": "E_calc_count", @@ -134,17 +123,40 @@ class Table: "my": "my", "mz": "mz", }, + "Oxs_TimeDriver": { + "Iteration": "iteration", + "Stage iteration": "stage_iteration", + "Stage": "stage", + "mx": "mx", + "my": "my", + "mz": "mz", + "Last time step": "last_time_step", + "Simulation time": "t", + }, "Oxs_UniformExchange": { "Max Spin Ang": "max_spin_ang", "Stage Max Spin Ang": "stage_max_spin_ang", "Run Max Spin Ang": "run_max_spin_ang", "Energy": "E_exchange", }, + "Oxs_Exchange6Ngbr": { + "Energy": "E_exchange6ngbr", + "Max Spin Ang": "max_spin_ang", + "Stage Max Spin Ang": "stage_max_spin_ang", + "Run Max Spin Ang": "run_max_spin_ang", + }, + "Oxs_ExchangePtwise": { + "Energy": "E_exchange_ptwise", # NO SAMPLE + "Max Spin Ang": "max_spin_ang", # NO SAMPLE + "Stage Max Spin Ang": "stage_max_spin_ang", # NO SAMPLE + "Run Max Spin Ang": "run_max_spin_ang", # NO SAMPLE + }, + "Oxs_TwoSurfaceExchange": {"Energy": "E_two_surface_exchange"}, # NO SAMPLE + "Oxs_Demag": {"Energy": "E_demag"}, "Oxs_DMExchange6Ngbr": {"Energy": "E_DM_exchange6ngbr"}, # NO SAMPLE "Oxs_DMI_Cnv": {"Energy": "E_DMI_Cnv"}, # TODO: PREFIX "Oxs_DMI_T": {"Energy": "E_DMI_T"}, # NO SAMPLE, TODO: PREFIX "Oxs_DMI_D2d": {"Energy": "E_DMI_Dd"}, # NO SAMPLE, TODO: PREFIX - "Oxs_Demag": {"Energy": "E_demag"}, "Oxs_FixedZeeman": {"Energy": "E_zeeman"}, "Oxs_UZeeman": { "Energy": "E_zeeman", @@ -164,19 +176,7 @@ class Table: "Oxs_CubicAnisotropy": {"Energy": "E_zeeman"}, "Oxs_UniaxialAnisotropy": {"Energy": "E_zeeman"}, "Southampton_UniaxialAnisotropy4": {"Energy": "E_zeeman"}, # NO SAMPLE - "Oxs_Exchange6Ngbr": { - "Energy": "E_exchange6ngbr", - "Max Spin Ang": "max_spin_ang", - "Stage Max Spin Ang": "stage_max_spin_ang", - "Run Max Spin Ang": "run_max_spin_ang", - }, - "Oxs_ExchangePtwise": { - "Energy": "E_exchange_ptwise", # NO SAMPLE - "Max Spin Ang": "max_spin_ang", # NO SAMPLE - "Stage Max Spin Ang": "stage_max_spin_ang", # NO SAMPLE - "Run Max Spin Ang": "run_max_spin_ang", # NO SAMPLE - }, - "Oxs_TwoSurfaceExchange": {"Energy": "E_two_surface_exchange"}, # NO SAMPLE + "YY_FixedMEL": {"Energy": "MEL_E"}, } # The mumax3 columns are renamed according to this dictionary. From d205f9bbbf5309167980f468581251421b110b4b Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Mon, 20 Feb 2023 12:57:24 +0100 Subject: [PATCH 09/11] Move tests for columns and units to Table class --- ubermagtable/tests/test_table.py | 28 ++++++++++++++-- ubermagtable/tests/test_util.py | 55 -------------------------------- 2 files changed, 26 insertions(+), 57 deletions(-) delete mode 100644 ubermagtable/tests/test_util.py diff --git a/ubermagtable/tests/test_table.py b/ubermagtable/tests/test_table.py index 305a1a7..5bae337 100644 --- a/ubermagtable/tests/test_table.py +++ b/ubermagtable/tests/test_table.py @@ -68,10 +68,34 @@ def test_init(self): assert isinstance(table.data, pd.DataFrame) def test_fromfile(self): + for odtfile in self.odtfiles: + table = ut.Table.fromfile(odtfile, rename=False) + check_table(table) + + table_short_names = ut.Table.fromfile(odtfile, rename=True) + check_table(table_short_names) + + assert len(table.data) == len(table_short_names.data) + assert len(table.data.columns) == len(table_short_names.data.columns) + + def test_columns(self): + for odtfile in self.odtfiles: + for rename in [True, False]: + table = ut.Table.fromfile(odtfile, rename=rename) + columns = table.data.columns + assert all(isinstance(column, str) for column in columns) + assert len(columns) == len(set(columns)) # unique column names + + def test_units(self): for odtfile in self.odtfiles: for rename in [True, False]: - table = ut.Table.fromfile(odtfile) - check_table(table) + table = ut.Table.fromfile(odtfile, rename=rename) + units = table.units + assert isinstance(units, dict) + assert all(isinstance(unit, str) for unit in units.keys()) + assert all(isinstance(unit, str) for unit in units.values()) + assert "J" in units.values() # Energy is always in + assert "" in units.values() # Columns with no units are always in def test_xy(self): table = ut.Table.fromfile(self.odtfiles[0], x="t") diff --git a/ubermagtable/tests/test_util.py b/ubermagtable/tests/test_util.py deleted file mode 100644 index 0d45ebe..0000000 --- a/ubermagtable/tests/test_util.py +++ /dev/null @@ -1,55 +0,0 @@ -import itertools -import numbers -import os - -import ubermagtable.util as uu - -dirname = os.path.join(os.path.dirname(__file__), "test_sample/") -filenames = [ - "oommf-old-file1.odt", - "oommf-old-file2.odt", - "oommf-old-file3.odt", - "oommf-old-file4.odt", - "oommf-old-file5.odt", - "oommf-old-file6.odt", - "oommf-old-file7.odt", - "oommf-old-file8.odt", - "oommf-new-file1.odt", - "oommf-new-file2.odt", - "oommf-new-file3.odt", - "oommf-new-file4.odt", - "oommf-new-file5.odt", - "mumax3-file1.txt", - "oommf-mel-file.odt", -] -odtfiles = [os.path.join(dirname, f) for f in filenames] - - -def test_columns(): - for odtfile in odtfiles: - for rename in [True, False]: - columns = uu.columns(odtfile, rename=rename) - - assert isinstance(columns, list) - assert all(isinstance(column, str) for column in columns) - assert len(columns) == len(set(columns)) # unique column names - - -def test_units(): - for odtfile in odtfiles: - for rename in [True, False]: - units = uu.units(odtfile, rename=rename) - - assert isinstance(units, dict) - assert all(isinstance(unit, str) for unit in units.keys()) - assert all(isinstance(unit, str) for unit in units.values()) - assert "J" in units.values() # Energy is always in - assert "" in units.values() # Columns with no units are always in - - -def test_data(): - for odtfile in odtfiles: - data = uu.data(odtfile) - - assert isinstance(data, list) - assert all(isinstance(i, numbers.Real) for i in itertools.chain(*data)) From 0ef000e7b63aeeeb2d8ccfedb8bb0c3a9f26355b Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Mon, 20 Feb 2023 13:39:29 +0100 Subject: [PATCH 10/11] Change variable names in _rename_column --- ubermagtable/table.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ubermagtable/table.py b/ubermagtable/table.py index 1011bd9..f28effb 100644 --- a/ubermagtable/table.py +++ b/ubermagtable/table.py @@ -328,13 +328,15 @@ def _rename_column(name, cols_dict): group = cols_dict[name_split[0]] if isinstance(group, str): # Mumax3 keys return group - quantity = group[name_split[-1]] + attribute = group[name_split[-1]] term_name = name_split[1] - if not quantity.endswith(term_name): - # unique names if the same quantity is present multiple times - # e.g. multiple Zeeman fields - quantity = f"{quantity}_{term_name}" - return quantity + if not attribute.endswith(term_name): + # - unique names if the same quantity is present multiple times + # e.g. multiple Zeeman fields + # - also required for changes in the exchange field in "old" and "new" + # OOMMF odt files + attribute = f"{attribute}_{term_name}" + return attribute except KeyError: return name From 86bc155e703f913292dde9c115901c695e7419f5 Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Wed, 29 Nov 2023 16:17:28 +0100 Subject: [PATCH 11/11] Remove all functionality to read table data from file This functionality is calculator-specific and is moved to the individual adapter packages --- ubermagtable/table.py | 278 ------------------------------------------ 1 file changed, 278 deletions(-) diff --git a/ubermagtable/table.py b/ubermagtable/table.py index f28effb..7b8af0c 100644 --- a/ubermagtable/table.py +++ b/ubermagtable/table.py @@ -1,5 +1,3 @@ -import re - import ipywidgets import matplotlib.pyplot as plt import numpy as np @@ -47,153 +45,6 @@ class Table: """ - # The OOMMF columns are renamed according to this dictionary. - _OOMMF_DICT = { - "Oxs_RungeKuttaEvolve": { - "Total energy": "E", - "Energy calc count": "E_calc_count", - "Max dm/dt": "max_dm/dt", - "dE/dt": "dE/dt", - "Delta E": "delta_E", - }, - "Oxs_EulerEvolve": { - "Total energy": "E", - "Energy calc count": "E_calc_count", - "Max dm/dt": "max_dmdt", - "dE/dt": "dE/dt", - "Delta E": "delta_E", - }, - "Oxs_CGEvolve": { - "Max mxHxm": "max_mxHxm", - "Total energy": "E", - "Delta E": "delta_E", - "Bracket count": "bracket_count", - "Line min count": "line_min_count", - "Conjugate cycle count": "conjugate_cycle_count", - "Cycle count": "cycle_count", - "Cycle sub count": "cycle_sub_count", - "Energy calc count": "energy_calc_count", - }, - "Anv_SpinTEvolve": { - "Total energy": "E", - "Energy calc count": "E_calc_count", - "Max dm/dt": "max_dmdt", - "dE/dt": "dE/dt", - "Delta E": "delta_E", - "average u": "average_u", - }, - "Oxs_SpinXferEvolve": { - "Total energy": "E", # NO SAMPLE - "Energy calc count": "E_calc_count", # NO SAMPLE - "Max dm/dt": "max_dmdt", # NO SAMPLE - "dE/dt": "dE/dt", # NO SAMPLE - "Delta E": "delta_E", # NO SAMPLE - "average u": "average_u", # NO SAMPLE - "average J": "average_J", # NO SAMPLE - }, - "UHH_ThetaEvolve": { - "Total energy": "E", # NO SAMPLE - "Energy calc count": "E_calc_count", # NO SAMPLE - "Max dm/dt": "max_dmdt", # NO SAMPLE - "dE/dt": "dE/dt", # NO SAMPLE - "Delta E": "delta_E", # NO SAMPLE - "Temperature": "T", # NO SAMPLE - }, - "Xf_ThermHeunEvolve": { - "Total energy": "E", # NO SAMPLE - "Energy calc count": "E_calc_count", # NO SAMPLE - "Max dm/dt": "max_dmdt", # NO SAMPLE - "dE/dt": "dE/dt", # NO SAMPLE - "Delta E": "delta_E", # NO SAMPLE - "Temperature": "T", # NO SAMPLE - }, - "Xf_ThermSpinXferEvolve": { - "Total energy": "E", # NO SAMPLE - "Energy calc count": "E_calc_count", # NO SAMPLE - "Max dm/dt": "max_dmdt", # NO SAMPLE - "dE/dt": "dE/dt", # NO SAMPLE - "Delta E": "delta_E", # NO SAMPLE - "Temperature": "T", # NO SAMPLE - }, - "Oxs_MinDriver": { - "Iteration": "iteration", - "Stage iteration": "stage_iteration", - "Stage": "stage", - "mx": "mx", - "my": "my", - "mz": "mz", - }, - "Oxs_TimeDriver": { - "Iteration": "iteration", - "Stage iteration": "stage_iteration", - "Stage": "stage", - "mx": "mx", - "my": "my", - "mz": "mz", - "Last time step": "last_time_step", - "Simulation time": "t", - }, - "Oxs_UniformExchange": { - "Max Spin Ang": "max_spin_ang", - "Stage Max Spin Ang": "stage_max_spin_ang", - "Run Max Spin Ang": "run_max_spin_ang", - "Energy": "E_exchange", - }, - "Oxs_Exchange6Ngbr": { - "Energy": "E_exchange6ngbr", - "Max Spin Ang": "max_spin_ang", - "Stage Max Spin Ang": "stage_max_spin_ang", - "Run Max Spin Ang": "run_max_spin_ang", - }, - "Oxs_ExchangePtwise": { - "Energy": "E_exchange_ptwise", # NO SAMPLE - "Max Spin Ang": "max_spin_ang", # NO SAMPLE - "Stage Max Spin Ang": "stage_max_spin_ang", # NO SAMPLE - "Run Max Spin Ang": "run_max_spin_ang", # NO SAMPLE - }, - "Oxs_TwoSurfaceExchange": {"Energy": "E_two_surface_exchange"}, # NO SAMPLE - "Oxs_Demag": {"Energy": "E_demag"}, - "Oxs_DMExchange6Ngbr": {"Energy": "E_DM_exchange6ngbr"}, # NO SAMPLE - "Oxs_DMI_Cnv": {"Energy": "E_DMI_Cnv"}, # TODO: PREFIX - "Oxs_DMI_T": {"Energy": "E_DMI_T"}, # NO SAMPLE, TODO: PREFIX - "Oxs_DMI_D2d": {"Energy": "E_DMI_Dd"}, # NO SAMPLE, TODO: PREFIX - "Oxs_FixedZeeman": {"Energy": "E_zeeman"}, - "Oxs_UZeeman": { - "Energy": "E_zeeman", - "B": "B", - "Bx": "Bx", - "By": "By", - "Bz": "Bz", - }, - "Oxs_ScriptUZeeman": { - "Energy": "E_zeeman", # NO SAMPLE - "B": "B", # NO SAMPLE - "Bx": "Bx", # NO SAMPLE - "By": "By", # NO SAMPLE - "Bz": "Bz", # NO SAMPLE - }, - "Oxs_TransformZeeman": {"Energy": "E_zeeman"}, # NO SAMPLE - "Oxs_CubicAnisotropy": {"Energy": "E_zeeman"}, - "Oxs_UniaxialAnisotropy": {"Energy": "E_zeeman"}, - "Southampton_UniaxialAnisotropy4": {"Energy": "E_zeeman"}, # NO SAMPLE - "YY_FixedMEL": {"Energy": "MEL_E"}, - } - - # The mumax3 columns are renamed according to this dictionary. - _MUMAX3_DICT = { - "t": "t", - "mx": "mx", - "my": "my", - "mz": "mz", - "E_total": "E", - "E_exch": "E_totalexchange", - "E_demag": "E_demag", - "E_Zeeman": "E_zeeman", - "E_anis": "E_totalanisotropy", - "dt": "dt", - "maxTorque": "maxtorque", - } - def __init__(self, data, units, x=None, attributes=None): self.data = data self.units = units @@ -211,135 +62,6 @@ def __init__(self, data, units, x=None, attributes=None): ignore_index=True, # reset the index to 0, 1, ..., n-1 ) - @classmethod - def fromfile(cls, filename, /, x=None, rename=True): - """Reads an OOMMF ``.odt`` or mumax3 ``.txt`` scalar data file and - returns a ``ubermagtable.Table`` object. - - Parameters - ---------- - filename : str - - OOMMF ``.odt`` or mumax3 ``.txt`` file. - - x : str, optional - - Independent variable name. Defaults to ``None``. - - rename : bool, optional - - If ``rename=True``, the column names are renamed with their shorter - versions. Defaults to ``True``. - - Returns - ------- - ubermagtable.Table - - Table object. - - Examples - -------- - 1. Defining ``ubermagtable.Table`` by reading an OOMMF ``.odt`` file. - - >>> import os - >>> import ubermagtable as ut - ... - >>> odtfile = os.path.join(os.path.dirname(__file__), - ... 'tests', 'test_sample', - ... 'oommf-hysteresis1.odt') - >>> table = ut.Table.fromfile(odtfile, x='B_hysteresis') - - 2. Defining ``ubermagtable.Table`` by reading a mumax3 ``.txt`` file. - - >>> odtfile = os.path.join(os.path.dirname(__file__), - ... 'tests', 'test_sample', 'mumax3-file1.txt') - >>> table = ut.Table.fromfile(odtfile, x='t') - - """ - quantities = cls._read_header(filename, rename=rename) - data = pd.read_csv( - filename, - sep=r"\s+", - comment="#", - header=None, - names=list(quantities.keys()), - ) - return cls(data=data, units=quantities, x=x) - - @classmethod - def _read_header(cls, filename, rename=True): - """Extracts quantities for individual columns from a table file. - - This method extracts both column names and units and returns a dictionary, - where keys are column names and values are the units. - - Parameters - ---------- - filename : str - - OOMMF ``.odt`` or mumax3 ``.txt`` file. - - rename : bool - - If ``rename=True``, the column names are renamed with their shorter - versions. Defaults to ``True``. - - Returns - ------- - dict - - Dictionary of column names and units. - """ - - with open(filename) as f: - if (header_line_1 := f.readline()).startswith("# ODT"): # OOMMF odt file - cols_dict = cls._OOMMF_DICT - # COLUMN NAMES - while not (cline := f.readline()).startswith("# Columns"): - pass - columns = cline.lstrip("# Columns:").rstrip() - cols = re.findall(r"(?<={)[^}]+|[^ {}]+", columns) - # UNITS - uline = f.readline() - assert uline.startswith("# Units:") - units = uline.split()[2:] # [2:] to remove ["#", "Units:"] - units = [re.sub(r"[{}]", "", unit) for unit in units] - else: # mumax3 txt file - cols_dict = cls._MUMAX3_DICT - header_line_1 = header_line_1[len("# ") :].rstrip().split("\t") - # COLUMN NAMES - cols = [elem.split()[0] for elem in header_line_1] - # UNITS - units = [re.sub(r"[()]", "", elem.split()[1]) for elem in header_line_1] - - if rename: - cols = [cls._rename_column(col, cols_dict) for col in cols] - - return dict(zip(cols, units)) - - @staticmethod - def _rename_column(name, cols_dict): - """Rename columns to get shorter names without spaces. - - Renaming is based on _OOMMF_DICT or _MUMAX3_DICT. - """ - name_split = name.split(":") - try: - group = cols_dict[name_split[0]] - if isinstance(group, str): # Mumax3 keys - return group - attribute = group[name_split[-1]] - term_name = name_split[1] - if not attribute.endswith(term_name): - # - unique names if the same quantity is present multiple times - # e.g. multiple Zeeman fields - # - also required for changes in the exchange field in "old" and "new" - # OOMMF odt files - attribute = f"{attribute}_{term_name}" - return attribute - except KeyError: - return name - @property def data(self): """Scalar data of the drive.