<filename>oommffield/oommffield.py<gh_stars>1-10
"""A Python package for analysing and manipulating OOMMF vector fields.

This module is a Python package that provides:

- Opening OOMMF vector field files (.omf and .ohf)
- Analysing vector fields, such as sampling, averaging, plotting, etc.
- Saving arbitrary vector fields to OOMMF vector field files.

oommffield is a member of JOOMMF project - a part of OpenDreamKit
Horizon 2020 European Research Infrastructure project

"""

import random
import numpy as np
import matplotlib.pyplot as plt
import finitedifferencefield
import struct


class Field(finitedifferencefield.Field):

    def write_oommf_file(self, filename, datatype='text'):
        """Write the FD field to the OOMMF (omf, ohf) file.

        This method writes all necessary data to the omf or ohf file,
        so that it can be read by OOMMF.

        Args:
          filename (str): filename including extension
          type(str): Either 'text' or 'binary'
        Example:

        .. code-block:: python

          >>> from oommffield import Field
          >>> field = Field((0, 0, 0), (5, 4, 3), (1, 1, 1))

          >>> field.set((1, 0, 5))
          >>> field.write_oommf_file('fdfield.omf')

        """
        oommf_file = open(filename, 'w')

        # Define header lines.
        header_lines = ['OOMMF OVF 2.0',
                        '',
                        'Segment count: 1',
                        '',
                        'Begin: Segment',
                        'Begin: Header',
                        '',
                        'Title: Field generated omf file',
                        'Desc: File generated by Field class',
                        'meshunit: m',
                        'meshtype: rectangular',
                        'xbase: {}'.format(self.d[0]),
                        'ybase: {}'.format(self.d[1]),
                        'zbase: {}'.format(self.d[2]),
                        'xnodes: {}'.format(self.n[0]),
                        'ynodes: {}'.format(self.n[1]),
                        'znodes: {}'.format(self.n[2]),
                        'xstepsize: {}'.format(self.d[0]),
                        'ystepsize: {}'.format(self.d[1]),
                        'zstepsize: {}'.format(self.d[2]),
                        'xmin: {}'.format(self.cmin[0]),
                        'ymin: {}'.format(self.cmin[1]),
                        'zmin: {}'.format(self.cmin[2]),
                        'xmax: {}'.format(self.cmax[0]),
                        'ymax: {}'.format(self.cmax[1]),
                        'zmax: {}'.format(self.cmax[2]),
                        'valuedim: {}'.format(self.dim),
                        'valuelabels: Magnetization_x Magnetization_y Magnetization_z',
                        'valueunits: A/m A/m A/m',
                        '',
                        'End: Header',
                        '']

        if datatype == 'binary':
            header_lines.append('Begin: Data Binary 8')
            footer_lines = ['End: Data Binary 8',
                            'End: Segment']
        if datatype == 'text':
            header_lines.append('Begin: Data Text')
            footer_lines = ['End: Data Text',
                            'End: Segment']

        # Write header lines to OOMMF file.
        for line in header_lines:
            if line == '':
                oommf_file.write('#\n')
            else:
                oommf_file.write('# ' + line + '\n')
        if datatype == 'binary':
            # Close the file and reopen with binary write
            # appending to end of file.
            oommf_file.close()
            oommf_file = open(filename, 'ab')
            # Add the 8 bit binary check value that OOMMF uses
            packarray = [123456789012345.0]
            # Write data lines to OOMMF file.
            for iz in range(self.n[2]):
                for iy in range(self.n[1]):
                    for ix in range(self.n[0]):
                        [packarray.append(vi) for vi in self.f[ix, iy, iz, :]]

            v_binary = struct.pack('d'*len(packarray), *packarray)
            oommf_file.write(v_binary)
            oommf_file.close()
            oommf_file = open(filename, 'a')

        else:
            for iz in range(self.n[2]):
                for iy in range(self.n[1]):
                    for ix in range(self.n[0]):
                        v = [str(vi) for vi in self.f[ix, iy, iz, :]]
                        for vi in v:
                            oommf_file.write(' ' + vi)
                        oommf_file.write('\n')
        # Write footer lines to OOMMF file.
        for line in footer_lines:
            oommf_file.write('# ' + line + '\n')

        # Close the file.
        oommf_file.close()


