Example #1
0
class TestImporter():

    def setup_method(self, method):
        self.importer = MySubsetMaskImporter()
        self.importer.filename = 'test-filename'
        self.importer.reader = MagicMock()
        self.data = Data(x=[1, 2, 3])
        self.data_collection = DataCollection([self.data])

    def test_single_valid(self):
        self.importer.reader.return_value = OrderedDict([('subset 1', np.array([0, 1, 0]))])
        self.importer.run(self.data, self.data_collection)
        assert len(self.data_collection.subset_groups) == 1
        assert_equal(self.data.subsets[0].to_mask(), [0, 1, 0])

    def test_multiple_valid(self):
        self.importer.reader.return_value = OrderedDict([('subset 1', np.array([0, 1, 0])),
                                                         ('subset 2', np.array([1, 1, 0]))])
        self.importer.run(self.data, self.data_collection)
        assert len(self.data_collection.subset_groups) == 2
        assert_equal(self.data.subsets[0].to_mask(), [0, 1, 0])
        assert_equal(self.data.subsets[1].to_mask(), [1, 1, 0])

    def test_missing_masks(self):
        self.importer.reader.return_value = OrderedDict()
        with pytest.raises(ValueError) as exc:
            self.importer.run(self.data, self.data_collection)
        assert exc.value.args[0] == "No subset masks were returned"

    def test_single_invalid_shape(self):
        self.importer.reader.return_value = OrderedDict([('subset 1', np.array([0, 1, 0, 1]))])
        with pytest.raises(ValueError) as exc:
            self.importer.run(self.data, self.data_collection)
        assert exc.value.args[0].replace('L', '') == "Mask shape (4,) does not match data shape (3,)"

    def test_multiple_inconsistent_shapes(self):
        self.importer.reader.return_value = OrderedDict([('subset 1', np.array([0, 1, 0])),
                                                         ('subset 2', np.array([0, 1, 0, 1]))])
        with pytest.raises(ValueError) as exc:
            self.importer.run(self.data, self.data_collection)
        assert exc.value.args[0] == "Not all subsets have the same shape"

    def test_subset_single(self):
        self.importer.reader.return_value = OrderedDict([('subset 1', np.array([0, 1, 0]))])
        subset = self.data.new_subset()
        assert_equal(self.data.subsets[0].to_mask(), [0, 0, 0])
        self.importer.run(subset, self.data_collection)
        assert_equal(self.data.subsets[0].to_mask(), [0, 1, 0])

    def test_subset_multiple(self):
        self.importer.reader.return_value = OrderedDict([('subset 1', np.array([0, 1, 0])),
                                                         ('subset 2', np.array([1, 1, 0]))])
        subset = self.data.new_subset()
        with pytest.raises(ValueError) as exc:
            self.importer.run(subset, self.data_collection)
        assert exc.value.args[0] == 'Can only read in a single subset when importing into a subset'
Example #2
0
class TestImporter():

    def setup_method(self, method):
        self.importer = MySubsetMaskImporter()
        self.importer.filename = 'test-filename'
        self.importer.reader = MagicMock()
        self.data = Data(x=[1, 2, 3])
        self.data_collection = DataCollection([self.data])

    def test_single_valid(self):
        self.importer.reader.return_value = OrderedDict([('subset 1', np.array([0, 1, 0]))])
        self.importer.run(self.data, self.data_collection)
        assert len(self.data_collection.subset_groups) == 1
        assert_equal(self.data.subsets[0].to_mask(), [0, 1, 0])

    def test_multiple_valid(self):
        self.importer.reader.return_value = OrderedDict([('subset 1', np.array([0, 1, 0])),
                                                         ('subset 2', np.array([1, 1, 0]))])
        self.importer.run(self.data, self.data_collection)
        assert len(self.data_collection.subset_groups) == 2
        assert_equal(self.data.subsets[0].to_mask(), [0, 1, 0])
        assert_equal(self.data.subsets[1].to_mask(), [1, 1, 0])

    def test_missing_masks(self):
        self.importer.reader.return_value = OrderedDict()
        with pytest.raises(ValueError) as exc:
            self.importer.run(self.data, self.data_collection)
        assert exc.value.args[0] == "No subset masks were returned"

    def test_single_invalid_shape(self):
        self.importer.reader.return_value = OrderedDict([('subset 1', np.array([0, 1, 0, 1]))])
        with pytest.raises(ValueError) as exc:
            self.importer.run(self.data, self.data_collection)
        assert exc.value.args[0].replace('L', '') == "Mask shape (4,) does not match data shape (3,)"

    def test_multiple_inconsistent_shapes(self):
        self.importer.reader.return_value = OrderedDict([('subset 1', np.array([0, 1, 0])),
                                                         ('subset 2', np.array([0, 1, 0, 1]))])
        with pytest.raises(ValueError) as exc:
            self.importer.run(self.data, self.data_collection)
        assert exc.value.args[0] == "Not all subsets have the same shape"

    def test_subset_single(self):
        self.importer.reader.return_value = OrderedDict([('subset 1', np.array([0, 1, 0]))])
        subset = self.data.new_subset()
        assert_equal(self.data.subsets[0].to_mask(), [0, 0, 0])
        self.importer.run(subset, self.data_collection)
        assert_equal(self.data.subsets[0].to_mask(), [0, 1, 0])

    def test_subset_multiple(self):
        self.importer.reader.return_value = OrderedDict([('subset 1', np.array([0, 1, 0])),
                                                         ('subset 2', np.array([1, 1, 0]))])
        subset = self.data.new_subset()
        with pytest.raises(ValueError) as exc:
            self.importer.run(subset, self.data_collection)
        assert exc.value.args[0] == 'Can only read in a single subset when importing into a subset'
Example #3
0
def test_hdf5_writer_subset(tmpdir, dtype):

    filename = tmpdir.join('test').strpath

    data = Data(x=np.arange(6).reshape(2, 3).astype(dtype),
                y=(np.arange(6) * 2).reshape(2, 3).astype(dtype))

    subset = data.new_subset()
    subset.subset_state = data.id['x'] > 2

    hdf5_writer(filename, subset)

    from h5py import File

    f = File(filename)

    if np.dtype(dtype).kind == 'f':
        assert np.all(np.isnan(f['x'][0]))
        assert np.all(np.isnan(f['y'][0]))
    else:
        np.testing.assert_equal(f['x'][0], 0)
        np.testing.assert_equal(f['y'][0], 0)

    np.testing.assert_equal(f['x'][1], data['x'][1])
    np.testing.assert_equal(f['y'][1], data['y'][1])
    assert f['x'][()].dtype == dtype
    assert f['y'][()].dtype == dtype
    f.close()
Example #4
0
    def setup_method(self, method):
        x = np.arange(80).reshape(8, 10)
        d = Data(x=x, label='data')
        s = d.new_subset()
        s.subset_state = d.id['x'] > 30
        print(s.to_mask())

        self.subset = s
        self.x = x
        self.im = SubsetImage(s, np.s_[:, :])

        m = (s.to_mask() * 127).astype(np.uint8)
        self.base = BaseImage.BaseImage(data_np=m)
Example #5
0
    def setup_method(self, method):
        x = np.arange(80).reshape(8, 10)
        d = Data(x=x, label='data')
        s = d.new_subset()
        s.subset_state = d.id['x'] > 30
        print(s.to_mask())

        self.subset = s
        self.x = x
        self.im = SubsetImage(s, np.s_[:, :])

        m = (s.to_mask() * 127).astype(np.uint8)
        self.base = BaseImage.BaseImage(data_np=m)
Example #6
0
def test_fits_writer_subset(tmpdir):

    filename = tmpdir.join('test').strpath

    data = Data(x=np.arange(6).reshape(2, 3),
                y=(np.arange(6) * 2).reshape(2, 3))

    subset = data.new_subset()
    subset.subset_state = data.id['x'] > 2

    fits_writer(filename, subset)

    with fits.open(filename) as hdulist:
        assert np.all(np.isnan(hdulist['x'].data[0]))
        assert np.all(np.isnan(hdulist['y'].data[0]))
        np.testing.assert_equal(hdulist['x'].data[1], data['x'][1])
        np.testing.assert_equal(hdulist['y'].data[1], data['y'][1])
Example #7
0
def test_fits_writer_subset(tmpdir):

    filename = tmpdir.join('test').strpath

    data = Data(x=np.arange(6).reshape(2, 3),
                y=(np.arange(6) * 2).reshape(2, 3))

    subset = data.new_subset()
    subset.subset_state = data.id['x'] > 2

    fits_writer(filename, subset)

    with fits.open(filename) as hdulist:
        assert np.all(np.isnan(hdulist['x'].data[0]))
        assert np.all(np.isnan(hdulist['y'].data[0]))
        np.testing.assert_equal(hdulist['x'].data[1], data['x'][1])
        np.testing.assert_equal(hdulist['y'].data[1], data['y'][1])
Example #8
0
def test_make_data_file():

    from astropy.table import Table

    # astropy.Table interface has changed across versions. Check
    # that we build a valid table
    d = Data(x=[1, 2, 3], y=[2, 3, 4], label='data')
    s = d.new_subset(label='test')
    s.subset_state = d.id['x'] > 1

    dir = mkdtemp()
    try:
        make_data_file(d, (s,), dir)
        t = Table.read(os.path.join(dir, 'data.csv'), format='ascii')
        np.testing.assert_array_equal(t['x'], [1, 2, 3])
        np.testing.assert_array_equal(t['y'], [2, 3, 4])
        np.testing.assert_array_equal(t['selection_0'], [0, 1, 1])
    finally:
        rmtree(dir, ignore_errors=True)
