Esempio n. 1
0
def tips(molID, isoID, temp):
  """
  Evaluate the partition function for the given isotope(s) at the given
  temperature(s).  This is a wrapper of ctips.tips.

  Parameters:
  -----------
  molID: Scalar or iterable
     The molecular ID as given by HITRAN 2012.
  isoID: Scalar or iterable
     The isotope ID (AFGL) as given by HITRAN 2012.
  temp:  Scalar or iterable
     Temperature a which to evaluate the partition function.

  Notes:
  ------
  - The molID and isoID are casted into an integer ndarray data types.
  - The temp is casted into a double ndarray data type.
  - If the arguments have different sizes, the code resizes them to
    a same size, unless they have incompatible sizes.
  """
  # Check scalar vs iterable, turn into iterable:
  if isscalar(molID):
    molID = [molID]
  if isscalar(isoID):
    isoID = [isoID]
  if isscalar(temp):
    temp = [temp]

  # Turn them numpy arrays:
  molID = np.asarray(molID, np.int)
  isoID = np.asarray(isoID, np.int)
  temp  = np.asarray(temp,  np.double)

  # Set them to the same size:
  if len(isoID) != len(temp):
    if   len(isoID) == 1:
      isoID = np.repeat(isoID, len(temp))
    elif len(temp)  == 1:
      temp  = np.repeat(temp,  len(isoID))
    else:
      sys.exit(0)

  if len(molID) != len(isoID):
    if len(molID) != 1:
      sys.exit(0)
    molID = np.repeat(molID, len(isoID))

  return ct.tips(molID, isoID, temp)
Esempio n. 2
0
def tips(molID, isoID, temp):
    """
  Evaluate the partition function for the given isotope(s) at the given
  temperature(s).  This is a wrapper of ctips.tips.

  Parameters
  ----------
  molID: Scalar or iterable
     The molecular ID as given by HITRAN 2012.
  isoID: Scalar or iterable
     The isotope ID (AFGL) as given by HITRAN 2012.
  temp:  Scalar or iterable
     Temperature a which to evaluate the partition function.

  Notes
  -----
  - The molID and isoID are casted into an integer ndarray data types.
  - The temp is casted into a double ndarray data type.
  - If the arguments have different sizes, the code resizes them to
    a same size, unless they have incompatible sizes.
  """
    # Check scalar vs iterable, turn into iterable:
    if isscalar(molID):
        molID = [molID]
    if isscalar(isoID):
        isoID = [isoID]
    if isscalar(temp):
        temp = [temp]

    # Turn them numpy arrays:
    molID = np.asarray(molID, np.int)
    isoID = np.asarray(isoID, np.int)
    temp = np.asarray(temp, np.double)

    # Set them to the same size:
    if len(isoID) != len(temp):
        if len(isoID) == 1:
            isoID = np.repeat(isoID, len(temp))
        elif len(temp) == 1:
            temp = np.repeat(temp, len(isoID))
        else:
            sys.exit(0)

    if len(molID) != len(isoID):
        if len(molID) != 1:
            sys.exit(0)
        molID = np.repeat(molID, len(isoID))

    return ct.tips(molID, isoID, temp)
Esempio n. 3
0
    def __getitem__(self, index):
        self._getitem = True

        try:
            out = N.ndarray.__getitem__(self, index)
        finally:
            self._getitem = False

        if not isinstance(out, N.ndarray):
            return out

        if out.ndim == 0:
            return out[()]
        if out.ndim == 1:
            sh = out.shape[0]
            # Determine when we should have a column array
            try:
                n = len(index)
            except:
                n = 0
            if n > 1 and isscalar(index[1]):
                out.shape = (sh, 1)
            else:
                out.shape = (1, sh)
        return out
Esempio n. 4
0
    def __getitem__(self, index):
        self._getitem = True

        try:
            out = N.ndarray.__getitem__(self, index)
        finally:
            self._getitem = False

        if not isinstance(out, N.ndarray):
            return out

        if out.ndim == 0:
            return out[()]
        if out.ndim == 1:
            sh = out.shape[0]
            # Determine when we should have a column array
            try:
                n = len(index)
            except:
                n = 0
            if n > 1 and isscalar(index[1]):
                out.shape = (sh, 1)
            else:
                out.shape = (1, sh)
        return out
Esempio n. 5
0
 def __mul__(self, other):
     if isinstance(other, (N.ndarray, list, tuple)):
         # This promotes 1-D vectors to row vectors
         return N.dot(self, asmatrix(other))
     if isscalar(other) or not hasattr(other, '__rmul__'):
         return N.dot(self, other)
     return NotImplemented
Esempio n. 6
0
 def __init__(self, dimension=1, randomize=True, seed=None):
     """
     Args:
         dimension (int): dimension of samples
         randomize (bool): scramble points? 
         seeds (list): int seed of list of seeds, one for each dimension.
     """
     try:
         from scipy.stats.qmc import Sobol as SobolScipyOG
     except:
         raise ParameterError(
             "scipy.stats.qmc.Sobol not found, try updating to scipy>=1.7.0"
         )
     self.parameters = ['randomize', 'graycode']
     if not isscalar(dimension):
         raise ParameterError(
             "SobolSciPy does not support vectorized dimension indexing")
     self.randomize = randomize
     self.graycode = True
     self.mimics = 'StdUniform'
     self.low_discrepancy = True
     self.d_max = 21201
     super(SobolSciPy, self).__init__(dimension, seed)
     self.sobol = SobolScipyOG(self.d,
                               scramble=self.randomize,
                               seed=self.entropy)
     self.ncurrent = 0
