def test_bg_correction_index(): qpi, path, dout = setup_test_data(num=2) path_out = drymass.convert(path_in=path, dir_out=dout, bg_data_amp=1, bg_data_pha=1) with qpimage.QPSeries(h5file=path_out, h5mode="r") as qps: # background correction with same input image will result # in a flat QPImage. assert np.all(qps[0].pha == 0) assert np.all(qps[0].amp == 1) # To be absolutely sure this works, append a blank # QPImage and do it again. with qpimage.QPSeries(h5file=path, h5mode="a") as qps: pha = .5 * np.ones(qps[0].shape) amp = .9 * np.ones(qps[0].shape) qps.add_qpimage( qpimage.QPImage(data=(pha, amp), which_data="phase,amplitude")) path_out = drymass.convert(path_in=path, dir_out=dout, bg_data_amp=3, bg_data_pha=3) with qpimage.QPSeries(h5file=path_out, h5mode="r") as qps: # background correction with same input image will result # in a flat QPImage. assert np.allclose(qps[0].pha, qpi.pha - .5) assert np.allclose(qps[0].amp, qpi.amp / .9)
def test_exclude_roi(): _, path_in, path_out = setup_test_data(num=2) cli_extract_roi(path=path_in) cfg = config.ConfigFile(path_out) h5data = cli_extract_roi(path=path_in, ret_data=True) with qpimage.QPSeries(h5file=h5data) as qps: assert len(qps) == 2 # remove first image cfg.set_value(section="roi", key="ignore data", value="1.1") h5data = cli_extract_roi(path=path_in, ret_data=True) with qpimage.QPSeries(h5file=h5data) as qps: assert len(qps) == 1 # remove second image cfg.set_value(section="roi", key="ignore data", value="2") h5data = cli_extract_roi(path=path_in, ret_data=True) with qpimage.QPSeries(h5file=h5data) as qps: assert len(qps) == 1 # remove all cfg.set_value(section="roi", key="ignore data", value=["1", "2"]) h5data = cli_extract_roi(path=path_in, ret_data=True) with qpimage.QPSeries(h5file=h5data) as qps: assert len(qps) == 0
def test_identifier(): h5file = pathlib.Path(__file__).parent / "data" / "bg_tilt.h5" qpi = qpimage.QPImage(h5file=h5file, h5mode="r") series1 = qpimage.QPSeries(qpimage_list=[qpi, qpi, qpi], identifier="test_identifier") assert series1.identifier == "test_identifier" series2 = qpimage.QPSeries(qpimage_list=[qpi, qpi, qpi]) assert series2.identifier is None
def setup_test_data(radius=30, pxsize=1e-6, size=200, cx=80, cy=120, num=1, identifier=None, medium_index=1.335, wavelength=550e-9, bg=None): x = np.arange(size).reshape(-1, 1) y = np.arange(size).reshape(1, -1) r = np.sqrt((x - cx)**2 + (y - cy)**2) image = (r < radius) * 1.3 if bg is not None: image += bg qpi = qpimage.QPImage(data=image, which_data="phase", meta_data={ "pixel size": pxsize, "medium index": medium_index, "wavelength": wavelength }) path = tempfile.mktemp(suffix=".h5", prefix="drymass_test_roi") dout = tempfile.mkdtemp(prefix="drymass_test_roi_") with qpimage.QPSeries(h5file=path, identifier=identifier) as qps: for ii in range(num): qpid = "{}_test_{}".format(identifier, ii) qps.add_qpimage(qpi, identifier=qpid) return qpi, path, dout
def test_bg_corr_mask(): radius = 30 pxsize = 1e-6 size = 200 bg = np.zeros((size, size)) + .1 bg += np.linspace(-.3, .5, size).reshape(-1, 1) _, path, dout = setup_test_data(radius=radius, size=size, pxsize=pxsize, bg=bg) qpiref, p2, d2 = setup_test_data(radius=radius, size=size, pxsize=pxsize, bg=None) bg_pha_kw = { "fit_offset": "mean", "fit_profile": "tilt", "border_perc": 0, "border_px": 0 } path_out = drymass.extract_roi(path, dir_out=dout, size_m=2 * radius * pxsize, bg_pha_kw=bg_pha_kw, bg_pha_mask_radial_clearance=1.1) with qpimage.QPSeries(h5file=path_out, h5mode="r") as qpso: assert np.allclose(np.min(qpso[0].pha), 0, atol=4e-9, rtol=0) assert np.allclose(np.max(qpso[0].pha), np.max(qpiref.pha), atol=1.1e-7, rtol=0)
def setup_test_data(radius_px=30, size=200, pxsize=1e-6, medium_index=1.335, wavelength=550e-9, num=1): x = np.arange(size).reshape(-1, 1) y = np.arange(size).reshape(1, -1) cx = 80 cy = 120 r = np.sqrt((x - cx)**2 + (y - cy)**2) pha = (r < radius_px) * 1.3 amp = .5 + np.roll(pha, 10) / pha.max() qpi = qpimage.QPImage(data=(pha, amp), which_data="phase,amplitude", meta_data={"pixel size": pxsize, "medium index": medium_index, "wavelength": wavelength}) path_in = tempfile.mktemp(suffix=".h5", prefix="drymass_test_cli_sphere") path_in = pathlib.Path(path_in) with qpimage.QPSeries(h5file=path_in, h5mode="w", identifier="tt") as qps: for ii in range(num): qps.add_qpimage(qpi, identifier="image_{}".format(ii)) # add drymass configuration file path_out = path_in.with_name(path_in.name + dialog.OUTPUT_SUFFIX) path_out.mkdir() cfg = config.ConfigFile(path_out) cfg.set_value(section="meta", key="pixel size um", value=pxsize*1e6) cfg.set_value(section="meta", key="wavelength nm", value=wavelength*1e9) cfg.set_value(section="meta", key="medium index", value=medium_index) cfg.set_value(section="specimen", key="size um", value=radius_px*2*pxsize*1e6) cfg.set_value(section="sphere", key="method", value="edge") cfg.set_value(section="sphere", key="model", value="projection") return qpi, path_in, path_out
def setup_test_data(radius_px=30, size=200, pxsize=1e-6, medium_index=1.335, wavelength=550e-9, num=1): x = np.arange(size).reshape(-1, 1) y = np.arange(size).reshape(1, -1) cx = 80 cy = 120 r = np.sqrt((x - cx)**2 + (y - cy)**2) image = (r < radius_px) * 1.3 qpi = qpimage.QPImage(data=image, which_data="phase", meta_data={ "pixel size": pxsize, "medium index": medium_index, "wavelength": wavelength }) path = tempfile.mktemp(suffix=".h5", prefix="drymass_test_sphere") dout = tempfile.mkdtemp(prefix="drymass_test_sphere_") identifier = "abcdef:123456:a1b2c3" with qpimage.QPSeries(h5file=path, identifier=identifier) as qps: for ii in range(num): qps.add_qpimage(qpi, identifier="test_{}".format(ii)) return qpi, path, dout
def setup_test_data(radius_px=30, size=200, pxsize=1e-6, medium_index=1.335, wavelength=550e-9, num=1): x = np.arange(size).reshape(-1, 1) y = np.arange(size).reshape(1, -1) cx = 80 cy = 120 r = np.sqrt((x - cx)**2 + (y - cy)**2) pha = (r < radius_px) * 1.3 amp = .5 + np.roll(pha, 10) / pha.max() qpi = qpimage.QPImage(data=(pha, amp), which_data="phase,amplitude", meta_data={ "pixel size": pxsize, "medium index": medium_index, "wavelength": wavelength }) path = tempfile.mktemp(suffix=".h5", prefix="drymass_test_convert") dout = tempfile.mkdtemp(prefix="drymass_test_sphere_") with qpimage.QPSeries(h5file=path, h5mode="w") as qps: for ii in range(num): qps.add_qpimage(qpi, identifier="test_{}".format(ii)) return qpi, path, dout
def test_bg_correction_none_bad(): _qpi, path, dout = setup_test_data(num=2) path_out = drymass.convert(path_in=path, dir_out=dout, bg_data_amp=1) with qpimage.QPSeries(h5file=path_out, h5mode="r") as qps: # background correction with same input image will result # in a flat QPImage. assert not np.all(qps[0].pha == 0) assert np.all(qps[0].amp == 1) path_out = drymass.convert(path_in=path, dir_out=dout, bg_data_pha=1) with qpimage.QPSeries(h5file=path_out, h5mode="r") as qps: # background correction with same input image will result # in a flat QPImage. assert np.all(qps[0].pha == 0) assert not np.all(qps[0].amp == 1)
def test_exclude_roi_bad(): _, path_in, path_out = setup_test_data(num=2) cli_extract_roi(path=path_in) cfg = config.ConfigFile(path_out) h5data = cli_extract_roi(path=path_in, ret_data=True) with qpimage.QPSeries(h5file=h5data) as qps: assert len(qps) == 2 # bad image cfg.set_value(section="roi", key="ignore data", value="3") try: cli_extract_roi(path=path_in, ret_data=True) except ValueError: pass else: assert False # bad roi cfg.set_value(section="roi", key="ignore data", value="1.2") try: cli_extract_roi(path=path_in, ret_data=True) except ValueError: pass else: assert False # bad image and roi cfg.set_value(section="roi", key="ignore data", value="4.2") try: cli_extract_roi(path=path_in, ret_data=True) except ValueError: pass else: assert False
def test_base(): qpi, path_in, path_out = setup_test_data(num=2) h5data = cli_convert(path=path_in, ret_data=True) with qpimage.QPSeries(h5file=h5data, h5mode="r") as qps: assert np.allclose(qpi.pha, qps[0].pha) assert np.allclose(qpi.amp, qps[0].amp)
def test_getitem_identifier(): size = 20 pha = np.repeat(np.linspace(0, 10, size), size) pha = pha.reshape(size, size) qpi1 = qpimage.QPImage(data=1.1 * pha, which_data="phase", meta_data={"identifier": "peter"}) qpi2 = qpimage.QPImage(data=1.2 * pha, which_data="phase", meta_data={"identifier": "hans"}) qpi3 = qpimage.QPImage(data=1.3 * pha, which_data="phase", meta_data={"identifier": "doe"}) series = qpimage.QPSeries(qpimage_list=[qpi1, qpi2, qpi3]) assert "peter" in series assert "peter_bad" not in series assert series["peter"] == qpi1 assert series["peter"] != qpi2 assert series["hans"] == qpi2 assert series["doe"] == qpi3 try: series["john"] except KeyError: pass else: assert False, "'john' is not in series" try: series.add_qpimage(qpi1) except ValueError: pass else: assert False, "Adding QPImage with same identifier should not work"
def test_getitem(): size = 20 pha = np.repeat(np.linspace(0, 10, size), size) pha = pha.reshape(size, size) qpi1 = qpimage.QPImage(data=1.1 * pha, which_data="phase") qpi2 = qpimage.QPImage(data=1.2 * pha, which_data="phase") qpi3 = qpimage.QPImage(data=1.3 * pha, which_data="phase") series = qpimage.QPSeries(qpimage_list=[qpi1, qpi2, qpi3]) assert qpi1 != qpi2 assert qpi1 != qpi3 assert series[0] == qpi1 assert series[1] == qpi2 assert series[2] == qpi3 assert series[-3] == qpi1 assert series[-2] == qpi2 assert series[-1] == qpi3 try: series[-4] except ValueError: pass else: assert False, "Negative index exceeds size."
def test_convert_with_profile(): cfgpath = setup_config(pxsize=1.34e-6, medium_index=1.346, wavelength=554.2e-9) _, path_in, path_out = setup_test_data() argsadd = argparse.Namespace(subparser_name="add", name="test_8440_prof_convert", path=cfgpath) profile.cli_profile(args=argsadd) try: # perform conversion h5data = cli_convert(path=path_in, ret_data=True, profile="test_8440_prof_convert") cfg = config.ConfigFile(path_out) assert np.allclose(cfg["meta"]["medium index"], 1.346) assert np.allclose(cfg["meta"]["pixel size um"], 1.34) assert np.allclose(cfg["meta"]["wavelength nm"], 554.2) with qpimage.QPSeries(h5file=h5data, h5mode="r") as qps: assert np.allclose(qps[0]["medium index"], 1.346) assert np.allclose(qps[0]["pixel size"], 1.34e-6) assert np.allclose(qps[0]["wavelength"], 554.2e-9) except BaseException: raise finally: # cleanup argsrem = argparse.Namespace(subparser_name="remove", name="test_8440_prof_convert") profile.cli_profile(args=argsrem)
def test_iter(): h5file = pathlib.Path(__file__).parent / "data" / "bg_tilt.h5" qpi = qpimage.QPImage(h5file=h5file, h5mode="r") series = qpimage.QPSeries(qpimage_list=[qpi, qpi, qpi]) for qpj in series: assert qpj == qpi
def test_series_meta(): h5file = pathlib.Path(__file__).parent / "data" / "bg_tilt.h5" try: qpimage.QPImage(h5file=h5file, meta_data={"wavelength": 333e-9}, h5mode="r") except OSError: # no write intent on file pass else: assert False, "should not be able to write" qpi0 = qpimage.QPImage(h5file=h5file, h5mode="r") tf = tempfile.mktemp(suffix=".h5", prefix="qpimage_test_") tf = pathlib.Path(tf) with qpi0.copy(h5file=tf): pass qpi1 = qpimage.QPImage(h5file=tf, meta_data={"wavelength": 335e-9}) assert qpi1.meta["wavelength"] == 335e-9 qps = qpimage.QPSeries(qpimage_list=[qpi1], meta_data={ "wavelength": 400e-9}) assert qps.get_qpimage(0).meta["wavelength"] == 400e-9 # cleanup try: tf.unlink() except OSError: pass
def test_series_error_noqpimage(): try: qpimage.QPSeries(qpimage_list=["hans", 1]) except ValueError: pass else: assert False, "qpimage list must contain QPImages"
def test_change_wavelength(): _qpi, path, dout = setup_test_data() path_out = drymass.convert(path_in=path, dir_out=dout, meta_data={"wavelength": 500e-9}) with qpimage.QPSeries(h5file=path_out, h5mode="r") as qpso: id1 = qpso.identifier path_out2 = drymass.convert(path_in=path, dir_out=dout, meta_data={"wavelength": 333e-9}) with qpimage.QPSeries(h5file=path_out2, h5mode="r") as qpso: id2 = qpso.identifier assert id1 != id2, "Files should have different identifiers"
def test_series_from_list(): h5file = pathlib.Path(__file__).parent / "data" / "bg_tilt.h5" qpi1 = qpimage.QPImage(h5file=h5file, h5mode="r") qpi2 = qpi1.copy() qps = qpimage.QPSeries(qpimage_list=[qpi1, qpi2]) assert len(qps) == 2 assert qps.get_qpimage(0) == qps.get_qpimage(1)
def test_series_from_h5file(): h5file = pathlib.Path(__file__).parent / "data" / "bg_tilt.h5" qpi1 = qpimage.QPImage(h5file=h5file, h5mode="r") qpi2 = qpi1.copy() tf = tempfile.mktemp(suffix=".h5", prefix="qpimage_test_") with qpimage.QPSeries(qpimage_list=[qpi1, qpi2], h5file=tf, h5mode="a"): pass qps2 = qpimage.QPSeries(h5file=tf, h5mode="r") assert len(qps2) == 2 assert qps2.get_qpimage(0) == qpi1 # cleanup try: os.remove(tf) except OSError: pass
def test_series_h5file(): tf = tempfile.mktemp(suffix=".h5", prefix="qpimage_test_") with h5py.File(tf, mode="a") as fd: qps = qpimage.QPSeries(h5file=fd) assert len(qps) == 0 # cleanup try: os.remove(tf) except OSError: pass
def test_h5file_confusion(): # make up temporary series file seriesfile = tempfile.mktemp(suffix=".h5", prefix="test_qpimage_series_") try: # h5file should be specified with its corresponding parameter qpimage.QPSeries(seriesfile) except ValueError: pass else: assert False, "h5file must be given as kwarg!"
def test_bg_corr_index(): _qpi, path_in, path_out = setup_test_data(num=2) cfg = config.ConfigFile(path_out) cfg.set_value(section="bg", key="phase data", value=1) cfg.set_value(section="bg", key="amplitude data", value=1) h5data = cli_convert(path=path_in, ret_data=True) with qpimage.QPSeries(h5file=h5data, h5mode="r") as qps: assert np.all(qps[0].pha == 0) assert np.all(qps[0].amp == 1)
def test_force_roi(): qpi, path_in, path_out = setup_test_data(num=2) cfg = config.ConfigFile(path_out) cfg.set_value(section="meta", key="pixel size um", value=1) cfg.set_value(section="roi", key="force", value=((10, 160), (24, 178))) h5data = cli_extract_roi(path=path_in, ret_data=True) with qpimage.QPSeries(h5file=h5data) as qps: assert qps[0].shape == (150, 154) assert np.allclose(qpi.pha[10:160, 24:178], qps[0].pha) assert np.all(qps[0].pha == qps[1].pha)
def test_simple_qpseries(): path = setup_test_data_recursive(n=2, num=3) ps = dialog.recursive_search(path) assert len(ps) == 2 # make sure files are the right ones for ii in range(len(ps)): with qpimage.QPSeries(h5file=ps[ii], h5mode="r") as qps: assert len(qps) == 3
def test_basic(): qpi, path, dout = setup_test_data(num=2) path_out = drymass.analyze_sphere(path, dir_out=dout) with qpimage.QPSeries(h5file=path_out, h5mode="r") as qpso: assert qpso[0].shape == qpi.shape assert qpso[0]["wavelength"] == qpi["wavelength"] assert qpso[0]["pixel size"] == qpi["pixel size"] assert qpso[0]["medium index"] == qpi["medium index"] assert qpso[0]["identifier"].count("projection")
def test_qpseries_with_bad_data(): path = setup_test_data_recursive(n=2, num=3) (path / "bad_data.h5").write_text("This file should be ignored.") ps = dialog.recursive_search(path) assert len(ps) == 2 # make sure files are the right ones for ii in range(len(ps)): with qpimage.QPSeries(h5file=ps[ii], h5mode="r") as qps: assert len(qps) == 3
def is_series_file(path): """Return True if `path` is a qpimage.QPSeries file with identifier""" valid = False if pathlib.Path(path).exists(): try: with qpimage.QPSeries(h5file=path, h5mode="r") as qps: if len(qps) and qps.identifier is not None: valid = True except (IOError, OSError): # corrupt file pass return valid
def test_identifier_qpimage(): size = 20 pha = np.repeat(np.linspace(0, 10, size), size) pha = pha.reshape(size, size) qpi1 = qpimage.QPImage(data=1.1 * pha, which_data="phase") qpi2 = qpimage.QPImage(data=1.2 * pha, which_data="phase") qpi3 = qpimage.QPImage(data=1.3 * pha, which_data="phase") series = qpimage.QPSeries(qpimage_list=[qpi1, qpi2]) series.add_qpimage(qpi=qpi3, identifier="hastalavista") assert series[2]["identifier"] == "hastalavista"
def test_series_error_key(): h5file = pathlib.Path(__file__).parent / "data" / "bg_tilt.h5" qpi1 = qpimage.QPImage(h5file=h5file, h5mode="r") qpi2 = qpi1.copy() qps = qpimage.QPSeries(qpimage_list=[qpi1, qpi2]) try: qps.get_qpimage(2) except KeyError: pass else: assert False, "get index 2 when length is 2"