source: orange/source/orange/numeric_interface.cpp @ 10603:72edca6ef4bc

Revision 10603:72edca6ef4bc, 6.9 KB checked in by Janez Demšar <janez.demsar@…>, 2 years ago (diff)

Fixed the code for constructing ExampleTable from masked array

Line 
1/*
2    This file is part of Orange.
3   
4    Copyright 1996-2010 Faculty of Computer and Information Science, University of Ljubljana
5    Contact: janez.demsar@fri.uni-lj.si
6
7    Orange is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11
12    Orange is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with Orange.  If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "numeric_interface.hpp"
22#include "errors.hpp"
23
24bool importarray_called = false;
25
26PyObject *moduleNumeric = NULL, *moduleNumarray = NULL, *moduleNumpy = NULL;
27PyObject *numericMaskedArray = NULL, *numarrayMaskedArray = NULL, *numpyMaskedArray = NULL;
28PyTypeObject *PyNumericArrayType = NULL, *PyNumarrayArrayType = NULL, *PyNumpyArrayType = NULL;
29
30void initializeNumTypes()
31{
32  PyObject *ma;
33 
34  moduleNumeric = PyImport_ImportModule("Numeric");
35  if (moduleNumeric) {
36    PyNumericArrayType = (PyTypeObject *)PyDict_GetItemString(PyModule_GetDict(moduleNumeric), "ArrayType");
37   
38    ma = PyImport_ImportModule("MA");
39    if (ma)
40      numericMaskedArray = PyDict_GetItemString(PyModule_GetDict(ma), "MaskedArray");
41  }
42  else
43    PyErr_Clear();
44 
45  moduleNumarray = PyImport_ImportModule("numarray");
46  if (moduleNumarray) {
47    PyNumarrayArrayType = (PyTypeObject *)PyDict_GetItemString(PyModule_GetDict(moduleNumarray), "ArrayType");
48
49    ma = PyImport_ImportModule("numarray.ma");
50    if (ma)
51      numarrayMaskedArray = PyDict_GetItemString(PyModule_GetDict(ma), "MaskedArray");
52  }
53  else
54    PyErr_Clear();
55
56  moduleNumpy = PyImport_ImportModule("numpy");
57  if (moduleNumpy) {
58    PyObject *mdict = PyModule_GetDict(moduleNumpy);
59    PyNumpyArrayType = (PyTypeObject *)PyDict_GetItemString(mdict, "ndarray");
60   
61    ma = PyDict_GetItemString(mdict, "ma");
62    if (ma)
63      numpyMaskedArray = PyDict_GetItemString(PyModule_GetDict(ma), "MaskedArray");
64  }
65  else
66    PyErr_Clear();
67   
68  importarray_called = true;
69//  import_array();
70}
71
72
73// avoids unnecessarily importing the numeric modules
74bool isSomeNumeric_wPrecheck(PyObject *args) {
75  static char *numericNames[] = {"array", "numpy.ndarray", "ndarray", "numarray.numarraycore.NumArray", "NumArray", 0};
76  for(char **nni = numericNames; *nni; nni++)
77    if (!strcmp(args->ob_type->tp_name, *nni))
78      return isSomeNumeric(args);
79  return false;
80}
81
82
83bool isSomeNumeric(PyObject *obj)
84{
85  if (!importarray_called)
86    initializeNumTypes();
87   
88  return     PyNumericArrayType && PyType_IsSubtype(obj->ob_type, PyNumericArrayType)
89          || PyNumarrayArrayType && PyType_IsSubtype(obj->ob_type, PyNumarrayArrayType)
90          || PyNumpyArrayType && PyType_IsSubtype(obj->ob_type, PyNumpyArrayType);
91}
92 
93bool isSomeMaskedNumeric_wPrecheck(PyObject *args) {
94  static char *numericNames[] = {"MaskedArray", "numpy.ma.core.MaskedArray", "numarray.ma.MA.MaskedArray", 0};
95  for(char **nni = numericNames; *nni; nni++)
96    if (!strcmp(args->ob_type->tp_name, *nni))
97      return isSomeMaskedNumeric(args);
98  return false;
99}
100
101
102bool isSomeMaskedNumeric(PyObject *obj)
103{
104  if (!importarray_called)
105    initializeNumTypes();
106   
107  return     numarrayMaskedArray && PyType_IsSubtype(obj->ob_type, (PyTypeObject *)numarrayMaskedArray)
108          || numpyMaskedArray && PyType_IsSubtype(obj->ob_type, (PyTypeObject *)numpyMaskedArray);
109}
110 
111
112char getArrayType(PyObject *args)
113{
114  PyObject *res = PyObject_CallMethod(args, "typecode", NULL);
115  if (!res) {
116    PyErr_Clear();
117    PyObject *ress = PyObject_GetAttrString(args, "dtype");
118    if (ress) {
119      res = PyObject_GetAttrString(ress, "char");
120      Py_DECREF(ress);
121    }
122  }
123 
124  if (!res) {
125    PyErr_Clear();
126    return -1;
127  }
128 
129  char cres = PyString_AsString(res)[0];
130  Py_DECREF(res);
131  return cres;
132}
133
134
135void numericToDouble(PyObject *args, double *&matrix, int &columns, int &rows)
136{
137  prepareNumeric();
138
139  if (!isSomeNumeric(args))
140    raiseErrorWho("numericToDouble", "invalid type (got '%s', expected 'ArrayType')", args->ob_type->tp_name);
141
142  PyArrayObject *array = (PyArrayObject *)(args);
143  if (array->nd != 2)
144    raiseErrorWho("numericToDouble", "two-dimensional array expected");
145
146  const char arrayType = getArrayType(array);
147  if (!strchr(supportedNumericTypes, arrayType))
148    raiseErrorWho("numericToDouble", "ExampleTable cannot use arrays of complex numbers or Python objects", NULL);
149
150  columns = array->dimensions[1];
151  rows = array->dimensions[0];
152  matrix = new double[columns * rows];
153 
154  const int &strideRow = array->strides[0];
155  const int &strideCol = array->strides[1];
156 
157  double *matrixi = matrix;
158  char *coli, *cole;
159
160  for(char *rowi = array->data, *rowe = array->data + rows*strideRow; rowi != rowe; rowi += strideRow) {
161    #define READLINE(TYPE) \
162      for(coli = rowi, cole = rowi + columns*strideCol; coli != cole; *matrixi++ = double(*(TYPE *)coli), coli += strideCol); \
163      break;
164
165    switch (arrayType) {
166      case 'c':
167      case 'b': READLINE(char)
168      case 'B': READLINE(unsigned char)
169      case 'h': READLINE(short)
170      case 'H': READLINE(unsigned short)
171      case 'i': READLINE(int)
172      case 'I': READLINE(unsigned int)
173      case 'l': READLINE(long)
174      case 'L': READLINE(unsigned long)
175      case 'f': READLINE(float)
176      case 'd': READLINE(double)
177    }
178
179    #undef READLINE
180  }
181}
182
183
184void numericToDouble(PyObject *args, double *&matrix, int &rows)
185{
186  prepareNumeric();
187
188  if (!isSomeNumeric(args))
189    raiseErrorWho("numericToDouble", "invalid type (got '%s', expected 'ArrayType')", args->ob_type->tp_name);
190
191  PyArrayObject *array = (PyArrayObject *)(args);
192  if (array->nd != 1)
193    raiseErrorWho("numericToDouble", "one-dimensional array expected");
194
195  const char arrayType = getArrayType(array);
196  if (!strchr(supportedNumericTypes, arrayType))
197    raiseError("numericToDouble", "ExampleTable cannot use arrays of complex numbers or Python objects", NULL);
198
199  rows = array->dimensions[0];
200  matrix = new double[rows];
201 
202  const int &strideRow = array->strides[0];
203 
204  double *matrixi = matrix;
205  char *rowi, *rowe;
206
207  #define READLINE(TYPE) \
208    for(rowi = array->data, rowe = array->data + rows*strideRow; rowi != rowe; *matrixi++ = double(*(TYPE *)rowi), rowi += strideRow); \
209    break;
210
211  switch (arrayType) {
212      case 'c':
213      case 'b': READLINE(char)
214      case 'B': READLINE(unsigned char)
215      case 'h': READLINE(short)
216      case 'H': READLINE(unsigned short)
217      case 'i': READLINE(int)
218      case 'I': READLINE(unsigned int)
219      case 'l': READLINE(long)
220      case 'L': READLINE(unsigned long)
221      case 'f': READLINE(float)
222      case 'd': READLINE(double)
223  }
224
225  #undef READLINE
226}
Note: See TracBrowser for help on using the repository browser.