def isnr(images, fill_value=0.0): """ Streaming, pixelwise signal-to-noise ratio (SNR). Parameters ---------- images : iterable of ndarray These images should represent identical measurements. ``images`` can also be a generator. fill_value : float, optional Division-by-zero results will be filled with this value. Yields ------ snr : `~numpy.ndarray` Pixelwise signal-to-noise ratio See Also -------- snr_from_collection : pixelwise signal-to-noise ratio from a collection of measurements """ first, images = peek(images) snr = np.empty_like(first) images1, images2 = itercopy(images, 2) for mean, std in zip(imean(images1), istd(images2)): valid = std != 0 snr[valid] = mean[valid] / std[valid] snr[np.logical_not(valid)] = fill_value yield snr
def mask_from_collection(images, px_thresh=(0, 3e4), std_thresh=None): """ Determine binary mask from a set of images. These images should represent identical measurements, e.g. a set of diffraction patterns before photoexcitation. Pixels are rejected on the following two criteria: * Pixels with a value above a certain threshold or below zero, for any image in the set, are considered dead; * Pixels with a cumulative standard deviation above a certain threshold are considered uncertain. This function operates in constant-memory; it is therefore safe to use on a large collection of images (>10GB). Parameters ---------- images : iterable of ndarray These images should represent identical measurements. ``images`` can also be a generator. px_thresh : float or iterable, optional Pixels with a value outside of [``min(px_thresh)``, ``max(px_thresh)``] in any of the images in ``images`` are rejected. If ``px_thresh`` is a single float, it is assumed to be the maximal intensity, and no lower bound is enforced. std_thresh : int or float or None, optional Standard-deviation threshold. If the standard deviation of a pixel exceeds ``std_thresh``, it is rejected. If None (default), a threshold is not enforced. Returns ------- mask : `~numpy.ndarray`, dtype bool Pixel mask. Pixels where ``mask`` is True are invalid. Notes ----- ``numpy.inf`` can be used to have a lower pixel value bound but no upper bound. For example, to reject all negative pixels only, set ``px_thresh = (0, numpy.inf)``. """ if isinstance(px_thresh, Iterable): min_int, max_int = min(px_thresh), max(px_thresh) else: min_int, max_int = None, px_thresh first, images = peek(images) mask = np.zeros_like(first, dtype=bool) # 0 = False if std_thresh is not None: images, images_for_std = itercopy(images) std_calc = istd(images_for_std) else: std_calc = repeat(np.inf) for image, std in zip(images, std_calc): mask[image > max_int] = True if std_thresh is not None: mask[std > std_thresh] = True if min_int is not None: mask[image < min_int] = True return mask
def _raw_combine(timedelay, raw, exclude_scans, normalize, align, valid_mask, dtype): images = raw.itertime(timedelay, exclude_scans=exclude_scans) if align: # Note : the fast = False fixes issue #11, where single crystal images were not successfully aligned. images = ialign(images, mask=valid_mask) # Set up normalization if normalize: images, images2 = itercopy(images, copies=2) # Compute the total intensity of first image # This will be the reference point first2, images2 = peek(images2) initial_weight = np.sum(first2[valid_mask]) weights = (initial_weight / np.sum(image[valid_mask]) for image in images2) else: weights = None return average(images, weights=weights).astype(dtype)