Esempio n. 1
0
    def _load_data(self):
        """Function to read in all particle data for a simulation.
        """
        particles = self
        pointer_location = {particle: [0] * len(self.times) for particle in particles}

        for particle in particles:
            if len(particle._positions) == 0 and len(particle._tags) == 0:
                for t in range(len(self.times)):
                    size = 0
                    for mesh in self._file_paths.keys():
                        size += particle.n_particles[mesh][t]
                    for quantity in particle.quantities:
                        particle._data[quantity.quantity].append(np.empty((size,), dtype=np.float32))
                    particle._positions.append(np.empty((size, 3), dtype=np.float32))
                    particle._tags.append(np.empty((size,), dtype=int))

        for mesh, file_path in self._file_paths.items():
            with open(file_path, 'rb') as infile:
                # Initial offset (ONE, fds version and number of particle classes)
                offset = 3 * fdtype.INT.itemsize
                # Number of quantities for each particle class (plus an INTEGER_ZERO)
                offset += fdtype.new((('i', 2),)).itemsize * len(particles)
                # 30-char long name and unit information for each quantity
                offset += fdtype.new((('c', 30),)).itemsize * 2 * sum(
                    [len(particle.quantities) for particle in particles])
                infile.seek(offset)

                for t in range(len(self.times)):
                    # Skip time value
                    infile.seek(fdtype.FLOAT.itemsize, 1)

                    # Read data for each particle class
                    for particle in particles:
                        # Read number of particles in each class
                        n_particles = fdtype.read(infile, fdtype.INT, 1)[0][0][0]
                        offset = pointer_location[particle][t]
                        # Read positions
                        dtype_positions = fdtype.new((('f', 3 * n_particles),))
                        pos = fdtype.read(infile, dtype_positions, 1)[0][0]
                        particle._positions[t][offset: offset + n_particles] = pos.reshape((n_particles, 3),
                                                                                           order='F').astype(float)

                        # Read tags
                        dtype_tags = fdtype.new((('i', n_particles),))
                        particle._tags[t][offset: offset + n_particles] = \
                            fdtype.read(infile, dtype_tags, 1)[0][0]

                        # Read actual quantity values
                        if len(particle.quantities) > 0:
                            dtype_data = fdtype.new(
                                (('f', str((n_particles, len(particle.quantities)))),))
                            data_raw = fdtype.read(infile, dtype_data, 1)[0][0].reshape(
                                (n_particles, len(particle.quantities)), order='F')

                            for q, quantity in enumerate(particle.quantities):
                                particle._data[quantity.quantity][t][
                                offset:offset + n_particles] = data_raw[:, q].astype(float)

                        pointer_location[particle][t] += particle.n_particles[mesh][t]
Esempio n. 2
0
class SubPlot3D:
    """Subplot of a pl3d output for a single mesh.

    :ivar mesh: The mesh containing the data.
    """
    # Offset of the binary file to the end of the file header.
    _offset = fdtype.new((('i', 3), )).itemsize + fdtype.new(
        (('i', 4), )).itemsize

    def __init__(self, file_path: str, mesh: Mesh):
        self.file_path = file_path  # Path to the binary data file
        self.mesh = mesh

    @property
    def data(self) -> np.ndarray:
        """Method to lazy load the 3D data for each quantity of a single mesh.

        :returns: 4D numpy array with (x,y,z,q) as dimensions, while q represents the 5 quantities.
        """
        if not hasattr(self, "_data"):
            with open(self.file_path, 'rb') as infile:
                dtype_data = fdtype.new(
                    (('f', self.mesh.dimension.size() * 5), ))
                infile.seek(self._offset)
                self._data = fdtype.read(infile, dtype_data, 1)[0][0].reshape(
                    self.mesh.dimension.shape() + (5, ), order='F')
        return self._data

    def clear_cache(self):
        """Remove all data from the internal cache that has been loaded so far to free memory.
        """
        if hasattr(self, "_data"):
            del self._data
