Beispiel #1
0
    def fit(self, model, data):
        """
        fit a model to some data

        Parameters
        ----------
        model : :class:`~holopy.fitting.model.Model` object
            A model describing the scattering system which leads to your
            data and the parameters to vary to fit it to the data
        data : xarray.DataArray
            The data to fit

        Returns
        -------
        result : :class:`FitResult`
            an object containing the best fit parameters and information
            about the fit
        """
        time_start = time.time()
        parameters = model._parameters
        if len(parameters) == 0:
            raise MissingParameter('at least one parameter to fit')

        if self.npixels is not None:
            data = make_subset_data(data, pixels=self.npixels, seed=self.seed)

        guess_prior = model.lnprior(
            {par.name: par.guess
             for par in parameters})

        def residual(par_vals):
            noise = model._find_noise(par_vals, data)
            residuals = model._residuals(par_vals, data, noise).flatten()
            prior = np.sqrt(guess_prior - model.lnprior(par_vals))
            residuals = np.append(residuals, prior)
            return residuals

        fitted_pars, minimizer_info = self.minimize(parameters, residual)

        if minimizer_info.status == 5:
            setattr(minimizer_info, 'converged', False)
            warnings.warn("Minimizer Convergence Failed, your results \
                                may not be correct.")
        else:
            setattr(minimizer_info, 'converged', True)

        # Getting errors:
        errors_rescaled = minimizer_info.perror
        if errors_rescaled is None:
            errors_rescaled = [0] * len(parameters)
        errors = self.unscale_pars_from_minimizer(parameters, errors_rescaled)
        intervals = [
            UncertainValue(fitted_pars[name], errors[name], name=name)
            for name in errors.keys()
        ]
        d_time = time.time() - time_start
        return FitResult(data, model, self, d_time, {
            'intervals': intervals,
            'mpfit_details': minimizer_info
        })
Beispiel #2
0
 def find_parameter(key):
     if key in mapped_optics and mapped_optics[key] is not None:
         val = mapped_optics[key]
     elif hasattr(schema, key) and getattr(schema, key) is not None:
         val = getattr(schema, key)
     else:
         raise MissingParameter(key)
     return val
Beispiel #3
0
 def _find_noise(self, pars, data):
     noise = dict_to_array(
         data, self._get_parameter('noise_sd', pars, data))
     if noise is None:
         if np.all([isinstance(par, Uniform) for par in self._parameters]):
             noise = 1
         else:
             raise MissingParameter('noise_sd for non-uniform priors')
     return noise
Beispiel #4
0
def prep_schema(detector, medium_index, illum_wavelen, illum_polarization):
    detector = update_metadata(
        detector, medium_index, illum_wavelen, illum_polarization)

    if detector.illum_wavelen is None:
        raise MissingParameter("wavelength")
    if detector.medium_index is None:
        raise MissingParameter("medium refractive index")
    if illum_polarization is not False and detector.illum_polarization is None:
        raise MissingParameter("polarization")

    illum_wavelen = ensure_array(detector.illum_wavelen)
    illum_polarization = detector.illum_polarization

    if len(illum_wavelen) > 1 or ensure_array(illum_polarization).ndim == 2:
        #  multiple illuminations to calculate
        if illumination in illum_polarization.dims:
            if isinstance(illum_wavelen, xr.DataArray):
                pass
            else:
                if len(illum_wavelen) == 1:
                    illum_wavelen = illum_wavelen.repeat(
                        len(illum_polarization.illumination))
                illum_wavelen = xr.DataArray(
                    illum_wavelen, dims=illumination,
                    coords={illumination: illum_polarization.illumination})
        else:
            #  need to interpret illumination from detector.illum_wavelen
            if not isinstance(illum_wavelen, xr.DataArray):
                illum_wavelen = xr.DataArray(
                    illum_wavelen, dims=illumination,
                    coords={illumination: illum_wavelen})
            illum_polarization = xr.broadcast(
                illum_polarization, illum_wavelen, exclude=[vector])[0]

        if illumination in detector.dims:
            detector = detector.sel(
                illumination=detector.illumination[0], drop=True)
        detector = update_metadata(
            detector, illum_wavelen=illum_wavelen,
            illum_polarization=illum_polarization)

    return detector
