def __init__(self, q_values, mask, n_bins=101): """ Parameters ---------- q_values : np.ndarray (float) For each pixel, this is the momentum transfer value of that pixel mask : np.ndarray (int) A boolean (int) saying if each pixel is masked or not n_bins : int The number of bins to employ. If `None` guesses a good value. """ self.q_values = enforce_raw_img_shape(q_values) self.mask = enforce_raw_img_shape(mask).astype(np.int) self.n_bins = n_bins # figure out the number of bins to use if n_bins != None: self.n_bins = n_bins self._bin_factor = float(self.n_bins - 1) / self.q_values.max() else: self._bin_factor = 25.0 self.n_bins = (self.q_values.max() * self._bin_factor) + 1 self._bin_assignments = np.floor(q_values * self._bin_factor).astype( np.int32) self._normalization_array = (np.bincount( self._bin_assignments.flatten(), weights=self.mask.flatten() ) \ + 1e-100).astype(np.float) assert self.n_bins == self._bin_assignments.max() + 1 self._normalization_array = self._normalization_array[:self.n_bins] return
def __init__(self, q_values, mask, n_bins=101): """ Parameters ---------- q_values : np.ndarray (float) For each pixel, this is the momentum transfer value of that pixel mask : np.ndarray (int) A boolean (int) saying if each pixel is masked or not n_bins : int The number of bins to employ. If `None` guesses a good value. """ self.q_values = read.enforce_raw_img_shape(q_values) self.mask = read.enforce_raw_img_shape(mask).astype(np.int) self.n_bins = n_bins # figure out the number of bins to use if n_bins != None: self.n_bins = n_bins self._bin_factor = float(self.n_bins-0.5) / self.q_values.max() else: self._bin_factor = 25.0 self.n_bins = (self.q_values.max() * self._bin_factor) + 1 self._bin_assignments = np.floor( q_values * self._bin_factor ).astype(np.int32) self._normalization_array = (np.bincount( self._bin_assignments.flatten(), weights=self.mask.flatten() ) \ + 1e-100).astype(np.float) #print self.n_bins, self._bin_assignments.max() + 1 assert self.n_bins == self._bin_assignments.max() + 1, 'bin mismatch in init' self._normalization_array = self._normalization_array[:self.n_bins] return
def __call__(self, image): """ Bin pixel intensities by their momentum transfer. Parameters ---------- image : np.ndarray The intensity at each pixel, same shape as pixel_pos Returns ------- bin_centers : ndarray, float The q center of each bin. bin_values : ndarray, int The average intensity in the bin. """ image = read.enforce_raw_img_shape(image) if not (image.shape == self.q_values.shape): raise ValueError('`image` and `q_values` must have the same shape') if not (image.shape == self.mask.shape): raise ValueError('`image` and `mask` must have the same shape') weights = image.flatten() * self.mask.flatten() bin_values = np.bincount(self._bin_assignments.flatten(), weights=weights) bin_values /= self._normalization_array assert bin_values.shape[0] == self.n_bins, 'bin number mismatch (%d, %d)' \ % (bin_values.shape[0], self.n_bins) return bin_values
def load(cls, filename): """ Load a saved mask. Can be one of many formats: -- pypad .mask -- cheetah .h5 Parameters ---------- filename : str The name of the file to read. """ m = cls() if filename.endswith('.mask'): f = h5py.File(filename, 'r') for k in f: m._masks[k] = np.array(f[k]) f.close() elif filename.endswith('.h5'): try: f = h5py.File(filename, 'r') d = np.array(f['/data/data']) assert d.shape == (1480, 1552) f.close() except: raise IOError('Cannot read data inside: %s. Either data is ' 'corrupt or not in cheetah format [in /data/data' ' and shape (1480, 1552)]' % filename) m._masks['cheetah'] = np.array(read.enforce_raw_img_shape(d)) else: raise IOError( 'Can only read files with {.mask, .h5} format -- got: %s' % filename) return m
def load(cls, filename): """ Load a saved mask. Can be one of many formats: -- pypad .mask -- cheetah .h5 Parameters ---------- filename : str The name of the file to read. """ m = cls() if filename.endswith('.mask'): f = h5py.File(filename, 'r') for k in f: m._masks[k] = np.array(f[k]) f.close() elif filename.endswith('.h5'): try: f = h5py.File(filename, 'r') d = np.array( f['/data/data'] ) assert d.shape == (1480, 1552) f.close() except: raise IOError('Cannot read data inside: %s. Either data is ' 'corrupt or not in cheetah format [in /data/data' ' and shape (1480, 1552)]' % filename) m._masks['cheetah'] = np.array( read.enforce_raw_img_shape(d) ) else: raise IOError('Can only read files with {.mask, .h5} format -- got: %s' % filename) return m
def preprocess_image(raw_image, threshold=0.0025, sigma=1.0, minf_size=1, rank_size=1, sobel=True): """ Applies an edge filter followed by a noise reduction filter. Very good at locating powder rings and filtering everything else out. Parameters ---------- raw_image : ndarray An image to find the edges of Returns ------- binary_image : ndarray, np.bool A binary image, with "1" where there are powder rings/strong edges """ # flatten the image into a two-D array and later re-process it # convert to cheetah-like format if raw_image.shape == (4, 16, 185, 194): non_flat_img = True image = np.zeros((1480, 1552), dtype=np.float) # flat image for i in range(8): for j in range(4): x_start = 185 * i x_stop = 185 * (i + 1) y_start = 388 * j y_stop = 388 * (j + 1) two_by_one = np.hstack( (raw_image[j, i * 2, :, :], raw_image[j, i * 2 + 1, :, :])).astype(np.float) image[x_start:x_stop, y_start:y_stop] = two_by_one elif len(raw_image.shape) == 2: non_flat_img = False image = raw_image.astype(np.float) else: raise ValueError( '`raw_image` should be 2d or shape-(4,16,185,194), got' ': %s' % str(raw_image.shape)) # apply rank filter & gaussian filter if rank_size > 2: image = filters.rank_filter(image, -1, size=rank_size) if sigma > 0.1: image = filters.gaussian_filter(image, sigma=sigma) image -= image.min() assert image.min() == 0 assert image.max() > 0 # threshold image = (image > (image.max() * threshold)) if minf_size > 2: image = filters.minimum_filter(image, size=minf_size) if sobel: image = np.abs(filters.sobel(image, 0)) + np.abs( filters.sobel(image, 1)) if non_flat_img: image = read.enforce_raw_img_shape(image.astype(np.bool)) else: image = image.astype(np.bool) return image
def preprocess_image(raw_image, threshold=0.0025, sigma=1.0, minf_size=1, rank_size=1, sobel=True): """ Applies an edge filter followed by a noise reduction filter. Very good at locating powder rings and filtering everything else out. Parameters ---------- raw_image : ndarray An image to find the edges of Returns ------- binary_image : ndarray, np.bool A binary image, with "1" where there are powder rings/strong edges """ # flatten the image into a two-D array and later re-process it # convert to cheetah-like format if raw_image.shape == (4,16,185,194): non_flat_img = True image = np.zeros((1480, 1552), dtype=np.float) # flat image for i in range(8): for j in range(4): x_start = 185 * i x_stop = 185 * (i+1) y_start = 388 * j y_stop = 388 * (j+1) two_by_one = np.hstack(( raw_image[j,i*2,:,:], raw_image[j,i*2+1,:,:])).astype(np.float) image[x_start:x_stop,y_start:y_stop] = two_by_one elif len(raw_image.shape) == 2: non_flat_img = False image = raw_image.astype(np.float) else: raise ValueError('`raw_image` should be 2d or shape-(4,16,185,194), got' ': %s' % str(raw_image.shape)) # apply rank filter & gaussian filter if rank_size > 2: image = filters.rank_filter(image, -1, size=rank_size) if sigma > 0.1: image = filters.gaussian_filter(image, sigma=sigma) image -= image.min() assert image.min() == 0 assert image.max() > 0 # threshold image = (image > (image.max() * threshold)) if minf_size > 2: image = filters.minimum_filter(image, size=minf_size) if sobel: image = np.abs(filters.sobel(image, 0)) + np.abs(filters.sobel(image, 1)) if non_flat_img: image = read.enforce_raw_img_shape( image.astype(np.bool) ) else: image = image.astype(np.bool) return image