Пример #1
0
    def test_get_spectral_regions_raise_value_error(self):
        with pytest.raises(ValueError):
            spectrum_viewer = self.spec_app.app.get_viewer("spectrum-viewer")

            spectrum_viewer.session.edit_subset_mode._mode = OrMode
            # Selecting ROIs that are not part of the actual spectrum raises an error
            self.spec_app.app.get_viewer("spectrum-viewer").apply_roi(
                XRangeROI(1, 3))
            self.spec_app.app.get_viewer("spectrum-viewer").apply_roi(
                XRangeROI(4, 6))

            self.spec_app.get_spectral_regions()
Пример #2
0
    def test_get_spectral_regions_two(self):
        spectrum_viewer = self.spec_app.app.get_viewer("spectrum-viewer")

        # Set the active edit_subset_mode to OrMode to be able to add multiple subregions
        spectrum_viewer.session.edit_subset_mode._mode = OrMode
        self.spec_app.app.get_viewer("spectrum-viewer").apply_roi(
            XRangeROI(6000, 6500))
        self.spec_app.app.get_viewer("spectrum-viewer").apply_roi(
            XRangeROI(7300, 7800))

        spec_region = self.spec_app.get_spectral_regions()

        assert len(spec_region['Subset 1'].subregions) == 2
Пример #3
0
def test_region_from_subset_profile(jdaviz_app, spectral_cube_wcs):
    data = Data(flux=np.ones((256, 128, 128)),
                label='Test 1D Flux',
                coords=spectral_cube_wcs)
    jdaviz_app.data_collection.append(data)

    subset_state = RoiSubsetState(data.pixel_component_ids[1],
                                  data.pixel_component_ids[0],
                                  XRangeROI(1, 3.5))

    jdaviz_app.add_data_to_viewer('spectrum-viewer', 'Test 1D Flux')

    jdaviz_app.data_collection.new_subset_group(subset_state=subset_state,
                                                label='rectangular')

    subsets = jdaviz_app.get_subsets_from_viewer('spectrum-viewer')
    reg = subsets.get('rectangular')

    assert len(subsets) == 1
    assert isinstance(reg, RectanglePixelRegion)

    assert_allclose(reg.center.x, 2.25)
    assert_allclose(reg.center.y, 128)
    assert_allclose(reg.width, 2.5)
    assert_allclose(reg.height, 256)
Пример #4
0
def test_region_spectral_spatial(jdaviz_app, spectral_cube_wcs):
    data = Data(flux=np.ones((256, 128, 128)), label='Test Flux', coords=spectral_cube_wcs)
    jdaviz_app.data_collection.append(data)

    jdaviz_app.add_data_to_viewer('spectrum-viewer', 'Test Flux')
    jdaviz_app.add_data_to_viewer('flux-viewer', 'Test Flux')

    jdaviz_app.get_viewer("spectrum-viewer").apply_roi(XRangeROI(5, 15.5))

    flux_viewer = jdaviz_app.get_viewer("flux-viewer")
    # We set the active tool here to trigger a reset of the Subset state to "Create new"
    flux_viewer.toolbar.active_tool = flux_viewer.toolbar.tools['bqplot:rectangle']
    flux_viewer.apply_roi(RectangularROI(1, 3.5, -0.2, 3.3))

    subsets = jdaviz_app.get_subsets_from_viewer('spectrum-viewer', subset_type='spectral')
    reg = subsets.get('Subset 1')

    print(reg)

    assert len(subsets) == 1
    assert isinstance(reg, SpectralRegion)

    assert_quantity_allclose(reg.lower, 5.0 * u.Hz)
    assert_quantity_allclose(reg.upper, 14 * u.Hz)

    subsets = jdaviz_app.get_subsets_from_viewer('flux-viewer', subset_type='spatial')
    reg = subsets.get('Subset 2')

    assert len(subsets) == 1
    assert isinstance(reg, RectanglePixelRegion)
    assert_allclose(reg.center.x, 2.25)
    assert_allclose(reg.center.x, 2.25)
    assert_allclose(reg.center.y, 1.55)
    assert_allclose(reg.width, 2.5)
    assert_allclose(reg.height, 3.5)
