コード例 #1
0
ファイル: subset_facet.py プロジェクト: nQuant/glue
class SubsetFacetState(State):

    log = CallbackProperty(False)
    v_min = CallbackProperty(0.)
    v_max = CallbackProperty(1.)
    steps = CallbackProperty(5)
    data = SelectionCallbackProperty()
    att = SelectionCallbackProperty()
    cmap = CallbackProperty()

    def __init__(self, data_collection):

        super(SubsetFacetState, self).__init__()

        self.data_helper = DataCollectionComboHelper(self, 'data',
                                                     data_collection)
        self.att_helper = ComponentIDComboHelper(self, 'att')
        self.lim_helper = StateAttributeLimitsHelper(self,
                                                     attribute='att',
                                                     lower='v_min',
                                                     upper='v_max',
                                                     log='log')

        self.add_callback('data', self._on_data_change)
        self._on_data_change()

    def _on_data_change(self, *args, **kwargs):
        self.att_helper.set_multiple_data(
            [] if self.data is None else [self.data])
コード例 #2
0
ファイル: save_data.py プロジェクト: harshalkokate/glue
class SaveDataState(State):

    data = SelectionCallbackProperty()
    component = SelectionCallbackProperty()
    exporter = SelectionCallbackProperty()

    def __init__(self, data_collection=None):

        super(SaveDataState, self).__init__()

        self.data_helper = DataCollectionComboHelper(self, 'data', data_collection)
        self.component_helper = ComponentIDComboHelper(self, 'component',
                                                       data_collection=data_collection)

        self.add_callback('data', self._on_data_change)
        self._on_data_change()

        self._sync_data_exporters()

    def _sync_data_exporters(self):

        exporters = list(config.data_exporter)

        def display_func(exporter):
            if exporter.extension == '':
                return "{0} (*)".format(exporter.label)
            else:
                return "{0} ({1})".format(exporter.label, ' '.join('*.' + ext for ext in exporter.extension))

        SaveDataState.exporter.set_choices(self, exporters)
        SaveDataState.exporter.set_display_func(self, display_func)

    def _on_data_change(self, event=None):
        self.component_helper.set_multiple_data([self.data])
コード例 #3
0
class SpecvizLayerState(LayerState):
    """

    """
    color = CallbackProperty(docstring='The color used to display the data')
    alpha = CallbackProperty(docstring='The transparency used to display the data')
    linewidth = CallbackProperty(1, docstring='The width of the line for the data')

    attribute = SelectionCallbackProperty(docstring='The attribute to use for the spectrum')
    statistic = SelectionCallbackProperty(docstring='The statistic to use to collapse data')

    def __init__(self, viewer_state=None, **kwargs):

        super(SpecvizLayerState, self).__init__(viewer_state=viewer_state, **kwargs)

        self.color = self.layer.style.color
        self.alpha = self.layer.style.alpha

        self._sync_color = keep_in_sync(self, 'color', self.layer.style, 'color')
        self._sync_alpha = keep_in_sync(self, 'alpha', self.layer.style, 'alpha')

        self._att_helper = ComponentIDComboHelper(self, 'attribute')
        self.add_callback('layer', self._on_layer_change)
        self._on_layer_change()

        SpecvizLayerState.statistic.set_choices(self, list(FUNCTIONS))
        SpecvizLayerState.statistic.set_display_func(self, FUNCTIONS.get)

    def _on_layer_change(self, *args):
        if self.layer is None:
            self._att_helper.set_multiple_data([])
        else:
            self._att_helper.set_multiple_data([self.layer])
コード例 #4
0
ファイル: viewer.py プロジェクト: nmearl/specviz
class SpecvizLayerState(LayerState):
    """

    """
    color = CallbackProperty(docstring='The color used to display the data')
    alpha = CallbackProperty(docstring='The transparency used to display the data')
    linewidth = CallbackProperty(1, docstring='The width of the line for the data')

    attribute = SelectionCallbackProperty(docstring='The attribute to use for the spectrum')
    statistic = SelectionCallbackProperty(docstring='The statistic to use to collapse data')

    def __init__(self, viewer_state=None, **kwargs):

        super(SpecvizLayerState, self).__init__(viewer_state=viewer_state, **kwargs)

        self.color = self.layer.style.color
        self.alpha = self.layer.style.alpha

        self._sync_color = keep_in_sync(self, 'color', self.layer.style, 'color')
        self._sync_alpha = keep_in_sync(self, 'alpha', self.layer.style, 'alpha')

        self._att_helper = ComponentIDComboHelper(self, 'attribute')
        self.add_callback('layer', self._on_layer_change)
        self._on_layer_change()

        SpecvizLayerState.statistic.set_choices(self, list(FUNCTIONS))
        SpecvizLayerState.statistic.set_display_func(self, FUNCTIONS.get)

    def _on_layer_change(self, *args):
        if self.layer is None:
            self._att_helper.set_multiple_data([])
        else:
            self._att_helper.set_multiple_data([self.layer])
コード例 #5
0
ファイル: layout.py プロジェクト: rosteen/cubeviz
 def _enable_viewer_combo(self, viewer, data, index, selection_label):
     connect_combo_selection(self, selection_label, viewer.combo)
     helper = ComponentIDComboHelper(self, selection_label)
     helper.set_multiple_data([data])
     viewer.combo.setEnabled(True)
     viewer.combo.currentIndexChanged.connect(
         self._get_change_viewer_combo_func(viewer.combo, index))
     self._viewer_combo_helpers.append(helper)
コード例 #6
0
ファイル: layout.py プロジェクト: spacetelescope/cube-tools
 def _enable_viewer_combo(self, viewer, data, index, selection_label):
     connect_combo_selection(self, selection_label, viewer.combo)
     helper = ComponentIDComboHelper(self, selection_label)
     helper.set_multiple_data([data])
     viewer.combo.setEnabled(True)
     viewer.combo.currentIndexChanged.connect(
         self._get_change_viewer_combo_func(viewer.combo, index))
     self._viewer_combo_helpers.append(helper)
コード例 #7
0
ファイル: save_data.py プロジェクト: glue-viz/glue
class SaveDataState(State):

    data = SelectionCallbackProperty()
    subset = SelectionCallbackProperty()
    component = SelectionCallbackProperty()
    exporter = SelectionCallbackProperty()

    def __init__(self, data_collection=None):

        super(SaveDataState, self).__init__()

        self.data_helper = DataCollectionComboHelper(self, 'data', data_collection)
        self.component_helper = ComponentIDComboHelper(self, 'component',
                                                       data_collection=data_collection)

        self.add_callback('data', self._on_data_change)
        self._on_data_change()

        self._sync_data_exporters()

    def _sync_data_exporters(self):

        exporters = list(config.data_exporter)

        def display_func(exporter):
            if exporter.extension == '':
                return "{0} (*)".format(exporter.label)
            else:
                return "{0} ({1})".format(exporter.label, ' '.join('*.' + ext for ext in exporter.extension))

        SaveDataState.exporter.set_choices(self, exporters)
        SaveDataState.exporter.set_display_func(self, display_func)

    def _on_data_change(self, event=None):
        self.component_helper.set_multiple_data([self.data])
        self._sync_subsets()

    def _sync_subsets(self):

        def display_func(subset):
            if subset is None:
                return "All data (no subsets applied)"
            else:
                return subset.label

        subsets = [None] + list(self.data.subsets)

        SaveDataState.subset.set_choices(self, subsets)
        SaveDataState.subset.set_display_func(self, display_func)
コード例 #8
0
class VolumeLayerState(VispyLayerState):
    """
    A state object for volume layers
    """

    attribute = SelectionCallbackProperty()
    vmin = CallbackProperty()
    vmax = CallbackProperty()
    subset_mode = CallbackProperty('data')
    limits_cache = CallbackProperty({})

    def __init__(self, layer=None, **kwargs):

        super(VolumeLayerState, self).__init__(layer=layer)

        if self.layer is not None:

            self.color = self.layer.style.color
            self.alpha = self.layer.style.alpha

        self.att_helper = ComponentIDComboHelper(self, 'attribute')

        self.lim_helper = StateAttributeLimitsHelper(self,
                                                     attribute='attribute',
                                                     lower='vmin',
                                                     upper='vmax',
                                                     cache=self.limits_cache)

        self.add_callback('layer', self._on_layer_change)
        if layer is not None:
            self._on_layer_change()

        if isinstance(self.layer, Subset):
            self.vmin = 0
            self.lim_helper.lower_frozen = True

        self.update_from_dict(kwargs)

    def _on_layer_change(self, layer=None):

        with delay_callback(self, 'vmin', 'vmin'):

            if self.layer is None:
                self.att_helper.set_multiple_data([])
            else:
                self.att_helper.set_multiple_data([self.layer])

    def update_priority(self, name):
        return 0 if name.endswith(('vmin', 'vmax')) else 1
コード例 #9
0
class Scatter3dLayerState(ScatterLayerState):
    vz_att = DDSCProperty(docstring="The attribute to use for the z vector arrow")

    def __init__(self, viewer_state=None, layer=None, **kwargs):
        self.vz_att_helper = ComponentIDComboHelper(self, 'vz_att',
                                                    numeric=True, categorical=False)
        super(Scatter3dLayerState, self).__init__(viewer_state=viewer_state, layer=layer)
        # self.update_from_dict(kwargs)

    def _on_layer_change(self, layer=None):
        super(Scatter3dLayerState, self)._on_layer_change(layer=layer)
        if self.layer is None:
            self.vz_att_helper.set_multiple_data([])
        else:
            self.vz_att_helper.set_multiple_data([self.layer])
コード例 #10
0
ファイル: config.py プロジェクト: sunn-e/glue
class TutorialViewerState(ViewerState):

    x_att = SelectionCallbackProperty(docstring='The attribute to use on the x-axis')
    y_att = SelectionCallbackProperty(docstring='The attribute to use on the y-axis')

    def __init__(self, *args, **kwargs):
        super(TutorialViewerState, self).__init__(*args, **kwargs)
        self._x_att_helper = ComponentIDComboHelper(self, 'x_att')
        self._y_att_helper = ComponentIDComboHelper(self, 'y_att')
        self.add_callback('layers', self._on_layers_change)

    def _on_layers_change(self, value):
        # self.layers_data is a shortcut for
        # [layer_state.layer for layer_state in self.layers]
        self._x_att_helper.set_multiple_data(self.layers_data)
        self._y_att_helper.set_multiple_data(self.layers_data)
コード例 #11
0
ファイル: layer_state.py プロジェクト: PennyQ/glue-3d-viewer
class VolumeLayerState(VispyLayerState):
    """
    A state object for volume layers
    """

    attribute = SelectionCallbackProperty()
    vmin = CallbackProperty()
    vmax = CallbackProperty()
    subset_mode = CallbackProperty('data')
    limits_cache = CallbackProperty({})

    def __init__(self, layer=None, **kwargs):

        super(VolumeLayerState, self).__init__(layer=layer)

        if self.layer is not None:

            self.color = self.layer.style.color
            self.alpha = self.layer.style.alpha

        self.att_helper = ComponentIDComboHelper(self, 'attribute')

        self.lim_helper = StateAttributeLimitsHelper(self, attribute='attribute',
                                                     lower='vmin', upper='vmax',
                                                     cache=self.limits_cache)

        self.add_callback('layer', self._on_layer_change)
        if layer is not None:
            self._on_layer_change()

        if isinstance(self.layer, Subset):
            self.vmin = 0
            self.lim_helper.lower_frozen = True

        self.update_from_dict(kwargs)

    def _on_layer_change(self, layer=None):

        with delay_callback(self, 'vmin', 'vmin'):

            if self.layer is None:
                self.att_helper.set_multiple_data([])
            else:
                self.att_helper.set_multiple_data([self.layer])

    def update_priority(self, name):
        return 0 if name.endswith(('vmin', 'vmax')) else 1
コード例 #12
0
class Scatter3DLayerState(ScatterLayerState):

    # FIXME: the following should be a SelectionCallbackProperty
    geo = CallbackProperty('sphere', docstring="Type of marker")
    vz_att = SelectionCallbackProperty(docstring="The attribute to use for the z vector arrow")

    def __init__(self, viewer_state=None, layer=None, **kwargs):
        self.vz_att_helper = ComponentIDComboHelper(self, 'vz_att',
                                                    numeric=True, categorical=False)
        super(Scatter3DLayerState, self).__init__(viewer_state=viewer_state, layer=layer)
        # self.update_from_dict(kwargs)

    def _on_layer_change(self, layer=None):
        super(Scatter3DLayerState, self)._on_layer_change(layer=layer)
        if self.layer is None:
            self.vz_att_helper.set_multiple_data([])
        else:
            self.vz_att_helper.set_multiple_data([self.layer])
コード例 #13
0
class IsosurfaceLayerState(VispyLayerState):
    """
    A state object for volume layers
    """

    attribute = SelectionCallbackProperty()

    level_low = CallbackProperty()
    level_high = CallbackProperty()
    cmap = CallbackProperty()
    step = CallbackProperty(4)

    level_cache = CallbackProperty({})

    def __init__(self, layer=None, **kwargs):

        super(IsosurfaceLayerState, self).__init__(layer=layer)

        self.att_helper = ComponentIDComboHelper(self, 'attribute')

        self.lim_helper = StateAttributeLimitsHelper(self,
                                                     attribute='attribute',
                                                     lower='level_low',
                                                     upper='level_high')

        self.add_callback('layer', self._on_layer_change)
        if layer is not None:
            self._on_layer_change()

        self.cmap = colormaps.members[0][1]

        self.update_from_dict(kwargs)

    def _on_layer_change(self, layer=None):

        with delay_callback(self, 'level_low', 'level_high'):

            if self.layer is None:
                self.att_helper.set_multiple_data([])
            else:
                self.att_helper.set_multiple_data([self.layer])

    def update_priority(self, name):
        return 0 if name == 'level' else 1
コード例 #14
0
ファイル: image_layer.py プロジェクト: glue-viz/glue-wwt
class WWTImageLayerState(LayerState):
    """A state object for WWT image layers

    """
    layer = CallbackProperty()
    color = CallbackProperty()
    alpha = CallbackProperty()
    vmin = CallbackProperty()
    vmax = CallbackProperty()

    img_data_att = SelectionCallbackProperty(default_index=0)
    stretch = SelectionCallbackProperty(default_index=0,
                                        choices=VALID_STRETCHES)

    def __init__(self, layer=None, **kwargs):
        super(WWTImageLayerState, self).__init__(layer=layer)

        self._sync_color = keep_in_sync(self, 'color', self.layer.style,
                                        'color')
        self._sync_alpha = keep_in_sync(self, 'alpha', self.layer.style,
                                        'alpha')

        self.color = self.layer.style.color

        self.img_data_att_helper = ComponentIDComboHelper(self,
                                                          'img_data_att',
                                                          numeric=True,
                                                          categorical=False)

        self.add_callback('layer', self._on_layer_change)
        if layer is not None:
            self._on_layer_change()

        self.update_from_dict(kwargs)

    def _on_layer_change(self, layer=None):
        if self.layer is None:
            self.img_data_att_helper.set_multiple_data([])
        else:
            self.img_data_att_helper.set_multiple_data([self.layer])

    def update_priority(self, name):
        return 0 if name.endswith(('vmin', 'vmax')) else 1
コード例 #15
0
class OptionsWidget(QWidget):

    file_att = SelectionCallbackProperty()

    def __init__(self, parent=None, data_viewer=None):

        super(OptionsWidget, self).__init__(parent=parent)

        self.ui = load_ui('viewer_options.ui',
                          self,
                          directory=os.path.dirname(__file__))

        self.file_helper = ComponentIDComboHelper(
            self, 'file_att', data_collection=data_viewer._data)

        connect_combo_selection(self, 'file_att', self.ui.combo_file_attribute)

    def set_data(self, data):
        self.file_helper.set_multiple_data([data])
コード例 #16
0
ファイル: config.py プロジェクト: hopehhchen/glue_tree
class TutorialLayerState(MatplotlibLayerState):

    # cmap is stuff used for colormap

    linewidth = CallbackProperty(1, docstring='line width')
    cmap_mode = DDSCProperty(
        docstring="Whether to use color to encode an attribute")
    cmap_att = DDSCProperty(docstring="The attribute to use for the color")
    cmap_vmin = DDCProperty(docstring="The lower level for the colormap")
    cmap_vmax = DDCProperty(docstring="The upper level for the colormap")
    cmap = DDCProperty(docstring="The colormap to use (when in colormap mode)")

    def __init__(self, viewer_state=None, layer=None, **kwargs):
        super(TutorialLayerState, self).__init__(viewer_state=viewer_state,
                                                 layer=layer)

        # set choices basically poplutes drop down menus

        TutorialLayerState.cmap_mode.set_choices(self, ['Fixed', 'Linear'])

        self.cmap_att_helper = ComponentIDComboHelper(self,
                                                      'cmap_att',
                                                      numeric=True,
                                                      categorical=False)
        self.add_callback('layer', self._on_layers_change)

        # kind of initializing. not having this line
        # made errors for cmap initialization- didn't pull
        # up linear part
        # thanks tom
        self._on_layers_change()

    def _on_layers_change(self, layer=None):

        # not exactly sure of this
        with delay_callback(self, 'cmap_vmin', 'cmap_vmax'):

            self.cmap_att_helper.set_multiple_data([self.layer])
            # not having this line threw None resulting in an error- can't
            # iterate over None....
            # this initializes some colormap
            # thanks tom
            self.cmap = colormaps.members[0][1]