Example #9
0
def test_hdf5_writer_subset(tmpdir):

    filename = tmpdir.join('test').strpath

    data = Data(x=np.arange(6).reshape(2, 3).astype(float),
                y=(np.arange(6) * 2).reshape(2, 3).astype(float))

    subset = data.new_subset()
    subset.subset_state = data.id['x'] > 2

    hdf5_writer(filename, subset)

    from h5py import File

    f = File(filename)
    assert np.all(np.isnan(f['x'].value[0]))
    assert np.all(np.isnan(f['y'].value[0]))
    np.testing.assert_equal(f['x'].value[1], data['x'][1])
    np.testing.assert_equal(f['y'].value[1], data['y'][1])
    f.close()
Example #10
0
def test_fits_writer_subset(tmpdir, dtype):

    filename = tmpdir.join('test').strpath

    data = Data(x=np.arange(6).reshape(2, 3).astype(dtype),
                y=(np.arange(6) * 2).reshape(2, 3).astype(dtype))

    subset = data.new_subset()
    subset.subset_state = data.id['x'] > 2

    fits_writer(filename, subset)

    with fits.open(filename) as hdulist:
        assert np.all(np.isnan(hdulist['x'].data[0]))
        assert np.all(np.isnan(hdulist['y'].data[0]))
        np.testing.assert_equal(hdulist['x'].data[1], data['x'][1])
        np.testing.assert_equal(hdulist['y'].data[1], data['y'][1])
        # Here we check BITPIX, not the dtype of the read in data, because if
        # BLANK is present, astropy.io.fits scales the data to float. We want to
        # just make sure here the data is stored with the correct type on disk.
        assert hdulist['x'].header['BITPIX'] == BITPIX[dtype]
        assert hdulist['y'].header['BITPIX'] == BITPIX[dtype]
Example #11
0
 def setup_method(self, method):
     d = Data(x=[1, 2, 3, 4, 5], c=['a', 'b', 'a', 'a', 'b'], label='test')
     s = d.new_subset()
     s.subset_state = d.id['x'] > 2
     self.d = d
     self.s = s
Example #12
0
class TestWWTDataViewer(object):
    def setup_method(self, method):
        self.d = Data(x=[1, 2, 3], y=[2, 3, 4], z=[4, 5, 6])
        self.application = GlueApplication()
        self.dc = self.application.data_collection
        self.dc.append(self.d)
        self.hub = self.dc.hub
        self.session = self.application.session
        self.viewer = self.application.new_data_viewer(WWTQtViewerBlocking)
        self.options = self.viewer.options_widget()

    def teardown_method(self, method):
        self.viewer.close(warn=False)
        self.viewer = None
        self.application.close()
        self.application = None

    def register(self):
        self.viewer.register_to_hub(self.hub)

    def test_add_data(self):
        self.viewer.add_data(self.d)
        self.viewer.state.lon_att = self.d.id['x']
        self.viewer.state.lat_att = self.d.id['y']

    def test_center(self):
        self.viewer.add_data(self.d)
        self.viewer.state.lon_att = self.d.id['x']
        self.viewer.state.lat_att = self.d.id['y']
        self.viewer.layers[0].center()

    def test_new_subset_group(self):
        # Make sure only the subset for data that is already inside the viewer
        # is added.
        d2 = Data(a=[4, 5, 6])
        self.dc.append(d2)
        self.viewer.add_data(self.d)
        assert len(self.viewer.layers) == 1
        self.dc.new_subset_group(subset_state=self.d.id['x'] > 1, label='A')
        assert len(self.viewer.layers) == 2

    def test_double_add_ignored(self):
        assert len(self.viewer.layers) == 0
        self.viewer.add_data(self.d)
        assert len(self.viewer.layers) == 1
        self.viewer.add_data(self.d)
        assert len(self.viewer.layers) == 1

    def test_remove_data(self):
        self.register()
        self.viewer.add_data(self.d)
        layer = self.viewer._layer_artist_container[self.d][0]

        layer.clear = MagicMock()
        self.hub.broadcast(
            message.DataCollectionDeleteMessage(self.dc, data=self.d))
        # TODO: the following currently fails but is not critical, so we
        #       skip for now.
        # assert layer.clear.call_count == 1
        assert self.d not in self.viewer._layer_artist_container

    def test_remove_subset(self):
        self.register()
        s = self.d.new_subset()
        self.viewer.add_subset(s)

        layer = self.viewer._layer_artist_container[s][0]
        layer.clear = MagicMock()

        self.hub.broadcast(message.SubsetDeleteMessage(s))

        # assert layer.clear.call_count == 1
        assert s not in self.viewer._layer_artist_container

    def test_subsets_added_with_data(self):
        s = self.d.new_subset()
        self.viewer.add_data(self.d)
        assert s in self.viewer._layer_artist_container

    def test_subsets_live_added(self):
        self.register()
        self.viewer.add_data(self.d)
        s = self.d.new_subset()
        assert s in self.viewer._layer_artist_container

    def test_clone(self):

        self.viewer.add_data(self.d)
        self.viewer.state.layers[0].ra_att = self.d.id['y']
        self.viewer.state.layers[0].dec_att = self.d.id['x']

        application2 = clone(self.application)

        application2.viewers[0][0]

    def test_changing_alt_back_to_none(self):

        # Regression test for a bug which caused an exception to
        # happen when changing the altitude attribute back to None
        self.viewer.add_data(self.d)
        self.viewer.state.mode = 'Milky Way'
        self.viewer.state.lon_att = self.d.id['x']
        self.viewer.state.lat_att = self.d.id['y']
        self.viewer.state.alt_att = self.d.id['z']
        self.viewer.state.alt_unit = 'kpc'
        self.viewer.state.alt_att = None

    def test_remove_layer(self):

        # Make sure that _update_markers doesn't get called after removing a
        # layer. This is a regression test for
        # https://github.com/glue-viz/glue-wwt/issues/54

        self.register()
        self.d.add_subset(self.d.id['x'] > 1)
        self.viewer.add_data(self.d)
        assert len(self.viewer.layers) == 2

        subset_layer = self.viewer.layers[1]

        subset_layer.wwt_client.layers.add_table_layer = MagicMock()

        self.viewer.remove_subset(self.d.subsets[0])
        assert len(self.viewer.layers) == 1
        assert subset_layer.wwt_client.layers.add_table_layer.call_count == 0
        assert subset_layer.wwt_layer is None

    @pytest.mark.skipif(sys.platform == 'win32',
                        reason="Test causes issues on Windows")
    def test_save_tour(self, tmpdir):

        filename = tmpdir.join('mytour.wtt').strpath
        self.viewer.add_data(self.d)
        with patch.object(compat,
                          'getsavefilename',
                          return_value=(filename, None)):
            self.viewer.toolbar.tools['save'].subtools[1].activate()

        assert os.path.exists(filename)
        with io.open(filename, newline='') as f:
            assert f.read().startswith(
                "<?xml version='1.0' encoding='UTF-8'?>\r\n<FileCabinet")

    def test_load_session_back_compat(self):

        # Make sure that old session files continue to work

        app = GlueApplication.restore_session(
            os.path.join(DATA, 'wwt_simple.glu'))
        viewer_state = app.viewers[0][0].state
        assert viewer_state.lon_att.label == 'a'
        assert viewer_state.lat_att.label == 'b'
        assert viewer_state.frame == 'Galactic'
Example #13
0
class TestDendroClient():
    def setup_method(self, method):

        self.data = Data(parent=[4, 4, 5, 5, 5, -1],
                         height=[5, 4, 3, 2, 1, 0],
                         label='dendro')
        self.dc = DataCollection([self.data])
        self.hub = self.dc.hub
        self.client = DendroClient(self.dc, figure=FIGURE)
        EditSubsetMode().data_collection = self.dc

    def add_subset_via_hub(self):
        self.connect()
        self.client.add_layer(self.data)
        s = self.data.new_subset()
        return s

    def connect(self):
        self.client.register_to_hub(self.hub)
        self.dc.register_to_hub(self.hub)

    def click(self, x, y):
        roi = PointROI(x=x, y=y)
        self.client.apply_roi(roi)

    def test_data_present_after_adding(self):
        assert self.data not in self.client
        self.client.add_layer(self.data)
        assert self.data in self.client

    def test_add_data_adds_subsets(self):
        s1 = self.data.new_subset()
        self.client.add_layer(self.data)
        assert s1 in self.client

    def test_remove_data(self):

        self.client.add_layer(self.data)
        self.client.remove_layer(self.data)

        assert self.data not in self.client

    def test_remove_data_removes_subsets(self):
        s = self.data.new_subset()
        self.client.add_layer(self.data)

        self.client.remove_layer(self.data)
        assert s not in self.client

    def test_add_subset_hub(self):
        s = self.add_subset_via_hub()
        assert s in self.client

    def test_new_subset_autoadd(self):
        self.connect()
        self.client.add_layer(self.data)
        s = self.data.new_subset()
        assert s in self.client

    def test_remove_subset_hub(self):

        s = self.add_subset_via_hub()
        s.delete()

        assert s not in self.client

    def test_subset_sync(self):
        s = self.add_subset_via_hub()

        self.client._update_layer = MagicMock()
        s.style.color = 'blue'
        self.client._update_layer.assert_called_once_with(s)

    def test_data_sync(self):
        self.connect()
        self.client.add_layer(self.data)

        self.client._update_layer = MagicMock()
        self.data.style.color = 'blue'
        self.client._update_layer.assert_called_once_with(self.data)

    def test_data_remove(self):
        s = self.add_subset_via_hub()
        self.dc.remove(self.data)

        assert self.data not in self.dc
        assert self.data not in self.client
        assert s not in self.client

    def test_log(self):
        self.client.ylog = True
        assert self.client.axes.get_yscale() == 'log'

    def test_1d_data_required(self):
        d = Data(x=[[1, 2], [2, 3]])
        self.dc.append(d)
        self.client.add_layer(d)
        assert d not in self.client

    def test_apply_roi(self):
        self.client.add_layer(self.data)
        self.client.select_substruct = False

        self.click(0, 4)
        s = self.data.subsets[0]

        assert_array_equal(s.to_index_list(), [1])

        self.click(0, 3)
        assert_array_equal(s.to_index_list(), [1])

        self.click(0, 0)
        assert_array_equal(s.to_index_list(), [4])

        self.click(.75, 4)
        assert_array_equal(s.to_index_list(), [0])

        self.click(0, 10)
        assert_array_equal(s.to_index_list(), [])

    def test_apply_roi_children_select(self):
        self.client.select_substruct = True
        self.client.add_layer(self.data)

        self.click(.5, .5)
        s = self.data.subsets[0]

        assert_array_equal(s.to_index_list(), [0, 1, 4])

    def test_attribute_change_triggers_relayout(self):
        self.client.add_layer(self.data)

        l = self.client._layout
        self.client.height_attr = self.data.id['parent']
        assert self.client._layout is not l

        l = self.client._layout
        self.client.parent_attr = self.data.id['height']
        assert self.client._layout is not l

        l = self.client._layout
        self.client.order_attr = self.data.id['parent']
        assert self.client._layout is not l
