Exemple #1
0
def get_contrast_map(epsilon_r=None,
                     sigma=None,
                     epsilon_rb=None,
                     sigma_b=None,
                     omega=None):
    """Compute the contrast function for a given image.

    Parameters
    ----------
        epsilon_r : `:class:numpy.ndarray`
            A matrix with the relative permittivity map.

        sigma : `:class:numpy.ndarray`
            A matrix with the conductivity map [S/m].

        epsilon_rb : float
            Background relative permittivity of the medium.

        sigma_b : float
            Background conductivity of the medium [S/m].

        frequency : float
            Linear frequency of operation [Hz].
    """
    if epsilon_r is None and sigma is None:
        raise error.MissingInputError('get_contrast_map', 'epsilon_r or sigma')
    if epsilon_r is not None and epsilon_rb is None:
        raise error.MissingInputError('get_contrast_map', 'epsilon_rb')
    if sigma is not None and sigma_b is None:
        raise error.MissingInputError('get_contrast_map', 'sigma_b')
    if sigma is not None and omega is None:
        raise error.MissingInputError('get_contrast_map', 'omega')
    if sigma is None:
        return (epsilon_r / epsilon_rb - 1) + 0j
    elif epsilon_r is None:
        return -1j * (sigma - sigma_b) / (omega * epsilon_rb * ct.epsilon_0)
    else:
        return (epsilon_r / epsilon_rb - 1 - 1j * (sigma - sigma_b) /
                (omega * epsilon_rb * ct.epsilon_0))
    def __init__(self, configuration, linear_solver, parameter):
        r"""Create the object.

        Parameters
        ----------
            configuration : :class:`configuration.Configuration`
                The container with the problem configuration variables.

            linear_solver : {'tikhonov', 'landweber', 'cg', 'lstsq'}
                The name of the chosen linear system solver.

            parameter
                The parameter to configure the linear solver. It may be
                defined in different ways:

            * `linear_solver='tikhonov'`: in this case, `parameter` will
              depend on different strategies of determining it. There
              are three different choice strategies:
                * Fixed: when you want to define an arbitrary value. The
                  argument must be `parameter=('fixed', float())` or
                  `parameter=float()`.
                * SVD-based: a strategy according to [1]_, which is
                  based on Singular Value Decomposition and the
                  definition of a Relative Residual Error. In this case,
                  `parameter='lavarello'.
                * The Discrepancy Principle of Mozorov: a traditional
                  principle for defining the regularization parameter of
                  Tikhonov regularization [2]_. In this case,
                  `parameter='mozorov'`.
                * L-curve: the parameter value is chosen according to
                  the curve which relates error and solution norm.

            * `linear_solver='landweber'`: the method depend on two
              parameters: the regularization coefficient and the number
              of iterations. Therefore, `parameter=(float(), int())` for
              defining the regularization coefficient and the number of
              iterations, respectively; or `parameter=float()`, which
              will define the regularization coefficient and the number
              of iterations will be defined as 1000. The regularization
              parameter is defined as a proportion constant to:
              .. math:: \frac{1}{||A||^2}

            * `linear_solver='cg'`: The Conjugated-Gradient method
              depends on a parameter which means the noise level of the
              data. Therefore, `parameter=float()`.

            * `linear_solver='lstsq'`: The Least Squares Method depend
              on a parameter called `rcond` which means the truncation
              level of singular values of `A`. Therefore, singular
              values under this threshold will be truncated to zero.
              The argument is `parameter=float()`. Default: `1e-3`.

        References
        ----------
        .. [1] Lavarello, Roberto, and Michael Oelze. "A study on the
           reconstruction of moderate contrast targets using the
           distorted Born iterative method." IEEE transactions on
           ultrasonics, ferroelectrics, and frequency control 55.1
           (2008): 112-124.
        .. [2] Kirsch, Andreas. An introduction to the mathematical
           theory of inverse problems. Vol. 120. Springer Science &
           Business Media, 2011.
        """
        super().__init__(configuration)
        self.name = "Method of Weighted Residuals"
        self.alias_name = 'mwr'
        self.discretization_method_alias = ''
        self.discretization_method_name = ''

        if linear_solver == TIKHONOV_METHOD:
            self.linsolver = linear_solver
            if isinstance(parameter, str):
                if (parameter == MOZOROV_CHOICE
                        or parameter == LAVARELLO_CHOICE):
                    self._choice_strategy = parameter
                    self.parameter = None
                elif parameter == LCURVE_CHOICE:
                    self._choice_strategy = parameter
                    self._bounds = None
                    self._number_terms = None
                elif parameter == FIXED_CHOICE:
                    raise error.MissingInputError(
                        'MethodOfWeightedResiduals.__init__',
                        'parameter_value')
                else:
                    raise error.WrongValueInput(
                        'MethodOfWeightedResiduals.__init__', 'parameter',
                        "{'mozorov', 'lavarello', 'fixed'}", parameter)
            elif isinstance(parameter, float):
                self.parameter = parameter
                self._choice_strategy = FIXED_CHOICE
            elif isinstance(parameter, tuple) or isinstance(parameter, list):
                if parameter[0] == FIXED_CHOICE:
                    if isinstance(parameter[1], float):
                        self._choice_strategy = parameter[0]
                        self.parameter = parameter[1]
                    else:
                        raise error.WrongTypeInput(
                            'MethodOfWeightedResiduals.__init__',
                            "('fixed', parameter_value)", 'float',
                            type(parameter[1]))
                elif (parameter[0] == LAVARELLO_CHOICE
                      or parameter[0] == MOZOROV_CHOICE):
                    self._choice_strategy = parameter[0]
                    self.parameter = parameter[1]
                elif parameter[0] == LCURVE_CHOICE:
                    self._choice_strategy = parameter[0]
                    if len(parameter) == 2:
                        self._number_terms = parameter[1]
                        self._bounds = None
                    elif len(parameter) == 3:
                        self._number_terms = parameter[1]
                        self._bounds = (parameter[2], 0)
                    elif len(parameter) == 4:
                        self._number_terms = parameter[1]
                        self._bounds = (parameter[2], parameter[3])
                    else:
                        raise error.WrongValueInput(
                            'MethodOfWeightedResiduals', 'parameter',
                            "'lcurve' or ('lcurve', number_terms) " +
                            "or ('lcurve', number_terms, lower_bound) " +
                            "or ('lcurve', number_terms, lower_bound, " +
                            " upper_bound)", "len(parameter) > 4")
                else:
                    raise error.WrongValueInput(
                        'MethodOfWeightedResiduals.__init__',
                        '(choice_strategy,...)',
                        "{'mozorov', 'lavarello', 'fixed', 'exhaustive'," +
                        " 'lcurve'}", parameter[0])
            if self._choice_strategy == LAVARELLO_CHOICE:
                self._beta_approximation = None

        elif linear_solver == LANDWEBER_METHOD:
            self.linsolver = linear_solver
            if isinstance(parameter, tuple):
                self.parameter = parameter
            else:
                self.parameter = (parameter, 1000)
        elif linear_solver == CONJUGATED_GRADIENT_METHOD:
            self.linsolver = linear_solver
            if isinstance(parameter, float):
                self.parameter = parameter
            else:
                raise error.WrongTypeInput(
                    'MethodOfWeightedResiduals.__init__', 'parameter', 'float',
                    type(parameter))
        elif linear_solver == LEAST_SQUARES_METHOD:
            self.linsolver = linear_solver
            if isinstance(parameter, float):
                self.parameter = parameter
            elif parameter is None:
                self.parameter = 1e-3
            else:
                raise error.WrongTypeInput(
                    'MethodOfWeightedResiduals.__init__',
                    'parameter',
                    'float',
                )
        else:
            raise error.WrongValueInput(
                'MethodOfWeightedResiduals.__init__', 'linear_solver',
                "{'tikhonov', 'landweber', 'cg'," + "'lstsq'}", linear_solver)