コード例 #17
0
ファイル: config.py プロジェクト: hopehhchen/glue_tree
class TutorialViewerState(MatplotlibDataViewerState):
    # x is parent; y is height.
    x_att = SelectionCallbackProperty(
        docstring='The attribute to use on the x-axis')
    y_att = SelectionCallbackProperty(
        docstring='The attribute to use on the y-axis')
    # change to parent and height
    # Tom is awesome!
    orientation = SelectionCallbackProperty(docstring='The orientation ....')
    sort_by = SelectionCallbackProperty(docstring='Sort by option ....')
    select_substruct = DDCProperty(True)

    def __init__(self, *args, **kwargs):
        # provides dropdown, parent, height etc. for plot options
        super(TutorialViewerState, self).__init__(*args, **kwargs)
        self._x_att_helper = ComponentIDComboHelper(self, 'x_att')
        self._y_att_helper = ComponentIDComboHelper(self, 'y_att')
        self.add_callback('layers', self._on_layers_change)
        self.add_callback('x_att', self._on_attribute_change)
        self.add_callback('y_att', self._on_attribute_change)
        TutorialViewerState.orientation.set_choices(
            self, ['bottom-up', 'left-right', 'top-down', 'right-left'])
        self.add_callback('orientation', self._on_attribute_change)
        TutorialViewerState.sort_by.set_choices(self, ['parent', 'height'])
        self.add_callback('sort_by', self._on_attribute_change)

    def _on_layers_change(self, value):
        # populates attributes
        self._x_att_helper.set_multiple_data(self.layers_data)
        self._y_att_helper.set_multiple_data(self.layers_data)

    def _on_attribute_change(self, value):
        if self.y_att is not None:
            # used for labels and axes depedning on orientation

            if (self.orientation == 'bottom-up') or (self.orientation
                                                     == 'top-down'):
                self.x_axislabel = ''
                self.y_axislabel = self.y_att.label
            elif (self.orientation == 'left-right') or (self.orientation
                                                        == 'right-left'):
                self.x_axislabel = self.y_att.label
                self.y_axislabel = ''
コード例 #18
0
class OpenSpaceViewerState(ViewerState):

    mode = SelectionCallbackProperty(default_index=0)
    frame = SelectionCallbackProperty(default_index=0)

    lon_att = SelectionCallbackProperty(default_index=0)
    lat_att = SelectionCallbackProperty(default_index=1)
    alt_att = SelectionCallbackProperty(default_index=2)
    alt_unit = SelectionCallbackProperty(default_index=4)
    alt_type = SelectionCallbackProperty(default_index=0)

    layers = ListCallbackProperty()

    def __init__(self, **kwargs):

        super(OpenSpaceViewerState, self).__init__()

        OpenSpaceViewerState.mode.set_choices(self, MODES)
        OpenSpaceViewerState.frame.set_choices(self, CELESTIAL_FRAMES)
        OpenSpaceViewerState.alt_unit.set_choices(self,
                                                  [str(x) for x in ALT_UNITS])
        OpenSpaceViewerState.alt_type.set_choices(self, ALT_TYPES)

        self.lon_att_helper = ComponentIDComboHelper(self,
                                                     'lon_att',
                                                     numeric=True,
                                                     categorical=False,
                                                     world_coord=True,
                                                     pixel_coord=False)

        self.lat_att_helper = ComponentIDComboHelper(self,
                                                     'lat_att',
                                                     numeric=True,
                                                     categorical=False,
                                                     world_coord=True,
                                                     pixel_coord=False)

        self.alt_att_helper = ComponentIDComboHelper(self,
                                                     'alt_att',
                                                     numeric=True,
                                                     categorical=False,
                                                     world_coord=True,
                                                     pixel_coord=False)

        self.add_callback('layers', self._on_layers_changed)
        self._on_layers_changed()

        self.update_from_dict(kwargs)

    def _on_layers_changed(self, *args):
        self.lon_att_helper.set_multiple_data(self.layers_data)
        self.lat_att_helper.set_multiple_data(self.layers_data)
        self.alt_att_helper.set_multiple_data(self.layers_data)

    def _update_priority(self, name):
        if name == 'layers':
            return 2
        else:
            return 0
コード例 #19
0
class TutorialViewerState(MatplotlibDataViewerState):

    x_att = SelectionCallbackProperty(
        docstring='The attribute to use on the x-axis')
    y_att = SelectionCallbackProperty(
        docstring='The attribute to use on the y-axis')

    def __init__(self, *args, **kwargs):
        super(TutorialViewerState, self).__init__(*args, **kwargs)
        self._x_att_helper = ComponentIDComboHelper(self, 'x_att')
        self._y_att_helper = ComponentIDComboHelper(self, 'y_att')
        self.add_callback('layers', self._on_layers_change)
        self.add_callback('x_att', self._on_attribute_change)
        self.add_callback('y_att', self._on_attribute_change)

    def _on_layers_change(self, value):
        self._x_att_helper.set_multiple_data(self.layers_data)
        self._y_att_helper.set_multiple_data(self.layers_data)

    def _on_attribute_change(self, value):
        if self.x_att is not None:
            self.x_axislabel = self.x_att.label
        if self.y_att is not None:
            self.y_axislabel = self.y_att.label
コード例 #20
0
ファイル: config_messy.py プロジェクト: hopehhchen/glue_tree
class TutorialViewerState(MatplotlibDataViewerState):

    x_att = SelectionCallbackProperty(
        docstring='The attribute to use on the x-axis')
    y_att = SelectionCallbackProperty(
        docstring='The attribute to use on the y-axis')
    # change to parent and height
    # Tom is awesome!
    orientation = SelectionCallbackProperty(docstring='The orientation ....')

    def __init__(self, *args, **kwargs):
        super(TutorialViewerState, self).__init__(*args, **kwargs)
        self._x_att_helper = ComponentIDComboHelper(self, 'x_att')
        self._y_att_helper = ComponentIDComboHelper(self, 'y_att')
        self.add_callback('layers', self._on_layers_change)
        self.add_callback('x_att', self._on_attribute_change)
        self.add_callback('y_att', self._on_attribute_change)
        TutorialViewerState.orientation.set_choices(
            self, ['bottom-up', 'left-right', 'top-down', 'right-left'])
        self.add_callback('orientation', self._on_attribute_change)

    def _on_layers_change(self, value):
        self._x_att_helper.set_multiple_data(self.layers_data)
        self._y_att_helper.set_multiple_data(self.layers_data)

    def _on_attribute_change(self, value):
        if self.y_att is not None:

            if (self.orientation == 'bottom-up') or (self.orientation
                                                     == 'top-down'):
                self.x_axislabel = ''
                self.y_axislabel = self.y_att.label
            elif (self.orientation == 'left-right') or (self.orientation
                                                        == 'right-left'):
                self.x_axislabel = self.y_att.label
                self.y_axislabel = ''
コード例 #21
0
ファイル: viewer_state.py プロジェクト: PennyQ/glue-3d-viewer
class Vispy3DScatterViewerState(Vispy3DViewerState):

    def __init__(self, **kwargs):

        super(Vispy3DScatterViewerState, self).__init__()

        self.x_att_helper = ComponentIDComboHelper(self, 'x_att', categorical=False)
        self.y_att_helper = ComponentIDComboHelper(self, 'y_att', categorical=False)
        self.z_att_helper = ComponentIDComboHelper(self, 'z_att', categorical=False)

        self.add_callback('layers', self._on_layers_change)

        self.update_from_dict(kwargs)

    def _on_layers_change(self, *args):
        layers_data = [layer_state.layer for layer_state in self.layers]
        self.x_att_helper.set_multiple_data(layers_data)
        self.y_att_helper.set_multiple_data(layers_data)
        self.z_att_helper.set_multiple_data(layers_data)
コード例 #22
0
class Scatter3DViewerState(ViewerState3D):

    def __init__(self, **kwargs):

        super(Scatter3DViewerState, self).__init__()

        self.x_att_helper = ComponentIDComboHelper(self, 'x_att', categorical=True)
        self.y_att_helper = ComponentIDComboHelper(self, 'y_att', categorical=True)
        self.z_att_helper = ComponentIDComboHelper(self, 'z_att', categorical=True)

        self.add_callback('layers', self._on_layers_change)

        self.update_from_dict(kwargs)

    def _on_layers_change(self, *args):
        layers_data = [layer_state.layer for layer_state in self.layers]
        self.x_att_helper.set_multiple_data(layers_data)
        self.y_att_helper.set_multiple_data(layers_data)
        self.z_att_helper.set_multiple_data(layers_data)
コード例 #23
0
class LinkEditorState(State):

    data1 = SelectionCallbackProperty()
    data2 = SelectionCallbackProperty()
    att1 = SelectionCallbackProperty()
    att2 = SelectionCallbackProperty()
    current_link = SelectionCallbackProperty()
    link_type = SelectionCallbackProperty()
    restrict_to_suggested = CallbackProperty(False)

    def __init__(self, data_collection, suggested_links=None):

        super(LinkEditorState, self).__init__()

        # Find identity function
        for func in link_function:
            if func.function.__name__ == 'identity':
                self._identity = func
                break
        else:
            raise ValueError("Could not find identity link function")

        self.data1_helper = DataCollectionComboHelper(self, 'data1',
                                                      data_collection)
        self.data2_helper = DataCollectionComboHelper(self, 'data2',
                                                      data_collection)

        self.att1_helper = ComponentIDComboHelper(self,
                                                  'att1',
                                                  pixel_coord=True,
                                                  world_coord=True)
        self.att2_helper = ComponentIDComboHelper(self,
                                                  'att2',
                                                  pixel_coord=True,
                                                  world_coord=True)

        # FIXME: We unregister the combo helpers straight away to avoid issues with
        # leftover references once the dialog is closed. This shouldn't happen
        # ideally so in future we should investigate how to avoid it.
        self.data1_helper.unregister(data_collection.hub)
        self.data2_helper.unregister(data_collection.hub)

        self.data_collection = data_collection

        # Convert links to editable states
        links = [
            EditableLinkFunctionState(link)
            for link in data_collection.external_links
        ]

        # If supplied, also add suggested links and make sure we toggle the
        # suggestion flag on the link state so that we can handle suggestions
        # differently in the link viewer.
        if suggested_links is not None:
            for link in suggested_links:
                link_state = EditableLinkFunctionState(link)
                link_state.suggested = True
                links.append(link_state)

        self.links = links

        if len(data_collection) == 2:
            self.data1, self.data2 = self.data_collection
        else:
            self.data1 = self.data2 = None

        self._on_data_change()
        self._on_data1_change()
        self._on_data2_change()

        self.add_callback('data1', self._on_data1_change)
        self.add_callback('data2', self._on_data2_change)
        self.add_callback('restrict_to_suggested', self._on_data_change)

        LinkEditorState.current_link.set_display_func(self, self._display_link)

    @property
    def visible_links(self):

        if self.data1 is None or self.data2 is None:
            return []

        links = []
        for link in self.links:
            if link.suggested or not self.restrict_to_suggested:
                if ((link.data1 is self.data1 and link.data2 is self.data2) or
                    (link.data1 is self.data2 and link.data2 is self.data1)):
                    links.append(link)

        return links

    def flip_data(self, *args):
        # FIXME: since the links will be the same in the list of current links,
        # we can make sure we reselect the same one as before - it would be
        # better if this didn't change in the first place though.
        _original_current_link = self.current_link
        with delay_callback(self, 'data1', 'data2'):
            self.data1, self.data2 = self.data2, self.data1
        self.current_link = _original_current_link

    def _on_data1_change(self, *args):
        if self.data1 is self.data2 and self.data1 is not None:
            self.data2 = next(data for data in self.data_collection
                              if data is not self.data1)
        else:
            self._on_data_change()
        self.att1_helper.set_multiple_data(
            [] if self.data1 is None else [self.data1])

    def _on_data2_change(self, *args):
        if self.data2 is self.data1 and self.data2 is not None:
            self.data1 = next(data for data in self.data_collection
                              if data is not self.data2)
        else:
            self._on_data_change()
        self.att2_helper.set_multiple_data(
            [] if self.data2 is None else [self.data2])

    def _on_data_change(self, *args):

        links = self.visible_links
        with delay_callback(self, 'current_link'):
            LinkEditorState.current_link.set_choices(self, links)
            if len(links) > 0:
                self.current_link = links[0]

    def _display_link(self, link):
        if link.suggested:
            return str(link) + ' [Suggested]'
        else:
            return str(link)

    def simple_link(self, *args):
        self.new_link(self._identity)
        self.current_link.x = self.att1
        self.current_link.y = self.att2

    def new_link(self, function_or_helper):

        if hasattr(function_or_helper, 'function'):
            link = EditableLinkFunctionState(
                function_or_helper.function,
                data1=self.data1,
                data2=self.data2,
                names2=function_or_helper.output_labels,
                description=function_or_helper.info,
                display=function_or_helper.function.__name__)
        elif function_or_helper.helper.cid_independent:
            # This shortcut is needed for e.g. the WCS auto-linker, which has a dynamic
            # description but doesn't need to take any component IDs.
            link = EditableLinkFunctionState(
                function_or_helper.helper(data1=self.data1, data2=self.data2))
        else:
            link = EditableLinkFunctionState(function_or_helper.helper,
                                             data1=self.data1,
                                             data2=self.data2)

        self.links.append(link)
        with delay_callback(self, 'current_link'):
            self._on_data_change()
            self.current_link = link

    def remove_link(self):
        self.links.remove(self.current_link)
        self._on_data_change()

    def update_links_in_collection(self):
        links = [link_state.link for link_state in self.links]
        self.data_collection.set_links(links)
コード例 #24
0
ファイル: state.py プロジェクト: glue-viz/glue
class ProfileLayerState(MatplotlibLayerState):
    """
    A state class that includes all the attributes for layers in a Profile plot.
    """

    linewidth = DDCProperty(1, docstring='The width of the line')

    attribute = DDSCProperty(docstring='The attribute shown in the layer')
    v_min = DDCProperty(docstring='The lower level shown')
    v_max = DDCProperty(docstring='The upper level shown')
    percentile = DDSCProperty(docstring='The percentile value used to '
                                        'automatically calculate levels')

    _viewer_callbacks_set = False
    _profile_cache = None

    def __init__(self, layer=None, viewer_state=None, **kwargs):

        super(ProfileLayerState, self).__init__(layer=layer, viewer_state=viewer_state)

        self.attribute_att_helper = ComponentIDComboHelper(self, 'attribute',
                                                           numeric=True, categorical=False)

        percentile_display = {100: 'Min/Max',
                              99.5: '99.5%',
                              99: '99%',
                              95: '95%',
                              90: '90%',
                              'Custom': 'Custom'}

        ProfileLayerState.percentile.set_choices(self, [100, 99.5, 99, 95, 90, 'Custom'])
        ProfileLayerState.percentile.set_display_func(self, percentile_display.get)

        self.add_callback('layer', self._update_attribute, priority=1000)

        if layer is not None:
            self._update_attribute()

        self.update_from_dict(kwargs)

    def _update_attribute(self, *args):
        if self.layer is not None:
            self.attribute_att_helper.set_multiple_data([self.layer])

    @property
    def independent_x_att(self):
        return is_convertible_to_single_pixel_cid(self.layer, self.viewer_state.x_att) is not None

    def normalize_values(self, values):
        return (np.asarray(values) - self.v_min) / (self.v_max - self.v_min)

    def reset_cache(self, *args):
        self._profile_cache = None

    @property
    def viewer_state(self):
        return self._viewer_state

    @viewer_state.setter
    def viewer_state(self, viewer_state):
        self._viewer_state = viewer_state

    @property
    def profile(self):
        self.update_profile()
        return self._profile_cache

    def update_profile(self, update_limits=True):

        if self._profile_cache is not None:
            return self._profile_cache

        if not self._viewer_callbacks_set:
            self.viewer_state.add_callback('x_att', self.reset_cache, priority=100000)
            self.viewer_state.add_callback('function', self.reset_cache, priority=100000)
            if self.is_callback_property('attribute'):
                self.add_callback('attribute', self.reset_cache, priority=100000)
            self._viewer_callbacks_set = True

        if self.viewer_state is None or self.viewer_state.x_att is None or self.attribute is None:
            raise IncompatibleDataException()

        # Check what pixel axis in the current dataset x_att corresponds to
        pix_cid = is_convertible_to_single_pixel_cid(self.layer, self.viewer_state.x_att_pixel)

        if pix_cid is None:
            raise IncompatibleDataException()

        # If we get here, then x_att does correspond to a single pixel axis in
        # the cube, so we now prepare a list of axes to collapse over.
        axes = tuple(i for i in range(self.layer.ndim) if i != pix_cid.axis)

        # We now get the y values for the data

        # TODO: in future we should optimize the case where the mask is much
        # smaller than the data to just average the relevant 'spaxels' in the
        # data rather than collapsing the whole cube.

        if isinstance(self.layer, Subset):
            data = self.layer.data
            subset_state = self.layer.subset_state
        else:
            data = self.layer
            subset_state = None

        profile_values = data.compute_statistic(self.viewer_state.function, self.attribute, axis=axes, subset_state=subset_state)

        if np.all(np.isnan(profile_values)):
            self._profile_cache = [], []
        else:
            axis_view = [0] * data.ndim
            axis_view[pix_cid.axis] = slice(None)
            axis_values = data[self.viewer_state.x_att, tuple(axis_view)]
            self._profile_cache = axis_values, profile_values

        if update_limits:
            self.update_limits(update_profile=False)

    def update_limits(self, update_profile=True):
        with delay_callback(self, 'v_min', 'v_max'):
            if update_profile:
                self.update_profile(update_limits=False)
            if self._profile_cache is not None and len(self._profile_cache[1]) > 0:
                self.v_min = nanmin(self._profile_cache[1])
                self.v_max = nanmax(self._profile_cache[1])
