Esempio n. 1
0
    def estimate_parameters(self, signal, x1, x2, only_current=False):
        """Estimate the parameters by the two area method

        Parameters
        ----------
        signal : Signal1D instance
        x1 : float
            Defines the left limit of the spectral range to use for the
            estimation.
        x2 : float
            Defines the right limit of the spectral range to use for the
            estimation.
        only_current : bool
            If False estimates the parameters for the full dataset.

        Returns
        -------
        bool
        """
        super(Polynomial, self)._estimate_parameters(signal)
        axis = signal.axes_manager.signal_axes[0]
        i1, i2 = axis.value_range_to_indices(x1, x2)
        if only_current is True:
            estimation = np.polyfit(axis.axis[i1:i2],
                                    signal()[i1:i2],
                                    self.get_polynomial_order())
            if is_binned(signal) is True:
                # in v2 replace by
                #if axis.is_binned:
                self.coefficients.value = estimation / axis.scale
            else:
                self.coefficients.value = estimation
            return True
        else:
            if self.coefficients.map is None:
                self._create_arrays()
            nav_shape = signal.axes_manager._navigation_shape_in_array
            with signal.unfolded():
                dc = signal.data
                # For polyfit the spectrum goes in the first axis
                if axis.index_in_array > 0:
                    dc = dc.T  # Unfolded, so simply transpose
                cmaps = np.polyfit(axis.axis[i1:i2], dc[i1:i2, ...],
                                   self.get_polynomial_order())
                if axis.index_in_array > 0:
                    cmaps = cmaps.T  # Transpose back if needed
                # Shape needed to fit coefficients.map:
                cmap_shape = nav_shape + (self.get_polynomial_order() + 1, )
                self.coefficients.map['values'][:] = cmaps.reshape(cmap_shape)
                if is_binned(signal) is True:
                    # in v2 replace by
                    #if axis.is_binned:
                    self.coefficients.map["values"] /= axis.scale
                self.coefficients.map['is_set'][:] = True
            self.fetch_stored_values()
            return True
Esempio n. 2
0
    def estimate_parameters(self, signal, x1, x2, only_current=False):
        """Estimate the parameters by the two area method

        Parameters
        ----------
        signal : BaseSignal instance
        x1 : float
            Defines the left limit of the spectral range to use for the
            estimation.
        x2 : float
            Defines the right limit of the spectral range to use for the
            estimation.

        only_current : bool
            If False estimates the parameters for the full dataset.

        Returns
        -------
        bool

        """
        super()._estimate_parameters(signal)
        axis = signal.axes_manager.signal_axes[0]
        i1, i2 = axis.value_range_to_indices(x1, x2)
        if is_binned(signal):
            # in v2 replace by
            #if axis.is_binned:
            # using the mean of the gradient for non-uniform axes is a best
            # guess to the scaling of binned signals for the estimation
            scaling_factor = axis.scale if axis.is_uniform \
                             else np.mean(np.gradient(axis.axis), axis=-1)

        if only_current is True:
            self.offset.value = signal()[i1:i2].mean()
            if is_binned(signal):
                # in v2 replace by
                #if axis.is_binned:
                self.offset.value /= scaling_factor
            return True
        else:
            if self.offset.map is None:
                self._create_arrays()
            dc = signal.data
            gi = [
                slice(None),
            ] * len(dc.shape)
            gi[axis.index_in_array] = slice(i1, i2)
            self.offset.map['values'][:] = dc[tuple(gi)].mean(
                axis.index_in_array)
            if is_binned(signal):
                # in v2 replace by
                #if axis.is_binned:
                self.offset.map['values'] /= scaling_factor
            self.offset.map['is_set'][:] = True
            self.fetch_stored_values()
            return True
Esempio n. 3
0
def _get_scaling_factor(signal, axis, parameter):
    """
    Convenience function to get the scaling factor required to take into
    account binned and/or non-uniform axes.

    Parameters
    ----------
    signal : BaseSignal
    axis : BaseDataAxis
    parameter : float or numpy array
        The axis value at which scaling factor is evaluated (ignored if the axis
        is uniform)

    Returns
    -------
    scaling_factor

    """

    if is_binned(signal):
        # in v2 replace by
        #if axis.is_binned:
        if axis.is_uniform:
            scaling_factor = axis.scale
        else:
            parameter_idx = axis.value2index(parameter)
            scaling_factor = np.gradient(axis.axis)[parameter_idx]
    else:
        scaling_factor = 1

    return scaling_factor