Example #14
0
class TestProfileViewerState:
    def setup_method(self, method):
        self.data = Data(label='d1')
        self.data.coords = SimpleCoordinates()
        self.data['x'] = np.arange(24).reshape((3, 4, 2)).astype(float)
        self.viewer_state = ProfileViewerState()
        self.layer_state = ProfileLayerState(viewer_state=self.viewer_state,
                                             layer=self.data)
        self.viewer_state.layers.append(self.layer_state)
        self.viewer_state.function = 'mean'

    def test_basic(self):
        x, y = self.layer_state.profile
        assert_allclose(x, [0, 2, 4])
        assert_allclose(y, [3.5, 11.5, 19.5])

    def test_basic_world(self):
        self.viewer_state.x_att = self.data.world_component_ids[0]
        x, y = self.layer_state.profile
        assert_allclose(x, [0, 2, 4])
        assert_allclose(y, [3.5, 11.5, 19.5])

    def test_x_att(self):

        self.viewer_state.x_att = self.data.pixel_component_ids[0]
        x, y = self.layer_state.profile
        assert_allclose(x, [0, 1, 2])
        assert_allclose(y, [3.5, 11.5, 19.5])

        self.viewer_state.x_att = self.data.pixel_component_ids[1]
        x, y = self.layer_state.profile
        assert_allclose(x, [0, 1, 2, 3])
        assert_allclose(y, [8.5, 10.5, 12.5, 14.5])

        self.viewer_state.x_att = self.data.pixel_component_ids[2]
        x, y = self.layer_state.profile
        assert_allclose(x, [0, 1])
        assert_allclose(y, [11, 12])

    def test_function(self):

        self.viewer_state.function = 'mean'
        x, y = self.layer_state.profile
        assert_allclose(y, [3.5, 11.5, 19.5])

        self.viewer_state.function = 'minimum'
        x, y = self.layer_state.profile
        assert_allclose(y, [0, 8, 16])

        self.viewer_state.function = 'maximum'
        x, y = self.layer_state.profile
        assert_allclose(y, [7, 15, 23])

        self.viewer_state.function = 'sum'
        x, y = self.layer_state.profile
        assert_allclose(y, [28, 92, 156])

        self.viewer_state.function = 'median'
        x, y = self.layer_state.profile
        assert_allclose(y, [3.5, 11.5, 19.5])

    def test_subset(self):

        subset = self.data.new_subset()
        subset.subset_state = self.data.id['x'] > 10

        self.layer_state.layer = subset

        x, y = self.layer_state.profile
        assert_allclose(x, [0, 2, 4])
        assert_allclose(y, [np.nan, 13., 19.5])

        subset.subset_state = self.data.id['x'] > 100

        # TODO: the fact we have to call this isn't ideal
        self.layer_state.reset_cache()

        x, y = self.layer_state.profile
        assert len(x) == 0
        assert len(y) == 0

    def test_clone(self):

        self.viewer_state.x_att = self.data.pixel_component_ids[1]
        self.viewer_state.function = 'median'

        self.layer_state.attribute = self.data.id['x']
        self.layer_state.linewidth = 3

        viewer_state_new = clone(self.viewer_state)

        assert viewer_state_new.x_att.label == 'Pixel Axis 1 [y]'
        assert viewer_state_new.function == 'median'

        assert self.layer_state.attribute.label == 'x'
        assert self.layer_state.linewidth == 3

    def test_limits(self):

        self.viewer_state.x_att = self.data.pixel_component_ids[0]

        assert self.viewer_state.x_min == -0.5
        assert self.viewer_state.x_max == 2.5

        self.viewer_state.flip_x()

        assert self.viewer_state.x_min == 2.5
        assert self.viewer_state.x_max == -0.5

        self.viewer_state.x_min = 1
        self.viewer_state.x_max = 1.5

        assert self.viewer_state.x_min == 1
        assert self.viewer_state.x_max == 1.5

        self.viewer_state.reset_limits()

        assert self.viewer_state.x_min == -0.5
        assert self.viewer_state.x_max == 2.5
Example #15
0
class TestHistogramLayerArtist(object):

    def setup_method(self, method):

        self.viewer_state = HistogramViewerState()

        ax = plt.subplot(1, 1, 1)

        self.data = Data(x=[1, 2, 3], y=[2, 3, 4])
        self.subset = self.data.new_subset()
        self.subset.subset_state = self.data.id['x'] > 1

        dc = DataCollection([self.data])

        # TODO: The following line shouldn't be needed
        self.viewer_state.data_collection = dc

        self.artist = HistogramLayerArtist(ax, self.viewer_state, layer=self.subset)
        self.layer_state = self.artist.state
        self.viewer_state.layers.append(self.layer_state)

        self.call_counter = CallCounter()
        sys.setprofile(self.call_counter)

    def teardown_method(self, method):
        self.artist.remove()
        sys.setprofile(None)

    def test_recalc_on_state_changes(self):

        assert self.call_counter['_calculate_histogram'] == 0
        assert self.call_counter['_update_artists'] == 0

        # attribute
        self.viewer_state.x_att = self.data.id['y']
        assert self.call_counter['_calculate_histogram'] == 1
        assert self.call_counter['_update_artists'] == 1

        # lo
        self.viewer_state.hist_x_min = -1
        assert self.call_counter['_calculate_histogram'] == 2
        assert self.call_counter['_update_artists'] == 2

        # hi
        self.viewer_state.hist_x_max = 5
        assert self.call_counter['_calculate_histogram'] == 3
        assert self.call_counter['_update_artists'] == 3

        # nbins
        self.viewer_state.hist_n_bin += 1
        assert self.call_counter['_calculate_histogram'] == 4
        assert self.call_counter['_update_artists'] == 4

        # xlog
        self.viewer_state.x_log ^= True
        assert self.call_counter['_calculate_histogram'] == 5
        assert self.call_counter['_update_artists'] == 5

        # TODO: find a way to determine whether the histogram calculation is
        # carried out since _calculate_histogram calls are no longer a good
        # way to find out (we now rely on state cache)

        # ylog -- no call
        self.viewer_state.y_log ^= True
        # assert self.call_counter['_calculate_histogram'] == 5
        assert self.call_counter['_update_artists'] == 6

        # cumulative -- no call
        self.viewer_state.cumulative ^= True
        # assert self.call_counter['_calculate_histogram'] == 5
        assert self.call_counter['_update_artists'] == 7

        # normed -- no call
        self.viewer_state.normalize ^= True
        # assert self.call_counter['_calculate_histogram'] == 5
        assert self.call_counter['_update_artists'] == 8

        # subset style -- no call
        self.subset.style.color = '#00ff00'
        # assert self.call_counter['_calculate_histogram'] == 5
        assert self.call_counter['_update_artists'] == 8
Example #16
0
 def setup_method(self, method):
     d = Data(x=[1, 2, 3, 4, 5], c=['a', 'b', 'a', 'a', 'b'], label='test')
     s = d.new_subset()
     s.subset_state = d.id['x'] > 2
     self.d = d
     self.s = s