Esempio n. 7
0
def apply_along_axis(func1d,axis,arr,*args):
    """ Execute func1d(arr[i],*args) where func1d takes 1-D arrays
        and arr is an N-d array.  i varies so as to apply the function
        along the given axis for each 1-d subarray in arr.
    """
    arr = asarray(arr)
    nd = arr.ndim
    if axis < 0:
        axis += nd
    if (axis >= nd):
        raise ValueError("axis must be less than arr.ndim; axis=%d, rank=%d."
            % (axis,nd))
    ind = [0]*(nd-1)
    i = zeros(nd,'O')
    indlist = range(nd)
    indlist.remove(axis)
    i[axis] = slice(None,None)
    outshape = asarray(arr.shape).take(indlist)
    i.put(indlist, ind)
    res = func1d(arr[tuple(i.tolist())],*args)
    #  if res is a number, then we have a smaller output array
    if isscalar(res):
        outarr = zeros(outshape,asarray(res).dtype)
        outarr[tuple(ind)] = res
        Ntot = product(outshape)
        k = 1
        while k < Ntot:
            # increment the index
            ind[-1] += 1
            n = -1
            while (ind[n] >= outshape[n]) and (n > (1-nd)):
                ind[n-1] += 1
                ind[n] = 0
                n -= 1
            i.put(indlist,ind)
            res = func1d(arr[tuple(i.tolist())],*args)
            outarr[tuple(ind)] = res
            k += 1
        return outarr
    else:
        Ntot = product(outshape)
        holdshape = outshape
        outshape = list(arr.shape)
        outshape[axis] = len(res)
        outarr = zeros(outshape,asarray(res).dtype)
        outarr[tuple(i.tolist())] = res
        k = 1
        while k < Ntot:
            # increment the index
            ind[-1] += 1
            n = -1
            while (ind[n] >= holdshape[n]) and (n > (1-nd)):
                ind[n-1] += 1
                ind[n] = 0
                n -= 1
            i.put(indlist, ind)
            res = func1d(arr[tuple(i.tolist())],*args)
            outarr[tuple(i.tolist())] = res
            k += 1
        return outarr
Esempio n. 8
0
def apply_along_axis(func1d, axis, arr, *args):
    """ Execute func1d(arr[i],*args) where func1d takes 1-D arrays
        and arr is an N-d array.  i varies so as to apply the function
        along the given axis for each 1-d subarray in arr.
    """
    arr = asarray(arr)
    nd = arr.ndim
    if axis < 0:
        axis += nd
    if (axis >= nd):
        raise ValueError("axis must be less than arr.ndim; axis=%d, rank=%d." %
                         (axis, nd))
    ind = [0] * (nd - 1)
    i = zeros(nd, 'O')
    indlist = range(nd)
    indlist.remove(axis)
    i[axis] = slice(None, None)
    outshape = asarray(arr.shape).take(indlist)
    i.put(indlist, ind)
    res = func1d(arr[tuple(i.tolist())], *args)
    #  if res is a number, then we have a smaller output array
    if isscalar(res):
        outarr = zeros(outshape, asarray(res).dtype)
        outarr[tuple(ind)] = res
        Ntot = product(outshape)
        k = 1
        while k < Ntot:
            # increment the index
            ind[-1] += 1
            n = -1
            while (ind[n] >= outshape[n]) and (n > (1 - nd)):
                ind[n - 1] += 1
                ind[n] = 0
                n -= 1
            i.put(indlist, ind)
            res = func1d(arr[tuple(i.tolist())], *args)
            outarr[tuple(ind)] = res
            k += 1
        return outarr
    else:
        Ntot = product(outshape)
        holdshape = outshape
        outshape = list(arr.shape)
        outshape[axis] = len(res)
        outarr = zeros(outshape, asarray(res).dtype)
        outarr[tuple(i.tolist())] = res
        k = 1
        while k < Ntot:
            # increment the index
            ind[-1] += 1
            n = -1
            while (ind[n] >= holdshape[n]) and (n > (1 - nd)):
                ind[n - 1] += 1
                ind[n] = 0
                n -= 1
            i.put(indlist, ind)
            res = func1d(arr[tuple(i.tolist())], *args)
            outarr[tuple(i.tolist())] = res
            k += 1
        return outarr
Esempio n. 9
0
 def __mul__(self, other):
     if isinstance(other, (N.ndarray, list, tuple)) :
         # This promotes 1-D vectors to row vectors
         return N.dot(self, asmatrix(other))
     if isscalar(other) or not hasattr(other, '__rmul__') :
         return N.dot(self, other)
     return NotImplemented
Esempio n. 10
0
    def __imul__(self, other):
        if not isscalar(other):
            return NotImplemented

        self.ent_table = self.ent_table * other
        self.att_table = [t * other for t in self.att_table]

        return self
Esempio n. 11
0
    def __pow__(self, other):
        if not isscalar(other):
            return NotImplemented

        return self._copy(
            (self.ent_table.power(other) if sp.issparse(self.ent_table) else
             np.power(self.ent_table, other)),
            [(t.power(other) if sp.issparse(t) else np.power(t, other))
             for t in self.att_table])
Esempio n. 12
0
 def __ipow__(self, other):
     if not isscalar(other):
         return NotImplemented
     self.ent_table = self.ent_table.power(2) if sp.issparse(
         self.ent_table) else np.power(self.ent_table, other)
     self.att_table = [
         (t.power(other) if sp.issparse(t) else np.power(t, other))
         for t in self.att_table
     ]
     return self
Esempio n. 13
0
 def __rmul__(self, other):
     # ! NumPy's matrix __rmul__ uses an apparently restrictive
     # dot() function that cannot handle the multiplication of a
     # scalar and of a matrix containing objects (when the
     # arguments are given in this order).  We go around this
     # limitation:
     if numeric.isscalar(other):
         return numeric.dot(self, other)
     else:
         return numeric.dot(other, self)  # The order is important
Esempio n. 14
0
 def __rmul__(self, other):
     # ! NumPy's matrix __rmul__ uses an apparently a restrictive
     # dot() function that cannot handle the multiplication of a
     # scalar and of a matrix containing objects (when the
     # arguments are given in this order).  We go around this
     # limitation:
     if numeric.isscalar(other):
         return numeric.dot(self, other)
     else:
         return numeric.dot(other, self)  # The order is important
Esempio n. 15
0
    def __rmul__(self, other):
        if isinstance(other, (N.ndarray, list, tuple)):
            if self.trans:
                return self._left_matrix_multiplication(self, asmatrix(other).T).T
            else:
                return self._right_matrix_multiplication(self, asmatrix(other))

        if isscalar(other) or not hasattr(other, '__rmul__'):
            return self._copy(self.ent_table, self.att_table, a=self.a*other)

        return NotImplemented
Esempio n. 16
0
    def __pow__(self, other):
        if not isscalar(other) or self.b != 0.0:
            return NotImplemented

        return self._copy(
            (self.ent_table.power(other) if sp.issparse(self.ent_table) else np.power(self.ent_table, other)),
            [(t.power(other) if sp.issparse(t) else np.power(t, other)) for t in self.att_table],
            a=self.a**other, c=self.c*other,
            shadow_att=([(t.power(other) if sp.issparse(t) else np.power(t, other)) for t in self.shadow_att_table]
                        if self.shadow_att_table is not None else None),
            shadow_ent=((self.shadow_ent_table.power(other) if sp.issparse(self.shadow_ent_table)
                         else np.power(self.shadow_ent_table, other)) if self.shadow_ent_table is not None else None))
