def cbed_frame(fy=128, fx=128, zero=None, a=None, b=None, indices=None, radius=4, all_equal=False): if zero is None: zero = (fy//2, fx//2) zero = np.array(zero) if a is None: a = (fy//8, 0) a = np.array(a) if b is None: b = make_cartesian(make_polar(a) - (0, np.pi/2)) b = np.array(b) if indices is None: indices = np.mgrid[-10:11, -10:11] indices, peaks = frame_peaks(fy=fy, fx=fx, zero=zero, a=a, b=b, r=radius, indices=indices) data = np.zeros((1, fy, fx), dtype=np.float32) dists = np.linalg.norm(peaks - zero, axis=-1) max_dist = dists.max() for i, p in enumerate(peaks): data += m.circular( centerX=p[1], centerY=p[0], imageSizeX=fx, imageSizeY=fy, radius=radius, antialiased=True, ) * (1 if all_equal else max_dist - dists[i] + i) return (data, indices, peaks)
def run_refine(ctx, dataset, zero, a, b, match_pattern: MatchPattern, matcher: grm.Matcher, correlation='fast', match='fast', indices=None, steps=5, zero_shift=None, roi=None, progress=False): ''' Wrapper function to refine the given lattice for each frame by calculating approximate peak positions and refining them for each frame using a combination of :class:`libertem_blobfinder.CorrelationUDF` and :class:`libertem_blobfinder.RefinementMixin`. .. versionchanged:: 0.3.0 Support for :class:`FullFrameCorrelationUDF` through parameter :code:`correlation = 'fullframe'` Parameters ---------- ctx : libertem.api.Context Instance of a LiberTEM :class:`~libertem.api.Context` dataset : libertem.io.dataset.base.DataSet Instance of a :class:`~libertem.io.dataset.base.DataSet` zero : numpy.ndarray Approximate value for "zero" point (y, x) in px (origin, zero order peak) a : numpy.ndarray Approximate value for "a" vector (y, x) in px. b : numpy.ndarray Approximate value for "b" vector (y, x) in px. match_pattern : MatchPattern Instance of :class:`~MatchPattern` matcher : libertem.analysis.gridmatching.Matcher Instance of :class:`~libertem.analysis.gridmatching.Matcher` to perform the matching correlation : {'fast', 'sparse', 'fullframe'}, optional 'fast', 'sparse' or 'fullframe' to select :class:`~FastCorrelationUDF`, :class:`~SparseCorrelationUDF` or :class:`~FullFrameCorrelationUDF` match : {'fast', 'affine'}, optional 'fast' or 'affine' to select :class:`~FastmatchMixin` or :class:`~AffineMixin` indices : numpy.ndarray, optional Indices to refine. This is trimmed down to positions within the frame. As a convenience, for the indices parameter this function accepts both shape (n, 2) and (2, n, m) so that numpy.mgrid[h:k, i:j] works directly to specify indices. This saves boilerplate code when using this function. Default: numpy.mgrid[-10:10, -10:10]. steps : int, optional Only for correlation == 'sparse': Correlation steps. See :meth:`~SparseCorelationUDF.__init__` for details. zero_shift : Union[AUXBufferWrapper, numpy.ndarray, None], optional Zero shift, for example descan error. Can be :code:`None`, :code:`numpy.array((y, x))` or AUX data with :code:`(y, x)` for each frame. Only supported for correlation methods :code:`fast` and `fullframe`. roi : numpy.ndarray, optional ROI for :meth:`~libertem.api.Context.run_udf` progress : bool, optional Show progress bar. Default :code:`False` Returns ------- result : Dict[str, BufferWrapper] Result buffers of the UDF. See :meth:`libertem_blobfinder.correlation.CorrelationUDF.get_result_buffers` and :meth:`RefinementMixin.get_result_buffers` for details on the available buffers. used_indices : numpy.ndarray The peak indices that were within the frame. Examples -------- >>> dataset = ctx.load( ... filetype="memory", ... data=np.zeros(shape=(2, 2, 128, 128), dtype=np.float32) ... ) >>> (result, used_indices) = run_refine( ... ctx, dataset, ... zero=(64, 64), a=(1, 0), b=(0, 1), ... match_pattern=libertem_blobfinder.common.patterns.RadialGradient(radius=4), ... matcher=grm.Matcher() ... ) >>> result['centers'].data #doctest: +ELLIPSIS array(...) ''' if indices is None: indices = np.mgrid[-10:11, -10:11] (fy, fx) = tuple(dataset.shape.sig) indices, peaks = frame_peaks(fy=fy, fx=fx, zero=zero, a=a, b=b, r=match_pattern.search, indices=indices) peaks = peaks.astype('int') if correlation == 'fast': method = FastCorrelationUDF elif correlation == 'sparse': method = SparseCorrelationUDF elif correlation == 'fullframe': method = FullFrameCorrelationUDF else: raise ValueError( "Unknown correlation method %s. Supported are 'fast' and 'sparse'" % correlation) if match == 'affine': mixin = AffineMixin elif match == 'fast': mixin = FastmatchMixin else: raise ValueError( "Unknown match method %s. Supported are 'fast' and 'affine'" % match) # The inheritance order matters: FIRST the mixin, which calls # the super class methods. class MyUDF(mixin, method): pass udf = MyUDF( peaks=peaks, indices=indices, start_zero=zero, start_a=a, start_b=b, match_pattern=match_pattern, matcher=matcher, steps=steps, zero_shift=zero_shift, ) result = ctx.run_udf(dataset=dataset, udf=udf, roi=roi, progress=progress) return (result, indices)
def run_refine(ctx, dataset, zero, a, b, match_pattern: MatchPattern, matcher: grm.Matcher, correlation='fast', match='fast', indices=None, steps=5, roi=None): ''' Refine the given lattice for each frame by calculating approximate peak positions and refining them for each frame by using the blobcorrelation and methods of :class:`~libertem.analysis.gridmatching.Matcher`. Parameters ---------- ctx : libertem.api.Context Instance of a LiberTEM :class:`~libertem.api.Context` dataset : libertem.io.dataset.base.DataSet Instance of a :class:`~libertem.io.dataset.base.DataSet` zero : numpy.ndarray Approximate value for "zero" point (y, x) in px (origin, zero order peak) a : numpy.ndarray Approximate value for "a" vector (y, x) in px. b : numpy.ndarray Approximate value for "b" vector (y, x) in px. match_pattern : MatchPattern Instance of :class:`~MatchPattern` matcher : libertem.analysis.gridmatching.Matcher Instance of :class:`~libertem.analysis.gridmatching.Matcher` to perform the matching correlation : {'fast', 'sparse'}, optional 'fast' or 'sparse' to select :class:`~FastCorrelationUDF` or :class:`~SparseCorrelationUDF` match : {'fast', 'affine'}, optional 'fast' or 'affine' to select :class:`~FastmatchMixin` or :class:`~AffineMixin` indices : numpy.ndarray, optional Indices to refine. This is trimmed down to positions within the frame. As a convenience, for the indices parameter this function accepts both shape (n, 2) and (2, n, m) so that numpy.mgrid[h:k, i:j] works directly to specify indices. This saves boilerplate code when using this function. Default: numpy.mgrid[-10:10, -10:10]. steps : int, optional Only for correlation == 'sparse': Correlation steps. See :meth:`~SparseCorelationUDF.__init__` for details. roi : numpy.ndarray, optional ROI for :meth:`~libertem.api.Context.run_udf` Returns ------- Tuple[Dict[str, BufferWrapper], numpy.ndarray] :code:`(result, used_indices)` where :code:`result` is a :code:`dict` mapping buffer names to result buffers based on .. code-block:: python { 'centers': BufferWrapper( kind="nav", extra_shape=(num_disks, 2), dtype="u2" ), 'refineds': BufferWrapper( kind="nav", extra_shape=(num_disks, 2), dtype="float32" ), 'peak_values': BufferWrapper( kind="nav", extra_shape=(num_disks,), dtype="float32" ), 'peak_elevations': BufferWrapper( kind="nav", extra_shape=(num_disks,), dtype="float32" ), 'zero': BufferWrapper( kind="nav", extra_shape=(2,), dtype="float32" ), 'a': BufferWrapper( kind="nav", extra_shape=(2,), dtype="float32" ), 'b': BufferWrapper( kind="nav", extra_shape=(2,), dtype="float32" ), 'selector': BufferWrapper( kind="nav", extra_shape=(num_disks,), dtype="bool" ), 'error': self.buffer( kind="nav", dtype="float32", ), } and :code:`used_indices` are the indices that were within the frame. Examples -------- >>> dataset = ctx.load( ... filetype="memory", ... data=np.zeros(shape=(2, 2, 128, 128), dtype=np.float32) ... ) >>> (result, used_indices) = run_refine( ... ctx, dataset, ... zero=(64, 64), a=(1, 0), b=(0, 1), ... match_pattern=RadialGradient(radius=4), ... matcher=grm.Matcher() ... ) >>> result['centers'].data #doctest: +ELLIPSIS array(...) ''' if indices is None: indices = np.mgrid[-10:11, -10:11] (fy, fx) = tuple(dataset.shape.sig) indices, peaks = frame_peaks(fy=fy, fx=fx, zero=zero, a=a, b=b, r=match_pattern.search, indices=indices) peaks = peaks.astype('int') if correlation == 'fast': method = FastCorrelationUDF elif correlation == 'sparse': method = SparseCorrelationUDF else: raise ValueError( "Unknown correlation method %s. Supported are 'fast' and 'sparse'" % correlation) if match == 'affine': mixin = AffineMixin elif match == 'fast': mixin = FastmatchMixin else: raise ValueError( "Unknown match method %s. Supported are 'fast' and 'affine'" % match) # The inheritance order matters: FIRST the mixin, which calls # the super class methods. class MyUDF(mixin, method): pass udf = MyUDF(peaks=peaks, indices=indices, start_zero=zero, start_a=a, start_b=b, match_pattern=match_pattern, matcher=matcher, steps=steps) result = ctx.run_udf( dataset=dataset, udf=udf, roi=roi, ) return (result, indices)