1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
|
from __future__ import absolute_import, division, print_function
from glue.core.message import (DataUpdateMessage,
SubsetUpdateMessage,
SubsetCreateMessage,
SubsetDeleteMessage,
DataCollectionDeleteMessage,
NumericalDataChangedMessage)
from glue.core.data_collection import DataCollection
from glue.core.subset import Subset
from glue.core.data import Data
from glue.core.hub import HubListener
__all__ = ['Client', 'BasicClient']
class Client(HubListener):
"""
Base class for interaction / visualization modules
Attributes
----------
data: DataCollection instance
The data associated with this client.
"""
def __init__(self, data):
"""
Create a new client object.
Parameters
----------
data: Data, DataCollection, or list of data
The primary data associated with this client.
Raises
------
TypeError: If the data input is the wrong type
"""
super(Client, self).__init__()
self._data = data
if not isinstance(data, DataCollection):
raise TypeError("Input data must be a DataCollection: %s"
% type(data))
@property
def data(self):
""" Returns the data collection """
return self._data
def register_to_hub(self, hub):
"""The main method to establish a link with a hub,
and set up event handlers. For common message types
Client subclasses at a minimum should override these methods
to provide functionality:
_add_subset
_update_subset
_remove_subset
_remove_data
Clients can also override register_to_hub to add additional
event handlers.
Attributes
----------
hub: The hub to subscribe to
"""
has_data = lambda x: x.sender.data in self._data
has_data_collection = lambda x: x.sender is self._data
hub.subscribe(self,
SubsetCreateMessage,
handler=self._add_subset,
filter=has_data)
hub.subscribe(self,
SubsetUpdateMessage,
handler=self._update_subset,
filter=has_data)
hub.subscribe(self,
SubsetDeleteMessage,
handler=self._remove_subset,
filter=has_data)
hub.subscribe(self,
DataUpdateMessage,
handler=self._update_data,
filter=has_data)
hub.subscribe(self,
NumericalDataChangedMessage,
handler=self._numerical_data_changed,
filter=has_data)
hub.subscribe(self,
DataCollectionDeleteMessage,
handler=self._remove_data,
filter=has_data_collection)
def _add_subset(self, message):
raise NotImplementedError
def _remove_data(self, message):
raise NotImplementedError
def _remove_subset(self, message):
raise NotImplementedError
def _update_data(self, message):
""" Default handler for DataMessage """
raise NotImplementedError
def _update_subset(self, message):
""" Default handler for SubsetUpdateMessage """
raise NotImplementedError
def apply_roi(self, roi):
raise NotImplementedError
def _numerical_data_changed(self, message):
raise NotImplementedError
class BasicClient(Client):
def _add_subset(self, message):
subset = message.subset
self.add_layer(subset)
def _update_subset(self, message):
subset = message.subset
self.update_layer(subset)
def _remove_subset(self, message):
subset = message.subset
self.remove_layer(subset)
def _remove_data(self, message):
self.remove_layer(message.data)
def _update_data(self, message):
self.update_layer(message.data)
def add_layer(self, layer):
if self.layer_present(layer):
return
if layer.data not in self.data:
raise TypeError("Data not in collection")
if isinstance(layer, Data):
self._do_add_data(layer)
for subset in layer.subsets:
self.add_layer(subset)
else:
if not self.layer_present(layer.data):
self.add_layer(layer.data)
else:
self._do_add_subset(layer)
self.update_layer(layer)
def update_layer(self, layer):
if not self.layer_present(layer):
return
if isinstance(layer, Subset):
self._do_update_subset(layer)
else:
self._do_update_data(layer)
def remove_layer(self, layer):
if not self.layer_present(layer):
return
if isinstance(layer, Data):
self._do_remove_data(layer)
for subset in layer.subsets:
self._do_remove_subset(subset)
else:
self._do_remove_subset(layer)
def _do_add_data(self, data):
raise NotImplementedError
def _do_add_subset(self, subset):
raise NotImplementedError
def _do_update_subset(self, subset):
raise NotImplementedError
def _do_update_data(self, data):
raise NotImplementedError
def _do_remove_subset(self, subset):
raise NotImplementedError
def _do_remove_data(self, data):
raise NotImplementedError
def layer_present(self, layer):
raise NotImplementedError
|