/usr/share/pyshared/chaco/subdivision_cells.py is in python-chaco 4.1.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 | """ Defines cell-related classes and functions.
"""
from numpy import take, array, concatenate, nonzero
from traits.api import HasStrictTraits, Instance, Delegate, Array, List, \
Tuple, Property, Trait, Any, Disallow
from datamapper import AbstractDataMapper, right_shift, left_shift, sort_points
def find_runs(int_array, order='ascending'):
"""
find_runs(int_array, order=<'ascending'|'flat'|'descending'>) -> list_of_int_arrays
Given an integer array sorted in ascending, descending, or flat order, this
function returns a list of continuous runs of integers inside the list.
For example::
find_runs([1,2,3,6,7,8,9,10,11,15])
returns [ [1,2,3], [6,7,8,9,10,11], [15] ]
and::
find_runs([0,0,0,1,1,1,1,0,0,0,0])
returns [ [0,0,0], [1,1,1,1], [0,0,0,0] ]
"""
ranges = arg_find_runs(int_array, order)
if ranges:
return [int_array[i:j] for (i,j) in ranges]
else:
return []
def arg_find_runs(int_array, order='ascending'):
"""
This function is like find_runs(), but it returns a list of tuples
indicating the start and end indices of runs in the input *int_array*.
"""
if len(int_array) == 0:
return []
assert len(int_array.shape)==1, "find_runs() requires a 1D integer array."
if order == 'ascending':
increment = 1
elif order == 'descending':
increment = -1
else:
increment = 0
rshifted = right_shift(int_array, int_array[0]-increment)
start_indices = concatenate([[0], nonzero(int_array - (rshifted+increment))[0]])
end_indices = left_shift(start_indices, len(int_array))
return zip(start_indices, end_indices)
class AbstractCell(HasStrictTraits):
""" Abstract class for grid cells in a uniform subdivision.
Individual subclasses store points in different, possibly optimized
fashion, and performance may be drastically different between different
cell subclasses for a given set of data.
"""
# The parent of this cell.
parent = Instance(AbstractDataMapper)
# The sort traits characterizes the internal points list.
_sort_order = Delegate('parent')
# The point array for this cell. This attribute delegates to parent._data,
# which references the actual point array. For the sake of simplicity,
# cells assume that _data is sorted in fashion indicated by **_sort_order**.
# If this doesn't hold, then each cell needs to have its own duplicate
# copy of the sorted data.
data = Delegate('parent', '_data')
# A list of indices into **data** that reflect the points inside this cell.
indices = Property
# Shadow trait for **indices**.
_indices = Any
def add_indices(self, indices):
""" Adds a list of integer indices to the existing list of indices.
"""
raise NotImplementedError
def get_points(self):
""" Returns a list of points that was previously set.
This operation might be large and expensive; in general, use
_get_indices() instead.
"""
raise NotImplementedError
def reverse_indices(self):
""" Tells the cell to manipulate its indices so that they index to the
same values in a reversed data array.
Generally this method handles the situation when the parent's _data
array has been flipped due to a sort order change.
The length of _data must not have changed; otherwise there is no way to
know the proper way to manipulate indices.
"""
raise NotImplementedError
def _set_indices(self, indices):
raise NotImplementedError
def _get_indices(self):
""" Returns the list of indices into _data that reflect the points
inside this cell.
"""
raise NotImplementedError
class Cell(AbstractCell):
"""
A basic cell that stores its point indices as an array of integers.
"""
# A list of indices into **data** that reflect the points inside this cell
# (overrides AbstractCell).
indices = Property(Array)
# A 1-D array of indices into _data.
_indices = Array
def __init__(self, **kw):
self._indices = array([])
super(AbstractCell, self).__init__(**kw)
def add_indices(self, indices):
""" Adds a list of integer indices to the existing list of indices.
Implements AbstractCell.
"""
self._indices = concatenate([self._indices, indices])
return
def get_points(self):
""" Returns a list of points that was previously set.
Implements AbstractCell.
"""
return take(self.data, self._indices)
def reverse_indices(self):
""" Tells the cell to manipulate its indices so that they index to the
same values in a reversed data array.
Implements AbstractCell.
"""
length = len(self.data)
self._indices = [length-i-1 for i in self._indices]
return
def _set_indices(self, indices):
self._indices = indices
return
def _get_indices(self):
return self._indices
class RangedCell(AbstractCell):
""" A cell optimized for storing lists of continuous points.
Rather than storing each individual point index as an element in an array,
RangedCell stores a list of index ranges; each range is a (start,end) tuple).
"""
# A list of indices into **data** that reflect the points inside this cell
# (overrides AbstractCell).
indices = Property
# Don't use the _indices shadow trait; rather, the getters and setters
# for 'index' procedurally generate indices from **ranges**.
_indices = Disallow
# Ranges are an additional interface on RangedCells.
ranges = Property(List(Tuple))
# Shadow trait for ranges.
_ranges = List(Tuple)
#---------------------------------------------------------------------
# AbstractCell methods
#---------------------------------------------------------------------
def add_indices(self, indices):
""" Adds a list of integer indices to the existing list of indices.
Implements AbstractCell.
"""
self.add_ranges(find_runs(indices))
return
def get_points(self):
""" Returns a list of points that was previously set.
Implements AbstractCell.
"""
return take(self.data, self.indices)
def reverse_indices(self):
""" Tells the cell to manipulate its indices so that they index to the
same values in a reversed data array.
Implements AbstractCell.
"""
length = len(self.data)
self._ranges = [(length-end-1, length-start-1) for (start,end) in self._ranges]
return
def _set_indices(self, indices):
self._ranges = find_runs(indices)
return
def _get_indices(self):
list_of_indices = [range(i,j) for (i,j) in self._ranges]
return sum(list_of_indices, [])
#---------------------------------------------------------------------
# additional RangedCell methods
#---------------------------------------------------------------------
def get_ranges(self):
""" Returns a list of tuples representing the (start,end) indices of
continuous ranges of points in self._data.
"""
return self._ranges()
def add_ranges(self, ranges):
""" Adds a list of ranges ((start,end) tuples) to the current list.
This method doesn't check for duplicate or overlapping ranges.
"""
if self._ranges:
self._ranges.extend(ranges)
else:
self._ranges = ranges
return
#EOF
|