def read_oommf_file(filename, name='unnamed'):
    try:
        f = open(filename)

        if 'Begin: Data Text' in f.read():
            return read_oommf_file_text(filename, name)
        else:
            return read_oommf_file_binary(filename, name)
    except UnicodeDecodeError:
        return read_oommf_file_binary(filename, name)


def read_oommf_file_text(filename, name='unnamed'):
    """Read the OOMMF file and create an Field object.

    Args:
      filename (str): OOMMF file name
      name (str): name of the Field object

    Return:
      Field object.

    Example:

        .. code-block:: python

          from oommffield import read_oommf_file
          oommf_filename = 'vector_field.omf'
          field = read_oommf_file(oommf_filename, name='magnetisation')

    """
    # Open and read the file.
    f = open(filename, 'r')
    lines = f.readlines()
    f.close()

    # Load metadata.
    dic = {'xmin': None, 'ymin': None, 'zmin': None,
           'xmax': None, 'ymax': None, 'zmax': None,
           'xstepsize': None, 'ystepsize': None, 'zstepsize': None,
           'xbase': None, 'ybase': None, 'zbase': None,
           'xnodes': None, 'ynodes': None, 'znodes': None,
           'valuedim': None}

    for line in lines[0:50]:
        for key in dic.keys():
            if line.find(key) != -1:
                dic[key] = float(line.split()[2])

    cmin = (dic['xmin'], dic['ymin'], dic['zmin'])
    cmax = (dic['xmax'], dic['ymax'], dic['zmax'])
    d = (dic['xstepsize'], dic['ystepsize'], dic['zstepsize'])
    cbase = (dic['xbase'], dic['ybase'], dic['zbase'])
    n = (int(round(dic['xnodes'])),
         int(round(dic['ynodes'])),
         int(round(dic['znodes'])))
    dim = int(dic['valuedim'])
    field = Field(cmin, cmax, d, dim, name=name)

    for j in range(len(lines)):
        if lines[j].find('Begin: Data Text') != -1:
            data_first_line = j+1

    counter = 0
    for iz in range(n[2]):
        for iy in range(n[1]):
            for ix in range(n[0]):
                i = (ix, iy, iz)
                line_data = lines[data_first_line+counter]
                value = [float(vi) for vi in line_data.split()]
                field.set_at_index(i, value)

                counter += 1

    return field


def read_oommf_file_binary(filename, name='unnamed'):
    """Read the OOMMF file and create an Field object.

    Args:
      filename (str): OOMMF file name
      name (str): name of the Field object

    Return:
      Field object.

    Example:

        .. code-block:: python

          from oommffield import read_oommf_file
          oommf_filename = 'vector_field.omf'
          field = read_oommf_file(oommf_filename, name='magnetisation')

    """
    # Open and read the file.
    with open(filename, 'rb') as f:
        file = f.read()
        lines = file.split(b'\n')

    # Load metadata.
    dic = {'xmin': None, 'ymin': None, 'zmin': None,
           'xmax': None, 'ymax': None, 'zmax': None,
           'xstepsize': None, 'ystepsize': None, 'zstepsize': None,
           'xbase': None, 'ybase': None, 'zbase': None,
           'xnodes': None, 'ynodes': None, 'znodes': None,
           'valuedim': None}

    for line in lines[0:50]:
        for key in dic.keys():
            if line.find(bytes(key, 'utf-8')) != -1:
                dic[key] = float(line.split()[2])

    cmin = (dic['xmin'], dic['ymin'], dic['zmin'])
    cmax = (dic['xmax'], dic['ymax'], dic['zmax'])
    d = (dic['xstepsize'], dic['ystepsize'], dic['zstepsize'])
    cbase = (dic['xbase'], dic['ybase'], dic['zbase'])
    n = (int(round(dic['xnodes'])),
         int(round(dic['ynodes'])),
         int(round(dic['znodes'])))
    dim = int(dic['valuedim'])
    field = Field(cmin, cmax, d, dim, name=name)

    binary_header = b'# Begin: Data Binary '
    # Here we find the start and end points of the 
    # binary data, in terms of byte position.
    data_start = file.find(binary_header)
    header = file[data_start:data_start + len(binary_header) + 1]
    if b'8' in header:
        bytesize = 8
    elif b'4' in header:
        bytesize = 4

    data_start += len(b'# Begin: Data Binary 8\n')
    data_end = file.find(b'# End: Data Binary ')
    if bytesize == 4:
        listdata = list(struct.iter_unpack('@f', file[data_start:data_end]))
        try:
            assert listdata[0] == 1234567.0
        except:
            raise AssertionError('Something has gone wrong'
                                 ' with reading Binary Data')
    elif bytesize == 8:
        listdata = list(struct.iter_unpack('@d', file[data_start:data_end]))
        try:
            assert listdata[0][0] == 123456789012345.0
        except:
            raise AssertionError('Something has gone wrong'
                                 ' with reading Binary Data')

    counter = 1
    for iz in range(n[2]):
        for iy in range(n[1]):
            for ix in range(n[0]):
                i = (ix, iy, iz)
                value = (listdata[counter][0],
                         listdata[counter+1][0],
                         listdata[counter+2][0])
                field.set_at_index(i, value)
                counter += 3

    return field

