File: client.py

package info (click to toggle)
glueviz 0.9.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 17,180 kB
  • ctags: 6,728
  • sloc: python: 37,111; makefile: 134; sh: 60
file content (200 lines) | stat: -rw-r--r-- 5,812 bytes parent folder | download
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