コード例 #25
0
ファイル: state.py プロジェクト: stscieisenhamer/glue
class ImageViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for an image viewer.
    """

    x_att = DDCProperty(docstring='The component ID giving the pixel component '
                                  'shown on the x axis')
    y_att = DDCProperty(docstring='The component ID giving the pixel component '
                                  'shown on the y axis')
    x_att_world = DDSCProperty(docstring='The component ID giving the world component '
                                         'shown on the x axis', default_index=-1)
    y_att_world = DDSCProperty(docstring='The component ID giving the world component '
                                         'shown on the y axis', default_index=-2)
    aspect = DDCProperty('equal', docstring='Whether to enforce square pixels (``equal``) '
                                            'or fill the axes (``auto``)')
    reference_data = DDSCProperty(docstring='The dataset that is used to define the '
                                            'available pixel/world components, and '
                                            'which defines the coordinate frame in '
                                            'which the images are shown')
    slices = DDCProperty(docstring='The current slice along all dimensions')
    color_mode = DDCProperty('Colormaps', docstring='Whether each layer can have '
                                                    'its own colormap (``Colormaps``) or '
                                                    'whether each layer is assigned '
                                                    'a single color (``One color per layer``)')

    dpi = DDCProperty(72, docstring='The resolution (in dots per inch) of density maps, if present')

    def __init__(self, **kwargs):

        super(ImageViewerState, self).__init__()

        self.limits_cache = {}

        self.x_lim_helper = StateAttributeLimitsHelper(self, attribute='x_att',
                                                       lower='x_min', upper='x_max',
                                                       limits_cache=self.limits_cache)

        self.y_lim_helper = StateAttributeLimitsHelper(self, attribute='y_att',
                                                       lower='y_min', upper='y_max',
                                                       limits_cache=self.limits_cache)

        self.ref_data_helper = ManualDataComboHelper(self, 'reference_data')

        self.xw_att_helper = ComponentIDComboHelper(self, 'x_att_world',
                                                    numeric=False, categorical=False,
                                                    world_coord=True)

        self.yw_att_helper = ComponentIDComboHelper(self, 'y_att_world',
                                                    numeric=False, categorical=False,
                                                    world_coord=True)

        self.add_callback('reference_data', self._reference_data_changed, priority=1000)
        self.add_callback('layers', self._layers_changed, priority=1000)

        self.add_callback('x_att', self._on_xatt_change, priority=500)
        self.add_callback('y_att', self._on_yatt_change, priority=500)

        self.add_callback('x_att_world', self._update_att, priority=500)
        self.add_callback('y_att_world', self._update_att, priority=500)

        self.add_callback('x_att_world', self._on_xatt_world_change, priority=1000)
        self.add_callback('y_att_world', self._on_yatt_world_change, priority=1000)

        self.update_from_dict(kwargs)

    def reset_limits(self):

        if self.reference_data is None or self.x_att is None or self.y_att is None:
            return

        nx = self.reference_data.shape[self.x_att.axis]
        ny = self.reference_data.shape[self.y_att.axis]

        with delay_callback(self, 'x_min', 'x_max', 'y_min', 'y_max'):
            self.x_min = -0.5
            self.x_max = nx - 0.5
            self.y_min = -0.5
            self.y_max = ny - 0.5

    def _reference_data_changed(self, *args):
        with delay_callback(self, 'x_att_world', 'y_att_world', 'slices'):
            self._update_combo_att()
            self._set_default_slices()

    def _layers_changed(self, *args):

        # The layers callback gets executed if anything in the layers changes,
        # but we only care about whether the actual set of 'layer' attributes
        # for all layers change.

        layers_data = self.layers_data
        layers_data_cache = getattr(self, '_layers_data_cache', [])

        if layers_data == layers_data_cache:
            return

        self._update_combo_ref_data()
        self._set_reference_data()
        self._update_syncing()

        self._layers_data_cache = layers_data

    def _update_syncing(self):

        # If there are multiple layers for a given dataset, we disable the
        # syncing by default.

        layer_state_by_data = defaultdict(list)

        for layer_state in self.layers:
            if isinstance(layer_state.layer, Data):
                layer_state_by_data[layer_state.layer].append(layer_state)

        for data, layer_states in layer_state_by_data.items():
            if len(layer_states) > 1:
                for layer_state in layer_states:
                    # Scatter layers don't have global_sync so we need to be
                    # careful here and make sure we return a default value
                    if getattr(layer_state, 'global_sync', False):
                        layer_state.global_sync = False

    def _update_combo_ref_data(self):
        self.ref_data_helper.set_multiple_data(self.layers_data)

    def _update_combo_att(self):
        with delay_callback(self, 'x_att_world', 'y_att_world'):
            if self.reference_data is None:
                self.xw_att_helper.set_multiple_data([])
                self.yw_att_helper.set_multiple_data([])
            else:
                self.xw_att_helper.set_multiple_data([self.reference_data])
                self.yw_att_helper.set_multiple_data([self.reference_data])

    def _update_priority(self, name):
        if name == 'layers':
            return 3
        elif name == 'reference_data':
            return 2
        elif name.endswith(('_min', '_max')):
            return 0
        else:
            return 1

    @defer_draw
    def _update_att(self, *args):
        # Need to delay the callbacks here to make sure that we get a chance to
        # update both x_att and y_att otherwise could end up triggering image
        # slicing with two pixel components that are the same.
        with delay_callback(self, 'x_att', 'y_att'):
            if self.x_att_world is not None:
                index = self.reference_data.world_component_ids.index(self.x_att_world)
                self.x_att = self.reference_data.pixel_component_ids[index]
            if self.y_att_world is not None:
                index = self.reference_data.world_component_ids.index(self.y_att_world)
                self.y_att = self.reference_data.pixel_component_ids[index]

    @defer_draw
    def _on_xatt_change(self, *args):
        if self.x_att is not None:
            self.x_att_world = self.reference_data.world_component_ids[self.x_att.axis]

    @defer_draw
    def _on_yatt_change(self, *args):
        if self.y_att is not None:
            self.y_att_world = self.reference_data.world_component_ids[self.y_att.axis]

    @defer_draw
    def _on_xatt_world_change(self, *args):
        if self.x_att_world is not None and self.x_att_world == self.y_att_world:
            world_ids = self.reference_data.world_component_ids
            if self.x_att_world == world_ids[-1]:
                self.y_att_world = world_ids[-2]
            else:
                self.y_att_world = world_ids[-1]

    @defer_draw
    def _on_yatt_world_change(self, *args):
        if self.y_att_world is not None and self.y_att_world == self.x_att_world:
            world_ids = self.reference_data.world_component_ids
            if self.y_att_world == world_ids[-1]:
                self.x_att_world = world_ids[-2]
            else:
                self.x_att_world = world_ids[-1]

    def _set_reference_data(self):
        if self.reference_data is None:
            for layer in self.layers:
                if isinstance(layer.layer, Data):
                    self.reference_data = layer.layer
                    return

    def _set_default_slices(self):
        # Need to make sure this gets called immediately when reference_data is changed
        if self.reference_data is None:
            self.slices = ()
        else:
            self.slices = (0,) * self.reference_data.ndim

    @property
    def numpy_slice_aggregation_transpose(self):
        """
        Returns slicing information usable by Numpy.

        This returns two objects: the first is an object that can be used to
        slice Numpy arrays and return a 2D array, and the second object is a
        boolean indicating whether to transpose the result.
        """
        if self.reference_data is None:
            return None
        slices = []
        agg_func = []
        for i in range(self.reference_data.ndim):
            if i == self.x_att.axis or i == self.y_att.axis:
                slices.append(slice(None))
                agg_func.append(None)
            else:
                if isinstance(self.slices[i], AggregateSlice):
                    slices.append(self.slices[i].slice)
                    agg_func.append(self.slices[i].function)
                else:
                    slices.append(self.slices[i])
        transpose = self.y_att.axis > self.x_att.axis
        return slices, agg_func, transpose

    @property
    def wcsaxes_slice(self):
        """
        Returns slicing information usable by WCSAxes.

        This returns an iterable of slices, and including ``'x'`` and ``'y'``
        for the dimensions along which we are not slicing.
        """
        if self.reference_data is None:
            return None
        slices = []
        for i in range(self.reference_data.ndim):
            if i == self.x_att.axis:
                slices.append('x')
            elif i == self.y_att.axis:
                slices.append('y')
            else:
                if isinstance(self.slices[i], AggregateSlice):
                    slices.append(self.slices[i].center)
                else:
                    slices.append(self.slices[i])
        return slices[::-1]

    def flip_x(self):
        """
        Flip the x_min/x_max limits.
        """
        self.x_lim_helper.flip_limits()

    def flip_y(self):
        """
        Flip the y_min/y_max limits.
        """
        self.y_lim_helper.flip_limits()
コード例 #26
0
ファイル: state.py プロジェクト: shreyasbapat/glue
class ImageViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for an image viewer.
    """

    x_att = DDCProperty(
        docstring='The component ID giving the pixel component '
        'shown on the x axis')
    y_att = DDCProperty(
        docstring='The component ID giving the pixel component '
        'shown on the y axis')
    x_att_world = DDSCProperty(
        docstring='The component ID giving the world component '
        'shown on the x axis',
        default_index=-1)
    y_att_world = DDSCProperty(
        docstring='The component ID giving the world component '
        'shown on the y axis',
        default_index=-2)
    aspect = DDSCProperty(
        0,
        docstring='Whether to enforce square pixels (``equal``) '
        'or fill the axes (``auto``)')
    reference_data = DDSCProperty(
        docstring='The dataset that is used to define the '
        'available pixel/world components, and '
        'which defines the coordinate frame in '
        'which the images are shown')
    slices = DDCProperty(docstring='The current slice along all dimensions')
    color_mode = DDSCProperty(0,
                              docstring='Whether each layer can have '
                              'its own colormap (``Colormaps``) or '
                              'whether each layer is assigned '
                              'a single color (``One color per layer``)')

    dpi = DDCProperty(
        72,
        docstring=
        'The resolution (in dots per inch) of density maps, if present')

    def __init__(self, **kwargs):

        super(ImageViewerState, self).__init__()

        self.limits_cache = {}

        # NOTE: we don't need to use StateAttributeLimitsHelper here because
        # we can simply call reset_limits below when x/y attributes change.
        # Using StateAttributeLimitsHelper makes things a lot slower.

        self.ref_data_helper = ManualDataComboHelper(self, 'reference_data')

        self.xw_att_helper = ComponentIDComboHelper(self,
                                                    'x_att_world',
                                                    numeric=False,
                                                    categorical=False)

        self.yw_att_helper = ComponentIDComboHelper(self,
                                                    'y_att_world',
                                                    numeric=False,
                                                    categorical=False)

        self.add_callback('reference_data',
                          self._reference_data_changed,
                          priority=1000)
        self.add_callback('layers', self._layers_changed, priority=1000)

        self.add_callback('x_att', self._on_xatt_change, priority=500)
        self.add_callback('y_att', self._on_yatt_change, priority=500)

        self.add_callback('x_att_world', self._update_att, priority=500)
        self.add_callback('y_att_world', self._update_att, priority=500)

        self.add_callback('x_att_world',
                          self._on_xatt_world_change,
                          priority=1000)
        self.add_callback('y_att_world',
                          self._on_yatt_world_change,
                          priority=1000)

        aspect_display = {'equal': 'Square Pixels', 'auto': 'Automatic'}
        ImageViewerState.aspect.set_choices(self, ['equal', 'auto'])
        ImageViewerState.aspect.set_display_func(self, aspect_display.get)

        ImageViewerState.color_mode.set_choices(
            self, ['Colormaps', 'One color per layer'])

        self.update_from_dict(kwargs)

    def reset_limits(self):

        if self.reference_data is None or self.x_att is None or self.y_att is None:
            return

        nx = self.reference_data.shape[self.x_att.axis]
        ny = self.reference_data.shape[self.y_att.axis]

        with delay_callback(self, 'x_min', 'x_max', 'y_min', 'y_max'):
            self.x_min = -0.5
            self.x_max = nx - 0.5
            self.y_min = -0.5
            self.y_max = ny - 0.5
            # We need to adjust the limits in here to avoid triggering all
            # the update events then changing the limits again.
            self._adjust_limits_aspect()

    @property
    def _display_world(self):
        return isinstance(getattr(self.reference_data, 'coords', None),
                          Coordinates)

    def _reference_data_changed(self, *args):
        # This signal can get emitted if just the choices but not the actual
        # reference data change, so we check here that the reference data has
        # actually changed
        if self.reference_data is not getattr(self, '_last_reference_data',
                                              None):
            self._last_reference_data = self.reference_data
            with delay_callback(self, 'x_att_world', 'y_att_world', 'slices'):
                if self._display_world:
                    self.xw_att_helper.pixel_coord = False
                    self.yw_att_helper.pixel_coord = False
                    self.xw_att_helper.world_coord = True
                    self.yw_att_helper.world_coord = True
                else:
                    self.xw_att_helper.pixel_coord = True
                    self.yw_att_helper.pixel_coord = True
                    self.xw_att_helper.world_coord = False
                    self.yw_att_helper.world_coord = False
                self._update_combo_att()
                self._set_default_slices()

    def _layers_changed(self, *args):

        # The layers callback gets executed if anything in the layers changes,
        # but we only care about whether the actual set of 'layer' attributes
        # for all layers change.

        layers_data = self.layers_data
        layers_data_cache = getattr(self, '_layers_data_cache', [])

        if layers_data == layers_data_cache:
            return

        self._update_combo_ref_data()
        self._set_reference_data()
        self._update_syncing()

        self._layers_data_cache = layers_data

    def _update_syncing(self):

        # If there are multiple layers for a given dataset, we disable the
        # syncing by default.

        layer_state_by_data = defaultdict(list)

        for layer_state in self.layers:
            if isinstance(layer_state.layer, BaseData):
                layer_state_by_data[layer_state.layer].append(layer_state)

        for data, layer_states in layer_state_by_data.items():
            if len(layer_states) > 1:
                for layer_state in layer_states:
                    # Scatter layers don't have global_sync so we need to be
                    # careful here and make sure we return a default value
                    if getattr(layer_state, 'global_sync', False):
                        layer_state.global_sync = False

    def _update_combo_ref_data(self):
        self.ref_data_helper.set_multiple_data(self.layers_data)

    def _update_combo_att(self):
        with delay_callback(self, 'x_att_world', 'y_att_world'):
            if self.reference_data is None:
                self.xw_att_helper.set_multiple_data([])
                self.yw_att_helper.set_multiple_data([])
            else:
                self.xw_att_helper.set_multiple_data([self.reference_data])
                self.yw_att_helper.set_multiple_data([self.reference_data])

    def _update_priority(self, name):
        if name == 'layers':
            return 3
        elif name == 'reference_data':
            return 2
        elif name.endswith(('_min', '_max')):
            return 0
        else:
            return 1

    @defer_draw
    def _update_att(self, *args):
        # Need to delay the callbacks here to make sure that we get a chance to
        # update both x_att and y_att otherwise could end up triggering image
        # slicing with two pixel components that are the same.
        with delay_callback(self, 'x_att', 'y_att'):
            if self.x_att_world is not None:
                if self._display_world:
                    index = self.reference_data.world_component_ids.index(
                        self.x_att_world)
                    self.x_att = self.reference_data.pixel_component_ids[index]
                else:
                    self.x_att = self.x_att_world
            if self.y_att_world is not None:
                if self._display_world:
                    index = self.reference_data.world_component_ids.index(
                        self.y_att_world)
                    self.y_att = self.reference_data.pixel_component_ids[index]
                else:
                    self.y_att = self.y_att_world

    @defer_draw
    def _on_xatt_change(self, *args):
        if self.x_att is not None:
            if self._display_world:
                self.x_att_world = self.reference_data.world_component_ids[
                    self.x_att.axis]
            else:
                self.x_att_world = self.x_att

    @defer_draw
    def _on_yatt_change(self, *args):
        if self.y_att is not None:
            if self._display_world:
                self.y_att_world = self.reference_data.world_component_ids[
                    self.y_att.axis]
            else:
                self.y_att_world = self.y_att

    @defer_draw
    def _on_xatt_world_change(self, *args):
        if self.x_att_world is not None and self.x_att_world == self.y_att_world:
            world_ids = self.reference_data.world_component_ids
            if self.x_att_world == world_ids[-1]:
                self.y_att_world = world_ids[-2]
            else:
                self.y_att_world = world_ids[-1]

    @defer_draw
    def _on_yatt_world_change(self, *args):
        if self.y_att_world is not None and self.y_att_world == self.x_att_world:
            world_ids = self.reference_data.world_component_ids
            if self.y_att_world == world_ids[-1]:
                self.x_att_world = world_ids[-2]
            else:
                self.x_att_world = world_ids[-1]

    def _set_reference_data(self):
        if self.reference_data is None:
            for layer in self.layers:
                if isinstance(layer.layer, BaseData):
                    self.reference_data = layer.layer
                    return

    def _set_default_slices(self):
        # Need to make sure this gets called immediately when reference_data is changed
        if self.reference_data is None:
            self.slices = ()
        else:
            self.slices = (0, ) * self.reference_data.ndim

    @property
    def numpy_slice_aggregation_transpose(self):
        """
        Returns slicing information usable by Numpy.

        This returns two objects: the first is an object that can be used to
        slice Numpy arrays and return a 2D array, and the second object is a
        boolean indicating whether to transpose the result.
        """
        if self.reference_data is None:
            return None
        slices = []
        agg_func = []
        for i in range(self.reference_data.ndim):
            if i == self.x_att.axis or i == self.y_att.axis:
                slices.append(slice(None))
                agg_func.append(None)
            else:
                if isinstance(self.slices[i], AggregateSlice):
                    slices.append(self.slices[i].slice)
                    agg_func.append(self.slices[i].function)
                else:
                    slices.append(self.slices[i])
        transpose = self.y_att.axis > self.x_att.axis
        return slices, agg_func, transpose

    @property
    def wcsaxes_slice(self):
        """
        Returns slicing information usable by WCSAxes.

        This returns an iterable of slices, and including ``'x'`` and ``'y'``
        for the dimensions along which we are not slicing.
        """
        if self.reference_data is None:
            return None
        slices = []
        for i in range(self.reference_data.ndim):
            if i == self.x_att.axis:
                slices.append('x')
            elif i == self.y_att.axis:
                slices.append('y')
            else:
                if isinstance(self.slices[i], AggregateSlice):
                    slices.append(self.slices[i].center)
                else:
                    slices.append(self.slices[i])
        return slices[::-1]

    def flip_x(self):
        """
        Flip the x_min/x_max limits.
        """
        with delay_callback(self, 'x_min', 'x_max'):
            self.x_min, self.x_max = self.x_max, self.x_min

    def flip_y(self):
        """
        Flip the y_min/y_max limits.
        """
        with delay_callback(self, 'y_min', 'y_max'):
            self.y_min, self.y_max = self.y_max, self.y_min
