コード例 #1
0
    def RequestData(self, request, inInfo, outInfo):
        output = dsa.WrapDataObject(vtkUnstructuredGrid.GetData(outInfo))

        # Use h5py to read the mesh
        import h5py

        f = h5py.File(self._filename, "r")
        mesh = f[list(f.keys())[0]]
        points = mesh["coordinates"][()]
        celltype = mesh["topology"].attrs["celltype"].decode("utf-8")
        cells = mesh["topology"][()]

        # Points
        if points.shape[1] == 2:
            points = np.hstack([points, np.zeros((len(points), 1))])
        output.SetPoints(points)

        # Cells
        vtk_type = dolfinx_to_vtk_type[celltype]
        ncells, npoints_per_cell = cells.shape
        cell_types = np.full(ncells, vtk_type, dtype=np.ubyte)
        cell_offsets = (1 + npoints_per_cell) * np.arange(ncells, dtype=int)
        cell_conn = np.hstack(
            [npoints_per_cell * np.ones((ncells, 1), dtype=int),
             cells]).flatten()
        output.SetCells(cell_types, cell_offsets, cell_conn)

        return 1
コード例 #2
0
    def RequestData(self, request, inInfoVec, outInfoVec):
        mesh = dsa.WrapDataObject(vtkUnstructuredGrid.GetData(inInfoVec[0]))

        # Read points
        points = np.asarray(mesh.GetPoints())

        # Read cells
        # Adapted from test/legacy_reader.py
        cell_conn = mesh.GetCells()
        cell_offsets = mesh.GetCellLocations()
        cell_types = mesh.GetCellTypes()
        cells_dict = {}
        for vtk_cell_type in np.unique(cell_types):
            offsets = cell_offsets[cell_types == vtk_cell_type]
            ncells = len(offsets)
            npoints = cell_conn[offsets[0]]
            array = np.empty((ncells, npoints), dtype=int)
            for i in range(npoints):
                array[:, i] = cell_conn[offsets + i + 1]
            cells_dict[vtk_to_meshio_type[vtk_cell_type]] = array
        cells = [meshio.CellBlock(key, cells_dict[key]) for key in cells_dict]

        # Read point and field data
        # Adapted from test/legacy_reader.py
        def _read_data(data):
            out = {}
            for i in range(data.VTKObject.GetNumberOfArrays()):
                name = data.VTKObject.GetArrayName(i)
                array = np.asarray(data.GetArray(i))
                out[name] = array
            return out

        point_data = _read_data(mesh.GetPointData())
        field_data = _read_data(mesh.GetFieldData())

        # Read cell data
        cell_data_flattened = _read_data(mesh.GetCellData())
        cell_data = {}
        for name, array in cell_data_flattened.items():
            cell_data[name] = []
            for cell_type in cells_dict:
                vtk_cell_type = meshio_to_vtk_type[cell_type]
                mask_cell_type = cell_types == vtk_cell_type
                cell_data[name].append(array[mask_cell_type])

        # Use meshiah to write mesh
        meshio.write_point_cells(
            self._filename,
            points,
            cells,
            point_data=point_data,
            cell_data=cell_data,
            field_data=field_data,
        )
        return 1
