prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Create classes to represent ionization state distributions
  My plan for this PR is to create classes to represent the ionization state distributions of one or more elements.  I am going to add in a bunch of dunder methods like `__getitem__` and maybe `__call__` to help making access to the ionization states more straightfoward and intuitive.  Any suggestions on the naming convention will be helpful so that we can maximize readability. 
  
  Eventually we'll need a way to calculate ionization state distributions assuming collisional ionization equilibrium, but that will be for a different PR.  The purpose of this PR is to set up how to store and access the ionization distributions.  This will be discussed in #352.
  
  This will address some of #352.  It will probably be best to wait until after the `0.1.0` release to merge this, since this PR is only for a partial implementation anyway.
  
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `plasmapy/examples/plot_dispersion_function.py`
  Content:
  ```
  1 """
  2 The plasma dispersion function
  3 ==============================
  4 
  5 Let's import some basics (and `PlasmaPy`!)
  6 """
  7 
  8 
  9 import numpy as np
  10 import matplotlib.pyplot as plt
  11 import plasmapy
  12 
  13 
  14 #######################################################################
  15 help(plasmapy.mathematics.plasma_dispersion_func)
  16 
  17 
  18 #######################################################################
  19 # We'll now make some sample data to visualize the dispersion function:
  20 
  21 x = np.linspace(-1, 1, 1000)
  22 X, Y = np.meshgrid(x, x)
  23 Z = X + 1j * Y
  24 print(Z.shape)
  25 
  26 #######################################################################
  27 # Before we start plotting, let's make a visualization function first:
  28 
  29 
  30 def plot_complex(X, Y, Z, N=50):
  31     fig, (real_axis, imag_axis) = plt.subplots(1, 2)
  32     real_axis.contourf(X, Y, Z.real, N)
  33     imag_axis.contourf(X, Y, Z.imag, N)
  34     real_axis.set_title("Real values")
  35     imag_axis.set_title("Imaginary values")
  36     for ax in [real_axis, imag_axis]:
  37         ax.set_xlabel("Real values")
  38         ax.set_ylabel("Imaginary values")
  39     fig.tight_layout()
  40 
  41 
  42 plot_complex(X, Y, Z)
  43 
  44 #######################################################################
  45 # We can now apply our visualization function to our simple
  46 
  47 F = plasmapy.mathematics.plasma_dispersion_func(Z)
  48 plot_complex(X, Y, F)
  49 
  50 
  51 #######################################################################
  52 # So this is going to be a hack and I'm not 100% sure the dispersion function
  53 # is quite what I think it is, but let's find the area where the dispersion
  54 # function has a lesser than zero real part because I think it may be important
  55 # (brb reading Fried and Conte):
  56 
  57 plot_complex(X, Y, F.real < 0)
  58 
  59 
  60 #######################################################################
  61 # We can also visualize the derivative:
  62 
  63 F = plasmapy.mathematics.plasma_dispersion_func_deriv(Z)
  64 plot_complex(X, Y, F)
  65 
  66 #######################################################################
  67 # Plotting the same function on a larger area:
  68 
  69 x = np.linspace(-2, 2, 2000)
  70 X, Y = np.meshgrid(x, x)
  71 Z = X + 1j * Y
  72 print(Z.shape)
  73 
  74 #######################################################################
  75 
  76 F = plasmapy.mathematics.plasma_dispersion_func(Z)
  77 plot_complex(X, Y, F, 100)
  78 
  79 #######################################################################
  80 # Now we examine the derivative of the dispersion function as a function
  81 # of the phase velocity of an electromagnetic wave propagating through
  82 # the plasma. This is recreating figure 5.1 in:
  83 # J. Sheffield, D. Froula, S. H. Glenzer, and N. C. Luhmann Jr,
  84 # Plasma scattering of electromagnetic radiation: theory and measurement
  85 # techniques. Chapter 5 Pg 106 (Academic press, 2010).
  86 
  87 xs = np.linspace(0, 4, 100)
  88 ws = (-1 / 2) * plasmapy.mathematics.plasma_dispersion_func_deriv(xs)
  89 wRe = np.real(ws)
  90 wIm = np.imag(ws)
  91 
  92 plt.plot(xs, wRe, label="Re")
  93 plt.plot(xs, wIm, label="Im")
  94 plt.axis([0, 4, -0.3, 1])
  95 plt.legend(loc='upper right',
  96            frameon=False,
  97            labelspacing=0.001,
  98            fontsize=14,
  99            borderaxespad=0.1)
  100 plt.show()
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/plasmapy/examples/plot_dispersion_function.py b/plasmapy/examples/plot_dispersion_function.py
  --- a/plasmapy/examples/plot_dispersion_function.py
  +++ b/plasmapy/examples/plot_dispersion_function.py
  @@ -10,7 +10,6 @@
   import matplotlib.pyplot as plt
   import plasmapy
   
  -
   #######################################################################
   help(plasmapy.mathematics.plasma_dispersion_func)
   
  @@ -41,9 +40,10 @@
   
   plot_complex(X, Y, Z)
   
  -#######################################################################
  -# We can now apply our visualization function to our simple
  +###############################################################################
  +# We can now apply our visualization function to our simple dispersion relation
   
  +# sphinx_gallery_thumbnail_number = 2
   F = plasmapy.mathematics.plasma_dispersion_func(Z)
   plot_complex(X, Y, F)
   
  @@ -97,4 +97,4 @@
              labelspacing=0.001,
              fontsize=14,
              borderaxespad=0.1)
  -plt.show()
  \ No newline at end of file
  +plt.show()
  
verification_info: {"golden_diff": "diff --git a/plasmapy/examples/plot_dispersion_function.py b/plasmapy/examples/plot_dispersion_function.py\n--- a/plasmapy/examples/plot_dispersion_function.py\n+++ b/plasmapy/examples/plot_dispersion_function.py\n@@ -10,7 +10,6 @@\n import matplotlib.pyplot as plt\n import plasmapy\n \n-\n #######################################################################\n help(plasmapy.mathematics.plasma_dispersion_func)\n \n@@ -41,9 +40,10 @@\n \n plot_complex(X, Y, Z)\n \n-#######################################################################\n-# We can now apply our visualization function to our simple\n+###############################################################################\n+# We can now apply our visualization function to our simple dispersion relation\n \n+# sphinx_gallery_thumbnail_number = 2\n F = plasmapy.mathematics.plasma_dispersion_func(Z)\n plot_complex(X, Y, F)\n \n@@ -97,4 +97,4 @@\n            labelspacing=0.001,\n            fontsize=14,\n            borderaxespad=0.1)\n-plt.show()\n\\ No newline at end of file\n+plt.show()\n", "issue": "Create classes to represent ionization state distributions\nMy plan for this PR is to create classes to represent the ionization state distributions of one or more elements.  I am going to add in a bunch of dunder methods like `__getitem__` and maybe `__call__` to help making access to the ionization states more straightfoward and intuitive.  Any suggestions on the naming convention will be helpful so that we can maximize readability. \r\n\r\nEventually we'll need a way to calculate ionization state distributions assuming collisional ionization equilibrium, but that will be for a different PR.  The purpose of this PR is to set up how to store and access the ionization distributions.  This will be discussed in #352.\r\n\r\nThis will address some of #352.  It will probably be best to wait until after the `0.1.0` release to merge this, since this PR is only for a partial implementation anyway.\r\n\r\n\n", "before_files": [{"content": "\"\"\"\nThe plasma dispersion function\n==============================\n\nLet's import some basics (and `PlasmaPy`!)\n\"\"\"\n\n\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport plasmapy\n\n\n#######################################################################\nhelp(plasmapy.mathematics.plasma_dispersion_func)\n\n\n#######################################################################\n# We'll now make some sample data to visualize the dispersion function:\n\nx = np.linspace(-1, 1, 1000)\nX, Y = np.meshgrid(x, x)\nZ = X + 1j * Y\nprint(Z.shape)\n\n#######################################################################\n# Before we start plotting, let's make a visualization function first:\n\n\ndef plot_complex(X, Y, Z, N=50):\n    fig, (real_axis, imag_axis) = plt.subplots(1, 2)\n    real_axis.contourf(X, Y, Z.real, N)\n    imag_axis.contourf(X, Y, Z.imag, N)\n    real_axis.set_title(\"Real values\")\n    imag_axis.set_title(\"Imaginary values\")\n    for ax in [real_axis, imag_axis]:\n        ax.set_xlabel(\"Real values\")\n        ax.set_ylabel(\"Imaginary values\")\n    fig.tight_layout()\n\n\nplot_complex(X, Y, Z)\n\n#######################################################################\n# We can now apply our visualization function to our simple\n\nF = plasmapy.mathematics.plasma_dispersion_func(Z)\nplot_complex(X, Y, F)\n\n\n#######################################################################\n# So this is going to be a hack and I'm not 100% sure the dispersion function\n# is quite what I think it is, but let's find the area where the dispersion\n# function has a lesser than zero real part because I think it may be important\n# (brb reading Fried and Conte):\n\nplot_complex(X, Y, F.real < 0)\n\n\n#######################################################################\n# We can also visualize the derivative:\n\nF = plasmapy.mathematics.plasma_dispersion_func_deriv(Z)\nplot_complex(X, Y, F)\n\n#######################################################################\n# Plotting the same function on a larger area:\n\nx = np.linspace(-2, 2, 2000)\nX, Y = np.meshgrid(x, x)\nZ = X + 1j * Y\nprint(Z.shape)\n\n#######################################################################\n\nF = plasmapy.mathematics.plasma_dispersion_func(Z)\nplot_complex(X, Y, F, 100)\n\n#######################################################################\n# Now we examine the derivative of the dispersion function as a function\n# of the phase velocity of an electromagnetic wave propagating through\n# the plasma. This is recreating figure 5.1 in:\n# J. Sheffield, D. Froula, S. H. Glenzer, and N. C. Luhmann Jr,\n# Plasma scattering of electromagnetic radiation: theory and measurement\n# techniques. Chapter 5 Pg 106 (Academic press, 2010).\n\nxs = np.linspace(0, 4, 100)\nws = (-1 / 2) * plasmapy.mathematics.plasma_dispersion_func_deriv(xs)\nwRe = np.real(ws)\nwIm = np.imag(ws)\n\nplt.plot(xs, wRe, label=\"Re\")\nplt.plot(xs, wIm, label=\"Im\")\nplt.axis([0, 4, -0.3, 1])\nplt.legend(loc='upper right',\n           frameon=False,\n           labelspacing=0.001,\n           fontsize=14,\n           borderaxespad=0.1)\nplt.show()", "path": "plasmapy/examples/plot_dispersion_function.py"}], "after_files": [{"content": "\"\"\"\nThe plasma dispersion function\n==============================\n\nLet's import some basics (and `PlasmaPy`!)\n\"\"\"\n\n\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport plasmapy\n\n#######################################################################\nhelp(plasmapy.mathematics.plasma_dispersion_func)\n\n\n#######################################################################\n# We'll now make some sample data to visualize the dispersion function:\n\nx = np.linspace(-1, 1, 1000)\nX, Y = np.meshgrid(x, x)\nZ = X + 1j * Y\nprint(Z.shape)\n\n#######################################################################\n# Before we start plotting, let's make a visualization function first:\n\n\ndef plot_complex(X, Y, Z, N=50):\n    fig, (real_axis, imag_axis) = plt.subplots(1, 2)\n    real_axis.contourf(X, Y, Z.real, N)\n    imag_axis.contourf(X, Y, Z.imag, N)\n    real_axis.set_title(\"Real values\")\n    imag_axis.set_title(\"Imaginary values\")\n    for ax in [real_axis, imag_axis]:\n        ax.set_xlabel(\"Real values\")\n        ax.set_ylabel(\"Imaginary values\")\n    fig.tight_layout()\n\n\nplot_complex(X, Y, Z)\n\n###############################################################################\n# We can now apply our visualization function to our simple dispersion relation\n\n# sphinx_gallery_thumbnail_number = 2\nF = plasmapy.mathematics.plasma_dispersion_func(Z)\nplot_complex(X, Y, F)\n\n\n#######################################################################\n# So this is going to be a hack and I'm not 100% sure the dispersion function\n# is quite what I think it is, but let's find the area where the dispersion\n# function has a lesser than zero real part because I think it may be important\n# (brb reading Fried and Conte):\n\nplot_complex(X, Y, F.real < 0)\n\n\n#######################################################################\n# We can also visualize the derivative:\n\nF = plasmapy.mathematics.plasma_dispersion_func_deriv(Z)\nplot_complex(X, Y, F)\n\n#######################################################################\n# Plotting the same function on a larger area:\n\nx = np.linspace(-2, 2, 2000)\nX, Y = np.meshgrid(x, x)\nZ = X + 1j * Y\nprint(Z.shape)\n\n#######################################################################\n\nF = plasmapy.mathematics.plasma_dispersion_func(Z)\nplot_complex(X, Y, F, 100)\n\n#######################################################################\n# Now we examine the derivative of the dispersion function as a function\n# of the phase velocity of an electromagnetic wave propagating through\n# the plasma. This is recreating figure 5.1 in:\n# J. Sheffield, D. Froula, S. H. Glenzer, and N. C. Luhmann Jr,\n# Plasma scattering of electromagnetic radiation: theory and measurement\n# techniques. Chapter 5 Pg 106 (Academic press, 2010).\n\nxs = np.linspace(0, 4, 100)\nws = (-1 / 2) * plasmapy.mathematics.plasma_dispersion_func_deriv(xs)\nwRe = np.real(ws)\nwIm = np.imag(ws)\n\nplt.plot(xs, wRe, label=\"Re\")\nplt.plot(xs, wIm, label=\"Im\")\nplt.axis([0, 4, -0.3, 1])\nplt.legend(loc='upper right',\n           frameon=False,\n           labelspacing=0.001,\n           fontsize=14,\n           borderaxespad=0.1)\nplt.show()\n", "path": "plasmapy/examples/plot_dispersion_function.py"}]}