コード例 #27
0
class WWTTableLayerState(LayerState):
    """
    A state object for WWT layers
    """

    layer = CallbackProperty()
    color = CallbackProperty()
    size = CallbackProperty()
    alpha = CallbackProperty()

    size_mode = SelectionCallbackProperty(default_index=0)
    size = CallbackProperty()
    size_att = SelectionCallbackProperty()
    size_vmin = CallbackProperty()
    size_vmax = CallbackProperty()
    size_scaling = CallbackProperty(1)

    color_mode = SelectionCallbackProperty(default_index=0)
    cmap_att = SelectionCallbackProperty()
    cmap_vmin = CallbackProperty()
    cmap_vmax = CallbackProperty()
    cmap = CallbackProperty()
    cmap_mode = color_mode

    size_limits_cache = CallbackProperty({})
    cmap_limits_cache = CallbackProperty({})

    img_data_att = SelectionCallbackProperty(default_index=0)

    def __init__(self, layer=None, **kwargs):

        self._sync_markersize = None

        super(WWTTableLayerState, self).__init__(layer=layer)

        self._sync_color = keep_in_sync(self, 'color', self.layer.style,
                                        'color')
        self._sync_alpha = keep_in_sync(self, 'alpha', self.layer.style,
                                        'alpha')
        self._sync_size = keep_in_sync(self, 'size', self.layer.style,
                                       'markersize')

        self.color = self.layer.style.color
        self.size = self.layer.style.markersize
        self.alpha = self.layer.style.alpha

        self.size_att_helper = ComponentIDComboHelper(self,
                                                      'size_att',
                                                      numeric=True,
                                                      categorical=False)
        self.cmap_att_helper = ComponentIDComboHelper(self,
                                                      'cmap_att',
                                                      numeric=True,
                                                      categorical=False)
        self.img_data_att_helper = ComponentIDComboHelper(self,
                                                          'img_data_att',
                                                          numeric=True,
                                                          categorical=False)

        self.size_lim_helper = StateAttributeLimitsHelper(
            self,
            attribute='size_att',
            lower='size_vmin',
            upper='size_vmax',
            cache=self.size_limits_cache)

        self.cmap_lim_helper = StateAttributeLimitsHelper(
            self,
            attribute='cmap_att',
            lower='cmap_vmin',
            upper='cmap_vmax',
            cache=self.cmap_limits_cache)

        self.add_callback('layer', self._on_layer_change)
        if layer is not None:
            self._on_layer_change()

        self.cmap = colormaps.members[0][1]

        # Color and size encoding depending on attributes is only available
        # in PyWWT 0.6 or later.
        if PYWWT_LT_06:
            modes = ['Fixed']
        else:
            modes = ['Fixed', 'Linear']

        WWTTableLayerState.color_mode.set_choices(self, modes)
        WWTTableLayerState.size_mode.set_choices(self, modes)

        self.update_from_dict(kwargs)

    def _on_layer_change(self, layer=None):
        with delay_callback(self, 'cmap_vmin', 'cmap_vmax', 'size_vmin',
                            'size_vmax'):
            if self.layer is None:
                self.cmap_att_helper.set_multiple_data([])
                self.size_att_helper.set_multiple_data([])
                self.img_data_att_helper.set_multiple_data([])
            else:
                self.cmap_att_helper.set_multiple_data([self.layer])
                self.size_att_helper.set_multiple_data([self.layer])
                self.img_data_att_helper.set_multiple_data([self.layer])

    def update_priority(self, name):
        return 0 if name.endswith(('vmin', 'vmax')) else 1

    def _layer_changed(self):

        super(WWTTableLayerState, self)._layer_changed()

        if self._sync_markersize is not None:
            self._sync_markersize.stop_syncing()

        if self.layer is not None:
            self.size = self.layer.style.markersize
            self._sync_markersize = keep_in_sync(self, 'size',
                                                 self.layer.style,
                                                 'markersize')

    def flip_size(self):
        self.size_lim_helper.flip_limits()

    def flip_cmap(self):
        self.cmap_lim_helper.flip_limits()
コード例 #28
0
ファイル: state.py プロジェクト: chaityacshah/glue
class HistogramViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for a histogram viewer.
    """

    x_att = DDSCProperty(
        docstring='The attribute to compute the histograms for')

    cumulative = DDCProperty(False,
                             docstring='Whether to show the histogram as '
                             'a cumulative histogram')
    normalize = DDCProperty(False,
                            docstring='Whether to normalize the histogram '
                            '(based on the total sum)')

    hist_x_min = DDCProperty(docstring='The minimum value used to compute the '
                             'histogram')
    hist_x_max = DDCProperty(docstring='The maxumum value used to compute the '
                             'histogram')
    hist_n_bin = DDCProperty(docstring='The number of bins in the histogram')

    common_n_bin = DDCProperty(True,
                               docstring='The number of bins to use for '
                               'all numerical components')

    def __init__(self, **kwargs):

        super(HistogramViewerState, self).__init__()

        self.hist_helper = StateAttributeHistogramHelper(
            self,
            'x_att',
            lower='hist_x_min',
            upper='hist_x_max',
            n_bin='hist_n_bin',
            common_n_bin='common_n_bin')

        self.x_lim_helper = StateAttributeLimitsHelper(self,
                                                       'x_att',
                                                       lower='x_min',
                                                       upper='x_max',
                                                       log='x_log')

        self.add_callback('layers', self._layers_changed)

        self.x_att_helper = ComponentIDComboHelper(self,
                                                   'x_att',
                                                   pixel_coord=True,
                                                   world_coord=True)

        self.update_from_dict(kwargs)

        # This should be added after update_from_dict since we don't want to
        # influence the restoring of sessions.
        self.add_callback('hist_x_min', self.update_view_to_bins)
        self.add_callback('hist_x_max', self.update_view_to_bins)

        self.add_callback('x_log', self._reset_x_limits, priority=1000)

    def _reset_x_limits(self, *args):
        with delay_callback(self, 'hist_x_min', 'hist_x_max', 'x_min', 'x_max',
                            'x_log'):
            self.x_lim_helper.percentile = 100
            self.x_lim_helper.update_values(force=True)
            self.update_bins_to_view()

    def reset_limits(self):
        self._reset_x_limits()
        self.y_min = min(
            getattr(layer, '_y_min', np.inf) for layer in self.layers)
        self.y_max = max(getattr(layer, '_y_max', 0) for layer in self.layers)

    def _update_priority(self, name):
        if name == 'layers':
            return 2
        elif name.endswith('_log'):
            return 0.5
        elif name.endswith(('_min', '_max', '_bin')):
            return 0
        else:
            return 1

    def flip_x(self):
        """
        Flip the x_min/x_max limits.
        """
        self.x_lim_helper.flip_limits()

    @avoid_circular
    def update_bins_to_view(self, *args):
        """
        Update the bins to match the current view.
        """
        with delay_callback(self, 'hist_x_min', 'hist_x_max'):
            if self.x_max > self.x_min:
                self.hist_x_min = self.x_min
                self.hist_x_max = self.x_max
            else:
                self.hist_x_min = self.x_max
                self.hist_x_max = self.x_min

    @avoid_circular
    def update_view_to_bins(self, *args):
        """
        Update the view to match the histogram interval
        """
        with delay_callback(self, 'x_min', 'x_max'):
            self.x_min = self.hist_x_min
            self.x_max = self.hist_x_max

    @property
    def x_categories(self):
        return self._categories(self.x_att)

    def _categories(self, cid):

        categories = []

        for layer_state in self.layers:

            if isinstance(layer_state.layer, BaseData):
                layer = layer_state.layer
            else:
                layer = layer_state.layer.data

            try:
                if layer.data.get_kind(cid) == 'categorical':
                    categories.append(layer.data.get_data(cid).categories)
            except IncompatibleAttribute:
                pass

        if len(categories) == 0:
            return None
        else:
            return np.unique(np.hstack(categories))

    @property
    def x_kinds(self):
        return self._component_kinds(self.x_att)

    def _component_kinds(self, cid):

        # Construct list of component kinds over all layers

        kinds = set()

        for layer_state in self.layers:

            if isinstance(layer_state.layer, BaseData):
                layer = layer_state.layer
            else:
                layer = layer_state.layer.data

            try:
                kinds.add(layer.data.get_kind(cid))
            except IncompatibleAttribute:
                pass

        return kinds

    @property
    def bins(self):
        """
        The position of the bins for the histogram based on the current state.
        """

        if self.hist_x_min is None or self.hist_x_max is None or self.hist_n_bin is None:
            return None

        if self.x_log:
            return np.logspace(np.log10(self.hist_x_min),
                               np.log10(self.hist_x_max), self.hist_n_bin + 1)
        elif isinstance(self.hist_x_min, np.datetime64):
            x_min = self.hist_x_min.astype(int)
            x_max = self.hist_x_max.astype(self.hist_x_min.dtype).astype(int)
            return np.linspace(x_min, x_max, self.hist_n_bin + 1).astype(
                self.hist_x_min.dtype)
        else:
            return np.linspace(self.hist_x_min, self.hist_x_max,
                               self.hist_n_bin + 1)

    @defer_draw
    def _layers_changed(self, *args):
        self.x_att_helper.set_multiple_data(self.layers_data)
コード例 #29
0
class ProfileViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for a Profile viewer.
    """

    x_att_pixel = DDCProperty(docstring='The component ID giving the pixel component '
                                  'shown on the x axis')

    x_att = DDSCProperty(docstring='The component ID giving the pixel or world component '
                                   'shown on the x axis')

    reference_data = DDSCProperty(docstring='The dataset that is used to define the '
                                            'available pixel/world components, and '
                                            'which defines the coordinate frame in '
                                            'which the images are shown')

    function = DDSCProperty(docstring='The function to use for collapsing data')

    normalize = DDCProperty(False, docstring='Whether to normalize all profiles '
                                             'to the [0:1] range')

    # TODO: add function to use

    def __init__(self, **kwargs):

        super(ProfileViewerState, self).__init__()

        self.ref_data_helper = ManualDataComboHelper(self, 'reference_data')

        self.add_callback('layers', self._layers_changed)
        self.add_callback('reference_data', self._reference_data_changed, echo_old=True)
        self.add_callback('x_att', self._update_att)
        self.add_callback('normalize', self._reset_y_limits)

        self.x_att_helper = ComponentIDComboHelper(self, 'x_att',
                                                   numeric=False, datetime=False, categorical=False,
                                                   pixel_coord=True)

        ProfileViewerState.function.set_choices(self, list(FUNCTIONS))
        ProfileViewerState.function.set_display_func(self, FUNCTIONS.get)

        self.update_from_dict(kwargs)

    def _update_combo_ref_data(self):
        self.ref_data_helper.set_multiple_data(self.layers_data)

    def reset_limits(self):
        with delay_callback(self, 'x_min', 'x_max', 'y_min', 'y_max'):
            self._reset_x_limits()
            self._reset_y_limits()

    @property
    def _display_world(self):
        return getattr(self.reference_data, 'coords', None) is not None

    @defer_draw
    def _update_att(self, *args):
        if self.x_att is not None:
            if self._display_world:
                if self.x_att in self.reference_data.pixel_component_ids:
                    self.x_att_pixel = self.x_att
                else:
                    index = self.reference_data.world_component_ids.index(self.x_att)
                    self.x_att_pixel = self.reference_data.pixel_component_ids[index]
            else:
                self.x_att_pixel = self.x_att
        self._reset_x_limits()

    def _reset_x_limits(self, *event):

        # NOTE: we don't use AttributeLimitsHelper because we need to avoid
        # trying to get the minimum of *all* the world coordinates in the
        # dataset. Instead, we use the same approach as in the layer state below
        # and in the case of world coordinates we use online the spine of the
        # data.

        if self.reference_data is None or self.x_att_pixel is None:
            return

        data = self.reference_data

        if self.x_att in data.pixel_component_ids:
            x_min, x_max = -0.5, data.shape[self.x_att.axis] - 0.5
        else:
            axis = data.world_component_ids.index(self.x_att)
            axis_view = [0] * data.ndim
            axis_view[axis] = slice(None)
            axis_values = data[self.x_att, tuple(axis_view)]
            x_min, x_max = np.nanmin(axis_values), np.nanmax(axis_values)

        with delay_callback(self, 'x_min', 'x_max'):
            self.x_min = x_min
            self.x_max = x_max

    def _reset_y_limits(self, *event):
        if self.normalize:
            with delay_callback(self, 'y_min', 'y_max'):
                self.y_min = -0.1
                self.y_max = +1.1
        else:
            y_min, y_max = np.inf, -np.inf
            for layer in self.layers:
                try:
                    profile = layer.profile
                except Exception:  # e.g. incompatible subset
                    continue
                if profile is not None:
                    x, y = profile
                    if len(y) > 0:
                        y_min = min(y_min, np.nanmin(y))
                        y_max = max(y_max, np.nanmax(y))
            with delay_callback(self, 'y_min', 'y_max'):
                if y_max > y_min:
                    self.y_min = y_min
                    self.y_max = y_max
                else:
                    self.y_min = 0
                    self.y_max = 1

    def flip_x(self):
        """
        Flip the x_min/x_max limits.
        """
        with delay_callback(self, 'x_min', 'x_max'):
            self.x_min, self.x_max = self.x_max, self.x_min

    @defer_draw
    def _layers_changed(self, *args):
        self._update_combo_ref_data()

    @defer_draw
    def _reference_data_changed(self, before=None, after=None):

        # A callback event for reference_data is triggered if the choices change
        # but the actual selection doesn't - so we avoid resetting the WCS in
        # this case.
        if before is after:
            return

        for layer in self.layers:
            layer.reset_cache()

        # This signal can get emitted if just the choices but not the actual
        # reference data change, so we check here that the reference data has
        # actually changed
        if self.reference_data is not getattr(self, '_last_reference_data', None):
            self._last_reference_data = self.reference_data

            with delay_callback(self, 'x_att'):

                if self.reference_data is None:
                    self.x_att_helper.set_multiple_data([])
                else:
                    self.x_att_helper.set_multiple_data([self.reference_data])
                    if self._display_world:
                        self.x_att_helper.world_coord = True
                        self.x_att = self.reference_data.world_component_ids[0]
                    else:
                        self.x_att_helper.world_coord = False
                        self.x_att = self.reference_data.pixel_component_ids[0]

                self._update_att()

        self.reset_limits()

    def _update_priority(self, name):
        if name == 'layers':
            return 2
        elif name == 'reference_data':
            return 1.5
        elif name.endswith(('_min', '_max')):
            return 0
        else:
            return 1
コード例 #30
0
ファイル: state.py プロジェクト: sergiopasra/glue
class HistogramViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for a histogram viewer.
    """

    x_att = DDSCProperty(docstring='The attribute to compute the histograms for')

    cumulative = DDCProperty(False, docstring='Whether to show the histogram as '
                                              'a cumulative histogram')
    normalize = DDCProperty(False, docstring='Whether to normalize the histogram '
                                             '(based on the total sum)')

    hist_x_min = DDCProperty(docstring='The minimum value used to compute the '
                                       'histogram')
    hist_x_max = DDCProperty(docstring='The maxumum value used to compute the '
                                       'histogram')
    hist_n_bin = DDCProperty(docstring='The number of bins in the histogram')

    common_n_bin = DDCProperty(True, docstring='The number of bins to use for '
                                               'all numerical components')

    def __init__(self, **kwargs):

        super(HistogramViewerState, self).__init__()

        self.hist_helper = StateAttributeHistogramHelper(self, 'x_att', lower='hist_x_min',
                                                         upper='hist_x_max', n_bin='hist_n_bin',
                                                         common_n_bin='common_n_bin')

        self.x_lim_helper = StateAttributeLimitsHelper(self, 'x_att', lower='x_min',
                                                       upper='x_max', log='x_log')

        self.add_callback('layers', self._layers_changed)

        self.x_att_helper = ComponentIDComboHelper(self, 'x_att',
                                                   pixel_coord=True, world_coord=True)

        self.update_from_dict(kwargs)

        # This should be added after update_from_dict since we don't want to
        # influence the restoring of sessions.
        self.add_callback('hist_x_min', self.update_view_to_bins)
        self.add_callback('hist_x_max', self.update_view_to_bins)

        self.add_callback('x_log', self._reset_x_limits, priority=1000)

    def _reset_x_limits(self, *args):
        with delay_callback(self, 'hist_x_min', 'hist_x_max', 'x_min', 'x_max', 'x_log'):
            self.x_lim_helper.percentile = 100
            self.x_lim_helper.update_values(force=True)
            self.update_bins_to_view()

    def reset_limits(self):
        self._reset_x_limits()
        self.y_min = min(getattr(layer, '_y_min', np.inf) for layer in self.layers)
        self.y_max = max(getattr(layer, '_y_max', 0) for layer in self.layers)

    def _update_priority(self, name):
        if name == 'layers':
            return 2
        elif name.endswith('_log'):
            return 0.5
        elif name.endswith(('_min', '_max', '_bin')):
            return 0
        else:
            return 1

    def flip_x(self):
        """
        Flip the x_min/x_max limits.
        """
        self.x_lim_helper.flip_limits()

    @avoid_circular
    def update_bins_to_view(self, *args):
        """
        Update the bins to match the current view.
        """
        with delay_callback(self, 'hist_x_min', 'hist_x_max'):
            if self.x_max > self.x_min:
                self.hist_x_min = self.x_min
                self.hist_x_max = self.x_max
            else:
                self.hist_x_min = self.x_max
                self.hist_x_max = self.x_min

    @avoid_circular
    def update_view_to_bins(self, *args):
        """
        Update the view to match the histogram interval
        """
        with delay_callback(self, 'x_min', 'x_max'):
            self.x_min = self.hist_x_min
            self.x_max = self.hist_x_max

    def _get_x_components(self):

        if self.x_att is None:
            return []

        # Construct list of components over all layers

        components = []

        for layer_state in self.layers:

            if isinstance(layer_state.layer, Data):
                layer = layer_state.layer
            else:
                layer = layer_state.layer.data

            try:
                components.append(layer.get_component(self.x_att))
            except IncompatibleAttribute:
                pass

        return components

    @property
    def bins(self):
        """
        The position of the bins for the histogram based on the current state.
        """

        if self.hist_x_min is None or self.hist_x_max is None or self.hist_n_bin is None:
            return None

        if self.x_log:
            return np.logspace(np.log10(self.hist_x_min),
                               np.log10(self.hist_x_max),
                               self.hist_n_bin + 1)
        elif isinstance(self.hist_x_min, np.datetime64):
            x_min = self.hist_x_min.astype(int)
            x_max = self.hist_x_max.astype(self.hist_x_min.dtype).astype(int)
            return np.linspace(x_min, x_max, self.hist_n_bin + 1).astype(self.hist_x_min.dtype)
        else:
            return np.linspace(self.hist_x_min, self.hist_x_max,
                               self.hist_n_bin + 1)

    @defer_draw
    def _layers_changed(self, *args):
        self.x_att_helper.set_multiple_data(self.layers_data)
コード例 #31
0
ファイル: state.py プロジェクト: jzuhone/glue
class ScatterViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for a scatter viewer.
    """

    x_att = DDSCProperty(docstring='The attribute to show on the x-axis', default_index=0)
    y_att = DDSCProperty(docstring='The attribute to show on the y-axis', default_index=1)
    dpi = DDCProperty(72, docstring='The resolution (in dots per inch) of density maps, if present')

    def __init__(self, **kwargs):

        super(ScatterViewerState, self).__init__()

        self.limits_cache = {}

        self.x_lim_helper = StateAttributeLimitsHelper(self, attribute='x_att',
                                                       lower='x_min', upper='x_max',
                                                       log='x_log', margin=0.05,
                                                       limits_cache=self.limits_cache)

        self.y_lim_helper = StateAttributeLimitsHelper(self, attribute='y_att',
                                                       lower='y_min', upper='y_max',
                                                       log='y_log', margin=0.05,
                                                       limits_cache=self.limits_cache)

        self.add_callback('layers', self._layers_changed)

        self.x_att_helper = ComponentIDComboHelper(self, 'x_att', pixel_coord=True, world_coord=True)
        self.y_att_helper = ComponentIDComboHelper(self, 'y_att', pixel_coord=True, world_coord=True)

        self.update_from_dict(kwargs)

        self.add_callback('x_log', self._reset_x_limits)
        self.add_callback('y_log', self._reset_y_limits)

    def _reset_x_limits(self, *args):
        self.x_lim_helper.percentile = 100
        self.x_lim_helper.update_values(force=True)

    def _reset_y_limits(self, *args):
        self.y_lim_helper.percentile = 100
        self.y_lim_helper.update_values(force=True)

    def reset_limits(self):
        self._reset_x_limits()
        self._reset_y_limits()

    def flip_x(self):
        """
        Flip the x_min/x_max limits.
        """
        self.x_lim_helper.flip_limits()

    def flip_y(self):
        """
        Flip the y_min/y_max limits.
        """
        self.y_lim_helper.flip_limits()

    @property
    def x_categories(self):
        return self._categories(self.x_att)

    @property
    def y_categories(self):
        return self._categories(self.y_att)

    def _categories(self, cid):

        categories = []

        for layer_state in self.layers:

            if isinstance(layer_state.layer, BaseData):
                layer = layer_state.layer
            else:
                layer = layer_state.layer.data

            try:
                if layer.data.get_kind(cid) == 'categorical':
                    categories.append(layer.data.get_data(cid).categories)
            except IncompatibleAttribute:
                pass

        if len(categories) == 0:
            return None
        else:
            return np.unique(np.hstack(categories))

    @property
    def x_kinds(self):
        return self._component_kinds(self.x_att)

    @property
    def y_kinds(self):
        return self._component_kinds(self.y_att)

    def _component_kinds(self, cid):

        # Construct list of component kinds over all layers

        kinds = set()

        for layer_state in self.layers:

            if isinstance(layer_state.layer, BaseData):
                layer = layer_state.layer
            else:
                layer = layer_state.layer.data

            try:
                kinds.add(layer.data.get_kind(cid))
            except IncompatibleAttribute:
                pass

        return kinds

    def _layers_changed(self, *args):

        layers_data = self.layers_data
        layers_data_cache = getattr(self, '_layers_data_cache', [])

        if layers_data == layers_data_cache:
            return

        self.x_att_helper.set_multiple_data(self.layers_data)
        self.y_att_helper.set_multiple_data(self.layers_data)

        self._layers_data_cache = layers_data