コード例 #3
0
    def RequestData(self, request, inInfoVec, outInfoVec):
        output = dsa.WrapDataObject(vtkUnstructuredGrid.GetData(outInfoVec))

        # Determine how to read the mesh
        self._file_format = get_erdc_extensions(self._filename)
        if (self._file_format):
            mesh = meshiah.read(self._filename)
            points, cells = mesh.points, mesh.cells
        elif (meshioLib and not self._file_format):
            mesh = meshio.read(self._filename, self._file_format)
            points, cells = mesh.points, mesh.cells
        else:
            print(f"Unable to deduce file format from file: {self._filename}")

        # Points
        if points.shape[1] == 2:
            points = np.hstack([points, np.zeros((len(points), 1))])
        output.SetPoints(points)

        # CellBlock, adapted from test/legacy_writer.py
        cell_types = np.array([], dtype=np.ubyte)
        cell_offsets = np.array([], dtype=int)
        cell_conn = np.array([], dtype=int)
        for meshio_type, data in cells:
            vtk_type = meshio.vtk._vtk.meshio_to_vtk_type[meshio_type]
            ncells, npoints = data.shape
            cell_types = np.hstack(
                [cell_types,
                 np.full(ncells, vtk_type, dtype=np.ubyte)])
            offsets = len(cell_conn) + (1 + npoints) * \
                np.arange(ncells, dtype=int)
            cell_offsets = np.hstack([cell_offsets, offsets])
            conn = np.hstack([npoints * np.ones((ncells, 1), dtype=int),
                              data]).flatten()
            cell_conn = np.hstack([cell_conn, conn])
        output.SetCells(cell_types, cell_offsets, cell_conn)

        # Point data
        for name, array in mesh.point_data.items():
            output.PointData.append(array, name)

        # Cell data
        for name, data in mesh.cell_data.items():
            array = np.concatenate(data)
            output.CellData.append(array, name)

        # Field data
        for name, array in mesh.field_data.items():
            output.FieldData.append(array, name)

        return 1
コード例 #4
0
ファイル: binary_filter.py プロジェクト: clockwork85/meshiah
 def RequestData(self, request, inInfo, outInfo):
     from vtkmodules.numpy_interface import dataset_adapter as dsa
     from vtkmodules.vtkCommonDataModel import vtkUnstructuredGrid
     import vtk
     inData = self.GetInputData(inInfo, 0, 0)
     # outData = self.GetOutputData(outInfo, 0)
     output = dsa.WrapDataObject(vtkUnstructuredGrid.GetData(outInfo, 0))
     output.ShallowCopy(inData)
     # output = dsa.WrapDataObject(vtkUnstructuredGrid.GetData(outData, 0))
     data = self._read_flux_file()
     data_vtk = vtk.vtkDoubleArray()
     data_vtk.SetNumberOfValues(len(data))
     data_vtk.SetName('FluxData')
     for i, val in enumerate(data):
         data_vtk.InsertValue(i, val[0] / self._numlights)
     output.GetCellData().AddArray(data_vtk)
     return 1
コード例 #5
0
    def RequestData(self, request, inInfoVec, outInfoVec):
        output = dsa.WrapDataObject(vtkUnstructuredGrid.GetData(outInfoVec))

        # Use meshio to read the mesh
        mesh = meshio.read(self._filename, self._file_format)
        points, cells = mesh.points, mesh.cells

        # Points
        if points.shape[1] == 2:
            points = np.hstack([points, np.zeros((len(points), 1))])
        output.SetPoints(points)

        # Cells, adapted from
        # https://github.com/nschloe/meshio/blob/master/test/legacy_writer.py
        cell_types = np.array([], dtype=np.ubyte)
        cell_offsets = np.array([], dtype=int)
        cell_conn = np.array([], dtype=int)
        for meshio_type, data in cells:
            vtk_type = meshio_to_vtk_type[meshio_type]
            ncells, npoints = data.shape
            cell_types = np.hstack(
                [cell_types,
                 np.full(ncells, vtk_type, dtype=np.ubyte)])
            offsets = len(cell_conn) + (1 + npoints) * np.arange(ncells,
                                                                 dtype=int)
            cell_offsets = np.hstack([cell_offsets, offsets])
            conn = np.hstack([npoints * np.ones((ncells, 1), dtype=int),
                              data]).flatten()
            cell_conn = np.hstack([cell_conn, conn])
        output.SetCells(cell_types, cell_offsets, cell_conn)

        # Point data
        for name, array in mesh.point_data.items():
            output.PointData.append(array, name)

        # Cell data
        print(mesh.cell_data)
        for name, data in mesh.cell_data.items():
            array = np.concatenate(data)
            output.CellData.append(array, name)

        # Field data
        for name, array in mesh.field_data.items():
            output.FieldData.append(array, name)

        return 1
