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))
示例#2
0
def test_roi3d(dataxyz):
    roi_2d = PolygonalROI(vx=[0.5, 2.5, 2.5, 0.5], vy=[1, 1, 3.5, 3.5])
    roi = Projected3dROI(roi_2d, projection_matrix=np.eye(4))
    assert roi.contains(dataxyz['x'], dataxyz['y']).tolist() == [True, True, False]

    roi_2d = PolygonalROI(vx=[1.5, 3.5, 3.5, 1.5], vy=[4, 4, 6.5, 6.5])
    roi = Projected3dROI(roi_2d, projection_matrix=xyzw2yxzw)
    assert roi.contains3d(dataxyz['x'], dataxyz['y'], dataxyz['z']).tolist() == [True, True, False]
示例#3
0
文件: view.py 项目: eteq/glue-jupyter
 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)
示例#4
0
    def apply_roi(self, roi):

        subset_state = RoiSubsetState()
        xroi, yroi = roi.to_polygon()
        x, y = self._get_plot_attributes()
        subset_state.xatt = x
        subset_state.yatt = y
        subset_state.roi = PolygonalROI(xroi, yroi)
        mode = EditSubsetMode()
        mode.update(self.data, subset_state, focus_data=self.display_data)
示例#5
0
    def setup(self):

        # Set up main 3-d dataset
        self.data = Data(values=np.random.random((512, 512, 512)))

        # Set up subset state which is a polygon defined in pixel space and
        # only covering a small fraction of the whole cube.
        self.polygonal_roi = PolygonalROI([440, 460, 450], [400, 455, 500])
        self.polygonal_subset_state = RoiSubsetState(xatt=self.data.pixel_component_ids[0],
                                                     yatt=self.data.pixel_component_ids[2],
                                                     roi=self.polygonal_roi)
示例#6
0
    def test_apply_roi_xlog(self):
        self.client.add_layer(self.data)
        self.client.set_component(self.data.id['x'])
        self.data.edit_subset = [self.data.subsets[0]]
        self.client.xlog = True
        roi = PolygonalROI(vx=[1, 2, 3], vy=[2, 3, 4])

        self.client.apply_roi(roi)
        state = self.data.subsets[0].subset_state
        assert isinstance(state, RangeSubsetState)
        np.testing.assert_allclose(state.lo, 7.3680629972807736)
        np.testing.assert_allclose(state.hi, 1000)
示例#7
0
    def on_selection(self, data, other=None):

        if data['type'] != self.selector:
            return

        if data['device']:
            with self.viewer.output_widget:
                region = data['device']
                vx, vy = zip(*region)
                roi_2d = PolygonalROI(vx=vx, vy=vy)
                roi = Projected3dROI(roi_2d, self.projection_matrix)
                self.viewer.apply_roi(roi)
    def release(self, event):

        if event.button == 1:

            if len(self.line_pos) > 0:
                vx, vy = np.array(self.line_pos).transpose()
                roi = Projected3dROI(roi_2d=PolygonalROI(vx, vy),
                                     projection_matrix=self.projection_matrix)
                self.apply_roi(roi)

            self.reset()

            self.viewer.toolbar.active_tool = None
示例#9
0
    def test_apply_roi(self):
        self.client.add_layer(self.data)
        self.client.set_component(self.data.id['y'])
        # bins are -7...-1

        self.data.edit_subset = [self.data.subsets[0]]
        roi = PolygonalROI(vx=[-5.1, -4.5, -3.2], vy=[2, 3, 4])

        self.client.apply_roi(roi)
        state = self.data.subsets[0].subset_state
        assert isinstance(state, RangeSubsetState)

        # range should expand to nearest bin edge
        assert state.lo == -6
        assert state.hi == -3
示例#10
0
文件: app.py 项目: pllim/glue-jupyter
    def subset_lasso2d(self, x_att, y_att, lasso_x, lasso_y):
        """
        Create a subset from a programmatic 2d lasso selection.

        Parameters
        ----------
        x_att : `~glue.core.component_id.ComponentID`
            The attribute corresponding to the x values being selected.
        y_att : `~glue.core.component_id.ComponentID`
            The attribute corresponding to the x values being selected.
        lasso_x : iterable
            The x values of the lasso.
        lasso_y : iterable
            The y values of the lasso.
        """
        roi = PolygonalROI(lasso_x, lasso_y)
        self.subset_roi([x_att, y_att], roi)
示例#11
0
    def test_polygonal_roi(self):

        xv = [1.3, 2, 3, 1.5, 0.5]
        yv = [10, 20.20, 30, 25, 17.17]

        subset_state = RoiSubsetState(self.data.pixel_component_ids[1],
                                      self.data.pixel_component_ids[0],
                                      PolygonalROI(xv, yv))

        self.dc.new_subset_group(subset_state=subset_state, label='polygon')

        reg = self.data.get_selection_definition(format='astropy-regions')

        assert isinstance(reg, PolygonPixelRegion)

        assert_array_equal(reg.vertices.x, xv)
        assert_array_equal(reg.vertices.y, yv)
