def on_mouse_release(self, event): # Get the visible datasets if event.button == 1 and self.mode is not None: visible_data, visual = self.get_visible_data() data = self.get_map_data() if len(self.line_pos) == 0: self.lasso_reset() return elif self.mode is 'lasso': selection_path = path.Path(self.line_pos, closed=True) mask = selection_path.contains_points(data) elif self.mode is 'ellipse': xmin, ymin = np.min(self.line_pos[:, 0]), np.min(self.line_pos[:, 1]) xmax, ymax = np.max(self.line_pos[:, 0]), np.max(self.line_pos[:, 1]) c = CircularROI((xmax + xmin) / 2., (ymax + ymin) / 2., (xmax - xmin) / 2.) # (xc, yc, radius) mask = c.contains(data[:, 0], data[:, 1]) elif self.mode is 'rectangle': xmin, ymin = np.min(self.line_pos[:, 0]), np.min(self.line_pos[:, 1]) xmax, ymax = np.max(self.line_pos[:, 0]), np.max(self.line_pos[:, 1]) r = RectangularROI(xmin, xmax, ymin, ymax) mask = r.contains(data[:, 0], data[:, 1]) else: raise ValueError("Unknown mode: {0}".format(self.mode)) self.mark_selected(mask, visible_data) self.lasso_reset()
def on_mouse_release(self, event): """ Get the mask of selected data and get them highlighted. :param event: """ # Get the visible datasets if event.button == 1 and self.mode and self.mode is not 'point': visible_data, visual = self.get_visible_data() data = self.get_map_data() if len(self.line_pos) == 0: self.lasso_reset() return elif self.mode is 'lasso': # Note, we use points_inside_poly here instead of calling e.g. # matplotlib directly, because we include some optimizations # in points_inside_poly vx, vy = np.array(self.line_pos).transpose() x, y = data.transpose() mask = points_inside_poly(x, y, vx, vy) elif self.mode is 'ellipse': xmin, ymin = np.min(self.line_pos[:, 0]), \ np.min(self.line_pos[:, 1]) xmax, ymax = np.max(self.line_pos[:, 0]), \ np.max(self.line_pos[:, 1]) # (xc, yc, radius) c = CircularROI((xmax+xmin)/2., (ymax+ymin)/2., (xmax-xmin)/2.) mask = c.contains(data[:, 0], data[:, 1]) elif self.mode is 'rectangle': xmin, ymin = np.min(self.line_pos[:, 0]), \ np.min(self.line_pos[:, 1]) xmax, ymax = np.max(self.line_pos[:, 0]), \ np.max(self.line_pos[:, 1]) r = RectangularROI(xmin, xmax, ymin, ymax) mask = r.contains(data[:, 0], data[:, 1]) else: raise ValueError("Unknown mode: {0}".format(self.mode)) # Mask matches transposed volume data set rather than the original one. # The ravel here is to make mask compatible with ElementSubsetState input. new_mask = np.reshape(mask, self.trans_ones_data.shape) new_mask = np.ravel(np.transpose(new_mask)) self.mark_selected(new_mask, self.visible_data) self.lasso_reset()
def update_selection(self, *args): if self.interact.brushing: return with self.viewer._output_widget: if self.interact.selected_x is not None and self.interact.selected_y is not None: x = self.interact.selected_x y = self.interact.selected_y # similar to https://github.com/glue-viz/glue/blob/b14ccffac6a5 # 271c2869ead9a562a2e66232e397/glue/core/roi.py#L1275-L1297 # We should now check if the radius in data coordinates is the same # along x and y, as if so then we can return a circle, otherwise we # should return an ellipse. xc = x.mean() yc = y.mean() rx = abs(x[1] - x[0]) / 2 ry = abs(y[1] - y[0]) / 2 # We use a tolerance of 1e-2 below to match the tolerance set in glue-core # https://github.com/glue-viz/glue/blob/6b968b352bc5ad68b95ad5e3bb25550782a69ee8/glue/viewers/matplotlib/state.py#L198 if np.allclose(rx, ry, rtol=1e-2): roi = CircularROI(xc=xc, yc=yc, radius=rx) else: roi = EllipticalROI(xc=xc, yc=yc, radius_x=rx, radius_y=ry) self.viewer.apply_roi(roi) if self.finalize_callback is not None: self.finalize_callback()
def on_selection(self, data, other=None): with self.output_widget: W = np.matrix(self.figure.matrix_world).reshape((4, 4)).T P = np.matrix(self.figure.matrix_projection).reshape((4, 4)).T M = np.dot(P, W) if data['device']: if data['type'] == 'lasso': region = data['device'] vx, vy = zip(*region) roi_2d = PolygonalROI(vx=vx, vy=vy) elif data['type'] == 'circle': x1, y1 = data['device']['begin'] x2, y2 = data['device']['end'] dx = x2 - x1 dy = y2 - y1 r = (dx**2 + dy**2)**0.5 roi_2d = CircularROI(xc=x1, yc=y1, radius=r) elif data['type'] == 'rectangle': x1, y1 = data['device']['begin'] x2, y2 = data['device']['end'] x = [x1, x2] y = [y1, y2] roi_2d = RectangularROI(xmin=min(x), xmax=max(x), ymin=min(y), ymax=max(y)) roi = Projected3dROI(roi_2d, M) self.apply_roi(roi)
def release(self, event): if event.button == 1: if self.radius > 0: c = CircularROI(self.center[0], self.center[1], self.radius) mask_dict = {} self.set_progress(0) for layer_artist in self.iter_data_layer_artists(): def selection(x, y): return c.contains(x, y) mask = get_mask_for_layer_artist(layer_artist, self.viewer, selection, progress=self.set_progress) mask_dict[layer_artist.layer] = mask self.mark_selected_dict(mask_dict) self.set_progress(-1) self.reset()
def reg_to_roi(reg): """ Function to convert a region to an ROI This might be implementable as a dictionary/registry, but hard-coding it isn't more difficult... """ if isinstance(reg, regions.CirclePixelRegion): return CircularROI(xc=reg.center.x, yc=reg.center.y, radius=reg.radius) elif isinstance(reg, regions.PointPixelRegion): return PointROI(x=reg.center.x, y=reg.center.y) elif isinstance(reg, regions.RectanglePixelRegion): if reg.angle == 0: xmin, xmax = reg.center.x - reg.width / 2, reg.center.x + reg.width / 2 ymin, ymax = reg.center.y - reg.height / 2, reg.center.y + reg.height / 2 return RectangularROI(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax) else: if hasattr(reg, 'corners'): xverts = [c[0] for c in reg.corners] yverts = [c[1] for c in reg.corners] return PolygonalROI(vx=xverts, vy=yverts) else: raise NotImplementedError("Rectangles need to convert to polygons.") elif isinstance(reg, regions.PolygonPixelRegion): return PolygonalROI(vx=reg.vertices.x, vy=reg.vertices.y) else: raise NotImplementedError("Region {0} not recognized".format(reg))
def setup(self): self.data_collection, self.viewer = get_data_collection_and_viewer() load_wcs_data(self.data_collection) self.viewer.add_data(self.data_collection[0]) self.viewer.add_data(self.data_collection[1]) roi = CircularROI(256, 256, 120) py1, px1 = self.data_collection[0].pixel_component_ids self.subset_state = RoiSubsetState(px1, py1, roi) self.viewer.register_to_hub(self.data_collection.hub)
def on_mouse_release(self, event): visible_data, visual = self.get_visible_data() # Get the visible datasets if event.button == 1 and self.mode is not None: visible_data, visual = self.get_visible_data() data = self.get_map_data() if len(self.line_pos) == 0: self.lasso_reset() return elif self.mode is 'lasso': # Note, we use points_inside_poly here instead of calling e.g. # matplotlib directly, because we include some optimizations # in points_inside_poly vx, vy = np.array(self.line_pos).transpose() x, y = data.transpose() mask = points_inside_poly(x, y, vx, vy) elif self.mode is 'ellipse': xmin, ymin = np.min(self.line_pos[:, 0]), np.min(self.line_pos[:, 1]) xmax, ymax = np.max(self.line_pos[:, 0]), np.max(self.line_pos[:, 1]) c = CircularROI((xmax + xmin) / 2., (ymax + ymin) / 2., (xmax - xmin) / 2.) # (xc, yc, radius) mask = c.contains(data[:, 0], data[:, 1]) elif self.mode is 'rectangle': xmin, ymin = np.min(self.line_pos[:, 0]), np.min(self.line_pos[:, 1]) xmax, ymax = np.max(self.line_pos[:, 0]), np.max(self.line_pos[:, 1]) r = RectangularROI(xmin, xmax, ymin, ymax) mask = r.contains(data[:, 0], data[:, 1]) else: raise ValueError("Unknown mode: {0}".format(self.mode)) # Mask matches transposed volume data set rather than the original one. # The ravel here is to make mask compatible with ElementSubsetState input. new_mask = np.reshape(mask, self.trans_ones_data.shape) new_mask = np.ravel(np.transpose(new_mask)) self.mark_selected(new_mask, visible_data) self.lasso_reset()
def release(self, event): if event.button == 1: if self.radius > 0: c = CircularROI(self.center[0], self.center[1], self.radius) indices_dict = {} for layer_artist in self.iter_data_layer_artists(): data = get_map_data(layer_artist, self.viewer) mask = c.contains(data[:, 0], data[:, 1]) shape_mask = np.reshape(mask, layer_artist.layer.shape[::-1]) shape_mask = np.ravel(np.transpose(shape_mask)) indices_dict[layer_artist.layer] = np.where(shape_mask)[0] self.mark_selected_dict(indices_dict) self.reset()
def release(self, event): if event.button == 1: if self.radius > 0: roi = Projected3dROI(roi_2d=CircularROI( self.center[0], self.center[1], self.radius), projection_matrix=self.projection_matrix) self.apply_roi(roi) self.reset() self.viewer.toolbar.active_tool = None
def on_selection(self, data, other=None): if data['type'] != self.selector: return if data['device']: with self.viewer.output_widget: x1, y1 = data['device']['begin'] x2, y2 = data['device']['end'] dx = x2 - x1 dy = y2 - y1 r = (dx**2 + dy**2)**0.5 roi_2d = CircularROI(xc=x1, yc=y1, radius=r) roi = Projected3dROI(roi_2d, self.projection_matrix) self.viewer.apply_roi(roi)
def test_circular_roi(self): subset_state = RoiSubsetState(self.data.pixel_component_ids[1], self.data.pixel_component_ids[0], CircularROI(1, 3.5, 0.75)) self.dc.new_subset_group(subset_state=subset_state, label='circular') reg = self.data.get_selection_definition(format='astropy-regions') assert isinstance(reg, CirclePixelRegion) assert_equal(reg.center.x, 1) assert_equal(reg.center.y, 3.5) assert_equal(reg.radius, 0.75)
def test_or_region(self): subset_state1 = RoiSubsetState(self.data.pixel_component_ids[1], self.data.pixel_component_ids[0], RectangularROI(1, 5, 2, 6)) subset_state2 = RoiSubsetState(self.data.pixel_component_ids[1], self.data.pixel_component_ids[0], CircularROI(4.75, 5.75, 0.5)) or_subset_state = OrState(subset_state1, subset_state2) self.dc.new_subset_group(subset_state=or_subset_state, label='orstate') reg = self.data.get_selection_definition(format='astropy-regions') assert isinstance(reg, CompoundPixelRegion) assert isinstance(reg.region1, RectanglePixelRegion) assert isinstance(reg.region2, CirclePixelRegion) assert reg.contains(PixCoord(4.5, 5.5)) assert reg.contains(PixCoord(3, 4)) assert reg.contains(PixCoord(5.1, 6.1)) assert not reg.contains(PixCoord(11, 12))
def update_selection(self, *args): if self.interact.brushing: return with self.viewer._output_widget: if self.interact.selected_x is not None and self.interact.selected_y is not None: x = self.interact.selected_x y = self.interact.selected_y # similar to https://github.com/glue-viz/glue/blob/b14ccffac6a5 # 271c2869ead9a562a2e66232e397/glue/core/roi.py#L1275-L1297 # We should now check if the radius in data coordinates is the same # along x and y, as if so then we can return a circle, otherwise we # should return an ellipse. xc = x.mean() yc = y.mean() rx = abs(x[1] - x[0])/2 ry = abs(y[1] - y[0])/2 if np.allclose(rx, ry): roi = CircularROI(xc=xc, yc=yc, radius=rx) else: roi = EllipticalROI(xc=xc, yc=yc, radius_x=rx, radius_y=ry) self.viewer.apply_roi(roi) if self.finalize_callback is not None: self.finalize_callback()
def test_invalid_combos(self): good_subset = RoiSubsetState(self.data.pixel_component_ids[1], self.data.pixel_component_ids[0], RectangularROI(1, 5, 2, 6)) bad_subset = RoiSubsetState(self.data.pixel_component_ids[1], self.data.main_components[0], CircularROI(4.75, 5.75, 0.5)) and_sub = AndState(good_subset, bad_subset) or_sub = OrState(good_subset, bad_subset) xor_sub = XorState(good_subset, bad_subset) multior = MultiOrState([good_subset, bad_subset]) self.dc.new_subset_group(subset_state=and_sub, label='and') self.dc.new_subset_group(subset_state=or_sub, label='or') self.dc.new_subset_group(subset_state=xor_sub, label='xor') self.dc.new_subset_group(subset_state=multior, label='multior') expected_error = 'Subset state yatt should be y pixel coordinate' with pytest.raises(ValueError) as exc: self.data.get_selection_definition(subset_id='and', format='astropy-regions') assert exc.value.args[0] == expected_error with pytest.raises(ValueError) as exc: self.data.get_selection_definition(subset_id='or', format='astropy-regions') assert exc.value.args[0] == expected_error with pytest.raises(ValueError) as exc: self.data.get_selection_definition(subset_id='xor', format='astropy-regions') assert exc.value.args[0] == expected_error with pytest.raises(ValueError) as exc: self.data.get_selection_definition(subset_id='multior', format='astropy-regions') assert exc.value.args[0] == expected_error
def test_datetime64_support(self, tmpdir): self.data.add_component(np.array([100, 200, 300, 400], dtype='M8[D]'), 't1') self.data.add_component(np.array([200, 300, 400, 500], dtype='M8[D]'), 't2') self.viewer.add_data(self.data) self.viewer.state.x_att = self.data.id['t1'] self.viewer.state.y_att = self.data.id['y'] # Matplotlib deals with dates by converting them to the number of days # since 01-01-0001, so we can check that the limits are correctly # converted (and not 100 to 400) assert self.viewer.axes.get_xlim() == (719248.0, 719578.0) assert self.viewer.axes.get_ylim() == (3.2 - 0.015, 3.5 + 0.015) # Apply an ROI selection in plotting coordinates roi = RectangularROI(xmin=719313, xmax=719513, ymin=3, ymax=4) self.viewer.apply_roi(roi) # Check that the two middle elements are selected assert_equal(self.data.subsets[0].to_mask(), [0, 1, 1, 0]) # Now do the same with the y axis self.viewer.state.y_att = self.data.id['t2'] assert self.viewer.axes.get_xlim() == (719248.0, 719578.0) assert self.viewer.axes.get_ylim() == (719348.0, 719678.0) # Apply an ROI selection in plotting coordinates edit = self.session.edit_subset_mode edit.edit_subset = [] roi = CircularROI(xc=719463, yc=719563, radius=200) self.viewer.apply_roi(roi) assert_equal(self.data.subsets[1].to_mask(), [0, 1, 1, 1]) # Make sure that the Qt labels look ok self.viewer.state.y_att = self.data.id['y'] options = self.viewer.options_widget().ui assert options.valuetext_x_min.text() == '1970-03-27' assert options.valuetext_x_max.text() == '1971-02-20' assert options.valuetext_y_min.text() == '3.185' assert options.valuetext_y_max.text() == '3.515' # Make sure that we can set the xmin/xmax to a string date assert_equal(self.viewer.state.x_min, np.datetime64('1970-03-27', 'D')) options.valuetext_x_min.setText('1970-04-14') options.valuetext_x_min.editingFinished.emit() assert self.viewer.axes.get_xlim() == (719266.0, 719578.0) assert_equal(self.viewer.state.x_min, np.datetime64('1970-04-14', 'D')) # Make sure that everything works fine after saving/reloading filename = tmpdir.join('test_datetime64.glu').strpath self.session.application.save_session(filename) with open(filename, 'r') as f: session = f.read() state = GlueUnSerializer.loads(session) ga = state.object('__main__') viewer = ga.viewers[0][0] options = viewer.options_widget().ui assert_equal(self.viewer.state.x_min, np.datetime64('1970-04-14', 'D')) assert options.valuetext_x_min.text() == '1970-04-14' assert options.valuetext_x_max.text() == '1971-02-20' assert options.valuetext_y_min.text() == '3.185' assert options.valuetext_y_max.text() == '3.515'