コード例 #6
0
    def RequestData(self, request, inInfoVec, outInfoVec):
        data_time = self.getCurrentTime(outInfoVec.GetInformationObject(0))
        output = dsa.WrapDataObject(vtkUnstructuredGrid.GetData(outInfoVec))

        currentFile = self.fileList[data_time]

        p = partio.read(currentFile)

        if p == None:
            return 1

        totalParticles = p.numParticles()

        for i in range(p.numAttributes()):
            attr = p.attributeInfo(i)
            if attr.name == "position":
                pos = np.array(p.data_buffer(attr), copy=False)
                output.SetPoints(pos)

        # cell_conn contains tuples (num indices, vertex ids)
        # e.g. particles (1,0), (1,1), (1,2), (1,3), ...
        # e.g. triangles (3, 0, 1, 2), (3, 2, 3, 4), ...
        cell_conn = np.hstack([
            np.ones((totalParticles, 1)),
            np.arange(0, totalParticles, 1, dtype=int).reshape(-1, 1)
        ]).flatten()
        # for particles use type VERTEX=1
        cell_types = np.full((totalParticles), 1, np.ubyte)
        # offset between two particles is 2 since cell_conn always contains the number of indices
        cell_offsets = 2 * np.arange(totalParticles, dtype=int)

        output.SetCells(cell_types, cell_offsets, cell_conn)

        # add field data
        for i in range(p.numAttributes()):
            attr = p.attributeInfo(i)
            if attr.name != "position":
                values = np.array(p.data_buffer(attr), copy=False)
                output.PointData.append(values, attr.name)
        return 1
コード例 #7
0
    def RequestData(self, request, inInfoVec, outInfoVec):
        output = dsa.WrapDataObject(vtkUnstructuredGrid.GetData(outInfoVec))

        # Use meshio to read the mesh
        # mesh = meshiah.read(self._filename, self._file_format)
        print(f"Opening mesh: {self._filename}")
        with open(self._filename) as ifile:
            points = []
            facets = []
            cells = []
            mats = []
            for line in ifile.readlines():
                strip = line.strip()
                split = strip.split()

                if split[0] == "ND":
                    # Vertex
                    points.append([float(x) for x in split[2:]])
                elif split[0] == "E3T":
                    # Triangle
                    data = [int(x) for x in split[2:]]
                    facets.append(data[0:3])
                    mats.append(data[3])
                elif split[0] == "E4T":
                    # Tetrahedron
                    data = [int(x) for x in split[2:]]
                    facets.append(data[0:4])
                    mats.append(data[4])
                else:
                    continue

        points_np = np.array(points)
        cells_np = np.array(facets)
        mats_np = np.array(mats, dtype=np.int32)

        if cells_np.shape[1] == 3:
            cells.append(["triangle", cells_np - 1])
        elif cells_np.shape[1] == 4:
            cells.append(["tetrahedron", cells_np - 1])
        else:
            logging.warning(
                "ERDC writer only support triangles and tetrahedrons at this time"
                "Skipping {} polygons with {} nodes".format(
                    cells_np.shape[0], cells_np.shape[1]))
        cell_data = {}
        cell_data['Region'] = []
        cell_data['Region'].append(mats_np)

        # Points
        # if points.shape[1] == 2:
        #    points = np.hstack([points, np.zeros((len(points), 1))])
        output.SetPoints(points_np)

        # CellBlock, adapted from test/legacy_writer.py
        cell_types = np.array([], dtype=np.ubyte)
        cell_offsets = np.array([], dtype=int)
        cell_conn = np.array([], dtype=int)
        # triangle - vtk type = 5
        # tetrahedron - vtk type = 10

        for erdc_type, data in cells:
            vtk_type = vtk_type_from_erdc(erdc_type)
            ncells, npoints = data.shape
            cell_types = np.hstack(
                [cell_types,
                 np.full(ncells, vtk_type, dtype=np.ubyte)])
            offsets = len(cell_conn) + (1 + npoints) * np.arange(ncells,
                                                                 dtype=int)
            cell_offsets = np.hstack([cell_offsets, offsets])
            conn = np.hstack([npoints * np.ones((ncells, 1), dtype=int),
                              data]).flatten()
            cell_conn = np.hstack([cell_conn, conn])
        print(f"cell_types: \n {cell_types}")
        print(f"cell_offsets: \n {cell_offsets}")
        print(f"cell_conn: \n {cell_conn}")
        output.SetCells(cell_types, cell_offsets, cell_conn)

        # Point data
        #        for name, array in mesh.point_data.items():
        #            output.PointData.append(array, name)

        # Cell data
        for name, data in cell_data.items():
            array = np.concatenate(data)
            output.CellData.append(array, name)

        # Field data


