Source code for stride.problem.problem


import os
import numpy as np

from .base import Gridded
from . import Medium, Transducers, Geometry, Acquisitions
from .. import plotting


__all__ = ['Problem', 'SubProblem']


[docs] class Problem(Gridded): """ The Problem is the object that fully defines the setting in which Stride works. The problem defines a medium with a set of fields (such as Vp or density), some transducers (such as a series of scalar point transducers), a geometry where those transducers are located in space, and the acquisitions that happen given that geometry. The problem also defines a problem type, which determines the physics of interest, such as the second-order isotropic acoustic wave equation. And a numerical implementation of those physics, such as through the finite-difference library Devito. Parameters ---------- name : str Name of the problem. grid : Grid or any of Space or Time Grid on which the Problem is defined input_folder : str, optional Default folder from which files should be read, defaults to current working directory. output_folder : str, optional Default folder to which files should be written, defaults to current working directory. medium : Medium, optional Predefined Medium of the problem. transducers : Transducers, optional Predefined Transducers of the problem. geometry : Geometry, optional Predefined Geometry of the problem. acquisitions : Acquisitions, optional Predefined Acquisitions of the problem. """ def __init__(self, name, *args, **kwargs): super().__init__(*args, **kwargs) self.name = name self.input_folder = kwargs.pop('input_folder', os.getcwd()) self.output_folder = kwargs.pop('output_folder', os.getcwd()) self.problem_config = {} medium = kwargs.pop('medium', None) if medium is None: medium = Medium(problem=self) self.medium = medium transducers = kwargs.pop('transducers', None) if transducers is None: transducers = Transducers(problem=self) self.transducers = transducers geometry = kwargs.pop('geometry', None) if geometry is None: geometry = Geometry(transducers=transducers, problem=self) self.geometry = geometry acquisitions = kwargs.pop('acquisitions', None) if acquisitions is None: acquisitions = Acquisitions(geometry=geometry, problem=self) self.acquisitions = acquisitions
[docs] def load(self, *args, **kwargs): """ Load all elements in the Problem. See :class:`~mosaic.file_manipulation.h5.HDF5` for more information on the parameters of this method. Returns ------- """ kwargs['project_name'] = kwargs.get('project_name', self.name) kwargs['path'] = kwargs.get('path', self.input_folder) try: self.medium.load(*args, **kwargs) except FileNotFoundError: pass try: self.transducers.load(*args, **kwargs) except FileNotFoundError: pass try: self.geometry.load(*args, **kwargs) except FileNotFoundError: pass try: self.acquisitions.load(*args, **kwargs) except FileNotFoundError: pass grid_properties = ['space', 'time', 'slow_time'] problem_properties = ['medium', 'transducers', 'geometry', 'acquisitions'] for problem_property in problem_properties: problem_property = getattr(self, problem_property) for grid_property in grid_properties: if getattr(self, grid_property) is None and getattr(problem_property, grid_property) is not None: setattr(self._grid, grid_property, getattr(problem_property, grid_property)) for problem_property in problem_properties: problem_property = getattr(self, problem_property) for grid_property in grid_properties: if getattr(problem_property, grid_property) is None: setattr(problem_property._grid, grid_property, getattr(self, grid_property))
[docs] def time_resample(self, new_step, new_num=None, **kwargs): ''' In-place operatin to resample the wavelets and data into a grid with new time-spacing. Sinc interpolation is used. Parameters ---------- new_step : float The time spacing for the interpolated grid new_num : int, optional The number of time-points, default is calculated to match input pulse length in [s] Returns ------- ''' old_step = self.time.step old_num = self.time.num self.grid.time.resample(new_step=new_step, new_num=new_num) for shot in self.acquisitions.shots: shot.wavelets = shot.wavelets._resample(factor=old_step/new_step, new_num=new_num) # resample wavelet shot.observed = shot.observed._resample(factor=old_step/new_step, new_num=new_num) # resample observed
[docs] def dump(self, *args, **kwargs): """ Dump all elements in the Problem. See :class:`~mosaic.file_manipulation.h5.HDF5` for more information on the parameters of this method. Returns ------- """ kwargs['project_name'] = kwargs.get('project_name', self.name) kwargs['path'] = kwargs.get('path', self.output_folder) if kwargs.pop('dump_medium', True): self.medium.dump(*args, **kwargs) if kwargs.pop('dump_transducers', True): self.transducers.dump(*args, **kwargs) if kwargs.pop('dump_geometry', True): self.geometry.dump(*args, **kwargs) if kwargs.pop('dump_acquisitions', True): self.acquisitions.dump(*args, **kwargs)
[docs] def plot(self, **kwargs): """ Plot all elements in the Problem. Parameters ---------- kwargs Arguments for plotting the fields. Returns ------- """ kwargs['plot'] = False plot_medium = kwargs.pop('medium', True) plot_geometry = kwargs.pop('geometry', True) plot_acquisitions = kwargs.pop('acquisitions', True) # Medium medium_axes = [None] if plot_medium: medium_axes = self.medium.plot(**kwargs) medium_axes = medium_axes if len(medium_axes) else [None] # Geometry geometry_axes = medium_axes if plot_geometry: geometry_axes = [] for axis in medium_axes: geometry_axes.append(self.geometry.plot(axis=axis, title=None, **kwargs)) plotting.show(geometry_axes) # Acquisitions if plot_acquisitions: acquisitions_axes = self.acquisitions.plot(plot=False) plotting.show(acquisitions_axes)
[docs] def sub_problem(self, shot_id): """ Create a subset object for a certain shot. A SubProblem contains everything that is needed to fully determine how to run a particular shot. This method takes care of selecting creating a SubProblem instance and populating it appropriately. Parameters ---------- shot_id : int ID of the shot for which this sub-problem will be generated. Returns ------- SubProblem Newly created SubProblem instance. """ if isinstance(shot_id, (np.int32, np.int64)): shot_id = int(shot_id) sub_problem = SubProblem(self.name, input_folder=self.input_folder, output_folder=self.output_folder, grid=self.grid) shot = self.acquisitions.get(shot_id) # Set up transducers sub_problem.transducers = self.transducers.sub_problem(shot, sub_problem) # Set up geometry sub_problem.geometry = self.geometry.sub_problem(shot, sub_problem) # Set up acquisitions shot = shot.sub_problem(shot, sub_problem) sub_problem.shot = shot sub_problem.shot_id = shot.id sub_problem.acquisitions = self.acquisitions.sub_problem(shot, sub_problem) return sub_problem
[docs] class SubProblem(Gridded): """ The SubProblem is the object that fully defines how a specific Shot is to be run. The SubProblem resembles the Problem from which ir originates, but takes from it only those parts that are relevant for this particular Shot. The SubProblem defines a medium with a set of fields (such as Vp or density), some transducers (such as a series of scalar point transducers), a geometry where those transducers are located in space, and the acquisitions that happen given that geometry. The SubProblem also defines a problem type, which determines the physics of interest, such as the second-order isotropic acoustic wave equation. And a numerical implementation of those physics, such as through the finite-difference library Devito. Parameters ---------- name : str Name of the problem. grid : Grid or any of Space or Time Grid on which the Problem is defined input_folder : str, optional Default folder from which files should be read, defaults to current working directory. output_folder : str, optional Default folder to which files should be written, defaults to current working directory. transducers : Transducers, optional Predefined Transducers of the problem. geometry : Geometry, optional Predefined Geometry of the problem. acquisitions : Acquisitions, optional Predefined Acquisitions of the problem. """ def __init__(self, name, *args, **kwargs): super().__init__(*args, **kwargs) self.shot = None self.shot_id = -1 self.name = name self.input_folder = kwargs.pop('input_folder', os.getcwd()) self.output_folder = kwargs.pop('output_folder', os.getcwd()) self.problem_config = {} self.transducers = kwargs.pop('transducers', None) self.geometry = kwargs.pop('geometry', None) self.acquisitions = kwargs.pop('acquisitions', None)