From 63712318900b156e4b0c63a146963698db33cf16 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauldmccarthy@gmail.com>
Date: Sat, 10 Feb 2018 16:08:30 +0000
Subject: [PATCH] Add appendix on matrix data type

---
 getting_started/04_numpy.ipynb | 60 +++++++++++++++++++++++++++++++---
 getting_started/04_numpy.md    | 59 ++++++++++++++++++++++++++++++---
 2 files changed, 111 insertions(+), 8 deletions(-)

diff --git a/getting_started/04_numpy.ipynb b/getting_started/04_numpy.ipynb
index 9ce491b..23b4131 100644
--- a/getting_started/04_numpy.ipynb
+++ b/getting_started/04_numpy.ipynb
@@ -51,6 +51,7 @@
     "* [Appendix A: Generating random numbers](#appendix-generating-random-numbers)\n",
     "* [Appendix B: Importing Numpy](#appendix-importing-numpy)\n",
     "* [Appendix C: Vectors in Numpy](#appendix-vectors-in-numpy)\n",
+    "* [Appendix D: The Numpy `matrix`](#appendix-the-numpy-matrix)\n",
     "\n",
     "* [Useful references](#useful-references)\n",
     "\n",
@@ -186,7 +187,8 @@
     "array, thus completely bypassing the use of Python lists and the costly\n",
     "list-to-array conversion.  I'm emphasising this to help you understand the\n",
     "difference between Python lists and Numpy arrays. Apologies if you've already\n",
-    "got it, forgiveness please.\n",
+    "got it, [forgiveness\n",
+    "please](https://www.youtube.com/watch?v=ZeHflFNR4kQ&feature=youtu.be&t=128).\n",
     "\n",
     "\n",
     "<a class=\"anchor\" id=\"numpy-basics\"></a>\n",
@@ -724,8 +726,8 @@
     "froth coming out of your mouth. I guess you're angry that `a * b` didn't give\n",
     "you the matrix product, like it would have in Matlab.  Well all I can say is\n",
     "that Numpy is not Matlab. Matlab operations are typically consistent with\n",
-    "linear algebra notation. This is not the case in Numpy. Get over it. Take a\n",
-    "calmative.\n",
+    "linear algebra notation. This is not the case in Numpy. Get over it.\n",
+    "[Get yourself a calmative](https://youtu.be/M_w_n-8w3IQ?t=32).\n",
     "\n",
     "\n",
     "<a class=\"anchor\" id=\"matrix-multiplication\"></a>\n",
@@ -805,6 +807,14 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
+    "If you really can't stand using `@` to denote matrix multiplication, and just\n",
+    "want things to be like they were back in Matlab-land, you do have the option\n",
+    "of using a different Numpy data type - the `matrix` - which behaves a bit more\n",
+    "like what you might expect from Matlab.  You can find a brief overview of the\n",
+    "`matrix` data type in [the appendix](appendix-the-numpy-matrix).\n",
+    "\n",
+    "\n",
+    "\n",
     "<a class=\"anchor\" id=\"broadcasting\"></a>\n",
     "### Broadcasting\n",
     "\n",
@@ -1480,6 +1490,47 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
+    "<a class=\"anchor\" id=\"appendix-the-numpy-matrix\"></a>\n",
+    "## Appendix D: The Numpy `matrix`\n",
+    "\n",
+    "\n",
+    "By now you should be aware that a Numpy `array` does not behave in quite the\n",
+    "same way as a Matlab matrix. The primary difference between Numpy and Matlab\n",
+    "is that in Numpy, the `*` operator denotes element-wise multiplication,\n",
+    "gwhereas in Matlab, `*` denotes matrix multiplication.\n",
+    "\n",
+    "\n",
+    "Numpy does support the `@` operator for matrix multiplication, but if this is\n",
+    "a complete show-stopper for you - if you just can't bring yourself to write `A\n",
+    "@ B` to denote the matrix product of `A` and `B` - if you _must_ have your\n",
+    "code looking as Matlab-like as possible, then you should look into the Numpy\n",
+    "[`matrix`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.matrix.html)\n",
+    "data type.\n",
+    "\n",
+    "\n",
+    "The `matrix` is an alternative to the `array` which essentially behaves more\n",
+    "like a Matlab matrix:\n",
+    "\n",
+    "* `matrix` objects always have exactly two dimensions.\n",
+    "* `a * b` denotes matrix multiplication, rather than elementwise\n",
+    "  multiplication.\n",
+    "* `matrix` objects have `.H` and `.I` attributes, which are convenient ways to\n",
+    "  access the conjugate transpose and inverse of the matrix respectively.\n",
+    "\n",
+    "\n",
+    "Note however that use of the `matrix` type is _not_ widespread, and if you use\n",
+    "it you will risk confusing others who are familiar with the much more commonly\n",
+    "used `array`, and who need to work with your code. In fact, the official Numpy\n",
+    "documentation [recommends against using the `matrix`\n",
+    "type](https://docs.scipy.org/doc/numpy-dev/user/numpy-for-matlab-users.html#array-or-matrix-which-should-i-use).\n",
+    "\n",
+    "\n",
+    "But if you are writing some very maths-heavy code, and you want your code to\n",
+    "be as clear and concise, and maths/Matlab-like as possible, then the `matrix`\n",
+    "type is there for you. Just make sure you document your code well to make it\n",
+    "clear to others what is going on!\n",
+    "\n",
+    "\n",
     "<a class=\"anchor\" id=\"useful-references\"></a>\n",
     "## Useful references\n",
     "\n",
