summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPauli Virtanen <pav@iki.fi>2015-10-25 16:24:06 +0200
committerPauli Virtanen <pav@iki.fi>2015-10-25 16:24:06 +0200
commit4b1f1243fb2b2eb35adf50a26b0c4d2bcc3a7709 (patch)
tree49fd8b8a6f200515684bc1ca3ddc3da9dfe04a2b
parent3f6ffa8b7062c7023705361540b6efbe192289c7 (diff)
downloadnumpy-4b1f1243fb2b2eb35adf50a26b0c4d2bcc3a7709.tar.gz
DOC: import "numpy for matlab users" from the wiki
Might be useful to someone. Excised too opinionated parts and replaced most links to specific software with the topical software page links.
-rw-r--r--doc/source/user/index.rst1
-rw-r--r--doc/source/user/numpy-for-matlab-users.rst695
2 files changed, 696 insertions, 0 deletions
diff --git a/doc/source/user/index.rst b/doc/source/user/index.rst
index 9f45b68d6..a45fec9ec 100644
--- a/doc/source/user/index.rst
+++ b/doc/source/user/index.rst
@@ -16,5 +16,6 @@ classes contained in the package, see the :ref:`reference`.
quickstart
basics
misc
+ numpy-for-matlab-users
building
c-info
diff --git a/doc/source/user/numpy-for-matlab-users.rst b/doc/source/user/numpy-for-matlab-users.rst
new file mode 100644
index 000000000..2b8f43749
--- /dev/null
+++ b/doc/source/user/numpy-for-matlab-users.rst
@@ -0,0 +1,695 @@
+.. _numpy-for-matlab-users:
+
+======================
+Numpy for Matlab users
+======================
+
+Introduction
+============
+
+MATLAB® and NumPy/SciPy have a lot in common. But
+there are many differences. NumPy and SciPy were created to do numerical
+and scientific computing in the most natural way with Python, not to be
+MATLAB® clones. This page is intended to be a place to collect wisdom
+about the differences, mostly for the purpose of helping proficient
+MATLAB® users become proficient NumPy and SciPy users.
+
+.. raw:: html
+
+ <style>
+ table.docutils td { border: solid 1px #ccc; }
+ </style>
+
+Some Key Differences
+====================
+
+.. list-table::
+
+ * - In MATLAB®, the basic data type is a multidimensional array of double precision floating point numbers. Most expressions take such arrays and return such arrays. Operations on the 2-D instances of these arrays are designed to act more or less like matrix operations in linear algebra.
+ - In NumPy the basic type is a multidimensional ``array``. Operations on these arrays in all dimensionalities including 2D are elementwise operations. However, there is a special ``matrix`` type for doing linear algebra, which is just a subclass of the ``array`` class. Operations on matrix-class arrays are linear algebra operations.
+
+ * - MATLAB® uses 1 (one) based indexing. The initial element of a sequence is found using a(1).
+ :ref:`See note INDEXING <numpy-for-matlab-users.notes>`
+ - Python uses 0 (zero) based indexing. The initial element of a sequence is found using a[0].
+
+ * - MATLAB®'s scripting language was created for doing linear algebra. The syntax for basic matrix operations is nice and clean, but the API for adding GUIs and making full-fledged applications is more or less an afterthought.
+ - NumPy is based on Python, which was designed from the outset to be an excellent general-purpose programming language. While Matlab's syntax for some array manipulations is more compact than NumPy's, NumPy (by virtue of being an add-on to Python) can do many things that Matlab just cannot, for instance subclassing the main array type to do both array and matrix math cleanly.
+
+ * - In MATLAB®, arrays have pass-by-value semantics, with a lazy copy-on-write scheme to prevent actually creating copies until they are actually needed. Slice operations copy parts of the array.
+ - In NumPy arrays have pass-by-reference semantics. Slice operations are views into an array.
+
+
+'array' or 'matrix'? Which should I use?
+========================================
+
+Numpy provides, in addition to `np.ndarray`` an additional matrix type
+that you may see used in some existing code. Which one to use?
+
+Short answer
+------------
+
+**Use arrays**.
+
+- They are the standard vector/matrix/tensor type of numpy. Many numpy
+ function return arrays, not matrices.
+- There is a clear distinction between element-wise operations and
+ linear algebra operations.
+- You can have standard vectors or row/column vectors if you like.
+
+The only disadvantage of using the array type is that you will have to
+use ``dot`` instead of ``*`` to multiply (reduce) two tensors (scalar
+product, matrix vector multiplication etc.).
+
+Long answer
+-----------
+
+Numpy contains both an ``array`` class and a ``matrix`` class. The
+``array`` class is intended to be a general-purpose n-dimensional array
+for many kinds of numerical computing, while ``matrix`` is intended to
+facilitate linear algebra computations specifically. In practice there
+are only a handful of key differences between the two.
+
+- Operator ``*``, ``dot()``, and ``multiply()``:
+
+ - For ``array``, **'``*``\ ' means element-wise multiplication**,
+ and the ``dot()`` function is used for matrix multiplication.
+ - For ``matrix``, **'``*``\ ' means matrix multiplication**, and the
+ ``multiply()`` function is used for element-wise multiplication.
+
+- Handling of vectors (rank-1 arrays)
+
+ - For ``array``, the **vector shapes 1xN, Nx1, and N are all
+ different things**. Operations like ``A[:,1]`` return a rank-1
+ array of shape N, not a rank-2 of shape Nx1. Transpose on a rank-1
+ ``array`` does nothing.
+ - For ``matrix``, **rank-1 arrays are always upconverted to 1xN or
+ Nx1 matrices** (row or column vectors). ``A[:,1]`` returns a
+ rank-2 matrix of shape Nx1.
+
+- Handling of higher-rank arrays (rank > 2)
+
+ - ``array`` objects **can have rank > 2**.
+ - ``matrix`` objects **always have exactly rank 2**.
+
+- Convenience attributes
+
+ - ``array`` **has a .T attribute**, which returns the transpose of
+ the data.
+ - ``matrix`` **also has .H, .I, and .A attributes**, which return
+ the conjugate transpose, inverse, and ``asarray()`` of the matrix,
+ respectively.
+
+- Convenience constructor
+
+ - The ``array`` constructor **takes (nested) Python sequences as
+ initializers**. As in, ``array([[1,2,3],[4,5,6]])``.
+ - The ``matrix`` constructor additionally **takes a convenient
+ string initializer**. As in ``matrix("[1 2 3; 4 5 6]")``.
+
+There are pros and cons to using both:
+
+- ``array``
+
+ - ``:)`` You can treat rank-1 arrays as *either* row or column
+ vectors. ``dot(A,v)`` treats ``v`` as a column vector, while
+ ``dot(v,A)`` treats ``v`` as a row vector. This can save you
+ having to type a lot of transposes.
+ - ``<:(`` Having to use the ``dot()`` function for matrix-multiply is
+ messy -- ``dot(dot(A,B),C)`` vs. ``A*B*C``.
+ - ``:)`` Element-wise multiplication is easy: ``A*B``.
+ - ``:)`` ``array`` is the "default" NumPy type, so it gets the most
+ testing, and is the type most likely to be returned by 3rd party
+ code that uses NumPy.
+ - ``:)`` Is quite at home handling data of any rank.
+ - ``:)`` Closer in semantics to tensor algebra, if you are familiar
+ with that.
+ - ``:)`` *All* operations (``*``, ``/``, ``+``, ```` etc.) are
+ elementwise
+
+- ``matrix``
+
+ - ``:\\`` Behavior is more like that of MATLAB® matrices.
+ - ``<:(`` Maximum of rank-2. To hold rank-3 data you need ``array`` or
+ perhaps a Python list of ``matrix``.
+ - ``<:(`` Minimum of rank-2. You cannot have vectors. They must be
+ cast as single-column or single-row matrices.
+ - ``<:(`` Since ``array`` is the default in NumPy, some functions may
+ return an ``array`` even if you give them a ``matrix`` as an
+ argument. This shouldn't happen with NumPy functions (if it does
+ it's a bug), but 3rd party code based on NumPy may not honor type
+ preservation like NumPy does.
+ - ``:)`` ``A*B`` is matrix multiplication, so more convenient for
+ linear algebra.
+ - ``<:(`` Element-wise multiplication requires calling a function,
+ ``multipy(A,B)``.
+ - ``<:(`` The use of operator overloading is a bit illogical: ``*``
+ does not work elementwise but ``/`` does.
+
+The ``array`` is thus much more advisable to use.
+
+Facilities for Matrix Users
+===========================
+
+Numpy has some features that facilitate the use of the ``matrix`` type,
+which hopefully make things easier for Matlab converts.
+
+- A ``matlib`` module has been added that contains matrix versions of
+ common array constructors like ``ones()``, ``zeros()``, ``empty()``,
+ ``eye()``, ``rand()``, ``repmat()``, etc. Normally these functions
+ return ``array``\ s, but the ``matlib`` versions return ``matrix``
+ objects.
+- ``mat`` has been changed to be a synonym for ``asmatrix``, rather
+ than ``matrix``, thus making it concise way to convert an ``array``
+ to a ``matrix`` without copying the data.
+- Some top-level functions have been removed. For example
+ ``numpy.rand()`` now needs to be accessed as ``numpy.random.rand()``.
+ Or use the ``rand()`` from the ``matlib`` module. But the
+ "numpythonic" way is to use ``numpy.random.random()``, which takes a
+ tuple for the shape, like other numpy functions.
+
+Table of Rough MATLAB-NumPy Equivalents
+=======================================
+
+The table below gives rough equivalents for some common MATLAB®
+expressions. **These are not exact equivalents**, but rather should be
+taken as hints to get you going in the right direction. For more detail
+read the built-in documentation on the NumPy functions.
+
+Some care is necessary when writing functions that take arrays or
+matrices as arguments --- if you are expecting an ``array`` and are
+given a ``matrix``, or vice versa, then '\*' (multiplication) will give
+you unexpected results. You can convert back and forth between arrays
+and matrices using
+
+- ``asarray``: always returns an object of type ``array``
+- ``asmatrix`` or ``mat``: always return an object of type
+ ``matrix``
+- ``asanyarray``: always returns an ``array`` object or a subclass
+ derived from it, depending on the input. For instance if you pass in
+ a ``matrix`` it returns a ``matrix``.
+
+These functions all accept both arrays and matrices (among other things
+like Python lists), and thus are useful when writing functions that
+should accept any array-like object.
+
+In the table below, it is assumed that you have executed the following
+commands in Python:
+
+::
+
+ from numpy import *
+ import scipy.linalg
+
+Also assume below that if the Notes talk about "matrix" that the
+arguments are rank 2 entities.
+
+General Purpose Equivalents
+---------------------------
+
+.. list-table::
+ :header-rows: 1
+
+ * - **MATLAB**
+ - **numpy**
+ - **Notes**
+ * - ``help func``
+ - ``info(func)`` or ``help(func)`` or ``func?`` (in Ipython)
+ - get help on the function *func*
+ * - ``which func``
+ - `see note HELP <numpy-for-matlab-users.notes>`__
+ - find out where *func* is defined
+ * - ``type func``
+ - ``source(func)`` or ``func??`` (in Ipython)
+ - print source for *func* (if not a native function)
+ * - ``a && b``
+ - ``a and b``
+ - short-circuiting logical AND operator (Python native operator); scalar arguments only
+ * - ``a || b``
+ - ``a or b``
+ - short-circuiting logical OR operator (Python native operator); scalar arguments only
+ * - ``1*i``, ``1*j``, ``1i``, ``1j``
+ - ``1j``
+ - complex numbers
+ * - ``eps``
+ - ``np.spacing(1)``
+ - Distance between 1 and the nearest floating point number
+ * - ``ode45``
+ - ``scipy.integrate.ode(f).set_integrator('dopri5')``
+ - integrate an ODE with Runge-Kutta 4,5
+ * - ``ode15s``
+ - ``scipy.integrate.ode(f).set_integrator('vode', method='bdf', order=15)``
+ - integrate an ODE with BDF method
+
+Linear Algebra Equivalents
+--------------------------
+
+.. list-table::
+ :header-rows: 1
+
+ * - MATLAB
+ - NumPy
+ - Notes
+
+ * - ``ndims(a)``
+ - ``ndim(a)`` or ``a.ndim``
+ - get the number of dimensions of a (tensor rank)
+
+ * - ``numel(a)``
+ - ``size(a)`` or ``a.size``
+ - get the number of elements of an array
+
+ * - ``size(a)``
+ - ``shape(a)`` or ``a.shape``
+ - get the "size" of the matrix
+
+ * - ``size(a,n)``
+ - ``a.shape[n-1]``
+ - get the number of elements of the n-th dimension of array a. (Note that MATLAB® uses 1 based indexing while Python uses 0 based indexing, See note :ref:`INDEXING <numpy-for-matlab-users.notes>`)
+
+ * - ``[ 1 2 3; 4 5 6 ]``
+ - ``array([[1.,2.,3.], [4.,5.,6.]])``
+ - 2x3 matrix literal
+
+ * - ``[ a b; c d ]``
+ - ``vstack([hstack([a,b]), hstack([c,d])])`` or
+ ``bmat('a b; c d').A``
+ - construct a matrix from blocks a,b,c, and d
+
+ * - ``a(end)``
+ - ``a[-1]``
+ - access last element in the 1xn matrix ``a``
+
+ * - ``a(2,5)``
+ - ``a[1,4]``
+ - access element in second row, fifth column
+
+ * - ``a(2,:)``
+ - ``a[1]`` or ``a[1,:]``
+ - entire second row of ``a``
+
+ * - ``a(1:5,:)``
+ - ``a[0:5]`` or ``a[:5]`` or ``a[0:5,:]``
+ - the first five rows of ``a``
+
+ * - ``a(end-4:end,:)``
+ - ``a[-5:]``
+ - the last five rows of ``a``
+
+ * - ``a(1:3,5:9)``
+ - ``a[0:3][:,4:9]``
+ - rows one to three and columns five to nine of ``a``. This gives read-only access.
+
+ * - ``a([2,4,5],[1,3])``
+ - ``a[ix_([1,3,4],[0,2])]``
+ - rows 2,4 and 5 and columns 1 and 3. This allows the matrix to be modified, and doesn't require a regular slice.
+
+ * - ``a(3:2:21,:)``
+ - ``a[ 2:21:2,:]``
+ - every other row of ``a``, starting with the third and going to the twenty-first
+
+ * - ``a(1:2:end,:)``
+ - ``a[ ::2,:]``
+ - every other row of ``a``, starting with the first
+
+ * - ``a(end:-1:1,:)`` or ``flipud(a)``
+ - ``a[ ::-1,:]``
+ - ``a`` with rows in reverse order
+
+ * - ``a([1:end 1],:)``
+ - ``a[r_[:len(a),0]]``
+ - ``a`` with copy of the first row appended to the end
+
+ * - ``a.'``
+ - ``a.transpose()`` or ``a.T``
+ - transpose of ``a``
+
+ * - ``a'``
+ - ``a.conj().transpose()`` or ``a.conj().T``
+ - conjugate transpose of ``a``
+
+ * - ``a * b``
+ - ``a.dot(b)``
+ - matrix multiply
+
+ * - ``a .* b``
+ - ``a * b``
+ - element-wise multiply
+
+ * - ``a./b``
+ - ``a/b``
+ - element-wise divide
+
+ * - ``a.^3``
+ - ``a**3``
+ - element-wise exponentiation
+
+ * - ``(a>0.5)``
+ - ``(a>0.5)``
+ - matrix whose i,jth element is (a_ij > 0.5)
+
+ * - ``find(a>0.5)``
+ - ``nonzero(a>0.5)``
+ - find the indices where (a > 0.5)
+
+ * - ``a(:,find(v>0.5))``
+ - ``a[:,nonzero(v>0.5)[0]]``
+ - extract the columms of a where vector v > 0.5
+
+ * - ``a(:,find(v>0.5))``
+ - ``a[:,v.T>0.5]``
+ - extract the columms of a where column vector v > 0.5
+
+ * - ``a(a<0.5)=0``
+ - ``a[a<0.5]=0``
+ - a with elements less than 0.5 zeroed out
+
+ * - ``a .* (a>0.5)``
+ - ``a * (a>0.5)``
+ - a with elements less than 0.5 zeroed out
+
+ * - ``a(:) = 3``
+ - ``a[:] = 3``
+ - set all values to the same scalar value
+
+ * - ``y=x``
+ - ``y = x.copy()``
+ - numpy assigns by reference
+
+ * - ``y=x(2,:)``
+ - ``y = x[1,:].copy()``
+ - numpy slices are by reference
+
+ * - ``y=x(:)``
+ - ``y = x.flatten(1)``
+ - turn array into vector (note that this forces a copy)
+
+ * - ``1:10``
+ - ``arange(1.,11.)`` or ``r_[1.:11.]`` or ``r_[1:10:10j]``
+ - create an increasing vector (see note :ref:`RANGES <numpy-for-matlab-users.notes>`)
+
+ * - ``0:9``
+ - ``arange(10.)`` or ``r_[:10.]`` or ``r_[:9:10j]``
+ - create an increasing vector (see note :ref:`RANGES <numpy-for-matlab-users.notes>`)
+
+ * - ``[1:10]'``
+ - ``arange(1.,11.)[:, newaxis]``
+ - create a column vector
+
+ * - ``zeros(3,4)``
+ - ``zeros((3,4))``
+ - 3x4 rank-2 array full of 64-bit floating point zeros
+
+ * - ``zeros(3,4,5)``
+ - ``zeros((3,4,5))``
+ - 3x4x5 rank-3 array full of 64-bit floating point zeros
+
+ * - ``ones(3,4)``
+ - ``ones((3,4))``
+ - 3x4 rank-2 array full of 64-bit floating point ones
+
+ * - ``eye(3)``
+ - ``eye(3)``
+ - 3x3 identity matrix
+
+ * - ``diag(a)``
+ - ``diag(a)``
+ - vector of diagonal elements of a
+
+ * - ``diag(a,0)``
+ - ``diag(a,0)``
+ - square diagonal matrix whose nonzero values are the elements of a
+
+ * - ``rand(3,4)``
+ - ``random.rand(3,4)``
+ - random 3x4 matrix
+
+ * - ``linspace(1,3,4)``
+ - ``linspace(1,3,4)``
+ - 4 equally spaced samples between 1 and 3, inclusive
+
+ * - ``[x,y]=meshgrid(0:8,0:5)``
+ - ``mgrid[0:9.,0:6.]`` or ``meshgrid(r_[0:9.],r_[0:6.]``
+ - two 2D arrays: one of x values, the other of y values
+
+ * -
+ - ``ogrid[0:9.,0:6.]`` or ``ix_(r_[0:9.],r_[0:6.]``
+ - the best way to eval functions on a grid
+
+ * - ``[x,y]=meshgrid([1,2,4],[2,4,5])``
+ - ``meshgrid([1,2,4],[2,4,5])``
+ -
+
+ * -
+ - ``ix_([1,2,4],[2,4,5])``
+ - the best way to eval functions on a grid
+
+ * - ``repmat(a, m, n)``
+ - ``tile(a, (m, n))``
+ - create m by n copies of a
+
+ * - ``[a b]``
+ - ``concatenate((a,b),1)`` or ``hstack((a,b))`` or ``column_stack((a,b))`` or ``c_[a,b]``
+ - concatenate columns of ``a`` and ``b``
+
+ * - ``[a; b]``
+ - ``concatenate((a,b))`` or ``vstack((a,b))`` or ``r_[a,b]``
+ - concatenate rows of a and b
+
+ * - ``max(max(a))``
+ - ``a.max()``
+ - maximum element of a (with ndims(a)<=2 for matlab)
+
+ * - ``max(a)``
+ - ``a.max(0)``
+ - maximum element of each column of matrix a
+
+ * - ``max(a,[],2)``
+ - ``a.max(1)``
+ - maximum element of each row of matrix a
+
+ * - ``max(a,b)``
+ - ``maximum(a, b)``
+ - compares a and b element-wise, and returns the maximum value from each pair
+
+ * - ``norm(v)``
+ - ``sqrt(dot(v,v))`` or ``np.linalg.norm(v)``
+ - L2 norm of vector v
+
+ * - ``a & b``
+ - ``logical_and(a,b)``
+ - element-by-element AND operator (Numpy ufunc) :ref:`See note LOGICOPS <numpy-for-matlab-users.notes>`
+
+ * - ``a | b``
+ - ``logical_or(a,b)``
+ - element-by-element OR operator (Numpy ufunc) :ref:`See note LOGICOPS <numpy-for-matlab-users.notes>`
+
+ * - ``bitand(a,b)``
+ - ``a & b``
+ - bitwise AND operator (Python native and Numpy ufunc)
+
+ * - ``bitor(a,b)``
+ - ``a | b``
+ - bitwise OR operator (Python native and Numpy ufunc)
+
+ * - ``inv(a)``
+ - ``linalg.inv(a)``
+ - inverse of square matrix a
+
+ * - ``pinv(a)``
+ - ``linalg.pinv(a)``
+ - pseudo-inverse of matrix a
+
+ * - ``rank(a)``
+ - ``linalg.matrix_rank(a)``
+ - rank of a matrix a
+
+ * - ``a\b``
+ - ``linalg.solve(a,b)`` if ``a`` is square; ``linalg.lstsq(a,b)`` otherwise
+ - solution of a x = b for x
+
+ * - ``b/a``
+ - Solve a.T x.T = b.T instead
+ - solution of x a = b for x
+
+ * - ``[U,S,V]=svd(a)``
+ - ``U, S, Vh = linalg.svd(a), V = Vh.T``
+ - singular value decomposition of a
+
+ * - ``chol(a)``
+ - ``linalg.cholesky(a).T``
+ - cholesky factorization of a matrix (chol(a) in matlab returns an upper triangular matrix, but linalg.cholesky(a) returns a lower triangular matrix)
+
+ * - ``[V,D]=eig(a)``
+ - ``D,V = linalg.eig(a)``
+ - eigenvalues and eigenvectors of a
+
+ * - ``[V,D]=eig(a,b)``
+ - ``V,D = np.linalg.eig(a,b)``
+ - eigenvalues and eigenvectors of a,b
+
+ * - ``[V,D]=eigs(a,k)``
+ -
+ - find the k largest eigenvalues and eigenvectors of a
+
+ * - ``[Q,R,P]=qr(a,0)``
+ - ``Q,R = scipy.linalg.qr(a)``
+ - QR decomposition
+
+ * - ``[L,U,P]=lu(a)``
+ - ``L,U = scipy.linalg.lu(a)`` or ``LU,P=scipy.linalg.lu_factor(a)``
+ - LU decomposition (note: P(Matlab) == transpose(P(numpy)) )
+
+ * - ``conjgrad``
+ - ``scipy.sparse.linalg.cg``
+ - Conjugate gradients solver
+
+ * - ``fft(a)``
+ - ``fft(a)``
+ - Fourier transform of a
+
+ * - ``ifft(a)``
+ - ``ifft(a)``
+ - inverse Fourier transform of a
+
+ * - ``sort(a)``
+ - ``sort(a)`` or ``a.sort()``
+ - sort the matrix
+
+ * - ``[b,I] = sortrows(a,i)``
+ - ``I = argsort(a[:,i]), b=a[I,:]``
+ - sort the rows of the matrix
+
+ * - ``regress(y,X)``
+ - ``linalg.lstsq(X,y)``
+ - multilinear regression
+
+ * - ``decimate(x, q)``
+ - ``scipy.signal.resample(x, len(x)/q)``
+ - downsample with low-pass filtering
+
+ * - ``unique(a)``
+ - ``unique(a)``
+ -
+
+ * - ``squeeze(a)``
+ - ``a.squeeze()``
+ -
+
+.. _numpy-for-matlab-users.notes:
+
+Notes
+=====
+
+\ **Submatrix**: Assignment to a submatrix can be done with lists of
+indexes using the ``ix_`` command. E.g., for 2d array ``a``, one might
+do: ``ind=[1,3]; a[np.ix_(ind,ind)]+=100``.
+
+\ **HELP**: There is no direct equivalent of MATLAB's ``which`` command,
+but the commands ``help`` and ``source`` will usually list the filename
+where the function is located. Python also has an ``inspect`` module (do
+``import inspect``) which provides a ``getfile`` that often works.
+
+\ **INDEXING**: MATLAB® uses one based indexing, so the initial element
+of a sequence has index 1. Python uses zero based indexing, so the
+initial element of a sequence has index 0. Confusion and flamewars arise
+because each has advantages and disadvantages. One based indexing is
+consistent with common human language usage, where the "first" element
+of a sequence has index 1. Zero based indexing `simplifies
+indexing <http://groups.google.com/group/comp.lang.python/msg/1bf4d925dfbf368?q=g:thl3498076713d&hl=en>`__.
+See also `a text by prof.dr. Edsger W.
+Dijkstra <http://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html>`__.
+
+\ **RANGES**: In MATLAB®, ``0:5`` can be used as both a range literal
+and a 'slice' index (inside parentheses); however, in Python, constructs
+like ``0:5`` can *only* be used as a slice index (inside square
+brackets). Thus the somewhat quirky ``r_`` object was created to allow
+numpy to have a similarly terse range construction mechanism. Note that
+``r_`` is not called like a function or a constructor, but rather
+*indexed* using square brackets, which allows the use of Python's slice
+syntax in the arguments.
+
+\ **LOGICOPS**: & or \| in Numpy is bitwise AND/OR, while in Matlab &
+and \| are logical AND/OR. The difference should be clear to anyone with
+significant programming experience. The two can appear to work the same,
+but there are important differences. If you would have used Matlab's &
+or \| operators, you should use the Numpy ufuncs
+logical\_and/logical\_or. The notable differences between Matlab's and
+Numpy's & and \| operators are:
+
+- Non-logical {0,1} inputs: Numpy's output is the bitwise AND of the
+ inputs. Matlab treats any non-zero value as 1 and returns the logical
+ AND. For example (3 & 4) in Numpy is 0, while in Matlab both 3 and 4
+ are considered logical true and (3 & 4) returns 1.
+- Precedence: Numpy's & operator is higher precedence than logical
+ operators like < and >; Matlab's is the reverse.
+
+If you know you have boolean arguments, you can get away with using
+Numpy's bitwise operators, but be careful with parentheses, like this: z
+= (x > 1) & (x < 2). The absence of Numpy operator forms of logical\_and
+and logical\_or is an unfortunate consequence of Python's design.
+
+**RESHAPE and LINEAR INDEXING**: Matlab always allows multi-dimensional
+arrays to be accessed using scalar or linear indices, Numpy does not.
+Linear indices are common in Matlab programs, e.g. find() on a matrix
+returns them, whereas Numpy's find behaves differently. When converting
+Matlab code it might be necessary to first reshape a matrix to a linear
+sequence, perform some indexing operations and then reshape back. As
+reshape (usually) produces views onto the same storage, it should be
+possible to do this fairly efficiently. Note that the scan order used by
+reshape in Numpy defaults to the 'C' order, whereas Matlab uses the
+Fortran order. If you are simply converting to a linear sequence and
+back this doesn't matter. But if you are converting reshapes from Matlab
+code which relies on the scan order, then this Matlab code: z =
+reshape(x,3,4); should become z = x.reshape(3,4,order='F').copy() in
+Numpy.
+
+Customizing Your Environment
+============================
+
+In MATLAB® the main tool available to you for customizing the
+environment is to modify the search path with the locations of your
+favorite functions. You can put such customizations into a startup
+script that MATLAB will run on startup.
+
+NumPy, or rather Python, has similar facilities.
+
+- To modify your Python search path to include the locations of your
+ own modules, define the ``PYTHONPATH`` environment variable.
+- To have a particular script file executed when the interactive Python
+ interpreter is started, define the ``PYTHONSTARTUP`` environment
+ variable to contain the name of your startup script.
+
+Unlike MATLAB®, where anything on your path can be called immediately,
+with Python you need to first do an 'import' statement to make functions
+in a particular file accessible.
+
+For example you might make a startup script that looks like this (Note:
+this is just an example, not a statement of "best practices"):
+
+::
+
+ # Make all numpy available via shorter 'num' prefix
+ import numpy as num
+ # Make all matlib functions accessible at the top level via M.func()
+ import numpy.matlib as M
+ # Make some matlib functions accessible directly at the top level via, e.g. rand(3,3)
+ from numpy.matlib import rand,zeros,ones,empty,eye
+ # Define a Hermitian function
+ def hermitian(A, **kwargs):
+ return num.transpose(A,**kwargs).conj()
+ # Make some shorcuts for transpose,hermitian:
+ # num.transpose(A) --> T(A)
+ # hermitian(A) --> H(A)
+ T = num.transpose
+ H = hermitian
+
+Links
+=====
+
+See http://mathesaurus.sf.net/ for another MATLAB®/NumPy
+cross-reference.
+
+An extensive list of tools for scientific work with python can be
+found in the `topical software page <http://scipy.org/topical-software.html>`__.
+
+MATLAB® and SimuLink® are registered trademarks of The MathWorks.