Repository: PlasmaPy/PlasmaPy
Pull request #141 (2017-10-04 09:09:05)

Distribution function
First contribution for me !
To start with #101, I added a 1D Maxwellian distribution function calculation.
Please tell me if you like the interface, numbre of arguments and so on.

Needs to be done :
- [ ] Do the same with Kappa
- [ ] implement a 2D and/or 3D version of it.
- [ ] add particle generator
- [ ] maybe : add symbolic formulation

pep8speaks: Hello @antoinelpp! Thanks for submitting the PR.

 - In the file [`plasmapy/physics/distribution.py`](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py), following are the PEP8 issues :

> [Line 17:20](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L17): [E231](https://duckduckgo.com/?q=pep8%20E231) missing whitespace after ','
> [Line 17:22](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L17): [E231](https://duckduckgo.com/?q=pep8%20E231) missing whitespace after ','
> [Line 17:27](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L17): [E251](https://duckduckgo.com/?q=pep8%20E251) unexpected spaces around keyword / parameter equals
> [Line 17:41](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L17): [E251](https://duckduckgo.com/?q=pep8%20E251) unexpected spaces around keyword / parameter equals
> [Line 17:43](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L17): [E251](https://duckduckgo.com/?q=pep8%20E251) unexpected spaces around keyword / parameter equals
> [Line 17:45](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L17): [E225](https://duckduckgo.com/?q=pep8%20E225) missing whitespace around operator
> [Line 18:80](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L18): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (157 > 79 characters)
> [Line 36:80](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L36): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (91 > 79 characters)
> [Line 61:5](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L61): [E265](https://duckduckgo.com/?q=pep8%20E265) block comment should start with '# '
> [Line 61:5](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L61): [E303](https://duckduckgo.com/?q=pep8%20E303) too many blank lines (3)
> [Line 62:37](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L62): [E203](https://duckduckgo.com/?q=pep8%20E203) whitespace before ':'
> [Line 65:9](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L65): [E203](https://duckduckgo.com/?q=pep8%20E203) whitespace before ':'
> [Line 70:5](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L70): [E265](https://duckduckgo.com/?q=pep8%20E265) block comment should start with '# '
> [Line 70:5](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L70): [E303](https://duckduckgo.com/?q=pep8%20E303) too many blank lines (3)
> [Line 75:9](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/distribution.py#L75): [E203](https://duckduckgo.com/?q=pep8%20E203) whitespace before ':'

 - In the file [`plasmapy/physics/tests/test_distribution.py`](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py), following are the PEP8 issues :

> [Line 12:16](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L12): [E703](https://duckduckgo.com/?q=pep8%20E703) statement ends with a semicolon
> [Line 13:21](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L13): [E703](https://duckduckgo.com/?q=pep8%20E703) statement ends with a semicolon
> [Line 15:14](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L15): [E703](https://duckduckgo.com/?q=pep8%20E703) statement ends with a semicolon
> [Line 16:15](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L16): [E703](https://duckduckgo.com/?q=pep8%20E703) statement ends with a semicolon
> [Line 17:21](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L17): [E703](https://duckduckgo.com/?q=pep8%20E703) statement ends with a semicolon
> [Line 19:25](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L19): [E231](https://duckduckgo.com/?q=pep8%20E231) missing whitespace after ','
> [Line 19:30](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L19): [E231](https://duckduckgo.com/?q=pep8%20E231) missing whitespace after ','
> [Line 19:47](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L19): [E225](https://duckduckgo.com/?q=pep8%20E225) missing whitespace around operator
> [Line 19:51](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L19): [E703](https://duckduckgo.com/?q=pep8%20E703) statement ends with a semicolon
> [Line 21:1](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L21): [E302](https://duckduckgo.com/?q=pep8%20E302) expected 2 blank lines, found 1
> [Line 24:50](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L24): [E231](https://duckduckgo.com/?q=pep8%20E231) missing whitespace after ','
> [Line 24:66](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L24): [E231](https://duckduckgo.com/?q=pep8%20E231) missing whitespace after ','
> [Line 24:74](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L24): [E251](https://duckduckgo.com/?q=pep8%20E251) unexpected spaces around keyword / parameter equals
> [Line 24:76](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L24): [E251](https://duckduckgo.com/?q=pep8%20E251) unexpected spaces around keyword / parameter equals
> [Line 24:80](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L24): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (108 > 79 characters)
> [Line 24:86](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L24): [E202](https://duckduckgo.com/?q=pep8%20E202) whitespace before ')'
> [Line 24:104](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L24): [E231](https://duckduckgo.com/?q=pep8%20E231) missing whitespace after ','
> [Line 26:50](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L26): [E231](https://duckduckgo.com/?q=pep8%20E231) missing whitespace after ','
> [Line 26:66](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L26): [E231](https://duckduckgo.com/?q=pep8%20E231) missing whitespace after ','
> [Line 26:74](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L26): [E251](https://duckduckgo.com/?q=pep8%20E251) unexpected spaces around keyword / parameter equals
> [Line 26:76](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L26): [E251](https://duckduckgo.com/?q=pep8%20E251) unexpected spaces around keyword / parameter equals
> [Line 26:80](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L26): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (116 > 79 characters)
> [Line 26:84](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L26): [E202](https://duckduckgo.com/?q=pep8%20E202) whitespace before ')'
> [Line 26:102](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L26): [E231](https://duckduckgo.com/?q=pep8%20E231) missing whitespace after ','
> [Line 28:5](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L28): [E265](https://duckduckgo.com/?q=pep8%20E265) block comment should start with '# '
> [Line 29:37](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L29): [E231](https://duckduckgo.com/?q=pep8%20E231) missing whitespace after ','
> [Line 29:40](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L29): [E251](https://duckduckgo.com/?q=pep8%20E251) unexpected spaces around keyword / parameter equals
> [Line 32:40](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L32): [E231](https://duckduckgo.com/?q=pep8%20E231) missing whitespace after ','
> [Line 35:31](https://github.com/PlasmaPy/PlasmaPy/blob/ea792780e13b5f6e088633c395ec7759b7263605/plasmapy/physics/tests/test_distribution.py#L35): [E231](https://duckduckgo.com/?q=pep8%20E231) missing whitespace after ','


StanczakDominik: That's a weird test failure:
```
063     Example
064     -------
065     >>> from plasmapy.physics import Maxwellian_1D
066     >>> from astropy import units as u
067     >>> Maxwellian_1D(v=1*u.m/u.s, T= 30000*u.K, particle='e',V_drift=0*u.m/u.s)
Expected:
    <Quantity 5.916 m/s >
Got:
    <Quantity 5.916329687405701e-07 s / m>
```
so you expect something on the order of 6m/s and get 6 * 10^-7 s/m ? This seems like some bug in the formula, I'll take a look.
StanczakDominik: Okay, so I just noticed that this returns `return f.to(units.s/units.m)`. Is this correct? It's 1/velocity, so given this is a probability distribution function it probably is correct as you can integrate it over velocities and get a 1 without units. The formula seems all right, though.

I also noticed I forgot to add `k_B` for each temperature in the formula docstring, sorry :(
antoinelpp: > so you expect something on the order of 6m/s and get 6 * 10^-7 s/m ? This seems like some bug in the formula, I'll take a look.
No that's my mistake !


antoinelpp: Sorry all for the PR spam, but I couldn't figure out how to run the tests without pushing...
Anyone could tell me the best way to run them from my repo ?

I tried to rebase it on Upstream, but the PR is now a mess... Shouldn't I do it ? Or I maybe I did it wrong...
StanczakDominik: I wouldn't worry about rebasing for now. I think we can live with a lengthy history.

We really need to look into this: run `pytest plasmapy` from repository root. Could someone start an issue for this? I can't right now.
antoinelpp: Ho !
Actually `pytest plasmapy` works fine ! I didn't knew about it.
I'm sorry :s
StanczakDominik: No worries, glad it works for you :)

I'll try to do a final review on this but I won't be able to do that by Friday, probably. If anyone wants to step in, I'd be much obliged!
StanczakDominik: @antoinelpp I took a closer look at the branch history and *moana*d, because something must have gone horribly wrong there. That tree was duplicated in some weird ways. I *tried everything*, but in the end the only thing that made sense was to fix some of that *tangled* mess via rebase - you can see the result of that [here](https://github.com/StanczakDominik/PlasmaPy/commits/Distrubution-fn), but at the same time I may have messed up some of the chronological ordering of the changes.

If you think we can *let it go* and let that previous messed up version rest *under the sea*, I made [another version](https://github.com/StanczakDominik/PlasmaPy/commits/Distribution-fn-squash) where it's all squashed into a single commit. Doing it that way means *no worries* about chronology for this PR.


antoinelpp: Hi @StanczakDominik !
> I took a closer look at the branch history and moanad, because something must have gone horribly wrong there. 

My bad :( I sorry about it.

> we can let it go and let that previous messed up version rest under the sea,

No no no, I'd like not to mess with the branch !

> I made another version where it's all squashed into a single commit. 

Ok that looks way better ! I can try to squash it myself (on my repo) in order to fix the other issues. Or I can remove this PR, clean my branch and do it again... What do you think ?

Again sorry
StanczakDominik: Hey don't worry about it! Git trees are literal straight-outta-Disney magic
from time to time.

I think the best  way to do this would be to go on your branch and sort of
overwrite it with the state of my squash branch, then merge it.

I'll put on my wizard robe and hat and discover a git incantation to do
this. :)

On Oct 6, 2017 10:09, "antoinelpp" <notifications@github.com> wrote:

> Hi @StanczakDominik <https://github.com/stanczakdominik> !
>
> I took a closer look at the branch history and moanad, because something
> must have gone horribly wrong there.
>
> My bad :( I sorry about it.
>
> we can let it go and let that previous messed up version rest under the
> sea,
>
> No no no, I'd like not to mess with the branch !
>
> I made another version where it's all squashed into a single commit.
>
> Ok that looks way better ! I can try to squash it myself (on my repo) in
> order to fix the other issues. Or I can remove this PR, clean my branch and
> do it again... What do you think ?
>
> Again sorry
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/PlasmaPy/PlasmaPy/pull/141#issuecomment-334688233>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AKxDL_2sQ-R25FnyJ3Q05LBeCHMc5a1Kks5speA_gaJpZM4PtTgi>
> .
>

StanczakDominik: I have used the power of Google and divined that (sorry for placeholders,
typing from phone)

`git remote add Dominik CLONE-URL-GOES-HERE`
`git checkout Distribution-fn` (branch name)
`git reset --hard Dominik/Distribution-fn-squash` or whatever the branch
name was
`git push -f`
should do it.

On Oct 6, 2017 10:24, "Dominik Stańczak" <stanczakdominik@gmail.com> wrote:

> Hey don't worry about it! Git trees are literal straight-outta-Disney
> magic from time to time.
>
> I think the best  way to do this would be to go on your branch and sort of
> overwrite it with the state of my squash branch, then merge it.
>
> I'll put on my wizard robe and hat and discover a git incantation to do
> this. :)
>
> On Oct 6, 2017 10:09, "antoinelpp" <notifications@github.com> wrote:
>
>> Hi @StanczakDominik <https://github.com/stanczakdominik> !
>>
>> I took a closer look at the branch history and moanad, because something
>> must have gone horribly wrong there.
>>
>> My bad :( I sorry about it.
>>
>> we can let it go and let that previous messed up version rest under the
>> sea,
>>
>> No no no, I'd like not to mess with the branch !
>>
>> I made another version where it's all squashed into a single commit.
>>
>> Ok that looks way better ! I can try to squash it myself (on my repo) in
>> order to fix the other issues. Or I can remove this PR, clean my branch and
>> do it again... What do you think ?
>>
>> Again sorry
>>
>> —
>> You are receiving this because you were mentioned.
>> Reply to this email directly, view it on GitHub
>> <https://github.com/PlasmaPy/PlasmaPy/pull/141#issuecomment-334688233>,
>> or mute the thread
>> <https://github.com/notifications/unsubscribe-auth/AKxDL_2sQ-R25FnyJ3Q05LBeCHMc5a1Kks5speA_gaJpZM4PtTgi>
>> .
>>
>


Patch:
diff --git a/plasmapy/examples/distribution.ipynb b/plasmapy/examples/distribution.ipynb
new file mode 100644
index 00000000..988de1e7
--- /dev/null
+++ b/plasmapy/examples/distribution.ipynb
@@ -0,0 +1,297 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# plasmapy.physics.distribution\n",
+    "We import the usual and the hero of this notebook, the Maxwellian 1D distribution:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {
+    "ExecuteTime": {
+     "end_time": "2017-10-06T15:17:56.840733Z",
+     "start_time": "2017-10-06T15:17:51.713033Z"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "import numpy as np\n",
+    "from astropy import units as u\n",
+    "import plasmapy\n",
+    "import matplotlib.pyplot as plt\n",
+    "from plasmapy.constants import (m_p, m_e, c, mu0, k_B, e, eps0, pi, e)\n",
+    "%matplotlib inline \n",
+    "from plasmapy.physics.distribution import Maxwellian_1D"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Given we'll be plotting:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {
+    "ExecuteTime": {
+     "end_time": "2017-10-06T15:17:56.868732Z",
+     "start_time": "2017-10-06T15:17:56.854076Z"
+    }
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "<astropy.visualization.units.quantity_support.<locals>.MplQuantityConverter at 0x7f0a9817bb00>"
+      ]
+     },
+     "execution_count": 2,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "from astropy.visualization import quantity_support\n",
+    "quantity_support() "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Let's get the probability density of finding an electron at 1 m/s if we have a plasma at 30 000 K:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {
+    "ExecuteTime": {
+     "end_time": "2017-10-06T15:17:56.955346Z",
+     "start_time": "2017-10-06T15:17:56.880340Z"
+    }
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/latex": [
+       "$5.9163297 \\times 10^{-7} \\; \\mathrm{\\frac{s}{m}}$"
+      ],
+      "text/plain": [
+       "<Quantity 5.916329687405701e-07 s / m>"
+      ]
+     },
+     "execution_count": 3,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "Maxwellian_1D(v=1*u.m/u.s, T= 30000*u.K, particle='e',V_drift=0*u.m/u.s)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Note the units! Integrated over velocities, this will give us a probability. Let's test that for a bunch of particles:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {
+    "ExecuteTime": {
+     "end_time": "2017-10-06T15:18:25.320320Z",
+     "start_time": "2017-10-06T15:18:22.766799Z"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Integral value for p: 0.9999999999999998\n",
+      "Integral value for e: 0.9999999999998787\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": [
+       "<matplotlib.legend.Legend at 0x7f0a6a2d9e48>"
+      ]
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    },
+    {
+     "data": {
+      "image/png": "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\n",
+      "text/plain": [
+       "<matplotlib.figure.Figure at 0x7f0a6a44fcc0>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "# With a vector (from Numpy)\n",
+    "start = -500000\n",
+    "stop = -start\n",
+    "v = np.arange(start,stop) * 10 * u.m/u.s\n",
+    "dv = v[1] - v[0]\n",
+    "\n",
+    "#Test the normationation to 1\n",
+    "for particle in ['p', 'e']:\n",
+    "    pdf = Maxwellian_1D(v,T= 30000*u.K, particle=particle)\n",
+    "    integral = (pdf).sum() * dv\n",
+    "    print(f\"Integral value for {particle}: {integral}\")\n",
+    "    plt.plot(v, pdf, label=particle)\n",
+    "plt.legend()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "The standard deviation of this distribution should give us back our temperature:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {
+    "ExecuteTime": {
+     "end_time": "2017-10-04T10:38:47.008876Z",
+     "start_time": "2017-10-04T10:38:46.994885Z"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "0.9999999999930749\n"
+     ]
+    }
+   ],
+   "source": [
+    "\n",
+    "T =  30000*u.K\n",
+    "std = np.sqrt((Maxwellian_1D(v,T=T, particle='e')*v**2*dv).sum())\n",
+    "T_theo = (std**2/k_B*m_e).to(u.K)\n",
+    "\n",
+    "print(T_theo/T)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "And the center of the distribution is, as can be seen below:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {
+    "ExecuteTime": {
+     "end_time": "2017-10-06T15:18:53.492114Z",
+     "start_time": "2017-10-06T15:18:53.470727Z"
+    }
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/latex": [
+       "$10000 \\; \\mathrm{\\frac{m}{s}}$"
+      ],
+      "text/plain": [
+       "<Quantity 10000.0 m / s>"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "T_e = 30000*u.K\n",
+    "V_drift = 10*u.km/u.s\n",
+    "\n",
+    "start = -5000\n",
+    "stop = - start\n",
+    "dv = 10000 * u.m/u.s\n",
+    "\n",
+    "v_vect = np.arange(start,stop,dtype='float64')* dv\n",
+    "\n",
+    "v_vect[Maxwellian_1D(v_vect,T=T_e, particle='e',V_drift = V_drift ).argmax()]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.6.2"
+  },
+  "varInspector": {
+   "cols": {
+    "lenName": 16,
+    "lenType": 16,
+    "lenVar": 40
+   },
+   "kernels_config": {
+    "python": {
+     "delete_cmd_postfix": "",
+     "delete_cmd_prefix": "del ",
+     "library": "var_list.py",
+     "varRefreshCmd": "print(var_dic_list())"
+    },
+    "r": {
+     "delete_cmd_postfix": ") ",
+     "delete_cmd_prefix": "rm(",
+     "library": "var_list.r",
+     "varRefreshCmd": "cat(var_dic_list()) "
+    }
+   },
+   "types_to_exclude": [
+    "module",
+    "function",
+    "builtin_function_or_method",
+    "instance",
+    "_Feature"
+   ],
+   "window_display": false
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/plasmapy/physics/__init__.py b/plasmapy/physics/__init__.py
index e851a391..e788f7af 100644
--- a/plasmapy/physics/__init__.py
+++ b/plasmapy/physics/__init__.py
@@ -21,3 +21,5 @@
 from .relativity import Lorentz_factor
 
 from .transport import Coulomb_logarithm
+
+from .distribution import (Maxwellian_1D)
diff --git a/plasmapy/physics/distribution.py b/plasmapy/physics/distribution.py
new file mode 100644
index 00000000..dee000b1
--- /dev/null
+++ b/plasmapy/physics/distribution.py
@@ -0,0 +1,94 @@
+"""Functions to deal with distribution : generate, fit, calculate"""
+
+from astropy import units
+
+from astropy.units import (UnitConversionError, UnitsError, quantity_input,
+                           Quantity)
+
+from ..constants import (m_p, m_e, c, mu0, k_B, e, eps0, pi, e)
+from ..atomic import (ion_mass, charge_state)
+from ..atomic.atomic import _is_electron as is_electron
+import numpy as np
+
+from ..utils import _check_quantity, check_relativistic, check_quantity
+
+
+@units.quantity_input
+def Maxwellian_1D(v: units.m/units.s,
+                  T: units.K, particle="e",
+                  V_drift=0*units.m/units.s):
+    r"""Return the probability at the velocity `v` in m/s
+     to find a particle `particle` in a plasma of temperature `T`
+     following the Maxwellian distribution function
+
+    Parameters
+    ----------
+    v: Quantity
+        The velocity in units convertible to m/s
+
+    T: Quantity
+        The temperature in Kelvin
+
+    particle: string, optional
+        Representation of the particle species(e.g., 'p' for protons, 'D+'
+        for deuterium, or 'He-4 +1' for $He_4^{+1}$ : singly ionized helium-4),
+        which defaults to electrons.
+
+    Returns
+    -------
+    f : Quantity
+        probability in Velocity^-1, normized so that:
+        $\int_{- \infty}^{\infty} f(v) dv = 1}
+
+    Raises
+    ------
+    TypeError
+        The parameter arguments are not Quantities and
+        cannot be converted into Quantities.
+
+    UnitConversionError
+        If the parameters is not in appropriate units.
+
+    ValueError
+        If the temperature is negative, or the particle mass or charge state
+        cannot be found.
+
+    Notes
+    -----
+    In one dimension, the Maxwellian distribution function for a particle of
+    mass m, velocity v, a drift velocity V and with temperature T is:
+
+    .. math::
+    f = \sqrt{\frac{m}{2 \pi k_B T}} \exp(-\frac{m}{2 k_B T} (v-V)^2)
+
+
+    Example
+    -------
+    >>> from plasmapy.physics import Maxwellian_1D
+    >>> from astropy import units as u
+    >>> v=1*u.m/u.s
+    >>> Maxwellian_1D(v=v, T= 30000*u.K, particle='e',V_drift=0*u.m/u.s)
+    <Quantity 5.916329687405701e-07 s / m>
+    """
+
+    # pass to Kelvin
+
+    if T.unit.is_equivalent(units.K):
+        T = T.to(units.K, equivalencies=units.temperature_energy())
+
+    # Get mass
+
+    if is_electron(particle):
+        m_s = m_e
+
+    else:
+        try:
+            m_s = ion_mass(particle)
+        except Exception:
+            raise ValueError("Unable to find ion mass in Maxwellian_1D")
+
+    T = k_B*T
+
+    f = np.sqrt((m_s/(2*pi*T)))*np.exp(-m_s/(2*T)*(v-V_drift)**2)
+
+    return f.to(units.s/units.m)


Test patch:
diff --git a/plasmapy/physics/tests/test_distribution.py b/plasmapy/physics/tests/test_distribution.py
new file mode 100644
index 00000000..eb93cd7d
--- /dev/null
+++ b/plasmapy/physics/tests/test_distribution.py
@@ -0,0 +1,44 @@
+"""Tests for functions that uses Distribution functions."""
+
+import numpy as np
+import pytest
+from astropy import units as u
+
+
+from ...constants import (m_p, m_e, c, mu0, k_B, e, eps0, pi, e)
+from ...atomic import (ion_mass, charge_state)
+from ..distribution import (Maxwellian_1D)
+
+T_e = 30000*u.K
+V_drift = 1000000*u.m/u.s
+
+start = -5000
+stop = - start
+dv = 10000 * u.m/u.s
+
+v_vect = np.arange(start, stop, dtype='float64') * dv
+
+
+def test_Maxwellian_1D():
+    """test the 1D maxwellian distribution function"""
+
+    max_index = Maxwellian_1D(v_vect, T=T_e, particle='e', V_drift=0*u.m/u.s
+                              ).argmax()
+    assert np.isclose(v_vect[max_index].value, 0.0)
+
+    max_index = Maxwellian_1D(v_vect, T=T_e, particle='e', V_drift=V_drift
+                              ).argmax()
+    assert np.isclose(v_vect[max_index].value, V_drift.value)
+
+    # integral of the distribution over v_vect
+    integral = (Maxwellian_1D(v_vect, T=30000*u.K, particle='e')).sum()*dv
+    assert np.isclose(integral, 1.0)
+
+    std = (Maxwellian_1D(v_vect, T=T_e, particle='e')*v_vect**2*dv).sum()
+    std = np.sqrt(std)
+    T_distri = (std**2/k_B*m_e).to(u.K)
+
+    assert np.isclose(T_distri.value, T_e.value)
+
+    with pytest.raises(ValueError):
+        Maxwellian_1D(1*u.m/u.s, T=1*u.K, particle='XXX')