Esempio n. 17
0
 def __add__(self, other):
     if isscalar(other):
         if self.isMorpheus:
             raise NotImplementedError
         else:
             newMat = self.inner("scalarAddition", other)
             return NormalizedMatrix(mat=newMat, avatar=self.avatar)
     if self.isMorpheus:
         return NotImplementedError
     else:
         newMat = self.inner("matrixAddition", other.mat)
         return NormalizedMatrix(mat=newMat, avatar=self.avatar)
     return self.normalizedTable.matrixAddition(other).unwrap()
Esempio n. 18
0
 def __mul__(self, other):
     if self.shape == (1,1):
         # extract scalars from singleton matrices (self)
         return N.dot(self.flat[0], other)
     if isinstance(other, N.ndarray) and other.shape == (1,1):
         # extract scalars from singleton matrices (other)
         return N.dot(self, other.flat[0])
     if isinstance(other, (N.ndarray, list, tuple)) :
         # This promotes 1-D vectors to row vectors
         return N.dot(self, asmatrix(other))
     if isscalar(other) or not hasattr(other, '__rmul__') :
         return N.dot(self, other)
     return NotImplemented
Esempio n. 19
0
    def __rpow__(self, other):
        if not isscalar(other):
            return NotImplemented

        return self._copy(
            np.power(
                other,
                self.ent_table.toarray()
                if sp.issparse(self.ent_table) else self.ent_table), [
                    np.power(other,
                             t.toarray() if sp.issparse(t) else t)
                    for t in self.att_table
                ])
Esempio n. 20
0
    def __ipow__(self, other):
        if not isscalar(other) or self.b != 0.0:
            return NotImplemented
        self.c = self.c * other
        self.a = self.a ** other
        self.ent_table = self.ent_table.power(2) if sp.issparse(self.ent_table) else np.power(self.ent_table, other)
        self.att_table = [(t.power(other) if sp.issparse(t) else np.power(t, other)) for t in self.att_table]
        if self.shadow_att_table is not None:
            self.shadow_att_table = [(t.power(other) if sp.issparse(t) else np.power(t, other))
                                     for t in self.shadow_att_table]
        if self.shadow_ent_table is not None:
            self.shadow_ent_table = (self.shadow_ent_table.power(other) if self.shadow_ent_table is not None else None)

        return self
Esempio n. 21
0
    def __rdiv__(self, other):
        if isscalar(other):
            return self._copy(other / self.ent_table,
                              [other / t for t in self.att_table])

        if isinstance(other, (N.ndarray, list, tuple)):
            other = asmatrix(other)
            if other.shape[1] == self.shape[1] and other.shape[0] == 1:
                return self._copy(
                    other[:, :self.ent_table.shape[1]] / self.ent_table, [
                        other[:, self.indexes[i][0]:self.indexes[i][1]] / t
                        for i, t in enumerate(self.att_table)
                    ])

        return NotImplemented
Esempio n. 22
0
    def __rmul__(self, other):

        if isscalar(other):
            if self.isMorpheus:
                raise NotImplementedError
            else:
                newMat = self.inner("scalarMultiplication", other)
                return NormalizedMatrix(mat=newMat, avatar=self.avatar)

        if isinstance(other, NormalizedMatrix):
            if self.stamp == other.stamp and self.is_transposed ^ other.is_transposed:
                return self.normalizedTable.crossProduct().unwrap()
            else:
                raise NotImplementedError
        if isinstance(other, (N.ndarray, list, tuple)):
            raise NotImplementedError
        raise NotImplementedError
Esempio n. 23
0
    def __idiv__(self, other):
        if isscalar(other):
            self.ent_table = self.ent_table / other
            self.att_table = [t / other for t in self.att_table]
            return self

        if isinstance(other, (N.ndarray, list, tuple)):
            other = asmatrix(other)
            if other.shape[1] == self.shape[1] and other.shape[0] == 1:
                self.ent_table = self.ent_table / other[:, :self.ent_table.
                                                        shape[1]]
                self.att_table = [
                    t / other[:, self.indexes[i][0]:self.indexes[i][1]]
                    for i, t in enumerate(self.att_table)
                ]
                return self

        return NotImplemented
Esempio n. 24
0
    def __mul__(self, other):
        if isinstance(other, NormalizedMatrix):
            if self.stamp == other.stamp and self.trans ^ other.trans:
                return self._cross_prod()
            else:
                return NotImplemented

        if isinstance(other, (N.ndarray, list, tuple)):
            # This promotes 1-D vectors to row vectors
            if self.trans:
                return self._right_matrix_multiplication(self, asmatrix(other).T).T
            else:
                return self._left_matrix_multiplication(self, asmatrix(other))

        if isscalar(other) or not hasattr(other, '__rmul__'):
            return self._copy(self.ent_table, self.att_table, a=self.a*other)

        return NotImplemented
Esempio n. 25
0
    def __mul__(self, other):
        if isscalar(other):
            if self.isMorpheus:
                raise NotImplementedError
            else:
                newMat = self.inner("scalarMultiplication", other)
                return NormalizedMatrix(mat=newMat, avatar=self.avatar)
            return normMatrix

        elif isinstance(other, NormalizedMatrix):
            if self.isMorpheus:
                newMat = self.inner.leftMatrixMultiplication(other.mat)
                return NormalizedMatrix(mat=newMat, avatar=self.avatar)
            else:
                # Here the reason for the switch is that the names are backwards
                newMat = self.inner("rightMatrixMultiplication", other.mat)
                return NormalizedMatrix(mat=newMat, avatar=self.avatar)
        return NotImplemented