コード例 #32
0
ファイル: state.py プロジェクト: PennyQ/glue
class HistogramViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for a histogram viewer.
    """

    x_att = DDSCProperty(docstring='The attribute to compute the histograms for')

    cumulative = DDCProperty(False, docstring='Whether to show the histogram as '
                                              'a cumulative histogram')
    normalize = DDCProperty(False, docstring='Whether to normalize the histogram '
                                             '(based on the total sum)')

    hist_x_min = DDCProperty(docstring='The minimum value used to compute the '
                                       'histogram')
    hist_x_max = DDCProperty(docstring='The maxumum value used to compute the '
                                       'histogram')
    hist_n_bin = DDCProperty(docstring='The number of bins in the histogram')

    common_n_bin = DDCProperty(True, docstring='The number of bins to use for '
                                               'all numerical components')

    def __init__(self, **kwargs):

        super(HistogramViewerState, self).__init__()

        self.hist_helper = StateAttributeHistogramHelper(self, 'x_att', lower='hist_x_min',
                                                         upper='hist_x_max', n_bin='hist_n_bin',
                                                         common_n_bin='common_n_bin')

        self.x_lim_helper = StateAttributeLimitsHelper(self, 'x_att', lower='x_min',
                                                       upper='x_max', log='x_log')

        self.add_callback('layers', self._layers_changed)

        self.x_att_helper = ComponentIDComboHelper(self, 'x_att')

        self.update_from_dict(kwargs)

    def _update_priority(self, name):
        if name == 'layers':
            return 2
        elif name.endswith('_log'):
            return 0.5
        elif name.endswith(('_min', '_max', '_bin')):
            return 0
        else:
            return 1

    def flip_x(self):
        """
        Flip the x_min/x_max limits.
        """
        self.x_lim_helper.flip_limits()

    def update_bins_to_view(self):
        """
        Update the bins to match the current view.
        """
        with delay_callback(self, 'hist_x_min', 'hist_x_max'):
            if self.x_max > self.x_min:
                self.hist_x_min = self.x_min
                self.hist_x_max = self.x_max
            else:
                self.hist_x_min = self.x_max
                self.hist_x_max = self.x_min

    def _get_x_components(self):

        if self.x_att is None:
            return []

        # Construct list of components over all layers

        components = []

        for layer_state in self.layers:

            if isinstance(layer_state.layer, Data):
                layer = layer_state.layer
            else:
                layer = layer_state.layer.data

            try:
                components.append(layer.get_component(self.x_att))
            except IncompatibleAttribute:
                pass

        return components

    @property
    def bins(self):
        """
        The position of the bins for the histogram based on the current state.
        """
        if self.x_log:
            return np.logspace(np.log10(self.hist_x_min),
                               np.log10(self.hist_x_max),
                               self.hist_n_bin + 1)
        else:
            return np.linspace(self.hist_x_min, self.hist_x_max,
                               self.hist_n_bin + 1)

    @defer_draw
    def _layers_changed(self, *args):
        self.x_att_helper.set_multiple_data(self.layers_data)
コード例 #33
0
ファイル: state.py プロジェクト: sarahb55/glue
class ScatterViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for a scatter viewer.
    """

    x_att = DDSCProperty(docstring='The attribute to show on the x-axis',
                         default_index=0)
    y_att = DDSCProperty(docstring='The attribute to show on the y-axis',
                         default_index=1)
    dpi = DDCProperty(
        72,
        docstring=
        'The resolution (in dots per inch) of density maps, if present')

    def __init__(self, **kwargs):

        super(ScatterViewerState, self).__init__()

        self.limits_cache = {}

        self.x_lim_helper = StateAttributeLimitsHelper(
            self,
            attribute='x_att',
            lower='x_min',
            upper='x_max',
            log='x_log',
            margin=0.05,
            limits_cache=self.limits_cache)

        self.y_lim_helper = StateAttributeLimitsHelper(
            self,
            attribute='y_att',
            lower='y_min',
            upper='y_max',
            log='y_log',
            margin=0.05,
            limits_cache=self.limits_cache)

        self.add_callback('layers', self._layers_changed)

        self.x_att_helper = ComponentIDComboHelper(self,
                                                   'x_att',
                                                   pixel_coord=True,
                                                   world_coord=True)
        self.y_att_helper = ComponentIDComboHelper(self,
                                                   'y_att',
                                                   pixel_coord=True,
                                                   world_coord=True)

        self.update_from_dict(kwargs)

        self.add_callback('x_log', self._reset_x_limits)
        self.add_callback('y_log', self._reset_y_limits)

    def _reset_x_limits(self, *args):
        self.x_lim_helper.percentile = 100
        self.x_lim_helper.update_values(force=True)

    def _reset_y_limits(self, *args):
        self.y_lim_helper.percentile = 100
        self.y_lim_helper.update_values(force=True)

    def reset_limits(self):
        self._reset_x_limits()
        self._reset_y_limits()

    def _update_priority(self, name):
        if name == 'layers':
            return 2
        elif name.endswith('_log'):
            return 0.5
        elif name.endswith(('_min', '_max')):
            return 0
        else:
            return 1

    def flip_x(self):
        """
        Flip the x_min/x_max limits.
        """
        self.x_lim_helper.flip_limits()

    def flip_y(self):
        """
        Flip the y_min/y_max limits.
        """
        self.y_lim_helper.flip_limits()

    def _get_x_components(self):
        return self._get_components(self.x_att)

    def _get_y_components(self):
        return self._get_components(self.y_att)

    def _get_components(self, cid):

        # Construct list of components over all layers

        components = []

        for layer_state in self.layers:

            if isinstance(layer_state.layer, Data):
                layer = layer_state.layer
            else:
                layer = layer_state.layer.data

            try:
                components.append(layer.data.get_component(cid))
            except IncompatibleAttribute:
                pass

        return components

    def _layers_changed(self, *args):

        layers_data = self.layers_data
        layers_data_cache = getattr(self, '_layers_data_cache', [])

        if layers_data == layers_data_cache:
            return

        self.x_att_helper.set_multiple_data(self.layers_data)
        self.y_att_helper.set_multiple_data(self.layers_data)

        self._layers_data_cache = layers_data
コード例 #34
0
ファイル: state.py プロジェクト: glue-viz/glue-wwt
class WWTLayerState(LayerState):
    """
    A state object for volume layers
    """


    layer = CallbackProperty()
    color = CallbackProperty()
    size = CallbackProperty()
    alpha = CallbackProperty()

    size_mode = SelectionCallbackProperty(default_index=0)
    size = CallbackProperty()
    size_att = SelectionCallbackProperty()
    size_vmin = CallbackProperty()
    size_vmax = CallbackProperty()
    size_scaling = CallbackProperty(1)

    color_mode = SelectionCallbackProperty(default_index=0)
    cmap_att = SelectionCallbackProperty()
    cmap_vmin = CallbackProperty()
    cmap_vmax = CallbackProperty()
    cmap = CallbackProperty()

    size_limits_cache = CallbackProperty({})
    cmap_limits_cache = CallbackProperty({})

    def __init__(self, layer=None, **kwargs):

        self._sync_markersize = None

        super(WWTLayerState, self).__init__(layer=layer)

        self._sync_color = keep_in_sync(self, 'color', self.layer.style, 'color')
        self._sync_alpha = keep_in_sync(self, 'alpha', self.layer.style, 'alpha')
        self._sync_size = keep_in_sync(self, 'size', self.layer.style, 'markersize')

        self.color = self.layer.style.color
        self.size = self.layer.style.markersize
        self.alpha = self.layer.style.alpha

        self.size_att_helper = ComponentIDComboHelper(self, 'size_att',
                                                      numeric=True,
                                                      categorical=False)
        self.cmap_att_helper = ComponentIDComboHelper(self, 'cmap_att',
                                                      numeric=True,
                                                      categorical=False)

        self.size_lim_helper = StateAttributeLimitsHelper(self, attribute='size_att',
                                                          lower='size_vmin', upper='size_vmax',
                                                          cache=self.size_limits_cache)

        self.cmap_lim_helper = StateAttributeLimitsHelper(self, attribute='cmap_att',
                                                          lower='cmap_vmin', upper='cmap_vmax',
                                                          cache=self.cmap_limits_cache)

        self.add_callback('layer', self._on_layer_change)
        if layer is not None:
            self._on_layer_change()

        self.cmap = colormaps.members[0][1]

        # Color and size encoding depending on attributes is only available
        # in PyWWT 0.6 or later.
        if PYWWT_LT_06:
            modes = ['Fixed']
        else:
            modes = ['Fixed', 'Linear']

        WWTLayerState.color_mode.set_choices(self, modes)
        WWTLayerState.size_mode.set_choices(self, modes)

        self.update_from_dict(kwargs)

    def _on_layer_change(self, layer=None):

        with delay_callback(self, 'cmap_vmin', 'cmap_vmax', 'size_vmin', 'size_vmax'):

            if self.layer is None:
                self.cmap_att_helper.set_multiple_data([])
                self.size_att_helper.set_multiple_data([])
            else:
                self.cmap_att_helper.set_multiple_data([self.layer])
                self.size_att_helper.set_multiple_data([self.layer])

    def update_priority(self, name):
        return 0 if name.endswith(('vmin', 'vmax')) else 1

    def _layer_changed(self):

        super(WWTLayerState, self)._layer_changed()

        if self._sync_markersize is not None:
            self._sync_markersize.stop_syncing()

        if self.layer is not None:
            self.size = self.layer.style.markersize
            self._sync_markersize = keep_in_sync(self, 'size', self.layer.style, 'markersize')

    def flip_size(self):
        self.size_lim_helper.flip_limits()

    def flip_cmap(self):
        self.cmap_lim_helper.flip_limits()