Exemple #3
0
def get_coordinates_ddomain(configuration=None,
                            resolution=None,
                            dx=None,
                            dy=None,
                            xmin=None,
                            xmax=None,
                            ymin=None,
                            ymax=None):
    """Return the meshgrid of the image domain.

    Examples
    --------
        The function must be called in only one of the two different
        ways:

        >>> get_coordinates_ddomain(configuration=Configuration()
                                    resolution=(100, 100))
        >>> get_coordinates_ddomain(dx=.1, dy=.1, xmin=-1., xmax=1.,
                                    ymin=-1., ymax=1.)

    Parameters
    ----------
        configuration : :class:`Configuration`
            A configuration object.

        resolution : 2-tuple
            Discretization size in y- and x-coordinates (this order).

        dx, dy : float
            Cell size.

        xmin, xmax : float
            Limits of the interval in x-axis.

        ymin, ymax : float
            Limits of the interval in y-axis.

    Notes
    -----
        The D-domain are such that (x,y) in [xmin,xmax] times [ymin,
        ymax]. The coordinates are positioned at the center of the
        cells.
    """
    function_name = 'get_coordinates_ddomain'
    if configuration is not None and resolution is None:
        raise error.MissingInputError(function_name, 'resolution')
    elif configuration is None and resolution is not None:
        raise error.MissingInputError(function_name, 'configuration')
    elif configuration is None and (dx is None or dy is None or xmin is None
                                    or xmax is None or ymin is None
                                    or ymax is None):
        inputs = []
        if dx is None:
            inputs.append('dx')
        if dy is None:
            inputs.append('dy')
        if xmin is None:
            inputs.append('xmin')
        if xmax is None:
            inputs.append('xmax')
        if ymin is None:
            inputs.append('ymin')
        if ymax is None:
            inputs.append('ymax')
        raise error.MissingInputError(function_name, inputs)

    if configuration is not None:
        NY, NX = resolution
        xmin, xmax = get_bounds(configuration.Lx)
        ymin, ymax = get_bounds(configuration.Ly)
        dx, dy = configuration.Lx / NX, configuration.Ly / NY

    return np.meshgrid(np.arange(xmin + .5 * dx, xmax, dx),
                       np.arange(ymin + .5 * dy, ymax, dy))