#        for name, array in mesh.field_data.items():
#            output.FieldData.append(array, name)

        return 1
コード例 #8
0
    def RequestData(self, request, inInfoVec, outInfoVec):
        import sys, os
        import vtk
        from vtkmodules.vtkCommonDataModel import vtkUnstructuredGrid, vtkImageData, vtkDataSet
        from vtk.numpy_interface import dataset_adapter as dsa
        import ctypes as C
        import numpy as np

        if 'HOME' in os.environ:
            ccode_so = os.environ['HOME'] + '/python/_sample.so'
        elif 'HOMEPATH' in os.environ:
            ccode_so = os.environ['HOMEPATH'] + '/python/_sample.so'
        else:
            code_so = '_sample.so'

        if not os.path.isfile(ccode_so):
            print('can\'t find so:', ccode_so)
            return

        ccode = C.CDLL(ccode_so)
        if not ccode:
            print('failed to load ', ccode.so)

        ccode.SampleTetrahedra.argtypes = [
            C.c_int, C.c_int, C.c_int, C.c_int,
            np.ctypeslib.ndpointer(C.c_float, flags="C_CONTIGUOUS"),
            np.ctypeslib.ndpointer(C.c_float, flags="C_CONTIGUOUS"),
            np.ctypeslib.ndpointer(C.c_int, flags="C_CONTIGUOUS")
        ]

        ccode.SampleRectilinear.argtypes = [
            C.c_int, C.c_int,
            np.ctypeslib.ndpointer(C.c_int, flags="C_CONTIGUOUS"),
            np.ctypeslib.ndpointer(C.c_float, flags="C_CONTIGUOUS"),
            np.ctypeslib.ndpointer(C.c_float, flags="C_CONTIGUOUS"),
            np.ctypeslib.ndpointer(C.c_float, flags="C_CONTIGUOUS"),
            np.ctypeslib.ndpointer(C.c_float, flags="C_CONTIGUOUS")
        ]

        ccode.SampleVTI.argtypes = [
            C.c_int, C.c_int,
            np.ctypeslib.ndpointer(C.c_int, flags="C_CONTIGUOUS"),
            np.ctypeslib.ndpointer(C.c_float, flags="C_CONTIGUOUS"),
            np.ctypeslib.ndpointer(C.c_float, flags="C_CONTIGUOUS"),
            np.ctypeslib.ndpointer(C.c_float, flags="C_CONTIGUOUS")
        ]

        ccode.GetNumberOfSamples.restype = C.c_int

        ccode.GetSamples.restype = C.c_void_p

        obj = dsa.WrapDataObject(vtkDataSet.GetData(inInfoVec[0], 0))

        pdf = self.inputArray
        nSamples = self.nSamples

        if obj.GetClassName() == 'vtkImageData':

            a = vtkImageData.GetData(inInfoVec[0], 0)
            vti = dsa.WrapDataObject(vtkImageData.GetData(inInfoVec[0], 0))
            e = vti.VTKObject.GetExtent()
            o = vti.VTKObject.GetOrigin()
            s = vti.VTKObject.GetSpacing()
            dimensions = np.array([(e[2 * i + 1] - e[2 * i]) + 1
                                   for i in range(3)]).astype('i4')
            origin = np.array([o[i] + e[2 * i] * s[i]
                               for i in range(3)]).astype('f4')
            spacing = np.array(s).astype('f4')
            pdf = np.ascontiguousarray(vti.CellData[pdf]).astype('f4')
            ccode.SampleVTI(0, nSamples, dimensions, origin, spacing, pdf)

        elif obj.GetClassName() == 'vtkUnstructuredGrid':

            vtu = dsa.WrapDataObject(
                vtkUnstructuredGrid.GetData(inInfoVec[0], 0))
            points = np.ascontiguousarray(vtu.Points).astype('f4')
            pdf = np.ascontiguousarray(vtu.CellData[pdf]).astype('f4')
            tets = np.ascontiguousarray(vtu.Cells).astype('i4')
            ccode.SampleTetrahedra(0, nSamples, vtu.GetNumberOfPoints(),
                                   vtu.GetNumberOfCells(), points, pdf, tets)

        elif obj.GetClassName() == 'vtkRectilinearGrid':

            vtr = vtkRectilinearGrid.GetData(inInfoVec[0], 0)
            x_array = dsa.numpy_support.vtk_to_numpy(
                vtr.GetXCoordinates()).astype('f4')
            y_array = dsa.numpy_support.vtk_to_numpy(
                vtr.GetYCoordinates()).astype('f4')
            z_array = dsa.numpy_support.vtk_to_numpy(
                vtr.GetZCoordinates()).astype('f4')
            pdf = dsa.numpy_support.vtk_to_numpy(
                vtr.GetCellData().GetArray(pdf)).astype('f4')
            dim = (len(x_array), len(y_array), len(z_array))
            ccode.SampleRectilinear(0, dim, x_array, y_array, z_array, pdf)

        else:
            print(
                "SampleCellDensity requires vtkImageData or vtkUnstructuredGrid"
            )
            return 0

        n = ccode.GetNumberOfSamples()
        s = np.ctypeslib.as_array(C.cast(ccode.GetSamples(),
                                         C.POINTER(C.c_float)),
                                  shape=(n, 3))
        samples = dsa.WrapDataObject(vtk.vtkUnstructuredGrid())
        co = dsa.numpy_support.numpy_to_vtkIdTypeArray(
            np.arange(n).astype('i8') * 2)
        ca = vtk.vtkCellArray()
        ca.SetCells(
            n,
            dsa.numpy_support.numpy_to_vtkIdTypeArray(
                np.column_stack(([1] * n, range(n))).reshape(
                    (2 * n, )).astype('i8')))
        ct = dsa.numpyTovtkDataArray(
            np.array([vtk.VTK_VERTEX] * n).astype('u1'))
        samples.VTKObject.SetCells(ct, co, ca)
        samples.Points = dsa.numpy_support.numpy_to_vtk(s, deep=1)

        outpt = vtkUnstructuredGrid.GetData(outInfoVec, 0)
        outpt.ShallowCopy(samples.VTKObject)

        ccode.Cleanup()
        return 1