Esempio n. 26
0
    def __init__(self, pressure, gravity=None):
        """
        Parameters
        ----------
        pressure: 1D float ndarray
            Atmospheric pressure profile (barye).
        gravity: 1D float ndarray or scalar
            Atmospheric gravity profile (cm s-2).
            If None, assume a constant gravity of 1 cm s-2, in which
            case, one should regard the kappa parameter as
            kappa' = kappa/gravity.

        Note that the input gravity can be a scalar value used at all
        atmospheric pressures (as it has been used so far in the
        literature.  However, from a parametric point of view, this is
        redundant, as it only acts as a scaling factor for kappa.
        Ideally, one would wish to input a pressure-dependent gravity,
        but such profile would need to be derived from a hydrostatic
        equilibrium calculation, for example.  Unfortunately, HE cannot
        be solved without knowing the temperature, thus making this a
        circular problem (shrug emoji).
        """
        self.name = 'tcea'
        self.pnames = [
            "log(kappa')", 'log(gamma1)', 'log(gamma2)', 'alpha', 'T_irr (K)',
            'T_int (K)'
        ]
        self.texnames = [
            r"$\log_{10}(\kappa')$", r'$\log_{10}(\gamma_1)$',
            r'$\log_{10}(\gamma_2)$', r'$\alpha$', r'$T_{\rm irr} (K)$',
            r'$T_{\rm int} (K)$'
        ]
        self.npars = len(self.pnames)

        if gravity is None:
            gravity = np.tile(1.0, len(pressure))
        elif isscalar(gravity):
            gravity = np.tile(gravity, len(pressure))
        self.pressure = np.asarray(pressure, float)
        self.gravity = np.asarray(gravity, float)
        self.temp = np.zeros_like(pressure, float)
Esempio n. 27
0
 def within_tol(x, y, atol, rtol):
     with errstate(invalid='ignore'):
         result = less_equal(abs(x - y), atol + rtol * abs(y))
     if isscalar(a) and isscalar(b):
         result = bool(result)
     return result
Esempio n. 28
0
def apply_along_axis(func1d, axis, arr, *args, **kwargs):
    """
    Apply a function to 1-D slices along the given axis.

    Execute `func1d(a, *args)` where `func1d` operates on 1-D arrays and `a`
    is a 1-D slice of `arr` along `axis`.

    Parameters
    ----------
    func1d : function
        This function should accept 1-D arrays. It is applied to 1-D
        slices of `arr` along the specified axis.
    axis : integer
        Axis along which `arr` is sliced.
    arr : ndarray
        Input array.
    args : any
        Additional arguments to `func1d`.
    kwargs: any
        Additional named arguments to `func1d`.

        .. versionadded:: 1.9.0


    Returns
    -------
    apply_along_axis : ndarray
        The output array. The shape of `outarr` is identical to the shape of
        `arr`, except along the `axis` dimension, where the length of `outarr`
        is equal to the size of the return value of `func1d`.  If `func1d`
        returns a scalar `outarr` will have one fewer dimensions than `arr`.

    See Also
    --------
    apply_over_axes : Apply a function repeatedly over multiple axes.

    Examples
    --------
    >>> def my_func(a):
    ...     \"\"\"Average first and last element of a 1-D array\"\"\"
    ...     return (a[0] + a[-1]) * 0.5
    >>> b = np.array([[1,2,3], [4,5,6], [7,8,9]])
    >>> np.apply_along_axis(my_func, 0, b)
    array([ 4.,  5.,  6.])
    >>> np.apply_along_axis(my_func, 1, b)
    array([ 2.,  5.,  8.])

    For a function that doesn't return a scalar, the number of dimensions in
    `outarr` is the same as `arr`.

    >>> b = np.array([[8,1,7], [4,3,9], [5,2,6]])
    >>> np.apply_along_axis(sorted, 1, b)
    array([[1, 7, 8],
           [3, 4, 9],
           [2, 5, 6]])

    """
    arr = asarray(arr)
    nd = arr.ndim
    if axis < 0:
        axis += nd
    if (axis >= nd):
        raise ValueError("axis must be less than arr.ndim; axis=%d, rank=%d." %
                         (axis, nd))
    ind = [0] * (nd - 1)
    i = zeros(nd, 'O')
    indlist = list(range(nd))
    indlist.remove(axis)
    i[axis] = slice(None, None)
    outshape = asarray(arr.shape).take(indlist)
    i.put(indlist, ind)
    res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
    #  if res is a number, then we have a smaller output array
    if isscalar(res):
        outarr = zeros(outshape, asarray(res).dtype)
        outarr[tuple(ind)] = res
        Ntot = product(outshape)
        k = 1
        while k < Ntot:
            # increment the index
            ind[-1] += 1
            n = -1
            while (ind[n] >= outshape[n]) and (n > (1 - nd)):
                ind[n - 1] += 1
                ind[n] = 0
                n -= 1
            i.put(indlist, ind)
            res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
            outarr[tuple(ind)] = res
            k += 1
        return outarr
    else:
        Ntot = product(outshape)
        holdshape = outshape
        outshape = list(arr.shape)
        outshape[axis] = len(res)
        outarr = zeros(outshape, asarray(res).dtype)
        outarr[tuple(i.tolist())] = res
        k = 1
        while k < Ntot:
            # increment the index
            ind[-1] += 1
            n = -1
            while (ind[n] >= holdshape[n]) and (n > (1 - nd)):
                ind[n - 1] += 1
                ind[n] = 0
                n -= 1
            i.put(indlist, ind)
            res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
            outarr[tuple(i.tolist())] = res
            k += 1
        return outarr
