~ubuntu-branches/ubuntu/utopic/python-chaco/utopic

« back to all changes in this revision

Viewing changes to chaco/_speedups.cpp

  • Committer: Package Import Robot
  • Author(s): Andrew Starr-Bochicchio
  • Date: 2014-06-01 17:04:08 UTC
  • mfrom: (7.2.5 sid)
  • Revision ID: package-import@ubuntu.com-20140601170408-m86xvdjd83a4qon0
Tags: 4.4.1-1ubuntu1
* Merge from Debian unstable. Remaining Ubuntu changes:
 - Let the binary-predeb target work on the usr/lib/python* directory
   as we don't have usr/share/pyshared anymore.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
#include <math.h>
3
 
#include "Python.h"
4
 
#include "structmember.h"
5
 
#include "numpy/arrayobject.h"
6
 
#include "numpy/ufuncobject.h"
7
 
 
8
 
#define SAFE_FROMARRAY_1D(a, type)  \
9
 
    ((a) == NULL) ? (a) : PyArray_FROMANY(a, type, 1, 1, NPY_IN_ARRAY)
10
 
 
11
 
extern "C" {
12
 
    PyMODINIT_FUNC init_speedups(void);
13
 
    //static PyObject *scatterplot_gather_points(PyObject *args, PyObject *kwargs);
14
 
}
15
 
 
16
 
 
17
 
// Given a tuple or list of indices and an array length, returns a new array of
18
 
// the given length with value 1 at each indices in the list of indices, and 0
19
 
// elsewhere.
20
 
// The caller must deallocate the array when they are done.
21
 
// If selections is NULL or arrayLen is 0, then a null pointer is returned.
22
 
char *create_mirror_mask_array(PyObject *selections, int arrayLen)
23
 
{
24
 
    if ((selections != NULL) && (arrayLen > 0) && (PySequence_Length(selections) > 0))
25
 
    {
26
 
 
27
 
        char *mirror = new char[arrayLen];
28
 
        memset(mirror, 0, arrayLen);
29
 
        int numIndices = PySequence_Length(selections);
30
 
        PyObject *tmp;
31
 
        for (int i=0; i < numIndices; i++)
32
 
        {
33
 
            tmp = PyTuple_GetItem(selections, i);
34
 
            mirror[PyInt_AsLong(tmp)] = 1;
35
 
            Py_XDECREF(tmp);
36
 
        }
37
 
        return mirror;
38
 
    }
39
 
    else
40
 
    {
41
 
        return NULL;
42
 
    }
43
 
}
44
 
 
45
 
/*
46
 
 * Scatterplot speedups
47
 
 */
48
 
 
49
 
static char scatterplot_gather_points_doc[] = \
50
 
    "Takes index and value arrays, masks, and optional selection arrays, \n" \
51
 
    "and returns the list of points and corresponding selection mask for \n" \
52
 
    "those points. \n " \
53
 
    "\n" \
54
 
    "Parameters\n" \
55
 
    "----------\n" \
56
 
    "index : float array (1D) \n" \
57
 
    "index_low : float or None\n" \
58
 
    "   The minimum acceptable value in the index array\n" \
59
 
    "index_high : float or None \n" \
60
 
    "   The maximum acceptable value in the index array\n" \
61
 
    "value : float array (1D) \n" \
62
 
    "value_low : float or None\n" \
63
 
    "   The minimum acceptable value in the value array\n" \
64
 
    "value_high : float or None \n" \
65
 
    "   The maximum acceptable value in the value array\n" \
66
 
    "\n" \
67
 
    "Optional Parameters\n" \
68
 
    "-------------------\n" \
69
 
    "index_mask : bool or int array (1D) \n" \
70
 
    "   A mask that indicates which index points should be used\n" \
71
 
    "index_sel : sequence of ints \n" \
72
 
    "   A list/tuple/array of indices of selected positions in the index array\n " \
73
 
    "index_sel_mask : array of ints or bools\n" \
74
 
    "   An mask array with True values indicating which points are selected\n" \
75
 
    "value_mask : bool or int array (1D) \n" \
76
 
    "   A mask that indicates which value points should be used\n" \
77
 
    "value_sel : sequence of ints \n" \
78
 
    "   A list/tuple/array of indices of selected positions in the value array\n " \
79
 
    "value_sel_mask : array of ints or bools\n" \
80
 
    "   An mask array with True values indicating which points are selected\n" \
81
 
    "\n" \
82
 
    "Returns\n" \
83
 
    "-------\n" \
84
 
    "points : float array (Nx2) \n " \
85
 
    "   The points that match all the masking criteria \n" \
86
 
    "sel_mask : bool array (1D) \n " \
87
 
    "   Mask indicating which indices in **points** are selected \n" \
88
 
    "";
89
 
 
90
 
#define DEBUG_SPEEDUP 0
91
 
 
92
 
static PyObject *scatterplot_gather_points(PyObject *self, PyObject* args, PyObject* kwargs)
93
 
