Exemplo n.º 1
0
def test_n_dimensional_data():

    # Create fake data
    data = Data(x=np.random.random((2, 3, 4, 5)),
                y=np.random.random((2, 3, 4, 5)),
                z=np.random.random((2, 3, 4, 5)))

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    scatter = ga.new_data_viewer(VispyScatterViewer)
    scatter.add_data(data)

    layer_artist = scatter.layers[0]
    style_widget = scatter._view.layout_style_widgets[layer_artist]

    style_widget.size_mode = 'Linear'
    style_widget.size_attribute = data.id['x']

    style_widget.color_mode = 'Linear'
    style_widget.cmap_attribute = data.id['y']
    style_widget.cmap = cm.BuGn

    ga.close()
Exemplo n.º 2
0
def test_error_bars(tmpdir):

    # Create fake data
    data = make_test_data()

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    scatter = ga.new_data_viewer(VispyScatterViewer)
    scatter.add_data(data)
    scatter.viewer_size = (400, 500)

    viewer_state = scatter.state

    viewer_state.x_att = data.id['a']
    viewer_state.y_att = data.id['f']
    viewer_state.z_att = data.id['z']

    layer_state = viewer_state.layers[0]

    layer_state.xerr_visible = True
    layer_state.xerr_attribute = data.id['b']

    layer_state.yerr_visible = False
    layer_state.yerr_attribute = data.id['c']

    layer_state.zerr_visible = True
    layer_state.zerr_attribute = data.id['d']

    assert viewer_state.line_width == 1

    # Check that writing a session works as expected.

    session_file = tmpdir.join('test_error_bars.glu').strpath
    ga.save_session(session_file)
    ga.close()

    # Now we can check that everything is restored correctly

    ga2 = GlueApplication.restore_session(session_file)
    ga2.show()

    scatter_r = ga2.viewers[0][0]
    layer_state = scatter_r.state.layers[0]

    assert layer_state.xerr_visible
    assert layer_state.xerr_attribute.label == 'b'

    assert not layer_state.yerr_visible
    assert layer_state.yerr_attribute.label == 'c'

    assert layer_state.zerr_visible
    assert layer_state.zerr_attribute.label == 'd'

    assert scatter_r.state.line_width == 1

    ga2.close()
Exemplo n.º 3
0
    def test_session_round_trip(self, tmpdir):

        self.init_subset()

        ga = GlueApplication(self.data_collection)
        ga.show()

        viewer = ga.new_data_viewer(self.viewer_cls)
        viewer.add_data(self.data)

        session_file = tmpdir.join('test_session_round_trip.glu').strpath
        ga.save_session(session_file)
        ga.close()

        ga2 = GlueApplication.restore_session(session_file)
        ga2.show()

        viewer2 = ga2.viewers[0][0]

        data2 = ga2.data_collection[0]

        assert viewer2.layers[0].layer is data2
        assert viewer2.layers[1].layer is data2.subsets[0]

        ga2.close()
Exemplo n.º 4
0
def test_categorical_color_size(tmpdir):

    # Create fake data
    data = make_test_data()

    # Add categorical component
    data['categorical'] = ['a', 'b'] * 50

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    scatter = ga.new_data_viewer(VispyScatterViewer)
    scatter.add_data(data)

    viewer_state = scatter.state

    viewer_state.x_att = data.id['a']
    viewer_state.y_att = data.id['b']
    viewer_state.z_att = data.id['z']

    layer_state = viewer_state.layers[0]

    layer_state.size_mode = 'Linear'
    layer_state.size_attribute = data.id['categorical']

    layer_state.color_mode = 'Linear'
    layer_state.cmap_attribute = data.id['categorical']

    ga.close()
Exemplo n.º 5
0
    def test_session_round_trip(self, tmpdir):

        self.init_subset()

        ga = GlueApplication(self.data_collection)
        ga.show()

        viewer = ga.new_data_viewer(self.viewer_cls)
        viewer.add_data(self.data)

        session_file = tmpdir.join('test_session_round_trip.glu').strpath
        ga.save_session(session_file)
        ga.close()

        ga2 = GlueApplication.restore_session(session_file)
        ga2.show()

        viewer2 = ga2.viewers[0][0]

        data2 = ga2.data_collection[0]

        assert viewer2.layers[0].layer is data2
        assert viewer2.layers[1].layer is data2.subsets[0]

        ga2.close()
def test_layer_visibility_clip():

    # Regression test for a bug that meant that updating the clip data setting
    # caused a layer to become visible even if it shouldn't be

    # Create fake data
    data = make_test_data()

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    volume = ga.new_data_viewer(VispyVolumeViewer)
    volume.add_data(data)

    assert volume.layers[0].visible
    assert volume.layers[0]._multivol.enabled[0]

    volume.layers[0].visible = False

    assert not volume.layers[0].visible
    assert not volume.layers[0]._multivol.enabled[0]

    volume.state.clip_data = True

    assert not volume.layers[0].visible
    assert not volume.layers[0]._multivol.enabled[0]

    ga.close()
Exemplo n.º 7
0
class TestExportPython(BaseTestExportPython):
    def setup_method(self, method):

        with NumpyRNGContext(12345):
            self.data = Data(cube=np.random.random((30, 50, 20)))
        self.data_collection = DataCollection([self.data])
        self.app = GlueApplication(self.data_collection)
        self.viewer = self.app.new_data_viewer(ImageViewer)
        self.viewer.add_data(self.data)
        # FIXME: On some platforms, using an integer label size
        # causes some of the labels to be non-deterministically
        # shifted by one pixel, so we pick a non-round font size
        # to avoid this.
        self.viewer.state.x_ticklabel_size = 8.21334111
        self.viewer.state.y_ticklabel_size = 8.21334111

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

    def test_simple(self, tmpdir):
        self.assert_same(tmpdir)

    def test_simple_att(self, tmpdir):
        self.viewer.state.x_att = self.data.pixel_component_ids[1]
        self.viewer.state.y_att = self.data.pixel_component_ids[0]
        self.assert_same(tmpdir)

    def test_simple_visual(self, tmpdir):
        self.viewer.state.layers[0].cmap = plt.cm.RdBu
        self.viewer.state.layers[0].v_min = 0.2
        self.viewer.state.layers[0].v_max = 0.8
        self.viewer.state.layers[0].stretch = 'sqrt'
        self.viewer.state.layers[0].stretch = 'sqrt'
        self.viewer.state.layers[0].contrast = 0.9
        self.viewer.state.layers[0].bias = 0.6
        self.assert_same(tmpdir)

    def test_slice(self, tmpdir):
        self.viewer.state.x_att = self.data.pixel_component_ids[1]
        self.viewer.state.y_att = self.data.pixel_component_ids[0]
        self.viewer.state.slices = (2, 3, 4)
        self.assert_same(tmpdir)

    def test_aspect(self, tmpdir):
        self.viewer.state.aspect = 'auto'
        self.assert_same(tmpdir)

    def test_subset(self, tmpdir):
        self.data_collection.new_subset_group('mysubset',
                                              self.data.id['cube'] > 0.5)
        self.assert_same(tmpdir)

    def test_subset_slice(self, tmpdir):
        self.data_collection.new_subset_group('mysubset',
                                              self.data.id['cube'] > 0.5)
        self.test_slice(tmpdir)
Exemplo n.º 8
0
class TestExportPython(BaseTestExportPython):

    def setup_method(self, method):

        with NumpyRNGContext(12345):
            self.data = Data(cube=np.random.random((30, 50, 20)))
        self.data_collection = DataCollection([self.data])
        self.app = GlueApplication(self.data_collection)
        self.viewer = self.app.new_data_viewer(ImageViewer)
        self.viewer.add_data(self.data)
        # FIXME: On some platforms, using an integer label size
        # causes some of the labels to be non-deterministically
        # shifted by one pixel, so we pick a non-round font size
        # to avoid this.
        self.viewer.state.x_ticklabel_size = 8.21334111
        self.viewer.state.y_ticklabel_size = 8.21334111

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

    def test_simple(self, tmpdir):
        self.assert_same(tmpdir)

    def test_simple_att(self, tmpdir):
        self.viewer.state.x_att = self.data.pixel_component_ids[1]
        self.viewer.state.y_att = self.data.pixel_component_ids[0]
        self.assert_same(tmpdir)

    def test_simple_visual(self, tmpdir):
        self.viewer.state.layers[0].cmap = plt.cm.RdBu
        self.viewer.state.layers[0].v_min = 0.2
        self.viewer.state.layers[0].v_max = 0.8
        self.viewer.state.layers[0].stretch = 'sqrt'
        self.viewer.state.layers[0].stretch = 'sqrt'
        self.viewer.state.layers[0].contrast = 0.9
        self.viewer.state.layers[0].bias = 0.6
        self.assert_same(tmpdir)

    def test_slice(self, tmpdir):
        self.viewer.state.x_att = self.data.pixel_component_ids[1]
        self.viewer.state.y_att = self.data.pixel_component_ids[0]
        self.viewer.state.slices = (2, 3, 4)
        self.assert_same(tmpdir)

    def test_aspect(self, tmpdir):
        self.viewer.state.aspect = 'auto'
        self.assert_same(tmpdir)

    def test_subset(self, tmpdir):
        self.data_collection.new_subset_group('mysubset', self.data.id['cube'] > 0.5)
        self.assert_same(tmpdir)

    def test_subset_slice(self, tmpdir):
        self.data_collection.new_subset_group('mysubset', self.data.id['cube'] > 0.5)
        self.test_slice(tmpdir)
Exemplo n.º 9
0
class TestExportPython(BaseTestExportPython):
    def setup_method(self, method):

        with NumpyRNGContext(12345):
            self.data = Data(**dict(
                (name, random_with_nan(100, nan_index=idx + 1))
                for idx, name in enumerate('abcdefgh')))
        self.data_collection = DataCollection([self.data])
        self.app = GlueApplication(self.data_collection)
        self.viewer = self.app.new_data_viewer(HistogramViewer)
        self.viewer.add_data(self.data)
        self.viewer.state.x_att = self.data.id['a']

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

    def test_simple(self, tmpdir):
        self.assert_same(tmpdir)

    def test_simple_visual(self, tmpdir):
        self.viewer.state.layers[0].color = 'blue'
        self.viewer.state.layers[0].alpha = 0.5
        self.assert_same(tmpdir)

    def test_simple_visual_legend(self, tmpdir):
        self.viewer.state.legend.visible = True
        self.viewer.state.layers[0].color = 'blue'
        self.viewer.state.layers[0].alpha = 0.5
        self.assert_same(tmpdir)

    def test_cumulative(self, tmpdir):
        self.viewer.state.cumulative = True
        self.assert_same(tmpdir)

    def test_normalize(self, tmpdir):
        self.viewer.state.normalize = True
        self.assert_same(tmpdir)

    def test_subset(self, tmpdir):
        self.data_collection.new_subset_group('mysubset',
                                              self.data.id['a'] > 0.5)
        self.assert_same(tmpdir)

    def test_subset_legend(self, tmpdir):
        self.viewer.state.legend.visible = True
        self.data_collection.new_subset_group('mysubset',
                                              self.data.id['a'] > 0.5)
        self.assert_same(tmpdir)

    def test_empty(self, tmpdir):
        self.viewer.state.x_min = 10
        self.viewer.state.x_max = 11
        self.viewer.state.hist_x_min = 10
        self.viewer.state.hist_x_max = 11
        self.assert_same(tmpdir)