def apply_along_axis(func1d,axis,arr,*args):
    """
    Apply a function to 1-D slices along the given axis.

    Execute `func1d(a, *args)` where `func1d` operates on 1-D arrays and `a`
    is a 1-D slice of `arr` along `axis`.

    Parameters
    ----------
    func1d : function
        This function should accept 1-D arrays. It is applied to 1-D
        slices of `arr` along the specified axis.
    axis : integer
        Axis along which `arr` is sliced.
    arr : ndarray
        Input array.
    args : any
        Additional arguments to `func1d`.

    Returns
    -------
    apply_along_axis : ndarray
        The output array. The shape of `outarr` is identical to the shape of
        `arr`, except along the `axis` dimension, where the length of `outarr`
        is equal to the size of the return value of `func1d`.  If `func1d`
        returns a scalar `outarr` will have one fewer dimensions than `arr`.

    See Also
    --------
    apply_over_axes : Apply a function repeatedly over multiple axes.

    Examples
    --------
    >>> def my_func(a):
    ...     \"\"\"Average first and last element of a 1-D array\"\"\"
    ...     return (a[0] + a[-1]) * 0.5
    >>> b = np.array([[1,2,3], [4,5,6], [7,8,9]])
    >>> np.apply_along_axis(my_func, 0, b)
    array([ 4.,  5.,  6.])
    >>> np.apply_along_axis(my_func, 1, b)
    array([ 2.,  5.,  8.])

    For a function that doesn't return a scalar, the number of dimensions in
    `outarr` is the same as `arr`.

    >>> def new_func(a):
    ...     \"\"\"Divide elements of a by 2.\"\"\"
    ...     return a * 0.5
    >>> b = np.array([[1,2,3], [4,5,6], [7,8,9]])
    >>> np.apply_along_axis(new_func, 0, b)
    array([[ 0.5,  1. ,  1.5],
           [ 2. ,  2.5,  3. ],
           [ 3.5,  4. ,  4.5]])

    """
    arr = asarray(arr)
    nd = arr.ndim
    if axis < 0:
        axis += nd
    if (axis >= nd):
        raise ValueError("axis must be less than arr.ndim; axis=%d, rank=%d."
            % (axis,nd))
    ind = [0]*(nd-1)
    i = zeros(nd,'O')
    indlist = list(range(nd))
    indlist.remove(axis)
    i[axis] = slice(None,None)
    outshape = asarray(arr.shape).take(indlist)
    i.put(indlist, ind)
    res = func1d(arr[tuple(i.tolist())],*args)
    #  if res is a number, then we have a smaller output array
    if isscalar(res):
        outarr = zeros(outshape,asarray(res).dtype)
        outarr[tuple(ind)] = res
        Ntot = product(outshape)
        k = 1
        while k < Ntot:
            # increment the index
            ind[-1] += 1
            n = -1
            while (ind[n] >= outshape[n]) and (n > (1-nd)):
                ind[n-1] += 1
                ind[n] = 0
                n -= 1
            i.put(indlist,ind)
            res = func1d(arr[tuple(i.tolist())],*args)
            outarr[tuple(ind)] = res
            k += 1
        return outarr
    else:
        Ntot = product(outshape)
        holdshape = outshape
        outshape = list(arr.shape)
        outshape[axis] = len(res)
        outarr = zeros(outshape,asarray(res).dtype)
        outarr[tuple(i.tolist())] = res
        k = 1
        while k < Ntot:
            # increment the index
            ind[-1] += 1
            n = -1
            while (ind[n] >= holdshape[n]) and (n > (1-nd)):
                ind[n-1] += 1
                ind[n] = 0
                n -= 1
            i.put(indlist, ind)
            res = func1d(arr[tuple(i.tolist())],*args)
            outarr[tuple(i.tolist())] = res
            k += 1
        return outarr
Esempio n. 30
0
def apply_along_axis(func1d,axis,arr,*args,**kwargs):
    """ Execute func1d(arr[i],*args) where func1d takes 1-D arrays
        and arr is an N-d array.  i varies so as to apply the function
        along the given axis for each 1-d subarray in arr.
    """
    arr = core.array(arr, copy=False, subok=True)
    nd = arr.ndim
    if axis < 0:
        axis += nd
    if (axis >= nd):
        raise ValueError("axis must be less than arr.ndim; axis=%d, rank=%d."
            % (axis,nd))
    ind = [0]*(nd-1)
    i = numeric.zeros(nd,'O')
    indlist = range(nd)
    indlist.remove(axis)
    i[axis] = slice(None,None)
    outshape = numeric.asarray(arr.shape).take(indlist)
    i.put(indlist, ind)
    j = i.copy()
    res = func1d(arr[tuple(i.tolist())],*args,**kwargs)
    #  if res is a number, then we have a smaller output array
    asscalar = numeric.isscalar(res)
    if not asscalar:
        try:
            len(res)
        except TypeError:
            asscalar = True
    # Note: we shouldn't set the dtype of the output from the first result...
    #...so we force the type to object, and build a list of dtypes
    #...we'll just take the largest, to avoid some downcasting
    dtypes = []
    if asscalar:
        dtypes.append(numeric.asarray(res).dtype)
        outarr = zeros(outshape, object_)
        outarr[tuple(ind)] = res
        Ntot = numeric.product(outshape)
        k = 1
        while k < Ntot:
            # increment the index
            ind[-1] += 1
            n = -1
            while (ind[n] >= outshape[n]) and (n > (1-nd)):
                ind[n-1] += 1
                ind[n] = 0
                n -= 1
            i.put(indlist,ind)
            res = func1d(arr[tuple(i.tolist())],*args,**kwargs)
            outarr[tuple(ind)] = res
            dtypes.append(asarray(res).dtype)
            k += 1
    else:
        res = core.array(res, copy=False, subok=True)
        j = i.copy()
        j[axis] = ([slice(None,None)] * res.ndim)
        j.put(indlist, ind)
        Ntot = numeric.product(outshape)
        holdshape = outshape
        outshape = list(arr.shape)
        outshape[axis] = res.shape
        dtypes.append(asarray(res).dtype)
        outshape = flatten_inplace(outshape)
        outarr = zeros(outshape, object_)
        outarr[tuple(flatten_inplace(j.tolist()))] = res
        k = 1
        while k < Ntot:
            # increment the index
            ind[-1] += 1
            n = -1
            while (ind[n] >= holdshape[n]) and (n > (1-nd)):
                ind[n-1] += 1
                ind[n] = 0
                n -= 1
            i.put(indlist, ind)
            j.put(indlist, ind)
            res = func1d(arr[tuple(i.tolist())],*args,**kwargs)
            outarr[tuple(flatten_inplace(j.tolist()))] = res
            dtypes.append(asarray(res).dtype)
            k += 1
    max_dtypes = numeric.dtype(numeric.asarray(dtypes).max())
    if not hasattr(arr, '_mask'):
        result = numeric.asarray(outarr, dtype=max_dtypes)
    else:
        result = core.asarray(outarr, dtype=max_dtypes)
        result.fill_value = core.default_fill_value(result)
    return result
Esempio n. 31
0
    def __div__(self, other):
        if isscalar(other):
            return self._copy(self.ent_table, self.att_table, a=self.a/other)

        return NotImplemented
Esempio n. 32
0
    def __imul__(self, other):
        if not isscalar(other):
            return NotImplemented

        self.a = self.a * other
        return self