Example #17
0
class TestWWTDataViewer(object):

    def setup_method(self, method):
        self.d = Data(x=[1, 2, 3], y=[2, 3, 4], z=[4, 5, 6])
        self.application = GlueApplication()
        self.dc = self.application.data_collection
        self.dc.append(self.d)
        self.hub = self.dc.hub
        self.session = self.application.session
        self.viewer = self.application.new_data_viewer(WWTDataViewer)
        self.options = self.viewer.options_widget()

    def register(self):
        self.viewer.register_to_hub(self.hub)

    def test_add_data(self):
        self.viewer.add_data(self.d)
        self.viewer.state.lon_att = self.d.id['x']
        self.viewer.state.lat_att = self.d.id['y']

    def test_center(self):
        self.viewer.add_data(self.d)
        self.viewer.state.lon_att = self.d.id['x']
        self.viewer.state.lat_att = self.d.id['y']
        self.viewer.layers[0].center()

    def test_new_subset_group(self):
        # Make sure only the subset for data that is already inside the viewer
        # is added.
        d2 = Data(a=[4, 5, 6])
        self.dc.append(d2)
        self.viewer.add_data(self.d)
        assert len(self.viewer.layers) == 1
        self.dc.new_subset_group(subset_state=self.d.id['x'] > 1, label='A')
        assert len(self.viewer.layers) == 2

    def test_double_add_ignored(self):
        assert len(self.viewer.layers) == 0
        self.viewer.add_data(self.d)
        assert len(self.viewer.layers) == 1
        self.viewer.add_data(self.d)
        assert len(self.viewer.layers) == 1

    def test_remove_data(self):
        self.register()
        self.viewer.add_data(self.d)
        layer = self.viewer._layer_artist_container[self.d][0]

        layer.clear = MagicMock()
        self.hub.broadcast(message.DataCollectionDeleteMessage(self.dc,
                                                               data=self.d))
        # TODO: the following currently fails but is not critical, so we
        #       skip for now.
        # assert layer.clear.call_count == 1
        assert self.d not in self.viewer._layer_artist_container

    def test_remove_subset(self):
        self.register()
        s = self.d.new_subset()
        self.viewer.add_subset(s)

        layer = self.viewer._layer_artist_container[s][0]
        layer.clear = MagicMock()

        self.hub.broadcast(message.SubsetDeleteMessage(s))

        #assert layer.clear.call_count == 1
        assert s not in self.viewer._layer_artist_container

    def test_subsets_added_with_data(self):
        s = self.d.new_subset()
        self.viewer.add_data(self.d)
        assert s in self.viewer._layer_artist_container

    def test_subsets_live_added(self):
        self.register()
        self.viewer.add_data(self.d)
        s = self.d.new_subset()
        assert s in self.viewer._layer_artist_container

    def test_clone(self):

        self.viewer.add_data(self.d)
        self.viewer.state.layers[0].ra_att = self.d.id['y']
        self.viewer.state.layers[0].dec_att = self.d.id['x']

        application2 = clone(self.application)

        viewer2 = application2.viewers[0][0]

    def test_changing_alt_back_to_none(self):

        # Regression test for a bug which caused an exception to
        # happen when changing the altitude attribute back to None
        self.viewer.add_data(self.d)
        self.viewer.state.mode = 'Milky Way'
        self.viewer.state.lon_att = self.d.id['x']
        self.viewer.state.lat_att = self.d.id['y']
        self.viewer.state.alt_att = self.d.id['z']
        self.viewer.state.alt_unit = 'kpc'
        self.viewer.state.alt_att = None
class TestWWTDataViewer(object):
    def setup_method(self, method):
        self.d = Data(x=[1, 2, 3], y=[2, 3, 4], z=[4, 5, 6])
        self.application = GlueApplication()
        self.dc = self.application.data_collection
        self.dc.append(self.d)
        self.hub = self.dc.hub
        self.session = self.application.session
        self.viewer = self.application.new_data_viewer(WWTDataViewer)
        self.options = self.viewer.options_widget()

    def register(self):
        self.viewer.register_to_hub(self.hub)

    def test_add_data(self):
        self.viewer.add_data(self.d)
        self.viewer.state.lon_att = self.d.id['x']
        self.viewer.state.lat_att = self.d.id['y']

    def test_center(self):
        self.viewer.add_data(self.d)
        self.viewer.state.lon_att = self.d.id['x']
        self.viewer.state.lat_att = self.d.id['y']
        self.viewer.layers[0].center()

    def test_new_subset_group(self):
        # Make sure only the subset for data that is already inside the viewer
        # is added.
        d2 = Data(a=[4, 5, 6])
        self.dc.append(d2)
        self.viewer.add_data(self.d)
        assert len(self.viewer.layers) == 1
        self.dc.new_subset_group(subset_state=self.d.id['x'] > 1, label='A')
        assert len(self.viewer.layers) == 2

    def test_double_add_ignored(self):
        assert len(self.viewer.layers) == 0
        self.viewer.add_data(self.d)
        assert len(self.viewer.layers) == 1
        self.viewer.add_data(self.d)
        assert len(self.viewer.layers) == 1

    def test_remove_data(self):
        self.register()
        self.viewer.add_data(self.d)
        layer = self.viewer._layer_artist_container[self.d][0]

        layer.clear = MagicMock()
        self.hub.broadcast(
            message.DataCollectionDeleteMessage(self.dc, data=self.d))
        # TODO: the following currently fails but is not critical, so we
        #       skip for now.
        # assert layer.clear.call_count == 1
        assert self.d not in self.viewer._layer_artist_container

    def test_remove_subset(self):
        self.register()
        s = self.d.new_subset()
        self.viewer.add_subset(s)

        layer = self.viewer._layer_artist_container[s][0]
        layer.clear = MagicMock()

        self.hub.broadcast(message.SubsetDeleteMessage(s))

        #assert layer.clear.call_count == 1
        assert s not in self.viewer._layer_artist_container

    def test_subsets_added_with_data(self):
        s = self.d.new_subset()
        self.viewer.add_data(self.d)
        assert s in self.viewer._layer_artist_container

    def test_subsets_live_added(self):
        self.register()
        self.viewer.add_data(self.d)
        s = self.d.new_subset()
        assert s in self.viewer._layer_artist_container

    def test_clone(self):

        self.viewer.add_data(self.d)
        self.viewer.state.layers[0].ra_att = self.d.id['y']
        self.viewer.state.layers[0].dec_att = self.d.id['x']

        application2 = clone(self.application)

        viewer2 = application2.viewers[0][0]

    def test_changing_alt_back_to_none(self):

        # Regression test for a bug which caused an exception to
        # happen when changing the altitude attribute back to None
        self.viewer.add_data(self.d)
        self.viewer.state.mode = 'Milky Way'
        self.viewer.state.lon_att = self.d.id['x']
        self.viewer.state.lat_att = self.d.id['y']
        self.viewer.state.alt_att = self.d.id['z']
        self.viewer.state.alt_unit = 'kpc'
        self.viewer.state.alt_att = None

    def test_remove_layer(self):

        # Make sure that _update_markers doesn't get called after removing a
        # layer. This is a regression test for
        # https://github.com/glue-viz/glue-wwt/issues/54

        self.register()
        self.d.add_subset(self.d.id['x'] > 1)
        self.viewer.add_data(self.d)
        assert len(self.viewer.layers) == 2

        subset_layer = self.viewer.layers[1]

        subset_layer.wwt_client.layers.add_table_layer = MagicMock()

        self.viewer.remove_subset(self.d.subsets[0])
        assert len(self.viewer.layers) == 1
        assert subset_layer.wwt_client.layers.add_table_layer.call_count == 0
        assert subset_layer.wwt_layer is None
Example #19
0
class TestProfileViewer(object):

    def setup_method(self, method):

        self.data = Data(label='d1')
        self.data.coords = SimpleCoordinates()
        self.data['x'] = np.arange(24).reshape((3, 4, 2))

        self.app = GlueApplication()
        self.session = self.app.session
        self.hub = self.session.hub

        self.data_collection = self.session.data_collection
        self.data_collection.append(self.data)

        self.viewer = self.app.new_data_viewer(ProfileViewer)

    def teardown_method(self, method):
        self.viewer.close()
        self.viewer = None
        self.app.close()
        self.app = None

    def test_functions(self):
        self.viewer.add_data(self.data)
        self.viewer.state.function = 'mean'
        assert len(self.viewer.layers) == 1
        layer_artist = self.viewer.layers[0]
        assert_allclose(layer_artist.state.profile[0], [0, 2, 4])
        assert_allclose(layer_artist.state.profile[1], [3.5, 11.5, 19.5])

    def test_incompatible(self):
        self.viewer.add_data(self.data)
        data2 = Data(y=np.random.random((3, 4, 2)))
        self.data_collection.append(data2)
        self.viewer.add_data(data2)
        assert len(self.viewer.layers) == 2
        assert self.viewer.layers[0].enabled
        assert not self.viewer.layers[1].enabled

    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])

    def test_enabled_layers(self):

        data2 = Data(label='d1', y=np.arange(24).reshape((3, 4, 2)))
        self.data_collection.append(data2)

        self.viewer.add_data(self.data)
        self.viewer.add_data(data2)

        assert self.viewer.layers[0].enabled
        assert not self.viewer.layers[1].enabled

        self.data_collection.add_link(ComponentLink([data2.world_component_ids[1]], self.data.world_component_ids[0], using=lambda x: 2 * x))

        assert self.viewer.layers[0].enabled
        assert self.viewer.layers[1].enabled

    def test_slice_subset_state(self):

        self.viewer.add_data(self.data)

        subset = self.data.new_subset()
        subset.subset_state = SliceSubsetState(self.data, [slice(1, 2), slice(None)])

        assert self.viewer.layers[0].enabled
        assert self.viewer.layers[1].enabled

    def test_clone(self):

        # Regression test for a bug that meant that deserializing a profile
        # viewer resulted in disabled layers

        self.viewer.add_data(self.data)

        subset = self.data.new_subset()
        subset.subset_state = SliceSubsetState(self.data, [slice(1, 2), slice(None)])

        app = clone(self.app)

        assert app.viewers[0][0].layers[0].enabled
        assert app.viewers[0][0].layers[1].enabled

        app.close()

    def test_incompatible_on_add(self):

        # Regression test for a bug when adding a dataset to a profile viewer
        # with a single incompatible subset.

        subset_state = SliceSubsetState(self.data, [slice(1, 2), slice(None)])
        self.data_collection.new_subset_group(subset_state=subset_state, label='s1')

        data2 = Data(x=[[2, 3], [4, 3]], label='d2')
        self.data_collection.append(data2)
        self.viewer.add_data(data2)
