def it_skips_too_oval(): """It doesn't have to work perfectly every time, but pass once in a 10 try loop""" n_fails = 0 for i in range(10): failed = 0 locs = [[64, 54], [64, 70]] with synth.Synth(overwrite=True, dim=(128, 128)) as s: peaks = synth.PeaksModelGaussianCircular( n_peaks=len(locs) ).amps_constant(val=4_000) peaks.std_x = [1.0, 1.0] peaks.std_y = [1.0, 2.0] synth.CameraModel(bias=bg_mean, std=bg_std) peaks.locs = locs im = s.render_chcy()[0, 0] im = im - bg_mean psf, reasons = worker._psf_estimate( im, peaks.locs, mea=17, return_reasons=True ) for loc, reason in zip(peaks.locs, reasons): if loc[1] < 64: if reason[worker.PSFEstimateMaskFields.skipped_too_oval] != 0: failed += 1 else: if reason[worker.PSFEstimateMaskFields.skipped_too_oval] != 1: failed += 1 if failed != 0: n_fails += 1 assert n_fails < 3
def it_skips_near_edges(): peaks, im, std = _make_image(0.0) psf, reasons = worker._psf_estimate(im, peaks.locs, mea=17, return_reasons=True) for loc, reason in zip(peaks.locs, reasons): skipped = reason[worker.PSFEstimateMaskFields.skipped_near_edges] if loc[0] < 5 or loc[0] > 1024 - 5 or loc[1] < 5 or loc[1] > 1024 - 5: assert skipped == 1
def it_skips_nans(): peaks, im = _make_image_n_locs([[64, 50], [64, 70]]) im[64, 50] = np.nan psf, reasons = worker._psf_estimate(im, peaks.locs, mea=17, return_reasons=True) for loc, reason in zip(peaks.locs, reasons): if loc[1] < 64: assert reason[worker.PSFEstimateMaskFields.skipped_has_nan] == 1 else: assert reason[worker.PSFEstimateMaskFields.skipped_has_nan] == 0
def it_skips_darks(): peaks, im = _make_image_n_locs([[64, 54]]) psf, reasons = worker._psf_estimate( im, peaks.locs, mea=17, threshold_abs=bg_std * 3, return_reasons=True ) peaks.locs = [[64, 54], [64, 80]] for loc, reason in zip(peaks.locs, reasons): if loc[1] < 64: assert reason[worker.PSFEstimateMaskFields.skipped_too_dark] == 0 else: assert reason[worker.PSFEstimateMaskFields.skipped_too_dark] == 1
def it_extracts_a_clean_psf_with_subpixel_alignment(): # Sweep over various psf z depths # Generate a seris of small synth images (representing a region over many fields) # Pass in the locs directly from the synth image maker (bypassing peak finder) # Check that we get back a good approximation of the PSF for i, depth in enumerate(np.linspace(-0.25, 0.25, 4)): peaks, im, expected_std = _make_image(depth) psf, reasons = worker._psf_estimate( im, peaks.locs, mea=17, return_reasons=True ) fit_params, _ = imops.fit_gauss2(psf) got = np.array(fit_params) expected = np.array([np.nan, expected_std, expected_std, 8, 8, 0, 0, 17]) assert np.all((got[1:] - expected[1:]) ** 2 < 0.15 ** 2)
def it_does_not_return_reasons_if_requested(): im = np.zeros((100, 100)) psf = worker._psf_estimate(im, [[64, 64]], mea=17, return_reasons=False) assert psf.shape == (17, 17)
def it_returns_reason_by_default(): im = np.zeros((100, 100)) psf, reasons = worker._psf_estimate(im, [[64, 64]], mea=17) assert psf.shape == (17, 17) and reasons.shape == (1, 8)
def it_normalizes(): peaks, im, std = _make_image(0.0, 100) psf = worker._psf_estimate(im, peaks.locs, mea=17, return_reasons=False) assert utils.np_within(np.sum(psf), 1.0, 0.001)
def it_does_not_skip_contentions(): peaks, im = _make_image_n_locs([[64, 50], [64, 60]]) psf, reasons = worker._psf_estimate(im, peaks.locs, mea=17, return_reasons=True) for loc, reason in zip(peaks.locs, reasons): assert reason[worker.PSFEstimateMaskFields.skipped_too_crowded] == 0