def poisson_noise(measurement: Measurement, dose: float): """ Add Poisson noise to a measurment. Parameters ---------- measurement: Measurement object The measurement to add noise to. dose: float The irradiation dose in electrons per Å^2. Returns ------- measurement: Measurement object The noisy measurement. """ pixel_area = np.product([calibration.sampling for calibration in measurement.calibrations[:2]]) measurement = measurement.copy() array = measurement.array electrons_per_pixel = dose * pixel_area measurement.array[:] = array * electrons_per_pixel measurement.array[:] = np.random.poisson(array).astype(np.float) return measurement
def poisson_noise(measurement: Measurement, dose: float, pixel_area: float = None, negative_values='clip'): """ Add Poisson noise to a measurment. Parameters ---------- measurement: Measurement object The measurement to add noise to. dose: float The irradiation dose in electrons per Å^2. pixel_area: float, optional Pixel area in Å^2. If not provided this will be calculated from the calibraions when possible. Returns ------- measurement: Measurement object The noisy measurement. """ if pixel_area is None: pixel_areas = [] for calibration in measurement.calibrations: if calibration is not None: if calibration.units.lower() in ('angstrom', 'å'): pixel_areas.append(calibration.sampling) if len(pixel_areas) != 2: raise RuntimeError( 'Real space pixel size not recognized from calibrations.') pixel_area = np.product(pixel_areas) measurement = measurement.copy() array = measurement.array if negative_values == 'clip': array = np.clip(array, a_min=1e-12, a_max=None) elif negative_values != 'raise': if np.any(array < 0.): raise ValueError('Measurement values must be positive.') electrons_per_pixel = dose * pixel_area array = array * electrons_per_pixel measurement.array[:] = np.random.poisson(array).astype(np.float) return measurement
def add_scan_noise(measurement: Measurement, dwell_time: float, flyback_time: float, max_frequency: float, rms_power: float, num_components: int = 200): """ Add scan noise to a measurement. Parameters ---------- measurement: Measurement object or 2d array The measurement to add noise to. dwell_time: float Dwell time on a single pixel in s. flyback_time: float Flyback time for the scanning probe at the end of each scan line in s. max_frequency: float Maximum noise frequency in 1 / s. rms_power: float Root-mean-square power of the distortion in unit of percent. num_components: int, optional Number of frequency components. More components will be more 'white' but will take longer. Returns ------- measurement: Measurement object The noisy measurement. """ measurement = measurement.copy() if isinstance(measurement, Measurement): array = measurement.array else: array = measurement time = _pixel_times(dwell_time, flyback_time, array.T.shape) displacement_x, displacement_y = _make_displacement_field( time, max_frequency, num_components, rms_power) array[:] = _apply_displacement_field(array.T, displacement_x, displacement_y).T return measurement