def histogramdd(sample, bins=10, range=None, normed=False, weights=None):
    """histogramdd(sample, bins=10, range=None, normed=False, weights=None)

    Return the N-dimensional histogram of the sample.

    Parameters:

        sample : sequence or array
            A sequence containing N arrays or an NxM array. Input data.

        bins : sequence or scalar
            A sequence of edge arrays, a sequence of bin counts, or a scalar
            which is the bin count for all dimensions. Default is 10.

        range : sequence
            A sequence of lower and upper bin edges. Default is [min, max].

        normed : boolean
            If False, return the number of samples in each bin, if True,
            returns the density.

        weights : array
            Array of weights.  The weights are normed only if normed is True.
            Should the sum of the weights not equal N, the total bin count will
            not be equal to the number of samples.

    Returns:

        hist : array
            Histogram array.

        edges : list
            List of arrays defining the lower bin edges.

    SeeAlso:

        histogram

    Example

        >>> x = random.randn(100,3)
        >>> hist3d, edges = histogramdd(x, bins = (5, 6, 7))

    """

    try:
        # Sample is an ND-array.
        N, D = sample.shape
    except (AttributeError, ValueError):
        # Sample is a sequence of 1D arrays.
        sample = atleast_2d(sample).T
        N, D = sample.shape

    nbin = empty(D, int)
    edges = D*[None]
    dedges = D*[None]
    if weights is not None:
        weights = asarray(weights)

    try:
        M = len(bins)
        if M != D:
            raise AttributeError, 'The dimension of bins must be a equal to the dimension of the sample x.'
    except TypeError:
        bins = D*[bins]

    # Select range for each dimension
    # Used only if number of bins is given.
    if range is None:
        smin = atleast_1d(array(sample.min(0), float))
        smax = atleast_1d(array(sample.max(0), float))
    else:
        smin = zeros(D)
        smax = zeros(D)
        for i in arange(D):
            smin[i], smax[i] = range[i]

    # Make sure the bins have a finite width.
    for i in arange(len(smin)):
        if smin[i] == smax[i]:
            smin[i] = smin[i] - .5
            smax[i] = smax[i] + .5

    # Create edge arrays
    for i in arange(D):
        if isscalar(bins[i]):
            nbin[i] = bins[i] + 2 # +2 for outlier bins
            edges[i] = linspace(smin[i], smax[i], nbin[i]-1)
        else:
            edges[i] = asarray(bins[i], float)
            nbin[i] = len(edges[i])+1  # +1 for outlier bins
        dedges[i] = diff(edges[i])

    nbin =  asarray(nbin)

    # Compute the bin number each sample falls into.
    Ncount = {}
    for i in arange(D):
        Ncount[i] = digitize(sample[:,i], edges[i])

    # Using digitize, values that fall on an edge are put in the right bin.
    # For the rightmost bin, we want values equal to the right
    # edge to be counted in the last bin, and not as an outlier.
    outliers = zeros(N, int)
    for i in arange(D):
        # Rounding precision
        decimal = int(-log10(dedges[i].min())) +6
        # Find which points are on the rightmost edge.
        on_edge = where(around(sample[:,i], decimal) == around(edges[i][-1], decimal))[0]
        # Shift these points one bin to the left.
        Ncount[i][on_edge] -= 1

    # Flattened histogram matrix (1D)
    hist = zeros(nbin.prod(), float)

    # Compute the sample indices in the flattened histogram matrix.
    ni = nbin.argsort()
    shape = []
    xy = zeros(N, int)
    for i in arange(0, D-1):
        xy += Ncount[ni[i]] * nbin[ni[i+1:]].prod()
    xy += Ncount[ni[-1]]

    # Compute the number of repetitions in xy and assign it to the flattened histmat.
    if len(xy) == 0:
        return zeros(nbin-2, int), edges

    flatcount = bincount(xy, weights)
    a = arange(len(flatcount))
    hist[a] = flatcount

    # Shape into a proper matrix
    hist = hist.reshape(sort(nbin))
    for i in arange(nbin.size):
        j = ni[i]
        hist = hist.swapaxes(i,j)
        ni[i],ni[j] = ni[j],ni[i]

    # Remove outliers (indices 0 and -1 for each dimension).
    core = D*[slice(1,-1)]
    hist = hist[core]

    # Normalize if normed is True
    if normed:
        s = hist.sum()
        for i in arange(D):
            shape = ones(D, int)
            shape[i] = nbin[i]-2
            hist = hist / dedges[i].reshape(shape)
        hist /= s

    return hist, edges
Esempio n. 34
0
def apply_along_axes(func1d, axis, arrs, *args):
    """
	Apply a function to 1-D slices along the given axis.

	Execute `func1d(a, *args)` where `func1d` operates on a set of 1-D arrays and `a`
	is a 1-D slice of `arr` along `axis`.

	Parameters
	----------
	func1d : function
		This function should accept 1-D arrays. It is applied to 1-D
		slices of `arr` along the specified axis.
	axis : integer
		Axis along which `arr` is sliced.
	arrs : tuple 
		tuple of input arrays. All arrays must have the same shape
	args : any
		Additional arguments to `func1d`.

	Returns
	-------
	outarr : ndarray
		The output array. The shape of `outarr` is identical to the shape of
		`arr`, except along the `axis` dimension, where the length of `outarr`
		is equal to the size of the return value of `func1d`.  If `func1d`
		returns a scalar `outarr` will have one fewer dimensions than `arr`.

	See Also
	--------
	apply_over_axis : Apply a function over 1-D slices of a single array.
	apply_over_axes : Apply a function repeatedly over multiple axes.

	"""
    arrs = list(map(asarray, arrs))
    arr = arrs[0]
    nd = arr.ndim
    if axis < 0:
        axis += nd
    if (axis >= nd):
        raise ValueError("axis must be less than arr.ndim; axis=%d, rank=%d." %
                         (axis, nd))
    ind = [0] * (nd - 1)
    i = zeros(nd, 'O')
    indlist = list(range(nd))
    indlist.remove(axis)
    i[axis] = slice(None, None)
    outshape = asarray(arr.shape).take(indlist)
    for arr in arrs[1:]:
        if tuple(asarray(arr.shape).take(indlist)) != tuple(outshape):
            raise ValueError(
                "Shape of all input arrays must match in all but the selected dimension."
            )
    i.put(indlist, ind)
    arglist = tuple([arr[tuple(i.tolist())] for arr in arrs]) + args
    res = func1d(*arglist)
    #  if res is a number, then we have a smaller output array
    if isscalar(res):
        outarr = zeros(outshape, asarray(res).dtype)
        outarr[tuple(ind)] = res
        Ntot = product(outshape)
        k = 1
        while k < Ntot:
            # increment the index
            ind[-1] += 1
            n = -1
            while (ind[n] >= outshape[n]) and (n > (1 - nd)):
                ind[n - 1] += 1
                ind[n] = 0
                n -= 1
            i.put(indlist, ind)
            arglist = tuple([arr[tuple(i.tolist())] for arr in arrs]) + args
            res = func1d(*arglist)
            outarr[tuple(ind)] = res
            k += 1
        return outarr
    else:
        Ntot = product(outshape)
        holdshape = outshape
        outshape = list(arr.shape)
        outshape[axis] = len(res)
        outarr = zeros(outshape, asarray(res).dtype)
        outarr[tuple(i.tolist())] = res
        k = 1
        while k < Ntot:
            # increment the index
            ind[-1] += 1
            n = -1
            while (ind[n] >= holdshape[n]) and (n > (1 - nd)):
                ind[n - 1] += 1
                ind[n] = 0
                n -= 1
            i.put(indlist, ind)
            arglist = tuple([arr[tuple(i.tolist())] for arr in arrs]) + args
            res = func1d(*arglist)
            #res = func1d(arr[tuple(i.tolist())],*args)
            outarr[tuple(i.tolist())] = res
            k += 1
        return outarr