Esempio n. 4
0
    def __call__(self,
                 non_convolved=False,
                 onlyactive=False,
                 component_list=None):
        """Returns the corresponding model for the current coordinates

        Parameters
        ----------
        non_convolved : bool
            If True it will return the deconvolved model
        only_active : bool
            If True, only the active components will be used to build the
            model.
        component_list : list or None
            If None, the sum of all the components is returned. If list, only
            the provided components are returned

        cursor: 1 or 2

        Returns
        -------
        numpy array
        """

        if component_list is None:
            component_list = self
        if not isinstance(component_list, (list, tuple)):
            raise ValueError(
                "'Component_list' parameter need to be a list or None")

        if onlyactive:
            component_list = [
                component for component in component_list if component.active
            ]

        if self.convolved is False or non_convolved is True:
            axis = self.axis.axis[self.channel_switches]
            sum_ = np.zeros(len(axis))
            for component in component_list:
                sum_ += component.function(axis)
            to_return = sum_

        else:  # convolved
            sum_convolved = np.zeros(len(self.convolution_axis))
            sum_ = np.zeros(len(self.axis.axis))
            for component in component_list:
                if component.convolved:
                    sum_convolved += component.function(self.convolution_axis)
                else:
                    sum_ += component.function(self.axis.axis)

            to_return = sum_ + np.convolve(
                self.low_loss(self.axes_manager), sum_convolved, mode="valid")
            to_return = to_return[self.channel_switches]
        if is_binned(self.signal) is True:
            # in v2 replace by
            #if self.signal.axes_manager[-1].is_binned is True:
            to_return *= self.signal.axes_manager[-1].scale
        return to_return
Esempio n. 5
0
 def _function(self, x, xscale, yscale, shift):
     if self.interpolate is True:
         result = yscale * self.f(x * xscale - shift)
     else:
         result = yscale * self.signal.data
     if is_binned(self.signal) is True:
     # in v2 replace by
     #if self.signal.axes_manager.signal_axes[0].is_binned is True:
         return result / self.signal.axes_manager.signal_axes[0].scale
     else:
         return result
Esempio n. 6
0
    def estimate_parameters(self, signal, x1, x2, only_current=False):
        """Estimate the Donach by calculating the median (centre) and the
        variance parameter (sigma).

        Note that an insufficient range will affect the accuracy of this
        method and that this method doesn't estimate the asymmetry parameter
        (alpha).

        Parameters
        ----------
        signal : Signal1D instance
        x1 : float
            Defines the left limit of the spectral range to use for the
            estimation.
        x2 : float
            Defines the right limit of the spectral range to use for the
            estimation.

        only_current : bool
            If False estimates the parameters for the full dataset.

        Returns
        -------
        bool
            Returns True when the parameters estimation is successful

        Examples
        --------

        >>> g = hs.model.components1D.Lorentzian()
        >>> x = np.arange(-10, 10, 0.01)
        >>> data = np.zeros((32, 32, 2000))
        >>> data[:] = g.function(x).reshape((1, 1, 2000))
        >>> s = hs.signals.Signal1D(data)
        >>> s.axes_manager[-1].offset = -10
        >>> s.axes_manager[-1].scale = 0.01
        >>> g.estimate_parameters(s, -10, 10, False)
        """

        super()._estimate_parameters(signal)
        axis = signal.axes_manager.signal_axes[0]
        centre, height, sigma = _estimate_gaussian_parameters(
            signal, x1, x2, only_current)
        scaling_factor = _get_scaling_factor(signal, axis, centre)

        if only_current is True:
            self.centre.value = centre
            self.sigma.value = sigma
            self.A.value = height * 1.3
            if is_binned(signal):
                # in v2 replace by
                #if axis.is_binned:
                self.A.value /= scaling_factor
            return True
        else:
            if self.A.map is None:
                self._create_arrays()
            self.A.map['values'][:] = height * 1.3
            if is_binned(signal):
                # in v2 replace by
                #if axis.is_binned:
                self.A.map['values'][:] /= scaling_factor
            self.A.map['is_set'][:] = True
            self.sigma.map['values'][:] = sigma
            self.sigma.map['is_set'][:] = True
            self.centre.map['values'][:] = centre
            self.centre.map['is_set'][:] = True
            self.fetch_stored_values()
            return True