Пример #5
0
def test_get_spectral_regions_unit_conversion(specviz_helper, spectrum1d):
    # If the reference (visible) data changes via unit conversion,
    # check that the region's units convert too
    specviz_helper.load_spectrum(spectrum1d)

    # Convert the wavelength axis to microns
    new_spectral_axis = "micron"
    conv_func = uc.UnitConversion.process_unit_conversion
    converted_spectrum = conv_func(specviz_helper.app,
                                   spectrum=spectrum1d,
                                   new_spectral_axis=new_spectral_axis)

    # Add this new data and clear the other, making the converted spectrum our reference
    specviz_helper.app.add_data(converted_spectrum, "Converted Spectrum")
    specviz_helper.app.add_data_to_viewer("spectrum-viewer",
                                          "Converted Spectrum",
                                          clear_other_data=True)

    specviz_helper.app.get_viewer("spectrum-viewer").apply_roi(
        XRangeROI(0.6, 0.7))

    # Retrieve the Subset
    subsets = specviz_helper.get_spectral_regions()
    reg = subsets.get('Subset 1')

    assert reg.lower.unit == u.Unit(new_spectral_axis)
    assert reg.upper.unit == u.Unit(new_spectral_axis)
Пример #6
0
    def test_apply_roi(self):

        # Check that when doing an ROI selection, the ROI clips to the bin edges
        # outside the selection

        viewer_state = self.viewer.state

        self.viewer.add_data(self.data)

        viewer_state.hist_x_min = -5
        viewer_state.hist_x_max = 5
        viewer_state.hist_n_bin = 4

        roi = XRangeROI(-0.2, 0.1)

        assert len(self.viewer.layers) == 1

        self.viewer.apply_roi(roi)

        assert len(self.viewer.layers) == 2

        assert_allclose(self.viewer.layers[0].mpl_hist, [0, 1, 2, 1])
        assert_allclose(self.viewer.layers[1].mpl_hist, [0, 1, 2, 0])

        assert_allclose(self.data.subsets[0].to_mask(), [0, 1, 1, 1])

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

        assert state.lo == -2.5
        assert state.hi == 2.5
Пример #7
0
    def test_apply_roi_categorical(self):

        # Check that when doing an ROI selection, the ROI clips to the bin edges
        # outside the selection

        viewer_state = self.viewer.state

        self.viewer.add_data(self.data)

        viewer_state.x_att = self.data.id['y']

        roi = XRangeROI(0.3, 0.9)

        assert len(self.viewer.layers) == 1

        self.viewer.apply_roi(roi)

        assert len(self.viewer.layers) == 2

        assert_allclose(self.viewer.layers[0].mpl_hist, [2, 1, 1])
        assert_allclose(self.viewer.layers[1].mpl_hist, [2, 1, 0])

        assert_allclose(self.data.subsets[0].to_mask(), [1, 1, 0, 1])

        state = self.data.subsets[0].subset_state
        assert isinstance(state, CategoricalROISubsetState)

        assert_equal(state.roi.categories, ['a', 'b'])
Пример #8
0
def test_get_spectral_regions_unit(specviz_app, spectrum1d):
    # Ensure units we put in are the same as the units we get out
    specviz_app.load_spectrum(spectrum1d)
    specviz_app.app.get_viewer("spectrum-viewer").apply_roi(XRangeROI(1, 3.5))

    subsets = specviz_app.get_spectral_regions()
    reg = subsets.get('Subset 1')

    assert spectrum1d.wavelength.unit == reg.lower.unit
    assert spectrum1d.wavelength.unit == reg.upper.unit
Пример #9
0
    def test_selection(self):

        self.viewer.add_data(self.data)

        self.viewer.state.x_att = self.data.pixel_component_ids[0]

        roi = XRangeROI(0.9, 2.1)

        self.viewer.apply_roi(roi)

        assert len(self.data.subsets) == 1
        assert_equal(self.data.subsets[0].to_mask()[:, 0, 0], [0, 1, 1])

        self.viewer.state.x_att = self.data.world_component_ids[0]

        roi = XRangeROI(1.9, 3.1)

        self.viewer.apply_roi(roi)

        assert len(self.data.subsets) == 1
        assert_equal(self.data.subsets[0].to_mask()[:, 0, 0], [0, 1, 0])