Exemple #4
0
    def __init__(self,
                 name=None,
                 number_measurements=10,
                 number_sources=10,
                 observation_radius=None,
                 frequency=None,
                 wavelength=None,
                 background_permittivity=1.,
                 background_conductivity=.0,
                 image_size=[1., 1.],
                 wavelength_unit=True,
                 magnitude=1.,
                 perfect_dielectric=False,
                 good_conductor=False,
                 import_filename=None,
                 import_filepath='',
                 path=''):
        """Build or import a configuration object.

        You may either give the parameters or import information from a
        save object. In addition, you must give either the frequency of
        operation or the wavelength.

        Parameters
        ----------
            name : string
                A string naming the problem configuration.

            number_measurements : int, default: 10
                Receivers in S-domain.

            number_sources : int, default: 10
                Sources in S-domain

            observation_radius : float, default: 1.1*sqrt(2)*max([Lx,Ly])
                Radius for circular array of sources and receivers at
                S-domain [m]

            frequency : float
                Linear frequency of operation [Hz]

            wavelength : float
                Background wavelength [m]

            background_permittivity : float, default: 1.
                Relative permittivity.

            background_conductivity : float, default: .0 [S/m]

            image_size : 2-tuple of int, default: (1., 1.)
                Side length of the image domain (D-domain). It may be
                given in meters or in wavelengths.

            wavelength_unit : boolean, default: True
                If `True`, the variable image_size will be interpreted
                as given in wavelegnths. Otherwise, it will be
                interpreted in meters.

            magnitude : float, default: 1.0
                Magnitude of the incident field.

            perfect_dielectric : boolean, default: False
                If `True`, it indicates the assumption of only perfect
                dielectric objects. Then, only the relative permittivity
                map will be recovered.

            good_conductor : boolean, default: False
                If `True`, it indicates the assumption of only good
                conductors objects. Then, only the conductivity map will
                be recovered.

            import_filename : string, default: None
                A string with the name of the pickle file containing the
                information of a previous Configuration object.

            import_filepath : string, default: ''
                A string containing the path to the object to be
                imported.

        """
        if import_filename is not None:
            self.importdata(import_filename, import_filepath)

        else:

            if name is None:
                raise error.MissingInputError('Configuration.__init__()',
                                              'name')
            if wavelength is None and frequency is None:
                raise error.MissingInputError('Configuration.__init__()',
                                              'frequency or wavelength')
            elif wavelength is not None and frequency is not None:
                raise error.ExcessiveInputsError('Configuration.__init__()',
                                                 ['frequency', 'wavelength'])
            if perfect_dielectric and good_conductor:
                raise error.ExcessiveInputsError(
                    'Configuration.__init__()',
                    ['perfect_dielectric', 'good_conductor'])

            self.name = name
            self.NM = number_measurements
            self.NS = number_sources
            self.epsilon_rb = background_permittivity
            self.sigma_b = background_conductivity
            self.perfect_dielectric = perfect_dielectric
            self.good_conductor = good_conductor
            self.E0 = magnitude
            self.path = path

            if frequency is not None:
                self.f = frequency
                self.lambda_b = compute_wavelength(frequency,
                                                   self.epsilon_rb,
                                                   sigma=self.sigma_b)
            else:
                self.lambda_b = wavelength
                self.f = compute_frequency(self.lambda_b, self.epsilon_rb)

            self.kb = compute_wavenumber(self.f,
                                         epsilon_r=self.epsilon_rb,
                                         sigma=self.sigma_b)

            if wavelength_unit:
                self.Lx = image_size[1] * self.lambda_b
                self.Ly = image_size[0] * self.lambda_b
            else:
                self.Lx = image_size[1]
                self.Ly = image_size[0]

            if observation_radius is None:
                self.Ro = 1.1 * np.sqrt(2) * max([self.Lx, self.Ly])
            else:
                if wavelength_unit:
                    self.Ro = observation_radius * self.lambda_b
                else:
                    self.Ro = observation_radius