Esempio n. 7
0
    def estimate_parameters(self, signal, x1, x2, only_current=False):
        """Estimate the Lorentzian by calculating the median (centre) and half
        the interquartile range (gamma).

        Note that an insufficient range will affect the accuracy of this
        method.

        Parameters
        ----------
        signal : Signal1D instance
        x1 : float
            Defines the left limit of the spectral range to use for the
            estimation.
        x2 : float
            Defines the right limit of the spectral range to use for the
            estimation.

        only_current : bool
            If False estimates the parameters for the full dataset.

        Returns
        -------
        bool

        Notes
        -----
        Adapted from gaussian.py and
        https://en.wikipedia.org/wiki/Cauchy_distribution

        Examples
        --------

        >>> g = hs.model.components1D.Lorentzian()
        >>> x = np.arange(-10, 10, 0.01)
        >>> data = np.zeros((32, 32, 2000))
        >>> data[:] = g.function(x).reshape((1, 1, 2000))
        >>> s = hs.signals.Signal1D(data)
        >>> s.axes_manager[-1].offset = -10
        >>> s.axes_manager[-1].scale = 0.01
        >>> g.estimate_parameters(s, -10, 10, False)
        """

        super()._estimate_parameters(signal)
        axis = signal.axes_manager.signal_axes[0]
        centre, height, gamma = _estimate_lorentzian_parameters(signal, x1, x2,
                                                              only_current)
        scaling_factor = _get_scaling_factor(signal, axis, centre)

        if only_current is True:
            self.centre.value = centre
            self.gamma.value = gamma
            self.A.value = height * gamma * np.pi
            if is_binned(signal):
            # in v2 replace by
            #if axis.is_binned:
                self.A.value /= scaling_factor
            return True
        else:
            if self.A.map is None:
                self._create_arrays()
            self.A.map['values'][:] = height * gamma * np.pi
            if is_binned(signal):
            # in v2 replace by
            #if axis.is_binned:
                self.A.map['values'] /= scaling_factor
            self.A.map['is_set'][:] = True
            self.gamma.map['values'][:] = gamma
            self.gamma.map['is_set'][:] = True
            self.centre.map['values'][:] = centre
            self.centre.map['is_set'][:] = True
            self.fetch_stored_values()
            return True
Esempio n. 8
0
    def estimate_parameters(self, signal, x1, x2, only_current=False):
        """Estimate the gaussian by calculating the momenta.

        Parameters
        ----------
        signal : Signal1D instance
        x1 : float
            Defines the left limit of the spectral range to use for the
            estimation.
        x2 : float
            Defines the right limit of the spectral range to use for the
            estimation.
        only_current : bool
            If False estimates the parameters for the full dataset.

        Returns
        -------
        bool

        Notes
        -----
        Adapted from http://www.scipy.org/Cookbook/FittingData

        Examples
        --------

        >>> g = hs.model.components1D.GaussianHF()
        >>> x = np.arange(-10, 10, 0.01)
        >>> data = np.zeros((32, 32, 2000))
        >>> data[:] = g.function(x).reshape((1, 1, 2000))
        >>> s = hs.signals.Signal1D(data)
        >>> s.axes_manager[-1].offset = -10
        >>> s.axes_manager[-1].scale = 0.01
        >>> g.estimate_parameters(s, -10, 10, False)
        """

        super()._estimate_parameters(signal)
        axis = signal.axes_manager.signal_axes[0]
        centre, height, sigma = _estimate_gaussian_parameters(
            signal, x1, x2, only_current)
        scaling_factor = _get_scaling_factor(signal, axis, centre)

        if only_current is True:
            self.centre.value = centre
            self.fwhm.value = sigma * sigma2fwhm
            self.height.value = float(height)
            if is_binned(signal):
                # in v2 replace by
                #if axis.is_binned:
                self.height.value /= scaling_factor
            return True
        else:
            if self.height.map is None:
                self._create_arrays()
            self.height.map['values'][:] = height
            if is_binned(signal):
                # in v2 replace by
                #if axis.is_binned:
                self.height.map['values'][:] /= scaling_factor
            self.height.map['is_set'][:] = True
            self.fwhm.map['values'][:] = sigma * sigma2fwhm
            self.fwhm.map['is_set'][:] = True
            self.centre.map['values'][:] = centre
            self.centre.map['is_set'][:] = True
            self.fetch_stored_values()
            return True
