-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add functionality for finding and reading data
moved from micromagneticdata and ubermagtable, respectively
- Loading branch information
Showing
3 changed files
with
252 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .mumax3drive import Mumax3Drive as Drive |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import pathlib | ||
|
||
import micromagneticdata as md | ||
import ubermagutil as uu | ||
|
||
from .abstract_drive import AbstractDrive | ||
|
||
|
||
@uu.inherit_docs | ||
class Mumax3Drive(md.Drive): | ||
"""Drive class for Mumax3Drives (created automatically). | ||
This class provides utility for the analysis of individual mumax3 drives. It should | ||
not be created explicitly. Instead, use ``micromagneticdata.Drive`` which | ||
automatically creates a ``drive`` object of the correct sub-type. | ||
Parameters | ||
---------- | ||
name : str | ||
System's name. | ||
number : int | ||
Drive number. | ||
dirname : str, optional | ||
Directory in which system's data is saved. Defults to ``'./'``. | ||
x : str, optional | ||
Independent variable column name. Defaults to ``None`` and depending on | ||
the driver used, one is found automatically. | ||
use_cache : bool, optional | ||
If ``True`` the Drive object will read tabular data and the names and number of | ||
magnetisation files only once. Note: this prevents Drive to detect new data when | ||
looking at the output of a running simulation. If set to ``False`` the data is | ||
read every time the user accesses it. Defaults to ``False``. | ||
Raises | ||
------ | ||
IOError | ||
If the drive directory cannot be found. | ||
Examples | ||
-------- | ||
1. Getting drive object. | ||
>>> import os | ||
>>> import micromagneticdata as md | ||
... | ||
>>> dirname = dirname=os.path.join(os.path.dirname(__file__), | ||
... 'tests', 'test_sample') | ||
>>> drive = md.Drive(name='system_name', number=1, dirname=dirname) | ||
>>> drive | ||
Mumax3Drive(...) | ||
""" | ||
|
||
def __init__(self, name, number, dirname="./", x=None, use_cache=False, **kwargs): | ||
self._mumax_output_path = pathlib.Path( | ||
f"{dirname}/{name}/drive-{number}/{name}.out" | ||
) # required to initialise self.x in super | ||
if not self._mumax_output_path.exists(): | ||
raise IOError( | ||
f"Output directory {self._mumax_output_path!r} does not exist." | ||
) | ||
|
||
super().__init__(name, number, dirname, x, use_cache, **kwargs) | ||
|
||
@AbstractDrive.x.setter | ||
def x(self, value): | ||
if value is None: | ||
# self.info["driver"] in ["TimeDriver", "RelaxDriver", "MinDriver"]: | ||
self._x = "t" | ||
else: | ||
# self.table reads self.x so self._x has to be defined first | ||
if hasattr(self, "_x"): | ||
# store old value to reset in case value is invalid | ||
_x = self._x | ||
self._x = value | ||
if value not in self.table.data.columns: | ||
self._x = _x | ||
raise ValueError(f"Column {value=} does not exist in data.") | ||
|
||
@property | ||
def _table_path(self): | ||
return self._mumax_output_path / "table.txt" | ||
|
||
@property | ||
def _step_file_glob(self): | ||
return self._mumax_output_path.glob("*.ovf") | ||
|
||
@property | ||
def calculator_script(self): | ||
with (self.drive_path / f"{self.name}.mx3").open() as f: | ||
return f.read() | ||
|
||
def __repr__(self): | ||
"""Representation string. | ||
Returns | ||
------- | ||
str | ||
Representation string. | ||
Examples | ||
-------- | ||
1. Representation string. | ||
>>> import os | ||
>>> import micromagneticdata as md | ||
... | ||
>>> dirname = dirname=os.path.join(os.path.dirname(__file__), | ||
... 'tests', 'test_sample') | ||
>>> drive = md.Drive(name='system_name', number=1, dirname=dirname) | ||
>>> drive | ||
Mumax3Drive(name='system_name', number=1, dirname='...test_sample', x='t') | ||
""" | ||
return ( | ||
f"Mumax3Drive(name='{self.name}', number={self.number}, " | ||
f"dirname='{self.dirname}', x='{self.x}')" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import re | ||
|
||
import pandas as pd | ||
import ubermagtable | ||
|
||
|
||
def table_from_file(filename, /, x=None, rename=True): | ||
"""Convert a mumax3 ``.txt`` scalar data file into a ``ubermagtable.Table``. | ||
Parameters | ||
---------- | ||
filename : str | ||
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. | ||
TODO: update example | ||
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 = _read_header(filename, rename=rename) | ||
data = pd.read_csv( | ||
filename, | ||
sep=r"\s+", | ||
comment="#", | ||
header=None, | ||
names=list(quantities.keys()), | ||
) | ||
return ubermagtable.Table(data=data, units=quantities, x=x) | ||
|
||
|
||
def _read_header(filename, rename=True): | ||
"""Extract 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: | ||
header_line_1 = f.readline() | ||
|
||
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 = [_rename_column(col, _MUMAX3_DICT) for col in cols] | ||
|
||
return dict(zip(cols, units)) | ||
|
||
|
||
def _rename_column(name, cols_dict): | ||
"""Rename columns to get shorter names without spaces. | ||
Renaming is based on _MUMAX3_DICT. | ||
""" | ||
return cols_dict.get(name, name) | ||
|
||
|
||
# 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", | ||
} |