Пример #10
0
    def test_get_spectral_regions_three(self):
        spectrum_viewer = self.spec_app.app.get_viewer("spectrum-viewer")

        spectrum_viewer.session.edit_subset_mode._mode = OrMode
        self.spec_app.app.get_viewer("spectrum-viewer").apply_roi(
            XRangeROI(6000, 6400))
        self.spec_app.app.get_viewer("spectrum-viewer").apply_roi(
            XRangeROI(6600, 7000))
        self.spec_app.app.get_viewer("spectrum-viewer").apply_roi(
            XRangeROI(7300, 7800))

        spec_region = self.spec_app.get_spectral_regions()

        assert len(spec_region['Subset 1'].subregions) == 3
        # Assert correct values for test with 3 subregions
        assert_quantity_allclose(
            spec_region['Subset 1'].subregions[0][0].value, 6000., atol=1e-5)
        assert_quantity_allclose(
            spec_region['Subset 1'].subregions[0][1].value,
            6222.22222222,
            atol=1e-5)

        assert_quantity_allclose(
            spec_region['Subset 1'].subregions[1][0].value,
            6666.66666667,
            atol=1e-5)
        assert_quantity_allclose(
            spec_region['Subset 1'].subregions[1][1].value,
            6888.88888889,
            atol=1e-5)

        assert_quantity_allclose(
            spec_region['Subset 1'].subregions[2][0].value,
            7333.33333333,
            atol=1e-5)
        assert_quantity_allclose(
            spec_region['Subset 1'].subregions[2][1].value,
            7555.55555556,
            atol=1e-5)