Esempio n. 9
0
    def _jacobian(self, param, y, weights=None):
        if weights is None:
            weights = 1.

        if self.convolved is True:
            counter = 0
            grad = np.zeros(len(self.axis.axis))
            for component in self:  # Cut the parameters list
                if component.active:
                    component.fetch_values_from_array(
                        param[counter:counter + component._nfree_param],
                        onlyfree=True)

                    if component.convolved:
                        for parameter in component.free_parameters:
                            par_grad = np.convolve(
                                parameter.grad(self.convolution_axis),
                                self.low_loss(self.axes_manager),
                                mode="valid")

                            if parameter._twins:
                                for par in parameter._twins:
                                    np.add(
                                        par_grad,
                                        np.convolve(
                                            par.grad(self.convolution_axis),
                                            self.low_loss(self.axes_manager),
                                            mode="valid"), par_grad)

                            grad = np.vstack((grad, par_grad))

                    else:
                        for parameter in component.free_parameters:
                            par_grad = parameter.grad(self.axis.axis)

                            if parameter._twins:
                                for par in parameter._twins:
                                    np.add(par_grad, par.grad(self.axis.axis),
                                           par_grad)

                            grad = np.vstack((grad, par_grad))

                    counter += component._nfree_param

            to_return = grad[1:, self.channel_switches] * weights

        else:
            axis = self.axis.axis[self.channel_switches]
            counter = 0
            grad = axis
            for component in self:  # Cut the parameters list
                if component.active:
                    component.fetch_values_from_array(
                        param[counter:counter + component._nfree_param],
                        onlyfree=True)

                    for parameter in component.free_parameters:
                        par_grad = parameter.grad(axis)
                        if parameter._twins:
                            for par in parameter._twins:
                                np.add(par_grad, par.grad(axis), par_grad)

                        grad = np.vstack((grad, par_grad))

                    counter += component._nfree_param

            to_return = grad[1:, :] * weights

        if is_binned(self.signal) is True:
            # in v2 replace by
            #if self.signal.axes_manager[-1].is_binned is True:
            to_return *= self.signal.axes_manager[-1].scale

        return to_return
Esempio n. 10
0
    def estimate_parameters(self, signal, E1, E2, only_current=False):
        """Estimate the Voigt function by calculating the momenta of the
        Gaussian.

        Parameters
        ----------
        signal : Signal1D instance
        x1 : float
            Defines the left limit of the spectral range to use for the
            estimation.
        x2 : float
            Defines the right limit of the spectral range to use for the
            estimation.

        only_current : bool
            If False estimates the parameters for the full dataset.

        Returns
        -------
         : bool
            Exit status required for the :meth:`remove_background` function.

        Notes
        -----
        Adapted from http://www.scipy.org/Cookbook/FittingData

        Examples
        --------

        >>> g = hs.model.components1D.PESVoigt()
        >>> x = np.arange(-10, 10, 0.01)
        >>> data = np.zeros((32, 32, 2000))
        >>> data[:] = g.function(x).reshape((1, 1, 2000))
        >>> s = hs.signals.Signal1D(data)
        >>> s.axes_manager[-1].offset = -10
        >>> s.axes_manager[-1].scale = 0.01
        >>> g.estimate_parameters(s, -10, 10, False)

        """
        super(PESVoigt, self)._estimate_parameters(signal)
        axis = signal.axes_manager.signal_axes[0]
        centre, height, sigma = _estimate_gaussian_parameters(
            signal, E1, E2, only_current)

        if only_current is True:
            self.centre.value = centre
            self.FWHM.value = sigma * sigma2fwhm
            self.area.value = height * sigma * sqrt2pi
            if is_binned(signal) is True:
                # in v2 replace by
                #if axis.is_binned:
                self.area.value /= axis.scale
            return True
        else:
            if self.area.map is None:
                self._create_arrays()
            self.area.map['values'][:] = height * sigma * sqrt2pi
            if is_binned(signal) is True:
                # in v2 replace by
                #if axis.is_binned:
                self.area.map['values'][:] /= axis.scale
            self.area.map['is_set'][:] = True
            self.FWHM.map['values'][:] = sigma * sigma2fwhm
            self.FWHM.map['is_set'][:] = True
            self.centre.map['values'][:] = centre
            self.centre.map['is_set'][:] = True
            self.fetch_stored_values()
            return True