コード例 #9
0
    def RequestData(self, request, inInfo, outInfo):
        """Process the request submitted after applying the filter."""
        source_input = vtkUnstructuredGrid.GetData(inInfo[0])
        source = dsa.WrapDataObject(source_input)
        target_input = vtkUnstructuredGrid.GetData(inInfo[1])
        target = dsa.WrapDataObject(target_input)

        output = dsa.WrapDataObject(vtkUnstructuredGrid.GetData(outInfo))
        output.ShallowCopy(target_input)

        # Compute target cell volume
        volumes = np.abs(algs.volume(target))

        # Create a vtkCellLocator for fast computation of neighborhood
        cell_locator = vtk.vtkCellLocator()
        cell_locator.SetDataSet(source_input)
        cell_locator.SetNumberOfCellsPerNode(1)
        cell_locator.BuildLocator()

        # Correct cell position indicators (for some reason they must be
        # all shifted)
        correction = np.arange(0, len(source.CellLocations))
        cell_pos = source.CellLocations + correction

        # Prepare source lines
        node_ids_a = cell_pos + 1
        node_ids_b = cell_pos + 2
        point_ids_a = source.Cells[node_ids_a]
        point_ids_b = source.Cells[node_ids_b]
        points_a = source.Points[point_ids_a]
        points_b = source.Points[point_ids_b]
        directions = points_a - points_b
        norm_directions = directions / np.linalg.norm(directions, axis=1)

        # Fill new cell data
        n_lines = np.zeros_like(volumes)
        vf = np.zeros_like(volumes)
        A = np.nan * np.ones((len(volumes), 3, 3))
        for i, cell_volume in enumerate(volumes):
            # Find a bounding box
            idList = vtk.vtkIdList()
            bounds = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
            target.GetCellBounds(i, bounds)
            cell_locator.FindCellsWithinBounds(bounds, idList)

            # Number of potential lines
            N0 = idList.GetNumberOfIds()

            # Compress to number of real intersections
            ids = [idList.GetId(j) for j in range(N0)]
            cell = target.GetCell(i)
            reduced_line_ids = []
            length_in_cell = []
            for id, p1, p2 in zip(ids, points_a[ids], points_b[ids]):
                res = self.compute_length_in_cell(cell, p1, p2)
                if res > 0.0:
                    reduced_line_ids.append(id)
                    length_in_cell.append(res)

            # Compute number of fibers in cell
            N = len(reduced_line_ids)
            n_lines[i] = N

            # Compute approximate fiber volume fraction
            vf[i] = np.sum(length_in_cell) * self._area / cell_volume

            # Compute fiber orientation tensors
            dirs = norm_directions[reduced_line_ids]
            if N > self._minN:
                A[i, :, :] = np.einsum("k, ki,kj->ij", length_in_cell, dirs,
                                       dirs) / np.sum(length_in_cell)

        output.CellData.append(volumes, "Cell Volume")
        output.CellData.append(n_lines, "N Lines")
        output.CellData.append(A, "Orientation Tensor (2nd Order)")
        output.CellData.append(vf, "Volume Fraction")

        return 1