Пример #11
0
    def test_datetime64_support(self, tmpdir):

        self.data.add_component(np.array([100, 200, 300, 400], dtype='M8[D]'),
                                't1')
        self.viewer.add_data(self.data)
        self.viewer.state.x_att = self.data.id['t1']

        wait_for_layers(self.viewer)

        # 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() == (719263.0, 719563.0)

        # Apply an ROI selection in plotting coordinates
        roi = XRangeROI(719313, 719513)
        self.viewer.apply_roi(roi)

        wait_for_layers(self.viewer)

        # Check that the two middle elements are selected
        assert_equal(self.data.subsets[0].to_mask(), [0, 1, 1, 0])

        # Make sure that the Qt labels look ok
        options = self.viewer.options_widget().ui
        assert options.valuetext_x_min.text() == '1970-04-11'
        assert options.valuetext_x_max.text() == '1971-02-05'

        # Make sure that we can set the xmin/xmax to a string date
        assert_equal(self.viewer.state.x_min, np.datetime64('1970-04-11', 'D'))
        options.valuetext_x_min.setText('1970-04-14')
        options.valuetext_x_min.editingFinished.emit()
        assert self.viewer.axes.get_xlim() == (719266.0, 719563.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

        wait_for_layers(viewer)

        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-05'
Пример #12
0
def test_disjoint_spectral_subset(jdaviz_app, spectral_cube_wcs):
    data = Data(flux=np.ones((256, 128, 128)), label='Test Flux', coords=spectral_cube_wcs)
    jdaviz_app.data_collection.append(data)

    jdaviz_app.add_data_to_viewer('spectrum-viewer', 'Test Flux')
    jdaviz_app.add_data_to_viewer('flux-viewer', 'Test Flux')

    spec_viewer = jdaviz_app.get_viewer("spectrum-viewer")
    spec_viewer.apply_roi(XRangeROI(5, 15.5))

    # Add second region to Subset 1
    jdaviz_app.session.edit_subset_mode.mode = OrMode
    spec_viewer.apply_roi(XRangeROI(30, 35))

    subsets = jdaviz_app.get_subsets_from_viewer('spectrum-viewer')
    reg = subsets.get('Subset 1')

    assert len(reg) == 2
    assert isinstance(reg, SpectralRegion)
    assert_quantity_allclose(reg[0].lower, 5.0*u.Hz)
    assert_quantity_allclose(reg[0].upper, 15.0*u.Hz)
    assert_quantity_allclose(reg[1].lower, 30.0*u.Hz)
    assert_quantity_allclose(reg[1].upper, 34.0*u.Hz)
Пример #13
0
    def test_apply_roi_undo(self):

        self.data_collection.append(self.data)
        self.viewer.add_data(self.data)

        roi = XRangeROI(1, 2)
        self.viewer.apply_roi(roi)

        assert len(self.data.subsets) == 1

        lo1 = self.data.subsets[0].subset_state.lo
        hi1 = self.data.subsets[0].subset_state.hi

        roi = XRangeROI(0, 3)
        self.viewer.apply_roi(roi)

        assert len(self.data.subsets) == 1

        lo2 = self.data.subsets[0].subset_state.lo
        hi2 = self.data.subsets[0].subset_state.hi

        assert lo2 != lo1
        assert hi2 != hi1

        self.application.undo()

        assert len(self.data.subsets) == 1

        assert self.data.subsets[0].subset_state.lo == lo1
        assert self.data.subsets[0].subset_state.hi == hi1

        self.application.redo()

        assert len(self.data.subsets) == 1

        assert self.data.subsets[0].subset_state.lo == lo2
        assert self.data.subsets[0].subset_state.hi == hi2
Пример #14
0
    def test_range_rois_preserved(self):
        data = self.add_data_and_attributes()
        assert self.client.xatt is not self.client.yatt

        roi = XRangeROI()
        roi.set_range(1, 2)
        self.client.apply_roi(roi)
        assert isinstance(data.edit_subset.subset_state, RangeSubsetState)
        assert data.edit_subset.subset_state.att == self.client.xatt

        roi = RectangularROI()
        roi = YRangeROI()
        roi.set_range(1, 2)
        self.client.apply_roi(roi)
        assert data.edit_subset.subset_state.att == self.client.yatt
Пример #15
0
def test_region_from_subset_profile(jdaviz_app, spectral_cube_wcs):
    data = Data(flux=np.ones((256, 128, 128)), label='Test 1D Flux', coords=spectral_cube_wcs)
    jdaviz_app.data_collection.append(data)

    jdaviz_app.add_data_to_viewer('spectrum-viewer', 'Test 1D Flux')

    jdaviz_app.get_viewer("spectrum-viewer").apply_roi(XRangeROI(5, 15.5))

    subsets = jdaviz_app.get_subsets_from_viewer('spectrum-viewer', subset_type='spectral')
    reg = subsets.get('Subset 1')

    assert len(subsets) == 1
    assert isinstance(reg, SpectralRegion)

    assert_quantity_allclose(reg.lower, 5.0 * u.Hz)
    assert_quantity_allclose(reg.upper, 14.0 * u.Hz)
Пример #16
0
    def test_xregion_roi(self):

        subset_state = RoiSubsetState(self.data.pixel_component_ids[1],
                                      self.data.pixel_component_ids[0],
                                      XRangeROI(1, 3.5))

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

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

        assert isinstance(reg, RectanglePixelRegion)

        assert_allclose(reg.center.x, 2.25)
        assert_allclose(reg.center.y, 64)
        assert_allclose(reg.width, 2.5)
        assert_allclose(reg.height, 128)
Пример #17
0
    def test_apply_roi_single(self):

        # Regression test for a bug that caused mode.update to be called
        # multiple times and resulted in all other viewers receiving many
        # messages regarding subset updates (this occurred when multiple)
        # datasets were present.

        layer_tree = LayerTreeWidget(session=self.session)
        layer_tree.set_checkable(False)
        layer_tree.setup(self.data_collection)
        layer_tree.bind_selection_to_edit_subset()

        class Client(HubListener):

            def __init__(self, *args, **kwargs):
                super(Client, self).__init__(*args, **kwargs)
                self.count = Counter()

            def ping(self, message):
                self.count[message.sender] += 1

            def register_to_hub(self, hub):
                hub.subscribe(self, SubsetUpdateMessage, handler=self.ping)

        d1 = Data(a=[[1, 2], [3, 4]], label='d1')
        d2 = Data(b=[[1, 2], [3, 4]], label='d2')
        d3 = Data(c=[[1, 2], [3, 4]], label='d3')
        d4 = Data(d=[[1, 2], [3, 4]], label='d4')

        self.data_collection.append(d1)
        self.data_collection.append(d2)
        self.data_collection.append(d3)
        self.data_collection.append(d4)

        client = Client()
        client.register_to_hub(self.hub)

        self.viewer.add_data(d1)
        self.viewer.add_data(d3)

        roi = XRangeROI(2.5, 3.5)
        self.viewer.apply_roi(roi)

        for subset in client.count:
            assert client.count[subset] == 1
Пример #18
0
 def test_limits_unchanged(self):
     # Make sure the limits don't change if a subset is created or another
     # dataset added - they should only change if the reference data is changed
     self.viewer.add_data(self.data)
     self.viewer.state.x_min = 0.2
     self.viewer.state.x_max = 0.4
     self.viewer.state.y_min = 0.3
     self.viewer.state.y_max = 0.5
     self.viewer.add_data(self.data2)
     assert self.viewer.state.x_min == 0.2
     assert self.viewer.state.x_max == 0.4
     assert self.viewer.state.y_min == 0.3
     assert self.viewer.state.y_max == 0.5
     roi = XRangeROI(0.9, 2.1)
     self.viewer.apply_roi(roi)
     assert self.viewer.state.x_min == 0.2
     assert self.viewer.state.x_max == 0.4
     assert self.viewer.state.y_min == 0.3
     assert self.viewer.state.y_max == 0.5
Пример #19
0
def test_region_from_subset_profile(jdaviz_app, spectral_cube_wcs):
    data = Data(flux=np.ones((256, 128, 128)),
                label='Test 1D Flux',
                coords=spectral_cube_wcs)
    jdaviz_app.data_collection.append(data)

    jdaviz_app.add_data_to_viewer('spectrum-viewer', 'Test 1D Flux')

    jdaviz_app.get_viewer("spectrum-viewer").apply_roi(XRangeROI(1, 3.5))

    subsets = jdaviz_app.get_subsets_from_viewer('spectrum-viewer',
                                                 subset_type='spectral')
    reg = subsets.get('Subset 1')

    assert len(subsets) == 1
    assert isinstance(reg, RectanglePixelRegion)

    assert_allclose(reg.center.x, 2.25)
    assert_allclose(reg.center.y, 128)
    assert_allclose(reg.width, 2.5)
    assert_allclose(reg.height, 256)
Пример #20
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
Пример #21
0
 def test_apply_roi_empty(self):
     # Make sure that doing an ROI selection on an empty viewer doesn't
     # produce error messsages
     roi = XRangeROI(-0.2, 0.1)
     self.viewer.apply_roi(roi)
Пример #22
0
    def subset_from_roi(self,
                        att,
                        roi,
                        other_comp=None,
                        other_att=None,
                        coord='x',
                        is_nested=False):
        """
        Create a SubsetState object from an ROI.

        This encapsulates the logic for creating subset states with
        CategoricalComponents. There is an important caveat, only RangeROIs
        and RectangularROIs make sense in mixed type plots. As such, polygons
        are converted to their outer-most edges in this case.

        :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')

        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
                return CategoricalROISubsetState.from_range(
                    self, att, roi.min, roi.max)

            else:

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

        elif isinstance(roi, RectangularROI):

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

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

            if coord == 'x':
                range1 = XRangeROI(roi.xmin, roi.xmax)
                range2 = YRangeROI(roi.ymin, roi.ymax)
            else:
                range2 = XRangeROI(roi.xmin, roi.xmax)
                range1 = YRangeROI(roi.ymin, roi.ymax)

            # We get the subset state for the current component
            subset1 = self.subset_from_roi(att,
                                           range1,
                                           other_comp=other_comp,
                                           other_att=other_att,
                                           coord=coord)

            # We now get the subset state for the other component
            subset2 = other_comp.subset_from_roi(other_att,
                                                 range2,
                                                 other_comp=self,
                                                 other_att=att,
                                                 coord=other_coord)

            return AndState(subset1, subset2)

        elif isinstance(roi, CategoricalROI):

            # The selection is categorical itself

            return CategoricalROISubsetState(roi=roi, att=att)

        else:

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

            if isinstance(other_comp, CategoricalComponent):

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

                selection = {}

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

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

                    if coord == 'y':
                        x, y = y, x

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

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

                return CategoricalROISubsetState2D(selection, att, other_att)

            else:

                # If the other component 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!

                x, y = roi.to_polygon()

                if is_nested:
                    x, y = y, x

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

                selection = {}

                for code, label in enumerate(self.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, att, other_att)
Пример #23
0
 def test_get_spectral_regions_one(self):
     self.spec_app.app.get_viewer("spectrum-viewer").apply_roi(
         XRangeROI(6000, 6500))
     spec_region = self.spec_app.get_spectral_regions()
     assert len(spec_region['Subset 1'].subregions) == 1