def apply(self): self.signal._plot.auto_update_plot = False maxval = self.signal.axes_manager.navigation_size if maxval > 0: pbar = progressbar(maxval=maxval) up_to = None if self.differential_order == 0: f = self.model2plot else: f = self.diff_model2plot if self.crop_diff_axis is True: up_to = -self.differential_order i = 0 for spectrum in self.signal: spectrum.data[:] = f() i += 1 if maxval > 0: pbar.update(i) if maxval > 0: pbar.finish() if self.differential_order > 0: self.signal.axes_manager.signal_axes[0].offset = \ self.smooth_diff_line.axis[0] self.signal.crop(-1, 0, int(-self.differential_order)) self.signal._replot() self.signal._plot.auto_update_plot = True
def richardson_lucy_deconvolution(self, psf, iterations=15, mask=None): """1D Richardson-Lucy Poissonian deconvolution of the spectrum by the given kernel. Parameters ---------- iterations: int Number of iterations of the deconvolution. Note that increasing the value will increase the noise amplification. psf: EELSSpectrum It must have the same signal dimension as the current spectrum and a spatial dimension of 0 or the same as the current spectrum. Notes: ----- For details on the algorithm see Gloter, A., A. Douiri, M. Tence, and C. Colliex. “Improving Energy Resolution of EELS Spectra: An Alternative to the Monochromator Solution.” Ultramicroscopy 96, no. 3–4 (September 2003): 385–400. """ self._check_signal_dimension_equals_one() ds = self.deepcopy() ds.data = ds.data.copy() ds.mapped_parameters.title += ( ' after Richardson-Lucy deconvolution %i iterations' % iterations) if ds.tmp_parameters.has_item('filename'): ds.tmp_parameters.filename += ( '_after_R-L_deconvolution_%iiter' % iterations) psf_size = psf.axes_manager.signal_axes[0].size kernel = psf() imax = kernel.argmax() j = 0 maxval = self.axes_manager.navigation_size if maxval > 0: pbar = progressbar(maxval=maxval) for D in self: D = D.data.copy() if psf.axes_manager.navigation_dimension != 0: kernel = psf(axes_manager=self.axes_manager) imax = kernel.argmax() s = ds(axes_manager=self.axes_manager) mimax = psf_size -1 - imax O = D.copy() for i in xrange(iterations): first = np.convolve(kernel, O)[imax: imax + psf_size] O = O * (np.convolve(kernel[::-1], D / first)[mimax: mimax + psf_size]) s[:] = O j += 1 if maxval > 0: pbar.update(j) if maxval > 0: pbar.finish() return ds
def apply(self): self.signal._plot.auto_update_plot = False maxval = self.signal.axes_manager.navigation_size if maxval > 0: pbar = progressbar( maxval=maxval) up_to = None if self.differential_order == 0: f = self.model2plot else: f = self.diff_model2plot if self.crop_diff_axis is True: up_to = -self.differential_order i = 0 for spectrum in self.signal: spectrum.data[:] = f() i += 1 if maxval > 0: pbar.update(i) if maxval > 0: pbar.finish() if self.differential_order > 0: self.signal.axes_manager.signal_axes[0].offset = \ self.smooth_diff_line.axis[0] self.signal.crop(-1, 0, int(-self.differential_order)) self.signal._replot() self.signal._plot.auto_update_plot = True
def apply(self): self.signal._plot.auto_update_plot = False pbar = progressbar( maxval = (np.cumprod(self.signal.axes_manager.navigation_shape)[-1])) up_to = None if self.differential_order == 0: f = self.model2plot else: f = self.diff_model2plot if self.crop_diff_axis is True: up_to = -self.differential_order i = 0 for index in np.ndindex( tuple(self.signal.axes_manager.navigation_shape)): self.signal.axes_manager.set_not_slicing_indexes(index) self.signal.data[ self.signal.axes_manager._getitem_tuple][:up_to]\ = f() i += 1 pbar.update(i) pbar.finish() if self.differential_order > 0: self.signal.axes_manager._slicing_axes[0].offset = \ self.smooth_diff_line.axis[0] self.signal.crop_in_pixels(-1,0,-self.differential_order) self.signal._replot() self.signal._plot.auto_update_plot = True
def richardson_lucy_deconvolution(self, iterations=15, to_dec='self.hl', kernel='self.psf', mask=None): """ Performs 1D Richardson-Lucy Poissonian deconvolution of the to_dec by the psf. The deconvolved spim will be stored in the to_dec as a new cube. Parameters: ----------- iterations: Number of iterations of the deconvolution. Note that increasing the value will increase the noise amplification. to_dec: a spectrum object. psf: a 1D spectrum object containing the Point Spread Function """ if to_dec == 'self.hl': to_dec = self.hl if kernel == 'self.psf': kernel = self.psf if check_cube_dimensions(to_dec, kernel, warn=False): kernel_data = kernel.data_cube elif check_energy_dimensions(to_dec, kernel, warn=False): shape = to_dec.data_cube.shape kernel_data = np.zeros(shape).swapaxes(0, 2) kernel_data[...] = kernel.data_cube[:, 0, 0] kernel_data = kernel_data.swapaxes(0, 2) else: print """ The kernel must have either the same dimensions as the to_dec or be an unidimensional spectrum with the same number of channels""" sys.exit() to_dec_data = copy.copy(to_dec.data_cube) length = kernel_data.shape[0] print "\nPerfoming Richardson-Lucy iterative deconvolution" dcshape = to_dec.data_cube.shape pbar = progressbar(maxval=(dcshape[1] * dcshape[2])) index = 0 for ix in xrange(to_dec.data_cube.shape[1]): for iy in xrange(to_dec.data_cube.shape[2]): if mask is None or mask[ix, iy]: # print "\n(%s, %s)" % (ix, iy) kernel_ = kernel_data[:, ix, iy] imax = kernel_.argmax() mimax = length - 1 - imax D = to_dec.data_cube[:, ix, iy] O = copy.copy(D) for i in xrange(iterations): first = np.convolve(kernel_, O)[imax:imax + length] O = O * (np.convolve(kernel_[::-1], D / first)[mimax:mimax + length]) to_dec_data[:, ix, iy] = O index += 1 pbar.update(index) pbar.finish() to_dec._Spectrum__new_cube( to_dec_data, 'poissonian R-L deconvolution %i iterations' % iterations)
def richardson_lucy_deconvolution(self, psf, iterations=15, mask=None): """1D Richardson-Lucy Poissonian deconvolution of the spectrum by the given kernel. Parameters ---------- iterations: int Number of iterations of the deconvolution. Note that increasing the value will increase the noise amplification. psf: EELSSpectrum It must have the same signal dimension as the current spectrum and a spatial dimension of 0 or the same as the current spectrum. Notes: ----- For details on the algorithm see Gloter, A., A. Douiri, M. Tence, and C. Colliex. “Improving Energy Resolution of EELS Spectra: An Alternative to the Monochromator Solution.” Ultramicroscopy 96, no. 3–4 (September 2003): 385–400. """ self._check_signal_dimension_equals_one() ds = self.deepcopy() ds.data = ds.data.copy() ds.metadata.General.title += ( ' after Richardson-Lucy deconvolution %i iterations' % iterations) if ds.tmp_parameters.has_item('filename'): ds.tmp_parameters.filename += ('_after_R-L_deconvolution_%iiter' % iterations) psf_size = psf.axes_manager.signal_axes[0].size kernel = psf() imax = kernel.argmax() j = 0 maxval = self.axes_manager.navigation_size if maxval > 0: pbar = progressbar(maxval=maxval) for D in self: D = D.data.copy() if psf.axes_manager.navigation_dimension != 0: kernel = psf(axes_manager=self.axes_manager) imax = kernel.argmax() s = ds(axes_manager=self.axes_manager) mimax = psf_size - 1 - imax O = D.copy() for i in xrange(iterations): first = np.convolve(kernel, O)[imax:imax + psf_size] O = O * (np.convolve(kernel[::-1], D / first)[mimax:mimax + psf_size]) s[:] = O j += 1 if maxval > 0: pbar.update(j) if maxval > 0: pbar.finish() return ds
def multifit(self, mask = None, fitter = None, charge_only_fixed = False, grad = False, autosave = False, autosave_every = 10, bounded = False, **kwargs): if fitter is None: fitter = preferences.Model.default_fitter print('Fitter: %s' % fitter) if autosave is not False: fd, autosave_fn = tempfile.mkstemp(prefix = 'hyperspy_autosave-', dir = '.', suffix = '.npz') os.close(fd) autosave_fn = autosave_fn[:-4] messages.information( "Autosaving each %s pixels to %s.npz" % (autosave_every, autosave_fn)) messages.information( "When multifit finishes its job the file will be deleted") if mask is not None and \ (mask.shape != tuple(self.axes_manager.navigation_shape)): messages.warning_exit( "The mask must be an array with the same espatial dimensions as the" "navigation shape, %s" % self.axes_manager.navigation_shape) masked_elements = 0 if mask is None else mask.sum() pbar = progressbar.progressbar( maxval = (np.cumprod(self.axes_manager.navigation_shape)[-1] - masked_elements)) if bounded is True: if fitter == 'mpfit': self.set_mpfit_parameters_info() bounded = None elif fitter in ("tnc", "l_bfgs_b"): self.set_boundaries() bounded = None else: messages.information( "The chosen fitter does not suppport bounding." "If you require boundinig please select one of the following" "fitters instead: mpfit, tnc, l_bfgs_b") bounded = False i = 0 for index in np.ndindex(tuple(self.axes_manager.navigation_shape)): if mask is None or not mask[index]: self.axes_manager.set_not_slicing_indexes(index) self.charge(only_fixed = charge_only_fixed) self.fit(fitter = fitter, grad = grad, bounded = bounded, **kwargs) i += 1 pbar.update(i) if autosave is True and i % autosave_every == 0: self.save_parameters2file(autosave_fn) pbar.finish() if autosave is True: messages.information( 'Deleting the temporary file %s pixels' % (autosave_fn + 'npz')) os.remove(autosave_fn + '.npz')
def chrono_align_and_sum(spectrum, energy_range=(None, None), spatial_shape=None): """Alignment and sum of a chrono-spim SI Parameters ---------- spectrum : Spectrum instance Chrono-spim energy_range : tuple of floats energy interval in which to perform the alignment in energy units axis : int """ from spectrum import Spectrum dc = spectrum.data_cube min_energy_size = dc.shape[0] # i = 0 new_dc = None # For the progress bar to work properly we must capture the output of the # functions that are called during the alignment process import cStringIO import sys capture_output = cStringIO.StringIO() from hyperspy.misc.progressbar import progressbar pbar = progressbar(maxval=dc.shape[2] - 1) for i in xrange(dc.shape[2]): pbar.update(i) sys.stdout = capture_output s = Spectrum({'calibration': {'data_cube': dc[:, :, i]}}) s.get_calibration_from(spectrum) s.find_low_loss_origin() s.align(energy_range, progress_bar=False) min_energy_size = min(s.data_cube.shape[0], min_energy_size) if new_dc is None: new_dc = s.data_cube.sum(1) else: new_dc = np.concatenate([ new_dc[:min_energy_size], s.data_cube.sum(1)[:min_energy_size] ], 1) sys.stdout = sys.__stdout__ pbar.finish() spectrum.data_cube = new_dc spectrum.get_dimensions_from_cube() spectrum.find_low_loss_origin() spectrum.align(energy_range) spectrum.find_low_loss_origin() if spatial_shape is not None: spectrum.data_cube = spectrum.data_cube.reshape( [spectrum.data_cube.shape[0]] + list(spatial_shape)) spectrum.data_cube = spectrum.data_cube.swapaxes(1, 2) spectrum.get_dimensions_from_cube()
def chrono_align_and_sum(spectrum, energy_range = (None, None), spatial_shape = None): """Alignment and sum of a chrono-spim SI Parameters ---------- spectrum : Spectrum instance Chrono-spim energy_range : tuple of floats energy interval in which to perform the alignment in energy units axis : int """ from spectrum import Spectrum dc = spectrum.data_cube min_energy_size = dc.shape[0] # i = 0 new_dc = None # For the progress bar to work properly we must capture the output of the # functions that are called during the alignment process import cStringIO import sys capture_output = cStringIO.StringIO() from hyperspy.misc.progressbar import progressbar pbar = progressbar(maxval = dc.shape[2] - 1) for i in xrange(dc.shape[2]): pbar.update(i) sys.stdout = capture_output s = Spectrum({'calibration': {'data_cube' : dc[:,:,i]}}) s.get_calibration_from(spectrum) s.find_low_loss_origin() s.align(energy_range, progress_bar = False) min_energy_size = min(s.data_cube.shape[0], min_energy_size) if new_dc is None: new_dc = s.data_cube.sum(1) else: new_dc = np.concatenate([new_dc[:min_energy_size], s.data_cube.sum(1)[:min_energy_size]], 1) sys.stdout = sys.__stdout__ pbar.finish() spectrum.data_cube = new_dc spectrum.get_dimensions_from_cube() spectrum.find_low_loss_origin() spectrum.align(energy_range) spectrum.find_low_loss_origin() if spatial_shape is not None: spectrum.data_cube = spectrum.data_cube.reshape( [spectrum.data_cube.shape[0]] + list(spatial_shape)) spectrum.data_cube = spectrum.data_cube.swapaxes(1,2) spectrum.get_dimensions_from_cube()
def align_with_array_1D(self, shift_array, axis=-1, interpolation_method='linear'): """Shift each one dimensional object by the amount specify by a given array Parameters ---------- shift_map : numpy array The shift is specify in the units of the selected axis interpolation_method : str or int Specifies the kind of interpolation as a string ('linear', 'nearest', 'zero', 'slinear', 'quadratic, 'cubic') or as an integer specifying the order of the spline interpolator to use. """ axis = self.axes_manager._get_positive_index(axis) coord = self.axes_manager.axes[axis] offset = coord.offset _axis = coord.axis.copy() maxval = np.cumprod(shift_array.shape)[-1] - 1 pbar = progressbar.progressbar(maxval = maxval) i = 0 for dat, shift in zip(self.iterate_axis(axis), utils.iterate_axis(shift_array, axis)): si = sp.interpolate.interp1d(_axis ,dat, bounds_error=False, fill_value=0., kind=interpolation_method) coord.offset = offset - shift[0] dat[:] = si(coord.axis) pbar.update(i) i += 1 coord.offset = offset # Cropping time mini, maxi = shift_array.min(), shift_array.max() if mini < 0: self.crop_in_units(axis, None, coord.axis[-1] + mini + coord.scale) if maxi > 0: self.crop_in_units(axis, offset + maxi)
def generate_data_from_model(self, out_of_range_to_nan = True): """Generate a SI with the current model The SI is stored in self.model_cube """ pbar = progressbar.progressbar( maxval = (np.cumprod(self.axes_manager.navigation_shape)[-1])) i = 0 for index in np.ndindex(tuple(self.axes_manager.navigation_shape)): self.axes_manager.set_not_slicing_indexes(index) self.charge(only_fixed = False) self.model_cube[self.axes_manager._getitem_tuple][ self.channel_switches] = self.__call__( non_convolved = not self.convolved, onlyactive = True) if out_of_range_to_nan is True: self.model_cube[self.axes_manager._getitem_tuple][ self.channel_switches == False] = np.nan i += 1 pbar.update(i)
def align_with_array_1D(self, shift_array, axis=-1, interpolation_method='linear'): """Shift each one dimensional object by the amount specify by a given array Parameters ---------- shift_map : numpy array The shift is specify in the units of the selected axis interpolation_method : str or int Specifies the kind of interpolation as a string ('linear', 'nearest', 'zero', 'slinear', 'quadratic, 'cubic') or as an integer specifying the order of the spline interpolator to use. """ axis = self._get_positive_axis_index_index(axis) coord = self.axes_manager.axes[axis] offset = coord.offset _axis = coord.axis.copy() maxval = np.cumprod(shift_array.shape)[-1] - 1 pbar = progressbar.progressbar(maxval=maxval) i = 0 for dat, shift in zip(self.iterate_axis(axis), utils.iterate_axis(shift_array, axis)): si = sp.interpolate.interp1d(_axis, dat, bounds_error=False, fill_value=0., kind=interpolation_method) coord.offset = offset - shift[0] dat[:] = si(coord.axis) pbar.update(i) i += 1 coord.offset = offset # Cropping time mini, maxi = shift_array.min(), shift_array.max() if mini < 0: self.crop_in_units(axis, offset - mini) if maxi > 0: self.crop_in_units(axis, None, _axis[-1] - maxi)
def multifit(self, mask=None, fitter="leastsq", charge_only_fixed=False, grad=False, autosave=False, autosave_every=10, **kwargs): if autosave is not False: fd, autosave_fn = tempfile.mkstemp(prefix='hyperspy_autosave-', dir='.', suffix='.npz') os.close(fd) autosave_fn = autosave_fn[:-4] messages.information("Autosaving each %s pixels to %s.npz" % (autosave_every, autosave_fn)) messages.information( "When multifit finishes its job the file will be deleted") if mask is not None and \ (mask.shape != tuple(self.axes_manager.navigation_shape)): messages.warning_exit( "The mask must be an array with the same espatial dimensions as the" "navigation shape, %s" % self.axes_manager.navigation_shape) masked_elements = 0 if mask is None else mask.sum() pbar = progressbar.progressbar( maxval=(np.cumprod(self.axes_manager.navigation_shape)[-1] - masked_elements)) i = 0 for index in np.ndindex(tuple(self.axes_manager.navigation_shape)): if mask is None or not mask[index]: self.axes_manager.set_not_slicing_indexes(index) self.charge(only_fixed=charge_only_fixed) self.fit(fitter=fitter, grad=grad, **kwargs) i += 1 pbar.update(i) if autosave is True and i % autosave_every == 0: self.save_parameters2file(autosave_fn) pbar.finish() if autosave is True: messages.information('Deleting the temporary file %s pixels' % (autosave_fn + 'npz')) os.remove(autosave_fn + '.npz')
def generate_data_from_model(self, out_of_range_to_nan=True): """Generate a SI with the current model The SI is stored in self.model_cube """ pbar = progressbar.progressbar( maxval=(np.cumprod(self.axes_manager.navigation_shape)[-1])) i = 0 for index in np.ndindex(tuple(self.axes_manager.navigation_shape)): self.axes_manager.set_not_slicing_indexes(index) self.charge(only_fixed=False) self.model_cube[self.axes_manager._getitem_tuple][ self.channel_switches] = self.__call__( non_convolved=not self.convolved, onlyactive=True) if out_of_range_to_nan is True: self.model_cube[self.axes_manager._getitem_tuple][ self.channel_switches == False] = np.nan self.model_cube[self.channel_switches == False, :, :] = np.nan i += 1 pbar.update(i)
def generate_data_from_model(self, out_of_range_to_nan=True): """Generate a SI with the current model The SI is stored in self.model_cube """ maxval = self.axes_manager.navigation_size if maxval > 0: pbar = progressbar.progressbar(maxval=maxval) i = 0 for index in self.axes_manager: self.charge(only_fixed=False) self.model_cube[self.axes_manager._getitem_tuple][ self.channel_switches] = self.__call__( non_convolved=not self.convolved, onlyactive=True) if out_of_range_to_nan is True: self.model_cube[self.axes_manager._getitem_tuple][ self.channel_switches == False] = np.nan i += 1 if maxval > 0: pbar.update(i) pbar.finish()
def apply(self): self.signal._plot.auto_update_plot = False maxval = self.signal.axes_manager.navigation_size if maxval > 0: pbar = progressbar(maxval=maxval) i = 0 self.bg_line_range = 'full' for s in self.signal: s.data[:] -= \ np.nan_to_num(self.bg_to_plot(self.signal.axes_manager, 0)) if self.background_type == 'Power Law': s.data[:self.axis.value2index(self.ss_right_value)] = 0 i+=1 if maxval > 0: pbar.update(i) if maxval > 0: pbar.finish() self.signal._replot() self.signal._plot.auto_update_plot = True
def apply(self): self.signal._plot.auto_update_plot = False maxval = self.signal.axes_manager.navigation_size if maxval > 0: pbar = progressbar(maxval=maxval) i = 0 self.bg_line_range = 'full' for s in self.signal: s.data[:] -= \ np.nan_to_num(self.bg_to_plot(self.signal.axes_manager, 0)) if self.background_type == 'Power Law': s.data[:self.axis.value2index(self.ss_right_value)] = 0 i += 1 if maxval > 0: pbar.update(i) if maxval > 0: pbar.finish() self.signal._replot() self.signal._plot.auto_update_plot = True
def apply(self): self.signal._plot.auto_update_plot = False if self.signal.axes_manager.navigation_dimension != 0: pbar = progressbar( maxval = (np.cumprod(self.signal.axes_manager.navigation_shape)[-1])) i = 0 self.bg_line_range = 'full' indexes = np.ndindex( tuple(self.signal.axes_manager.navigation_shape)) for index in indexes: self.signal.axes_manager.set_not_slicing_indexes(index) self.signal.data[ self.signal.axes_manager._getitem_tuple] -= \ np.nan_to_num(self.bg_to_plot(self.signal.axes_manager, 0)) i+=1 pbar.update(i) pbar.finish() else: self.signal.data[self.signal.axes_manager._getitem_tuple] -= \ np.nan_to_num(self.bg_to_plot(self.signal.axes_manager, 0)) self.signal._replot() self.signal._plot.auto_update_plot = True
def multifit(self, mask = None, fitter = "leastsq", charge_only_fixed = False, grad = False, autosave = False, autosave_every = 10, **kwargs): if autosave is not False: fd, autosave_fn = tempfile.mkstemp(prefix = 'hyperspy_autosave-', dir = '.', suffix = '.npz') os.close(fd) autosave_fn = autosave_fn[:-4] messages.information( "Autosaving each %s pixels to %s.npz" % (autosave_every, autosave_fn)) messages.information( "When multifit finishes its job the file will be deleted") if mask is not None and \ (mask.shape != tuple(self.axes_manager.navigation_shape)): messages.warning_exit( "The mask must be an array with the same espatial dimensions as the" "navigation shape, %s" % self.axes_manager.navigation_shape) masked_elements = 0 if mask is None else mask.sum() pbar = progressbar.progressbar( maxval = (np.cumprod(self.axes_manager.navigation_shape)[-1] - masked_elements)) i = 0 for index in np.ndindex(tuple(self.axes_manager.navigation_shape)): if mask is None or not mask[index]: self.axes_manager.set_not_slicing_indexes(index) self.charge(only_fixed = charge_only_fixed) self.fit(fitter = fitter, grad = grad, **kwargs) i += 1 pbar.update(i) if autosave is True and i % autosave_every == 0: self.save_parameters2file(autosave_fn) pbar.finish() if autosave is True: messages.information( 'Deleting the temporary file %s pixels' % (autosave_fn + 'npz')) os.remove(autosave_fn + '.npz')
def estimate_shift_in_index_1D(self, irange=(None,None), axis=-1, reference_indices=None, max_shift=None, interpolate=True, number_of_interpolation_points=5): """Estimate the shifts in a given axis using cross-correlation This method can only estimate the shift by comparing unidimensional features that should not change the position in the given axis. To decrease the memory usage, the time of computation and the accuracy of the results it is convenient to select the feature of interest setting the irange keyword. By default interpolation is used to obtain subpixel precision. Parameters ---------- axis : int The axis in which the analysis will be performed. irange : tuple of ints (i1, i2) Define the range of the feature of interest. If i1 or i2 are None, the range will not be limited in that side. reference_indices : tuple of ints or None Defines the coordinates of the spectrum that will be used as a reference. If None the spectrum of 0 coordinates will be used. max_shift : int interpolate : bool number_of_interpolation_points : int Number of interpolation points. Warning: making this number too big can saturate the memory Return ------ An array with the result of the estimation. """ ip = number_of_interpolation_points + 1 axis = self.axes_manager.axes[axis] if reference_indices is None: reference_indices = [0,] * (len(self.axes_manager.axes) - 1) else: reference_indices = list(reference_indices) reference_indices.insert(axis.index_in_array, slice(None)) i1, i2 = irange array_shape = [axis.size for axis in self.axes_manager.axes] array_shape[axis.index_in_array] = 1 shift_array = np.zeros(array_shape) ref = self.data[reference_indices][i1:i2] if interpolate is True: ref = utils.interpolate_1D(ip, ref) maxval = self.axes_manager.navigation_size pbar = progressbar.progressbar(maxval=maxval) i = 0 for dat, shift in zip(self.iterate_axis(axis.index_in_array), utils.iterate_axis(shift_array, axis.index_in_array)): dat = dat[i1:i2] if interpolate is True: dat = utils.interpolate_1D(ip, dat) shift[:] = np.argmax( np.correlate(ref, dat,'full')) - len(ref) + 1 i+=1 pbar.update(i) pbar.finish() if max_shift is not None: if interpolate is True: max_shift *= ip shift_array.clip(a_min = -max_shift, a_max = max_shift) if interpolate is True: shift_array /= ip shift_array *= axis.scale return shift_array
def estimate_2D_translation(self, reference='current', correlation_threshold=None, chunk_size=30, roi=None, normalize_corr=False, sobel=True, medfilter=True, hanning=True, plot=False, dtype='float',): """Estimate the shifts in a image using phase correlation This method can only estimate the shift by comparing bidimensional features that should not change position between frames. To decrease the memory usage, the time of computation and the accuracy of the results it is convenient to select a region of interest by setting the roi keyword. Parameters ---------- reference : {'current', 'cascade' ,'stat'} If 'current' (default) the image at the current coordinates is taken as reference. If 'cascade' each image is aligned with the previous one. If 'stat' the translation of every image with all the rest is estimated and by performing statistical analysis on the result the translation is estimated. correlation_threshold : {None, 'auto', float} This parameter is only relevant when `reference` is 'stat'. If float, the shift estimations with a maximum correlation value lower than the given value are not used to compute the estimated shifts. If 'auto' the threshold is calculated automatically as the minimum maximum correlation value of the automatically selected reference image. chunk_size: {None, int} If int and `reference`=='stat' the number of images used as reference are limited to the given value. roi : tuple of ints (top, bottom, left, right) Define the region of interest sobel : bool apply a sobel filter for edge enhancement medfilter : bool apply a median filter for noise reduction hanning : bool Apply a 2d hanning filter plot : bool If True plots the images after applying the filters and the phase correlation dtype : str or dtype Typecode or data-type in which the calculations must be performed. Returns ------- list of applied shifts Notes ----- The statistical analysis approach to the translation estimation when using `reference`='stat' roughly follows [1]_ . If you use it please cite their article. References ---------- .. [1] Schaffer, Bernhard, Werner Grogger, and Gerald Kothleitner. “Automated Spatial Drift Correction for EFTEM Image Series.” Ultramicroscopy 102, no. 1 (December 2004): 27–36. """ axes = self.axes_manager.signal_axes ref = None if reference == 'cascade' else \ self.__call__().copy() shifts = [] nrows = None images_number = self.axes_manager._max_index + 1 if reference == 'stat': nrows = images_number if chunk_size is None else \ min(images_number, chunk_size) pcarray = ma.zeros((nrows, self.axes_manager._max_index + 1, ), dtype=np.dtype([('max_value', np.float), ('shift', np.int32, (2,))])) nshift, max_value = estimate_image_shift( self(), self(), roi=roi, sobel=sobel, medfilter=medfilter, hanning=hanning, normalize_corr=normalize_corr, plot=plot, dtype=dtype) np.fill_diagonal(pcarray['max_value'], max_value) pbar = progressbar(maxval=nrows*images_number).start() else: pbar = progressbar(maxval=images_number).start() # Main iteration loop. Fills the rows of pcarray when reference # is stat for i1, im in enumerate(self._iterate_signal(copy=False)): if reference in ['current', 'cascade']: if ref is None: ref = im.copy() shift = np.array([0,0]) nshift, max_val = estimate_image_shift(ref, im, roi=roi, sobel=sobel, medfilter=medfilter, hanning=hanning, plot=plot, normalize_corr=normalize_corr, dtype=dtype) if reference == 'cascade': shift += nshift ref = im.copy() else: shift = nshift shifts.append(shift.copy()) pbar.update(i1+1) elif reference == 'stat': if i1 == nrows: break # Iterate to fill the columns of pcarray for i2, im2 in enumerate( self._iterate_signal(copy=False)): if i2 > i1: nshift, max_value = estimate_image_shift( im, im2, roi=roi, sobel=sobel, medfilter=medfilter, hanning=hanning, normalize_corr=normalize_corr, plot=plot, dtype=dtype) pcarray[i1,i2] = max_value, nshift del im2 pbar.update(i2 + images_number*i1 + 1) del im if reference == 'stat': # Select the reference image as the one that has the # higher max_value in the row sqpcarr = pcarray[:,:nrows] sqpcarr['max_value'][:] = symmetrize(sqpcarr['max_value']) sqpcarr['shift'][:] = antisymmetrize(sqpcarr['shift']) ref_index = np.argmax(pcarray['max_value'].min(1)) self.ref_index = ref_index shifts = (pcarray['shift'] + pcarray['shift'][ref_index,:nrows][:,np.newaxis]) if correlation_threshold is not None: if correlation_threshold == 'auto': correlation_threshold = \ (pcarray['max_value'].min(0)).max() print("Correlation threshold = %1.2f" % correlation_threshold) shifts[pcarray['max_value'] < \ correlation_threshold] = ma.masked shifts.mask[ref_index,:] = False std_ = shifts.std(0) shifts = shifts.mean(0) else: shifts = np.array(shifts) del ref return shifts
def multifit(self, mask=None, charge_only_fixed=False, autosave=False, autosave_every=10, **kwargs): """Fit the data to the model at all the positions of the navigation dimensions. Parameters ---------- mask : {None, numpy.array} To mask (do not fit) at certain position pass a numpy.array of type bool where True indicates that the data will not be fitted at the given position. charge_only_fixed : bool If True, only the fixed parameters values will be updated when changing the positon. autosave : bool If True, the result of the fit will be saved automatically with a frequency defined by autosave_every. autosave_every : int Save the result of fitting every given number of spectra. **kwargs : key word arguments Any extra key word argument will be passed to the fit method. See the fit method documentation for a list of valid arguments. See Also -------- fit """ if autosave is not False: fd, autosave_fn = tempfile.mkstemp( prefix = 'hyperspy_autosave-', dir = '.', suffix = '.npz') os.close(fd) autosave_fn = autosave_fn[:-4] messages.information( "Autosaving each %s pixels to %s.npz" % (autosave_every, autosave_fn)) messages.information( "When multifit finishes its job the file will be deleted") if mask is not None and \ (mask.shape != tuple(self.axes_manager.navigation_shape)): messages.warning_exit( "The mask must be a numpy array of boolen type with " " the same shape as the navigation: %s" % self.axes_manager.navigation_shape) masked_elements = 0 if mask is None else mask.sum() maxval=self.axes_manager.navigation_size - masked_elements if maxval > 0: pbar = progressbar.progressbar(maxval=maxval) if 'bounded' in kwargs and kwargs['bounded'] is True: if kwargs['fitter'] == 'mpfit': self.set_mpfit_parameters_info() kwargs['bounded'] = None elif kwargs['fitter'] in ("tnc", "l_bfgs_b"): self.set_boundaries() kwargs['bounded'] = None else: messages.information( "The chosen fitter does not suppport bounding." "If you require boundinig please select one of the " "following fitters instead: mpfit, tnc, l_bfgs_b") kwargs['bounded'] = False i = 0 for index in self.axes_manager: if mask is None or not mask[index]: self.fit(**kwargs) i += 1 if maxval > 0: pbar.update(i) if autosave is True and i % autosave_every == 0: self.save_parameters2file(autosave_fn) if maxval > 0: pbar.finish() if autosave is True: messages.information( 'Deleting the temporary file %s pixels' % ( autosave_fn + 'npz')) os.remove(autosave_fn + '.npz')