Example #20
0
class MyClient(HubListener):
    def register_to_hub(self, hub):
        """ Sign up to receive DataMessages from the hub """
        hub.subscribe(self,                     # subscribing object
                      DataMessage,  # message type to subscribe to
                      handler=self.receive_message)  # method to call

    def receive_message(self, message):
        """ Receives each DataMessage relay """
        print("    MyClient received a message \n")


# create objects
client = MyClient()
data = Data()
subset = data.new_subset()
data_collection = DataCollection()

# connect them to each other
hub = data_collection.hub
data_collection.append(data)
client.register_to_hub(hub)

# manually send a DataMessage. Relayed to MyClient
print('Manually sending DataMessage')
message = DataMessage(data)
hub.broadcast(message)

# modify the data object. Automatically generates a DataMessage
print('Automatically triggering DataMessage')
data.label = "New label"
Example #21
0
        """ Sign up to receive DataMessages from the hub """
        hub.subscribe(self,                     # subscribing object
                      DataMessage, # message type to subscribe to
                      handler = self.receive_message) # method to call


    def receive_message(self, message):
        """ Receives each DataMessage relay """
        print "    MyClient received a message \n"


# create objects
hub = Hub()
client = MyClient()
data = Data()
subset = data.new_subset()
data_collection = DataCollection()

# connect them to each other
data_collection.append(data)
data_collection.register_to_hub(hub)
client.register_to_hub(hub)

# manually send a DataMessage. Relayed to MyClient
print 'Manually sending DataMessage'
message = DataMessage(data)
hub.broadcast(message)

#modify the data object. Automatically generates a DataMessage
print 'Automatically triggering DataMessage'
data.label = "New label"
Example #22
0
class TestWWTDataViewer(object):

    def setup_method(self, method):
        self.d = Data(x=[1, 2, 3], y=[2, 3, 4])
        self.dc = DataCollection([self.d])
        self.hub = self.dc.hub
        self.session = Session(data_collection=self.dc, hub=self.hub)
        self.widget = WWTDataViewer(self.session, webdriver_class=MagicMock)
        self.options = self.widget.options_widget()

    def register(self):
        self.widget.register_to_hub(self.hub)

    def test_add_data(self):
        self.widget.add_data(self.d)
        self.options.ra_att = self.d.id['x'], self.d
        self.options.dec_att = self.d.id['y'], self.d
        assert self.d in self.widget

    def test_double_add_ignored(self):
        assert len(self.widget) == 0
        self.widget.add_data(self.d)
        assert len(self.widget) == 1
        self.widget.add_data(self.d)
        assert len(self.widget) == 1

    def test_updated_on_data_update_message(self):
        self.register()
        self.widget.add_data(self.d)
        layer = self.widget._layer_artist_container[self.d][0]
        layer.update = MagicMock()
        self.d.style.color = 'green'
        assert layer.update.call_count == 1

    def test_updated_on_subset_update_message(self):
        self.register()
        s = self.d.new_subset()
        self.widget.add_subset(s)
        layer = self.widget._layer_artist_container[s][0]
        layer.update = MagicMock()
        s.style.color = 'green'
        assert layer.update.call_count == 1

    def test_remove_data(self):
        self.register()
        self.widget.add_data(self.d)
        layer = self.widget._layer_artist_container[self.d][0]

        layer.clear = MagicMock()
        self.hub.broadcast(message.DataCollectionDeleteMessage(self.dc,
                                                               data=self.d))
        # TODO: the following currently fails but is not critical, so we
        #       skip for now.
        # assert layer.clear.call_count == 1
        assert self.d not in self.widget

    def test_remove_subset(self):
        self.register()
        s = self.d.new_subset()
        self.widget.add_subset(s)

        layer = self.widget._layer_artist_container[s][0]
        layer.clear = MagicMock()

        self.hub.broadcast(message.SubsetDeleteMessage(s))

        assert layer.clear.call_count == 1
        assert self.d not in self.widget

    def test_subsets_added_with_data(self):
        s = self.d.new_subset()
        self.widget.add_data(self.d)
        assert s in self.widget

    def test_subsets_live_added(self):
        self.register()
        self.widget.add_data(self.d)
        s = self.d.new_subset()
        assert s in self.widget

    # TODO: determine if the following test is the desired behavior
    # def test_subsets_not_live_added_if_data_not_present(self):
    #     self.register()
    #     s = self.d.new_subset()
    #     assert s not in self.widget

    def test_updated_on_add(self):
        self.register()
        self.widget._update_layer = MagicMock()
        self.widget.add_data(self.d)
        # TODO: ideally, the following should be called exactly once
        assert self.widget._update_layer.call_count >= 1

    def test_updated_on_coordinate_change(self):
        self.register()
        self.widget.add_data(self.d)
        self.options.ra_att = self.d.id['x'], self.d
        self.options.dec_att = self.d.id['y'], self.d
        artist = self.widget._layer_artist_container[self.d][0]
        self.widget._update_layer = MagicMock()
        self.options.ra_att = self.d.id['y'], self.d
        self.widget._update_layer.call_count > 0
Example #23
0
class TestWWTDataViewer(object):
    def setup_method(self, method):
        self.d = Data(x=[1, 2, 3], y=[2, 3, 4])
        self.dc = DataCollection([self.d])
        self.hub = self.dc.hub
        self.session = Session(data_collection=self.dc, hub=self.hub)
        self.widget = WWTDataViewer(self.session)
        self.widget.register_to_hub(self.hub)
        self.options = self.widget.options_widget()

    def register(self):
        self.widget.register_to_hub(self.hub)

    def test_add_data(self):
        self.widget.add_data(self.d)
        self.widget.state.layers[0].ra_att = self.d.id['x']
        self.widget.state.layers[0].dec_att = self.d.id['y']

    def test_center(self):
        self.widget.add_data(self.d)
        self.widget.state.layers[0].ra_att = self.d.id['x']
        self.widget.state.layers[0].dec_att = self.d.id['y']
        self.widget.layers[0].center()

    def test_new_subset_group(self):
        # Make sure only the subset for data that is already inside the viewer
        # is added.
        d2 = Data(a=[4, 5, 6])
        self.dc.append(d2)
        self.widget.add_data(self.d)
        assert len(self.widget.layers) == 1
        self.dc.new_subset_group(subset_state=self.d.id['x'] > 1, label='A')
        assert len(self.widget.layers) == 2

    def test_double_add_ignored(self):
        assert len(self.widget.layers) == 0
        self.widget.add_data(self.d)
        assert len(self.widget.layers) == 1
        self.widget.add_data(self.d)
        assert len(self.widget.layers) == 1

    def test_updated_on_data_update_message(self):
        self.register()
        self.widget.add_data(self.d)
        layer = self.widget._layer_artist_container[self.d][0]
        layer.update = MagicMock()
        self.d.style.color = 'green'
        assert layer.update.call_count == 1

    def test_updated_on_subset_update_message(self):
        self.register()
        s = self.d.new_subset()
        self.widget.add_subset(s)
        layer = self.widget._layer_artist_container[s][0]
        layer.update = MagicMock()
        s.style.color = 'green'
        assert layer.update.call_count == 1

    def test_remove_data(self):
        self.register()
        self.widget.add_data(self.d)
        layer = self.widget._layer_artist_container[self.d][0]

        layer.clear = MagicMock()
        self.hub.broadcast(
            message.DataCollectionDeleteMessage(self.dc, data=self.d))
        # TODO: the following currently fails but is not critical, so we
        #       skip for now.
        # assert layer.clear.call_count == 1
        assert self.d not in self.widget._layer_artist_container

    def test_remove_subset(self):
        self.register()
        s = self.d.new_subset()
        self.widget.add_subset(s)

        layer = self.widget._layer_artist_container[s][0]
        layer.clear = MagicMock()

        self.hub.broadcast(message.SubsetDeleteMessage(s))

        assert layer.clear.call_count == 1
        assert self.d not in self.widget._layer_artist_container

    def test_subsets_added_with_data(self):
        s = self.d.new_subset()
        self.widget.add_data(self.d)
        assert s in self.widget._layer_artist_container

    def test_subsets_live_added(self):
        self.register()
        self.widget.add_data(self.d)
        s = self.d.new_subset()
        assert s in self.widget._layer_artist_container