Exemplo n.º 10
0
def test_save_d3po(tmpdir):

    from glue.app.qt.application import GlueApplication
    from glue.viewers.scatter.qt import ScatterViewer
    from glue.viewers.histogram.qt import HistogramViewer

    output = tmpdir.join('output.html').strpath

    d = Data(x=[1, 2, 3], y=[2, 3, 4], label='data')
    dc = DataCollection([d])
    app = GlueApplication(dc)
    app.new_data_viewer(ScatterViewer, data=d)
    app.new_data_viewer(HistogramViewer, data=d)
    save_d3po(app, output, launch=False)
    app.close()
Exemplo n.º 11
0
def test_save_d3po(tmpdir):

    from glue.app.qt.application import GlueApplication
    from glue.viewers.scatter.qt import ScatterViewer
    from glue.viewers.histogram.qt import HistogramViewer

    output = tmpdir.join('output.html').strpath

    d = Data(x=[1, 2, 3], y=[2, 3, 4], label='data')
    dc = DataCollection([d])
    app = GlueApplication(dc)
    app.new_data_viewer(ScatterViewer, data=d)
    app.new_data_viewer(HistogramViewer, data=d)
    save_d3po(app, output, launch=False)
    app.close()
Exemplo n.º 12
0
def test_add_data_with_incompatible_subsets(tmpdir):

    data1 = Data(label="Data 1", x=np.arange(24).reshape((4, 3, 2)))
    data2 = Data(label="Data 2", y=np.arange(24).reshape((4, 3, 2)))

    dc = DataCollection([data1, data2])
    ga = GlueApplication(dc)
    ga.show()

    # Subset is defined in terms of data2, so it's an incompatible subset
    # for data1
    dc.new_subset_group(subset_state=data2.id['y'] > 0.5, label='subset 1')

    volume = ga.new_data_viewer(VispyVolumeViewer)
    volume.add_data(data1)

    ga.close()
Exemplo n.º 13
0
class TestExportPython(BaseTestExportPython):

    def setup_method(self, method):

        with NumpyRNGContext(12345):
            self.data = Data(**dict((name, random_with_nan(100, nan_index=idx + 1)) for idx, name in enumerate('abcdefgh')))
        self.data_collection = DataCollection([self.data])
        self.app = GlueApplication(self.data_collection)
        self.viewer = self.app.new_data_viewer(HistogramViewer)
        self.viewer.add_data(self.data)
        self.viewer.state.x_att = self.data.id['a']

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

    def test_simple(self, tmpdir):
        self.assert_same(tmpdir)

    def test_simple_visual(self, tmpdir):
        self.viewer.state.layers[0].color = 'blue'
        self.viewer.state.layers[0].alpha = 0.5
        self.assert_same(tmpdir)

    def test_cumulative(self, tmpdir):
        self.viewer.state.cumulative = True
        self.assert_same(tmpdir)

    def test_normalize(self, tmpdir):
        self.viewer.state.normalize = True
        self.assert_same(tmpdir)

    def test_subset(self, tmpdir):
        self.data_collection.new_subset_group('mysubset', self.data.id['a'] > 0.5)
        self.assert_same(tmpdir)

    def test_empty(self, tmpdir):
        self.viewer.state.x_min = 10
        self.viewer.state.x_max = 11
        self.viewer.state.hist_x_min = 10
        self.viewer.state.hist_x_max = 11
        self.assert_same(tmpdir)
Exemplo n.º 14
0
def test_array_shape(tmpdir):
    # Create irregularly shaped data cube
    data = make_test_data((3841, 48, 46))

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)

    volume = ga.new_data_viewer(VispyVolumeViewer)
    volume.add_data(data)

    viewer_state = volume.state

    # Get layer artist style editor
    layer_state = viewer_state.layers[0]

    layer_state.attribute = data.id['b']

    ga.close()
Exemplo n.º 15
0
def test_add_data_with_incompatible_subsets(tmpdir):

    # Regression test for a bug that an error when adding a dataset with an
    # incompatible subset to a 3D scatter viewer.

    data1 = Data(label="Data 1", x=[1, 2, 3])
    data2 = Data(label="Data 2", y=[4, 5, 6])

    dc = DataCollection([data1, data2])
    ga = GlueApplication(dc)
    ga.show()

    # Subset is defined in terms of data2, so it's an incompatible subset
    # for data1
    dc.new_subset_group(subset_state=data2.id['y'] > 0.5, label='subset 1')

    scatter = ga.new_data_viewer(VispyScatterViewer)
    scatter.add_data(data1)

    ga.close()
Exemplo n.º 16
0
def test_scatter_remove_layer_artists(tmpdir):

    # Regression test for a bug that caused layer states to not be removed
    # when the matching layer artist was removed. This then caused issues when
    # loading session files.

    # Create fake data
    data = make_test_data()

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    scatter = ga.new_data_viewer(VispyScatterViewer)
    scatter.add_data(data)

    dc.new_subset_group(subset_state=data.id['x'] > 0.5, label='subset 1')

    scatter.add_subset(data.subsets[0])

    assert len(scatter.layers) == 2
    assert len(scatter.state.layers) == 2

    dc.remove_subset_group(dc.subset_groups[0])

    assert len(scatter.layers) == 1
    assert len(scatter.state.layers) == 1

    # Check that writing a session works as expected.

    session_file = tmpdir.join('test_scatter_viewer.glu').strpath
    ga.save_session(session_file)
    ga.close()

    # Now we can check that everything is restored correctly

    ga2 = GlueApplication.restore_session(session_file)
    ga2.show()
    ga2.close()
Exemplo n.º 17
0
def test_not_all_points_inside_limits(tmpdir):

    # Regression test for a bug that occurred when not all points were inside
    # the visible limits and the color or size mode is linear.

    data1 = Data(label="Data", x=[1, 2, 3])

    dc = DataCollection([data1])
    ga = GlueApplication(dc)
    ga.show()

    scatter = ga.new_data_viewer(VispyScatterViewer)
    scatter.add_data(data1)

    scatter.state.layers[0].color_mode = 'Linear'
    scatter.state.layers[0].size_mode = 'Linear'

    scatter.state.x_min = -0.1
    scatter.state.x_max = 2.1

    ga.close()
Exemplo n.º 18
0
def test_scatter_remove_layer_artists(tmpdir):

    # Regression test for a bug that caused layer states to not be removed
    # when the matching layer artist was removed. This then caused issues when
    # loading session files.

    # Create fake data
    data = make_test_data()

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    scatter = ga.new_data_viewer(VispyScatterViewer)
    scatter.add_data(data)

    dc.new_subset_group(subset_state=data.id['x'] > 0.5, label='subset 1')

    scatter.add_subset(data.subsets[0])

    assert len(scatter.layers) == 2
    assert len(scatter.state.layers) == 2

    dc.remove_subset_group(dc.subset_groups[0])

    assert len(scatter.layers) == 1
    assert len(scatter.state.layers) == 1

    # Check that writing a session works as expected.

    session_file = tmpdir.join('test_scatter_viewer.glu').strpath
    ga.save_session(session_file)
    ga.close()

    # Now we can check that everything is restored correctly

    ga2 = GlueApplication.restore_session(session_file)
    ga2.show()
Exemplo n.º 19
0
def test_layer_visibility_after_session(tmpdir):

    # Regression test for a bug that caused layers to be incorrectly visible
    # after saving and loading a session file.

    # Create fake data
    data = make_test_data()

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    scatter = ga.new_data_viewer(VispyScatterViewer)
    scatter.add_data(data)

    viewer_state = scatter.state
    layer_state = viewer_state.layers[0]
    layer_state.visible = False

    session_file = tmpdir.join('test_layer_visibility.glu').strpath
    ga.save_session(session_file)
    ga.close()

    ga2 = GlueApplication.restore_session(session_file)
    ga2.show()

    scatter_r = ga2.viewers[0][0]
    viewer_state = scatter_r.state
    layer_state = viewer_state.layers[0]
    assert not layer_state.visible

    # Make sure the multiscat layer is also not visible (this was where the bug was)
    layer_artist = scatter_r.layers[0]
    assert not layer_artist._multiscat.layers[layer_artist.id]['visible']

    ga2.close()
Exemplo n.º 20
0
def test_remove_subset_group():

    # Regression test for a bug that meant that removing a subset caused an
    # error when multiple viewers were present.

    # Create fake data
    data = make_test_data()

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    volume1 = ga.new_data_viewer(VispyVolumeViewer)
    volume1.add_data(data)

    volume2 = ga.new_data_viewer(VispyVolumeViewer)
    volume2.add_data(data)

    dc.new_subset_group(subset_state=data.id['a'] > 0, label='Subset 1')
    dc.remove_subset_group(dc.subset_groups[0])

    ga.close()
Exemplo n.º 21
0
def test_scatter_on_volume(tmpdir):

    data1 = Data(a=np.arange(60).reshape((3, 4, 5)))
    data2 = Data(x=[1, 2, 3], y=[2, 3, 4], z=[3, 4, 5])
    data3 = Data(b=np.arange(60).reshape((3, 4, 5)))

    dc = DataCollection([data1, data2, data3])

    dc.add_link(LinkSame(data1.pixel_component_ids[2], data2.id['x']))
    dc.add_link(LinkSame(data1.pixel_component_ids[1], data2.id['y']))
    dc.add_link(LinkSame(data1.pixel_component_ids[0], data2.id['z']))

    ga = GlueApplication(dc)
    ga.show()

    volume = ga.new_data_viewer(VispyVolumeViewer)
    volume.add_data(data1)
    volume.add_data(data2)
    volume.add_data(data3)

    # Check that writing a session works as expected.

    session_file = tmpdir.join('test_scatter_on_volume.glu').strpath
    ga.save_session(session_file)
    ga.close()

    # Now we can check that everything is restored correctly

    ga2 = GlueApplication.restore_session(session_file)
    ga2.show()

    volume_r = ga2.viewers[0][0]

    assert len(volume_r.layers) == 3

    ga2.close()