<filename>oommffield/oommffield.py<gh_stars>1-10
"""A Python package for analysing and manipulating OOMMF vector fields.

This module is a Python package that provides:

- Opening OOMMF vector field files (.omf and .ohf)
- Analysing vector fields, such as sampling, averaging, plotting, etc.
- Saving arbitrary vector fields to OOMMF vector field files.

oommffield is a member of JOOMMF project - a part of OpenDreamKit
Horizon 2020 European Research Infrastructure project

"""

import random
import numpy as np
import matplotlib.pyplot as plt
import finitedifferencefield
import struct


class Field(finitedifferencefield.Field):

    def write_oommf_file(self, filename, datatype='text'):
        """Write the FD field to the OOMMF (omf, ohf) file.

        This method writes all necessary data to the omf or ohf file,
        so that it can be read by OOMMF.

        Args:
          filename (str): filename including extension
          type(str): Either 'text' or 'binary'
        Example:

        .. code-block:: python

          >>> from oommffield import Field
          >>> field = Field((0, 0, 0), (5, 4, 3), (1, 1, 1))

          >>> field.set((1, 0, 5))
          >>> field.write_oommf_file('fdfield.omf')

        """
        oommf_file = open(filename, 'w')

        # Define header lines.
        header_lines = ['OOMMF OVF 2.0',
                        '',
                        'Segment count: 1',
                        '',
                        'Begin: Segment',
                        'Begin: Header',
                        '',
                        'Title: Field generated omf file',
                        'Desc: File generated by Field class',
                        'meshunit: m',
                        'meshtype: rectangular',
                        'xbase: {}'.format(self.d[0]),
                        'ybase: {}'.format(self.d[1]),
                        'zbase: {}'.format(self.d[2]),
                        'xnodes: {}'.format(self.n[0]),
                        'ynodes: {}'.format(self.n[1]),
                        'znodes: {}'.format(self.n[2]),
                        'xstepsize: {}'.format(self.d[0]),
                        'ystepsize: {}'.format(self.d[1]),
                        'zstepsize: {}'.format(self.d[2]),
                        'xmin: {}'.format(self.cmin[0]),
                        'ymin: {}'.format(self.cmin[1]),
                        'zmin: {}'.format(self.cmin[2]),
                        'xmax: {}'.format(self.cmax[0]),
                        'ymax: {}'.format(self.cmax[1]),
                        'zmax: {}'.format(self.cmax[2]),
                        'valuedim: {}'.format(self.dim),
                        'valuelabels: Magnetization_x Magnetization_y Magnetization_z',
                        'valueunits: A/m A/m A/m',
                        '',
                        'End: Header',
                        '']

        if datatype == 'binary':
            header_lines.append('Begin: Data Binary 8')
            footer_lines = ['End: Data Binary 8',
                            'End: Segment']
        if datatype == 'text':
            header_lines.append('Begin: Data Text')
            footer_lines = ['End: Data Text',
                            'End: Segment']

        # Write header lines to OOMMF file.
        for line in header_lines:
            if line == '':
                oommf_file.write('#\n')
            else:
                oommf_file.write('# ' + line + '\n')
        if datatype == 'binary':
            # Close the file and reopen with binary write
            # appending to end of file.
            oommf_file.close()
            oommf_file = open(filename, 'ab')
            # Add the 8 bit binary check value that OOMMF uses
            packarray = [123456789012345.0]
            # Write data lines to OOMMF file.
            for iz in range(self.n[2]):
                for iy in range(self.n[1]):
                    for ix in range(self.n[0]):
                        [packarray.append(vi) for vi in self.f[ix, iy, iz, :]]

            v_binary = struct.pack('d'*len(packarray), *packarray)
            oommf_file.write(v_binary)
            oommf_file.close()
            oommf_file = open(filename, 'a')

        else:
            for iz in range(self.n[2]):
                for iy in range(self.n[1]):
                    for ix in range(self.n[0]):
                        v = [str(vi) for vi in self.f[ix, iy, iz, :]]
                        for vi in v:
                            oommf_file.write(' ' + vi)
                        oommf_file.write('\n')
        # Write footer lines to OOMMF file.
        for line in footer_lines:
            oommf_file.write('# ' + line + '\n')

        # Close the file.
        oommf_file.close()