Beispiel #5
0
 def __init__(self, data, model, strategy, time, kwargs={}):
     self.data = data
     self.model = model
     self.strategy = strategy
     if hasattr(strategy, 'parallel') and hasattr(strategy.parallel, 'map'):
         self.strategy.parallel = 'external_pool'
     self.time = time
     self._kwargs_keys = []
     self.add_attr(kwargs)
     needs_intervals = not isinstance(self, SamplingResult)
     if needs_intervals and not hasattr(self, 'intervals'):
         raise MissingParameter('intervals')
Beispiel #6
0
 def _get_parameter(self, name, pars, schema=None):
     interpreted_pars = _interpret_parameters(pars)
     if name in pars.keys():
         return pars[name]
     elif name in interpreted_pars.keys():
         return interpreted_pars[name]
     elif hasattr(self, name):
         return getattr(self, name)
     try:
         return getattr(schema, name)
     except:
         raise MissingParameter(name)
Beispiel #7
0
    def _find_noise(self, pars, schema):
        """
        finds appropriate noise_sd for residuals calculations

        Parameters
        ----------
        pars: list
            values to create noise_sd. Order should match model._parameters
        """
        optics_map = read_map(self._maps['optics'], pars)
        if 'noise_sd' in optics_map and optics_map['noise_sd'] is not None:
            val = optics_map['noise_sd']
        elif hasattr(schema, 'noise_sd'):
            val = schema.noise_sd
        else:
            raise MissingParameter('noise_sd')
        if val is None:
            if np.all([isinstance(par, Uniform) for par in self._parameters]):
                val = 1
            else:
                raise MissingParameter('noise_sd for non-uniform priors')
        return val
Beispiel #8
0
    def calculate_scattered_field(self, scatterer, schema):
        """
        Implemented in derived classes only.

        Parameters
        ----------
        scatterer : :mod:`.scatterer` object
            (possibly composite) scatterer for which to compute scattering

        Returns
        -------
        e_field : :mod:`.VectorGrid`
            scattered electric field
        """
        if scatterer.center is None:
            raise MissingParameter("center")
        is_multicolor_hologram = len(ensure_array(schema.illum_wavelen)) > 1
        field = (self._calculate_multiple_color_scattered_field(
            scatterer, schema) if is_multicolor_hologram else
                 self._calculate_single_color_scattered_field(
                     scatterer, schema))
        return field
Beispiel #9
0
    def fit(self, model, data):
        """
        fit a model to some data

        Parameters
        ----------
        model : :class:`~holopy.fitting.model.Model` object
            A model describing the scattering system which leads to your
            data and the parameters to vary to fit it to the data
        data : xarray.DataArray
            The data to fit

        Returns
        -------
        result : :class:`FitResult`
            Contains the best fit parameters and information about the fit
        """
        # timing decorator...
        time_start = time.time()

        parameters = model._parameters
        if len(parameters) == 0:
            raise MissingParameter('at least one parameter to fit')

        if self.npixels is None:
            data = flat(data)
        else:
            data = make_subset_data(data, pixels=self.npixels)
        guess_lnprior = model.lnprior(
            {par.name:par.guess for par in parameters})

        def residual(rescaled_values):
            unscaled_values = self.unscale_pars_from_minimizer(
                parameters, rescaled_values)
            noise = model._find_noise(unscaled_values, data)
            residuals = model._residuals(unscaled_values, data, noise)
            ln_prior = model.lnprior(unscaled_values) - guess_lnprior
            zscore_prior = np.sqrt(2 * -ln_prior)
            np.append(residuals, zscore_prior)
            return residuals

        # The only work here
        fitted_pars, minimizer_info = self.minimize(parameters, residual)

        if not minimizer_info.success:
            warnings.warn("Minimizer Convergence Failed, your results \
                                may not be correct.")

        unit_errors = self._calculate_unit_noise_errors_from_fit(minimizer_info)
        noise = model._find_noise(fitted_pars, data)
        errors_scaled = noise * unit_errors
        errors = self.unscale_pars_from_minimizer(parameters, errors_scaled)
        intervals = [
            UncertainValue(
                fitted_pars[par.name], errors[par.name], name=par.name)
            for err, par in zip(errors, parameters)]

        # timing decorator...
        d_time = time.time() - time_start
        kwargs = {'intervals': intervals, 'minimizer_info': minimizer_info}
        return FitResult(data, model, self, d_time, kwargs)