Exemplo n.º 22
0
def test_scatter_viewer(tmpdir):

    # Create fake data
    data = make_test_data()

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    scatter = ga.new_data_viewer(VispyScatterViewer)
    scatter.add_data(data)
    scatter.viewer_size = (400, 500)

    options = scatter.options_widget()

    options.x_att = data.id['a']
    options.y_att = data.id['f']
    options.z_att = data.id['z']

    options.x_stretch = 0.5
    options.y_stretch = 1.0
    options.z_stretch = 2.0

    options.x_min = -0.1
    options.x_max = 1.1
    options.y_min = 0.1
    options.y_max = 0.9
    options.z_min = 0.2
    options.z_max = 0.8

    options.visible_box = False

    # Get layer artist style editor
    layer_artist = scatter.layers[0]
    style_widget = scatter._view.layout_style_widgets[layer_artist]

    style_widget.size_mode = 'Linear'
    style_widget.size_attribute = data.id['c']
    style_widget.size_scaling = 2
    style_widget.size_vmin = 0.2
    style_widget.size_vmax = 0.8

    style_widget.color_mode = 'Linear'
    style_widget.cmap_attribute = data.id['y']
    style_widget.cmap_vmin = 0.1
    style_widget.cmap_vmax = 0.9
    style_widget.cmap = cm.BuGn

    # Check that writing a session works as expected. However, this only
    # works with Glue 0.8 and above, so we skip this test if we are using an
    # older version.

    if GLUE_LT_08:
        return

    session_file = tmpdir.join('test_scatter_viewer.glu').strpath
    ga.save_session(session_file)
    ga.close()

    # Now we can check that everything is restored correctly

    ga2 = GlueApplication.restore_session(session_file)
    ga2.show()

    scatter_r = ga2.viewers[0][0]

    assert scatter_r.viewer_size == (400, 500)

    options = scatter_r.options_widget()

    assert options.x_att.label == 'a'
    assert options.y_att.label == 'f'
    assert options.z_att.label == 'z'

    assert options.x_stretch == 0.5
    assert options.y_stretch == 1.0
    assert options.z_stretch == 2.0

    assert options.x_min == -0.1
    assert options.x_max == 1.1
    assert options.y_min == 0.1
    assert options.y_max == 0.9
    assert options.z_min == 0.2
    assert options.z_max == 0.8

    assert not options.visible_box

    layer_artist = scatter_r.layers[0]

    assert layer_artist.size_mode == 'linear'
    assert layer_artist.size_attribute.label == 'c'
    np.testing.assert_allclose(layer_artist.size_scaling, 2, rtol=0.01)
    assert layer_artist.size_vmin == 0.2
    assert layer_artist.size_vmax == 0.8

    assert layer_artist.color_mode == 'linear'
    assert layer_artist.cmap_attribute.label == 'y'
    assert layer_artist.cmap_vmin == 0.1
    assert layer_artist.cmap_vmax == 0.9
    assert layer_artist.cmap is cm.BuGn
Exemplo n.º 23
0
class BaseTestMatplotlibDataViewer(object):
    """
    Base class to test viewers based on MatplotlibDataViewer. This only runs
    a subset of tests that relate to functionality implemented in
    MatplotlibDataViewer and specific viewers are responsible for implementing
    a more complete test suite.

    Viewers based on this should inherit from this test class and define the
    following attributes:

    * ``data``: an instance of a data object that works by default in the viewer
    * ``viewer_cls``: the viewer class

    It is then safe to assume that ``data_collection``, ``viewer``, and ``hub``
    are defined when writing tests.
    """
    def setup_method(self, method):

        if OBJGRAPH_INSTALLED:
            self.viewer_count_start = self.viewer_count

        self.data = self.init_data()

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

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

        self.viewer = self.viewer_cls(self.session)

        self.data_collection.register_to_hub(self.hub)
        self.viewer.register_to_hub(self.hub)

    def init_subset(self):
        cid = self.data.main_components[0]
        self.data_collection.new_subset_group('subset 1', cid > 0)

    @property
    def viewer_count(self):
        app = get_qapp()
        app.processEvents()
        obj = objgraph.by_type(self.viewer_cls.__name__)
        return len(obj)

    def teardown_method(self, method):

        if self.viewer is not None:
            self.viewer.close()
        self.application.close()

        # The following is a check to make sure that once the viewer and
        # application have been closed, there are no leftover references to
        # the data viewer. This was introduced because there were previously
        # circular references that meant that viewer instances were not
        # properly garbage collected, which in turn meant they still reacted
        # in some cases to events.
        if OBJGRAPH_INSTALLED:
            self.viewer = None
            self.application = None
            if self.viewer_count > self.viewer_count_start:
                objgraph.show_backrefs(
                    objgraph.by_type(self.viewer_cls.__name__))
                raise ValueError("No net viewers should be created in tests")

    def test_add_data(self):

        # Add a dataset with no subsets and make sure the appropriate layer
        # state and layer artists are created

        self.viewer.add_data(self.data)

        assert len(self.viewer.layers) == 1
        assert self.viewer.layers[0].layer is self.data

        assert len(self.viewer.state.layers) == 1
        assert self.viewer.state.layers[0].layer is self.data

    def test_add_data_with_subset(self):

        # Make sure that if subsets are present in the data, they are added
        # automatically

        self.init_subset()
        self.viewer.add_data(self.data)

        assert len(self.viewer.layers) == 2
        assert self.viewer.layers[0].layer is self.data
        assert self.viewer.layers[1].layer is self.data.subsets[0]

        assert len(self.viewer.state.layers) == 2
        assert self.viewer.state.layers[0].layer is self.data
        assert self.viewer.state.layers[1].layer is self.data.subsets[0]

    def test_add_data_then_subset(self):

        # Make sure that if a subset is created in a dataset that has already
        # been added to a viewer, the subset gets added

        self.viewer.add_data(self.data)

        assert len(self.viewer.layers) == 1
        assert self.viewer.layers[0].layer is self.data

        assert len(self.viewer.state.layers) == 1
        assert self.viewer.state.layers[0].layer is self.data

        self.init_subset()

        assert len(self.viewer.layers) == 2
        assert self.viewer.layers[0].layer is self.data
        assert self.viewer.layers[1].layer is self.data.subsets[0]

        assert len(self.viewer.state.layers) == 2
        assert self.viewer.state.layers[0].layer is self.data
        assert self.viewer.state.layers[1].layer is self.data.subsets[0]

    def init_draw_count(self):
        self.mpl_counter = MatplotlibDrawCounter(self.viewer.axes.figure)

    @property
    def draw_count(self):
        return self.mpl_counter.draw_count

    def test_single_draw(self):
        # Make sure that the number of draws is kept to a minimum
        self.init_draw_count()
        self.init_subset()
        assert self.draw_count == 0
        self.viewer.add_data(self.data)
        assert self.draw_count == 1

    def test_update_subset(self):

        self.init_draw_count()

        # Check that updating a subset causes the plot to be updated

        self.init_subset()

        assert self.draw_count == 0

        self.viewer.add_data(self.data)

        count_before = self.draw_count

        # Change the subset
        cid = self.data.main_components[0]
        self.data.subsets[0].subset_state = cid > 1

        # Make sure the figure has been redrawn
        assert self.draw_count - count_before > 0

    def test_double_add_ignored(self):
        self.viewer.add_data(self.data)
        assert len(self.viewer.state.layers) == 1
        self.viewer.add_data(self.data)
        assert len(self.viewer.state.layers) == 1

    def test_removing_data_removes_layer_state(self):
        # Removing data from data collection should remove data from viewer
        self.viewer.add_data(self.data)
        assert len(self.viewer.state.layers) == 1
        self.data_collection.remove(self.data)
        assert len(self.viewer.state.layers) == 0

    def test_removing_data_removes_subsets(self):
        # Removing data from data collection should remove subsets from viewer
        self.init_subset()
        self.viewer.add_data(self.data)
        assert len(self.viewer.state.layers) == 2
        self.data_collection.remove(self.data)
        assert len(self.viewer.state.layers) == 0

    def test_removing_subset_removes_layers(self):

        # Removing a layer artist removes the corresponding layer state. We need
        # to do this with a subset otherwise the viewer is closed

        self.init_subset()
        self.viewer.add_data(self.data)

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

        self.data_collection.remove_subset_group(
            self.data_collection.subset_groups[0])

        assert len(self.viewer.layers) == 1
        assert self.viewer.layers[0].layer is self.data

        assert len(self.viewer.state.layers) == 1
        assert self.viewer.state.layers[0].layer is self.data

    def test_removing_layer_artist_removes_layer_state(self):

        # Removing a layer artist removes the corresponding layer state. We need
        # to do this with a subset otherwise the viewer is closed

        self.init_subset()
        self.viewer.add_data(self.data)

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

        # self.layers is a copy so we need to remove from the original list
        self.viewer._layer_artist_container.remove(self.viewer.layers[1])

        assert len(self.viewer.layers) == 1
        assert self.viewer.layers[0].layer is self.data

        assert len(self.viewer.state.layers) == 1
        assert self.viewer.state.layers[0].layer is self.data

    def test_removing_layer_state_removes_layer_artist(self):

        # Removing a layer artist removes the corresponding layer state. We need
        # to do this with a subset otherwise the viewer is closed

        self.init_subset()
        self.viewer.add_data(self.data)

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

        # self.layers is a copy so we need to remove from the original list
        self.viewer.state.layers.pop(1)

        assert len(self.viewer.layers) == 1
        assert self.viewer.layers[0].layer is self.data

        assert len(self.viewer.state.layers) == 1
        assert self.viewer.state.layers[0].layer is self.data

    def test_new_subset_after_remove_data(self):

        # Once we remove a dataset, if we make a new subset, it will not be
        # added to the viewer

        self.init_subset()
        self.viewer.add_data(self.data)

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

        self.viewer.state.layers.pop(0)

        self.init_subset()  # makes a new subset

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

        assert len(self.viewer.layers) == 1
        assert self.viewer.layers[0].layer is self.data.subsets[0]

        assert len(self.viewer.state.layers) == 1
        assert self.viewer.state.layers[0].layer is self.data.subsets[0]

    def test_remove_not_present_ignored(self):
        data = Data(label='not in viewer')
        self.viewer.remove_data(data)

    def test_limits_sync(self):

        viewer_state = self.viewer.state
        axes = self.viewer.axes

        if axes.get_adjustable() == 'datalim':
            pytest.xfail()

        # Make sure that the viewer state and matplotlib viewer limits and log
        # settings are in sync. We start by modifying the state and making sure
        # that the axes follow.

        viewer_state.x_min = 3
        viewer_state.x_max = 9

        viewer_state.y_min = -2
        viewer_state.y_max = 3

        assert axes.get_xlim() == (3, 9)
        assert axes.get_ylim() == (-2, 3)
        assert axes.get_xscale() == 'linear'
        assert axes.get_yscale() == 'linear'

        viewer_state.x_log = True

        assert axes.get_xlim() == (3, 9)
        assert axes.get_ylim() == (-2, 3)
        assert axes.get_xscale() == 'log'
        assert axes.get_yscale() == 'linear'

        viewer_state.y_log = True

        # FIXME: the limits for y don't seem right, should be adjusted because of log?
        assert axes.get_xlim() == (3, 9)
        assert axes.get_ylim() == (-2, 3)
        assert axes.get_xscale() == 'log'
        assert axes.get_yscale() == 'log'

        # Check that changing the axes changes the state

        # NOTE: at the moment this doesn't work because Matplotlib doesn't
        # emit events for changing xscale/yscale. This isn't crucial anyway for
        # glue, but leaving the tests below in case this is fixed some day. The
        # Matplotlib issue is https://github.com/matplotlib/matplotlib/issues/8439

        # axes.set_xscale('linear')
        #
        # assert viewer_state.x_min == 3
        # assert viewer_state.x_max == 9
        # assert viewer_state.y_min == -2
        # assert viewer_state.y_max == 3
        # assert not viewer_state.x_log
        # assert viewer_state.y_log
        #
        # axes.set_yscale('linear')
        #
        # assert viewer_state.x_min == 3
        # assert viewer_state.x_max == 9
        # assert viewer_state.y_min == -2
        # assert viewer_state.y_max == 3
        # assert not viewer_state.x_log
        # assert not viewer_state.y_log

        viewer_state.x_log = False
        viewer_state.y_log = False

        axes.set_xlim(-1, 4)

        assert viewer_state.x_min == -1
        assert viewer_state.x_max == 4
        assert viewer_state.y_min == -2
        assert viewer_state.y_max == 3
        # assert not viewer_state.x_log
        # assert not viewer_state.y_log

        axes.set_ylim(5, 6)

        assert viewer_state.x_min == -1
        assert viewer_state.x_max == 4
        assert viewer_state.y_min == 5
        assert viewer_state.y_max == 6
        # assert not viewer_state.x_log
        # assert not viewer_state.y_log

    # TODO: the following test should deal gracefully with the fact that
    # some viewers will want to show a Qt error for IncompatibleDataException
    def test_add_invalid_data(self):
        data2 = Data()
        with pytest.raises(IncompatibleDataException):
            self.viewer.add_data(data2)

    # Communication tests

    def test_ignore_data_add_message(self):
        self.data_collection.append(self.data)
        assert len(self.viewer.layers) == 0

    def test_update_data_ignored_if_data_not_present(self):
        self.init_draw_count()
        self.data_collection.append(self.data)
        ct0 = self.draw_count
        self.data.style.color = 'blue'
        assert self.draw_count == ct0

    def test_update_data_processed_if_data_present(self):
        self.init_draw_count()
        self.data_collection.append(self.data)
        self.viewer.add_data(self.data)
        ct0 = self.draw_count
        self.data.style.color = 'blue'
        assert self.draw_count > ct0

    def test_add_subset_ignored_if_data_not_present(self):
        self.data_collection.append(self.data)
        sub = self.data.new_subset()
        assert sub not in self.viewer._layer_artist_container

    def test_add_subset_processed_if_data_present(self):
        self.data_collection.append(self.data)
        self.viewer.add_data(self.data)
        sub = self.data.new_subset()
        assert sub in self.viewer._layer_artist_container

    def test_update_subset_ignored_if_not_present(self):
        # This can be quite a difficult test to pass because it makes sure that
        # there are absolutely no references to the layer state left over once
        # a subset is removed - when originally written this identified quite
        # a few places where references were being accidentally kept, and
        # resulted in weakref being needed in a number of places. But ultimately
        # this test should pass! No cheating :)
        self.init_draw_count()
        self.data_collection.append(self.data)
        self.viewer.add_data(self.data)
        sub = self.data.new_subset()
        self.viewer.remove_subset(sub)
        ct0 = self.draw_count
        sub.style.color = 'blue'
        assert self.draw_count == ct0

    def test_update_subset_processed_if_present(self):
        self.init_draw_count()
        self.data_collection.append(self.data)
        self.viewer.add_data(self.data)
        sub = self.data.new_subset()
        ct0 = self.draw_count
        sub.style.color = 'blue'
        assert self.draw_count > ct0

    def test_data_remove_message(self):
        self.data_collection.append(self.data)
        self.viewer.add_data(self.data)
        self.data_collection.remove(self.data)
        assert self.data not in self.viewer._layer_artist_container

    def test_subset_remove_message(self):
        self.data_collection.append(self.data)
        self.viewer.add_data(self.data)
        sub = self.data.new_subset()
        assert sub in self.viewer._layer_artist_container
        sub.delete()
        assert sub not in self.viewer._layer_artist_container

    def test_session_round_trip(self, tmpdir):

        self.init_subset()

        ga = GlueApplication(self.data_collection)
        ga.show()

        viewer = ga.new_data_viewer(self.viewer_cls)
        viewer.add_data(self.data)

        session_file = tmpdir.join('test_session_round_trip.glu').strpath
        ga.save_session(session_file)
        ga.close()

        ga2 = GlueApplication.restore_session(session_file)
        ga2.show()

        viewer2 = ga2.viewers[0][0]

        data2 = ga2.data_collection[0]

        assert viewer2.layers[0].layer is data2
        assert viewer2.layers[1].layer is data2.subsets[0]

        ga2.close()

    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

    def test_numerical_data_changed(self):
        self.init_draw_count()
        self.init_subset()
        assert self.draw_count == 0
        self.viewer.add_data(self.data)
        assert self.draw_count == 1
        data = Data(label=self.data.label)
        data.coords = self.data.coords
        for cid in self.data.main_components:
            if self.data.get_kind(cid) == 'numerical':
                data.add_component(self.data[cid] * 2, cid.label)
            else:
                data.add_component(self.data[cid], cid.label)
        self.data.update_values_from_data(data)
        assert self.draw_count == 2

    @requires_matplotlib_ge_22
    def test_aspect_resize(self):

        # Make sure that the limits are adjusted appropriately when resizing
        # depending on the aspect ratio mode. Note that we don't add any data
        # here since it isn't needed for this test.

        # This test works with Matplotlib 2.0 and 2.2 but not 2.1, hence we
        # skip it with Matplotlib 2.1 above.

        app = get_qapp()

        # Set initial limits to deterministic values
        self.viewer.state.aspect = 'auto'
        self.viewer.state.x_min = 0.
        self.viewer.state.x_max = 1.
        self.viewer.state.y_min = 0.
        self.viewer.state.y_max = 1.

        self.viewer.state.aspect = 'equal'

        # Resize events only work if widget is visible
        self.viewer.show()
        app.processEvents()

        def limits(viewer):
            return (viewer.state.x_min, viewer.state.x_max, viewer.state.y_min,
                    viewer.state.y_max)

        # Set viewer to an initial size and save limits
        self.viewer.viewer_size = (800, 400)
        app.processEvents()
        initial_limits = limits(self.viewer)

        # Change the viewer size, and make sure the limits are adjusted
        self.viewer.viewer_size = (400, 400)
        app.processEvents()
        with pytest.raises(AssertionError):
            assert_allclose(limits(self.viewer), initial_limits)

        # Now change the viewer size a number of times and make sure if we
        # return to the original size, the limits match the initial ones.
        self.viewer.viewer_size = (350, 800)
        app.processEvents()
        self.viewer.viewer_size = (900, 300)
        app.processEvents()
        self.viewer.viewer_size = (600, 600)
        app.processEvents()
        self.viewer.viewer_size = (800, 400)
        app.processEvents()
        assert_allclose(limits(self.viewer), initial_limits)

        # Now check that the limits don't change in 'auto' mode
        self.viewer.state.aspect = 'auto'
        self.viewer.viewer_size = (900, 300)
        assert_allclose(limits(self.viewer), initial_limits)

    def test_update_data_values(self):

        # Regression test for a bug that caused some viewers to not behave
        # correctly if the data values were updated.

        self.viewer.add_data(self.data)

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

        self.data.update_values_from_data(data)