Esempio n. 3
0
    def __init__(self,
                 mesh: Mesh,
                 iso_filepath: str,
                 times: List,
                 viso_filepath: str = ""):
        self.mesh = mesh

        self.file_path = iso_filepath
        if viso_filepath != "":
            self.v_file_path = viso_filepath

        with open(self.file_path, 'rb') as infile:
            nlevels = fdtype.read(infile, fdtype.INT, 3)[2][0][0]
            dtype_header_levels = fdtype.new((('f', nlevels), ))
            dtype_header_zeros = fdtype.combine(fdtype.INT,
                                                fdtype.new((('i', 2), )))
            self._offset = fdtype.INT.itemsize * 3 + dtype_header_levels.itemsize + \
                           dtype_header_zeros.itemsize

            self.times = times
            self.n_vertices = list()
            self.n_triangles = list()

            if not settings.LAZY_LOAD:
                self._load_data(infile)

        if self.has_color_data:
            if not settings.LAZY_LOAD:
                with open(self.v_file_path, 'rb') as infile:
                    self._load_vdata(infile)
Esempio n. 4
0
    def _load_vdata(self, infile: BinaryIO):
        """Loads all color data for all isosurfaces in a given viso file.
        """
        self._colors = np.empty((self.n_t, ), dtype=object)
        dtype_nverts = fdtype.new((('i', 4), ))

        infile.seek(fdtype.INT.itemsize * 2)
        t = fdtype.read(infile, fdtype.FLOAT, 1)
        while t.size != 0:
            time_index = self.times.index(t[0][0][0])
            n_vertices = fdtype.read(infile, dtype_nverts, 1)[0][0][2]
            if n_vertices > 0:
                self._colors[time_index] = fdtype.read(
                    infile, fdtype.new((('f', n_vertices), )), 1)
            t = fdtype.read(infile, fdtype.FLOAT, 1)
Esempio n. 5
0
    def _load_data(self, infile: BinaryIO):
        """Loads data for the subsurface which is given in an iso file.
        """
        dtype_time = fdtype.new((('f', 1), ('i', 1)))
        dtype_dims = fdtype.new((('i', 2), ))

        self._vertices = list()
        self._triangles = list()
        self._surfaces = list()

        infile.seek(self._offset)
        time_data = fdtype.read(infile, dtype_time, 1)
        while time_data.size != 0:
            self.times.append(time_data[0][0][0])

            dims_data = fdtype.read(infile, dtype_dims, 1)
            n_vertices = dims_data[0][0][0]
            n_triangles = dims_data[0][0][1]
            if n_vertices > 0:
                dtype_vertices = fdtype.new((('f', 3 * n_vertices), ))
                dtype_triangles = fdtype.new((('i', 3 * n_triangles), ))
                dtype_surfaces = fdtype.new((('i', n_triangles), ))

                self._vertices.append(
                    fdtype.read(infile, dtype_vertices, 1)[0][0].reshape(
                        (n_vertices, 3)).astype(float))
                self._triangles.append(
                    fdtype.read(infile, dtype_triangles, 1)[0][0].reshape(
                        (n_triangles, 3)).astype(int) - 1)
                self._surfaces.append(
                    fdtype.read(infile, dtype_surfaces, 1)[0][0].astype(int) -
                    1)
                self.n_vertices.append(n_vertices)
                self.n_triangles.append(n_triangles)
            else:
                self._vertices.append(np.empty((0, 3)))
                self._triangles.append(np.empty((0, 3)))
                self._surfaces.append(np.empty((0, )))
                self.n_vertices.append(0)
                self.n_triangles.append(0)

            time_data = fdtype.read(infile, dtype_time, 1)

        self.n_t = len(self.times)
Esempio n. 6
0
    def data(self) -> np.ndarray:
        """Method to lazy load the 3D data for each quantity of a single mesh.

        :returns: 4D numpy array with (x,y,z,q) as dimensions, while q represents the 5 quantities.
        """
        if not hasattr(self, "_data"):
            with open(self.file_path, 'rb') as infile:
                dtype_data = fdtype.new(
                    (('f', self.mesh.dimension.size() * 5), ))
                infile.seek(self._offset)
                self._data = fdtype.read(infile, dtype_data, 1)[0][0].reshape(
                    self.mesh.dimension.shape() + (5, ), order='F')
        return self._data