@@ -1489,7 +1540,8 @@
     "* [Broadcasting in Numpy](https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)\n",
     "* [Indexing in Numpy](https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html)\n",
     "* [Random sampling in `numpy.random`](https://docs.scipy.org/doc/numpy/reference/routines.random.html)\n",
-    "* [Python slicing](https://www.pythoncentral.io/how-to-slice-listsarrays-and-tuples-in-python/)"
+    "* [Python slicing](https://www.pythoncentral.io/how-to-slice-listsarrays-and-tuples-in-python/)\n",
+    "* [Numpy for Matlab users](https://docs.scipy.org/doc/numpy-dev/user/numpy-for-matlab-users.html)"
    ]
   }
  ],
diff --git a/getting_started/04_numpy.md b/getting_started/04_numpy.md
index 5cbabce..8ea10a8 100644
--- a/getting_started/04_numpy.md
+++ b/getting_started/04_numpy.md
@@ -45,6 +45,7 @@ out of date, but we will update it for the next release of FSL.
 * [Appendix A: Generating random numbers](#appendix-generating-random-numbers)
 * [Appendix B: Importing Numpy](#appendix-importing-numpy)
 * [Appendix C: Vectors in Numpy](#appendix-vectors-in-numpy)
+* [Appendix D: The Numpy `matrix`](#appendix-the-numpy-matrix)
 
 * [Useful references](#useful-references)
 
@@ -148,7 +149,8 @@ will be loading our data from text or binary files directly into a Numpy
 array, thus completely bypassing the use of Python lists and the costly
 list-to-array conversion.  I'm emphasising this to help you understand the
 difference between Python lists and Numpy arrays. Apologies if you've already
-got it, forgiveness please.
+got it, [forgiveness
+please](https://www.youtube.com/watch?v=ZeHflFNR4kQ&feature=youtu.be&t=128).
 
 
 <a class="anchor" id="numpy-basics"></a>
@@ -532,8 +534,8 @@ Wait ... what's that you say? Oh, I couldn't understand because of all the
 froth coming out of your mouth. I guess you're angry that `a * b` didn't give
 you the matrix product, like it would have in Matlab.  Well all I can say is
 that Numpy is not Matlab. Matlab operations are typically consistent with
-linear algebra notation. This is not the case in Numpy. Get over it. Take a
-calmative.
+linear algebra notation. This is not the case in Numpy. Get over it.
+[Get yourself a calmative](https://youtu.be/M_w_n-8w3IQ?t=32).
 
 
 <a class="anchor" id="matrix-multiplication"></a>
@@ -597,6 +599,13 @@ print(b @ a)
 ```
 
 
+If you really can't stand using `@` to denote matrix multiplication, and just
+want things to be like they were back in Matlab-land, you do have the option
+of using a different Numpy data type - the `matrix` - which behaves a bit more
+like what you might expect from Matlab.  You can find a brief overview of the
+`matrix` data type in [the appendix](appendix-the-numpy-matrix).
+
+
 
 <a class="anchor" id="broadcasting"></a>
 ### Broadcasting
@@ -1108,6 +1117,47 @@ print(np.atleast_2d(r).T)
 ```
 
 
+<a class="anchor" id="appendix-the-numpy-matrix"></a>
+## Appendix D: The Numpy `matrix`
+
+
+By now you should be aware that a Numpy `array` does not behave in quite the
+same way as a Matlab matrix. The primary difference between Numpy and Matlab
+is that in Numpy, the `*` operator denotes element-wise multiplication,
+gwhereas in Matlab, `*` denotes matrix multiplication.
+
+
+Numpy does support the `@` operator for matrix multiplication, but if this is
+a complete show-stopper for you - if you just can't bring yourself to write `A
+@ B` to denote the matrix product of `A` and `B` - if you _must_ have your
+code looking as Matlab-like as possible, then you should look into the Numpy
+[`matrix`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.matrix.html)
+data type.
+
+
+The `matrix` is an alternative to the `array` which essentially behaves more
+like a Matlab matrix:
+
+* `matrix` objects always have exactly two dimensions.
+* `a * b` denotes matrix multiplication, rather than elementwise
+  multiplication.
+* `matrix` objects have `.H` and `.I` attributes, which are convenient ways to
+  access the conjugate transpose and inverse of the matrix respectively.
+
+
+Note however that use of the `matrix` type is _not_ widespread, and if you use
+it you will risk confusing others who are familiar with the much more commonly
+used `array`, and who need to work with your code. In fact, the official Numpy
+documentation [recommends against using the `matrix`
+type](https://docs.scipy.org/doc/numpy-dev/user/numpy-for-matlab-users.html#array-or-matrix-which-should-i-use).
+
+
+But if you are writing some very maths-heavy code, and you want your code to
+be as clear and concise, and maths/Matlab-like as possible, then the `matrix`
+type is there for you. Just make sure you document your code well to make it
+clear to others what is going on!
+
+
 <a class="anchor" id="useful-references"></a>
 ## Useful references
 
@@ -1117,4 +1167,5 @@ print(np.atleast_2d(r).T)
 * [Broadcasting in Numpy](https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
 * [Indexing in Numpy](https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html)
 * [Random sampling in `numpy.random`](https://docs.scipy.org/doc/numpy/reference/routines.random.html)
-* [Python slicing](https://www.pythoncentral.io/how-to-slice-listsarrays-and-tuples-in-python/)
\ No newline at end of file
+* [Python slicing](https://www.pythoncentral.io/how-to-slice-listsarrays-and-tuples-in-python/)
+* [Numpy for Matlab users](https://docs.scipy.org/doc/numpy-dev/user/numpy-for-matlab-users.html)
-- 
GitLab