def test_scatter_viewer(tmpdir):

    # Create fake data
    data = make_test_data()

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    scatter = ga.new_data_viewer(VispyScatterViewer)
    scatter.add_data(data)
    scatter.viewer_size = (400, 500)

    options = scatter.options_widget()

    options.x_att = data.id['a']
    options.y_att = data.id['f']
    options.z_att = data.id['z']

    options.x_stretch = 0.5
    options.y_stretch = 1.0
    options.z_stretch = 2.0

    options.x_min = -0.1
    options.x_max = 1.1
    options.y_min = 0.1
    options.y_max = 0.9
    options.z_min = 0.2
    options.z_max = 0.8

    options.visible_box = False

    # Get layer artist style editor
    layer_artist = scatter.layers[0]
    style_widget = scatter._view.layout_style_widgets[layer_artist]

    style_widget.size_mode = 'Linear'
    style_widget.size_attribute = data.id['c']
    style_widget.size_scaling = 2
    style_widget.size_vmin = 0.2
    style_widget.size_vmax = 0.8

    style_widget.color_mode = 'Linear'
    style_widget.cmap_attribute = data.id['y']
    style_widget.cmap_vmin = 0.1
    style_widget.cmap_vmax = 0.9
    style_widget.cmap = cm.BuGn

    # Check that writing a session works as expected. However, this only
    # works with Glue 0.8 and above, so we skip this test if we are using an
    # older version.

    if GLUE_LT_08:
        return

    session_file = tmpdir.join('test_scatter_viewer.glu').strpath
    ga.save_session(session_file)
    ga.close()

    # Now we can check that everything is restored correctly

    ga2 = GlueApplication.restore_session(session_file)
    ga2.show()

    scatter_r = ga2.viewers[0][0]

    assert scatter_r.viewer_size == (400, 500)

    options = scatter_r.options_widget()

    assert options.x_att.label == 'a'
    assert options.y_att.label == 'f'
    assert options.z_att.label == 'z'

    assert options.x_stretch == 0.5
    assert options.y_stretch == 1.0
    assert options.z_stretch == 2.0

    assert options.x_min == -0.1
    assert options.x_max == 1.1
    assert options.y_min == 0.1
    assert options.y_max == 0.9
    assert options.z_min == 0.2
    assert options.z_max == 0.8

    assert not options.visible_box

    layer_artist = scatter_r.layers[0]

    assert layer_artist.size_mode == 'linear'
    assert layer_artist.size_attribute.label == 'c'
    np.testing.assert_allclose(layer_artist.size_scaling, 2, rtol=0.01)
    assert layer_artist.size_vmin == 0.2
    assert layer_artist.size_vmax == 0.8

    assert layer_artist.color_mode == 'linear'
    assert layer_artist.cmap_attribute.label == 'y'
    assert layer_artist.cmap_vmin == 0.1
    assert layer_artist.cmap_vmax == 0.9
    assert layer_artist.cmap is cm.BuGn
