Relationship between SciPy and NumPy
numpy, python, scipy
Solution
Last time I checked it, the scipy `__init__` method executes a
from numpy import *
so that the whole numpy namespace is included into scipy when the scipy module is imported.
The `log10` behavior you are describing is interesting, because both versions are coming from numpy. One is a `ufunc`, the other is a `numpy.lib` function. Why scipy is preferring the library function over the `ufunc`, I don't know off the top of my head.
EDIT: In fact, I can answer the `log10` question. Looking in the scipy `__init__` method I see this:
# Import numpy symbols to scipy name space
import numpy as _num
from numpy import oldnumeric
from numpy import *
from numpy.random import rand, randn
from numpy.fft import fft, ifft
from numpy.lib.scimath import *
The `log10` function you get in scipy comes from `numpy.lib.scimath`. Looking at that code, it says:
"""
Wrapper functions to more user-friendly calling of certain math functions
whose output data-type is different than the input data-type in certain
domains of the input.
For example, for functions like log() with branch cuts, the versions in this
module provide the mathematically valid answers in the complex plane:
>>> import math
>>> from numpy.lib import scimath
>>> scimath.log(-math.exp(1)) == (1+1j*math.pi)
True
Similarly, sqrt(), other base logarithms, power() and trig functions are
correctly handled. See their respective docstrings for specific examples.
"""
It seems that module overlays the base numpy ufuncs for `sqrt`, `log`, `log2`, `logn`, `log10`, `power`, `arccos`, `arcsin`, and `arctanh`. That explains the behavior you are seeing. The underlying design reason why it is done like that is probably buried in a mailing list post somewhere.
Problem
SciPy appears to provide most (but not all [1]) of NumPy's functions in its own namespace. In other words, if there's a function named `numpy.foo`, there's almost certainly a `scipy.foo`. Most of the time, the two appear to be exactly the same, oftentimes even pointing to the same function object. Sometimes, they're different. To give an example that came up recently: - `numpy.log10` is a ufunc that returns NaNs for negative arguments; - `scipy.log10` returns complex values for negative arguments and doesn't appear to be a ufunc. The same can be said about `log`, `log2` and `logn`, but not about `log1p` [2]. On the other hand, `numpy.exp` and `scipy.exp` appear to be different names for the same ufunc. This is also true of `scipy.log1p` and `numpy.log1p`. Another example is `numpy.linalg.solve` vs `scipy.linalg.solve`. They're similar, but the latter offers some additional features over the former. Why the apparent duplication? If this is meant to be a wholesale import of `numpy` into the `scipy` namespace, why the subtle differences in behaviour and the missing functions? Is there some overarching logic that would help clear up the confusion? [1] `numpy.min`, `numpy.max`, `numpy.abs` and a few others have no counterparts in the `scipy` namespace. [2] Tested using NumPy 1.5.1 and SciPy 0.9.0rc2.