コード例 #35
0
ファイル: state.py プロジェクト: glue-viz/glue
class ProfileViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for a Profile viewer.
    """

    x_att_pixel = DDCProperty(docstring='The component ID giving the pixel component '
                                  'shown on the x axis')

    x_att = DDSCProperty(docstring='The component ID giving the pixel or world component '
                                   'shown on the x axis')

    reference_data = DDSCProperty(docstring='The dataset that is used to define the '
                                            'available pixel/world components, and '
                                            'which defines the coordinate frame in '
                                            'which the images are shown')

    function = DDSCProperty(docstring='The function to use for collapsing data')

    normalize = DDCProperty(False, docstring='Whether to normalize all profiles '
                                             'to the [0:1] range')

    # TODO: add function to use

    def __init__(self, **kwargs):

        super(ProfileViewerState, self).__init__()

        self.ref_data_helper = ManualDataComboHelper(self, 'reference_data')

        self.add_callback('layers', self._layers_changed)
        self.add_callback('reference_data', self._reference_data_changed)
        self.add_callback('x_att', self._update_att)
        self.add_callback('normalize', self._reset_y_limits)

        self.x_att_helper = ComponentIDComboHelper(self, 'x_att',
                                                   numeric=False, categorical=False,
                                                   pixel_coord=True)

        ProfileViewerState.function.set_choices(self, list(FUNCTIONS))
        ProfileViewerState.function.set_display_func(self, FUNCTIONS.get)

        self.update_from_dict(kwargs)

    def _update_combo_ref_data(self):
        self.ref_data_helper.set_multiple_data(self.layers_data)

    def reset_limits(self):
        with delay_callback(self, 'x_min', 'x_max', 'y_min', 'y_max'):
            self._reset_x_limits()
            self._reset_y_limits()

    @property
    def _display_world(self):
        return (isinstance(getattr(self.reference_data, 'coords', None), Coordinates) and
                type(self.reference_data.coords) != Coordinates)

    @defer_draw
    def _update_att(self, *args):
        if self.x_att is not None:
            if self._display_world:
                if self.x_att in self.reference_data.pixel_component_ids:
                    self.x_att_pixel = self.x_att
                else:
                    index = self.reference_data.world_component_ids.index(self.x_att)
                    self.x_att_pixel = self.reference_data.pixel_component_ids[index]
            else:
                self.x_att_pixel = self.x_att
        self._reset_x_limits()

    def _reset_x_limits(self, *event):

        # NOTE: we don't use AttributeLimitsHelper because we need to avoid
        # trying to get the minimum of *all* the world coordinates in the
        # dataset. Instead, we use the same approach as in the layer state below
        # and in the case of world coordinates we use online the spine of the
        # data.

        if self.reference_data is None or self.x_att_pixel is None:
            return

        data = self.reference_data

        if self.x_att in data.pixel_component_ids:
            x_min, x_max = -0.5, data.shape[self.x_att.axis] - 0.5
        else:
            axis = data.world_component_ids.index(self.x_att)
            axis_view = [0] * data.ndim
            axis_view[axis] = slice(None)
            axis_values = data[self.x_att, tuple(axis_view)]
            x_min, x_max = np.nanmin(axis_values), np.nanmax(axis_values)

        with delay_callback(self, 'x_min', 'x_max'):
            self.x_min = x_min
            self.x_max = x_max

    def _reset_y_limits(self, *event):
        if self.normalize:
            with delay_callback(self, 'y_min', 'y_max'):
                self.y_min = -0.1
                self.y_max = +1.1

    def flip_x(self):
        """
        Flip the x_min/x_max limits.
        """
        with delay_callback(self, 'x_min', 'x_max'):
            self.x_min, self.x_max = self.x_max, self.x_min

    @defer_draw
    def _layers_changed(self, *args):
        self._update_combo_ref_data()

    @defer_draw
    def _reference_data_changed(self, *args):

        # This signal can get emitted if just the choices but not the actual
        # reference data change, so we check here that the reference data has
        # actually changed
        if self.reference_data is not getattr(self, '_last_reference_data', None):
            self._last_reference_data = self.reference_data

            if self.reference_data is None:
                self.x_att_helper.set_multiple_data([])
            else:
                self.x_att_helper.set_multiple_data([self.reference_data])
                if self._display_world:
                    self.x_att_helper.world_coord = True
                    self.x_att = self.reference_data.world_component_ids[0]
                else:
                    self.x_att_helper.world_coord = False
                    self.x_att = self.reference_data.pixel_component_ids[0]
コード例 #36
0
ファイル: layer_state.py プロジェクト: PennyQ/glue-3d-viewer
class ScatterLayerState(VispyLayerState):
    """
    A state object for volume layers
    """

    size_mode = CallbackProperty('Fixed')
    size = CallbackProperty()
    size_attribute = SelectionCallbackProperty()
    size_vmin = CallbackProperty()
    size_vmax = CallbackProperty()
    size_scaling = CallbackProperty(1)

    color_mode = CallbackProperty('Fixed')
    cmap_attribute = SelectionCallbackProperty()
    cmap_vmin = CallbackProperty()
    cmap_vmax = CallbackProperty()
    cmap = CallbackProperty()

    size_limits_cache = CallbackProperty({})
    cmap_limits_cache = CallbackProperty({})

    def __init__(self, layer=None, **kwargs):

        self._sync_markersize = None

        super(ScatterLayerState, self).__init__(layer=layer)

        if self.layer is not None:

            self.color = self.layer.style.color
            self.size = self.layer.style.markersize
            self.alpha = self.layer.style.alpha

        self.size_att_helper = ComponentIDComboHelper(self, 'size_attribute')
        self.cmap_att_helper = ComponentIDComboHelper(self, 'cmap_attribute')

        self.size_lim_helper = StateAttributeLimitsHelper(self, attribute='size_attribute',
                                                          lower='size_vmin', upper='size_vmax',
                                                          cache=self.size_limits_cache)

        self.cmap_lim_helper = StateAttributeLimitsHelper(self, attribute='cmap_attribute',
                                                          lower='cmap_vmin', upper='cmap_vmax',
                                                          cache=self.cmap_limits_cache)

        self.add_callback('layer', self._on_layer_change)
        if layer is not None:
            self._on_layer_change()

        self.cmap = colormaps.members[0][1]

        self.update_from_dict(kwargs)

    def _on_layer_change(self, layer=None):

        with delay_callback(self, 'cmap_vmin', 'cmap_vmax', 'size_vmin', 'size_vmax'):

            if self.layer is None:
                self.cmap_att_helper.set_multiple_data([])
                self.size_att_helper.set_multiple_data([])
            else:
                self.cmap_att_helper.set_multiple_data([self.layer])
                self.size_att_helper.set_multiple_data([self.layer])

    def update_priority(self, name):
        return 0 if name.endswith(('vmin', 'vmax')) else 1

    def _layer_changed(self):

        super(ScatterLayerState, self)._layer_changed()

        if self._sync_markersize is not None:
            self._sync_markersize.stop_syncing()

        if self.layer is not None:
            self.size = self.layer.style.markersize
            self._sync_markersize = keep_in_sync(self, 'size', self.layer.style, 'markersize')

    def flip_size(self):
        self.size_lim_helper.flip_limits()

    def flip_cmap(self):
        self.cmap_lim_helper.flip_limits()
コード例 #37
0
ファイル: state.py プロジェクト: stscieisenhamer/glue
class ImageLayerState(BaseImageLayerState):
    """
    A state class that includes all the attributes for data layers in an image plot.
    """

    attribute = DDSCProperty(docstring='The attribute shown in the layer')
    v_min = DDCProperty(docstring='The lower level shown')
    v_max = DDCProperty(docstring='The upper leven shown')
    percentile = DDSCProperty(docstring='The percentile value used to '
                                        'automatically calculate levels')
    contrast = DDCProperty(1, docstring='The contrast of the layer')
    bias = DDCProperty(0.5, docstring='A constant value that is added to the '
                                      'layer before rendering')
    cmap = DDCProperty(docstring='The colormap used to render the layer')
    stretch = DDSCProperty(docstring='The stretch used to render the layer, '
                                     'which should be one of ``linear``, '
                                     '``sqrt``, ``log``, or ``arcsinh``')
    global_sync = DDCProperty(True, docstring='Whether the color and transparency '
                                              'should be synced with the global '
                                              'color and transparency for the data')

    def __init__(self, layer=None, viewer_state=None, **kwargs):

        super(ImageLayerState, self).__init__(layer=layer, viewer_state=viewer_state)

        self.attribute_lim_helper = StateAttributeLimitsHelper(self, attribute='attribute',
                                                               percentile='percentile',
                                                               lower='v_min', upper='v_max')

        self.attribute_att_helper = ComponentIDComboHelper(self, 'attribute',
                                                           numeric=True, categorical=False)

        percentile_display = {100: 'Min/Max',
                              99.5: '99.5%',
                              99: '99%',
                              95: '95%',
                              90: '90%',
                              'Custom': 'Custom'}

        ImageLayerState.percentile.set_choices(self, [100, 99.5, 99, 95, 90, 'Custom'])
        ImageLayerState.percentile.set_display_func(self, percentile_display.get)

        stretch_display = {'linear': 'Linear',
                           'sqrt': 'Square Root',
                           'arcsinh': 'Arcsinh',
                           'log': 'Logarithmic'}

        ImageLayerState.stretch.set_choices(self, ['linear', 'sqrt', 'arcsinh', 'log'])
        ImageLayerState.stretch.set_display_func(self, stretch_display.get)

        self.add_callback('global_sync', self._update_syncing)
        self.add_callback('layer', self._update_attribute)

        self._update_syncing()

        if layer is not None:
            self._update_attribute()

        self.update_from_dict(kwargs)

        if self.cmap is None:
            self.cmap = colormaps.members[0][1]

    def _update_attribute(self, *args):
        if self.layer is not None:
            self.attribute_att_helper.set_multiple_data([self.layer])
            self.attribute = self.layer.visible_components[0]

    def _update_priority(self, name):
        if name == 'layer':
            return 3
        elif name == 'attribute':
            return 2
        elif name == 'global_sync':
            return 1.5
        elif name.endswith(('_min', '_max')):
            return 0
        else:
            return 1

    def _update_syncing(self, *args):
        if self.global_sync:
            self._sync_color.enable_syncing()
            self._sync_alpha.enable_syncing()
        else:
            self._sync_color.disable_syncing()
            self._sync_alpha.disable_syncing()

    def _get_image(self, view=None):
        return self.layer[self.attribute, view]

    def flip_limits(self):
        """
        Flip the image levels.
        """
        self.attribute_lim_helper.flip_limits()

    def reset_contrast_bias(self):
        with delay_callback(self, 'contrast', 'bias'):
            self.contrast = 1
            self.bias = 0.5
コード例 #38
0
class ProfileLayerState(MatplotlibLayerState):
    """
    A state class that includes all the attributes for layers in a Profile plot.
    """

    linewidth = DDCProperty(1, docstring='The width of the line')

    attribute = DDSCProperty(docstring='The attribute shown in the layer')
    v_min = DDCProperty(docstring='The lower level shown')
    v_max = DDCProperty(docstring='The upper leven shown')
    percentile = DDSCProperty(docstring='The percentile value used to '
                              'automatically calculate levels')

    def __init__(self, layer=None, viewer_state=None, **kwargs):

        super(ProfileLayerState, self).__init__(layer=layer,
                                                viewer_state=viewer_state)

        self.attribute_att_helper = ComponentIDComboHelper(self,
                                                           'attribute',
                                                           numeric=True,
                                                           categorical=False)

        percentile_display = {
            100: 'Min/Max',
            99.5: '99.5%',
            99: '99%',
            95: '95%',
            90: '90%',
            'Custom': 'Custom'
        }

        ProfileLayerState.percentile.set_choices(
            self, [100, 99.5, 99, 95, 90, 'Custom'])
        ProfileLayerState.percentile.set_display_func(self,
                                                      percentile_display.get)

        self.add_callback('layer', self._update_attribute, priority=1000)
        self.add_callback('layer', self._update_profile, priority=1000)
        self.add_callback('attribute', self._update_profile, priority=1000)

        if layer is not None:
            self._update_attribute()

        self.update_from_dict(kwargs)

    def _update_attribute(self, *args):
        if self.layer is not None:
            self.attribute_att_helper.set_multiple_data([self.layer])

    @property
    def independent_x_att(self):
        return is_convertible_to_single_pixel_cid(
            self.layer, self.viewer_state.x_att) is not None

    def normalize_values(self, values):
        return (np.asarray(values) - self.v_min) / (self.v_max - self.v_min)

    @property
    def viewer_state(self):
        return self._viewer_state

    @viewer_state.setter
    def viewer_state(self, viewer_state):
        self._viewer_state = viewer_state
        if viewer_state is not None:
            self._viewer_state.add_callback('x_att',
                                            self._update_profile,
                                            priority=1000)
            self._viewer_state.add_callback('function',
                                            self._update_profile,
                                            priority=1000)
            self._update_profile()

    @property
    def profile(self):
        return self._profile

    def _update_profile(self, *event):

        if self.viewer_state is None or self.viewer_state.x_att is None or self.attribute is None:
            self._profile = None, None
            return

        # Check what pixel axis in the current dataset x_att corresponds to
        pix_cid = is_convertible_to_single_pixel_cid(self.layer,
                                                     self.viewer_state.x_att)

        if pix_cid is None:
            self._profile = None, None
            return

        # If we get here, then x_att does correspond to a single pixel axis in
        # the cube, so we now prepare a list of axes to collapse over.
        axes = tuple(i for i in range(self.layer.ndim) if i != pix_cid.axis)

        # We now get the y values for the data

        # TODO: in future we should optimize the case where the mask is much
        # smaller than the data to just average the relevant 'spaxels' in the
        # data rather than collapsing the whole cube.

        try:
            if isinstance(self.layer, Data):
                data = self.layer
                data_values = data[self.attribute]
            else:
                data = self.layer.data
                if isinstance(self.layer.subset_state, SliceSubsetState):
                    data_values = self.layer.subset_state.to_array(
                        self.layer.data, self.attribute)
                else:
                    # We need to force a copy *and* convert to float just in case
                    data_values = np.array(data[self.attribute], dtype=float)
                    mask = self.layer.to_mask()
                    if np.sum(mask) == 0:
                        self._profile = [], []
                        return
                    data_values[~mask] = np.nan
        except IncompatibleAttribute:
            self._profile = None, None
            return

        # Collapse along all dimensions except x_att
        if self.layer.ndim > 1:
            with warnings.catch_warnings():
                warnings.simplefilter("ignore", category=RuntimeWarning)
                profile_values = self.viewer_state.function(data_values,
                                                            axis=axes)
        else:
            profile_values = data_values

        # Finally, we get the coordinate values for the requested axis
        axis_view = [0] * data.ndim
        axis_view[pix_cid.axis] = slice(None)
        axis_values = data[self.viewer_state.x_att, axis_view]

        with delay_callback(self, 'v_min', 'v_max'):
            self._profile = axis_values, profile_values
            self.v_min = nanmin(profile_values)
            self.v_max = nanmax(profile_values)
コード例 #39
0
ファイル: state.py プロジェクト: DPoloski/glue
class ScatterViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for a scatter viewer.
    """

    x_att = DDSCProperty(docstring='The attribute to show on the x-axis',
                         default_index=0)
    y_att = DDSCProperty(docstring='The attribute to show on the y-axis',
                         default_index=1)
    dpi = DDCProperty(
        72,
        docstring=
        'The resolution (in dots per inch) of density maps, if present')

    def __init__(self, **kwargs):

        super(ScatterViewerState, self).__init__()

        self.limits_cache = {}

        self.x_lim_helper = StateAttributeLimitsHelper(
            self,
            attribute='x_att',
            lower='x_min',
            upper='x_max',
            log='x_log',
            margin=0.04,
            limits_cache=self.limits_cache)

        self.y_lim_helper = StateAttributeLimitsHelper(
            self,
            attribute='y_att',
            lower='y_min',
            upper='y_max',
            log='y_log',
            margin=0.04,
            limits_cache=self.limits_cache)

        self.add_callback('layers', self._layers_changed)

        self.x_att_helper = ComponentIDComboHelper(self,
                                                   'x_att',
                                                   pixel_coord=True,
                                                   world_coord=True)
        self.y_att_helper = ComponentIDComboHelper(self,
                                                   'y_att',
                                                   pixel_coord=True,
                                                   world_coord=True)

        self.update_from_dict(kwargs)

        self.add_callback('x_log', self._reset_x_limits)
        self.add_callback('y_log', self._reset_y_limits)

    def _reset_x_limits(self, *args):
        if self.x_att is None:
            return
        self.x_lim_helper.percentile = 100
        self.x_lim_helper.update_values(force=True)

    def _reset_y_limits(self, *args):
        if self.y_att is None:
            return
        self.y_lim_helper.percentile = 100
        self.y_lim_helper.update_values(force=True)

    def reset_limits(self):
        self._reset_x_limits()
        self._reset_y_limits()

    def flip_x(self):
        """
        Flip the x_min/x_max limits.
        """
        self.x_lim_helper.flip_limits()

    def flip_y(self):
        """
        Flip the y_min/y_max limits.
        """
        self.y_lim_helper.flip_limits()

    @property
    def x_categories(self):
        return self._categories(self.x_att)

    @property
    def y_categories(self):
        return self._categories(self.y_att)

    def _categories(self, cid):

        categories = []

        for layer_state in self.layers:

            if isinstance(layer_state.layer, BaseData):
                layer = layer_state.layer
            else:
                layer = layer_state.layer.data

            try:
                if layer.data.get_kind(cid) == 'categorical':
                    categories.append(layer.data.get_data(cid).categories)
            except IncompatibleAttribute:
                pass

        if len(categories) == 0:
            return None
        else:
            return np.unique(np.hstack(categories))

    @property
    def x_kinds(self):
        return self._component_kinds(self.x_att)

    @property
    def y_kinds(self):
        return self._component_kinds(self.y_att)

    def _component_kinds(self, cid):

        # Construct list of component kinds over all layers

        kinds = set()

        for layer_state in self.layers:

            if isinstance(layer_state.layer, BaseData):
                layer = layer_state.layer
            else:
                layer = layer_state.layer.data

            try:
                kinds.add(layer.data.get_kind(cid))
            except IncompatibleAttribute:
                pass

        return kinds

    def _layers_changed(self, *args):

        layers_data = self.layers_data
        layers_data_cache = getattr(self, '_layers_data_cache', [])

        if layers_data == layers_data_cache:
            return

        self.x_att_helper.set_multiple_data(self.layers_data)
        self.y_att_helper.set_multiple_data(self.layers_data)

        self._layers_data_cache = layers_data
