summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scipy/base/__init__.py1
-rw-r--r--scipy/base/_internal.py5
-rw-r--r--scipy/base/chararray.py23
-rw-r--r--scipy/base/records.py65
-rw-r--r--scipy/base/src/arraymethods.c11
-rw-r--r--scipy/base/src/arrayobject.c6
-rw-r--r--scipy/base/src/ufuncobject.c6
7 files changed, 61 insertions, 56 deletions
diff --git a/scipy/base/__init__.py b/scipy/base/__init__.py
index 60c4fb723..2cffbf759 100644
--- a/scipy/base/__init__.py
+++ b/scipy/base/__init__.py
@@ -21,6 +21,7 @@ from polynomial import *
from machar import *
from getlimits import *
import ma
+import chararray as char
import records as rec
from records import *
from memmap import *
diff --git a/scipy/base/_internal.py b/scipy/base/_internal.py
index a39ac2641..7dcfdd882 100644
--- a/scipy/base/_internal.py
+++ b/scipy/base/_internal.py
@@ -2,7 +2,7 @@
#A place for code to be called from C-code
# that implements more complicated stuff.
-from multiarray import _flagdict, dtypedescr
+from multiarray import _flagdict, dtypedescr, ndarray
_defflags = _flagdict.keys()
@@ -280,3 +280,6 @@ def _array_descr(descriptor):
result.append(tup)
return result
+
+def _reconstruct(subtype, shape, dtype):
+ return ndarray.__new__(subtype, shape, dtype)
diff --git a/scipy/base/chararray.py b/scipy/base/chararray.py
index 6a6195b04..3133de07b 100644
--- a/scipy/base/chararray.py
+++ b/scipy/base/chararray.py
@@ -3,12 +3,14 @@ from numerictypes import character, string, unicode_, \
from numeric import ndarray, broadcast, empty, array
import sys
+__all__ = ['chararray']
+
# special sub-class for character arrays (string and unicode_)
# This adds equality testing and methods of str and unicode types
# which operate on an element-by-element basis
-class ndchararray(ndarray):
+class chararray(ndarray):
def __new__(subtype, shape, itemlen=1, unicode=False, buffer=None,
offset=0, strides=None, swap=0, fortran=0):
@@ -28,9 +30,6 @@ class ndchararray(ndarray):
swap=swap, fortran=fortran)
return self
- def __reduce__(self):
- pass
-
def _richcmpfunc(self, other, op):
b = broadcast(self, other)
result = empty(b.shape, dtype=bool)
@@ -282,9 +281,9 @@ class ndchararray(ndarray):
def zfill(self, width):
return self._generalmethod('zfill', broadcast(self, width))
-
-def chararray(obj, itemlen=7, copy=True, unicode=False, fortran=False):
-
+
+def array(obj, itemlen=7, copy=True, unicode=False, fortran=False):
+
if isinstance(obj, ndchararray):
if copy or (itemlen != obj.itemlen) \
or (not unicode and obj.dtype == unicode_) \
@@ -320,10 +319,10 @@ def chararray(obj, itemlen=7, copy=True, unicode=False, fortran=False):
val = array(obj, dtype=dtype, fortran=fortran, subok=1)
- return ndchararray(val.shape, itemlen, unicode, buffer=val,
- strides=val.strides, swap=val.flags.swapped,
- fortran=fortran)
-
-def aschararray(obj, itemlen=7, unicode=False, fortran=False):
+ return chararray(val.shape, itemlen, unicode, buffer=val,
+ strides=val.strides, swap=val.flags.swapped,
+ fortran=fortran)
+
+def asarray(obj, itemlen=7, unicode=False, fortran=False):
return chararray(obj, itemlen, copy=False,
unicode=unicode, fortran=fortran)
diff --git a/scipy/base/records.py b/scipy/base/records.py
index 62eb76777..0b2a6be6a 100644
--- a/scipy/base/records.py
+++ b/scipy/base/records.py
@@ -247,9 +247,8 @@ class record(nt.void):
# The recarray is almost identical to a standard array (which supports
-# named fields already) The biggest difference is that it is always of
-# record data-type, has fields, and can use attribute-lookup to access
-# those fields.
+# named fields already) The biggest difference is that it can use
+# attribute-lookup to the fields.
class recarray(sb.ndarray):
@@ -257,7 +256,7 @@ class recarray(sb.ndarray):
buf=None, offset=0, strides=None, swap=0, aligned=0):
if isinstance(formats, sb.dtypedescr):
- descr = formats
+ descr = formats
elif isinstance(formats,str):
parsed = format_parser(formats, names, titles, aligned)
descr = parsed._descr
@@ -312,6 +311,9 @@ def fromarrays(arrayList, formats=None, names=None, titles=None, shape=None,
if shape is None or shape == 0:
shape = arrayList[0].shape
+
+ if isinstance(shape, int):
+ shape = (shape,)
if formats is None:
# go through each object in the list to see if it is an ndarray
@@ -344,7 +346,8 @@ def fromarrays(arrayList, formats=None, names=None, titles=None, shape=None,
return _array
-def fromrecords(recList, formats=None, names=None, shape=0, swap=0, aligned=0):
+def fromrecords(recList, formats=None, names=None, titles=None, shape=None,
+ swap=0, aligned=0):
""" create a Record Array from a list of records in text form
The data in the same field can be heterogeneous, they will be promoted
@@ -358,9 +361,9 @@ def fromrecords(recList, formats=None, names=None, shape=0, swap=0, aligned=0):
>>> r=fromrecords([[456,'dbe',1.2],[2,'de',1.3]],names='col1,col2,col3')
>>> print r[0]
(456, 'dbe', 1.2)
- >>> r.field('col1')
+ >>> r.col1
array([456, 2])
- >>> r.field('col2')
+ >>> r.col2
array(['dbe', 'de'])
>>> import cPickle
>>> print cPickle.loads(cPickle.dumps(r))
@@ -370,30 +373,28 @@ def fromrecords(recList, formats=None, names=None, shape=0, swap=0, aligned=0):
]
"""
- if shape == 0:
- _shape = len(recList)
- else:
- _shape = shape
-
- _nfields = len(recList[0])
- for _rec in recList:
- if len(_rec) != _nfields:
- raise ValueError, "inconsistent number of objects in each record"
- arrlist = [0]*_nfields
- for col in range(_nfields):
- tmp = [0]*_shape
- for row in range(_shape):
- tmp[row] = recList[row][col]
- try:
- arrlist[col] = num.array(tmp)
- except:
- try:
- arrlist[col] = chararray.array(tmp)
- except:
- raise ValueError, "inconsistent data at row %d,field %d" % (row, col)
- _array = fromarrays(arrlist, formats=formats, shape=_shape, names=names,
- byteorder=byteorder, aligned=aligned)
- del arrlist
- del tmp
+ if (shape is None or shape == 0):
+ shape = len(recList)
+
+ if isinstance(shape, int):
+ shape = (shape,)
+
+ nfields = len(recList[0])
+ if formats is None: # slower
+ obj = sb.array(recList,dtype=object)
+ arrlist = [sb.array(obj[:,i].tolist()) for i in xrange(nfields)]
+ return fromarrays(arrlist, formats=formats, shape=shape, names=names,
+ titles=titles, swap=swap, aligned=aligned)
+
+ parsed = format_parser(formats, names, titles, aligned)
+ _names = parsed._names
+ _array = recarray(shape, parsed._descr, swap=swap)
+
+ farr = _array.flat
+
+ for k in xrange(_array.size):
+ for j in xrange(nfields):
+ farr[k][_names[j]] = recList[k][j]
+
return _array
diff --git a/scipy/base/src/arraymethods.c b/scipy/base/src/arraymethods.c
index 0cca98896..089aedf23 100644
--- a/scipy/base/src/arraymethods.c
+++ b/scipy/base/src/arraymethods.c
@@ -863,19 +863,18 @@ array_reduce(PyArrayObject *self, PyObject *args)
ret = PyTuple_New(3);
if (ret == NULL) return NULL;
- mod = PyImport_ImportModule("scipy.base.multiarray");
+ mod = PyImport_ImportModule("scipy.base._internal");
if (mod == NULL) {Py_DECREF(ret); return NULL;}
- obj = PyObject_GetAttrString(mod, "empty");
+ obj = PyObject_GetAttrString(mod, "_reconstruct");
Py_DECREF(mod);
- if (obj == NULL) {Py_DECREF(ret); return NULL;}
PyTuple_SET_ITEM(ret, 0, obj);
PyTuple_SET_ITEM(ret, 1,
- Py_BuildValue("NNN",
+ Py_BuildValue("ONN",
+ (PyObject *)self->ob_type,
Py_BuildValue("(N)",
PyInt_FromLong(0)),
PyObject_GetAttrString((PyObject *)self,
- "dtypechar"),
- PyInt_FromLong((long) self->descr->elsize)));
+ "dtypechar")));
/* Now fill in object's state. This is a tuple with
4 arguments
diff --git a/scipy/base/src/arrayobject.c b/scipy/base/src/arrayobject.c
index ba4d17762..2610fe59c 100644
--- a/scipy/base/src/arrayobject.c
+++ b/scipy/base/src/arrayobject.c
@@ -8047,7 +8047,7 @@ arraydescr_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
}
if (!PyArray_DescrConverter(odescr, &conv))
return NULL;
- /* Get a new copy of it */
+ /* Get a new copy of it (so it can be changed in setstate) */
descr = PyArray_DescrNew(conv);
Py_DECREF(conv);
return (PyObject *)descr;
@@ -8072,7 +8072,9 @@ arraydescr_reduce(PyArray_Descr *self, PyObject *args)
Py_DECREF(mod);
if (obj == NULL) {Py_DECREF(ret); return NULL;}
PyTuple_SET_ITEM(ret, 0, obj);
- if (PyTypeNum_ISUSERDEF(self->type_num)) {
+ if (PyTypeNum_ISUSERDEF(self->type_num) || \
+ ((self->type_num == PyArray_VOID && \
+ self->typeobj != &PyVoidArrType_Type))) {
obj = (PyObject *)self->typeobj;
Py_INCREF(obj);
}
diff --git a/scipy/base/src/ufuncobject.c b/scipy/base/src/ufuncobject.c
index a3d508a7d..4cf5b9c41 100644
--- a/scipy/base/src/ufuncobject.c
+++ b/scipy/base/src/ufuncobject.c
@@ -1374,10 +1374,10 @@ _printcastbuf(PyUFuncLoopObject *loop, int bufnum)
/* currently generic ufuncs cannot be built for use on flexible arrays.
The cast functions in the generic loop would need to be fixed to pass
- something besides NULL, NULL.
+ in something besides NULL, NULL.
- Also the underlying ufunc loops would not know the array size unless
- that were passed in as data.
+ Also the underlying ufunc loops would not know the element-size unless
+ that was passed in as data (which could be arranged).
*/