Skip to content

Commit 029302d

Browse files
author
Craig Jones
authored
Merge pull request #169 from astrofrog/moment-dataset
Make proper glue dataset to hold moment maps
2 parents 8f6e892 + dddb446 commit 029302d

File tree

7 files changed

+208
-86
lines changed

7 files changed

+208
-86
lines changed

cubeviz/image_viewer.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,8 @@ def _delete_contour(self):
326326

327327
def get_contour_array(self):
328328
if self.contour_component is None:
329-
arr = self.state.layers[0].get_sliced_data()
329+
layer_artist = self.first_visible_layer()
330+
arr = layer_artist.state.get_sliced_data()
330331
else:
331332
data = self.state.layers_data[0]
332333
arr = data[self.contour_component][self.slice_index]
@@ -342,18 +343,18 @@ def draw_contour(self, draw=True):
342343

343344
arr = self.get_contour_array()
344345

345-
vmax = arr.max()
346+
vmax = np.nanmax(arr)
346347
if settings.vmax is not None:
347348
vmax = settings.vmax
348349

349-
vmin = arr.min()
350+
vmin = np.nanmin(arr)
350351
if settings.vmin is not None:
351352
vmin = settings.vmin
352353

353354
if settings.spacing is None:
354355
spacing = 1
355356
if vmax != vmin:
356-
spacing = (vmax-vmin)/CONTOUR_DEFAULT_NUMBER_OF_LEVELSS
357+
spacing = (vmax - vmin)/CONTOUR_DEFAULT_NUMBER_OF_LEVELSS
357358
else:
358359
spacing = settings.spacing
359360

@@ -542,13 +543,14 @@ def synced(self, value):
542543
def slice_index(self):
543544
return self._slice_index
544545

545-
def update_component_unit_label(self, component_label):
546+
def update_component_unit_label(self, component_id):
546547
"""
547548
Update component's unit label.
548-
:param component_label: component id as a string
549+
:param component_id: component id
549550
"""
550-
data = self.state.layers_data[0]
551-
unit = str(data.get_component(component_label).units)
551+
552+
data = component_id.parent
553+
unit = str(data.get_component(component_id).units)
552554
if unit:
553555
self.component_unit_label = "{0}".format(unit)
554556
else:
@@ -681,9 +683,9 @@ def mouse_move(self, event):
681683

682684
# If viewer has a layer.
683685
if len(self.state.layers) > 0:
684-
# Get array arr that contains the image values
685-
# Default layer is layer at index 0.
686-
arr = self.state.layers[0].get_sliced_data()
686+
687+
arr = self.first_visible_layer().state.get_sliced_data()
688+
687689
if 0 <= y < arr.shape[0] and 0 <= x < arr.shape[1]:
688690
# if x and y are in bounds. Note: x and y are swapped in array.
689691
# get value and check if wcs is obtainable
@@ -702,7 +704,7 @@ def mouse_move(self, event):
702704
string = string + " " + self._coords_format_function(ra, dec)
703705
# Pixel Value:
704706
v = arr[y][x]
705-
string = "{0:1.4f} {1} ".format(v, self.component_unit_label) + string
707+
string = "{0:.3e} {1} ".format(v, self.component_unit_label) + string
706708
# Add a gap to string and add to viewer.
707709
string += " "
708710
self._dont_update_status = True
@@ -711,6 +713,20 @@ def mouse_move(self, event):
711713
self.coord_label.setText(string)
712714
return
713715