コード例 #40
0
class ProfileViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for a Profile viewer.
    """

    reference_data = DDSCProperty(
        docstring='The dataset that is used to define the '
        'available pixel/world components, and '
        'which defines the coordinate frame in '
        'which the images are shown')

    x_att = DDSCProperty(docstring='The data component to use for the x-axis '
                         'of the profile (should be a pixel component)')

    function = DDSCProperty(
        docstring='The function to use for collapsing data')

    normalize = DDCProperty(False,
                            docstring='Whether to normalize all profiles '
                            'to the [0:1] range')

    # TODO: add function to use

    def __init__(self, **kwargs):

        super(ProfileViewerState, self).__init__()

        self.ref_data_helper = ManualDataComboHelper(self, 'reference_data')

        self.x_lim_helper = StateAttributeLimitsHelper(self,
                                                       'x_att',
                                                       lower='x_min',
                                                       upper='x_max')

        self.add_callback('layers', self._layers_changed)
        self.add_callback('reference_data', self._reference_data_changed)
        self.add_callback('normalize', self._reset_y_limits)

        self.x_att_helper = ComponentIDComboHelper(self,
                                                   'x_att',
                                                   numeric=False,
                                                   categorical=False,
                                                   world_coord=True,
                                                   pixel_coord=True)

        ProfileViewerState.function.set_choices(self, list(FUNCTIONS))
        ProfileViewerState.function.set_display_func(self, FUNCTIONS.get)

        self.update_from_dict(kwargs)

    def _update_combo_ref_data(self):
        self.ref_data_helper.set_multiple_data(self.layers_data)

    def reset_limits(self):
        with delay_callback(self, 'x_min', 'x_max', 'y_min', 'y_max'):
            self.x_lim_helper.percentile = 100
            self.x_lim_helper.update_values(force=True)
            self._reset_y_limits()

    def _reset_y_limits(self, *event):
        if self.normalize:
            self.y_min = -0.1
            self.y_max = +1.1

    def _update_priority(self, name):
        if name == 'layers':
            return 2
        elif name.endswith(('_min', '_max')):
            return 0
        else:
            return 1

    def flip_x(self):
        """
        Flip the x_min/x_max limits.
        """
        self.x_lim_helper.flip_limits()

    @defer_draw
    def _layers_changed(self, *args):
        self._update_combo_ref_data()

    @defer_draw
    def _reference_data_changed(self, *args):
        if self.reference_data is None:
            self.x_att_helper.set_multiple_data([])
        else:
            self.x_att_helper.set_multiple_data([self.reference_data])
            if type(self.reference_data.coords) == Coordinates:
                self.x_att = self.reference_data.pixel_component_ids[0]
            else:
                self.x_att = self.reference_data.world_component_ids[0]
コード例 #41
0
ファイル: viewer_state.py プロジェクト: glue-viz/glue-wwt
class WWTDataViewerState(ViewerState):

    mode = SelectionCallbackProperty(default_index=0)
    frame = SelectionCallbackProperty(default_index=0)

    lon_att = SelectionCallbackProperty(default_index=0)
    lat_att = SelectionCallbackProperty(default_index=1)
    alt_att = SelectionCallbackProperty(default_index=0)
    alt_unit = SelectionCallbackProperty(default_index=0)
    alt_type = SelectionCallbackProperty(default_index=0)

    foreground = SelectionCallbackProperty(default_index=1)
    foreground_opacity = CallbackProperty(1)
    background = SelectionCallbackProperty(default_index=8)

    galactic = CallbackProperty(False)

    layers = ListCallbackProperty()

    # For now we need to include this here otherwise when loading files, the
    # imagery layers are only available asynchronously and the session loading
    # fails.
    imagery_layers = ListCallbackProperty()

    def __init__(self, **kwargs):

        super(WWTDataViewerState, self).__init__()

        WWTDataViewerState.mode.set_choices(self,
                                            ['Sky'] + MODES_3D + MODES_BODIES)
        WWTDataViewerState.frame.set_choices(self, CELESTIAL_FRAMES)
        WWTDataViewerState.alt_unit.set_choices(self,
                                                [str(x) for x in ALT_UNITS])
        WWTDataViewerState.alt_type.set_choices(self, ALT_TYPES)

        self.add_callback('imagery_layers', self._update_imagery_layers)

        self.lon_att_helper = ComponentIDComboHelper(self,
                                                     'lon_att',
                                                     numeric=True,
                                                     categorical=False,
                                                     world_coord=True,
                                                     pixel_coord=False)

        self.lat_att_helper = ComponentIDComboHelper(self,
                                                     'lat_att',
                                                     numeric=True,
                                                     categorical=False,
                                                     world_coord=True,
                                                     pixel_coord=False)

        self.alt_att_helper = ComponentIDComboHelper(self,
                                                     'alt_att',
                                                     numeric=True,
                                                     categorical=False,
                                                     world_coord=True,
                                                     pixel_coord=False,
                                                     none='None')

        self.add_callback('layers', self._on_layers_changed)
        self._on_layers_changed()

        self.update_from_dict(kwargs)

    def _on_layers_changed(self, *args):
        self.lon_att_helper.set_multiple_data(self.layers_data)
        self.lat_att_helper.set_multiple_data(self.layers_data)
        self.alt_att_helper.set_multiple_data(self.layers_data)

    def _update_imagery_layers(self, *args):
        WWTDataViewerState.foreground.set_choices(self, self.imagery_layers)
        WWTDataViewerState.background.set_choices(self, self.imagery_layers)

    def _update_priority(self, name):
        if name == 'layers':
            return 2
        elif name == 'imagery_layers':
            return 1
        else:
            return 0
コード例 #42
0
ファイル: state.py プロジェクト: PennyQ/glue
class ScatterLayerState(MatplotlibLayerState):
    """
    A state class that includes all the attributes for layers in a scatter plot.
    """

    # General properties

    style = DDSCProperty(docstring="The layer style")
    size = DDCProperty(docstring="The size of the markers")

    # Scatter layer

    cmap_mode = DDSCProperty(docstring="Whether to use color to encode an attribute")
    cmap_att = DDSCProperty(docstring="The attribute to use for the color")
    cmap_vmin = DDCProperty(docstring="The lower level for the colormap")
    cmap_vmax = DDCProperty(docstring="The upper level for the colormap")
    cmap = DDCProperty(docstring="The colormap to use (when in colormap mode)")

    size_mode = DDSCProperty(docstring="Whether to use size to encode an attribute")
    size_att = DDSCProperty(docstring="The attribute to use for the size")
    size_vmin = DDCProperty(docstring="The lower level for the size mapping")
    size_vmax = DDCProperty(docstring="The upper level for the size mapping")
    size_scaling = DDCProperty(1, docstring="Relative scaling of the size")

    xerr_visible = DDCProperty(False, docstring="Whether to show x error bars")
    yerr_visible = DDCProperty(False, docstring="Whether to show y error bars")
    xerr_att = DDSCProperty(docstring="The attribute to use for the x error bars")
    yerr_att = DDSCProperty(docstring="The attribute to use for the y error bars")

    # Line plot layer

    linewidth = DDCProperty(1, docstring="The line width")
    linestyle = DDSCProperty(docstring="The line style")

    def __init__(self, viewer_state=None, layer=None, **kwargs):

        super(ScatterLayerState, self).__init__(viewer_state=viewer_state, layer=layer)

        self.limits_cache = {}

        self.cmap_lim_helper = StateAttributeLimitsHelper(self, attribute='cmap_att',
                                                          lower='cmap_vmin', upper='cmap_vmax',
                                                          limits_cache=self.limits_cache)

        self.size_lim_helper = StateAttributeLimitsHelper(self, attribute='size_att',
                                                          lower='size_vmin', upper='size_vmax',
                                                          limits_cache=self.limits_cache)

        self.cmap_att_helper = ComponentIDComboHelper(self, 'cmap_att',
                                                      numeric=True, categorical=False)

        self.size_att_helper = ComponentIDComboHelper(self, 'size_att',
                                                      numeric=True, categorical=False)

        self.xerr_att_helper = ComponentIDComboHelper(self, 'xerr_att',
                                                      numeric=True, categorical=False)

        self.yerr_att_helper = ComponentIDComboHelper(self, 'yerr_att',
                                                      numeric=True, categorical=False)

        ScatterLayerState.style.set_choices(self, ['Scatter', 'Line'])
        ScatterLayerState.cmap_mode.set_choices(self, ['Fixed', 'Linear'])
        ScatterLayerState.size_mode.set_choices(self, ['Fixed', 'Linear'])

        linestyle_display = {'solid': '–––––––',
                             'dashed': '– – – – –',
                             'dotted': '· · · · · · · ·',
                             'dashdot': '– · – · – ·'}

        ScatterLayerState.linestyle.set_choices(self, ['solid', 'dashed', 'dotted', 'dashdot'])
        ScatterLayerState.linestyle.set_display_func(self, linestyle_display.get)

        self.add_callback('layer', self._on_layer_change)
        if layer is not None:
            self._on_layer_change()

        self.cmap = colormaps.members[0][1]

        self.size = self.layer.style.markersize

        self._sync_size = keep_in_sync(self, 'size', self.layer.style, 'markersize')

        self.update_from_dict(kwargs)

    def _on_layer_change(self, layer=None):

        with delay_callback(self, 'cmap_vmin', 'cmap_vmax', 'size_vmin', 'size_vmax'):

            if self.layer is None:
                self.cmap_att_helper.set_multiple_data([])
                self.size_att_helper.set_multiple_data([])
            else:
                self.cmap_att_helper.set_multiple_data([self.layer])
                self.size_att_helper.set_multiple_data([self.layer])

            if self.layer is None:
                self.xerr_att_helper.set_multiple_data([])
                self.yerr_att_helper.set_multiple_data([])
            else:
                self.xerr_att_helper.set_multiple_data([self.layer])
                self.yerr_att_helper.set_multiple_data([self.layer])

    def flip_cmap(self):
        """
        Flip the cmap_vmin/cmap_vmax limits.
        """
        self.cmap_lim_helper.flip_limits()

    def flip_size(self):
        """
        Flip the size_vmin/size_vmax limits.
        """
        self.size_lim_helper.flip_limits()
コード例 #43
0
class DendrogramViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for a dendrogram viewer.
    """

    height_att = DDSCProperty()
    parent_att = DDSCProperty()
    order_att = DDSCProperty()
    y_log = DDCProperty(False)
    select_substruct = DDCProperty(True)
    reference_data = DDCProperty()

    _layout = DDCProperty()

    def __init__(self, **kwargs):

        super(DendrogramViewerState, self).__init__()

        self.add_callback('layers', self._layers_changed)

        self.height_att_helper = ComponentIDComboHelper(self, 'height_att')
        self.parent_att_helper = ComponentIDComboHelper(self, 'parent_att')
        self.order_att_helper = ComponentIDComboHelper(self, 'order_att')

        self.add_callback('height_att', self._update_layout)
        self.add_callback('parent_att', self._update_layout)
        self.add_callback('order_att', self._update_layout)

        self.add_callback('reference_data', self._on_reference_data_change)

        self.update_from_dict(kwargs)

    def _on_reference_data_change(self, data):

        if self.reference_data is None:
            return

        self.height_att = self.reference_data.find_component_id('height')
        self.parent_att = self.reference_data.find_component_id('parent')
        self.order_att = self.height_att

    def _update_layout(self, att):
        if self.height_att is None or self.parent_att is None or self.order_att is None or self.reference_data is None:
            self._layout = None
        else:
            height = self.reference_data[self.height_att].ravel()
            parent = self.reference_data[self.parent_att].astype(int).ravel()
            order = self.reference_data[self.order_att].ravel()
            x, y = dendrogram_layout(parent, height, order)
            self._layout = Layout(x, y)

    def _layers_changed(self, *args):

        layers_data = self.layers_data
        layers_data_cache = getattr(self, '_layers_data_cache', [])

        if layers_data == layers_data_cache:
            return

        self.height_att_helper.set_multiple_data(layers_data)
        self.parent_att_helper.set_multiple_data(layers_data)
        self.order_att_helper.set_multiple_data(layers_data)

        for layer in layers_data:
            if isinstance(layer, Data):
                self.reference_data = layer
                break

        self._layers_data_cache = layers_data
コード例 #44
0
ファイル: state.py プロジェクト: PennyQ/glue
class ScatterViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for a scatter viewer.
    """

    x_att = DDSCProperty(docstring='The attribute to show on the x-axis', default_index=0)
    y_att = DDSCProperty(docstring='The attribute to show on the y-axis', default_index=1)

    def __init__(self, **kwargs):

        super(ScatterViewerState, self).__init__()

        self.limits_cache = {}

        self.x_lim_helper = StateAttributeLimitsHelper(self, attribute='x_att',
                                                       lower='x_min', upper='x_max',
                                                       log='x_log',
                                                       limits_cache=self.limits_cache)

        self.y_lim_helper = StateAttributeLimitsHelper(self, attribute='y_att',
                                                       lower='y_min', upper='y_max',
                                                       log='y_log',
                                                       limits_cache=self.limits_cache)

        self.add_callback('layers', self._layers_changed)

        self.x_att_helper = ComponentIDComboHelper(self, 'x_att')
        self.y_att_helper = ComponentIDComboHelper(self, 'y_att')

        self.update_from_dict(kwargs)

    def _update_priority(self, name):
        if name == 'layers':
            return 2
        elif name.endswith('_log'):
            return 0.5
        elif name.endswith(('_min', '_max')):
            return 0
        else:
            return 1

    def flip_x(self):
        """
        Flip the x_min/x_max limits.
        """
        self.x_lim_helper.flip_limits()

    def flip_y(self):
        """
        Flip the y_min/y_max limits.
        """
        self.y_lim_helper.flip_limits()

    def _get_x_components(self):
        return self._get_components(self.x_att)

    def _get_y_components(self):
        return self._get_components(self.y_att)

    def _get_components(self, cid):

        # Construct list of components over all layers

        components = []

        for layer_state in self.layers:

            if isinstance(layer_state.layer, Data):
                layer = layer_state.layer
            else:
                layer = layer_state.layer.data

            try:
                components.append(layer.data.get_component(cid))
            except IncompatibleAttribute:
                pass

        return components

    def _layers_changed(self, *args):

        layers_data = self.layers_data
        layers_data_cache = getattr(self, '_layers_data_cache', [])

        if layers_data == layers_data_cache:
            return

        self.x_att_helper.set_multiple_data(self.layers_data)
        self.y_att_helper.set_multiple_data(self.layers_data)

        self._layers_data_cache = layers_data
コード例 #45
0
ファイル: state.py プロジェクト: shreyasbapat/glue
class ImageLayerState(BaseImageLayerState):
    """
    A state class that includes all the attributes for data layers in an image plot.
    """

    attribute = DDSCProperty(docstring='The attribute shown in the layer')
    v_min = DDCProperty(docstring='The lower level shown')
    v_max = DDCProperty(docstring='The upper level shown')
    percentile = DDSCProperty(docstring='The percentile value used to '
                              'automatically calculate levels')
    contrast = DDCProperty(1, docstring='The contrast of the layer')
    bias = DDCProperty(0.5,
                       docstring='A constant value that is added to the '
                       'layer before rendering')
    cmap = DDCProperty(docstring='The colormap used to render the layer')
    stretch = DDSCProperty(docstring='The stretch used to render the layer, '
                           'which should be one of ``linear``, '
                           '``sqrt``, ``log``, or ``arcsinh``')
    global_sync = DDCProperty(True,
                              docstring='Whether the color and transparency '
                              'should be synced with the global '
                              'color and transparency for the data')

    def __init__(self, layer=None, viewer_state=None, **kwargs):

        super(ImageLayerState, self).__init__(layer=layer,
                                              viewer_state=viewer_state)

        self.attribute_lim_helper = StateAttributeLimitsHelper(
            self,
            attribute='attribute',
            percentile='percentile',
            lower='v_min',
            upper='v_max')

        self.attribute_att_helper = ComponentIDComboHelper(self,
                                                           'attribute',
                                                           numeric=True,
                                                           categorical=False)

        percentile_display = {
            100: 'Min/Max',
            99.5: '99.5%',
            99: '99%',
            95: '95%',
            90: '90%',
            'Custom': 'Custom'
        }

        ImageLayerState.percentile.set_choices(
            self, [100, 99.5, 99, 95, 90, 'Custom'])
        ImageLayerState.percentile.set_display_func(self,
                                                    percentile_display.get)

        stretch_display = {
            'linear': 'Linear',
            'sqrt': 'Square Root',
            'arcsinh': 'Arcsinh',
            'log': 'Logarithmic'
        }

        ImageLayerState.stretch.set_choices(
            self, ['linear', 'sqrt', 'arcsinh', 'log'])
        ImageLayerState.stretch.set_display_func(self, stretch_display.get)

        self.add_callback('global_sync', self._update_syncing)
        self.add_callback('layer', self._update_attribute)

        self._update_syncing()

        if layer is not None:
            self._update_attribute()

        self.update_from_dict(kwargs)

        if self.cmap is None:
            self.cmap = colormaps.members[0][1]

    def _update_attribute(self, *args):
        if self.layer is not None:
            self.attribute_att_helper.set_multiple_data([self.layer])
            self.attribute = self.layer.main_components[0]

    def _update_priority(self, name):
        if name == 'layer':
            return 3
        elif name == 'attribute':
            return 2
        elif name == 'global_sync':
            return 1.5
        elif name.endswith(('_min', '_max')):
            return 0
        else:
            return 1

    def _update_syncing(self, *args):
        if self.global_sync:
            self._sync_color.enable_syncing()
            self._sync_alpha.enable_syncing()
        else:
            self._sync_color.disable_syncing()
            self._sync_alpha.disable_syncing()

    def _get_image(self, view=None):
        return self.layer[self.attribute, view]

    def flip_limits(self):
        """
        Flip the image levels.
        """
        self.attribute_lim_helper.flip_limits()

    def reset_contrast_bias(self):
        with delay_callback(self, 'contrast', 'bias'):
            self.contrast = 1
            self.bias = 0.5
コード例 #46
0
ファイル: state.py プロジェクト: sergiopasra/glue
class ProfileViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for a Profile viewer.
    """

    reference_data = DDSCProperty(docstring='The dataset that is used to define the '
                                            'available pixel/world components, and '
                                            'which defines the coordinate frame in '
                                            'which the images are shown')

    x_att = DDSCProperty(docstring='The data component to use for the x-axis '
                                   'of the profile (should be a pixel component)')

    function = DDSCProperty(docstring='The function to use for collapsing data')

    normalize = DDCProperty(False, docstring='Whether to normalize all profiles '
                                             'to the [0:1] range')

    # TODO: add function to use

    def __init__(self, **kwargs):

        super(ProfileViewerState, self).__init__()

        self.ref_data_helper = ManualDataComboHelper(self, 'reference_data')

        self.x_lim_helper = StateAttributeLimitsHelper(self, 'x_att', lower='x_min',
                                                       upper='x_max')

        self.add_callback('layers', self._layers_changed)
        self.add_callback('reference_data', self._reference_data_changed)
        self.add_callback('normalize', self._reset_y_limits)

        self.x_att_helper = ComponentIDComboHelper(self, 'x_att',
                                                   numeric=False, categorical=False,
                                                   world_coord=True, pixel_coord=True)

        ProfileViewerState.function.set_choices(self, list(FUNCTIONS))
        ProfileViewerState.function.set_display_func(self, FUNCTIONS.get)

        self.update_from_dict(kwargs)

    def _update_combo_ref_data(self):
        self.ref_data_helper.set_multiple_data(self.layers_data)

    def reset_limits(self):
        with delay_callback(self, 'x_min', 'x_max', 'y_min', 'y_max'):
            self.x_lim_helper.percentile = 100
            self.x_lim_helper.update_values(force=True)
            self._reset_y_limits()

    def _reset_y_limits(self, *event):
        if self.normalize:
            self.y_min = -0.1
            self.y_max = +1.1

    def flip_x(self):
        """
        Flip the x_min/x_max limits.
        """
        self.x_lim_helper.flip_limits()

    @defer_draw
    def _layers_changed(self, *args):
        self._update_combo_ref_data()

    @defer_draw
    def _reference_data_changed(self, *args):
        if self.reference_data is None:
            self.x_att_helper.set_multiple_data([])
        else:
            self.x_att_helper.set_multiple_data([self.reference_data])
            if type(self.reference_data.coords) == Coordinates:
                self.x_att = self.reference_data.pixel_component_ids[0]
            else:
                self.x_att = self.reference_data.world_component_ids[0]