示例#12
0
    def subset_from_roi(self,
                        att,
                        roi,
                        other_comp=None,
                        other_att=None,
                        coord='x'):
        """
        Create a SubsetState object from an ROI.

        This encapsulates the logic for creating subset states with Components.
        See the documentation for CategoricalComponents for caveats involved
        with mixed-type plots.

        :param att: attribute name of this Component
        :param roi: an ROI object
        :param other_comp: The other Component for 2D ROIs
        :param other_att: The attribute name of the other Component
        :param coord: The orientation of this Component
        :param is_nested: True if this was passed from another Component.
        :return: A SubsetState (or subclass) object
        """

        if coord not in ('x', 'y'):
            raise ValueError('coord should be one of x/y')

        other_coord = 'y' if coord == 'x' else 'x'

        if isinstance(roi, RangeROI):

            # The selection is either an x range or a y range

            if roi.ori == coord:

                # The selection applies to the current component
                lo, hi = roi.range()
                subset_state = RangeSubsetState(lo, hi, att)

            else:

                # The selection applies to the other component, so we delegate
                return other_comp.subset_from_roi(other_att,
                                                  roi,
                                                  other_comp=self,
                                                  other_att=att,
                                                  coord=other_coord)

        else:

            # The selection is polygon-like. Categorical components require
            # special care, so if the other component is categorical, we need to
            # delegate to CategoricalComponent.subset_from_roi.

            if isinstance(other_comp, CategoricalComponent):

                return other_comp.subset_from_roi(other_att,
                                                  roi,
                                                  other_comp=self,
                                                  other_att=att,
                                                  is_nested=True,
                                                  coord=other_coord)
            else:

                subset_state = RoiSubsetState()
                subset_state.xatt = att
                subset_state.yatt = other_att
                x, y = roi.to_polygon()
                subset_state.roi = PolygonalROI(x, y)

        return subset_state
示例#13
0
 def subset_lasso2d(self, x, y, xvalues, yvalues):
     roi = PolygonalROI(xvalues, yvalues)
     self.subset_roi([x, y], roi)
示例#14
0
def roi_to_subset_state(roi, x_att=None, y_att=None, x_comp=None, y_comp=None):
    """
    Given a 2D ROI and attributes on the x and y axis, determine the
    corresponding subset state.
    """

    if isinstance(roi, RangeROI):

        if roi.ori == 'x':
            att = x_att
            comp = x_comp
        else:
            att = y_att
            comp = y_comp

        if comp.categorical:
            return CategoricalROISubsetState.from_range(comp, att, roi.min, roi.max)
        else:
            return RangeSubsetState(roi.min, roi.max, att)

    elif x_comp.categorical or y_comp.categorical:

        if isinstance(roi, RectangularROI):

            # In this specific case, we can decompose the rectangular ROI into
            # two RangeROIs that are combined with an 'and' logical operation.

            range1 = XRangeROI(roi.xmin, roi.xmax)
            range2 = YRangeROI(roi.ymin, roi.ymax)

            subset1 = roi_to_subset_state(range1, x_att=x_att, x_comp=x_comp)
            subset2 = roi_to_subset_state(range2, y_att=y_att, y_comp=y_comp)

            return AndState(subset1, subset2)

        elif isinstance(roi, CategoricalROI):

            # The selection is categorical itself. We assume this is along the x axis

            return CategoricalROISubsetState(roi=roi, att=x_att)

        else:

            # The selection is polygon-like, which requires special care.

            if x_comp.categorical and y_comp.categorical:

                # For each category, we check which categories along the other
                # axis fall inside the polygon:

                selection = {}

                for code, label in enumerate(x_comp.categories):

                    # Determine the coordinates of the points to check
                    n_other = len(y_comp.categories)
                    y = np.arange(n_other)
                    x = np.repeat(code, n_other)

                    # Determine which points are in the polygon, and which
                    # categories these correspond to
                    in_poly = roi.contains(x, y)
                    categories = y_comp.categories[in_poly]

                    if len(categories) > 0:
                        selection[label] = set(categories)

                return CategoricalROISubsetState2D(selection, x_att, y_att)

            else:

                # If one of the components is not categorical, we treat this as
                # if each categorical component was mapped to a numerical value,
                # and at each value, we keep track of the polygon intersection
                # with the component. This will result in zero, one, or multiple
                # separate numerical ranges for each categorical value.

                # TODO: if we ever allow the category order to be changed, we
                # need to figure out how to update this!

                # We loop over each category and for each one we find the
                # numerical ranges

                selection = {}

                if x_comp.categorical:
                    cat_comp = x_comp
                    cat_att = x_att
                    num_att = y_att
                    x, y = roi.to_polygon()
                else:
                    cat_comp = y_comp
                    cat_att = y_att
                    num_att = x_att
                    y, x = roi.to_polygon()

                for code, label in enumerate(cat_comp.categories):

                    # We determine all the numerical segments that represent the
                    # ensemble of points in y that fall in the polygon
                    # TODO: profile the following function
                    segments = polygon_line_intersections(x, y, xval=code)

                    if len(segments) > 0:
                        selection[label] = segments

                return CategoricalMultiRangeSubsetState(selection, cat_att=cat_att, num_att=num_att)

    else:

        # The selection is polygon-like and components are numerical

        subset_state = RoiSubsetState()
        subset_state.xatt = x_att
        subset_state.yatt = y_att
        subset_state.roi = PolygonalROI(*roi.to_polygon())

        return subset_state