def test_save(): dclab.PolygonFilter.clear_all_filters() _fd, tf = tempfile.mkstemp(prefix="dclab_polgyon_test") with open(tf, "w") as fd: fd.write(filter_data) # Add polygon filter pf = dclab.PolygonFilter(filename=tf) _fd, tf2 = tempfile.mkstemp(prefix="dclab_polgyon_test") with open(tf2, "w") as fd: fd.write(filter_data) pf.save(tf2, ret_fobj=True) pf2 = dclab.PolygonFilter(filename=tf2) assert np.allclose(pf.points, pf2.points) _fd, tf3 = tempfile.mkstemp(prefix="dclab_polgyon_test") dclab.PolygonFilter.save_all(tf3) pf.save(tf3, ret_fobj=False) # ensure backwards compatibility: the names of the # three filters should be the same names = dclab.polygon_filter.get_polygon_filter_names() assert len(names) == 2 assert names.count(names[0]) == 2 try: os.remove(tf) os.remove(tf2) os.remove(tf3) except OSError: pass
def test_invert_saveload(): dclab.PolygonFilter.clear_all_filters() ddict = example_data_dict(size=1234, keys=["aspect", "tilt"]) # points of polygon filter points = [[np.min(ddict["aspect"]), np.min(ddict["tilt"])], [np.min(ddict["aspect"]), np.max(ddict["tilt"])], [np.average(ddict["aspect"]), np.max(ddict["tilt"])], [np.average(ddict["aspect"]), np.min(ddict["tilt"])], ] filt1 = dclab.PolygonFilter(axes=["aspect", "tilt"], points=points, inverted=True) name = tempfile.mktemp(prefix="test_dclab_polygon_") filt1.save(name) filt2 = dclab.PolygonFilter(filename=name) assert filt2 == filt1 filt3 = dclab.PolygonFilter(axes=["aspect", "tilt"], points=points, inverted=False) try: os.remove(name) except OSError: pass name = tempfile.mktemp(prefix="test_dclab_polygon_") filt3.save(name) filt4 = dclab.PolygonFilter(filename=name) assert filt4 == filt3 try: os.remove(name) except OSError: pass
def test_invert(): dclab.PolygonFilter.clear_all_filters() ddict = example_data_dict(size=1234, keys=["aspect", "tilt"]) ds = dclab.new_dataset(ddict) # points of polygon filter points = [[np.min(ddict["aspect"]), np.min(ddict["tilt"])], [np.min(ddict["aspect"]), np.max(ddict["tilt"])], [np.average(ddict["aspect"]), np.max(ddict["tilt"])], [np.average(ddict["aspect"]), np.min(ddict["tilt"])], ] filt1 = dclab.PolygonFilter(axes=["aspect", "tilt"], points=points, inverted=False) ds.polygon_filter_add(filt1) assert [0] == ds.config["filtering"]["polygon filters"] n1 = np.sum(ds.filter.all) ds.apply_filter() n2 = np.sum(ds.filter.all) assert n1 != n2 filt2 = dclab.PolygonFilter(axes=["aspect", "tilt"], points=points, inverted=True) ds.polygon_filter_add(filt2) assert [0, 1] == ds.config["filtering"]["polygon filters"] ds.apply_filter() assert np.sum(ds.filter.all) == 0, "inverted+normal filter filters all" dclab.PolygonFilter.clear_all_filters()
def test_save_all_polygon_filters_issue_101(): pl = make_pipeline() # add a polygon filter ds = pl.get_dataset(0) pf1 = dclab.PolygonFilter( axes=("deform", "area_um"), points=[ [ds["deform"].min(), ds["area_um"].min()], [ds["deform"].min(), ds["area_um"].mean()], [ds["deform"].mean(), ds["area_um"].mean()], ], name="Triangle of Minimum", ) pf2_state = dclab.PolygonFilter( axes=("deform", "area_um"), points=[ [ds["deform"].max(), ds["area_um"].max()], [ds["deform"].max(), ds["area_um"].mean()], [ds["deform"].mean(), ds["area_um"].mean()], ], name="Triangle of Maximum", ).__getstate__() pl.filters[0].polylist.append(pf1.unique_id) old_state = pl.__getstate__() tempdir = pathlib.Path(tempfile.mkdtemp(prefix="test_shapeout2_session_")) spath = tempdir / "session.so2" session.save_session(spath, pl) assert len(dclab.PolygonFilter.instances) == 2 session.clear_session(pl) assert len(dclab.PolygonFilter.instances) == 0 # currently, there may only be one pipeline session.open_session(spath, pl) new_state = pl.__getstate__() # This is the actual test for issue #101 assert len(dclab.PolygonFilter.instances) == 2 # This is a sanity check assert equal_state(old_state, new_state) # This is another sanity check pf2_id = pf2_state["identifier"] assert equal_state( pf2_state, dclab.PolygonFilter.get_instance_from_id(pf2_id).__getstate__())
def test_unique_id(): dclab.PolygonFilter.clear_all_filters() _fd, tf = tempfile.mkstemp(prefix="dclab_polgyon_test") with open(tf, "w") as fd: fd.write(filter_data) # Add polygon filter pf = dclab.PolygonFilter(filename=tf, unique_id=2) pf2 = dclab.PolygonFilter(filename=tf, unique_id=2) assert pf.unique_id != pf2.unique_id dclab.PolygonFilter.clear_all_filters() try: os.remove(tf) except OSError: pass
def test_polygon_filter_basic(qtbot): path = data_path / "calibration_beads_47.rtdc" with dclab.new_dataset(path) as ds: pf1 = dclab.PolygonFilter( axes=("deform", "area_um"), points=[ [ds["deform"].min(), ds["area_um"].min()], [ds["deform"].min(), ds["area_um"].mean()], [ds["deform"].mean(), ds["area_um"].mean()], ], name="Triangle of Death", ) mw = ShapeOut2() qtbot.addWidget(mw) # add the file mw.add_dataslot(paths=[path]) # enable the filter slot_id = mw.pipeline.slot_ids[0] filt_id = mw.pipeline.filter_ids[0] em = mw.block_matrix.get_widget(slot_id, filt_id) qtbot.mouseClick(em, QtCore.Qt.LeftButton) # did that work? assert mw.pipeline.is_element_active(slot_id, filt_id) assert len(mw.pipeline.slot_ids) == 1, "we added that" assert len(mw.pipeline.filter_ids) == 1, "automatically added" # open the filter edit in the Analysis View fe = mw.block_matrix.get_widget(filt_plot_id=mw.pipeline.filter_ids[0]) qtbot.mouseClick(fe.toolButton_modify, QtCore.Qt.LeftButton) # enable the polygon filter wf = mw.widget_ana_view.widget_filter filter_ids = list(wf._polygon_checkboxes.keys()) # sanity check assert filter_ids == [pf1.unique_id] wf._polygon_checkboxes[pf1.unique_id].setChecked(True) assert wf._polygon_checkboxes[pf1.unique_id].isChecked() # click apply qtbot.mouseClick(wf.pushButton_apply, QtCore.Qt.LeftButton) # check the filter assert pf1.unique_id in mw.pipeline.filters[0].polylist # get the dataset assert len(mw.pipeline.slots) == 1 assert len(mw.pipeline.filters) == 1 ds_slot = mw.pipeline.slots[0].get_dataset() ds = mw.pipeline.get_dataset(0) assert ds_slot is not ds assert np.sum(ds.filter.all) == 5 assert len(ds) == 47
def test_save_multiple(): dclab.PolygonFilter.clear_all_filters() _fd, tf = tempfile.mkstemp(prefix="dclab_polgyon_test") with open(tf, "w") as fd: fd.write(filter_data) # Add polygon filter pf = dclab.PolygonFilter(filename=tf) _fd, tf2 = tempfile.mkstemp(prefix="dclab_polgyon_test") with open(tf2, "a") as fd: pf.save(fd) pf2 = dclab.PolygonFilter(filename=tf2) assert np.allclose(pf.points, pf2.points) try: os.remove(tf) os.remove(tf2) except OSError: pass
def test_with_rtdc_data_set(): dclab.PolygonFilter.clear_all_filters() ddict = example_data_dict(size=821, keys=["aspect", "tilt"]) ds = dclab.new_dataset(ddict) # save polygon data _fd, tf = tempfile.mkstemp(prefix="dclab_polgyon_test") with open(tf, "w") as fd: fd.write(filter_data) pf = dclab.PolygonFilter(filename=tf) pf2 = dclab.PolygonFilter(filename=tf) ds.polygon_filter_add(pf) ds.polygon_filter_add(1) ds.polygon_filter_rm(0) ds.polygon_filter_rm(pf2) dclab.PolygonFilter.clear_all_filters() try: os.remove(tf) except OSError: pass
def on_poly_done(self): """User is done creating or modifying a polygon filter""" self.pushButton_poly_create.setEnabled(True) self.label_poly_create.setVisible(False) self.label_poly_modify.setVisible(False) self.pushButton_poly_save.setVisible(False) self.pushButton_poly_cancel.setVisible(False) self.pushButton_poly_delete.setVisible(False) if self.sender() == self.pushButton_poly_delete: # delete the polygon filter idp = self.comboBox_poly.currentData() if idp is not None: # There is a polygon filter that we want to delete self.polygon_filter_about_to_be_deleted.emit(idp) dclab.PolygonFilter.remove(idp) mode = "modify" else: mode = "none" elif self.sender() == self.pushButton_poly_save: # save the polygon filter points = self.widget_scatter.get_poly_points() name = self.lineEdit_poly.text() inverted = self.checkBox_poly.isChecked() axes = self.widget_scatter.xax, self.widget_scatter.yax # determine whether to create a new polygon filter or whether # to update an existing one. idp = self.comboBox_poly.currentData() if idp is None: dclab.PolygonFilter(axes=axes, points=points, name=name, inverted=inverted) mode = "create" else: pf = dclab.PolygonFilter.get_instance_from_id(idp) pf.name = name pf.inverted = inverted pf.points = points mode = "modify" else: mode = "none" # remove the PolyLineRoi self.widget_scatter.activate_scatter_mode() self.update_polygon_panel() if mode == "create": self.polygon_filter_created.emit() elif mode == "modify": self.polygon_filter_modified.emit()
def test_inverted_wrong(): dclab.PolygonFilter.clear_all_filters() ddict = example_data_dict(size=1234, keys=["aspect", "tilt"]) # points of polygon filter points = [[np.min(ddict["aspect"]), np.min(ddict["tilt"])], [np.min(ddict["aspect"]), np.max(ddict["tilt"])], [np.average(ddict["aspect"]), np.max(ddict["tilt"])], [np.average(ddict["aspect"]), np.min(ddict["tilt"])], ] try: dclab.PolygonFilter(axes=["aspect", "tilt"], points=points, inverted=0) except dclab.polygon_filter.PolygonFilterError: pass else: raise ValueError("inverted should only be allowed to be bool")
def test_remove(): dclab.PolygonFilter.clear_all_filters() _fd, tf = tempfile.mkstemp(prefix="dclab_polgyon_test") with open(tf, "w") as fd: fd.write(filter_data) # Add polygon filter pf = dclab.PolygonFilter(filename=tf) dclab.PolygonFilter.remove(pf.unique_id) assert len(dclab.PolygonFilter.instances) == 0 dclab.PolygonFilter.clear_all_filters() try: os.remove(tf) except OSError: pass
def import_filter_set(path, pipeline, strict=False): """Import a filter set See :func:`import_filters` """ if isinstance(path, io.IOBase): dump = path.read() else: dump = path.read_text() dump_state = json.loads(dump) # add polygon filters from file if not strict: pf_dict = {} # maps old to new identifiers for pstate in dump_state["polygon filters"]: pf = dclab.PolygonFilter(axes=(pstate["axis x"], pstate["axis y"]), points=pstate["points"]) pid = pstate["identifier"] if not strict: # keep track of old and new identifiers pf_dict[pid] = pf.unique_id if pid != pf.unique_id: if strict: if dclab.PolygonFilter.unique_id_exists(pid): raise ValueError("PolygonFilter with unique_id " + "{} already exists!".format(pid)) else: # change the unique_id to that of the original filter pf._set_unique_id(pid) else: # use the unique_id of the newly-created filter pstate["identifier"] = pf.unique_id pf.__setstate__(pstate) # add a new filter set for state in dump_state["filters"]: if strict: filt = Filter(identifier=state["identifier"]) else: filt = Filter() state["identifier"] = filt.identifier # transform original polygon filter ids newpids = [pf_dict[pid] for pid in state["polygon filters"]] state["polygon filters"] = newpids filt.__setstate__(state) pipeline.add_filter(filt=filt)
def test_wrong_load_key(): dclab.PolygonFilter.clear_all_filters() # save polygon data _fd, tf = tempfile.mkstemp(prefix="dclab_polgyon_test") with open(tf, "w") as fd: fd.write(filter_data + "peter=4\n") try: dclab.PolygonFilter(filename=tf) except KeyError: pass else: raise ValueError("_load should not accept unknown key!") dclab.PolygonFilter.clear_all_filters() try: os.remove(tf) except OSError: pass
def OnPolygonFilter(self, result): """ Called by polygon Window """ pf = dclab.PolygonFilter(points=result["points"], axes=result["axes"]) uid = pf.unique_id mcur = result["measurement"] # update list of polygon filters self.UpdatePages() # Determine the number of existing polygon filters npol = len(dclab.PolygonFilter.instances) if npol == 1 and mcur.format != "hierarchy": # apply to all measurements except hierarchy children for mm in self.analysis.measurements: if not mm.format == "hierarchy": mm.config["filtering"]["polygon filters"].append(uid) else: # apply only to this one data set mcur.config["filtering"]["polygon filters"].append(uid) self.OnChangeFilter()
def test_changed_polygon_filter(): ddict = example_data_dict(size=8472, keys=["area_um", "deform"]) ds = new_dataset(ddict) amin, amax = ds["area_um"].min(), ds["area_um"].max() dmin, dmax = ds["deform"].min(), ds["deform"].max() pf = dclab.PolygonFilter(axes=["area_um", "deform"], points=[[amin, dmin], [(amax + amin) / 2, dmin], [(amax + amin) / 2, dmax], ]) ds.config["filtering"]["polygon filters"].append(pf.unique_id) ds.apply_filter() assert np.sum(ds.filter.all) == 2138 # change the filter pf.points = list(pf.points) + [np.array([amin, dmax])] ds.apply_filter() assert np.sum(ds.filter.all) == 4215 # invert the filter pf.inverted = True ds.apply_filter() assert np.sum(ds.filter.all) == 4257
def test_polygon(): """ In versions before 0.7.6, polygons in dclab were exported with other column names. """ sdir, _path = extract_session("session_v0.6.0.zmso") pfile = op.join(sdir, "PolygonFilters.poly") # conversion outfile = conversion.convert_polygon( pfile, # pretend we don't know the version version=None, ) # load polygon file pf = dclab.PolygonFilter(filename=outfile) assert pf.axes == (u'area_um', u'deform') cleanup() try: outfile.unlink() except OSError: pass
def test_import(): dclab.PolygonFilter.clear_all_filters() ddict = example_data_dict(size=1000, keys=["aspect", "tilt"]) ds = dclab.new_dataset(ddict) # save polygon data _fd, tf = tempfile.mkstemp(prefix="dclab_polgyon_test") with open(tf, "w") as fd: fd.write(filter_data) # Add polygon filter pf = dclab.PolygonFilter(filename=tf) ds.polygon_filter_add(pf) ds.apply_filter() assert np.sum(ds.filter.all) == 330 dclab.PolygonFilter.import_all(tf) assert len(dclab.PolygonFilter.instances) == 2 # Import multiples b = filter_data b = b.replace("Polygon 00000000", "Polygon 00000001") with open(tf, "a") as fd: fd.write(b) dclab.PolygonFilter.import_all(tf) # Import previously saved dclab.PolygonFilter.save_all(tf) dclab.PolygonFilter.import_all(tf) assert len(dclab.PolygonFilter.instances) == 10 try: os.remove(tf) except OSError: pass
def test_state(): dclab.PolygonFilter.clear_all_filters() _fd, tf = tempfile.mkstemp(prefix="dclab_polgyon_test") with open(tf, "w") as fd: fd.write(filter_data) # Add polygon filter pf = dclab.PolygonFilter(filename=tf) state = pf.__getstate__() assert state["name"] == "polygon filter 0" assert state["axis x"] == "aspect" assert state["axis y"] == "tilt" assert np.allclose(state["points"][0][0], 6.344607717656481e-03) assert np.allclose(state["points"][3][1], 1.015706806282723e-03) assert not state["inverted"] state["name"] = "peter" state["axis x"] = "tilt" state["axis y"] = "aspect" state["points"][0][0] = 1 state["inverted"] = True pf.__setstate__(state) assert pf.name == "peter" assert pf.axes[0] == "tilt" assert pf.axes[1] == "aspect" assert np.allclose(pf.points[0, 0], 1) assert pf.inverted try: os.remove(tf) except OSError: pass
def test_polygon_filter_delete(qtbot): path = data_path / "calibration_beads_47.rtdc" with dclab.new_dataset(path) as ds: pf1 = dclab.PolygonFilter( axes=("deform", "area_um"), points=[ [ds["deform"].min(), ds["area_um"].min()], [ds["deform"].min(), ds["area_um"].mean()], [ds["deform"].mean(), ds["area_um"].mean()], ], name="Triangle of Death", ) mw = ShapeOut2() qtbot.addWidget(mw) # add the file mw.add_dataslot(paths=[path]) # enable the filter slot_id = mw.pipeline.slot_ids[0] filt_id = mw.pipeline.filter_ids[0] em = mw.block_matrix.get_widget(slot_id, filt_id) qtbot.mouseClick(em, QtCore.Qt.LeftButton) # did that work? assert mw.pipeline.is_element_active(slot_id, filt_id) assert len(mw.pipeline.slot_ids) == 1, "we added that" assert len(mw.pipeline.filter_ids) == 1, "automatically added" # open the filter edit in the Analysis View fe = mw.block_matrix.get_widget(filt_plot_id=mw.pipeline.filter_ids[0]) qtbot.mouseClick(fe.toolButton_modify, QtCore.Qt.LeftButton) # enable the polygon filter wf = mw.widget_ana_view.widget_filter filter_ids = list(wf._polygon_checkboxes.keys()) # sanity check assert filter_ids == [pf1.unique_id] wf._polygon_checkboxes[pf1.unique_id].setChecked(True) assert wf._polygon_checkboxes[pf1.unique_id].isChecked() # click apply qtbot.mouseClick(wf.pushButton_apply, QtCore.Qt.LeftButton) # check the filter assert pf1.unique_id in mw.pipeline.filters[0].polylist # now remove the filter em1 = mw.block_matrix.get_widget(slot_id, filt_id) qtbot.mouseClick(em1, QtCore.Qt.LeftButton, QtCore.Qt.ShiftModifier) qv = mw.widget_quick_view qtbot.mouseClick(qv.toolButton_poly, QtCore.Qt.LeftButton) qv.comboBox_poly.setCurrentIndex(1) QtWidgets.QApplication.processEvents(QEventLoop.AllEvents, 300) assert qv.pushButton_poly_save.isVisible() assert qv.pushButton_poly_cancel.isVisible() assert qv.pushButton_poly_delete.isVisible() qtbot.mouseClick(qv.pushButton_poly_delete, QtCore.Qt.LeftButton) assert not qv.pushButton_poly_delete.isVisible() # did that work? assert len(mw.pipeline.filters[0].polylist) == 0 # get the dataset assert len(mw.pipeline.slots) == 1 assert len(mw.pipeline.filters) == 1 ds = mw.pipeline.get_dataset(0) assert np.sum(ds.filter.all) == 47 assert len(ds) == 47
mw.widget_quick_view.toolButton_settings.toggle() idx = mw.widget_quick_view.comboBox_x.findData("fl3_max_ctc") mw.widget_quick_view.comboBox_x.setCurrentIndex(idx) idy = mw.widget_quick_view.comboBox_y.findData("fl2_max_ctc") mw.widget_quick_view.comboBox_y.setCurrentIndex(idy) mw.widget_quick_view.comboBox_xscale.setCurrentIndex(1) mw.widget_quick_view.comboBox_yscale.setCurrentIndex(1) QApplication.processEvents(QtCore.QEventLoop.AllEvents, 300) mw.widget_quick_view.grab().save("_ui_qv_settings.png") mw.widget_quick_view.toolButton_event.toggle() mw.widget_quick_view.spinBox_event.setValue(4829) QApplication.processEvents(QtCore.QEventLoop.AllEvents, 300) mw.widget_quick_view.grab().save("_ui_qv_event.png") # manually create a polygon filter with points from the poly file mw.widget_quick_view.toolButton_poly.toggle() pf = dclab.PolygonFilter(filename="CD66+_CD14-.poly") mw.widget_quick_view.pushButton_poly_create.click() mw.widget_quick_view.lineEdit_poly.setText("CD66⁺/CD14⁻") mw.widget_quick_view.widget_scatter.set_poly_points(pf.points) # show an even cellimg, imkw = mw.widget_quick_view.get_event_image( mw.widget_quick_view.rtdc_ds, 42) mw.widget_quick_view.imageView_image_poly.setImage(cellimg, **imkw) mw.widget_quick_view.imageView_image_poly.show() QApplication.processEvents(QtCore.QEventLoop.AllEvents, 300) mw.widget_quick_view.grab().save("_ui_qv_poly.png") # block matrix mw.block_matrix.setFixedSize(420, 320) mw.block_matrix.repaint() QApplication.processEvents(QtCore.QEventLoop.AllEvents, 300)
def test_nofile_copy(): dclab.PolygonFilter.clear_all_filters() a = dclab.PolygonFilter(axes=("tilt", "aspect"), points=[[0, 1], [1, 1]]) a.copy() dclab.PolygonFilter.clear_all_filters()