Example #24
0
class Test3DExtractor(object):
    def setup_method(self, method):
        self.data = Data()
        self.data.coords = MockCoordinates()
        self.data.add_component(np.random.random((3, 4, 5)), label='x')
        self.x = self.data['x']

    def test_abcissa(self):
        expected = [0, 2, 4]
        actual = Extractor.abcissa(self.data, 0)
        np.testing.assert_equal(expected, actual)

        expected = [0, 2, 4, 6]
        actual = Extractor.abcissa(self.data, 1)
        np.testing.assert_equal(expected, actual)

        expected = [0, 2, 4, 6, 8]
        actual = Extractor.abcissa(self.data, 2)
        np.testing.assert_equal(expected, actual)

    def test_spectrum(self):
        roi = RectangularROI()
        roi.update_limits(0, 0, 3, 3)

        expected = self.x[:, :3, :3].mean(axis=1).mean(axis=1)
        _, actual = Extractor.spectrum(self.data, self.data.id['x'], roi,
                                       (0, 'x', 'y'), 0)
        np.testing.assert_array_almost_equal(expected, actual)

    def test_spectrum_oob(self):
        roi = RectangularROI()
        roi.update_limits(-1, -1, 3, 3)

        expected = self.x[:, :3, :3].mean(axis=1).mean(axis=1)

        _, actual = Extractor.spectrum(self.data, self.data.id['x'], roi,
                                       (0, 'x', 'y'), 0)
        np.testing.assert_array_almost_equal(expected, actual)

    def test_pixel2world(self):
        # p2w(x) = 2x, 0 <= x <= 2
        assert Extractor.pixel2world(self.data, 0, 1) == 2

        # clips to boundary
        assert Extractor.pixel2world(self.data, 0, -1) == 0
        assert Extractor.pixel2world(self.data, 0, 5) == 4

    def test_world2pixel(self):
        # w2p(x) = x/2, 0 <= x <= 4
        assert Extractor.world2pixel(self.data, 0, 2.01) == 1

        # clips to boundary
        assert Extractor.world2pixel(self.data, 0, -1) == 0
        assert Extractor.world2pixel(self.data, 0, 8) == 2

    def test_extract_subset(self):
        sub = self.data.new_subset()
        sub.subset_state = self.data.id['x'] > .5
        slc = (0, 'y', 'x')
        mask = sub.to_mask()[0]
        mask = mask.reshape(-1, mask.shape[0], mask.shape[1])

        expected = (self.x * mask).sum(axis=1).sum(axis=1)
        expected /= mask.sum(axis=1).sum(axis=1)
        _, actual = Extractor.subset_spectrum(sub, self.data.id['x'], slc, 0)
        np.testing.assert_array_almost_equal(expected, actual)
Example #25
0
class TestDendroClient():

    def setup_method(self, method):

        self.data = Data(parent=[4, 4, 5, 5, 5, -1],
                         height=[5, 4, 3, 2, 1, 0],
                         label='dendro')
        self.dc = DataCollection([self.data])
        self.hub = self.dc.hub
        self.client = DendroClient(self.dc, figure=FIGURE)
        EditSubsetMode().data_collection = self.dc

    def add_subset_via_hub(self):
        self.connect()
        self.client.add_layer(self.data)
        s = self.data.new_subset()
        return s

    def connect(self):
        self.client.register_to_hub(self.hub)
        self.dc.register_to_hub(self.hub)

    def click(self, x, y):
        roi = PointROI(x=x, y=y)
        self.client.apply_roi(roi)

    def test_data_present_after_adding(self):
        assert self.data not in self.client
        self.client.add_layer(self.data)
        assert self.data in self.client

    def test_add_data_adds_subsets(self):
        s1 = self.data.new_subset()
        self.client.add_layer(self.data)
        assert s1 in self.client

    def test_remove_data(self):

        self.client.add_layer(self.data)
        self.client.remove_layer(self.data)

        assert self.data not in self.client

    def test_remove_data_removes_subsets(self):
        s = self.data.new_subset()
        self.client.add_layer(self.data)

        self.client.remove_layer(self.data)
        assert s not in self.client

    def test_add_subset_hub(self):
        s = self.add_subset_via_hub()
        assert s in self.client

    def test_new_subset_autoadd(self):
        self.connect()
        self.client.add_layer(self.data)
        s = self.data.new_subset()
        assert s in self.client

    def test_remove_subset_hub(self):

        s = self.add_subset_via_hub()
        s.delete()

        assert s not in self.client

    def test_subset_sync(self):
        s = self.add_subset_via_hub()

        self.client._update_layer = MagicMock()
        s.style.color = 'blue'
        self.client._update_layer.assert_called_once_with(s)

    def test_data_sync(self):
        self.connect()
        self.client.add_layer(self.data)

        self.client._update_layer = MagicMock()
        self.data.style.color = 'blue'
        self.client._update_layer.assert_called_once_with(self.data)

    def test_data_remove(self):
        s = self.add_subset_via_hub()
        self.dc.remove(self.data)

        assert self.data not in self.dc
        assert self.data not in self.client
        assert s not in self.client

    def test_log(self):
        self.client.ylog = True
        assert self.client.axes.get_yscale() == 'log'

    def test_1d_data_required(self):
        d = Data(x=[[1, 2], [2, 3]])
        self.dc.append(d)
        self.client.add_layer(d)
        assert d not in self.client

    def test_apply_roi(self):
        self.client.add_layer(self.data)
        self.client.select_substruct = False

        self.click(0, 4)
        s = self.data.subsets[0]

        assert_array_equal(s.to_index_list(), [1])

        self.click(0, 3)
        assert_array_equal(s.to_index_list(), [1])

        self.click(0, 0)
        assert_array_equal(s.to_index_list(), [4])

        self.click(.75, 4)
        assert_array_equal(s.to_index_list(), [0])

        self.click(0, 10)
        assert_array_equal(s.to_index_list(), [])

    def test_apply_roi_children_select(self):
        self.client.select_substruct = True
        self.client.add_layer(self.data)

        self.click(.5, .5)
        s = self.data.subsets[0]

        assert_array_equal(s.to_index_list(), [0, 1, 4])

    def test_attribute_change_triggers_relayout(self):
        self.client.add_layer(self.data)

        l = self.client._layout
        self.client.height_attr = self.data.id['parent']
        assert self.client._layout is not l

        l = self.client._layout
        self.client.parent_attr = self.data.id['height']
        assert self.client._layout is not l

        l = self.client._layout
        self.client.order_attr = self.data.id['parent']
        assert self.client._layout is not l
Example #26
0
class TestProfileViewerState:

    def setup_method(self, method):
        self.data = Data(label='d1')
        self.data.coords = SimpleCoordinates()
        self.data['x'] = np.arange(24).reshape((3, 4, 2)).astype(float)
        self.viewer_state = ProfileViewerState()
        self.layer_state = ProfileLayerState(viewer_state=self.viewer_state,
                                             layer=self.data)
        self.viewer_state.layers.append(self.layer_state)
        self.viewer_state.function = 'mean'

    def test_basic(self):
        x, y = self.layer_state.profile
        assert_allclose(x, [0, 2, 4])
        assert_allclose(y, [3.5, 11.5, 19.5])

    def test_basic_world(self):
        self.viewer_state.x_att = self.data.world_component_ids[0]
        x, y = self.layer_state.profile
        assert_allclose(x, [0, 2, 4])
        assert_allclose(y, [3.5, 11.5, 19.5])

    def test_x_att(self):

        self.viewer_state.x_att = self.data.pixel_component_ids[0]
        x, y = self.layer_state.profile
        assert_allclose(x, [0, 1, 2])
        assert_allclose(y, [3.5, 11.5, 19.5])

        self.viewer_state.x_att = self.data.pixel_component_ids[1]
        x, y = self.layer_state.profile
        assert_allclose(x, [0, 1, 2, 3])
        assert_allclose(y, [8.5, 10.5, 12.5, 14.5])

        self.viewer_state.x_att = self.data.pixel_component_ids[2]
        x, y = self.layer_state.profile
        assert_allclose(x, [0, 1])
        assert_allclose(y, [11, 12])

    def test_function(self):

        self.viewer_state.function = 'mean'
        x, y = self.layer_state.profile
        assert_allclose(y, [3.5, 11.5, 19.5])

        self.viewer_state.function = 'minimum'
        x, y = self.layer_state.profile
        assert_allclose(y, [0, 8, 16])

        self.viewer_state.function = 'maximum'
        x, y = self.layer_state.profile
        assert_allclose(y, [7, 15, 23])

        self.viewer_state.function = 'sum'
        x, y = self.layer_state.profile
        assert_allclose(y, [28, 92, 156])

        self.viewer_state.function = 'median'
        x, y = self.layer_state.profile
        assert_allclose(y, [3.5, 11.5, 19.5])

    def test_subset(self):

        subset = self.data.new_subset()
        subset.subset_state = self.data.id['x'] > 10

        self.layer_state.layer = subset

        x, y = self.layer_state.profile
        assert_allclose(x, [0, 2, 4])
        assert_allclose(y, [np.nan, 13., 19.5])

        subset.subset_state = self.data.id['x'] > 100

        # TODO: the fact we have to call this isn't ideal
        self.layer_state.reset_cache()

        x, y = self.layer_state.profile
        assert len(x) == 0
        assert len(y) == 0

    def test_clone(self):

        self.viewer_state.x_att = self.data.pixel_component_ids[1]
        self.viewer_state.function = 'median'

        self.layer_state.attribute = self.data.id['x']
        self.layer_state.linewidth = 3

        viewer_state_new = clone(self.viewer_state)

        assert viewer_state_new.x_att.label == 'Pixel Axis 1 [y]'
        assert viewer_state_new.function == 'median'

        assert self.layer_state.attribute.label == 'x'
        assert self.layer_state.linewidth == 3

    def test_limits(self):

        self.viewer_state.x_att = self.data.pixel_component_ids[0]

        assert self.viewer_state.x_min == -0.5
        assert self.viewer_state.x_max == 2.5

        self.viewer_state.flip_x()

        assert self.viewer_state.x_min == 2.5
        assert self.viewer_state.x_max == -0.5

        self.viewer_state.x_min = 1
        self.viewer_state.x_max = 1.5

        assert self.viewer_state.x_min == 1
        assert self.viewer_state.x_max == 1.5

        self.viewer_state.reset_limits()

        assert self.viewer_state.x_min == -0.5
        assert self.viewer_state.x_max == 2.5