Exemplo n.º 25
0
class TestExportPython(BaseTestExportPython):
    def setup_method(self, method):

        with NumpyRNGContext(12345):
            self.data = Data(**dict(
                (name, random_with_nan(100, nan_index=idx + 1))
                for idx, name in enumerate('abcdefgh')))
        self.data['angle'] = np.random.uniform(0, 360, 100)
        self.data_collection = DataCollection([self.data])
        self.app = GlueApplication(self.data_collection)
        self.viewer = self.app.new_data_viewer(ScatterViewer)
        self.viewer.add_data(self.data)
        self.viewer.state.x_att = self.data.id['a']
        self.viewer.state.y_att = self.data.id['b']

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

    def test_simple(self, tmpdir):
        self.assert_same(tmpdir)

    def test_simple_nofill(self, tmpdir):
        self.viewer.state.layers[0].fill = False
        self.viewer.state.layers[0].size_scaling = 10
        self.assert_same(tmpdir)

    def test_simple_visual(self, tmpdir):
        self.viewer.state.layers[0].color = 'blue'
        self.viewer.state.layers[0].markersize = 30
        self.viewer.state.layers[0].alpha = 0.5
        self.assert_same(tmpdir)

    def test_cmap_mode(self, tmpdir):
        self.viewer.state.layers[0].cmap_mode = 'Linear'
        self.viewer.state.layers[0].cmap_att = self.data.id['c']
        self.viewer.state.layers[0].cmap = plt.cm.BuGn
        self.viewer.state.layers[0].cmap_vmin = 0.2
        self.viewer.state.layers[0].cmap_vmax = 0.7
        self.viewer.state.layers[0].alpha = 0.8
        self.assert_same(tmpdir)

    def test_cmap_mode_nofill(self, tmpdir):
        self.viewer.state.layers[0].fill = False
        self.test_cmap_mode(tmpdir)

    def test_size_mode(self, tmpdir):
        self.viewer.state.layers[0].size_mode = 'Linear'
        self.viewer.state.layers[0].size_att = self.data.id['d']
        self.viewer.state.layers[0].size_vmin = 0.1
        self.viewer.state.layers[0].size_vmax = 0.8
        self.viewer.state.layers[0].size_scaling = 0.4
        self.viewer.state.layers[0].alpha = 0.7
        self.assert_same(tmpdir)

    def test_size_mode_nofill(self, tmpdir):
        self.viewer.state.layers[0].fill = False
        self.test_size_mode(tmpdir)

    def test_line(self, tmpdir):
        self.viewer.state.layers[0].line_visible = True
        self.viewer.state.layers[0].linewidth = 10
        self.viewer.state.layers[0].linestype = 'dashed'
        self.viewer.state.layers[0].color = 'orange'
        self.viewer.state.layers[0].alpha = 0.7
        self.viewer.state.layers[0].markersize = 100
        self.assert_same(tmpdir, tol=5)

    def test_line_cmap(self, tmpdir):
        self.viewer.state.layers[0].cmap_mode = 'Linear'
        self.viewer.state.layers[0].cmap_vmin = 0.2
        self.viewer.state.layers[0].cmap_vmax = 0.7
        self.viewer.state.layers[0].cmap = plt.cm.BuGn
        self.test_line(tmpdir)

    def test_errorbarx(self, tmpdir):
        self.viewer.state.layers[0].xerr_visible = True
        self.viewer.state.layers[0].xerr_att = self.data.id['e']
        self.viewer.state.layers[0].color = 'purple'
        self.viewer.state.layers[0].alpha = 0.5
        self.assert_same(tmpdir)

    def test_errorbary(self, tmpdir):
        self.viewer.state.layers[0].yerr_visible = True
        self.viewer.state.layers[0].yerr_att = self.data.id['f']
        self.viewer.state.layers[0].color = 'purple'
        self.viewer.state.layers[0].alpha = 0.5
        self.assert_same(tmpdir)

    def test_errorbarxy(self, tmpdir):
        self.viewer.state.layers[0].xerr_visible = True
        self.viewer.state.layers[0].xerr_att = self.data.id['e']
        self.viewer.state.layers[0].yerr_visible = True
        self.viewer.state.layers[0].yerr_att = self.data.id['f']
        self.viewer.state.layers[0].color = 'purple'
        self.viewer.state.layers[0].alpha = 0.5
        self.assert_same(tmpdir)

    def test_errorbarxy_cmap(self, tmpdir):
        self.viewer.state.layers[0].cmap_mode = 'Linear'
        self.viewer.state.layers[0].cmap_vmin = 0.2
        self.viewer.state.layers[0].cmap_vmax = 0.7
        self.viewer.state.layers[0].cmap = plt.cm.BuGn
        self.test_errorbarxy(tmpdir)

    def _vector_common(self, tmpdir):
        self.viewer.state.layers[0].vector_visible = True
        self.viewer.state.layers[0].vy_att = self.data.id['g']
        self.viewer.state.layers[0].vector_arrowhead = True
        self.viewer.state.layers[0].vector_origin = 'tail'
        self.viewer.state.layers[0].vector_scaling = 1.5
        self.viewer.state.layers[0].color = 'teal'
        self.viewer.state.layers[0].alpha = 0.9
        self.assert_same(tmpdir, tol=1)

    def test_vector_cartesian(self, tmpdir):
        self.viewer.state.layers[0].vector_mode = 'Cartesian'
        self.viewer.state.layers[0].vx_att = self.data.id['h']
        self._vector_common(tmpdir)

    def test_vector_polar(self, tmpdir):
        self.viewer.state.layers[0].vector_mode = 'Polar'
        self.viewer.state.layers[0].vx_att = self.data.id['angle']
        self._vector_common(tmpdir)

    def test_vector_cartesian_cmap(self, tmpdir):
        self.viewer.state.layers[0].cmap_mode = 'Linear'
        self.viewer.state.layers[0].cmap_vmin = 0.2
        self.viewer.state.layers[0].cmap_vmax = 0.7
        self.viewer.state.layers[0].cmap = plt.cm.BuGn
        self.test_vector_cartesian(tmpdir)

    def test_vector_cartesian_xflip(self, tmpdir):
        # Regression test for a bug that caused vectors to not be flipped
        self.viewer.state.layers[0].vector_mode = 'Cartesian'
        self.viewer.state.layers[0].vx_att = self.data.id['h']
        self.viewer.state.flip_x()
        self._vector_common(tmpdir)

    def test_subset(self, tmpdir):
        self.data_collection.new_subset_group('mysubset',
                                              self.data.id['a'] > 0.5)
        self.assert_same(tmpdir)

    def test_density_map_with_subset(self, tmpdir):
        self.viewer.state.dpi = 2
        self.viewer.state.layers[0].density_map = True
        self.data_collection.new_subset_group('mysubset',
                                              self.data.id['a'] > 0.5)
        self.assert_same(tmpdir)

    def test_density_map_cmap_with_subset(self, tmpdir):
        self.viewer.state.dpi = 2
        self.viewer.state.layers[0].density_map = True
        self.viewer.state.layers[0].cmap_mode = 'Linear'
        self.viewer.state.layers[0].cmap_vmin = 0.2
        self.viewer.state.layers[0].cmap_vmax = 0.7
        self.viewer.state.layers[0].cmap = plt.cm.BuGn
        self.data_collection.new_subset_group('mysubset',
                                              self.data.id['a'] > 0.5)
        self.assert_same(tmpdir)

    def test_cmap_mode_change(self, tmpdir):
        # Regression test for a bug that caused scatter markers to not change
        # color when going from Linear to Fixed mode
        self.viewer.state.layers[0].size_mode = 'Linear'
        self.viewer.state.layers[0].cmap_mode = 'Linear'
        self.viewer.state.layers[0].cmap_mode = 'Fixed'
        self.assert_same(tmpdir)

    def test_density_map_change(self, tmpdir):
        # Regression test for a bug that caused the density map to still
        # be visible if using color-coding with the density map then
        # switching to markers.
        self.viewer.state.layers[0].density_map = True
        self.viewer.state.layers[0].cmap_mode = 'Linear'
        self.viewer.state.layers[0].cmap = plt.cm.BuGn
        self.viewer.state.layers[0].density_map = False
        self.assert_same(tmpdir)
def test_scatter_viewer(tmpdir):

    # Create fake data
    data = make_test_data()

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    scatter = ga.new_data_viewer(VispyScatterViewer)
    scatter.add_data(data)
    scatter.viewer_size = (400, 500)

    viewer_state = scatter.state

    viewer_state.x_att = data.id['a']
    viewer_state.y_att = data.id['f']
    viewer_state.z_att = data.id['z']

    viewer_state.x_stretch = 0.5
    viewer_state.y_stretch = 1.0
    viewer_state.z_stretch = 2.0

    viewer_state.x_min = -0.1
    viewer_state.x_max = 1.1
    viewer_state.y_min = 0.1
    viewer_state.y_max = 0.9
    viewer_state.z_min = 0.2
    viewer_state.z_max = 0.8

    viewer_state.visible_axes = False

    # Get layer artist style editor
    layer_state = viewer_state.layers[0]

    layer_state.size_attribute = data.id['c']
    layer_state.size_mode = 'Linear'
    layer_state.size_scaling = 2
    layer_state.size_vmin = 0.2
    layer_state.size_vmax = 0.8

    layer_state.cmap_attribute = data.id['y']
    layer_state.color_mode = 'Linear'
    layer_state.cmap_vmin = 0.1
    layer_state.cmap_vmax = 0.9
    layer_state.cmap = cm.BuGn

    # Check that writing a session works as expected.

    session_file = tmpdir.join('test_scatter_viewer.glu').strpath
    ga.save_session(session_file)
    ga.close()

    # Now we can check that everything is restored correctly

    ga2 = GlueApplication.restore_session(session_file)
    ga2.show()

    scatter_r = ga2.viewers[0][0]

    assert scatter_r.viewer_size == (400, 500)

    viewer_state = scatter_r.state

    assert viewer_state.x_att.label == 'a'
    assert viewer_state.y_att.label == 'f'
    assert viewer_state.z_att.label == 'z'

    np.testing.assert_allclose(viewer_state.x_stretch, 0.5, rtol=1e-3)
    np.testing.assert_allclose(viewer_state.y_stretch, 1.0, rtol=1e-3)
    np.testing.assert_allclose(viewer_state.z_stretch, 2.0, rtol=1e-3)

    assert viewer_state.x_min == -0.1
    assert viewer_state.x_max == 1.1
    assert viewer_state.y_min == 0.1
    assert viewer_state.y_max == 0.9
    assert viewer_state.z_min == 0.2
    assert viewer_state.z_max == 0.8

    assert not viewer_state.visible_axes

    layer_state = viewer_state.layers[0]

    assert layer_state.size_mode == 'Linear'
    assert layer_state.size_attribute.label == 'c'
    np.testing.assert_allclose(layer_state.size_scaling, 2, rtol=0.01)
    assert layer_state.size_vmin == 0.2
    assert layer_state.size_vmax == 0.8

    assert layer_state.color_mode == 'Linear'
    assert layer_state.cmap_attribute.label == 'y'
    assert layer_state.cmap_vmin == 0.1
    assert layer_state.cmap_vmax == 0.9
    assert layer_state.cmap is cm.BuGn