Exemple #5
0
    def __init__(self,
                 name=None,
                 configuration_filename=None,
                 resolution=None,
                 scattered_field=None,
                 total_field=None,
                 incident_field=None,
                 relative_permittivity_map=None,
                 conductivity_map=None,
                 noise=None,
                 import_filename=None,
                 import_filepath='',
                 homogeneous_objects=True,
                 compute_residual_error=True,
                 compute_map_error=False,
                 compute_totalfield_error=False,
                 path=''):
        r"""Build or import an object.

        You must give either the import file name and path or the
        required variables.

        Call signatures::

            InputData(import_filename='my_file',
                      import_filepath='./data/')
            InputData(name='instance00',
                      configuration_filename='setup00', ...)

        Parameters
        ----------
            name : string
                The name of the instance.

            `configuration_filename` : string
                A string with the name of the problem configuration
                file.

            resolution : 2-tuple
                The size, in pixels, of the image to be recovered. Y-X
                ordered.

            scattered_field : :class:`numpy.ndarray`
                A matrix containing the scattered field information at
                S-domain.

            total_field : :class:`numpy.ndarray`
                A matrix containing the total field information at
                D-domain.

            incident_field : :class:`numpy.ndarray`
                A matrix containing the incident field information at
                D-domain.

            relative_permittivity_map : :class:`numpy.ndarray`
                A matrix with the discretized image of the relative
                permittivity map.

            conductivity_map : :class:`numpy.ndarray`
                A matrix with the discretized image of the conductivity
                map.

            noise : float
                Noise level of scattered field data.

            homogeneous_objects : bool
                A flag to indicate if the instance only contains
                homogeneous objects.

            compute_residual_error : bool
                A flag to indicate the measurement of the residual error
                throughout or at the end of the solver executation.

             compute_map_error : bool
                A flag to indicate the measurement of the error in
                predicting the dielectric properties of the image.

             compute_totalfield_error : bool
                A flag to indicate the measurement of the estimation
                error of the total field throughout or at the end of the
                solver executation.

            import_filename : string
                A string with the name of the saved file.

            import_filepath : string
                A string with the path to the saved file.
        """
        if import_filename is not None:
            self.importdata(import_filename, import_filepath)

        else:

            if name is None:
                raise error.MissingInputError('InputData.__init__()', 'name')
            if configuration_filename is None:
                raise error.MissingInputError('InputData.__init__()',
                                              'configuration_filename')
            if (resolution is None and relative_permittivity_map is None
                    and conductivity_map is None):
                raise error.MissingInputError('InputData.__init__()',
                                              'resolution')

            self.name = name
            self.path = path
            self.configuration_filename = configuration_filename
            self.homogeneous_objects = homogeneous_objects
            self.compute_residual_error = compute_residual_error
            self.compute_map_error = compute_map_error
            self.compute_totalfield_error = compute_totalfield_error
            self.total_field_resolution = None

            if resolution is not None:
                self.resolution = resolution
            else:
                self.resolution = None

            if scattered_field is not None:
                self.es = np.copy(scattered_field)
            else:
                self.es = None

            if total_field is not None:
                self.et = np.copy(total_field)
            else:
                self.et = None

            if incident_field is not None:
                self.ei = np.copy(incident_field)
            else:
                self.ei = None

            if relative_permittivity_map is not None:
                self.epsilon_r = relative_permittivity_map
                if resolution is None:
                    self.resolution = relative_permittivity_map.shape
            else:
                self.epsilon_r = None

            if conductivity_map is not None:
                self.sigma = conductivity_map
                if resolution is None:
                    self.resolution = conductivity_map.shape
            else:
                self.sigma = None

            if noise is not None:
                self.noise = noise
            else:
                self.noise = None