Esempio n. 35
0
def isclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False):
    """
    Returns a boolean array where two arrays are element-wise equal within a
    tolerance.

    The tolerance values are positive, typically very small numbers.  The
    relative difference (`rtol` * abs(`b`)) and the absolute difference
    `atol` are added together to compare against the absolute difference
    between `a` and `b`.

    Parameters
    ----------
    a, b : array_like
        Input arrays to compare.
    rtol : float
        The relative tolerance parameter (see Notes).
    atol : float
        The absolute tolerance parameter (see Notes).
    equal_nan : bool
        Whether to compare NaN's as equal.  If True, NaN's in `a` will be
        considered equal to NaN's in `b` in the output array.

    Returns
    -------
    y : array_like
        Returns a boolean array of where `a` and `b` are equal within the
        given tolerance. If both `a` and `b` are scalars, returns a single
        boolean value.

    See Also
    --------
    allclose

    Notes
    -----
    .. versionadded:: 1.7.0

    For finite values, isclose uses the following equation to test whether
    two floating point values are equivalent.

     absolute(`a` - `b`) <= (`atol` + `rtol` * absolute(`b`))

    The above equation is not symmetric in `a` and `b`, so that
    `isclose(a, b)` might be different from `isclose(b, a)` in
    some rare cases.

    Examples
    --------
    >>> np.isclose([1e10,1e-7], [1.00001e10,1e-8])
    array([True, False])
    >>> np.isclose([1e10,1e-8], [1.00001e10,1e-9])
    array([True, True])
    >>> np.isclose([1e10,1e-8], [1.0001e10,1e-9])
    array([False, True])
    >>> np.isclose([1.0, np.nan], [1.0, np.nan])
    array([True, False])
    >>> np.isclose([1.0, np.nan], [1.0, np.nan], equal_nan=True)
    array([True, True])
    """
    def within_tol(x, y, atol, rtol):
        with errstate(invalid='ignore'):
            result = less_equal(abs(x - y), atol + rtol * abs(y))
        if isscalar(a) and isscalar(b):
            result = bool(result)
        return result

    x = array(a, copy=False, subok=True, ndmin=1)
    y = array(b, copy=False, subok=True, ndmin=1)

    # Make sure y is an inexact type to avoid bad behavior on abs(MIN_INT).
    # This will cause casting of x later. Also, make sure to allow subclasses
    # (e.g., for numpy.ma).
    dt = multiarray.result_type(y, 1.)
    y = array(y, dtype=dt, copy=False, subok=True)

    xfin = isfinite(x)
    yfin = isfinite(y)
    if all(xfin) and all(yfin):
        return within_tol(x, y, atol, rtol)
    else:
        finite = xfin & yfin
        cond = zeros_like(finite, subok=True)
        # Because we're using boolean indexing, x & y must be the same shape.
        # Ideally, we'd just do x, y = broadcast_arrays(x, y). It's in
        # lib.stride_tricks, though, so we can't import it here.
        x = x * ones_like(cond)
        y = y * ones_like(cond)
        # Avoid subtraction with infinite/nan values...
        cond[finite] = within_tol(x[finite], y[finite], atol, rtol)
        # Check for equality of infinite values...
        cond[~finite] = (x[~finite] == y[~finite])
        if equal_nan:
            # Make NaN == NaN
            both_nan = isnan(x) & isnan(y)
            cond[both_nan] = both_nan[both_nan]

        if isscalar(a) and isscalar(b):
            return bool(cond)
        else:
            return cond
Esempio n. 36
0
    def __rdiv__(self, other):
        if isscalar(other):
            return self._copy(self.ent_table, self.att_table, a=other/self.a, c=-self.c)

        return NotImplemented