def read_oommf_file(filename, name='unnamed'):
    try:
        f = open(filename)

        if 'Begin: Data Text' in f.read():
            return read_oommf_file_text(filename, name)
        else:
            return read_oommf_file_binary(filename, name)
    except UnicodeDecodeError:
        return read_oommf_file_binary(filename, name)


def read_oommf_file_text(filename, name='unnamed'):
    """Read the OOMMF file and create an Field object.

    Args:
      filename (str): OOMMF file name
      name (str): name of the Field object

    Return:
      Field object.

    Example:

        .. code-block:: python

          from oommffield import read_oommf_file
          oommf_filename = 'vector_field.omf'
          field = read_oommf_file(oommf_filename, name='magnetisation')

    """
    # Open and read the file.
    f = open(filename, 'r')
    lines = f.readlines()
    f.close()

    # Load metadata.
    dic = {'xmin': None, 'ymin': None, 'zmin': None,
           'xmax': None, 'ymax': None, 'zmax': None,
           'xstepsize': None, 'ystepsize': None, 'zstepsize': None,
           'xbase': None, 'ybase': None, 'zbase': None,
           'xnodes': None, 'ynodes': None, 'znodes': None,
           'valuedim': None}

    for line in lines[0:50]:
        for key in dic.keys():
            if line.find(key) != -1:
                dic[key] = float(line.split()[2])

    cmin = (dic['xmin'], dic['ymin'], dic['zmin'])
    cmax = (dic['xmax'], dic['ymax'], dic['zmax'])
    d = (dic['xstepsize'], dic['ystepsize'], dic['zstepsize'])
    cbase = (dic['xbase'], dic['ybase'], dic['zbase'])
    n = (int(round(dic['xnodes'])),
         int(round(dic['ynodes'])),
         int(round(dic['znodes'])))
    dim = int(dic['valuedim'])
    field = Field(cmin, cmax, d, dim, name=name)

    for j in range(len(lines)):
        if lines[j].find('Begin: Data Text') != -1:
            data_first_line = j+1

    counter = 0
    for iz in range(n[2]):
        for iy in range(n[1]):
            for ix in range(n[0]):
                i = (ix, iy, iz)
                line_data = lines[data_first_line+counter]
                value = [float(vi) for vi in line_data.split()]
                field.set_at_index(i, value)

                counter += 1

    return field