716+
def first_visible_layer(self):
717+
layers = self.visible_layers()
718+
if len(layers) == 0:
719+
raise Exception("Couldn't find any visible layers")
720+
else:
721+
return layers[0]
722+
723+
def visible_layers(self):
724+
layers = []
725+
for layer_artist in self.layers:
726+
if layer_artist.enabled and layer_artist.visible:
727+
layers.append(layer_artist)
728+
return layers
729+
714730
def mouse_exited(self, event):
715731
"""
716732
Event handler for matplotlib axes_leave_event.

cubeviz/layout.py

Lines changed: 98 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import os
22
from collections import OrderedDict
33

4-
import numpy as np
5-
64
from qtpy import QtWidgets, QtCore
75
from qtpy.QtWidgets import QMenu, QAction, QInputDialog
86

@@ -28,6 +26,7 @@
2826
from .tools import collapse_cube
2927
from .tools.spectral_operations import SpectralOperationHandler
3028

29+
3130
class WidgetWrapper(QtWidgets.QWidget):
3231

3332
def __init__(self, widget=None, tab_widget=None, parent=None):
@@ -137,9 +136,6 @@ def __init__(self, session=None, parent=None):
137136
# Add menu buttons to the cubeviz toolbar.
138137
self._init_menu_buttons()
139138

140-
# This maps the combo box indicies to the glue data component labels
141-
self._component_labels = []
142-
143139
self.sync = {}
144140
# Track the slice index of the synced viewers. This is updated by the
145141
# slice controller
@@ -268,9 +264,13 @@ def _open_dialog(self, name, widget):
268264
if ok_pressed:
269265
self._units_controller.on_combobox_change(wavelength)
270266

267+
@property
268+
def data_components(self):
269+
return self._data.main_components + self._data.derived_components
270+
271271
@property
272272
def component_labels(self):
273-
return self._component_labels
273+
return [str(cid) for cid in self.data_components]
274274

275275
def refresh_viewer_combo_helpers(self):
276276
for i, helper in enumerate(self._viewer_combo_helpers):
@@ -288,48 +288,85 @@ def apply_to_cube(self, stack):
288288
parent=self)
289289
operation_handler.exec_()
290290

291-
def add_new_data_component(self, name):
292-
self._component_labels.append(str(name))
291+
def add_new_data_component(self, component_id):
293292

294293
self.refresh_viewer_combo_helpers()
295294

296295
if self._active_view in self.all_views:
297296
view_index = self.all_views.index(self._active_view)
298-
component_index = self._component_labels.index(str(name))
299-
self.change_viewer_component(view_index, component_index)
297+
self.change_viewer_component(view_index, component_id)
300298

301-
def remove_component(self, name):
302-
if str(name) not in self._component_labels:
303-
return
304-
self._component_labels.remove(str(name))
299+
def remove_data_component(self, component_id):
300+
pass
305301

306302
def _enable_option_buttons(self):
307303
for button in self._option_buttons:
308304
button.setEnabled(True)
309305
self.ui.sync_button.setEnabled(True)
310306

311-
def _get_change_viewer_func(self, view_index):
312-
def change_viewer(dropdown_index):
313-
view = self.all_views[view_index].widget()
314-
label = self._component_labels[dropdown_index]
315-
if view.is_smoothing_preview_active:
316-
view.end_smoothing_preview()
317-
view.update_component_unit_label(label)
318-
view.update_axes_title(title=str(label))
319-
view.state.layers[0]._update_attribute()
320-
view.state.layers[0].attribute = self._data.id[label]
321-
if view.is_contour_active:
322-
view.draw_contour()
323-
324-
return change_viewer
307+
def _get_change_viewer_combo_func(self, combo, view_index):
308+
309+
def _on_viewer_combo_change(dropdown_index):
310+
311+
# This function gets called whenever one of the viewer combos gets
312+
# changed. The active combo is the one that comes from the parent
313+
# _get_change_viewer_combo_func function.
314+
315+
# Find the relevant viewer
316+
viewer = self.all_views[view_index].widget()
317+
318+
# Get the label of the component and the component ID itself
319+
label = combo.currentText()
320+
component = combo.currentData()
321+
322+
# If the user changed the current component, stop previewing
323+
# smoothing.
324+
if viewer.is_smoothing_preview_active:
325+
viewer.end_smoothing_preview()
326+
327+
# Change the title and unit shown in the viwer
328+
viewer.update_component_unit_label(component)
329+
viewer.update_axes_title(title=str(label))
330+
331+
# Change the viewer's reference data to be the data containing the
332+
# current component.
333+
viewer.state.reference_data = component.parent
334+
335+
# The viewer may have multiple layers, for instance layers for
336+
# the main cube and for any overlay datasets, as well as subset
337+
# layers. We go through all the layers and make sure that for the
338+
# layer which corresponds to the current dataset, the correct
339+
# attribute is shown.
340+
for layer_artist in viewer.layers:
341+
layer_state = layer_artist.state
342+
if layer_state.layer is component.parent:
343+
344+
# We call _update_attribute here manually so that if this
345+
# function gets called before _update_attribute, it gets
346+
# called before we try and set the attribute below
347+
# (_update_attribute basically updates the internal list
348+
# of available attributes for the attribute combo)
349+
layer_state._update_attribute()
350+
layer_state.attribute = component
351+
352+
# We then also make sure that this layer artist is the
353+
# one that is selected so that if the user uses e.g. the
354+
# contrast tool, it will change the right layer
355+
viewer._view.layer_list.select_artist(layer_artist)
356+
357+
# If contours are being currently shown, we need to force a redraw
358+
if viewer.is_contour_active:
359+
viewer.draw_contour()
360+
361+
return _on_viewer_combo_change
325362

326363
def _enable_viewer_combo(self, data, index, combo_label, selection_label):
327364
combo = getattr(self.ui, combo_label)
328365
connect_combo_selection(self, selection_label, combo)
329366
helper = ComponentIDComboHelper(self, selection_label)
330367
helper.set_multiple_data([data])
331368
combo.setEnabled(True)
332-
combo.currentIndexChanged.connect(self._get_change_viewer_func(index))
369+
combo.currentIndexChanged.connect(self._get_change_viewer_combo_func(combo, index))
333370
self._viewer_combo_helpers.append(helper)
334371

335372
def _enable_all_viewer_combos(self, data):
@@ -344,39 +381,47 @@ def _enable_all_viewer_combos(self, data):
344381
self._enable_viewer_combo(
345382
data, 0, 'single_viewer_combo', 'single_viewer_attribute')
346383
view = self.all_views[0].widget()
347-
component_label = str(getattr(self, 'single_viewer_attribute'))
348-
view.update_component_unit_label(component_label)
349-
view.update_axes_title(component_label)
384+
component = getattr(self, 'single_viewer_attribute')
385+
view.update_component_unit_label(component)
386+
view.update_axes_title(component.label)
350387

351388
for i in range(1,4):
352389
combo_label = 'viewer{0}_combo'.format(i)
353390
selection_label = 'viewer{0}_attribute'.format(i)
354391
self._enable_viewer_combo(data, i, combo_label, selection_label)
355392
view = self.all_views[i].widget()
356-
component_label = str(getattr(self, selection_label))
357-
view.update_component_unit_label(component_label)
358-
view.update_axes_title(component_label)
393+
component = getattr(self, selection_label)
394+
view.update_component_unit_label(component)
395+
view.update_axes_title(component.label)
359396

360-
def change_viewer_component(self, view_index,
361-
component_index,
362-
force=False):
397+
def change_viewer_component(self, view_index, component_id, force=False):
363398
"""
364399
Given a viewer at an index view_index, change combo
365400
selection to component at an index component_index.
366401
:param view_index: int: Viewer index
367-
:param component_index: int: Component index in viewer combo
402+
:param component_id: ComponentID: Component ID in viewer combo
368403
:param force: bool: force change if component is already displayed.
369404
"""
370-
if view_index == 0:
371-
combo_label = 'single_viewer_combo'
372-
else:
373-
combo_label = 'viewer{0}_combo'.format(view_index)
374-
combo = getattr(self.ui, combo_label)
405+
406+
combo = self.get_viewer_combo(view_index)
407+
408+
component_index = combo.findData(component_id)
409+
375410
if combo.currentIndex() == component_index and force:
376411
combo.currentIndexChanged.emit(component_index)
377412
else:
378413
combo.setCurrentIndex(component_index)
379414

415+
def get_viewer_combo(self, view_index):
416+
"""
417+
Get viewer combo for a given viewer index
418+
"""
419+
if view_index == 0:
420+
combo_label = 'single_viewer_combo'
421+
else:
422+
combo_label = 'viewer{0}_combo'.format(view_index)
423+
return getattr(self.ui, combo_label)
424+
380425
def add_overlay(self, data, label):
381426
self._overlay_controller.add_overlay(data, label)
382427

@@ -401,9 +446,6 @@ def add_data(self, data):
401446
self._last_active_view = self.single_view
402447
self._active_split_cube = self.left_view
403448

404-
# Set the component labels to what was actually in the file.
405-
self._component_labels = [str(x).strip() for x in data.component_ids() if not x in data.coordinate_components]
406-
407449
# Store pointer to wavelength information
408450
self._wavelengths = self.single_view._widget._data[0].coords.world_axis(self.single_view._widget._data[0], axis=0)
409451

@@ -545,20 +587,25 @@ def start_smoothing_preview(self, preview_function, component_id, preview_title=
545587
:param preview_title: str: Title displayed when previewing
546588
"""
547589
# For single and first viewer:
590+
self._original_components = {}
548591
for view_index in [0, 1]:
592+
combo = self.get_viewer_combo(view_index)
593+
self._original_components[view_index] = combo.currentData()
549594
view = self.all_views[view_index].widget()
550-
component_index = self._component_labels.index(component_id)
551-
self.change_viewer_component(view_index, component_index, force=True)
595+
self.change_viewer_component(view_index, component_id, force=True)
552596
view.set_smoothing_preview(preview_function, preview_title)
553597

554598
def end_smoothing_preview(self):
555599
"""
556600
End preview and change viewer combo index to the first component.
557601
"""
558-
for view_index in [0,1]:
602+
for view_index in [0, 1]:
559603
view = self.all_views[view_index].widget()
560604
view.end_smoothing_preview()
561-
self.change_viewer_component(view_index, 0, force=True)
605+
if view_index in self._original_components:
606+
component_id = self._original_components[view_index]
607+
self.change_viewer_component(view_index, component_id, force=True)
608+
self._original_components = {}
562609

563610
def showEvent(self, event):
564611
super(CubeVizLayout, self).showEvent(event)

cubeviz/listener.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def handle_new_component(self, message):
5757
self._layout.add_new_data_component(message.component_id)
5858

5959
def handle_remove_component(self, message):
60-
self._layout.remove_component(message.component_id)
60+
self._layout.remove_data_component(message.component_id)
6161

6262
def handle_settings_change(self, message):
6363
if self._layout is not None:

0 commit comments

Comments
 (0)