def test_component_id_combo_helper_init(): # Regression test to make sure that the numeric and categorical options # in the __init__ are taken into account properly combo = QtWidgets.QComboBox() dc = DataCollection([]) data = Data(a=[1, 2, 3], b=['a', 'b', 'c'], label='data2') dc.append(data) helper = ComponentIDComboHelper(combo, dc) helper.append_data(data) assert combo_as_string(combo) == "a:b" helper = ComponentIDComboHelper(combo, dc, numeric=False) helper.append_data(data) assert combo_as_string(combo) == "b" helper = ComponentIDComboHelper(combo, dc, categorical=False) helper.append_data(data) assert combo_as_string(combo) == "a" helper = ComponentIDComboHelper(combo, dc, numeric=False, categorical=False) helper.append_data(data) assert combo_as_string(combo) == ""
def test_component_id_combo_helper_init(): # Regression test to make sure that the numeric and categorical options # in the __init__ are taken into account properly state = ExampleState() dc = DataCollection([]) data = Data(a=[1, 2, 3], b=['a', 'b', 'c'], label='data2') dc.append(data) helper = ComponentIDComboHelper(state, 'combo', dc) helper.append_data(data) assert selection_choices(state, 'combo') == "a:b" helper = ComponentIDComboHelper(state, 'combo', dc, numeric=False) helper.append_data(data) assert selection_choices(state, 'combo') == "b" helper = ComponentIDComboHelper(state, 'combo', dc, categorical=False) helper.append_data(data) assert selection_choices(state, 'combo') == "a" helper = ComponentIDComboHelper(state, 'combo', dc, numeric=False, categorical=False) helper.append_data(data) assert selection_choices(state, 'combo') == ""
def test_data_collection_combo_helper(): callback = MagicMock() state = ExampleState() state.add_callback('combo', callback) dc = DataCollection([]) helper = DataCollectionComboHelper(state, 'combo', dc) # noqa data1 = Data(x=[1, 2, 3], y=[2, 3, 4], label='data1') assert callback.call_count == 0 dc.append(data1) assert callback.call_count == 1 assert selection_choices(state, 'combo') == "data1" data1.label = 'mydata1' assert selection_choices(state, 'combo') == "mydata1" assert callback.call_count == 2 dc.remove(data1) assert callback.call_count == 3 assert selection_choices(state, 'combo') == ""
def test_component_id_combo_helper_add(): # Make sure that when adding a component, and if a data collection is not # present, the choices still get updated callback = MagicMock() state = ExampleState() state.add_callback('combo', callback) dc = DataCollection([]) helper = ComponentIDComboHelper(state, 'combo') assert selection_choices(state, 'combo') == "" data1 = Data(x=[1, 2, 3], y=[2, 3, 4], label='data1') callback.reset_mock() dc.append(data1) helper.append_data(data1) callback.assert_called_once_with(0) callback.reset_mock() assert selection_choices(state, 'combo') == "x:y" data1.add_component([7, 8, 9], 'z') # Should get notification since choices have changed callback.assert_called_once_with(0) callback.reset_mock() assert selection_choices(state, 'combo') == "x:y:z"
def test_component_id_combo_helper_init(): # Regression test to make sure that the numeric and categorical options # in the __init__ are taken into account properly combo = QtWidgets.QComboBox() dc = DataCollection([]) data = Data(a=[1,2,3], b=['a','b','c'], label='data2') dc.append(data) helper = ComponentIDComboHelper(combo, dc) helper.append_data(data) assert _items_as_string(combo) == "a:b" helper = ComponentIDComboHelper(combo, dc, numeric=False) helper.append_data(data) assert _items_as_string(combo) == "b" helper = ComponentIDComboHelper(combo, dc, categorical=False) helper.append_data(data) assert _items_as_string(combo) == "a" helper = ComponentIDComboHelper(combo, dc, numeric=False, categorical=False) helper.append_data(data) assert _items_as_string(combo) == ""
def jglue(*args, **kwargs): """ Create a new Jupyter-based glue application. It is typically easiest to call this function without arguments and load data and add links separately in subsequent calls. However, this function can also take the same inputs as the `~glue.qglue.qglue` function. Once this function is called, it will return a `~glue_jupyter.JupyterApplication` object, which can then be used to load data, set up links, and create visualizations. See the documentation for that class for more details. """ show = kwargs.pop('show', False) from glue.core import DataCollection from glue.qglue import parse_data, parse_links from glue.core.data_factories import load_data links = kwargs.pop('links', None) dc = DataCollection() for label, data in kwargs.items(): if isinstance(data, str): data = load_data(data) dc.extend(parse_data(data, label)) for data in args: dc.append(data) if links is not None: dc.add_link(parse_links(dc, links)) japp = JupyterApplication(dc) if show: display(app) return japp
def commit(self): # Test if Glueviz is running or closed already if self.gluvizapp is not None: import sip app = self.gluvizapp if sip.isdeleted(app): # Clear last instance closed self.gluvizapp = None self.infob.setText( "Please click the button below to run Glueviz.") return # Glueviz is running else: return from glue.core import DataCollection from glue.qglue import parse_data dc = DataCollection() for table in self.tables.values(): gd = parse_data(table, table.name) dc.append(gd[0]) # start Glue from glue.app.qt.application import GlueApplication self.gluvizapp = GlueApplication(dc) # ------------------------------------------------------------------ # Very important!!! Can't open another QMainWindow without this line self.windowList.append(self.gluvizapp) self.close() self.gluvizapp.start() self.infob.setText("Glueviz is running.")
def test_component_id_combo_helper(): combo = QtWidgets.QComboBox() dc = DataCollection([]) helper = ComponentIDComboHelper(combo, dc) assert combo_as_string(combo) == "" data1 = Data(x=[1, 2, 3], y=[2, 3, 4], label='data1') dc.append(data1) helper.append_data(data1) assert combo_as_string(combo) == "x:y" data2 = Data(a=[1, 2, 3], b=['a', 'b', 'c'], label='data2') dc.append(data2) helper.append_data(data2) assert combo_as_string(combo) == "data1:x:y:data2:a:b" helper.categorical = False assert combo_as_string(combo) == "data1:x:y:data2:a" helper.numeric = False assert combo_as_string(combo) == "data1:data2" helper.categorical = True helper.numeric = True helper.visible = False assert combo_as_string( combo ) == "data1:Pixel Axis 0 [x]:World 0:x:y:data2:Pixel Axis 0 [x]:World 0:a:b" helper.visible = True dc.remove(data2) assert combo_as_string(combo) == "x:y" # TODO: check that renaming a component updates the combo # data1.id['x'].label = 'z' # assert combo_as_string(combo) == "z:y" helper.remove_data(data1) assert combo_as_string(combo) == ""
def test_component_id_combo_helper(): state = ExampleState() dc = DataCollection([]) helper = ComponentIDComboHelper(state, 'combo', dc) assert selection_choices(state, 'combo') == "" data1 = Data(x=[1, 2, 3], y=[2, 3, 4], label='data1') dc.append(data1) helper.append_data(data1) assert selection_choices(state, 'combo') == "x:y" data2 = Data(a=[1, 2, 3], b=['a', 'b', 'c'], label='data2') dc.append(data2) helper.append_data(data2) assert selection_choices(state, 'combo') == "data1:x:y:data2:a:b" helper.categorical = False assert selection_choices(state, 'combo') == "data1:x:y:data2:a" helper.numeric = False assert selection_choices(state, 'combo') == "data1:data2" helper.categorical = True helper.numeric = True helper.visible = False assert selection_choices( state, 'combo' ) == "data1:x:Pixel Axis 0 [x]:World 0:y:data2:a:Pixel Axis 0 [x]:World 0:b" helper.visible = True dc.remove(data2) assert selection_choices(state, 'combo') == "x:y" # TODO: check that renaming a component updates the combo # data1.id['x'].label = 'z' # assert selection_choices(state, 'combo') == "z:y" helper.remove_data(data1) assert selection_choices(state, 'combo') == ""
def test_component_id_combo_helper(): combo = QtWidgets.QComboBox() dc = DataCollection([]) helper = ComponentIDComboHelper(combo, dc) assert _items_as_string(combo) == "" data1 = Data(x=[1,2,3], y=[2,3,4], label='data1') dc.append(data1) helper.append_data(data1) assert _items_as_string(combo) == "x:y" data2 = Data(a=[1,2,3], b=['a','b','c'], label='data2') dc.append(data2) helper.append_data(data2) assert _items_as_string(combo) == "data1:x:y:data2:a:b" helper.categorical = False assert _items_as_string(combo) == "data1:x:y:data2:a" helper.numeric = False assert _items_as_string(combo) == "data1:data2" helper.categorical = True helper.numeric = True helper.visible = False assert _items_as_string(combo) == "data1:Pixel Axis 0 [x]:World 0:x:y:data2:Pixel Axis 0 [x]:World 0:a:b" helper.visible = True dc.remove(data2) assert _items_as_string(combo) == "x:y" # TODO: check that renaming a component updates the combo # data1.id['x'].label = 'z' # assert _items_as_string(combo) == "z:y" helper.remove_data(data1) assert _items_as_string(combo) == ""
def glue_gui(): d = data_factories.load_data(DEIMOSTABLE) dc = DataCollection([]) dc.append(d) # Creates glue instance app = GlueApplication(dc) app.setVisible(True) # Adds data to the MosVizViewer app.new_data_viewer(MOSVizViewer) app.viewers[0][0].add_data_for_testing(app.data_collection[0]) return app
def main(): import numpy as np from glue.utils.qt import get_qapp from glue.core import Data, DataCollection app = get_qapp() dc = DataCollection() for i in range(10): x = np.array([1, 2, 3]) d = Data(label='data_{0:02d}'.format(i), x=x, y=x * 2) dc.append(d) LinkEditor.update_links(dc)
def test_data_collection_combo_helper(): combo = QtWidgets.QComboBox() dc = DataCollection([]) helper = DataCollectionComboHelper(combo, dc) data1 = Data(x=[1,2,3], y=[2,3,4], label='data1') dc.append(data1) assert _items_as_string(combo) == "data1" data1.label = 'mydata1' assert _items_as_string(combo) == "mydata1" dc.remove(data1) assert _items_as_string(combo) == ""
def test_data_collection_combo_helper(): state = ExampleState() dc = DataCollection([]) helper = DataCollectionComboHelper(state, 'combo', dc) # noqa data1 = Data(x=[1, 2, 3], y=[2, 3, 4], label='data1') dc.append(data1) assert selection_choices(state, 'combo') == "data1" data1.label = 'mydata1' assert selection_choices(state, 'combo') == "mydata1" dc.remove(data1) assert selection_choices(state, 'combo') == ""
def test_data_collection_combo_helper(): combo = QtWidgets.QComboBox() dc = DataCollection([]) helper = DataCollectionComboHelper(combo, dc) data1 = Data(x=[1, 2, 3], y=[2, 3, 4], label='data1') dc.append(data1) assert combo_as_string(combo) == "data1" data1.label = 'mydata1' assert combo_as_string(combo) == "mydata1" dc.remove(data1) assert combo_as_string(combo) == ""
def test_manual_data_combo_helper(initialize_data_collection): # The case with initialize_data_collection=False is a regression test for a # bug which meant that when a ManualDataComboHelper was initialized without # a data collection, it did not change when a data object added later has a # label changed. callback = MagicMock() state = ExampleState() state.add_callback('combo', callback) dc = DataCollection([]) if initialize_data_collection: helper = ManualDataComboHelper(state, 'combo', dc) else: helper = ManualDataComboHelper(state, 'combo') data1 = Data(x=[1, 2, 3], y=[2, 3, 4], label='data1') dc.append(data1) assert callback.call_count == 0 assert selection_choices(state, 'combo') == "" helper.append_data(data1) assert callback.call_count == 1 assert selection_choices(state, 'combo') == "data1" data1.label = 'mydata1' assert selection_choices(state, 'combo') == "mydata1" assert callback.call_count == 2 if initialize_data_collection: dc.remove(data1) assert selection_choices(state, 'combo') == "" assert callback.call_count == 3
def jglue(*args, **kwargs): from glue.core import DataCollection from glue.app.qt import GlueApplication from glue.qglue import parse_data, parse_links from glue.core.data_factories import load_data links = kwargs.pop('links', None) dc = DataCollection() for label, data in kwargs.items(): if isinstance(data, six.string_types): data = load_data(data) dc.extend(parse_data(data, label)) for data in args: dc.append(data) if links is not None: dc.add_link(parse_links(dc, links)) japp = JupyterApplication(dc) return japp
def test_component_id_combo_helper_replaced(): # Make sure that when components are replaced, the equivalent combo index # remains selected and an event is broadcast so that any attached callback # properties can be sure to pull the latest text/userData. callback = MagicMock() combo = QtWidgets.QComboBox() combo.currentIndexChanged.connect(callback) dc = DataCollection([]) helper = ComponentIDComboHelper(combo, dc) assert combo_as_string(combo) == "" data1 = Data(x=[1, 2, 3], y=[2, 3, 4], label='data1') callback.reset_mock() dc.append(data1) helper.append_data(data1) callback.assert_called_once_with(0) callback.reset_mock() assert combo_as_string(combo) == "x:y" new_id = ComponentID(label='new') data1.update_id(data1.id['x'], new_id) callback.assert_called_once_with(0) callback.reset_mock() assert combo_as_string(combo) == "new:y"
def test_component_id_combo_helper_replaced(): # Make sure that when components are replaced, the equivalent combo index # remains selected and an event is broadcast so that any attached callback # properties can be sure to pull the latest text/userData. callback = MagicMock() state = ExampleState() state.add_callback('combo', callback) dc = DataCollection([]) helper = ComponentIDComboHelper(state, 'combo', dc) assert selection_choices(state, 'combo') == "" data1 = Data(x=[1, 2, 3], y=[2, 3, 4], label='data1') callback.reset_mock() dc.append(data1) helper.append_data(data1) callback.assert_called_once_with(0) callback.reset_mock() assert selection_choices(state, 'combo') == "x:y" new_id = ComponentID(label='new') data1.update_id(data1.id['x'], new_id) callback.assert_called_once_with(0) callback.reset_mock() assert selection_choices(state, 'combo') == "new:y"
def test_manual_data_combo_helper(): combo = QtGui.QComboBox() dc = DataCollection([]) helper = ManualDataComboHelper(combo, dc) data1 = Data(x=[1, 2, 3], y=[2, 3, 4], label='data1') dc.append(data1) assert _items_as_string(combo) == "" helper.append(data1) assert _items_as_string(combo) == "data1" data1.label = 'mydata1' assert _items_as_string(combo) == "mydata1" dc.remove(data1) assert _items_as_string(combo) == ""
self.layer_combo.setEnabled(True) # Set up contents of combo box labeldata = [] # First include the dataset itself labeldata.append(('Full dataset', self.data)) for subset in self.data.subsets: labeldata.append((subset.label, subset)) update_combobox(self.layer_combo, labeldata) if __name__ == "__main__": from glue.utils.qt import get_qapp from glue.core import Data, DataCollection data_collection = DataCollection() data = Data(x=[1, 2, 3], label='banana') data_collection.append(data) data_collection.new_subset_group('a', data.id['x'] > 0) app = get_qapp() widget = SimpleLayerWidget() widget.show() widget.data = data app.exec_()
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
column_name = 'cat_peak' nc = Component.autotyped(cc, units=uu) catalog.add_component(nc, column_name) # if column_name != 'parent' else '_flarent_' catalog.join_on_key(dendro, '_idx', dendro.pixel_component_ids[0]) dc = DataCollection(dendrogram) #dc = DataCollection([cube, dendrogram, catalog]) #dc.merge(cube,sncube) #sncube.join_on_key(dendro, 'structure', dendro.pixel_component_ids[0]) #dc.merge(catalog, dendro) # UNCOMMENT THIS LINE TO BREAK THE VIEWER dc.append(catalog) app = GlueApplication(dc) cube_viewer = app.new_data_viewer(ImageWidget) cube_viewer.add_data(sncube) # link positional information dc.add_link(LinkSame(sncube.id['structure'], catalog.id['_idx'])) #dc.add_link(LinkSame(image.id['World y: DEC--TAN'], catalog.id['DEJ2000'])) dc.add_link(LinkSame(cube.id['Galactic Longitude'], catalog.id['x_cen'])) dc.add_link(LinkSame(cube.id['Galactic Latitude'], catalog.id['y_cen'])) def ms_to_kms(x): return x/1e3 def kms_to_ms(x): return x*1e3
class TestFixedResolutionBuffer(): def setup_method(self, method): self.data_collection = DataCollection() # The reference dataset. Shape is (6, 7, 8, 9). self.data1 = Data(x=ARRAY) self.data_collection.append(self.data1) # A dataset with the same shape but not linked. Shape is (6, 7, 8, 9). self.data2 = Data(x=ARRAY) self.data_collection.append(self.data2) # A dataset with the same number of dimensions but in a different # order, linked to the first. Shape is (9, 7, 6, 8). self.data3 = Data(x=np.moveaxis(ARRAY, (3, 1, 0, 2), (0, 1, 2, 3))) self.data_collection.append(self.data3) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[0], self.data3.pixel_component_ids[2])) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[1], self.data3.pixel_component_ids[1])) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[2], self.data3.pixel_component_ids[3])) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[3], self.data3.pixel_component_ids[0])) # A dataset with fewer dimensions, linked to the first one. Shape is # (8, 7, 6) self.data4 = Data(x=ARRAY[:, :, :, 0].transpose()) self.data_collection.append(self.data4) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[0], self.data4.pixel_component_ids[2])) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[1], self.data4.pixel_component_ids[1])) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[2], self.data4.pixel_component_ids[0])) # A dataset with even fewer dimensions, linked to the first one. Shape # is (8, 6) self.data5 = Data(x=ARRAY[:, 0, :, 0].transpose()) self.data_collection.append(self.data5) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[0], self.data5.pixel_component_ids[1])) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[2], self.data5.pixel_component_ids[0])) # A dataset that is not on the same pixel grid and requires reprojection # self.data6 = Data() # self.data6.coords = SimpleCoordinates() # self.array_nonaligned = np.arange(60).reshape((5, 3, 4)) # self.data6['x'] = np.array(self.array_nonaligned) # self.data_collection.append(self.data6) # self.data_collection.add_link(LinkSame(self.data1.world_component_ids[0], # self.data6.world_component_ids[1])) # self.data_collection.add_link(LinkSame(self.data1.world_component_ids[1], # self.data6.world_component_ids[2])) # self.data_collection.add_link(LinkSame(self.data1.world_component_ids[2], # self.data6.world_component_ids[0])) # Start off with the cases where the data is the target data. Enumerate # the different cases for the bounds and the expected result. DATA_IS_TARGET_CASES = [ # Bounds are full extent of data ([(0, 5, 6), (0, 6, 7), (0, 7, 8), (0, 8, 9)], ARRAY), # Bounds are inside data ([(2, 3, 2), (3, 3, 1), (0, 7, 8), (0, 7, 8)], ARRAY[2:4, 3:4, :, :8]), # Bounds are outside data along some dimensions ([(-5, 9, 15), (3, 5, 3), (0, 9, 10), (5, 6, 2)], np.pad(ARRAY[:, 3:6, :, 5:7], [(5, 4), (0, 0), (0, 2), (0, 0)], mode='constant', constant_values=-np.inf)), # No overlap ([(2, 3, 2), (3, 3, 1), (-5, -4, 2), (0, 7, 8)], -np.inf * np.ones((2, 1, 2, 8))) ] @pytest.mark.parametrize(('bounds', 'expected'), DATA_IS_TARGET_CASES) def test_data_is_target_full_bounds(self, bounds, expected): buffer = self.data1.compute_fixed_resolution_buffer(target_data=self.data1, bounds=bounds, target_cid=self.data1.id['x']) assert_equal(buffer, expected) buffer = self.data3.compute_fixed_resolution_buffer(target_data=self.data1, bounds=bounds, target_cid=self.data3.id['x']) assert_equal(buffer, expected)
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
def activate(self): #grab hover info# dc_hover=DataCollection() for layer in self.viewer.layers: layer_state=layer.state if (layer_state.visible) and (layer.enabled): data=Data(label=layer_state.layer.label) for component in layer_state.layer.components: data[component.label]=np.ones(10) dc_hover.append(data) global checked_dictionary checked_dictionary={} #figure out which hover info user wants to display# for layer in self.viewer.layers: layer_state=layer.state if (layer_state.visible) and (layer.enabled): checked_dictionary[layer_state.layer.label]=np.zeros((len(layer_state.layer.components))).astype(bool) app = get_qapp() dialog = save_hover.SaveHoverDialog(data_collection=dc_hover,checked_dictionary=checked_dictionary) dialog.exec_() filename, _ = compat.getsavefilename(parent=self.viewer, basedir="plot.html") width, height = self.viewer.figure.get_size_inches()*self.viewer.figure.dpi # set the aspect ratio of the axes, the tick label size, the axis label # sizes, and the axes limits layout = go.Layout( margin=dict(r=50, l=50, b=50, t=50), # noqa width=1200, height=1200*height/width, # scale axis correctly plot_bgcolor='white', xaxis=dict( title=self.viewer.axes.get_xlabel(), titlefont=dict( family=DEFAULT_FONT, size=2*self.viewer.axes.xaxis.get_label().get_size(), color='black' ), showspikes=False, zerolinecolor='rgb(128,128,128)', showticklabels=True, tickfont=dict( family=DEFAULT_FONT, size=1.5*self.viewer.axes.xaxis.get_ticklabels()[ 0].get_fontsize(), color='black'), range=[self.viewer.state.x_min, self.viewer.state.x_max]), yaxis=dict( title=self.viewer.axes.get_ylabel(), titlefont=dict( family=DEFAULT_FONT, size=2*self.viewer.axes.yaxis.get_label().get_size(), color='black'), showspikes=False, gridcolor='rgb(220,220,220)', range=[self.viewer.state.y_min, self.viewer.state.y_max], showticklabels=True, tickfont=dict( family=DEFAULT_FONT, size=1.5*self.viewer.axes.yaxis.get_ticklabels()[ 0].get_fontsize(), color='black'), ) ) fig = go.Figure(layout=layout) for layer in self.viewer.layers: layer_state=layer.state if (layer_state.visible) and (layer.enabled): x = layer_state.layer[self.viewer.state.x_att] y = layer_state.layer[self.viewer.state.y_att] marker = {} # set all points to be the same color if layer_state.cmap_mode == 'Fixed': if layer_state.color != '0.35': marker['color'] = layer_state.color else: marker['color'] = 'gray' # color by some attribute else: if layer_state.cmap_vmin > layer_state.cmap_vmax: cmap = layer_state.cmap.reversed() norm = Normalize( vmin=layer_state.cmap_vmax, vmax=layer_state.cmap_vmin) else: cmap = layer_state.cmap norm = Normalize( vmin=layer_state.cmap_vmin, vmax=layer_state.cmap_vmax) # most matplotlib colormaps aren't recognized by plotly, so we convert manually to a hex code rgba_list = [ cmap(norm(point)) for point in layer_state.layer[layer_state.cmap_att].copy()] rgb_str = [r'{}'.format(colors.rgb2hex( (rgba[0], rgba[1], rgba[2]))) for rgba in rgba_list] marker['color'] = rgb_str # set all points to be the same size, with some arbitrary scaling if layer_state.size_mode == 'Fixed': marker['size'] = layer_state.size # scale size of points by some attribute else: marker['size'] = 25 * (layer_state.layer[layer_state.size_att] - layer_state.size_vmin) / ( layer_state.size_vmax - layer_state.size_vmin) marker['sizemin'] = 1 marker['size'][np.isnan(marker['size'])] = 0 marker['size'][marker['size'] < 0] = 0 # set the opacity marker['opacity'] = layer_state.alpha # remove default white border around points marker['line'] = dict(width=0) #add hover info to layer# hovertextarr=["" for x in range(layer_state.layer.shape[0])] if np.sum(dialog.checked_dictionary[layer_state.layer.label])==0: hoverinfo='skip' hovertext=None else: hoverinfo='text' hovertext=["" for i in range((layer_state.layer.shape[0]))] for i in range(0,len(layer_state.layer.components)): if dialog.checked_dictionary[layer_state.layer.label][i]==True: hover_data=layer_state.layer[layer_state.layer.components[i].label] for k in range(0,len(hover_data)): hovertext[k]=hovertext[k]+"{}: {} <br>".format(layer_state.layer.components[i].label,hover_data[k]) # add layer to axes fig.add_scatter(x=x, y=y, mode='markers', marker=marker, hoverinfo=hoverinfo, hovertext=hovertext, name=layer_state.layer.label) plot(fig, filename=filename, auto_open=False)
def test_component_id_combo_helper(): state = ExampleState() dc = DataCollection([]) helper = ComponentIDComboHelper(state, 'combo', dc) assert selection_choices(state, 'combo') == "" data1 = Data(x=[1, 2, 3], y=[2, 3, 4], label='data1') dc.append(data1) helper.append_data(data1) assert selection_choices(state, 'combo') == "x:y" data2 = Data(a=[1, 2, 3], b=['a', 'b', 'c'], label='data2') dc.append(data2) helper.append_data(data2) assert selection_choices(state, 'combo') == "data1:x:y:data2:a:b" helper.categorical = False assert selection_choices(state, 'combo') == "data1:x:y:data2:a" helper.numeric = False assert selection_choices(state, 'combo') == "data1:data2" helper.categorical = True helper.numeric = True helper.pixel_coord = True assert selection_choices( state, 'combo' ) == "data1:main:x:y:coord:Pixel Axis 0 [x]:data2:main:a:b:coord:Pixel Axis 0 [x]" helper.world_coord = True assert selection_choices( state, 'combo' ) == "data1:main:x:y:coord:Pixel Axis 0 [x]:World 0:data2:main:a:b:coord:Pixel Axis 0 [x]:World 0" helper.pixel_coord = False assert selection_choices( state, 'combo') == "data1:main:x:y:coord:World 0:data2:main:a:b:coord:World 0" helper.world_coord = False dc.remove(data2) assert selection_choices(state, 'combo') == "x:y" data1['z'] = data1.id['x'] + 1 assert selection_choices(state, 'combo') == "main:x:y:derived:z" helper.derived = False assert selection_choices(state, 'combo') == "x:y" data1.id['x'].label = 'z' assert selection_choices(state, 'combo') == "z:y" helper.remove_data(data1) assert selection_choices(state, 'combo') == ""
def activate(self): # grab hover info dc_hover = DataCollection() for layer in self.viewer.layers: layer_state = layer.state if layer_state.visible and layer.enabled: data = Data(label=layer_state.layer.label) for component in layer_state.layer.components: data[component.label] = np.ones(10) dc_hover.append(data) checked_dictionary = {} # figure out which hover info user wants to display for layer in self.viewer.layers: layer_state = layer.state if layer_state.visible and layer.enabled: checked_dictionary[layer_state.layer.label] = np.zeros( (len(layer_state.layer.components))).astype(bool) dialog = save_hover.SaveHoverDialog( data_collection=dc_hover, checked_dictionary=checked_dictionary) dialog.exec_() # query filename filename, _ = compat.getsavefilename(parent=self.viewer, basedir="plot.html") # when vispy viewer is in "native aspect ratio" mode, scale axes size by data if self.viewer.state.native_aspect: width = self.viewer.state.x_max - self.viewer.state.x_min height = self.viewer.state.y_max - self.viewer.state.y_min depth = self.viewer.state.z_max - self.viewer.state.z_min # otherwise, set all axes to be equal size else: width = 1200 # this 1200 size is arbitrary, could change to any width; just need to scale rest accordingly height = 1200 depth = 1200 # set the aspect ratio of the axes, the tick label size, the axis label sizes, and the axes limits layout = go.Layout( margin=dict(r=50, l=50, b=50, t=50), # noqa width=1200, scene=dict( xaxis=dict( title=self.viewer.state.x_att.label, titlefont=dict(family=DEFAULT_FONT, size=20, color='black'), showspikes=False, backgroundcolor='white', gridcolor='rgb(220,220,220)', showticklabels=True, tickfont=dict(family=DEFAULT_FONT, size=12, color='black'), range=[self.viewer.state.x_min, self.viewer.state.x_max]), yaxis=dict( title=self.viewer.state.y_att.label, titlefont=dict(family=DEFAULT_FONT, size=20, color='black'), showspikes=False, backgroundcolor='white', gridcolor='rgb(220,220,220)', range=[self.viewer.state.y_min, self.viewer.state.y_max], showticklabels=True, tickfont=dict(family=DEFAULT_FONT, size=12, color='black'), ), zaxis=dict( title=self.viewer.state.z_att.label, titlefont=dict(family=DEFAULT_FONT, size=20, color='black'), showspikes=False, backgroundcolor='white', gridcolor='rgb(220,220,220)', range=[self.viewer.state.z_min, self.viewer.state.z_max], showticklabels=True, tickfont=dict(family=DEFAULT_FONT, size=12, color='black'), ), aspectratio=dict( x=1 * self.viewer.state.x_stretch, y=height / width * self.viewer.state.y_stretch, z=depth / width * self.viewer.state.z_stretch), aspectmode='manual', ), ) fig = go.Figure(layout=layout) for layer in self.viewer.layers: layer_state = layer.state if layer_state.visible and layer.enabled: x = layer_state.layer[self.viewer.state.x_att] y = layer_state.layer[self.viewer.state.y_att] z = layer_state.layer[self.viewer.state.z_att] marker = {} # set all points to be the same color if layer_state.color_mode == 'Fixed': if layer_state.color != '0.35': marker['color'] = layer_state.color else: marker['color'] = 'gray' # color by some attribute else: if layer_state.cmap_vmin > layer_state.cmap_vmax: cmap = layer_state.cmap.reversed() norm = Normalize(vmin=layer_state.cmap_vmax, vmax=layer_state.cmap_vmin) else: cmap = layer_state.cmap norm = Normalize(vmin=layer_state.cmap_vmin, vmax=layer_state.cmap_vmax) # most matplotlib colormaps aren't recognized by plotly, so we convert manually to a hex code rgba_list = [ cmap(norm(point)) for point in layer_state.layer[ layer_state.cmap_attribute].copy() ] rgb_str = [ r'{}'.format( colors.rgb2hex((rgba[0], rgba[1], rgba[2]))) for rgba in rgba_list ] marker['color'] = rgb_str # set all points to be the same size, with some arbitrary scaling if layer_state.size_mode == 'Fixed': marker['size'] = layer_state.size # scale size of points by some attribute else: marker['size'] = 25 * ( layer_state.layer[layer_state.size_attribute] - layer_state.size_vmin) / (layer_state.size_vmax - layer_state.size_vmin) marker['sizemin'] = 1 marker['size'][np.isnan(marker['size'])] = 0 marker['size'][marker['size'] < 0] = 0 # set the opacity marker['opacity'] = layer_state.alpha marker['line'] = dict(width=0) # add hover info to layer if np.sum(dialog.checked_dictionary[ layer_state.layer.label]) == 0: hoverinfo = 'skip' hovertext = None else: hoverinfo = 'text' hovertext = [ "" for i in range((layer_state.layer.shape[0])) ] for i in range(0, len(layer_state.layer.components)): if dialog.checked_dictionary[ layer_state.layer.label][i]: hover_data = layer_state.layer[ layer_state.layer.components[i].label] for k in range(0, len(hover_data)): hovertext[k] = ( hovertext[k] + "{}: {} <br>".format( layer_state.layer.components[i].label, hover_data[k])) # add layer to axes fig.add_scatter3d(x=x, y=y, z=z, mode='markers', marker=marker, hoverinfo=hoverinfo, hovertext=hovertext, name=layer_state.layer.label) plot(fig, filename=filename, auto_open=False)
class TestReprojection(): def setup_method(self, method): self.data_collection = DataCollection() self.array = np.arange(3024).reshape((6, 7, 8, 9)) # The reference dataset. Shape is (6, 7, 8, 9). self.data1 = Data(x=self.array) self.data_collection.append(self.data1) # A dataset with the same shape but not linked. Shape is (6, 7, 8, 9). self.data2 = Data(x=self.array) self.data_collection.append(self.data2) # A dataset with the same number of dimesnions but in a different # order, linked to the first. Shape is (9, 7, 6, 8). self.data3 = Data(x=np.moveaxis(self.array, (3, 1, 0, 2), (0, 1, 2, 3))) self.data_collection.append(self.data3) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[0], self.data3.pixel_component_ids[2])) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[1], self.data3.pixel_component_ids[1])) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[2], self.data3.pixel_component_ids[3])) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[3], self.data3.pixel_component_ids[0])) # A dataset with fewer dimensions, linked to the first one. Shape is # (8, 7, 6) self.data4 = Data(x=self.array[:, :, :, 0].transpose()) self.data_collection.append(self.data4) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[0], self.data4.pixel_component_ids[2])) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[1], self.data4.pixel_component_ids[1])) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[2], self.data4.pixel_component_ids[0])) # A dataset with even fewer dimensions, linked to the first one. Shape # is (8, 6) self.data5 = Data(x=self.array[:, 0, :, 0].transpose()) self.data_collection.append(self.data5) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[0], self.data5.pixel_component_ids[1])) self.data_collection.add_link(LinkSame(self.data1.pixel_component_ids[2], self.data5.pixel_component_ids[0])) # A dataset that is not on the same pixel grid and requires reprojection self.data6 = Data() self.data6.coords = SimpleCoordinates() self.array_nonaligned = np.arange(60).reshape((5, 3, 4)) self.data6['x'] = np.array(self.array_nonaligned) self.data_collection.append(self.data6) self.data_collection.add_link(LinkSame(self.data1.world_component_ids[0], self.data6.world_component_ids[1])) self.data_collection.add_link(LinkSame(self.data1.world_component_ids[1], self.data6.world_component_ids[2])) self.data_collection.add_link(LinkSame(self.data1.world_component_ids[2], self.data6.world_component_ids[0])) self.viewer_state = ImageViewerState() self.viewer_state.layers.append(ImageLayerState(viewer_state=self.viewer_state, layer=self.data1)) self.viewer_state.layers.append(ImageLayerState(viewer_state=self.viewer_state, layer=self.data2)) self.viewer_state.layers.append(ImageLayerState(viewer_state=self.viewer_state, layer=self.data3)) self.viewer_state.layers.append(ImageLayerState(viewer_state=self.viewer_state, layer=self.data4)) self.viewer_state.layers.append(ImageLayerState(viewer_state=self.viewer_state, layer=self.data5)) self.viewer_state.layers.append(ImageLayerState(viewer_state=self.viewer_state, layer=self.data6)) self.viewer_state.reference_data = self.data1 def test_default_axis_order(self): # Start off with a combination of x/y that means that only one of the # other datasets will be matched. self.viewer_state.x_att = self.data1.pixel_component_ids[3] self.viewer_state.y_att = self.data1.pixel_component_ids[2] self.viewer_state.slices = (3, 2, 4, 1) image = self.viewer_state.layers[0].get_sliced_data() assert_equal(image, self.array[3, 2, :, :]) with pytest.raises(IncompatibleAttribute): self.viewer_state.layers[1].get_sliced_data() image = self.viewer_state.layers[2].get_sliced_data() assert_equal(image, self.array[3, 2, :, :]) with pytest.raises(IncompatibleDataException): self.viewer_state.layers[3].get_sliced_data() with pytest.raises(IncompatibleDataException): self.viewer_state.layers[4].get_sliced_data() def test_transpose_axis_order(self): # Next make it so the x/y axes correspond to the dimensions with length # 6 and 8 which most datasets will be compatible with, and this also # requires a tranposition. self.viewer_state.x_att = self.data1.pixel_component_ids[0] self.viewer_state.y_att = self.data1.pixel_component_ids[2] self.viewer_state.slices = (3, 2, 4, 1) image = self.viewer_state.layers[0].get_sliced_data() print(image.shape) assert_equal(image, self.array[:, 2, :, 1].transpose()) with pytest.raises(IncompatibleAttribute): self.viewer_state.layers[1].get_sliced_data() image = self.viewer_state.layers[2].get_sliced_data() print(image.shape) assert_equal(image, self.array[:, 2, :, 1].transpose()) image = self.viewer_state.layers[3].get_sliced_data() assert_equal(image, self.array[:, 2, :, 0].transpose()) image = self.viewer_state.layers[4].get_sliced_data() assert_equal(image, self.array[:, 0, :, 0].transpose()) def test_transpose_axis_order_view(self): # As for the previous test, but this time with a view applied self.viewer_state.x_att = self.data1.pixel_component_ids[0] self.viewer_state.y_att = self.data1.pixel_component_ids[2] self.viewer_state.slices = (3, 2, 4, 1) view = [slice(1, None, 2), slice(None, None, 3)] image = self.viewer_state.layers[0].get_sliced_data(view=view) assert_equal(image, self.array[::3, 2, 1::2, 1].transpose()) with pytest.raises(IncompatibleAttribute): self.viewer_state.layers[1].get_sliced_data(view=view) image = self.viewer_state.layers[2].get_sliced_data(view=view) print(image.shape) assert_equal(image, self.array[::3, 2, 1::2, 1].transpose()) image = self.viewer_state.layers[3].get_sliced_data(view=view) assert_equal(image, self.array[::3, 2, 1::2, 0].transpose()) image = self.viewer_state.layers[4].get_sliced_data(view=view) assert_equal(image, self.array[::3, 0, 1::2, 0].transpose()) def test_reproject(self): # Test a case where the data needs to actually be reprojected # As for the previous test, but this time with a view applied self.viewer_state.x_att = self.data1.pixel_component_ids[0] self.viewer_state.y_att = self.data1.pixel_component_ids[2] self.viewer_state.slices = (3, 2, 4, 1) view = [slice(1, None, 2), slice(None, None, 3)] actual = self.viewer_state.layers[5].get_sliced_data(view=view) # The data to be reprojected is 3-dimensional. The axes we have set # correspond to 1 (for x) and 0 (for y). The third dimension of the # data to be reprojected should be sliced. This is linked with the # second dimension of the original data, for which the slice index is # 2. Since the data to be reprojected has coordinates that are 2.5 times # those of the reference data, this means the slice index should be 0.8, # which rounded corresponds to 1. expected = self.array_nonaligned[:, :, 1] # Now in the frame of the reference data, the data to show are indices # [0, 3] along x and [1, 3, 5, 7] along y. Applying the transformation, # this gives values of [0, 1.2] and [0.4, 1.2, 2, 2.8] for x and y, # and rounded, this gives [0, 1] and [0, 1, 2, 3]. As a reminder, in the # data to reproject, dimension 0 is y and dimension 1 is x expected = expected[:4, :2] # Let's make sure this works! assert_equal(actual, expected) def test_too_many_dimensions(self): # If we change the reference data, then the first dataset won't be # visible anymore because it has too many dimensions self.viewer_state.reference_data = self.data4 with pytest.raises(IncompatibleAttribute): self.viewer_state.layers[0].get_sliced_data() self.viewer_state.reference_data = self.data6 with pytest.raises(IncompatibleAttribute): self.viewer_state.layers[0].get_sliced_data() def test_reset_pixel_cache(self): # Test to make sure that resetting the pixel cache works properly self.viewer_state.x_att = self.data1.pixel_component_ids[0] self.viewer_state.y_att = self.data1.pixel_component_ids[2] self.viewer_state.slices = (1, 1, 1, 1) layer = self.viewer_state.layers[5] assert layer._pixel_cache is None layer.get_sliced_data() assert layer._pixel_cache['reset_slices'][0] == [False, False, True, False] assert layer._pixel_cache['reset_slices'][1] == [True, True, False, False] assert layer._pixel_cache['reset_slices'][2] == [True, True, False, False] self.viewer_state.slices = (1, 1, 1, 2) assert layer._pixel_cache['reset_slices'][0] == [False, False, True, False] assert layer._pixel_cache['reset_slices'][1] == [True, True, False, False] assert layer._pixel_cache['reset_slices'][2] == [True, True, False, False] self.viewer_state.slices = (1, 2, 1, 2) assert layer._pixel_cache['reset_slices'][0] == [False, False, True, False] assert layer._pixel_cache['reset_slices'][1] is None assert layer._pixel_cache['reset_slices'][2] is None self.viewer_state.slices = (1, 2, 2, 2) assert layer._pixel_cache['reset_slices'][0] is None assert layer._pixel_cache['reset_slices'][1] is None assert layer._pixel_cache['reset_slices'][2] is None
def test_component_id_combo_helper(): state = ExampleState() dc = DataCollection([]) helper = ComponentIDComboHelper(state, 'combo', dc) assert selection_choices(state, 'combo') == "" data1 = Data(x=[1, 2, 3], y=[2, 3, 4], label='data1') dc.append(data1) helper.append_data(data1) assert selection_choices(state, 'combo') == "x:y" data2 = Data(a=[1, 2, 3], b=['a', 'b', 'c'], label='data2') dc.append(data2) helper.append_data(data2) assert selection_choices(state, 'combo') == "data1:x:y:data2:a:b" helper.categorical = False assert selection_choices(state, 'combo') == "data1:x:y:data2:a" helper.numeric = False assert selection_choices(state, 'combo') == "data1:data2" helper.categorical = True helper.numeric = True helper.pixel_coord = True assert selection_choices(state, 'combo') == "data1:main:x:y:coord:Pixel Axis 0 [x]:data2:main:a:b:coord:Pixel Axis 0 [x]" helper.world_coord = True assert selection_choices(state, 'combo') == "data1:main:x:y:coord:Pixel Axis 0 [x]:World 0:data2:main:a:b:coord:Pixel Axis 0 [x]:World 0" helper.pixel_coord = False assert selection_choices(state, 'combo') == "data1:main:x:y:coord:World 0:data2:main:a:b:coord:World 0" helper.world_coord = False dc.remove(data2) assert selection_choices(state, 'combo') == "x:y" data1['z'] = data1.id['x'] + 1 assert selection_choices(state, 'combo') == "main:x:y:derived:z" helper.derived = False assert selection_choices(state, 'combo') == "x:y" data1.id['x'].label = 'z' assert selection_choices(state, 'combo') == "z:y" helper.remove_data(data1) assert selection_choices(state, 'combo') == ""
def get_subsets_from_viewer(self, viewer_reference, data_label=None): """ Returns the subsets of a specified viewer converted to astropy regions objects. It should be noted that the subset translation machinery lives in the glue-astronomy repository. Currently, the machinery only works on 2D data for cases like range selection. For e.g. a profile viewer that is ostensibly just a view into a 3D data set, it is necessary to first reduce the dimensions of the data, then retrieve the subset information as a regions object. This means that the returned y extents in the region are not strictly representative of the subset range in y. Parameters ---------- viewer_reference : str The reference to the viewer defined with the ``reference`` key in the yaml configuration file. data_label : str, optional Optionally provide a label to retrieve a specific data set from the viewer instance. Returns ------- data : dict A dict of the transformed Glue subset objects, with keys representing the subset name and values as astropy regions objects. """ viewer = self.get_viewer(viewer_reference) data = self.get_data_from_viewer(viewer_reference, data_label, cls=None) regions = {} for key, value in data.items(): if isinstance(value, Subset): # Range selection on a profile is currently not supported in # the glue translation machinery for astropy regions, so we # have to do it manually. Only data that is 2d is supported, # therefore, if the data is already 2d, simply use as is. if value.data.ndim == 2: region = value.data.get_selection_definition( format='astropy-regions') regions[key] = region continue # There is a special case for 1d data (which is also not # supported currently). We now eschew the use of the # translation machinery entirely and construct the astropy # region ourselves. elif value.data.ndim == 1: # Grab the data units from the glue-astronomy spectral axis # TODO: this needs to be much simpler; i.e. data units in # the glue component objects unit = value.data.coords.spectral_axis.unit hi, lo = value.subset_state.hi, value.subset_state.lo xcen = 0.5 * (lo + hi) width = hi - lo region = RectanglePixelRegion( PixCoord(xcen, 0), width, 0, meta={'spectal_axis_unit': unit}) regions[key] = region continue # Get the pixel coordinate [z] of the 3D data, repeating the # wavelength axis. This doesn't seem strictly necessary as it # returns the same data if the pixel axis is [y] or [x] xid = value.data.pixel_component_ids[0] # Construct a new data object collapsing over one of the # spatial dimensions. This is necessary because the astropy # region translation machinery in glue-astronomy does not # support non-2D data, even for range objects. stat_func = 'median' if hasattr(viewer.state, 'function'): stat_func = viewer.state.function # Compute reduced data based on the current viewer's statistic # function. This doesn't seem particularly useful, but better # to be consistent. reduced_data = Data(x=value.data.compute_statistic( stat_func, value.data.id[xid], subset_state=value.subset_state, axis=1)) # Instantiate a new data collection since we need to compose # the collapsed data with the current subset state. We use a # new data collection so as not to inference with the one used # by the application. temp_data_collection = DataCollection() temp_data_collection.append(reduced_data) # Get the data id of the pixel axis that will be used in the # range composition. This is the wavelength axis for the new # 2d data. xid = reduced_data.pixel_component_ids[1] # Create a new subset group to hold our current subset state subset_group = temp_data_collection.new_subset_group( label=value.label, subset_state=value.subset_state) # Set the subset state axis to the wavelength pixel coordinate subset_group.subsets[0].subset_state.att = xid # Use the associated collapsed subset data to get an astropy # regions object dependent on the extends of the subset. # **Note** that the y values in this region object are not # useful, only the x values are. region = subset_group.subsets[0].data.get_selection_definition( format='astropy-regions') regions[key] = region return regions
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" # send a SubsetMessage to the Hub. print('Manually sending SubsetMessage') message = SubsetMessage(subset) hub.broadcast(message) # nothing is printed
dendrogram = load_dendro(hpath('DendroMask_H2CO303202.hdf5')) dendro,dendcube = dendrogram dendcube.label='Dendrogram Cube' # this label is redundant, it will be deleted upon merge # cube contains real WCS information; dendcube does not h2cocube = load_data(hpath('APEX_H2CO_303_202_bl.fits')) h2cocube.label='H2CO 303202 Cube' catalog = astropy_tabular_data(hpath('PPV_H2CO_Temperature.ipac'), format='ipac') catalog.label='Fitted Catalog' h2cocube.add_component(dendcube.get_component('structure'), 'structure') dc = DataCollection(dendrogram) dc.append(h2cocube) dc.append(catalog) dc.append(dendcube) dc.merge(h2cocube,dendcube) dc.merge(dendro, catalog) app = GlueApplication(dc) cube_viewer = app.new_data_viewer(ImageWidget) cube_viewer.add_data(h2cocube) h2cocube.join_on_key(dendro, 'structure', dendro.pixel_component_ids[0]) scatter = app.new_data_viewer(ScatterWidget) scatter.add_data(dendro)
class LabeledDelegate(QtWidgets.QStyledItemDelegate): """ Add placeholder text to default delegate """ def setEditorData(self, editor, index): super(LabeledDelegate, self).setEditorData(editor, index) label = index.model().data(index, role=Qt.DisplayRole) editor.selectAll() editor.setText(label) if __name__ == "__main__": from glue.utils.qt import get_qapp from qtpy import QtWidgets from glue.core import Data, DataCollection app = get_qapp() dc = DataCollection() dc.append(Data(label='w')) view = DataCollectionView() view.set_data_collection(dc) view.show() view.raise_() dc.extend([Data(label='x', x=[1, 2, 3]), Data(label='y', y=[1, 2, 3]), Data(label='z', z=[1, 2, 3])]) app.exec_()
class TestReprojection(): def setup_method(self, method): self.data_collection = DataCollection() self.array = np.arange(3024).reshape((6, 7, 8, 9)) # The reference dataset. Shape is (6, 7, 8, 9). self.data1 = Data(x=self.array) self.data_collection.append(self.data1) # A dataset with the same shape but not linked. Shape is (6, 7, 8, 9). self.data2 = Data(x=self.array) self.data_collection.append(self.data2) # A dataset with the same number of dimesnions but in a different # order, linked to the first. Shape is (9, 7, 6, 8). self.data3 = Data( x=np.moveaxis(self.array, (3, 1, 0, 2), (0, 1, 2, 3))) self.data_collection.append(self.data3) self.data_collection.add_link( LinkSame(self.data1.pixel_component_ids[0], self.data3.pixel_component_ids[2])) self.data_collection.add_link( LinkSame(self.data1.pixel_component_ids[1], self.data3.pixel_component_ids[1])) self.data_collection.add_link( LinkSame(self.data1.pixel_component_ids[2], self.data3.pixel_component_ids[3])) self.data_collection.add_link( LinkSame(self.data1.pixel_component_ids[3], self.data3.pixel_component_ids[0])) # A dataset with fewer dimensions, linked to the first one. Shape is # (8, 7, 6) self.data4 = Data(x=self.array[:, :, :, 0].transpose()) self.data_collection.append(self.data4) self.data_collection.add_link( LinkSame(self.data1.pixel_component_ids[0], self.data4.pixel_component_ids[2])) self.data_collection.add_link( LinkSame(self.data1.pixel_component_ids[1], self.data4.pixel_component_ids[1])) self.data_collection.add_link( LinkSame(self.data1.pixel_component_ids[2], self.data4.pixel_component_ids[0])) # A dataset with even fewer dimensions, linked to the first one. Shape # is (8, 6) self.data5 = Data(x=self.array[:, 0, :, 0].transpose()) self.data_collection.append(self.data5) self.data_collection.add_link( LinkSame(self.data1.pixel_component_ids[0], self.data5.pixel_component_ids[1])) self.data_collection.add_link( LinkSame(self.data1.pixel_component_ids[2], self.data5.pixel_component_ids[0])) # A dataset that is not on the same pixel grid and requires reprojection self.data6 = Data() self.data6.coords = SimpleCoordinates() self.array_nonaligned = np.arange(60).reshape((5, 3, 4)) self.data6['x'] = np.array(self.array_nonaligned) self.data_collection.append(self.data6) self.data_collection.add_link( LinkSame(self.data1.world_component_ids[0], self.data6.world_component_ids[1])) self.data_collection.add_link( LinkSame(self.data1.world_component_ids[1], self.data6.world_component_ids[2])) self.data_collection.add_link( LinkSame(self.data1.world_component_ids[2], self.data6.world_component_ids[0])) self.viewer_state = ImageViewerState() self.viewer_state.layers.append( ImageLayerState(viewer_state=self.viewer_state, layer=self.data1)) self.viewer_state.layers.append( ImageLayerState(viewer_state=self.viewer_state, layer=self.data2)) self.viewer_state.layers.append( ImageLayerState(viewer_state=self.viewer_state, layer=self.data3)) self.viewer_state.layers.append( ImageLayerState(viewer_state=self.viewer_state, layer=self.data4)) self.viewer_state.layers.append( ImageLayerState(viewer_state=self.viewer_state, layer=self.data5)) self.viewer_state.layers.append( ImageLayerState(viewer_state=self.viewer_state, layer=self.data6)) self.viewer_state.reference_data = self.data1 def test_default_axis_order(self): # Start off with a combination of x/y that means that only one of the # other datasets will be matched. self.viewer_state.x_att = self.data1.pixel_component_ids[3] self.viewer_state.y_att = self.data1.pixel_component_ids[2] self.viewer_state.slices = (3, 2, 4, 1) image = self.viewer_state.layers[0].get_sliced_data() assert_equal(image, self.array[3, 2, :, :]) with pytest.raises(IncompatibleAttribute): self.viewer_state.layers[1].get_sliced_data() image = self.viewer_state.layers[2].get_sliced_data() assert_equal(image, self.array[3, 2, :, :]) with pytest.raises(IncompatibleDataException): self.viewer_state.layers[3].get_sliced_data() with pytest.raises(IncompatibleDataException): self.viewer_state.layers[4].get_sliced_data() def test_transpose_axis_order(self): # Next make it so the x/y axes correspond to the dimensions with length # 6 and 8 which most datasets will be compatible with, and this also # requires a tranposition. self.viewer_state.x_att = self.data1.pixel_component_ids[0] self.viewer_state.y_att = self.data1.pixel_component_ids[2] self.viewer_state.slices = (3, 2, 4, 1) image = self.viewer_state.layers[0].get_sliced_data() print(image.shape) assert_equal(image, self.array[:, 2, :, 1].transpose()) with pytest.raises(IncompatibleAttribute): self.viewer_state.layers[1].get_sliced_data() image = self.viewer_state.layers[2].get_sliced_data() print(image.shape) assert_equal(image, self.array[:, 2, :, 1].transpose()) image = self.viewer_state.layers[3].get_sliced_data() assert_equal(image, self.array[:, 2, :, 0].transpose()) image = self.viewer_state.layers[4].get_sliced_data() assert_equal(image, self.array[:, 0, :, 0].transpose()) def test_transpose_axis_order_view(self): # As for the previous test, but this time with a view applied self.viewer_state.x_att = self.data1.pixel_component_ids[0] self.viewer_state.y_att = self.data1.pixel_component_ids[2] self.viewer_state.slices = (3, 2, 4, 1) view = [slice(1, None, 2), slice(None, None, 3)] image = self.viewer_state.layers[0].get_sliced_data(view=view) assert_equal(image, self.array[::3, 2, 1::2, 1].transpose()) with pytest.raises(IncompatibleAttribute): self.viewer_state.layers[1].get_sliced_data(view=view) image = self.viewer_state.layers[2].get_sliced_data(view=view) print(image.shape) assert_equal(image, self.array[::3, 2, 1::2, 1].transpose()) image = self.viewer_state.layers[3].get_sliced_data(view=view) assert_equal(image, self.array[::3, 2, 1::2, 0].transpose()) image = self.viewer_state.layers[4].get_sliced_data(view=view) assert_equal(image, self.array[::3, 0, 1::2, 0].transpose()) def test_reproject(self): # Test a case where the data needs to actually be reprojected # As for the previous test, but this time with a view applied self.viewer_state.x_att = self.data1.pixel_component_ids[0] self.viewer_state.y_att = self.data1.pixel_component_ids[2] self.viewer_state.slices = (3, 2, 4, 1) view = [slice(1, None, 2), slice(None, None, 3)] actual = self.viewer_state.layers[5].get_sliced_data(view=view) # The data to be reprojected is 3-dimensional. The axes we have set # correspond to 1 (for x) and 0 (for y). The third dimension of the # data to be reprojected should be sliced. This is linked with the # second dimension of the original data, for which the slice index is # 2. Since the data to be reprojected has coordinates that are 2.5 times # those of the reference data, this means the slice index should be 0.8, # which rounded corresponds to 1. expected = self.array_nonaligned[:, :, 1] # Now in the frame of the reference data, the data to show are indices # [0, 3] along x and [1, 3, 5, 7] along y. Applying the transformation, # this gives values of [0, 1.2] and [0.4, 1.2, 2, 2.8] for x and y, # and rounded, this gives [0, 1] and [0, 1, 2, 3]. As a reminder, in the # data to reproject, dimension 0 is y and dimension 1 is x expected = expected[:4, :2] # Let's make sure this works! assert_equal(actual, expected) def test_too_many_dimensions(self): # If we change the reference data, then the first dataset won't be # visible anymore because it has too many dimensions self.viewer_state.reference_data = self.data4 with pytest.raises(IncompatibleAttribute): self.viewer_state.layers[0].get_sliced_data() self.viewer_state.reference_data = self.data6 with pytest.raises(IncompatibleAttribute): self.viewer_state.layers[0].get_sliced_data()
cc.name = 'cat_peak' column_name = 'cat_peak' nc = Component.autotyped(cc, units=uu) catalog.add_component(nc, column_name) # if column_name != 'parent' else '_flarent_' catalog.join_on_key(dendro, '_idx', dendro.pixel_component_ids[0]) dc = DataCollection(dendrogram) #dc = DataCollection([cube, dendrogram, catalog]) #dc.merge(cube,sncube) #sncube.join_on_key(dendro, 'structure', dendro.pixel_component_ids[0]) #dc.merge(catalog, dendro) # UNCOMMENT THIS LINE TO BREAK THE VIEWER dc.append(catalog) app = GlueApplication(dc) cube_viewer = app.new_data_viewer(ImageWidget) cube_viewer.add_data(sncube) # link positional information dc.add_link(LinkSame(sncube.id['structure'], catalog.id['_idx'])) #dc.add_link(LinkSame(image.id['World y: DEC--TAN'], catalog.id['DEJ2000'])) dc.add_link(LinkSame(cube.id['Galactic Longitude'], catalog.id['x_cen'])) dc.add_link(LinkSame(cube.id['Galactic Latitude'], catalog.id['y_cen'])) def ms_to_kms(x):