Example #27
0
class TestProfileViewer(object):
    def setup_method(self, method):

        self.data = Data(label='d1')
        self.data.coords = SimpleCoordinates()
        self.data['x'] = np.arange(24).reshape((3, 4, 2))

        self.data2 = Data(label='d2')
        self.data2['y'] = np.arange(24).reshape((3, 4, 2))

        self.app = GlueApplication()
        self.session = self.app.session
        self.hub = self.session.hub

        self.data_collection = self.session.data_collection
        self.data_collection.append(self.data)
        self.data_collection.append(self.data2)

        self.viewer = self.app.new_data_viewer(ProfileViewer)

    def teardown_method(self, method):
        self.viewer.close()
        self.viewer = None
        self.app.close()
        self.app = None

    def test_functions(self):
        self.viewer.add_data(self.data)
        self.viewer.state.function = 'mean'
        assert len(self.viewer.layers) == 1
        layer_artist = self.viewer.layers[0]
        assert_allclose(layer_artist.state.profile[0], [0, 2, 4])
        assert_allclose(layer_artist.state.profile[1], [3.5, 11.5, 19.5])

    def test_incompatible(self):
        self.viewer.add_data(self.data)
        data2 = Data(y=np.random.random((3, 4, 2)))
        self.data_collection.append(data2)
        self.viewer.add_data(data2)
        assert len(self.viewer.layers) == 2
        assert self.viewer.layers[0].enabled
        assert not self.viewer.layers[1].enabled

    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])

    def test_enabled_layers(self):

        data2 = Data(label='d1',
                     y=np.arange(24).reshape((3, 4, 2)),
                     coords=IdentityCoordinates(n_dim=3))
        self.data_collection.append(data2)

        self.viewer.add_data(self.data)
        self.viewer.add_data(data2)

        assert self.viewer.layers[0].enabled
        assert not self.viewer.layers[1].enabled

        self.data_collection.add_link(
            ComponentLink([data2.world_component_ids[1]],
                          self.data.world_component_ids[0],
                          using=lambda x: 2 * x))

        assert self.viewer.layers[0].enabled
        assert self.viewer.layers[1].enabled

    def test_slice_subset_state(self):

        self.viewer.add_data(self.data)

        subset = self.data.new_subset()
        subset.subset_state = SliceSubsetState(
            self.data, [slice(1, 2), slice(None)])

        assert self.viewer.layers[0].enabled
        assert self.viewer.layers[1].enabled

    def test_clone(self):

        # Regression test for a bug that meant that deserializing a profile
        # viewer resulted in disabled layers

        self.viewer.add_data(self.data)

        subset = self.data.new_subset()
        subset.subset_state = SliceSubsetState(
            self.data, [slice(1, 2), slice(None)])

        app = clone(self.app)

        assert app.viewers[0][0].layers[0].enabled
        assert app.viewers[0][0].layers[1].enabled

        app.close()

    def test_incompatible_on_add(self):

        # Regression test for a bug when adding a dataset to a profile viewer
        # with a single incompatible subset.

        subset_state = SliceSubsetState(self.data, [slice(1, 2), slice(None)])
        self.data_collection.new_subset_group(subset_state=subset_state,
                                              label='s1')

        data2 = Data(x=[[2, 3], [4, 3]], label='d2')
        self.data_collection.append(data2)
        self.viewer.add_data(data2)

    def test_dependent_axes(self):

        # Make sure that if we pick a world component that has correlations with
        # others and is not lined up with the pixel grid, a warning is shown.

        self.viewer.add_data(self.data)

        self.viewer.state.x_att = self.data.pixel_component_ids[0]
        assert self.viewer.options_widget().ui.text_warning.text() == ''

        self.viewer.state.x_att = self.data.pixel_component_ids[1]
        assert self.viewer.options_widget().ui.text_warning.text() == ''

        self.viewer.state.x_att = self.data.pixel_component_ids[2]
        assert self.viewer.options_widget().ui.text_warning.text() == ''

        self.viewer.state.x_att = self.data.world_component_ids[0]
        assert self.viewer.options_widget().ui.text_warning.text() == ''

        self.viewer.state.x_att = self.data.world_component_ids[1]
        assert self.viewer.options_widget().ui.text_warning.text() != ''

        self.viewer.state.x_att = self.data.world_component_ids[2]
        assert self.viewer.options_widget().ui.text_warning.text() != ''

    def test_multiple_data(self, tmpdir):

        # Regression test for issues when multiple datasets are present
        # and the reference data is not the default one.

        self.viewer.add_data(self.data)
        self.viewer.add_data(self.data2)
        assert self.viewer.layers[0].enabled
        assert not self.viewer.layers[1].enabled

        # Make sure that when changing the reference data, which layer
        # is enabled changes.
        self.viewer.state.reference_data = self.data2
        assert not self.viewer.layers[0].enabled
        assert self.viewer.layers[1].enabled

        # Make sure that everything works fine after saving/reloading
        filename = tmpdir.join('test_multiple_data.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]
        assert not viewer.layers[0].enabled
        assert viewer.layers[1].enabled
        ga.close()

    @pytest.mark.parametrize('protocol', [1])
    def test_session_back_compat(self, protocol):

        filename = os.path.join(DATA, 'profile_v{0}.glu'.format(protocol))

        with open(filename, 'r') as f:
            session = f.read()

        state = GlueUnSerializer.loads(session)

        ga = state.object('__main__')

        dc = ga.session.data_collection

        assert len(dc) == 1

        assert dc[0].label == 'array'

        viewer1 = ga.viewers[0][0]
        assert len(viewer1.state.layers) == 3
        assert viewer1.state.x_att_pixel is dc[0].pixel_component_ids[0]
        assert_allclose(viewer1.state.x_min, -0.5)
        assert_allclose(viewer1.state.x_max, 2.5)
        assert_allclose(viewer1.state.y_min, 13)
        assert_allclose(viewer1.state.y_max, 63)
        assert viewer1.state.function == 'maximum'
        assert not viewer1.state.normalize
        assert viewer1.state.layers[0].visible
        assert viewer1.state.layers[1].visible
        assert viewer1.state.layers[2].visible

        viewer2 = ga.viewers[0][1]
        assert viewer2.state.x_att_pixel is dc[0].pixel_component_ids[1]
        assert_allclose(viewer2.state.x_min, -0.5)
        assert_allclose(viewer2.state.x_max, 3.5)
        assert_allclose(viewer2.state.y_min, -0.1)
        assert_allclose(viewer2.state.y_max, 1.1)
        assert viewer2.state.function == 'maximum'
        assert viewer2.state.normalize
        assert viewer2.state.layers[0].visible
        assert not viewer2.state.layers[1].visible
        assert viewer2.state.layers[2].visible

        viewer3 = ga.viewers[0][2]
        assert viewer3.state.x_att_pixel is dc[0].pixel_component_ids[2]
        assert_allclose(viewer3.state.x_min, -0.5)
        assert_allclose(viewer3.state.x_max, 4.5)
        assert_allclose(viewer3.state.y_min, -0.4)
        assert_allclose(viewer3.state.y_max, 4.4)
        assert viewer3.state.function == 'minimum'
        assert not viewer3.state.normalize
        assert viewer3.state.layers[0].visible
        assert viewer3.state.layers[1].visible
        assert not viewer3.state.layers[2].visible

        viewer4 = ga.viewers[0][3]
        assert viewer4.state.x_att_pixel is dc[0].pixel_component_ids[2]
        assert_allclose(viewer4.state.x_min, -5.5)
        assert_allclose(viewer4.state.x_max, 9.5)
        assert_allclose(viewer4.state.y_min, 27.1)
        assert_allclose(viewer4.state.y_max, 31.9)
        assert viewer4.state.function == 'mean'
        assert not viewer4.state.normalize
        assert viewer4.state.layers[0].visible
        assert not viewer4.state.layers[1].visible
        assert not viewer4.state.layers[2].visible

        ga.close()
Example #28
0
class Test3DExtractor(object):

    def setup_method(self, method):
        self.data = Data()
        self.data.coords = MockCoordinates()
        self.data.add_component(np.random.random((3, 4, 5)), label='x')
        self.x = self.data['x']

    def test_abcissa(self):
        expected = [0, 2, 4]
        actual = Extractor.abcissa(self.data, 0)
        np.testing.assert_equal(expected, actual)

        expected = [0, 2, 4, 6]
        actual = Extractor.abcissa(self.data, 1)
        np.testing.assert_equal(expected, actual)

        expected = [0, 2, 4, 6, 8]
        actual = Extractor.abcissa(self.data, 2)
        np.testing.assert_equal(expected, actual)

    def test_spectrum(self):
        roi = RectangularROI()
        roi.update_limits(0, 0, 3, 3)

        expected = self.x[:, :3, :3].mean(axis=1).mean(axis=1)
        _, actual = Extractor.spectrum(
            self.data, self.data.id['x'], roi, (0, 'x', 'y'), 0)
        np.testing.assert_array_almost_equal(expected, actual)

    def test_spectrum_oob(self):
        roi = RectangularROI()
        roi.update_limits(-1, -1, 3, 3)

        expected = self.x[:, :3, :3].mean(axis=1).mean(axis=1)

        _, actual = Extractor.spectrum(self.data, self.data.id['x'],
                                       roi, (0, 'x', 'y'), 0)
        np.testing.assert_array_almost_equal(expected, actual)

    def test_pixel2world(self):
        # p2w(x) = 2x, 0 <= x <= 2
        assert Extractor.pixel2world(self.data, 0, 1) == 2

        # clips to boundary
        assert Extractor.pixel2world(self.data, 0, -1) == 0
        assert Extractor.pixel2world(self.data, 0, 5) == 4

    def test_world2pixel(self):
        # w2p(x) = x/2, 0 <= x <= 4
        assert Extractor.world2pixel(self.data, 0, 2.01) == 1

        # clips to boundary
        assert Extractor.world2pixel(self.data, 0, -1) == 0
        assert Extractor.world2pixel(self.data, 0, 8) == 2

    def test_extract_subset(self):
        sub = self.data.new_subset()
        sub.subset_state = self.data.id['x'] > .5
        slc = (0, 'y', 'x')
        mask = sub.to_mask()[0]
        mask = mask.reshape(-1, mask.shape[0], mask.shape[1])

        expected = (self.x * mask).sum(axis=1).sum(axis=1)
        expected /= mask.sum(axis=1).sum(axis=1)
        _, actual = Extractor.subset_spectrum(sub, self.data.id['x'],
                                              slc, 0)
        np.testing.assert_array_almost_equal(expected, actual)
Example #29
0
class TestHistogramLayerArtist(object):

    def setup_method(self, method):

        self.viewer_state = HistogramViewerState()

        ax = plt.subplot(1, 1, 1)

        self.data = Data(x=[1, 2, 3], y=[2, 3, 4])
        self.subset = self.data.new_subset()
        self.subset.subset_state = self.data.id['x'] > 1

        dc = DataCollection([self.data])

        # TODO: The following line shouldn't be needed
        self.viewer_state.data_collection = dc

        self.artist = HistogramLayerArtist(ax, self.viewer_state, layer=self.subset)
        self.layer_state = self.artist.state
        self.viewer_state.layers.append(self.layer_state)

        self.call_counter = CallCounter()
        sys.setprofile(self.call_counter)

    def teardown_method(self, method):
        sys.setprofile(None)

    def test_recalc_on_state_changes(self):

        assert self.call_counter['_calculate_histogram'] == 0
        assert self.call_counter['_scale_histogram'] == 0

        # attribute
        self.viewer_state.x_att = self.data.id['y']
        assert self.call_counter['_calculate_histogram'] == 1
        assert self.call_counter['_scale_histogram'] == 1

        # lo
        self.viewer_state.hist_x_min = -1
        assert self.call_counter['_calculate_histogram'] == 2
        assert self.call_counter['_scale_histogram'] == 2

        # hi
        self.viewer_state.hist_x_max = 5
        assert self.call_counter['_calculate_histogram'] == 3
        assert self.call_counter['_scale_histogram'] == 3

        # nbins
        self.viewer_state.hist_n_bin += 1
        assert self.call_counter['_calculate_histogram'] == 4
        assert self.call_counter['_scale_histogram'] == 4

        # xlog
        self.viewer_state.x_log ^= True
        assert self.call_counter['_calculate_histogram'] == 5
        assert self.call_counter['_scale_histogram'] == 5

        # ylog -- no call
        self.viewer_state.y_log ^= True
        assert self.call_counter['_calculate_histogram'] == 5
        assert self.call_counter['_scale_histogram'] == 6

        # cumulative -- no call
        self.viewer_state.cumulative ^= True
        assert self.call_counter['_calculate_histogram'] == 5
        assert self.call_counter['_scale_histogram'] == 7

        # normed -- no call
        self.viewer_state.normalize ^= True
        assert self.call_counter['_calculate_histogram'] == 5
        assert self.call_counter['_scale_histogram'] == 8

        # subset style -- no call
        self.subset.style.color = '#00ff00'
        assert self.call_counter['_calculate_histogram'] == 5
        assert self.call_counter['_scale_histogram'] == 8
Example #30
0
class TestWWTDataViewer(object):
    def setup_method(self, method):
        self.d = Data(x=[1, 2, 3], y=[2, 3, 4])
        self.dc = DataCollection([self.d])
        self.hub = self.dc.hub
        self.session = Session(data_collection=self.dc, hub=self.hub)
        self.widget = WWTDataViewer(self.session, webdriver_class=MagicMock)
        self.options = self.widget.options_widget()

    def register(self):
        self.widget.register_to_hub(self.hub)

    def test_add_data(self):
        self.widget.add_data(self.d)
        self.options.ra_att = self.d.id['x'], self.d
        self.options.dec_att = self.d.id['y'], self.d
        assert self.d in self.widget

    def test_double_add_ignored(self):
        assert len(self.widget) == 0
        self.widget.add_data(self.d)
        assert len(self.widget) == 1
        self.widget.add_data(self.d)
        assert len(self.widget) == 1

    def test_updated_on_data_update_message(self):
        self.register()
        self.widget.add_data(self.d)
        layer = self.widget._layer_artist_container[self.d][0]
        layer.update = MagicMock()
        self.d.style.color = 'green'
        assert layer.update.call_count == 1

    def test_updated_on_subset_update_message(self):
        self.register()
        s = self.d.new_subset()
        self.widget.add_subset(s)
        layer = self.widget._layer_artist_container[s][0]
        layer.update = MagicMock()
        s.style.color = 'green'
        assert layer.update.call_count == 1

    def test_remove_data(self):
        self.register()
        self.widget.add_data(self.d)
        layer = self.widget._layer_artist_container[self.d][0]

        layer.clear = MagicMock()
        self.hub.broadcast(
            message.DataCollectionDeleteMessage(self.dc, data=self.d))
        # TODO: the following currently fails but is not critical, so we
        #       skip for now.
        # assert layer.clear.call_count == 1
        assert self.d not in self.widget

    def test_remove_subset(self):
        self.register()
        s = self.d.new_subset()
        self.widget.add_subset(s)

        layer = self.widget._layer_artist_container[s][0]
        layer.clear = MagicMock()

        self.hub.broadcast(message.SubsetDeleteMessage(s))

        assert layer.clear.call_count == 1
        assert self.d not in self.widget

    def test_subsets_added_with_data(self):
        s = self.d.new_subset()
        self.widget.add_data(self.d)
        assert s in self.widget

    def test_subsets_live_added(self):
        self.register()
        self.widget.add_data(self.d)
        s = self.d.new_subset()
        assert s in self.widget

    # TODO: determine if the following test is the desired behavior
    # def test_subsets_not_live_added_if_data_not_present(self):
    #     self.register()
    #     s = self.d.new_subset()
    #     assert s not in self.widget

    def test_updated_on_add(self):
        self.register()
        self.widget._update_layer = MagicMock()
        self.widget.add_data(self.d)
        # TODO: ideally, the following should be called exactly once
        assert self.widget._update_layer.call_count >= 1

    def test_updated_on_coordinate_change(self):
        self.register()
        self.widget.add_data(self.d)
        self.options.ra_att = self.d.id['x'], self.d
        self.options.dec_att = self.d.id['y'], self.d
        artist = self.widget._layer_artist_container[self.d][0]
        self.widget._update_layer = MagicMock()
        self.options.ra_att = self.d.id['y'], self.d
        self.widget._update_layer.call_count > 0
Example #31
0
class TestProfileViewer(object):
    def setup_method(self, method):

        self.data = Data(label='d1')
        self.data.coords = SimpleCoordinates()
        self.data['x'] = np.arange(24).reshape((3, 4, 2))

        self.app = GlueApplication()
        self.session = self.app.session
        self.hub = self.session.hub

        self.data_collection = self.session.data_collection
        self.data_collection.append(self.data)

        self.viewer = self.app.new_data_viewer(ProfileViewer)

    def teardown_method(self, method):
        self.viewer.close()
        self.viewer = None
        self.app.close()
        self.app = None

    def test_functions(self):
        self.viewer.add_data(self.data)
        self.viewer.state.function = 'mean'
        assert len(self.viewer.layers) == 1
        layer_artist = self.viewer.layers[0]
        assert_allclose(layer_artist.state.profile[0], [0, 2, 4])
        assert_allclose(layer_artist.state.profile[1], [3.5, 11.5, 19.5])

    def test_incompatible(self):
        self.viewer.add_data(self.data)
        data2 = Data(y=np.random.random((3, 4, 2)))
        self.data_collection.append(data2)
        self.viewer.add_data(data2)
        assert len(self.viewer.layers) == 2
        assert self.viewer.layers[0].enabled
        assert not self.viewer.layers[1].enabled

    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])

    def test_enabled_layers(self):

        data2 = Data(label='d1', y=np.arange(24).reshape((3, 4, 2)))
        self.data_collection.append(data2)

        self.viewer.add_data(self.data)
        self.viewer.add_data(data2)

        assert self.viewer.layers[0].enabled
        assert not self.viewer.layers[1].enabled

        self.data_collection.add_link(
            ComponentLink([data2.world_component_ids[1]],
                          self.data.world_component_ids[0],
                          using=lambda x: 2 * x))

        assert self.viewer.layers[0].enabled
        assert self.viewer.layers[1].enabled

    def test_slice_subset_state(self):

        self.viewer.add_data(self.data)

        subset = self.data.new_subset()
        subset.subset_state = SliceSubsetState(
            self.data, [slice(1, 2), slice(None)])

        assert self.viewer.layers[0].enabled
        assert self.viewer.layers[1].enabled

    def test_clone(self):

        # Regression test for a bug that meant that deserializing a profile
        # viewer resulted in disabled layers

        self.viewer.add_data(self.data)

        subset = self.data.new_subset()
        subset.subset_state = SliceSubsetState(
            self.data, [slice(1, 2), slice(None)])

        app = clone(self.app)

        assert app.viewers[0][0].layers[0].enabled
        assert app.viewers[0][0].layers[1].enabled

        app.close()

    def test_incompatible_on_add(self):

        # Regression test for a bug when adding a dataset to a profile viewer
        # with a single incompatible subset.

        subset_state = SliceSubsetState(self.data, [slice(1, 2), slice(None)])
        self.data_collection.new_subset_group(subset_state=subset_state,
                                              label='s1')

        data2 = Data(x=[[2, 3], [4, 3]], label='d2')
        self.data_collection.append(data2)
        self.viewer.add_data(data2)