Esempio n. 7
0
    def _load_isosurface(self, smv_file: TextIO, line: str):
        """Loads the isosurface at current pointer position.
        """
        double_quantity = line[0] == 'T'
        mesh_index = int(line.strip().split()[1]) - 1

        iso_filename = smv_file.readline().strip()
        iso_id = int(iso_filename.split('_')[-1][:-4])
        iso_file_path = os.path.join(self.root_path, iso_filename)

        if double_quantity:
            viso_file_path = os.path.join(self.root_path,
                                          smv_file.readline().strip())
        quantity = smv_file.readline().strip()
        label = smv_file.readline().strip()
        unit = smv_file.readline().strip()
        if double_quantity:
            v_quantity = smv_file.readline().strip()
            v_label = smv_file.readline().strip()
            v_unit = smv_file.readline().strip()

        if iso_id not in self.isosurfaces:
            with open(iso_file_path, 'rb') as infile:
                nlevels = fdtype.read(infile, fdtype.INT, 3)[2][0][0]

                dtype_header_levels = fdtype.new((('f', nlevels), ))
                levels = fdtype.read(infile, dtype_header_levels, 1)[0]
        if double_quantity:
            if iso_id not in self.isosurfaces:
                self.isosurfaces[iso_id] = Isosurface(iso_id,
                                                      double_quantity,
                                                      quantity,
                                                      label,
                                                      unit,
                                                      levels,
                                                      v_quantity=v_quantity,
                                                      v_label=v_label,
                                                      v_unit=v_unit)
            self.isosurfaces[iso_id]._add_subsurface(
                self.meshes[mesh_index],
                iso_file_path,
                viso_file_path=viso_file_path)
        else:
            if iso_id not in self.isosurfaces:
                self.isosurfaces[iso_id] = Isosurface(iso_id, double_quantity,
                                                      quantity, label, unit,
                                                      levels)
            self.isosurfaces[iso_id]._add_subsurface(self.meshes[mesh_index],
                                                     iso_file_path)
Esempio n. 8
0
    def _load_boundary_data(self, smv_file: TextIO, line: str,
                            cell_centered: bool):
        """Loads the boundary data at current pointer position.
        """
        line = line.split()
        mesh_index = int(line[1]) - 1
        mesh = self.meshes[mesh_index]

        filename = smv_file.readline().strip()
        quantity = smv_file.readline().strip()
        label = smv_file.readline().strip()
        unit = smv_file.readline().strip()

        bid = int(filename.split('_')[-1][:-3]) - 1

        file_path = os.path.join(self.root_path, filename)

        patches = dict()

        if os.path.exists(file_path + ".bnd"):
            times = list()
            lower_bounds = list()
            upper_bounds = list()
            with open(file_path + ".bnd", 'r') as bnd_file:
                for line in bnd_file:
                    splits = line.split()
                    times.append(float(splits[0]))
                    lower_bounds.append(float(splits[1]))
                    upper_bounds.append(float(splits[2]))
            times = np.array(times)
            lower_bounds = np.array(lower_bounds, dtype=np.float32)
            upper_bounds = np.array(upper_bounds, dtype=np.float32)
            n_t = times.shape[0]
        else:
            times = None
            n_t = -1
            lower_bounds = np.array([0.0], dtype=np.float32)
            upper_bounds = np.array([np.float32(-1e33)], dtype=np.float32)

        with open(file_path, 'rb') as infile:
            # Offset of the binary file to the end of the file header.
            offset = 3 * fdtype.new((('c', 30), )).itemsize
            infile.seek(offset)

            n_patches = fdtype.read(infile, fdtype.INT, 1)[0][0][0]

            dtype_patches = fdtype.new((('i', 9), ))
            patch_infos = fdtype.read(infile, dtype_patches, n_patches)
            offset += fdtype.INT.itemsize + dtype_patches.itemsize * n_patches
            patch_offset = fdtype.FLOAT.itemsize

            for patch_info in patch_infos:
                patch_info = patch_info[0]

                extent, dimension = self._indices_to_extent(
                    patch_info[:6], mesh)
                orientation = patch_info[6]
                obst_index = patch_info[7]

                p = Patch(file_path, dimension, extent, orientation,
                          cell_centered, patch_offset, offset, n_t)

                # Skip obstacles with index 0, which just gives the extent of the (whole) mesh faces
                # These might be needed in case of "closed" mesh faces
                if obst_index != 0:
                    obst_index -= 1  # Account for fortran indexing
                    if obst_index not in patches:
                        patches[obst_index] = list()
                    patches[obst_index].append(p)
                patch_offset += fdtype.new(
                    (('f',
                      str(p.dimension.shape(cell_centered=False))), )).itemsize

        for obst_index, p in patches.items():
            for patch in p:
                patch._post_init(patch_offset)

            self._subobstructions[mesh][obst_index]._add_patches(
                bid, cell_centered, quantity, label, unit, p, times, n_t,
                lower_bounds, upper_bounds)