Exemplo n.º 27
0
class TestExportPython(BaseTestExportPython):
    def setup_method(self, method):

        self.data = Data(label='d1')
        self.data.coords = SimpleCoordinates()
        with NumpyRNGContext(12345):
            self.data['x'] = random_with_nan(48, 5).reshape((6, 4, 2))
            self.data['y'] = random_with_nan(48, 12).reshape((6, 4, 2))
        self.data_collection = DataCollection([self.data])
        self.app = GlueApplication(self.data_collection)
        self.viewer = self.app.new_data_viewer(ProfileViewer)
        self.viewer.add_data(self.data)

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

    def test_simple(self, tmpdir):
        self.assert_same(tmpdir)

    def test_color(self, tmpdir):
        self.viewer.state.layers[0].color = '#ac0567'
        self.assert_same(tmpdir)

    def test_linewidth(self, tmpdir):
        self.viewer.state.layers[0].linewidth = 7.25
        self.assert_same(tmpdir)

    def test_max(self, tmpdir):
        self.viewer.state.function = 'maximum'
        self.assert_same(tmpdir)

    def test_min(self, tmpdir):
        self.viewer.state.function = 'minimum'
        self.assert_same(tmpdir)

    def test_mean(self, tmpdir):
        self.viewer.state.function = 'mean'
        self.assert_same(tmpdir)

    def test_median(self, tmpdir):
        self.viewer.state.function = 'median'
        self.assert_same(tmpdir)

    def test_sum(self, tmpdir):
        self.viewer.state.function = 'sum'
        self.assert_same(tmpdir)

    def test_normalization(self, tmpdir):
        self.viewer.state.normalize = True
        self.assert_same(tmpdir)

    def test_subset(self, tmpdir):
        self.viewer.state.function = 'mean'
        self.data_collection.new_subset_group('mysubset',
                                              self.data.id['x'] > 0.25)
        self.assert_same(tmpdir)

    def test_xatt(self, tmpdir):
        self.viewer.x_att = self.data.pixel_component_ids[1]
        self.assert_same(tmpdir)

    def test_profile_att(self, tmpdir):
        self.viewer.layers[0].state.attribute = self.data.id['y']
        self.assert_same(tmpdir)
Exemplo n.º 28
0
class TestExportPython(BaseTestExportPython):

    def setup_method(self, method):

        with NumpyRNGContext(12345):
            self.data = Data(**dict((name, random_with_nan(100, nan_index=idx + 1)) for idx, name in enumerate('abcdefgh')))
        self.data['angle'] = np.random.uniform(0, 360, 100)
        self.data_collection = DataCollection([self.data])
        self.app = GlueApplication(self.data_collection)
        self.viewer = self.app.new_data_viewer(ScatterViewer)
        self.viewer.add_data(self.data)
        self.viewer.state.x_att = self.data.id['a']
        self.viewer.state.y_att = self.data.id['b']

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

    def test_simple(self, tmpdir):
        self.assert_same(tmpdir)

    def test_simple_nofill(self, tmpdir):
        self.viewer.state.layers[0].fill = False
        self.viewer.state.layers[0].size_scaling = 10
        self.assert_same(tmpdir)

    def test_simple_visual(self, tmpdir):
        self.viewer.state.layers[0].color = 'blue'
        self.viewer.state.layers[0].markersize = 30
        self.viewer.state.layers[0].alpha = 0.5
        self.assert_same(tmpdir)

    def test_cmap_mode(self, tmpdir):
        self.viewer.state.layers[0].cmap_mode = 'Linear'
        self.viewer.state.layers[0].cmap_att = self.data.id['c']
        self.viewer.state.layers[0].cmap = plt.cm.BuGn
        self.viewer.state.layers[0].cmap_vmin = 0.2
        self.viewer.state.layers[0].cmap_vmax = 0.7
        self.viewer.state.layers[0].alpha = 0.8
        self.assert_same(tmpdir)

    def test_cmap_mode_nofill(self, tmpdir):
        self.viewer.state.layers[0].fill = False
        self.test_cmap_mode(tmpdir)

    def test_size_mode(self, tmpdir):
        self.viewer.state.layers[0].size_mode = 'Linear'
        self.viewer.state.layers[0].size_att = self.data.id['d']
        self.viewer.state.layers[0].size_vmin = 0.1
        self.viewer.state.layers[0].size_vmax = 0.8
        self.viewer.state.layers[0].size_scaling = 0.4
        self.viewer.state.layers[0].alpha = 0.7
        self.assert_same(tmpdir)

    def test_size_mode_nofill(self, tmpdir):
        self.viewer.state.layers[0].fill = False
        self.test_size_mode(tmpdir)

    def test_line(self, tmpdir):
        self.viewer.state.layers[0].line_visible = True
        self.viewer.state.layers[0].linewidth = 10
        self.viewer.state.layers[0].linestype = 'dashed'
        self.viewer.state.layers[0].color = 'orange'
        self.viewer.state.layers[0].alpha = 0.7
        self.viewer.state.layers[0].markersize = 100
        self.assert_same(tmpdir, tol=5)

    def test_line_cmap(self, tmpdir):
        self.viewer.state.layers[0].cmap_mode = 'Linear'
        self.viewer.state.layers[0].cmap_vmin = 0.2
        self.viewer.state.layers[0].cmap_vmax = 0.7
        self.viewer.state.layers[0].cmap = plt.cm.BuGn
        self.test_line(tmpdir)

    def test_errorbarx(self, tmpdir):
        self.viewer.state.layers[0].xerr_visible = True
        self.viewer.state.layers[0].xerr_att = self.data.id['e']
        self.viewer.state.layers[0].color = 'purple'
        self.viewer.state.layers[0].alpha = 0.5
        self.assert_same(tmpdir)

    def test_errorbary(self, tmpdir):
        self.viewer.state.layers[0].yerr_visible = True
        self.viewer.state.layers[0].yerr_att = self.data.id['f']
        self.viewer.state.layers[0].color = 'purple'
        self.viewer.state.layers[0].alpha = 0.5
        self.assert_same(tmpdir)

    def test_errorbarxy(self, tmpdir):
        self.viewer.state.layers[0].xerr_visible = True
        self.viewer.state.layers[0].xerr_att = self.data.id['e']
        self.viewer.state.layers[0].yerr_visible = True
        self.viewer.state.layers[0].yerr_att = self.data.id['f']
        self.viewer.state.layers[0].color = 'purple'
        self.viewer.state.layers[0].alpha = 0.5
        self.assert_same(tmpdir)

    def test_errorbarxy_cmap(self, tmpdir):
        self.viewer.state.layers[0].cmap_mode = 'Linear'
        self.viewer.state.layers[0].cmap_vmin = 0.2
        self.viewer.state.layers[0].cmap_vmax = 0.7
        self.viewer.state.layers[0].cmap = plt.cm.BuGn
        self.test_errorbarxy(tmpdir)

    def _vector_common(self, tmpdir):
        self.viewer.state.layers[0].vector_visible = True
        self.viewer.state.layers[0].vy_att = self.data.id['g']
        self.viewer.state.layers[0].vector_arrowhead = True
        self.viewer.state.layers[0].vector_origin = 'tail'
        self.viewer.state.layers[0].vector_scaling = 1.5
        self.viewer.state.layers[0].color = 'teal'
        self.viewer.state.layers[0].alpha = 0.9
        self.assert_same(tmpdir)

    def test_vector_cartesian(self, tmpdir):
        self.viewer.state.layers[0].vector_mode = 'Cartesian'
        self.viewer.state.layers[0].vx_att = self.data.id['h']
        self._vector_common(tmpdir)

    def test_vector_polar(self, tmpdir):
        self.viewer.state.layers[0].vector_mode = 'Polar'
        self.viewer.state.layers[0].vx_att = self.data.id['angle']
        self._vector_common(tmpdir)

    def test_vector_cartesian_cmap(self, tmpdir):
        self.viewer.state.layers[0].cmap_mode = 'Linear'
        self.viewer.state.layers[0].cmap_vmin = 0.2
        self.viewer.state.layers[0].cmap_vmax = 0.7
        self.viewer.state.layers[0].cmap = plt.cm.BuGn
        self.test_vector_cartesian(tmpdir)

    def test_vector_cartesian_xflip(self, tmpdir):
        # Regression test for a bug that caused vectors to not be flipped
        self.viewer.state.layers[0].vector_mode = 'Cartesian'
        self.viewer.state.layers[0].vx_att = self.data.id['h']
        self.viewer.state.flip_x()
        self._vector_common(tmpdir)

    def test_subset(self, tmpdir):
        self.data_collection.new_subset_group('mysubset', self.data.id['a'] > 0.5)
        self.assert_same(tmpdir)

    def test_density_map_with_subset(self, tmpdir):
        self.viewer.state.dpi = 2
        self.viewer.state.layers[0].density_map = True
        self.data_collection.new_subset_group('mysubset', self.data.id['a'] > 0.5)
        self.assert_same(tmpdir)

    def test_density_map_cmap_with_subset(self, tmpdir):
        self.viewer.state.dpi = 2
        self.viewer.state.layers[0].density_map = True
        self.viewer.state.layers[0].cmap_mode = 'Linear'
        self.viewer.state.layers[0].cmap_vmin = 0.2
        self.viewer.state.layers[0].cmap_vmax = 0.7
        self.viewer.state.layers[0].cmap = plt.cm.BuGn
        self.data_collection.new_subset_group('mysubset', self.data.id['a'] > 0.5)
        self.assert_same(tmpdir)

    def test_cmap_mode_change(self, tmpdir):
        # Regression test for a bug that caused scatter markers to not change
        # color when going from Linear to Fixed mode
        self.viewer.state.layers[0].size_mode = 'Linear'
        self.viewer.state.layers[0].cmap_mode = 'Linear'
        self.viewer.state.layers[0].cmap_mode = 'Fixed'
        self.assert_same(tmpdir)