コード例 #47
0
ファイル: state.py プロジェクト: sarahb55/glue
class ScatterLayerState(MatplotlibLayerState):
    """
    A state class that includes all the attributes for layers in a scatter plot.
    """

    # Color

    cmap_mode = DDSCProperty(
        docstring="Whether to use color to encode an attribute")
    cmap_att = DDSCProperty(docstring="The attribute to use for the color")
    cmap_vmin = DDCProperty(docstring="The lower level for the colormap")
    cmap_vmax = DDCProperty(docstring="The upper level for the colormap")
    cmap = DDCProperty(docstring="The colormap to use (when in colormap mode)")

    # Points

    points_mode = DDSCProperty(
        docstring='Whether to use markers or a density map')

    # Markers

    markers_visible = DDCProperty(True, docstring="Whether to show markers")
    size = DDCProperty(docstring="The size of the markers")
    size_mode = DDSCProperty(
        docstring="Whether to use size to encode an attribute")
    size_att = DDSCProperty(docstring="The attribute to use for the size")
    size_vmin = DDCProperty(docstring="The lower level for the size mapping")
    size_vmax = DDCProperty(docstring="The upper level for the size mapping")
    size_scaling = DDCProperty(1, docstring="Relative scaling of the size")
    fill = DDCProperty(True, docstring="Whether to fill the markers")

    # Density map

    density_map = DDCProperty(
        False, docstring="Whether to show the points as a density map")
    stretch = DDSCProperty(default='log',
                           docstring='The stretch used to render the layer, '
                           'which should be one of ``linear``, '
                           '``sqrt``, ``log``, or ``arcsinh``')
    density_contrast = DDCProperty(
        1, docstring="The dynamic range of the density map")

    # Note that we keep the dpi in the viewer state since we want it to always
    # be in sync between layers.

    # Line

    line_visible = DDCProperty(
        False, docstring="Whether to show a line connecting all positions")
    linewidth = DDCProperty(1, docstring="The line width")
    linestyle = DDSCProperty(docstring="The line style")

    # Errorbars

    xerr_visible = DDCProperty(False, docstring="Whether to show x error bars")
    yerr_visible = DDCProperty(False, docstring="Whether to show y error bars")
    xerr_att = DDSCProperty(
        docstring="The attribute to use for the x error bars")
    yerr_att = DDSCProperty(
        docstring="The attribute to use for the y error bars")

    # Vectors

    vector_visible = DDCProperty(False,
                                 docstring="Whether to show vector plot")
    vx_att = DDSCProperty(
        docstring="The attribute to use for the x vector arrow")
    vy_att = DDSCProperty(
        docstring="The attribute to use for the y vector arrow")
    vector_arrowhead = DDCProperty(False,
                                   docstring="Whether to show vector arrow")
    vector_mode = DDSCProperty(
        default_index=0,
        docstring="Whether to plot the vectors in cartesian or polar mode")
    vector_origin = DDSCProperty(
        default_index=1,
        docstring=
        "Whether to place the vector so that the origin is at the tail, middle, or tip"
    )
    vector_scaling = DDCProperty(
        1, docstring="The relative scaling of the arrow length")

    def __init__(self, viewer_state=None, layer=None, **kwargs):

        super(ScatterLayerState, self).__init__(viewer_state=viewer_state,
                                                layer=layer)

        self.limits_cache = {}

        self.cmap_lim_helper = StateAttributeLimitsHelper(
            self,
            attribute='cmap_att',
            lower='cmap_vmin',
            upper='cmap_vmax',
            limits_cache=self.limits_cache)

        self.size_lim_helper = StateAttributeLimitsHelper(
            self,
            attribute='size_att',
            lower='size_vmin',
            upper='size_vmax',
            limits_cache=self.limits_cache)

        self.cmap_att_helper = ComponentIDComboHelper(self,
                                                      'cmap_att',
                                                      numeric=True,
                                                      categorical=False)

        self.size_att_helper = ComponentIDComboHelper(self,
                                                      'size_att',
                                                      numeric=True,
                                                      categorical=False)

        self.xerr_att_helper = ComponentIDComboHelper(self,
                                                      'xerr_att',
                                                      numeric=True,
                                                      categorical=False)

        self.yerr_att_helper = ComponentIDComboHelper(self,
                                                      'yerr_att',
                                                      numeric=True,
                                                      categorical=False)

        self.vx_att_helper = ComponentIDComboHelper(self,
                                                    'vx_att',
                                                    numeric=True,
                                                    categorical=False)

        self.vy_att_helper = ComponentIDComboHelper(self,
                                                    'vy_att',
                                                    numeric=True,
                                                    categorical=False)

        points_mode_display = {
            'auto': 'Density map or markers (auto)',
            'markers': 'Markers',
            'density': 'Density map'
        }

        ScatterLayerState.points_mode.set_choices(
            self, ['auto', 'markers', 'density'])
        ScatterLayerState.points_mode.set_display_func(self,
                                                       points_mode_display.get)

        self.add_callback('points_mode', self._update_density_map_mode)

        ScatterLayerState.cmap_mode.set_choices(self, ['Fixed', 'Linear'])
        ScatterLayerState.size_mode.set_choices(self, ['Fixed', 'Linear'])

        linestyle_display = {
            'solid': '–––––––',
            'dashed': '– – – – –',
            'dotted': '· · · · · · · ·',
            'dashdot': '– · – · – ·'
        }

        ScatterLayerState.linestyle.set_choices(
            self, ['solid', 'dashed', 'dotted', 'dashdot'])
        ScatterLayerState.linestyle.set_display_func(self,
                                                     linestyle_display.get)

        ScatterLayerState.vector_mode.set_choices(self, ['Cartesian', 'Polar'])

        vector_origin_display = {
            'tail': 'Tail of vector',
            'middle': 'Middle of vector',
            'tip': 'Tip of vector'
        }

        ScatterLayerState.vector_origin.set_choices(self,
                                                    ['tail', 'middle', 'tip'])
        ScatterLayerState.vector_origin.set_display_func(
            self, vector_origin_display.get)

        stretch_display = {
            'linear': 'Linear',
            'sqrt': 'Square Root',
            'arcsinh': 'Arcsinh',
            'log': 'Logarithmic'
        }

        ScatterLayerState.stretch.set_choices(
            self, ['linear', 'sqrt', 'arcsinh', 'log'])
        ScatterLayerState.stretch.set_display_func(self, stretch_display.get)

        self.add_callback('layer', self._on_layer_change)
        if layer is not None:
            self._on_layer_change()

        self.cmap = colormaps.members[0][1]

        self.size = self.layer.style.markersize

        self._sync_size = keep_in_sync(self, 'size', self.layer.style,
                                       'markersize')

        self.update_from_dict(kwargs)

    def _on_layer_change(self, layer=None):

        with delay_callback(self, 'cmap_vmin', 'cmap_vmax', 'size_vmin',
                            'size_vmax', 'density_map'):

            self._update_density_map_mode()

            if self.layer is None:
                self.cmap_att_helper.set_multiple_data([])
                self.size_att_helper.set_multiple_data([])
            else:
                self.cmap_att_helper.set_multiple_data([self.layer])
                self.size_att_helper.set_multiple_data([self.layer])

            if self.layer is None:
                self.xerr_att_helper.set_multiple_data([])
                self.yerr_att_helper.set_multiple_data([])
            else:
                self.xerr_att_helper.set_multiple_data([self.layer])
                self.yerr_att_helper.set_multiple_data([self.layer])

            if self.layer is None:
                self.vx_att_helper.set_multiple_data([])
                self.vy_att_helper.set_multiple_data([])
            else:
                self.vx_att_helper.set_multiple_data([self.layer])
                self.vy_att_helper.set_multiple_data([self.layer])

    def _update_density_map_mode(self, *args):
        if self.points_mode == 'auto':
            if self.layer.size > 100000:
                self.density_map = True
            else:
                self.density_map = False
        elif self.points_mode == 'density':
            self.density_map = True
        else:
            self.density_map = False

    def flip_cmap(self):
        """
        Flip the cmap_vmin/cmap_vmax limits.
        """
        self.cmap_lim_helper.flip_limits()

    def flip_size(self):
        """
        Flip the size_vmin/size_vmax limits.
        """
        self.size_lim_helper.flip_limits()

    @property
    def cmap_name(self):
        return colormaps.name_from_cmap(self.cmap)

    @classmethod
    def __setgluestate__(cls, rec, context):
        # Patch for glue files produced with glue v0.11
        if 'style' in rec['values']:
            style = context.object(rec['values'].pop('style'))
            if style == 'Scatter':
                rec['values']['markers_visible'] = True
                rec['values']['line_visible'] = False
            elif style == 'Line':
                rec['values']['markers_visible'] = False
                rec['values']['line_visible'] = True
        return super(ScatterLayerState, cls).__setgluestate__(rec, context)
コード例 #48
0
ファイル: state.py プロジェクト: glue-viz/glue-wwt
class WWTDataViewerState(ViewerState):

    mode = SelectionCallbackProperty(default_index=0)
    frame = SelectionCallbackProperty(default_index=0)

    lon_att = SelectionCallbackProperty(default_index=0)
    lat_att = SelectionCallbackProperty(default_index=1)
    alt_att = SelectionCallbackProperty(default_index=0)
    alt_unit = SelectionCallbackProperty(default_index=0)
    alt_type = SelectionCallbackProperty(default_index=0)

    foreground = SelectionCallbackProperty(default_index=1)
    foreground_opacity = CallbackProperty(1)
    background = SelectionCallbackProperty(default_index=8)

    galactic = CallbackProperty(False)

    layers = ListCallbackProperty()

    # For now we need to include this here otherwise when loading files, the
    # imagery layers are only available asynchronously and the session loading
    # fails.
    imagery_layers = ListCallbackProperty()

    def __init__(self, **kwargs):

        super(WWTDataViewerState, self).__init__()

        WWTDataViewerState.mode.set_choices(self, ['Sky'] + MODES_3D + MODES_BODIES)
        WWTDataViewerState.frame.set_choices(self, CELESTIAL_FRAMES)
        WWTDataViewerState.alt_unit.set_choices(self, [str(x) for x in ALT_UNITS])
        WWTDataViewerState.alt_type.set_choices(self, ALT_TYPES)

        self.add_callback('imagery_layers', self._update_imagery_layers)

        self.lon_att_helper = ComponentIDComboHelper(self, 'lon_att',
                                                     numeric=True,
                                                     categorical=False,
                                                     world_coord=True,
                                                     pixel_coord=False)

        self.lat_att_helper = ComponentIDComboHelper(self, 'lat_att',
                                                     numeric=True,
                                                     categorical=False,
                                                     world_coord=True,
                                                     pixel_coord=False)

        self.alt_att_helper = ComponentIDComboHelper(self, 'alt_att',
                                                     numeric=True,
                                                     categorical=False,
                                                     world_coord=True,
                                                     pixel_coord=False,
                                                     none='None')

        self.add_callback('layers', self._on_layers_changed)
        self._on_layers_changed()

        self.update_from_dict(kwargs)

    def _on_layers_changed(self, *args):
        self.lon_att_helper.set_multiple_data(self.layers_data)
        self.lat_att_helper.set_multiple_data(self.layers_data)
        self.alt_att_helper.set_multiple_data(self.layers_data)

    def _update_imagery_layers(self, *args):
        WWTDataViewerState.foreground.set_choices(self, self.imagery_layers)
        WWTDataViewerState.background.set_choices(self, self.imagery_layers)

    def _update_priority(self, name):
        if name == 'layers':
            return 2
        elif name == 'imagery_layers':
            return 1
        else:
            return 0
コード例 #49
0
ファイル: state.py プロジェクト: sergiopasra/glue
class DendrogramViewerState(MatplotlibDataViewerState):
    """
    A state class that includes all the attributes for a dendrogram viewer.
    """

    height_att = DDSCProperty()
    parent_att = DDSCProperty()
    order_att = DDSCProperty()
    y_log = DDCProperty(False)
    select_substruct = DDCProperty(True)
    reference_data = DDCProperty()

    _layout = DDCProperty()

    def __init__(self, **kwargs):

        super(DendrogramViewerState, self).__init__()

        self.add_callback('layers', self._layers_changed)

        self.height_att_helper = ComponentIDComboHelper(self, 'height_att')
        self.parent_att_helper = ComponentIDComboHelper(self, 'parent_att')
        self.order_att_helper = ComponentIDComboHelper(self, 'order_att')

        self.add_callback('height_att', self._update_layout)
        self.add_callback('parent_att', self._update_layout)
        self.add_callback('order_att', self._update_layout)

        self.add_callback('reference_data', self._on_reference_data_change)

        self.update_from_dict(kwargs)

    def _on_reference_data_change(self, data):

        if self.reference_data is None:
            return

        self.height_att = self.reference_data.find_component_id('height')
        self.parent_att = self.reference_data.find_component_id('parent')
        self.order_att = self.height_att

    def _update_layout(self, att):
        if self.height_att is None or self.parent_att is None or self.order_att is None or self.reference_data is None:
            self._layout = None
        else:
            height = self.reference_data[self.height_att].ravel()
            parent = self.reference_data[self.parent_att].astype(int).ravel()
            order = self.reference_data[self.order_att].ravel()
            x, y = dendrogram_layout(parent, height, order)
            self._layout = Layout(x, y)

    def _layers_changed(self, *args):

        layers_data = self.layers_data
        layers_data_cache = getattr(self, '_layers_data_cache', [])

        if layers_data == layers_data_cache:
            return

        self.height_att_helper.set_multiple_data(layers_data)
        self.parent_att_helper.set_multiple_data(layers_data)
        self.order_att_helper.set_multiple_data(layers_data)

        for layer in layers_data:
            if isinstance(layer, Data):
                self.reference_data = layer
                break

        self._layers_data_cache = layers_data
コード例 #50
0
ファイル: state.py プロジェクト: jzuhone/glue
class ScatterLayerState(MatplotlibLayerState):
    """
    A state class that includes all the attributes for layers in a scatter plot.
    """

    # Color

    cmap_mode = DDSCProperty(docstring="Whether to use color to encode an attribute")
    cmap_att = DDSCProperty(docstring="The attribute to use for the color")
    cmap_vmin = DDCProperty(docstring="The lower level for the colormap")
    cmap_vmax = DDCProperty(docstring="The upper level for the colormap")
    cmap = DDCProperty(docstring="The colormap to use (when in colormap mode)")

    # Points

    points_mode = DDSCProperty(docstring='Whether to use markers or a density map')

    # Markers

    markers_visible = DDCProperty(True, docstring="Whether to show markers")
    size = DDCProperty(docstring="The size of the markers")
    size_mode = DDSCProperty(docstring="Whether to use size to encode an attribute")
    size_att = DDSCProperty(docstring="The attribute to use for the size")
    size_vmin = DDCProperty(docstring="The lower level for the size mapping")
    size_vmax = DDCProperty(docstring="The upper level for the size mapping")
    size_scaling = DDCProperty(1, docstring="Relative scaling of the size")
    fill = DDCProperty(True, docstring="Whether to fill the markers")

    # Density map

    density_map = DDCProperty(False, docstring="Whether to show the points as a density map")
    stretch = DDSCProperty(default='log', docstring='The stretch used to render the layer, '
                                                    'which should be one of ``linear``, '
                                                    '``sqrt``, ``log``, or ``arcsinh``')
    density_contrast = DDCProperty(1, docstring="The dynamic range of the density map")

    # Note that we keep the dpi in the viewer state since we want it to always
    # be in sync between layers.

    # Line

    line_visible = DDCProperty(False, docstring="Whether to show a line connecting all positions")
    linewidth = DDCProperty(1, docstring="The line width")
    linestyle = DDSCProperty(docstring="The line style")

    # Errorbars

    xerr_visible = DDCProperty(False, docstring="Whether to show x error bars")
    yerr_visible = DDCProperty(False, docstring="Whether to show y error bars")
    xerr_att = DDSCProperty(docstring="The attribute to use for the x error bars")
    yerr_att = DDSCProperty(docstring="The attribute to use for the y error bars")

    # Vectors

    vector_visible = DDCProperty(False, docstring="Whether to show vector plot")
    vx_att = DDSCProperty(docstring="The attribute to use for the x vector arrow")
    vy_att = DDSCProperty(docstring="The attribute to use for the y vector arrow")
    vector_arrowhead = DDCProperty(False, docstring="Whether to show vector arrow")
    vector_mode = DDSCProperty(default_index=0, docstring="Whether to plot the vectors in cartesian or polar mode")
    vector_origin = DDSCProperty(default_index=1, docstring="Whether to place the vector so that the origin is at the tail, middle, or tip")
    vector_scaling = DDCProperty(1, docstring="The relative scaling of the arrow length")

    def __init__(self, viewer_state=None, layer=None, **kwargs):

        super(ScatterLayerState, self).__init__(viewer_state=viewer_state, layer=layer)

        self.limits_cache = {}

        self.cmap_lim_helper = StateAttributeLimitsHelper(self, attribute='cmap_att',
                                                          lower='cmap_vmin', upper='cmap_vmax',
                                                          limits_cache=self.limits_cache)

        self.size_lim_helper = StateAttributeLimitsHelper(self, attribute='size_att',
                                                          lower='size_vmin', upper='size_vmax',
                                                          limits_cache=self.limits_cache)

        self.cmap_att_helper = ComponentIDComboHelper(self, 'cmap_att',
                                                      numeric=True, categorical=False)

        self.size_att_helper = ComponentIDComboHelper(self, 'size_att',
                                                      numeric=True, categorical=False)

        self.xerr_att_helper = ComponentIDComboHelper(self, 'xerr_att',
                                                      numeric=True, categorical=False)

        self.yerr_att_helper = ComponentIDComboHelper(self, 'yerr_att',
                                                      numeric=True, categorical=False)

        self.vx_att_helper = ComponentIDComboHelper(self, 'vx_att',
                                                    numeric=True, categorical=False)

        self.vy_att_helper = ComponentIDComboHelper(self, 'vy_att',
                                                    numeric=True, categorical=False)

        points_mode_display = {'auto': 'Density map or markers (auto)',
                               'markers': 'Markers',
                               'density': 'Density map'}

        ScatterLayerState.points_mode.set_choices(self, ['auto', 'markers', 'density'])
        ScatterLayerState.points_mode.set_display_func(self, points_mode_display.get)

        self.add_callback('points_mode', self._update_density_map_mode)

        ScatterLayerState.cmap_mode.set_choices(self, ['Fixed', 'Linear'])
        ScatterLayerState.size_mode.set_choices(self, ['Fixed', 'Linear'])

        linestyle_display = {'solid': '–––––––',
                             'dashed': '– – – – –',
                             'dotted': '· · · · · · · ·',
                             'dashdot': '– · – · – ·'}

        ScatterLayerState.linestyle.set_choices(self, ['solid', 'dashed', 'dotted', 'dashdot'])
        ScatterLayerState.linestyle.set_display_func(self, linestyle_display.get)

        ScatterLayerState.vector_mode.set_choices(self, ['Cartesian', 'Polar'])

        vector_origin_display = {'tail': 'Tail of vector',
                                 'middle': 'Middle of vector',
                                 'tip': 'Tip of vector'}

        ScatterLayerState.vector_origin.set_choices(self, ['tail', 'middle', 'tip'])
        ScatterLayerState.vector_origin.set_display_func(self, vector_origin_display.get)

        stretch_display = {'linear': 'Linear',
                           'sqrt': 'Square Root',
                           'arcsinh': 'Arcsinh',
                           'log': 'Logarithmic'}

        ScatterLayerState.stretch.set_choices(self, ['linear', 'sqrt', 'arcsinh', 'log'])
        ScatterLayerState.stretch.set_display_func(self, stretch_display.get)

        self.add_callback('layer', self._on_layer_change)
        if layer is not None:
            self._on_layer_change()

        self.cmap = colormaps.members[0][1]

        self.size = self.layer.style.markersize

        self._sync_size = keep_in_sync(self, 'size', self.layer.style, 'markersize')

        self.update_from_dict(kwargs)

    def _on_layer_change(self, layer=None):

        with delay_callback(self, 'cmap_vmin', 'cmap_vmax', 'size_vmin', 'size_vmax', 'density_map'):

            self._update_density_map_mode()

            if self.layer is None:
                self.cmap_att_helper.set_multiple_data([])
                self.size_att_helper.set_multiple_data([])
            else:
                self.cmap_att_helper.set_multiple_data([self.layer])
                self.size_att_helper.set_multiple_data([self.layer])

            if self.layer is None:
                self.xerr_att_helper.set_multiple_data([])
                self.yerr_att_helper.set_multiple_data([])
            else:
                self.xerr_att_helper.set_multiple_data([self.layer])
                self.yerr_att_helper.set_multiple_data([self.layer])

            if self.layer is None:
                self.vx_att_helper.set_multiple_data([])
                self.vy_att_helper.set_multiple_data([])
            else:
                self.vx_att_helper.set_multiple_data([self.layer])
                self.vy_att_helper.set_multiple_data([self.layer])

    def _update_density_map_mode(self, *args):
        if self.points_mode == 'auto':
            if self.layer.size > 100000:
                self.density_map = True
            else:
                self.density_map = False
        elif self.points_mode == 'density':
            self.density_map = True
        else:
            self.density_map = False

    def flip_cmap(self):
        """
        Flip the cmap_vmin/cmap_vmax limits.
        """
        self.cmap_lim_helper.flip_limits()

    def flip_size(self):
        """
        Flip the size_vmin/size_vmax limits.
        """
        self.size_lim_helper.flip_limits()

    @property
    def cmap_name(self):
        return colormaps.name_from_cmap(self.cmap)

    @classmethod
    def __setgluestate__(cls, rec, context):
        # Patch for glue files produced with glue v0.11
        if 'style' in rec['values']:
            style = context.object(rec['values'].pop('style'))
            if style == 'Scatter':
                rec['values']['markers_visible'] = True
                rec['values']['line_visible'] = False
            elif style == 'Line':
                rec['values']['markers_visible'] = False
                rec['values']['line_visible'] = True
        return super(ScatterLayerState, cls).__setgluestate__(rec, context)