コード例 #10
0
    def RequestData(self, request, inInfo, outInfo):
        output = dsa.WrapDataObject(vtkUnstructuredGrid.GetData(outInfo))

        import os
        import json
        import mfem.ser as mfem

        _, ext = os.path.splitext(self._filename)
        cwd = os.path.dirname(self._filename)

        if ext == ".mfem_root":
            with open(self._filename) as f:
                root = json.load(f)
                cycle = int(root['dsets']['main']['cycle'])
                mesh_filename = root['dsets']['main']['mesh']['path']
                mesh_filename = format(mesh_filename % cycle)
                mesh_filename = os.path.join(cwd, mesh_filename)
        else:
            mesh_filename = self._filename

        mesh = mfem.Mesh(mesh_filename)
        dim = mesh.SpaceDimension()
        nelem = mesh.GetNE()

        # Points
        mesh_fes = mesh.GetNodalFESpace()
        nodes = mesh.GetNodes()
        if nodes is None:
            nnode = mesh.GetNV()
            points = np.array(mesh.GetVertexArray())
        else:
            nnode = mesh.GetNodes().Size() // dim
            points = np.array(mesh.GetNodes().GetDataArray())
            if mesh_fes.GetOrdering() == 0:
                points = points.reshape((dim, nnode)).T
            elif mesh_fes.GetOrdering() == 1:
                points = points.reshape((nnode, dim))
            else:
                raise NotImplementedError
        if dim == 1:
            points = np.hstack([points, np.zeros((nnode, 2))])
        elif dim == 2:
            points = np.hstack([points, np.zeros((nnode, 1))])
        output.SetPoints(points)

        # Cells
        cell_attributes = np.empty((nelem), dtype=int)
        cell_types = np.empty((nelem), dtype=np.ubyte)
        cell_offsets = np.empty((nelem), dtype=int)
        cell_conn = []

        offset = 0
        if nodes is None:
            for i in range(nelem):
                v = mesh.GetElementVertices(i)
                geom = mesh.GetElementBaseGeometry(i)
                perm = VTKGeometry_VertexPermutation[geom]
                if perm: v = [v[i] for i in perm]
                cell_types[i] = VTKGeometry_Map[geom]
                cell_offsets[i] = offset
                offset += len(v) + 1
                cell_conn.append(len(v))
                cell_conn.extend(v)
        else:
            for i in range(nelem):
                v = mesh_fes.GetElementDofs(i)
                geom = mesh.GetElementBaseGeometry(i)
                order = mesh_fes.GetOrder(i)
                if order == 1:
                    perm = VTKGeometry_VertexPermutation[geom]
                    cell_types[i] = VTKGeometry_Map[geom]
                elif order == 2:
                    perm = VTKGeometry_QuadraticVertexPermutation[geom]
                    cell_types[i] = VTKGeometry_QuadraticMap[geom]
                else:
                    # FIXME: this needs more work...
                    # See CreateVTKMesh for reading VTK Lagrange elements and
                    # invert that process to create VTK Lagrange elements.
                    # https://github.com/mfem/mfem/blob/master/mesh/mesh_readers.cpp
                    parray = mfem.intArray()
                    mfem.CreateVTKElementConnectivity(parray, geom, order)
                    perm = parray.ToList()
                    cell_types[i] = VTKGeometry_HighOrderMap[geom]
                if perm: v = [v[i] for i in perm]
                cell_offsets[i] = offset
                offset += len(v) + 1
                cell_conn.append(len(v))
                cell_conn.extend(v)

        output.SetCells(cell_types, cell_offsets, cell_conn)

        # Attributes
        for i in range(nelem):
            cell_attributes[i] = mesh.GetAttribute(i)
        output.CellData.append(cell_attributes, "attribute")

        # Read fields
        if ext == ".mfem_root":
            fields = root['dsets']['main']['fields']
            for name, prop in fields.items():
                filename = prop['path']
                filename = format(filename % cycle)
                filename = os.path.join(cwd, filename)
                gf = mfem.GridFunction(mesh, filename)
                gf_fes = gf.FESpace()
                gf_vdim = gf.VectorDim()
                gf_nnode = gf_fes.GetNDofs() // gf_vdim
                gf_nelem = gf_fes.GetNBE()
                data = np.array(gf.GetDataArray())
                if prop['tags']['assoc'] == 'nodes':
                    assert gf_nnode == nnode, "Mesh and grid function have different number of nodes"
                    if gf_fes.GetOrdering() == 0:
                        data = data.reshape((gf_vdim, gf_nnode)).T
                    elif gf_fes.GetOrdering() == 1:
                        data = data.reshape((gf_nnode, gf_vdim))
                    else:
                        raise NotImplementedError
                    output.PointData.append(data, name)
                elif prop['tags']['assoc'] == 'elements':
                    assert gf_nelem == nelem, "Mesh and grid function have different number of elements"
                    if gf_fes.GetOrdering() == 0:
                        data = data.reshape((gf_vdim, gf_nelem)).T
                    elif gf_fes.GetOrdering() == 1:
                        data = data.reshape((gf_nelem, gf_vdim))
                    else:
                        raise NotImplementedError
                    output.CellData.append(data, name)
                else:
                    raise NotImplementedError("assoc: '{}'".format(
                        prop['tags']['assoc']))

        return 1