Exemplo n.º 29
0
def test_volume_viewer(tmpdir):

    # Create fake data
    data = make_test_data()

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    volume = ga.new_data_viewer(VispyVolumeViewer)
    volume.add_data(data)
    volume.viewer_size = (400, 500)

    options = volume.options_widget()

    options.x_stretch = 0.5
    options.y_stretch = 1.0
    options.z_stretch = 2.0

    options.x_min = -0.1
    options.x_max = 10.1
    options.y_min = 0.1
    options.y_max = 10.9
    options.z_min = 0.2
    options.z_max = 10.8

    options.visible_box = False

    # Get layer artist style editor
    layer_artist = volume.layers[0]
    style_widget = volume._view.layout_style_widgets[layer_artist]

    style_widget.attribute = data.id['b']
    style_widget.vmin = 0.1
    style_widget.vmax = 0.9
    style_widget.alpha = 0.8

    # Check that writing a session works as expected.

    session_file = tmpdir.join('test_volume_viewer.glu').strpath
    ga.save_session(session_file)
    ga.close()

    # Now we can check that everything is restored correctly

    ga2 = GlueApplication.restore_session(session_file)
    ga2.show()

    volume_r = ga2.viewers[0][0]

    assert volume_r.viewer_size == (400, 500)

    options = volume_r.options_widget()

    assert options.x_stretch == 0.5
    assert options.y_stretch == 1.0
    assert options.z_stretch == 2.0

    assert options.x_min == -0.1
    assert options.x_max == 10.1
    assert options.y_min == 0.1
    assert options.y_max == 10.9
    assert options.z_min == 0.2
    assert options.z_max == 10.8

    assert not options.visible_box

    layer_artist = volume_r.layers[0]

    assert style_widget.attribute.label == 'b'
    assert style_widget.vmin == 0.1
    assert style_widget.vmax == 0.9
    assert style_widget.alpha == 0.8

    ga2.close()
Exemplo n.º 30
0
class BaseTestMatplotlibDataViewer(object):
    """
    Base class to test viewers based on MatplotlibDataViewer. This only runs
    a subset of tests that relate to functionality implemented in
    MatplotlibDataViewer and specific viewers are responsible for implementing
    a more complete test suite.

    Viewers based on this should inherit from this test class and define the
    following attributes:

    * ``data``: an instance of a data object that works by default in the viewer
    * ``viewer_cls``: the viewer class

    It is then safe to assume that ``data_collection``, ``viewer``, and ``hub``
    are defined when writing tests.
    """

    def setup_method(self, method):

        if OBJGRAPH_INSTALLED:
            self.viewer_count_start = self.viewer_count

        self.data = self.init_data()

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

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

        self.viewer = self.viewer_cls(self.session)

        self.data_collection.register_to_hub(self.hub)
        self.viewer.register_to_hub(self.hub)

    def init_subset(self):
        cid = self.data.visible_components[0]
        self.data_collection.new_subset_group('subset 1', cid > 0)

    @property
    def viewer_count(self):
        app = get_qapp()
        app.processEvents()
        obj = objgraph.by_type(self.viewer_cls.__name__)
        return len(obj)

    def teardown_method(self, method):

        if self.viewer is not None:
            self.viewer.close()
        self.application.close()

        # The following is a check to make sure that once the viewer and
        # application have been closed, there are no leftover references to
        # the data viewer. This was introduced because there were previously
        # circular references that meant that viewer instances were not
        # properly garbage collected, which in turn meant they still reacted
        # in some cases to events.
        if OBJGRAPH_INSTALLED:
            self.viewer = None
            self.application = None
            if self.viewer_count > self.viewer_count_start:
                raise ValueError("No net viewers should be created in tests")

    def test_add_data(self):

        # Add a dataset with no subsets and make sure the appropriate layer
        # state and layer artists are created

        self.viewer.add_data(self.data)

        assert len(self.viewer.layers) == 1
        assert self.viewer.layers[0].layer is self.data

        assert len(self.viewer.state.layers) == 1
        assert self.viewer.state.layers[0].layer is self.data

    def test_add_data_with_subset(self):

        # Make sure that if subsets are present in the data, they are added
        # automatically

        self.init_subset()
        self.viewer.add_data(self.data)

        assert len(self.viewer.layers) == 2
        assert self.viewer.layers[0].layer is self.data
        assert self.viewer.layers[1].layer is self.data.subsets[0]

        assert len(self.viewer.state.layers) == 2
        assert self.viewer.state.layers[0].layer is self.data
        assert self.viewer.state.layers[1].layer is self.data.subsets[0]

    def test_adding_subset_adds_data(self):

        # TODO: in future consider whether we want to deprecate this behavior

        self.init_subset()
        self.viewer.add_subset(self.data.subsets[0])

        assert len(self.viewer.layers) == 2
        assert self.viewer.layers[0].layer is self.data
        assert self.viewer.layers[1].layer is self.data.subsets[0]

        assert len(self.viewer.state.layers) == 2
        assert self.viewer.state.layers[0].layer is self.data
        assert self.viewer.state.layers[1].layer is self.data.subsets[0]

    def test_add_data_then_subset(self):

        # Make sure that if a subset is created in a dataset that has already
        # been added to a viewer, the subset gets added

        self.viewer.add_data(self.data)

        assert len(self.viewer.layers) == 1
        assert self.viewer.layers[0].layer is self.data

        assert len(self.viewer.state.layers) == 1
        assert self.viewer.state.layers[0].layer is self.data

        self.init_subset()

        assert len(self.viewer.layers) == 2
        assert self.viewer.layers[0].layer is self.data
        assert self.viewer.layers[1].layer is self.data.subsets[0]

        assert len(self.viewer.state.layers) == 2
        assert self.viewer.state.layers[0].layer is self.data
        assert self.viewer.state.layers[1].layer is self.data.subsets[0]

    def init_draw_count(self):
        self.mpl_counter = MatplotlibDrawCounter(self.viewer.axes.figure)

    @property
    def draw_count(self):
        return self.mpl_counter.draw_count

    def test_single_draw(self):
        # Make sure that the number of draws is kept to a minimum
        self.init_draw_count()
        self.init_subset()
        assert self.draw_count == 0
        self.viewer.add_data(self.data)
        assert self.draw_count == 1

    def test_update_subset(self):

        self.init_draw_count()

        # Check that updating a subset causes the plot to be updated

        self.init_subset()

        assert self.draw_count == 0

        self.viewer.add_data(self.data)

        count_before = self.draw_count

        # Change the subset
        cid = self.data.visible_components[0]
        self.data.subsets[0].subset_state = cid > 1

        # Make sure the figure has been redrawn
        assert self.draw_count - count_before > 0

    def test_double_add_ignored(self):
        self.viewer.add_data(self.data)
        assert len(self.viewer.state.layers) == 1
        self.viewer.add_data(self.data)
        assert len(self.viewer.state.layers) == 1

    def test_removing_data_removes_layer_state(self):
        # Removing data from data collection should remove data from viewer
        self.viewer.add_data(self.data)
        assert len(self.viewer.state.layers) == 1
        self.data_collection.remove(self.data)
        assert len(self.viewer.state.layers) == 0

    def test_removing_data_removes_subsets(self):
        # Removing data from data collection should remove subsets from viewer
        self.init_subset()
        self.viewer.add_data(self.data)
        assert len(self.viewer.state.layers) == 2
        self.data_collection.remove(self.data)
        assert len(self.viewer.state.layers) == 0

    def test_removing_subset_removes_layers(self):

        # Removing a layer artist removes the corresponding layer state. We need
        # to do this with a subset otherwise the viewer is closed

        self.init_subset()
        self.viewer.add_data(self.data)

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

        self.data_collection.remove_subset_group(self.data_collection.subset_groups[0])

        assert len(self.viewer.layers) == 1
        assert self.viewer.layers[0].layer is self.data

        assert len(self.viewer.state.layers) == 1
        assert self.viewer.state.layers[0].layer is self.data

    def test_removing_layer_artist_removes_layer_state(self):

        # Removing a layer artist removes the corresponding layer state. We need
        # to do this with a subset otherwise the viewer is closed

        self.init_subset()
        self.viewer.add_data(self.data)

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

        # self.layers is a copy so we need to remove from the original list
        self.viewer._layer_artist_container.remove(self.viewer.layers[1])

        assert len(self.viewer.layers) == 1
        assert self.viewer.layers[0].layer is self.data

        assert len(self.viewer.state.layers) == 1
        assert self.viewer.state.layers[0].layer is self.data

    def test_removing_layer_state_removes_layer_artist(self):

        # Removing a layer artist removes the corresponding layer state. We need
        # to do this with a subset otherwise the viewer is closed

        self.init_subset()
        self.viewer.add_data(self.data)

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

        # self.layers is a copy so we need to remove from the original list
        self.viewer.state.layers.pop(1)

        assert len(self.viewer.layers) == 1
        assert self.viewer.layers[0].layer is self.data

        assert len(self.viewer.state.layers) == 1
        assert self.viewer.state.layers[0].layer is self.data

    def test_new_subset_after_remove_data(self):

        # Once we remove a dataset, if we make a new subset, it will not be
        # added to the viewer

        self.init_subset()
        self.viewer.add_data(self.data)

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

        self.viewer.state.layers.pop(0)

        self.init_subset()  # makes a new subset

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

        assert len(self.viewer.layers) == 1
        assert self.viewer.layers[0].layer is self.data.subsets[0]

        assert len(self.viewer.state.layers) == 1
        assert self.viewer.state.layers[0].layer is self.data.subsets[0]

    def test_remove_not_present_ignored(self):
        data = Data(label='not in viewer')
        self.viewer.remove_data(data)

    def test_limits_sync(self):

        viewer_state = self.viewer.state
        axes = self.viewer.axes

        if axes.get_adjustable() == 'datalim':
            pytest.xfail()

        # Make sure that the viewer state and matplotlib viewer limits and log
        # settings are in sync. We start by modifying the state and making sure
        # that the axes follow.

        viewer_state.x_min = 3
        viewer_state.x_max = 9

        viewer_state.y_min = -2
        viewer_state.y_max = 3

        assert axes.get_xlim() == (3, 9)
        assert axes.get_ylim() == (-2, 3)
        assert axes.get_xscale() == 'linear'
        assert axes.get_yscale() == 'linear'

        viewer_state.x_log = True

        assert axes.get_xlim() == (3, 9)
        assert axes.get_ylim() == (-2, 3)
        assert axes.get_xscale() == 'log'
        assert axes.get_yscale() == 'linear'

        viewer_state.y_log = True

        # FIXME: the limits for y don't seem right, should be adjusted because of log?
        assert axes.get_xlim() == (3, 9)
        assert axes.get_ylim() == (-2, 3)
        assert axes.get_xscale() == 'log'
        assert axes.get_yscale() == 'log'

        # Check that changing the axes changes the state

        # NOTE: at the moment this doesn't work because Matplotlib doesn't
        # emit events for changing xscale/yscale. This isn't crucial anyway for
        # glue, but leaving the tests below in case this is fixed some day. The
        # Matplotlib issue is https://github.com/matplotlib/matplotlib/issues/8439

        axes.set_xscale('linear')
        #
        # assert viewer_state.x_min == 3
        # assert viewer_state.x_max == 9
        # assert viewer_state.y_min == -2
        # assert viewer_state.y_max == 3
        # assert not viewer_state.x_log
        # assert viewer_state.y_log
        #
        axes.set_yscale('linear')
        #
        # assert viewer_state.x_min == 3
        # assert viewer_state.x_max == 9
        # assert viewer_state.y_min == -2
        # assert viewer_state.y_max == 3
        # assert not viewer_state.x_log
        # assert not viewer_state.y_log

        axes.set_xlim(-1, 4)

        assert viewer_state.x_min == -1
        assert viewer_state.x_max == 4
        assert viewer_state.y_min == -2
        assert viewer_state.y_max == 3
        # assert not viewer_state.x_log
        # assert not viewer_state.y_log

        axes.set_ylim(5, 6)

        assert viewer_state.x_min == -1
        assert viewer_state.x_max == 4
        assert viewer_state.y_min == 5
        assert viewer_state.y_max == 6
        # assert not viewer_state.x_log
        # assert not viewer_state.y_log

    # TODO: the following test should deal gracefully with the fact that
    # some viewers will want to show a Qt error for IncompatibleDataException
    def test_add_invalid_data(self):
        data2 = Data()
        with pytest.raises(IncompatibleDataException):
            self.viewer.add_data(data2)

    # Communication tests

    def test_ignore_data_add_message(self):
        self.data_collection.append(self.data)
        assert len(self.viewer.layers) == 0

    def test_update_data_ignored_if_data_not_present(self):
        self.init_draw_count()
        self.data_collection.append(self.data)
        ct0 = self.draw_count
        self.data.style.color = 'blue'
        assert self.draw_count == ct0

    def test_update_data_processed_if_data_present(self):
        self.init_draw_count()
        self.data_collection.append(self.data)
        self.viewer.add_data(self.data)
        ct0 = self.draw_count
        self.data.style.color = 'blue'
        assert self.draw_count > ct0

    def test_add_subset_ignored_if_data_not_present(self):
        self.data_collection.append(self.data)
        sub = self.data.new_subset()
        assert sub not in self.viewer._layer_artist_container

    def test_add_subset_processed_if_data_present(self):
        self.data_collection.append(self.data)
        self.viewer.add_data(self.data)
        sub = self.data.new_subset()
        assert sub in self.viewer._layer_artist_container

    def test_update_subset_ignored_if_not_present(self):
        # This can be quite a difficult test to pass because it makes sure that
        # there are absolutely no references to the layer state left over once
        # a subset is removed - when originally written this identified quite
        # a few places where references were being accidentally kept, and
        # resulted in weakref being needed in a number of places. But ultimately
        # this test should pass! No cheating :)
        self.init_draw_count()
        self.data_collection.append(self.data)
        self.viewer.add_data(self.data)
        sub = self.data.new_subset()
        self.viewer.remove_subset(sub)
        ct0 = self.draw_count
        sub.style.color = 'blue'
        assert self.draw_count == ct0

    def test_update_subset_processed_if_present(self):
        self.init_draw_count()
        self.data_collection.append(self.data)
        self.viewer.add_data(self.data)
        sub = self.data.new_subset()
        ct0 = self.draw_count
        sub.style.color = 'blue'
        assert self.draw_count > ct0

    def test_data_remove_message(self):
        self.data_collection.append(self.data)
        self.viewer.add_data(self.data)
        self.data_collection.remove(self.data)
        assert self.data not in self.viewer._layer_artist_container

    def test_subset_remove_message(self):
        self.data_collection.append(self.data)
        self.viewer.add_data(self.data)
        sub = self.data.new_subset()
        assert sub in self.viewer._layer_artist_container
        sub.delete()
        assert sub not in self.viewer._layer_artist_container

    def test_session_round_trip(self, tmpdir):

        self.init_subset()

        ga = GlueApplication(self.data_collection)
        ga.show()

        viewer = ga.new_data_viewer(self.viewer_cls)
        viewer.add_data(self.data)

        session_file = tmpdir.join('test_session_round_trip.glu').strpath
        ga.save_session(session_file)
        ga.close()

        ga2 = GlueApplication.restore_session(session_file)
        ga2.show()

        viewer2 = ga2.viewers[0][0]

        data2 = ga2.data_collection[0]

        assert viewer2.layers[0].layer is data2
        assert viewer2.layers[1].layer is data2.subsets[0]

        ga2.close()

    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

    def test_numerical_data_changed(self):
        self.init_draw_count()
        self.init_subset()
        assert self.draw_count == 0
        self.viewer.add_data(self.data)
        assert self.draw_count == 1
        data = Data()
        for cid in self.data.visible_components:
            data.add_component(self.data[cid] * 2, cid.label)
        self.data.update_values_from_data(data)
        assert self.draw_count == 2