def read_oommf_file_binary(filename, name='unnamed'):
    """Read the OOMMF file and create an Field object.

    Args:
      filename (str): OOMMF file name
      name (str): name of the Field object

    Return:
      Field object.

    Example:

        .. code-block:: python

          from oommffield import read_oommf_file
          oommf_filename = 'vector_field.omf'
          field = read_oommf_file(oommf_filename, name='magnetisation')

    """
    # Open and read the file.
    with open(filename, 'rb') as f:
        file = f.read()
        lines = file.split(b'\n')

    # Load metadata.
    dic = {'xmin': None, 'ymin': None, 'zmin': None,
           'xmax': None, 'ymax': None, 'zmax': None,
           'xstepsize': None, 'ystepsize': None, 'zstepsize': None,
           'xbase': None, 'ybase': None, 'zbase': None,
           'xnodes': None, 'ynodes': None, 'znodes': None,
           'valuedim': None}

    for line in lines[0:50]:
        for key in dic.keys():
            if line.find(bytes(key, 'utf-8')) != -1:
                dic[key] = float(line.split()[2])

    cmin = (dic['xmin'], dic['ymin'], dic['zmin'])
    cmax = (dic['xmax'], dic['ymax'], dic['zmax'])
    d = (dic['xstepsize'], dic['ystepsize'], dic['zstepsize'])
    cbase = (dic['xbase'], dic['ybase'], dic['zbase'])
    n = (int(round(dic['xnodes'])),
         int(round(dic['ynodes'])),
         int(round(dic['znodes'])))
    dim = int(dic['valuedim'])
    field = Field(cmin, cmax, d, dim, name=name)

    binary_header = b'# Begin: Data Binary '
    # Here we find the start and end points of the 
    # binary data, in terms of byte position.
    data_start = file.find(binary_header)
    header = file[data_start:data_start + len(binary_header) + 1]
    if b'8' in header:
        bytesize = 8
    elif b'4' in header:
        bytesize = 4

    data_start += len(b'# Begin: Data Binary 8\n')
    data_end = file.find(b'# End: Data Binary ')
    if bytesize == 4:
        listdata = list(struct.iter_unpack('@f', file[data_start:data_end]))
        try:
            assert listdata[0] == 1234567.0
        except:
            raise AssertionError('Something has gone wrong'
                                 ' with reading Binary Data')
    elif bytesize == 8:
        listdata = list(struct.iter_unpack('@d', file[data_start:data_end]))
        try:
            assert listdata[0][0] == 123456789012345.0
        except:
            raise AssertionError('Something has gone wrong'
                                 ' with reading Binary Data')

    counter = 1
    for iz in range(n[2]):
        for iy in range(n[1]):
            for ix in range(n[0]):
                i = (ix, iy, iz)
                value = (listdata[counter][0],
                         listdata[counter+1][0],
                         listdata[counter+2][0])
                field.set_at_index(i, value)
                counter += 3

    return field

A Python package for analysing and manipulating OOMMF vector fields.  This module is a Python package that provides:  - Opening OOMMF vector field files (.omf and .ohf) - Analysing vector fields, such as sampling, averaging, plotting, etc. - Saving arbitrary vector fields to OOMMF vector field files.  oommffield is a member of JOOMMF project - a part of OpenDreamKit Horizon 2020 European Research Infrastructure project Write the FD field to the OOMMF (omf, ohf) file.          This method writes all necessary data to the omf or ohf file,         so that it can be read by OOMMF.          Args:           filename (str): filename including extension           type(str): Either 'text' or 'binary'         Example:          .. code-block:: python            >>> from oommffield import Field           >>> field = Field((0, 0, 0), (5, 4, 3), (1, 1, 1))            >>> field.set((1, 0, 5))           >>> field.write_oommf_file('fdfield.omf') # Define header lines. # Write header lines to OOMMF file. # Close the file and reopen with binary write # appending to end of file. # Add the 8 bit binary check value that OOMMF uses # Write data lines to OOMMF file. # Write footer lines to OOMMF file. # Close the file. Read the OOMMF file and create an Field object.      Args:       filename (str): OOMMF file name       name (str): name of the Field object      Return:       Field object.      Example:          .. code-block:: python            from oommffield import read_oommf_file           oommf_filename = 'vector_field.omf'           field = read_oommf_file(oommf_filename, name='magnetisation') # Open and read the file. # Load metadata. Read the OOMMF file and create an Field object.      Args:       filename (str): OOMMF file name       name (str): name of the Field object      Return:       Field object.      Example:          .. code-block:: python            from oommffield import read_oommf_file           oommf_filename = 'vector_field.omf'           field = read_oommf_file(oommf_filename, name='magnetisation') # Open and read the file. # Load metadata. # Here we find the start and end points of the # binary data, in terms of byte position.