{
94
 
    PyObject *index, *index_mask, *index_sel, *index_sel_mask;
95
 
    PyObject *value, *value_mask, *value_sel, *value_sel_mask;
96
 
    PyObject *tmp;
97
 
 
98
 
    index = index_mask = index_sel = index_sel_mask = NULL;
99
 
    value = value_mask = value_sel = value_sel_mask = NULL;
100
 
 
101
 
    // Stores the points and selection array while we're iterating over the input
102
 
    npy_float *points = NULL;
103
 
    npy_bool *points_mask = NULL; 
104
 
 
105
 
    PyObject *np_points, *np_points_mask, *returnval = NULL;
106
 
 
107
 
    double index_low, index_high, value_low, value_high;
108
 
    unsigned int numValidPts = 0;
109
 
    float x, y;
110
 
 
111
 
    int numIndex, numValue;
112
 
    char *index_sel_mirror, *value_sel_mirror;
113
 
    int numpoints;      // The number of points to iterate over in the input arrays
114
 
 
115
 
    static char *keywords[] = {"index", "index_low", "index_high",
116
 
                               "value", "value_low", "value_high",
117
 
                               "index_mask", "index_sel", "index_sel_mask",
118
 
                               "value_mask", "value_sel", "value_sel_mask", NULL};
119
 
 
120
 
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OddOdd|OOOOOO", keywords, 
121
 
                &index, &index_low, &index_high,
122
 
                &value, &value_low, &value_high,
123
 
                &index_mask, &index_sel, &index_sel_mask,
124
 
                &value_mask, &value_sel, &value_sel_mask))
125
 
        return NULL;
126
 
 
127
 
#if DEBUG_SPEEDUP
128
 
    printf("Parsed arguments\n");
129
 
#endif
130
 
 
131
 
    index = PyArray_FROMANY(index, NPY_DOUBLE, 1, 1, NPY_IN_ARRAY);
132
 
    if (index == NULL)
133
 
        goto cleanup;
134
 
    value = PyArray_FROMANY(value, NPY_DOUBLE, 1, 1, NPY_IN_ARRAY);
135
 
    if (value == NULL)
136
 
        goto cleanup;
137
 
 
138
 
#if DEBUG_SPEEDUP
139
 
    printf("Got index and value\n");
140
 
#endif
141
 
 
142
 
    index_mask = SAFE_FROMARRAY_1D(index_mask, NPY_BOOL);
143
 
    index_sel = SAFE_FROMARRAY_1D(index_sel, NPY_INT);
144
 
    index_sel_mask = SAFE_FROMARRAY_1D(index_sel_mask, NPY_BOOL);
145
 
 
146
 
    value_mask = SAFE_FROMARRAY_1D(value_mask, NPY_BOOL);
147
 
    value_sel = SAFE_FROMARRAY_1D(value_sel, NPY_INT);
148
 
    value_sel_mask = SAFE_FROMARRAY_1D(value_sel_mask, NPY_BOOL);
149
 
 
150
 
    numIndex = PyArray_DIM(index, 0);
151
 
    numValue = PyArray_DIM(value, 0);
152
 
 
153
 
    index_sel_mirror = create_mirror_mask_array(index_sel, numIndex);
154
 
    value_sel_mirror = create_mirror_mask_array(value_sel, numValue);
155
 
 
156
 
#if DEBUG_SPEEDUP
157
 
    if ((index_sel_mirror != NULL) || (value_sel_mirror != NULL))
158
 
        printf("Created mirrors\n");
159
 
    else
160
 
        printf("Created empty mirrors\n");
161
 
#endif
162
 
 
163
 
    // Determine the total number of points to iterate over in the input arrays
164
 
    // based on the shorter of index or value
165
 
    numpoints = PySequence_Length(index);
166
 
    if (PySequence_Length(value) < numpoints)
167
 
        numpoints = PySequence_Length(value);
168
 
 
169
 
    // Create a new array for the list of good points and selections into that array
170
 
    points = new npy_float[numpoints * 2];
171
 
 
172
 
#if DEBUG_SPEEDUP
173
 
    printf("Created points array\n");
174
 
#endif
175
 
 
176
 
    if ((index_sel != NULL) || (index_sel_mask != NULL) || 
177
 
        (value_sel != NULL) || (value_sel_mask != NULL))
178
 
    {
179
 
        points_mask = new npy_bool[numpoints];
180
 
#if DEBUG_SPEEDUP
181
 
        printf("Created points_mask array\n");
182
 
#endif
183
 
    }
184
 
 
185
 
 
186
 
    // Iterate over the list of x,y positions and check to see if they
187
 
    // should be copied into the output list
188
 
    for (int i=0; i < numpoints; i++)