Esempio n. 37
0
def histogramdd(sample, bins=10, range=None, normed=False, weights=None):
    """histogramdd(sample, bins=10, range=None, normed=False, weights=None)

    Return the N-dimensional histogram of the sample.

    Parameters:

        sample : sequence or array
            A sequence containing N arrays or an NxM array. Input data.

        bins : sequence or scalar
            A sequence of edge arrays, a sequence of bin counts, or a scalar
            which is the bin count for all dimensions. Default is 10.

        range : sequence
            A sequence of lower and upper bin edges. Default is [min, max].

        normed : boolean
            If False, return the number of samples in each bin, if True,
            returns the density.

        weights : array
            Array of weights.  The weights are normed only if normed is True.
            Should the sum of the weights not equal N, the total bin count will
            not be equal to the number of samples.

    Returns:

        hist : array
            Histogram array.

        edges : list
            List of arrays defining the lower bin edges.

    SeeAlso:

        histogram

    Example

        >>> x = random.randn(100,3)
        >>> hist3d, edges = histogramdd(x, bins = (5, 6, 7))

    """

    try:
        # Sample is an ND-array.
        N, D = sample.shape
    except (AttributeError, ValueError):
        # Sample is a sequence of 1D arrays.
        sample = atleast_2d(sample).T
        N, D = sample.shape

    nbin = empty(D, int)
    edges = D * [None]
    dedges = D * [None]
    if weights is not None:
        weights = asarray(weights)

    try:
        M = len(bins)
        if M != D:
            raise AttributeError, 'The dimension of bins must be a equal to the dimension of the sample x.'
    except TypeError:
        bins = D * [bins]

    # Select range for each dimension
    # Used only if number of bins is given.
    if range is None:
        smin = atleast_1d(array(sample.min(0), float))
        smax = atleast_1d(array(sample.max(0), float))
    else:
        smin = zeros(D)
        smax = zeros(D)
        for i in arange(D):
            smin[i], smax[i] = range[i]

    # Make sure the bins have a finite width.
    for i in arange(len(smin)):
        if smin[i] == smax[i]:
            smin[i] = smin[i] - .5
            smax[i] = smax[i] + .5

    # Create edge arrays
    for i in arange(D):
        if isscalar(bins[i]):
            nbin[i] = bins[i] + 2  # +2 for outlier bins
            edges[i] = linspace(smin[i], smax[i], nbin[i] - 1)
        else:
            edges[i] = asarray(bins[i], float)
            nbin[i] = len(edges[i]) + 1  # +1 for outlier bins
        dedges[i] = diff(edges[i])

    nbin = asarray(nbin)

    # Compute the bin number each sample falls into.
    Ncount = {}
    for i in arange(D):
        Ncount[i] = digitize(sample[:, i], edges[i])

    # Using digitize, values that fall on an edge are put in the right bin.
    # For the rightmost bin, we want values equal to the right
    # edge to be counted in the last bin, and not as an outlier.
    outliers = zeros(N, int)
    for i in arange(D):
        # Rounding precision
        decimal = int(-log10(dedges[i].min())) + 6
        # Find which points are on the rightmost edge.
        on_edge = where(
            around(sample[:, i], decimal) == around(edges[i][-1], decimal))[0]
        # Shift these points one bin to the left.
        Ncount[i][on_edge] -= 1

    # Flattened histogram matrix (1D)
    hist = zeros(nbin.prod(), float)

    # Compute the sample indices in the flattened histogram matrix.
    ni = nbin.argsort()
    shape = []
    xy = zeros(N, int)
    for i in arange(0, D - 1):
        xy += Ncount[ni[i]] * nbin[ni[i + 1:]].prod()
    xy += Ncount[ni[-1]]

    # Compute the number of repetitions in xy and assign it to the flattened histmat.
    if len(xy) == 0:
        return zeros(nbin - 2, int), edges

    flatcount = bincount(xy, weights)
    a = arange(len(flatcount))
    hist[a] = flatcount

    # Shape into a proper matrix
    hist = hist.reshape(sort(nbin))
    for i in arange(nbin.size):
        j = ni[i]
        hist = hist.swapaxes(i, j)
        ni[i], ni[j] = ni[j], ni[i]

    # Remove outliers (indices 0 and -1 for each dimension).
    core = D * [slice(1, -1)]
    hist = hist[core]

    # Normalize if normed is True
    if normed:
        s = hist.sum()
        for i in arange(D):
            shape = ones(D, int)
            shape[i] = nbin[i] - 2
            hist = hist / dedges[i].reshape(shape)
        hist /= s

    return hist, edges
Esempio n. 38
0
    def __idiv__(self, other):
        if isscalar(other):
            self.a = self.a / other
            return self

        return NotImplemented
Esempio n. 39
0
def apply_along_axis(func1d, axis, arr, *args):
    """
    Apply function to 1-D slices along the given axis.

    Execute `func1d(a[i],*args)` where `func1d` takes 1-D arrays, `a` is
    the input array, and `i` is an integer that varies in order to apply the
    function along the given axis for each 1-D subarray in `a`.

    Parameters
    ----------
    func1d : function
        This function should be able to take 1-D arrays. It is applied to 1-D
        slices of `a` along the specified axis.
    axis : integer
        Axis along which `func1d` is applied.
    a : ndarray
        Input array.
    args : any
        Additional arguments to `func1d`.

    Returns
    -------
    out : ndarray
        The output array. The shape of `out` is identical to the shape of `a`,
        except along the `axis` dimension, whose length is equal to the size
        of the return value of `func1d`.

    See Also
    --------
    apply_over_axes : Apply a function repeatedly over multiple axes.

    Examples
    --------
    >>> def my_func(a):
    ...     \"\"\"Average first and last element of a 1-D array\"\"\"
    ...     return (a[0] + a[-1]) * 0.5
    >>> b = np.array([[1,2,3], [4,5,6], [7,8,9]])
    >>> np.apply_along_axis(my_func, 0, b)
    array([4., 5., 6.])
    >>> np.apply_along_axis(my_func, 1, b)
    array([2., 5., 8.])

    """
    arr = asarray(arr)
    nd = arr.ndim
    if axis < 0:
        axis += nd
    if (axis >= nd):
        raise ValueError("axis must be less than arr.ndim; axis=%d, rank=%d." %
                         (axis, nd))
    ind = [0] * (nd - 1)
    i = zeros(nd, 'O')
    indlist = range(nd)
    indlist.remove(axis)
    i[axis] = slice(None, None)
    outshape = asarray(arr.shape).take(indlist)
    i.put(indlist, ind)
    res = func1d(arr[tuple(i.tolist())], *args)
    #  if res is a number, then we have a smaller output array
    if isscalar(res):
        outarr = zeros(outshape, asarray(res).dtype)
        outarr[tuple(ind)] = res
        Ntot = product(outshape)
        k = 1
        while k < Ntot:
            # increment the index
            ind[-1] += 1
            n = -1
            while (ind[n] >= outshape[n]) and (n > (1 - nd)):
                ind[n - 1] += 1
                ind[n] = 0
                n -= 1
            i.put(indlist, ind)
            res = func1d(arr[tuple(i.tolist())], *args)
            outarr[tuple(ind)] = res
            k += 1
        return outarr
    else:
        Ntot = product(outshape)
        holdshape = outshape
        outshape = list(arr.shape)
        outshape[axis] = len(res)
        outarr = zeros(outshape, asarray(res).dtype)
        outarr[tuple(i.tolist())] = res
        k = 1
        while k < Ntot:
            # increment the index
            ind[-1] += 1
            n = -1
            while (ind[n] >= holdshape[n]) and (n > (1 - nd)):
                ind[n - 1] += 1
                ind[n] = 0
                n -= 1
            i.put(indlist, ind)
            res = func1d(arr[tuple(i.tolist())], *args)
            outarr[tuple(i.tolist())] = res
            k += 1
        return outarr