Esempio n. 11
0
    def estimate_parameters(self, signal, x1, x2, only_current=False):
        """Estimate the parameters by the two area method

        Parameters
        ----------
        signal : Signal1D instance
        x1 : float
            Defines the left limit of the spectral range to use for the
            estimation.
        x2 : float
            Defines the right limit of the spectral range to use for the
            estimation.

        only_current : bool
            If False estimates the parameters for the full dataset.

        Returns
        -------
        bool

        """
        super()._estimate_parameters(signal)
        axis = signal.axes_manager.signal_axes[0]
        i1, i2 = axis.value_range_to_indices(x1, x2)

        if is_binned(signal):
            # in v2 replace by
            #if axis.is_binned:
            # using the mean of the gradient for non-uniform axes is a best
            # guess to the scaling of binned signals for the estimation
            scaling_factor = axis.scale if axis.is_uniform \
                             else np.mean(np.gradient(axis.axis), axis=-1)

        if only_current is True:
            estimation = np.polyfit(axis.axis[i1:i2],
                                    signal()[i1:i2],
                                    self.get_polynomial_order())
            if is_binned(signal):
                # in v2 replace by
                #if axis.is_binned:
                for para, estim in zip(self.parameters[::-1], estimation):
                    para.value = estim / scaling_factor
            else:
                for para, estim in zip(self.parameters[::-1], estimation):
                    para.value = estim
            return True
        else:
            if self.parameters[0].map is None:
                self._create_arrays()

            nav_shape = signal.axes_manager._navigation_shape_in_array
            with signal.unfolded():
                data = signal.data
                # For polyfit the spectrum goes in the first axis
                if axis.index_in_array > 0:
                    data = data.T  # Unfolded, so simply transpose
                fit = np.polyfit(axis.axis[i1:i2], data[i1:i2, ...],
                                 self.get_polynomial_order())
                if axis.index_in_array > 0:
                    fit = fit.T  # Transpose back if needed
                # Shape needed to fit parameter.map:
                cmap_shape = nav_shape + (self.get_polynomial_order() + 1, )
                fit = fit.reshape(cmap_shape)

                if is_binned(signal):
                    # in v2 replace by
                    #if axis.is_binned:
                    for i, para in enumerate(self.parameters[::-1]):
                        para.map['values'][:] = fit[..., i] / scaling_factor
                        para.map['is_set'][:] = True
                else:
                    for i, para in enumerate(self.parameters[::-1]):
                        para.map['values'][:] = fit[..., i]
                        para.map['is_set'][:] = True
            self.fetch_stored_values()
            return True
Esempio n. 12
0
def test_is_binned():
    s = signals.Signal1D(np.zeros((5, 5)))
    assert is_binned(s) == s.axes_manager[-1].is_binned
    with pytest.warns(VisibleDeprecationWarning, match="Use of the `binned`"):
        s.metadata.set_item("Signal.binned", True)
    assert is_binned(s) == s.metadata.Signal.binned