Exemple #6
0
    def draw(self,
             figure_title=None,
             file_path='',
             file_format='eps',
             show=False):
        """Draw the relative permittivity/conductivity map.

        Parameters
        ----------
            figure_title : str, optional
                A title that you want to give to the figure.

            show : boolean, default: False
                If `True`, a window will be raised to show the image. If
                `False`, the image will be saved.

            file_path : str, default: ''
                A path where you want to save the figure.

            file_format : str, default: 'eps'
                The file format. It must be one of the available ones by
                `matplotlib.pyplot.savefig()`.
        """
        if self.epsilon_r is not None and self.sigma is None:
            plt.imshow(self.epsilon_r, origin='lower')
            plt.xlabel('x [Pixels]')
            plt.ylabel('y [Pixels]')
            if figure_title is None:
                plt.title('Relative Permittivity Map')
            else:
                plt.title(figure_title)
            cbar = plt.colorbar()
            cbar.set_label(r'$\epsilon_r$')

        elif self.epsilon_r is None and self.sigma is not None:
            plt.imshow(self.sigma, origin='lower')
            plt.xlabel('x [Pixels]')
            plt.ylabel('y [Pixels]')
            if figure_title is None:
                plt.title('Conductivity Map')
            else:
                plt.title(figure_title)
            cbar = plt.colorbar()
            cbar.set_label(r'$\sigma$ [S/m]')

        elif self.epsilon_r is not None and self.sigma is not None:
            fig = plt.figure(figsize=(10, 4))
            fig.subplots_adjust(left=.125,
                                bottom=.1,
                                right=.9,
                                top=.9,
                                wspace=.5,
                                hspace=.2)
            if type(figure_title) is str:
                fig.suptitle(figure_title, fontsize=16)
            elif figure_title is None:
                fig.suptitle(self.name, fontsize=16)
            ax = fig.add_subplot(1, 2, 1)
            im1 = ax.imshow(self.epsilon_r, origin='lower')
            ax.set_xlabel('x [Pixels]')
            ax.set_ylabel('y [Pixels]')
            cbar = fig.colorbar(im1, fraction=0.046, pad=0.04)
            cbar.set_label(r'$\epsilon_r$')
            ax.set_title('Relative Permittivity')
            ax = fig.add_subplot(1, 2, 2)
            im2 = ax.imshow(self.sigma, origin='lower')
            ax.set_xlabel('x [Pixels]')
            ax.set_ylabel('y [Pixels]')
            cbar = fig.colorbar(im2, fraction=0.046, pad=0.04)
            cbar.set_label(r'$\sigma$')
            ax.set_title('Conductivity')

        else:
            raise error.MissingInputError(
                'InputData.draw()',
                'relative_permittivity or ' + 'conductivity')

        if self.epsilon_r is not None or self.sigma is not None:
            if show:
                plt.show()
            else:
                plt.savefig(file_path + self.name + '.' + file_format,
                            format=file_format)
                plt.close()