189
 
    {
190
 
        x = *((double *) (PyArray_GETPTR1(index, i)));
191
 
        y = *((double *) (PyArray_GETPTR1(value, i)));
192
 
 
193
 
        if (((index_mask != NULL) && (*(npy_bool*)PyArray_GETPTR1(index_mask, i) == 0)) || 
194
 
            ((value_mask != NULL) && (*(npy_bool*)PyArray_GETPTR1(value_mask, i) == 0)))
195
 
            continue;
196
 
 
197
 
        if (isnan(x) || isnan(y))
198
 
            continue;
199
 
 
200
 
        if ((x < index_low) || (x > index_high) ||
201
 
            (y < value_low) || (y > value_high))
202
 
            continue;
203
 
 
204
 
        points[numValidPts * 2] = x;
205
 
        points[numValidPts * 2 + 1] = y;
206
 
 
207
 
        if (((index_sel_mirror != NULL) && (index_sel_mirror[i] == 1)) ||
208
 
            ((value_sel_mirror != NULL) && (value_sel_mirror[i] == 1)) ||
209
 
            ((index_sel_mask != NULL) && 
210
 
                    (*(npy_bool*)PyArray_GETPTR1(index_sel_mask, i) == 1))  ||
211
 
            ((value_sel_mask != NULL) && 
212
 
                    (*(npy_bool*)PyArray_GETPTR1(value_sel_mask, i) == 1)))
213
 
        {
214
 
            points_mask[numValidPts] = 1;
215
 
        }
216
 
        else if (points_mask != NULL)
217
 
        {
218
 
            points_mask[numValidPts] = 0;
219
 
        }
220
 
 
221
 
        numValidPts++;
222
 
    }
223
 
 
224
 
#if DEBUG_SPEEDUP
225
 
    printf("Finished main loop\n");
226
 
#endif
227
 
 
228
 
    // Copy the valid points into a compact array of the right length
229
 
    npy_intp dims[2];
230
 
    dims[0] = numValidPts;
231
 
    dims[1] = 2;
232
 
    np_points = PyArray_SimpleNew(2, dims, NPY_DOUBLE);
233
 
    for (int i=0; i < numValidPts; i++)
234
 
    {
235
 
        *((npy_double*) PyArray_GETPTR2(np_points, i, 0)) = points[i*2];
236
 
        *((npy_double*) PyArray_GETPTR2(np_points, i, 1)) = points[i*2 + 1];
237
 
    }
238
 
 
239
 
    if (points_mask != NULL)
240
 
    {
241
 
        npy_intp maskdims[1];
242
 
        maskdims[0] = numValidPts;
243
 
        np_points_mask = PyArray_SimpleNew(1, maskdims, NPY_BOOL);
244
 
        for (int i=0; i< numValidPts; i++)
245
 
            *(npy_bool*)(PyArray_GETPTR1(np_points_mask, i)) = points_mask[i];
246
 
    }
247
 
    else
248
 
    {
249
 
        Py_INCREF(Py_None);
250
 
        np_points_mask = Py_None;
251
 
    }
252
 
 
253
 
#if DEBUG_SPEEDUP
254
 
    printf("Compacted array\n");
255
 
#endif
256
 
 
257
 
    returnval = Py_BuildValue("(OO)", np_points, np_points_mask);
258
 
 
259
 
    if (index_sel_mirror != NULL)
260
 
        delete[] index_sel_mirror;
261
 
    if (value_sel_mirror != NULL)
262
 
        delete[] value_sel_mirror;
263
 
    if (points != NULL)
264
 
        delete[] points;
265
 
    if (points_mask != NULL)
266
 
        delete[] points_mask;
267
 
 
268
 
    Py_DECREF(np_points);
269
 
    Py_DECREF(np_points_mask);
270
 
 
271
 
#if DEBUG_SPEEDUP
272
 
    printf("Built return value and DECREFed\n");
273
 
#endif
274
 
 
275
 
cleanup:
276
 
    Py_XDECREF(index);
277
 
    Py_XDECREF(index_mask);
278
 
    Py_XDECREF(index_sel);
279
 
    Py_XDECREF(index_sel_mask);
280
 
    Py_XDECREF(value);
281
 
    Py_XDECREF(value_mask);
282
 
    Py_XDECREF(value_sel);
283
 
    Py_XDECREF(value_sel_mask);
284
 
 
285
 
#if DEBUG_SPEEDUP
286
 
    printf("About to return\n");
287
 
    fflush(stdout);
288
 
#endif
289
 
    return returnval;
290
 
}
291
 
 
292
 
 
293
 
static PyMethodDef speedups_methods[] = {
294
 
    {"scatterplot_gather_points", (PyCFunction)scatterplot_gather_points, 
295
 
         METH_VARARGS | METH_KEYWORDS, 
296
 
         scatterplot_gather_points_doc},
297
 
    {NULL, NULL, 0, NULL}
298
 
};
299
 
 
300
 
PyMODINIT_FUNC init_speedups(void)
301
 
{
302
 
    PyObject *module = Py_InitModule3("_speedups", speedups_methods,
303
 
                "Fast array range/NaN checking to accelerate plotting");
304
 
    if (module == NULL)
305
 
        return;
306
 
 
307
 
    import_array();
308
 
};
309