This file is indexed.

/usr/lib/python2.7/dist-packages/chaco/grid_mapper.py is in python-chaco 4.5.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
"""
Defines the GridMapper class, which maps from a 2-D region in data space
into a structured (gridded) 1-D output space.
"""

# Python standard library imports
from contextlib import contextmanager

# Major library imports
from numpy import column_stack, transpose

# Enthought library imports
from traits.api import Bool, DelegatesTo, Instance, Float, Property

# Local relative imports
from abstract_mapper import AbstractMapper
from base_1d_mapper import Base1DMapper
from data_range_2d import DataRange2D
from linear_mapper import LinearMapper
from log_mapper import LogMapper


class GridMapper(AbstractMapper):
    """
    Maps a 2-D data space to and from screen space by specifying a 2-tuple in
    data space or by specifying a pair of screen coordinates.

    The mapper concerns itself only with metric and not with orientation. So,
    to "flip" a screen space orientation, swap the appropriate screen space
    values for **x_low_pos**, **x_high_pos**, **y_low_pos**, and
    **y_high_pos**.
    """

    # The data-space bounds of the mapper.
    range = Instance(DataRange2D)

    # The screen space position of the lower bound of the horizontal axis.
    x_low_pos = Float(0.0)

    # The screen space position of the upper bound of the horizontal axis.
    x_high_pos = Float(1.0)

    # The screen space position of the lower bound of the vertical axis.
    y_low_pos = Float(0.0)

    # The screen space position of the upper bound of the vertical axis.
    y_high_pos = Float(1.0)

    # Convenience property for low and high positions in one structure.
    # Must be a tuple (x_low_pos, x_high_pos, y_low_pos, y_high_pos).
    screen_bounds = Property

    # Should the mapper stretch the dataspace when its screen space bounds are
    # modified (default), or should it preserve the screen-to-data ratio and
    # resize the data bounds?  If the latter, it will only try to preserve
    # the ratio if both screen and data space extents are non-zero.
    stretch_data_x = DelegatesTo("_xmapper", prefix="stretch_data")
    stretch_data_y = DelegatesTo("_ymapper", prefix="stretch_data")

    # Should the mapper try to maintain a fixed aspect ratio between x and y
    maintain_aspect_ratio = Bool

    # The aspect ratio that we wish to maintain
    aspect_ratio = Float(1.0)

    #------------------------------------------------------------------------
    # Private Traits
    #------------------------------------------------------------------------

    _updating_submappers = Bool(False)
    _updating_aspect = Bool(False)

    _xmapper = Instance(Base1DMapper)
    _ymapper = Instance(Base1DMapper)

    #------------------------------------------------------------------------
    # Public methods
    #------------------------------------------------------------------------

    def __init__(self, x_type="linear", y_type="linear", range=None, **kwargs):
        # TODO: This is currently an implicit assumption, i.e. that the range
        # will be passed in to the constructor.  It would be impossible to
        # create the xmapper and ymapper otherwise.  However, this should be
        # changed so that the mappers get created or modified in response to
        # the .range attribute changing, instead of requiring the range to
        # be passed in at construction time.
        self.range = range

        if "_xmapper" not in kwargs:
            if x_type == "linear":
                self._xmapper = LinearMapper(range=self.range.x_range)
            elif x_type == "log":
                self._xmapper = LogMapper(range=self.range.x_range)
            else:
                raise ValueError("Invalid x axis type: %s" % x_type)
        else:
            self._xmapper = kwargs.pop("_xmapper")

        if "_ymapper" not in kwargs:
            if y_type == "linear":
                self._ymapper = LinearMapper(range=self.range.y_range)
            elif y_type == "log":
                self._ymapper = LogMapper(range=self.range.y_range)
            else:
                raise ValueError("Invalid y axis type: %s" % y_type)
        else:
            self._ymapper = kwargs.pop("_ymapper")

        # Now that the mappers are created, we can go to the normal HasTraits
        # constructor, which might set values that depend on us having a valid
        # range and mappers.
        super(GridMapper, self).__init__(**kwargs)

    def map_screen(self, data_pts):
        """ map_screen(data_pts) -> screen_array

        Maps values from data space into screen space.
        """
        xs, ys = transpose(data_pts)
        screen_xs = self._xmapper.map_screen(xs)
        screen_ys = self._ymapper.map_screen(ys)
        screen_pts = column_stack([screen_xs, screen_ys])
        return screen_pts

    def map_data(self, screen_pts):
        """ map_data(screen_pts) -> data_vals

        Maps values from screen space into data space.
        """
        screen_xs, screen_ys = transpose(screen_pts)
        xs = self._xmapper.map_data(screen_xs)
        ys = self._ymapper.map_data(screen_ys)
        data_pts = column_stack([xs, ys])
        return data_pts

    def map_data_array(self, screen_pts):
        return self.map_data(screen_pts)

    #------------------------------------------------------------------------
    # Private Methods
    #------------------------------------------------------------------------

    def _update_bounds(self):
        with self._update_submappers():
            self._xmapper.screen_bounds = (self.x_low_pos, self.x_high_pos)
            self._ymapper.screen_bounds = (self.y_low_pos, self.y_high_pos)
        self.updated = True

    def _update_range(self):
        self.updated = True

    def _update_aspect_x(self):
        y_width = self._ymapper.high_pos - self._ymapper.low_pos
        if y_width == 0:
            return
        y_scale = (self._ymapper.range.high - self._ymapper.range.low)/y_width
        x_range_low = self._xmapper.range.low
        x_width = self._xmapper.high_pos - self._xmapper.low_pos
        sign = self._xmapper.sign * self._ymapper.sign
        if x_width == 0 or sign == 0:
            return
        x_scale = sign*y_scale/self.aspect_ratio
        with self._update_aspect():
            self._xmapper.range.set_bounds(x_range_low, x_range_low +
                x_scale*x_width)

    def _update_aspect_y(self):
        x_width = self._xmapper.high_pos - self._xmapper.low_pos
        if x_width == 0:
            return
        x_scale = (self._xmapper.range.high - self._xmapper.range.low)/x_width
        y_range_low = self._ymapper.range.low
        y_width = self._ymapper.high_pos-self._ymapper.low_pos
        sign = self._xmapper.sign * self._ymapper.sign
        if y_width == 0 or sign == 0:
            return
        y_scale = sign*x_scale*self.aspect_ratio
        with self._update_aspect():
            self._ymapper.range.set_bounds(y_range_low, y_range_low +
                y_scale*y_width)

    #------------------------------------------------------------------------
    # Property handlers
    #------------------------------------------------------------------------

    def _range_changed(self, old, new):
        if old is not None:
            old.on_trait_change(self._update_range, "updated", remove=True)
        if new is not None:
            new.on_trait_change(self._update_range, "updated")
            if self._xmapper is not None:
                self._xmapper.range = new.x_range
            if self._ymapper is not None:
                self._ymapper.range = new.y_range
            self._update_range()

    def _x_low_pos_changed(self):
        self._xmapper.low_pos = self.x_low_pos

    def _x_high_pos_changed(self):
        self._xmapper.high_pos = self.x_high_pos

    def _y_low_pos_changed(self):
        self._ymapper.low_pos = self.y_low_pos

    def _y_high_pos_changed(self):
        self._ymapper.high_pos = self.y_high_pos

    def _set_screen_bounds(self, new_bounds):
        # TODO: figure out a way to not need to do this check:
        if self.screen_bounds == new_bounds:
            return
        self.set(x_low_pos=new_bounds[0], trait_change_notify=False)
        self.set(x_high_pos=new_bounds[1], trait_change_notify=False)
        self.set(y_low_pos=new_bounds[2], trait_change_notify=False)
        self.set(y_high_pos=new_bounds[3], trait_change_notify=False)
        self._update_bounds()

    def _get_screen_bounds(self):
        return (self.x_low_pos, self.x_high_pos,
                self.y_low_pos, self.y_high_pos)

    def _updated_fired_for__xmapper(self):
        if not self._updating_aspect:
            if self.maintain_aspect_ratio and self.stretch_data_x:
                self._update_aspect_y()
        if not self._updating_submappers:
            self.updated = True

    def _updated_fired_for__ymapper(self):
        if not self._updating_aspect:
            if self.maintain_aspect_ratio and self.stretch_data_y:
                self._update_aspect_x()
        if not self._updating_submappers:
            self.updated = True

    @contextmanager
    def _update_submappers(self):
        self._updating_submappers = True
        try:
            yield
        finally:
            self._updating_submappers = False

    @contextmanager
    def _update_aspect(self):
        self._updating_aspect = True
        try:
            yield
        finally:
            self._updating_aspect = False