Esempio n. 13
0
    def estimate_parameters(self, signal, x1, x2, only_current=False):
        """Estimate the parameters for the exponential component by splitting
        the signal window into two regions and using their geometric means

        Parameters
        ----------
        signal : BaseSignal instance
        x1 : float
            Defines the left limit of the spectral range to use for the
            estimation.
        x2 : float
            Defines the right limit of the spectral range to use for the
            estimation.

        only_current : bool
            If False estimates the parameters for the full dataset.

        Returns
        -------
        bool

        """
        super()._estimate_parameters(signal)
        axis = signal.axes_manager.signal_axes[0]
        i1, i2 = axis.value_range_to_indices(x1, x2)
        if i1 + 1 == i2:
            if i2 < axis.high_index:
                i2 += 1
            elif i1 > axis.low_index:
                i1 -= 1
        i_mid = (i1 + i2) // 2
        x_start = axis.index2value(i1)
        x_mid = axis.index2value(i_mid)
        x_end = axis.index2value(i2)

        if only_current is True:
            s = signal.get_current_signal()
        else:
            s = signal

        if s._lazy:
            import dask.array as da
            exp = da.exp
            log = da.log
        else:
            exp = np.exp
            log = np.log

        with np.errstate(divide='raise', invalid='raise'):
            try:
                # use log and exp to compute geometric mean to avoid overflow
                a1 = s.isig[i1:i_mid].data
                b1 = log(a1)
                a2 = s.isig[i_mid:i2].data
                b2 = log(a2)
                geo_mean1 = exp(b1.mean(axis=-1))
                geo_mean2 = exp(b2.mean(axis=-1))
                x1 = (x_start + x_mid) / 2
                x2 = (x_mid + x_end) / 2

                A = exp((log(geo_mean1) - (x1 / x2) * log(geo_mean2)) /
                        (1 - x1 / x2))
                t = -x2 / (log(geo_mean2) - log(A))

                if s._lazy:
                    A = A.map_blocks(np.nan_to_num)
                    t = t.map_blocks(np.nan_to_num)
                else:
                    A = np.nan_to_num(A)
                    t = np.nan_to_num(t)

            except (FloatingPointError):
                if i1 == i2:
                    _logger.warning('Exponential parameters estimation failed '
                                    'because signal range includes only one '
                                    'point.')
                else:
                    _logger.warning(
                        'Exponential parameters estimation failed '
                        'with a "divide by zero" error (likely log of '
                        'a zero or negative value).')
                return False
            if is_binned(signal):
                # in v2 replace by
                #if axis.is_binned:
                if axis.is_uniform:
                    A /= axis.scale
                else:
                    # using the mean of the gradient for non-uniform axes is a best
                    # guess to the scaling of binned signals for the estimation
                    A /= np.mean(np.gradient(axis.axis))
            if only_current is True:
                self.A.value = A
                self.tau.value = t
                return True

            if self.A.map is None:
                self._create_arrays()
            self.A.map['values'][:] = A
            self.A.map['is_set'][:] = True
            self.tau.map['values'][:] = t
            self.tau.map['is_set'][:] = True
            self.fetch_stored_values()

            return True
Esempio n. 14
0
    def estimate_parameters(self, signal, x1, x2, only_current=False):
        """Estimate the skew normal distribution by calculating the momenta.

        Parameters
        ----------
        signal : Signal1D instance
        x1 : float
            Defines the left limit of the spectral range to use for the
            estimation.
        x2 : float
            Defines the right limit of the spectral range to use for the
            estimation.

        only_current : bool
            If False estimates the parameters for the full dataset.

        Returns
        -------
        bool

        Notes
        -----
        Adapted from Lin, Lee and Yen, Statistica Sinica 17, 909-927 (2007)
        https://www.jstor.org/stable/24307705

        Examples
        --------

        >>> g = hs.model.components1D.SkewNormal()
        >>> x = np.arange(-10, 10, 0.01)
        >>> data = np.zeros((32, 32, 2000))
        >>> data[:] = g.function(x).reshape((1, 1, 2000))
        >>> s = hs.signals.Signal1D(data)
        >>> s.axes_manager._axes[-1].offset = -10
        >>> s.axes_manager._axes[-1].scale = 0.01
        >>> g.estimate_parameters(s, -10, 10, False)
        """

        super(SkewNormal, self)._estimate_parameters(signal)
        axis = signal.axes_manager.signal_axes[0]
        x0, height, scale, shape = _estimate_skewnormal_parameters(
            signal, x1, x2, only_current)
        if only_current is True:
            self.x0.value = x0
            self.A.value = height * sqrt2pi
            self.scale.value = scale
            self.shape.value = shape
            if is_binned(signal) is True:
                # in v2 replace by
                #if axis.is_binned:
                self.A.value /= axis.scale
            return True
        else:
            if self.A.map is None:
                self._create_arrays()
            self.A.map['values'][:] = height * sqrt2pi

            if is_binned(signal) is True:
                # in v2 replace by
                #if axis.is_binned:
                self.A.map['values'] /= axis.scale
            self.A.map['is_set'][:] = True
            self.x0.map['values'][:] = x0
            self.x0.map['is_set'][:] = True
            self.scale.map['values'][:] = scale
            self.scale.map['is_set'][:] = True
            self.shape.map['values'][:] = shape
            self.shape.map['is_set'][:] = True
            self.fetch_stored_values()
            return True