Exemplo n.º 31
0
def test_vectors(tmpdir):

    # Create fake data
    data = make_test_data()

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    scatter = ga.new_data_viewer(VispyScatterViewer)
    scatter.add_data(data)
    scatter.viewer_size = (400, 500)

    viewer_state = scatter.state

    viewer_state.x_att = data.id['a']
    viewer_state.y_att = data.id['f']
    viewer_state.z_att = data.id['z']

    layer_state = viewer_state.layers[0]

    layer_state.vector_visible = True
    layer_state.vx_attribute = data.id['x']
    layer_state.vy_attribute = data.id['y']
    layer_state.vz_attribute = data.id['e']
    layer_state.vector_scaling = 0.1
    layer_state.vector_origin = 'tail'
    layer_state.vector_arrowhead = True

    viewer_state.line_width = 3

    # Check that writing a session works as expected.

    session_file = tmpdir.join('test_vectors.glu').strpath
    ga.save_session(session_file)
    ga.close()

    # Now we can check that everything is restored correctly

    ga2 = GlueApplication.restore_session(session_file)
    ga2.show()

    scatter_r = ga2.viewers[0][0]
    layer_state = scatter_r.state.layers[0]

    assert layer_state.vector_visible

    assert layer_state.vx_attribute.label == 'x'
    assert layer_state.vy_attribute.label == 'y'
    assert layer_state.vz_attribute.label == 'e'

    assert np.isclose(layer_state.vector_scaling, 0.1)

    assert layer_state.vector_origin == 'tail'

    assert layer_state.vector_arrowhead

    assert scatter_r.state.line_width == 3

    ga2.close()
def test_isosurface_viewer(tmpdir):

    # Create fake data
    data = make_test_data()

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    volume = ga.new_data_viewer(VispyIsosurfaceViewer)
    volume.add_data(data)
    volume.viewer_size = (400, 500)

    viewer_state = volume.state

    viewer_state.x_stretch = 0.5
    viewer_state.y_stretch = 1.0
    viewer_state.z_stretch = 2.0

    viewer_state.x_min = -0.1
    viewer_state.x_max = 10.1
    viewer_state.y_min = 0.1
    viewer_state.y_max = 10.9
    viewer_state.z_min = 0.2
    viewer_state.z_max = 10.8

    viewer_state.visible_axes = False

    # Get layer artist style editor
    layer_state = viewer_state.layers[0]

    layer_state.attribute = data.id['b']
    layer_state.level_low = 0.1
    layer_state.level_high = 0.9
    # layer_state.alpha = 0.8

    # test set label from slider
    layer_state.step = 5
    assert layer_state.step == 5.0

    # Check that writing a session works as expected.

    session_file = tmpdir.join('test_volume_viewer.glu').strpath
    ga.save_session(session_file)
    ga.close()

    # Now we can check that everything is restored correctly

    ga2 = GlueApplication.restore_session(session_file)
    ga2.show()

    volume_r = ga2.viewers[0][0]

    assert volume_r.viewer_size == (400, 500)

    viewer_state = volume_r.state

    np.testing.assert_allclose(viewer_state.x_stretch, 0.5, rtol=1e-3)
    np.testing.assert_allclose(viewer_state.y_stretch, 1.0, rtol=1e-3)
    np.testing.assert_allclose(viewer_state.z_stretch, 2.0, rtol=1e-3)

    assert viewer_state.x_min == -0.1
    assert viewer_state.x_max == 10.1
    assert viewer_state.y_min == 0.1
    assert viewer_state.y_max == 10.9
    assert viewer_state.z_min == 0.2
    assert viewer_state.z_max == 10.8

    assert not viewer_state.visible_axes

    layer_artist = viewer_state.layers[0]

    assert layer_artist.attribute.label == 'b'
    assert layer_artist.level_low == 0.1
    assert layer_artist.level_high == 0.9
    # assert layer_artist.alpha == 0.8
    assert layer_artist.step == 5

    ga2.close()
Exemplo n.º 33
0
def test_volume_viewer(tmpdir):

    # Create fake data
    data = make_test_data()

    # Create fake session

    dc = DataCollection([data])
    ga = GlueApplication(dc)
    ga.show()

    volume = ga.new_data_viewer(VispyIsosurfaceViewer)
    volume.add_data(data)
    volume.viewer_size = (400, 500)

    viewer_state = volume.state

    viewer_state.x_stretch = 0.5
    viewer_state.y_stretch = 1.0
    viewer_state.z_stretch = 2.0

    viewer_state.x_min = -0.1
    viewer_state.x_max = 10.1
    viewer_state.y_min = 0.1
    viewer_state.y_max = 10.9
    viewer_state.z_min = 0.2
    viewer_state.z_max = 10.8

    viewer_state.visible_axes = False

    # Get layer artist style editor
    layer_state = viewer_state.layers[0]

    layer_state.attribute = data.id['b']
    layer_state.level_low = 0.1
    layer_state.level_high = 0.9
    # layer_state.alpha = 0.8

    # test set label from slider
    layer_state.step = 5
    assert layer_state.step == 5.0

    # Check that writing a session works as expected.

    session_file = tmpdir.join('test_volume_viewer.glu').strpath
    ga.save_session(session_file)
    ga.close()

    # Now we can check that everything is restored correctly

    ga2 = GlueApplication.restore_session(session_file)
    ga2.show()

    volume_r = ga2.viewers[0][0]

    assert volume_r.viewer_size == (400, 500)

    viewer_state = volume_r.state

    np.testing.assert_allclose(viewer_state.x_stretch, 0.5, rtol=1e-3)
    np.testing.assert_allclose(viewer_state.y_stretch, 1.0, rtol=1e-3)
    np.testing.assert_allclose(viewer_state.z_stretch, 2.0, rtol=1e-3)

    assert viewer_state.x_min == -0.1
    assert viewer_state.x_max == 10.1
    assert viewer_state.y_min == 0.1
    assert viewer_state.y_max == 10.9
    assert viewer_state.z_min == 0.2
    assert viewer_state.z_max == 10.8

    assert not viewer_state.visible_axes

    layer_artist = viewer_state.layers[0]

    assert layer_artist.attribute.label == 'b'
    assert layer_artist.level_low == 0.1
    assert layer_artist.level_high == 0.9
    # assert layer_artist.alpha == 0.8
    assert layer_artist.step == 5

    ga2.close()