Repository: materials-data-facility/scythe (language: python)

Issue:
Remove setup.py and associated changes
Resolves #41 

Among the changes in this PR:

- Update of major dependencies to latest practical versions (see `pyproject.toml`)
  - This means dependabot's #40 and #39 can be closed since this PR bumps those packages
- Bump of minimum Python version to 3.8 (required to update dependencies)
- Bump overall project version to 0.1.1 (if this is too much, we could do 0.0.2 instead if you prefer @WardLT) 
- Document install and development using poetry
- Document user install via `pip install git+https://....`
- Fix all Sphinx warnings in documentation generation
- Add `flake8` and coverage reports to tox workflows
- Add `schema` property to electron microscopy parser (sort of unrelated, sorry it's in this one)

This PR does not include CI/CD via Github actions, so in the meantime it would be good for someone else to test out the install instructions and such prior to merging. I gave it a few tests in bare 3.8 virtualenvs, but it's always good to confirm on an unrelated system.
Setup Github actions
As discussed in https://github.com/materials-data-facility/MaterialsIO/pull/38#issuecomment-1078046434, we should use Github actions to setup automatic CI/CD, code coverage, and documentation generation.


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/ensure-pip-installable.yml b/.github/workflows/ensure-pip-installable.yml
new file mode 100644
index 0000000..b8d0cb0
--- /dev/null
+++ b/.github/workflows/ensure-pip-installable.yml
@@ -0,0 +1,18 @@
+name: Install with pip
+on: [push, pull_request]
+jobs:
+  install:
+    name: ${{ matrix.os }}-py${{ matrix.python-version }}
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        python-version: [ "3.8", "3.9", "3.10" ]
+        poetry-version: [ "1.1.13" ]
+        os: [ ubuntu-latest, macos-latest ] #, windows-latest]
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-python@v2
+        with:
+          python-version: ${{ matrix.python-version }}
+      - run: pip install .[all]
diff --git a/.gitignore b/.gitignore
index c605a6d..3531a04 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,10 +8,16 @@ Untitled*.ipynb
 *.DS_Store
 
 */build/*
+docs/_build
+materials_io/schemas/doc/
 */dist/*
 *.egg*
 src/*
+dist/
+.tox
 
+coverage_html/
+coverage.xml
 *.coverage*
 *.pytest_cache*
 .vscode
diff --git a/.python-version b/.python-version
index f7e5aa8..8b4d27e 100644
--- a/.python-version
+++ b/.python-version
@@ -1,1 +1,3 @@
-3.7.12
+3.8.12
+3.9.12
+3.10.4
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index e71c745..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-language: python
-python:
-- "3.6"
-cache: pip
-install:
-- wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
-- bash miniconda.sh -b -p $HOME/miniconda
-- export PATH="$HOME/miniconda/bin:$PATH"
-- conda config --set always_yes yes --set changeps1 no
-- conda update -q conda
-- conda create -q -n test-env python=$TRAVIS_PYTHON_VERSION
-- source activate test-env
-- conda install hyperspy -c conda-forge
-- conda install -c pycalphad -c msys2 -c conda-forge pycalphad
-- pip install --upgrade pip
-- pip install -e .
-- pip install -r requirements.txt --src ~/pip_src/
-- pip install -r test_requirements.txt
-script:
-- flake8 . && travis_wait 50 py.test
-after_success:
-- coveralls
diff --git a/README.md b/README.md
index 1b4f386..64b997f 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,11 @@
 # MaterialsIO
 
-[![Build Status](https://travis-ci.org/materials-data-facility/MaterialsIO.svg?branch=master)](https://travis-ci.org/materials-data-facility/MaterialsIO)
-[![Documentation Status](https://readthedocs.org/projects/materialsio/badge/?version=latest)](https://materialsio.readthedocs.io/en/latest/?badge=latest)
-[![Coverage Status](https://coveralls.io/repos/github/materials-data-facility/MaterialsIO/badge.svg?branch=master)](https://coveralls.io/github/materials-data-facility/MaterialsIO?branch=master)
+[![Build Status](https://github.com/materials-data-facility/MaterialsIO/workflows/Build%20Status/badge.svg)](https://github.com/materials-data-facility/MaterialsIO/actions/workflows/test-suite-and-docs.yml)
+[![Documentation](https://img.shields.io/badge/-Documentation-blue?style=flat&logo=bookstack&labelColor=grey&logoColor=white)](https://materials-data-facility.github.io/MaterialsIO)
+[![Coverage Status](https://codecov.io/gh/materials-data-facility/MaterialsIO/branch/master/graph/badge.svg)](https://codecov.io/gh/materials-data-facility/MaterialsIO)
+[![GitHub tag checks state](https://img.shields.io/github/checks-status/materials-data-facility/MaterialsIO/master)](https://github.com/materials-data-facility/MaterialsIO/actions)
+[![GitHub last commit](https://img.shields.io/github/last-commit/materials-data-facility/MaterialsIO)](https://github.com/materials-data-facility/MaterialsIO/commits/master)
+[![GitHub contributors](https://img.shields.io/github/contributors/materials-data-facility/MaterialsIO)](https://github.com/materials-data-facility/MaterialsIO/graphs/contributors)
 
 MaterialsIO is a library of tools that generate summaries of the data contained in scientific data files.
 The goal of MaterialsIO is to provide a shared resources of these tool to avoid duplication of effort between the many emerging materials databases.
@@ -11,18 +14,25 @@ Each parser is designed to generate the sum of all data needed by each of these
 ## Installation
 
 MaterialsIO is still under early stages of development. 
-To use it, first clone this repository and then install the library with pip:
+To use it (as a user, rather than a developer), install the library from Github
+with an up-to-date version of `pip` on version 3.8 or higher of Python:
 
 ```bash
-git clone git@github.com:materials-data-facility/MaterialsIO.git
-cd MaterialsIO
-pip install -e .
+pip install git+https://github.com/materials-data-facility/MaterialsIO.git
 ```
 
 Each specific parser module has its own set of required libraries.
 Given that some modules have extensive dependencies, we do not install all of them automatically.
-You can install them either module-by-module using the pip "extras" installation (e.g., `pip install -e .['image']`),
-or install all requirements with the requirements file `pip install -r requirements.txt`.
+You can install them either module-by-module using the pip "extras" installation (e.g., 
+`pip install "git+https://github.com/materials-data-facility/MaterialsIO.git#egg=materials_io[image]"`),
+or install all parsers with 
+`pip install "git+https://github.com/materials-data-facility/MaterialsIO.git#egg=materials_io[all]"`.
+
+## Development/Contribution
+
+If you wish to develop new features using MaterialsIO, please consult the 
+[Contributor Guide](https://materialsio.readthedocs.io/en/latest/contributor-guide.html) that will
+walk you through installing [Poetry](https://python-poetry.org/) and the MaterialsIO dependencies.
 
 ## Documentation
 
diff --git a/docs/source/conf.py b/docs/source/conf.py
index b266c38..bf04430 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -22,7 +22,7 @@
 # -- Project information -----------------------------------------------------
 
 project = 'MaterialsIO'
-copyright = '2019, Materials Data Facility Team, Citrine Informatics'
+copyright = '2019 - 2022, Materials Data Facility Team, Citrine Informatics'
 author = 'Materials Data Facility Team, Citrine Informatics'
 
 # The short X.Y version
@@ -46,7 +46,9 @@
     'sphinx.ext.todo',
     'sphinx.ext.napoleon',
     'sphinx.ext.viewcode',
-    'stevedore.sphinxext'
+    'stevedore.sphinxext',
+    'sphinx.ext.autosectionlabel',
+    'sphinx.ext.githubpages'
 ]
 
 # Add any paths that contain templates here, relative to this directory.
@@ -93,7 +95,7 @@
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+# html_static_path = ['_static']
 
 # Custom sidebar templates, must be a dictionary that maps document names
 # to template names.
@@ -188,7 +190,7 @@
 # -- Options for intersphinx extension ---------------------------------------
 
 # Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'https://docs.python.org/': None}
+intersphinx_mapping = {'python': ('https://docs.python.org/3/', None)}
 
 # -- Options for todo extension ----------------------------------------------
 
diff --git a/docs/source/contributor-guide.rst b/docs/source/contributor-guide.rst
index 6f4fb39..063a2de 100644
--- a/docs/source/contributor-guide.rst
+++ b/docs/source/contributor-guide.rst
@@ -1,15 +1,72 @@
 Contributor Guide
 =================
 
-This part of the MaterialsIO guide details how to add a new parser to the ecosystem.
+Setting up development environment
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+MaterialsIO makes use of the `Poetry <https://python-poetry.org/docs/>`_ project to manage
+dependencies and packaging. To install the latest version of MaterialsIO, first install poetry
+following `their documentation <https://python-poetry.org/docs/#installation>`_. Once that's
+done, clone/download the MaterialsIO repository locally from
+`Github <https://github.com/materials-data-facility/MaterialsIO/>`_. Change into that directory
+and run ``poetry install`` (it would be a good idea to create a new virtual environment for your
+project first too, so as to not mix dependencies with your system environment).
+
+By default, only a small subset of parsers will be installed (this is done so that you do not
+need to install all the dependencies of parsers you may never use). To install additional
+parsers, you can specify "extras" at install time using ``poetry``. Any of the values specified
+in the ``[tool.poetry.extras]`` section of ``pyproject.toml`` can be provided, including ``all``,
+which will install all bundled parsers and their dependencies. For example::
+
+    poetry install -E all
+
+Poetry wil create a dedicated virtual environment for the project and the MaterialsIO code will
+be installed in "editable" mode, so any changes you make to the code will be reflected when
+running tests, importing parsers, etc. It will use the default version of python available.
+MaterialsIO is currently developed and tested against Python versions 3.8.12, 3.9.12, and 3.10.4.
+We recommend using the `pyenv <https://github.com/pyenv/pyenv>`_ project to manage
+various python versions on your system if this does not match your system version of Python. It
+is required to use ``tox`` as well (see next paragraph). Make sure you install the versions
+specified in the ``.python-version`` file by running commands such as ``pyenv install 3.8.12`` etc.
+
+Additionally, the project uses `tox <https://tox.wiki/en/latest/>`_ to simplify common tasks and
+to be able to run tests in isolated environments. This will be installed automatically as a
+development package when running the ``poetry install`` command above. It can be used to run the
+test suite with common settings, as well as building the documentation. For example, to
+run the full MaterialsIO test suite on all three versions of Python targetd, just run::
+
+    poetry run tox
+
+To build the HTML documentation (will be placed inside the ``./docs/_build/`` folder), run::
+
+    poetry run tox -e docs
+
+For the sake of speed, if you would like to focus your testing on just one Python version, you can
+temporarily override the environment list from ``pyproject.toml`` with an enviornment variable.
+For example, to only run the test/coverage suite on Python 3.8.X, run::
+
+    TOXENV=py38 poetry run tox
+
+Check out the ``[tool.tox]`` section of the ``pyproject.toml`` file to view how these tasks are
+configured, and the `tox documentation <https://tox.wiki/en/latest/config.html>`_ on how to add your
+own custom tasks, if needed.
+
+Finally, MaterialsIO uses ``flake8`` to enforce code styles, which will be run for you
+automatically when using ``tox`` as defined above. Any code-style errors, such as lines longer
+than 100 characters, trailing whitespace, etc. will be flagged when running ``poetry run tox``.
+
+The next part of the MaterialsIO guide details how to add a new parser to the ecosystem.
 
 Step 1: Implement the Parser
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Creating a new parser is accomplished by implementing the `BaseParser <user-guide.html#parser-api>`_ abstract class.
-If you are new to MaterailsIO, we recommend reviewing the `User Guide <user-guide.html#available-methods>`_ first to learn about the available methods of BaseParser.
-Minimally, you need only implement the ``parse``, ``version``, and ``implementors`` operations for a new parser.
-Each of these methods (and any other methods you override) must be stateless, so that running the operation does not change the behavior of the parser.
+Creating a new parser is accomplished by implementing the
+`BaseParser <user-guide.html#parser-api>`_ abstract class. If you are new to MaterailsIO, we
+recommend reviewing the `User Guide <user-guide.html#available-methods>`_ first to learn about
+the available methods of BaseParser. Minimally, you need only implement the ``parse``,
+``version``, and ``implementors`` operations for a new parser. Each of these methods (and any
+other methods you override) must be stateless, so that running the operation does not change the
+behavior of the parser.
 
 We also have subclasses of ``BaseParser`` that are useful for common types of parsers:
 
@@ -20,109 +77,117 @@ Class Attributes and Initializer
 
 The ``BaseParser`` class supports configuration options as Python class attributes.
 These options are intended to define the behavior of a parser for a particular environment
-(e.g., paths of required executables) or for a particular application (e.g., turning off unneeded features).
-We recommend limiting these options to be only JSON-serializable data types and for all to be defined in the ``__init__`` function to simplify text-based configuration files.
+(e.g., paths of required executables) or for a particular application (e.g., turning off unneeded
+features). We recommend limiting these options to be only JSON-serializable data types and for
+all to be defined in the ``__init__`` function to simplify text-based configuration files.
 
-The initializer function should check if a parser has access to all required external tools, and throw exceptions if not.
-For example, a parser that relies on calling an external command-line tool should check whether the package is installed.
-In general, parsers should fail during initialization and not during the parsing operation if the system in misconfigured.
+The initializer function should check if a parser has access to all required external tools, and
+throw exceptions if not. For example, a parser that relies on calling an external command-line
+tool should check whether the package is installed. In general, parsers should fail during
+initialization and not during the parsing operation if the system in misconfigured.
 
 Implementing ``parse``
 ----------------------
 
-The ``parse`` method contains the core logic of a MaterialsIO parser: rendering a summary of a group of data files.
-We do not specify any particular schema for the output but we do recommend best practices:
+The ``parse`` method contains the core logic of a MaterialsIO parser: rendering a summary of a
+group of data files. We do not specify any particular schema for the output but we do recommend
+best practices:
 
 
 #. *Summaries must be JSON-serializable.*
-    Limiting to JSON data types ensures summaries are readable by most software without special libraries.
-    JSON documents are also able to be documented easily.
+    Limiting to JSON data types ensures summaries are readable by most software without specia
+    libraries. JSON documents are also able to be documented easily.
 
 #. *Human-readability is desirable.*
     JSON summaries should be understandable to users without expert-level knowledge of the data.
-    Avoid unfamiliar acronyms, such as names of variables in a specific simulation code or settings specific to a certain brand of instrument.
+    Avoid unfamiliar acronyms, such as names of variables in a specific simulation code or settings
+    specific to a certain brand of instrument.
 
 #. *Adhere closely to the original format.*
-    If feasible, try to stay close to the original data format of a file or the output of a library used for parsing.
-    Deviating from already existing formats complicates modifications to a parser.
+    If feasible, try to stay close to the original data format of a file or the output of a library
+    used for parsing. Deviating from already existing formats complicates modifications to a parser.
 
 #. *Always return a dictionary.*
-    If a parser can return multiple records from a single file group, return the list as an element of the dictionary.
-    Any metadata that pertains to each of the sub-records should be stored as a distinct element
-    rather than being duplicated in each sub-record.
+    If a parser can return multiple records from a single file group, return the list as an element
+    of the dictionary. Any metadata that pertains to each of the sub-records should be stored as
+    a distinct element rather than being duplicated in each sub-record.
 
 
 We also have a recommendations for the parser behavior:
 
 #. *Avoid configuration options that change only output format.*
-    Parsers can take configuration options that alter the output format, but configurations should be used sparingly.
-    A good use of configuration would be to disable complex parsing operations if unneeded.
-    A bad use of configuration would be to change the output to match a different schema.
-    Operations that significantly alter the form but not the content of a summary should be implemented as adaptors.
+    Parsers can take configuration options that alter the output format, but configurations
+    should be used sparingly. A good use of configuration would be to disable complex parsing
+    operations if unneeded. A bad use of configuration would be to change the output to match a
+    different schema. Operations that significantly alter the form but not the content of a
+    summary should be implemented as adaptors.
 
 #. *Consider whether context should be configuration.*
-    Settings that are identical for each file could be better suited as configuration settings than as context.
+    Settings that are identical for each file could be better suited as configuration settings
+    than as context.
 
 Implementing ``group``
 ----------------------
 
-The ``group`` operation finds all sets of files in a user-provided list files and directories that should be parsed together.
-Implementing ``group`` is optional.
-Implementing a new ``group`` method is required only when the default behavior of "each file is its own group"
-(i.e., the parser only treats files individually) is incorrect.
+The ``group`` operation finds all sets of files in a user-provided list files and directories
+that should be parsed together. Implementing ``group`` is optional. Implementing a new ``group``
+method is required only when the default behavior of "each file is its own group" (i.e., the
+parser only treats files individually) is incorrect.
 
-The ``group`` operation should not require access to the content of the files or directories
-to determine groupings.
-Being able to determine file groups via only file names improves performance
-and allows for determining groups of parsable files without needing to download
-them from remote systems.
+The ``group`` operation should not require access to the content of the files or directories to
+determine groupings. Being able to determine file groups via only file names improves performance
+and allows for determining groups of parsable files without needing to download them from remote
+systems.
 
-Files are allowed to appear in more than one group,
-but we recommend generating only the largest valid group of files to minimize the same metadata being generated multiple times.
+Files are allowed to appear in more than one group, but we recommend generating only the largest
+valid group of files to minimize the same metadata being generated multiple times.
 
-It is important to note that that file groups are specific to a parser.
-Groupings of files that are meaningful to one parser need not be meaningful to another.
-For that reason, limit the definition of groups to sets of files that can be parsed together
-without consideration to what other information makes the files related (e.g., being in the same directory).
+It is important to note that that file groups are specific to a parser. Groupings of files that
+are meaningful to one parser need not be meaningful to another. For that reason, limit the
+definition of groups to sets of files that can be parsed together without consideration to what
+other information makes the files related (e.g., being in the same directory).
 
-Another appropriate use of the ``group`` operation is to filter out files which are very unlikely to parse correctly.
-For example, a PDF parser could identify only files with a ".pdf" extension.
+Another appropriate use of the ``group`` operation is to filter out files which are very unlikely
+to parse correctly. For example, a PDF parser could identify only files with a ".pdf" extension.
 However, we recommend using filtering sparing to ensure no files are missed.
 
 Implementing ``citations`` and ``implementors``
 -----------------------------------------------
 
-The ``citation`` and ``implementors`` methods identify additional resources describing a parser and provide credit to contributors.
-``implementors`` is required, as this operation is also used to identify points-of-contact for support requests.
+The ``citation`` and ``implementors`` methods identify additional resources describing a parser
+and provide credit to contributors. ``implementors`` is required, as this operation is also used
+to identify points-of-contact for support requests.
 
 ``citation`` should return a list of BibTeX-format references.
 
-``implementors`` should return a list of people and, optionally, their contract infomration
+``implementors`` should return a list of people and, optionally, their contract information
 in the form: "FirstName LastName <email@provider.com>".
 
 Implementing ``version``
 ------------------------
 
 We require using `semantic versioning <https://semver.org/>`_ for specifying the version of parsers.
-As the API of the parser should remain unchanged, use versioning to indicate changes in available options or the output schema.
-The ``version`` operation should return the version of the parser.
+As the API of the parser should remain unchanged, use versioning to indicate changes in available
+options or the output schema. The ``version`` operation should return the version of the parser.
 
 
 Step 2: Document the Parser
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The docstring for a parser must start with a short, one sentence summary of the parser,
-which will be used by our autodocumentation tooling.
-The rest of the documentation should describe what types of files are compatible,
-what context infomration can be used, and
+The docstring for a parser must start with a short, one sentence summary of the parser, which
+will be used by our autodocumentation tooling. The rest of the documentation should describe what
+types of files are compatible, what context infomration can be used, and
 summarize what types of metadata are generated.
 
 .. todo:: Actually write these descriptors for the available parsers
 
-The MaterialsIO project uses JSON documents as the output for all parsers and `JSON Schema <https://json-schema.org/>`_ to describe the content of the documents.
-The BaseParser class includes a property, ``schema``, that stores a description of the output format.
-We recommend writing your description as a separate file and having the ``schema`` property read and output the contents of this file.
-See the `GenericFileParser source code <https://github.com/materials-data-facility/MaterialsIO/blob/master/materials_io/file.py>`_ for a example.
+The MaterialsIO project uses JSON documents as the output for all parsers and
+`JSON Schema <https://json-schema.org/>`_ to describe the content of the documents. The
+BaseParser class includes a property, ``schema``, that stores a description of the output format.
+We recommend writing your description as a separate file and having the ``schema`` property read
+and output the contents of this file. See the
+`GenericFileParser source code <https://github.com/materials-data-facility/MaterialsIO/blob/master/materials_io/file.py>`_
+for a example.
 
 
 Step 3: Register the Parser
@@ -131,23 +196,33 @@ Step 3: Register the Parser
 Preferred Route: Adding the Parser to MaterialsIO
 -------------------------------------------------
 
-If your parser has the same dependencies as existing parsers, add it to the existing module with the same dependencies.
+If your parser has the same dependencies as existing parsers, add it to the existing module with
+the same dependencies.
 
-If your parser has new dependencies, create a new module for your parser in ``materials_io``, and then add the requirements as a new key in the ``extras_require`` dictionary of ``setup.py`` and the ``requirements.txt`` file.
-Next, add your parser to ``docs/source/parsers.rst`` by adding an ``.. automodule::`` statement that refers to your new module.
+If your parser has new dependencies, create a new module for your parser in ``materials_io``, and
+then add the requirements as a new key in the ``[tool.poetry.extras]`` section of ``pyproject
+.toml``, following the other parser examples in that section. Next, add your parser to
+``docs/source/parsers.rst`` by adding an ``.. automodule::`` statement that refers to your new
+module (again, following the existing pattern).
 
-MaterialsIO uses stevedore to simplify access to the parsers.
-After implementing and documenting the parser, add it to the ``entry_points`` section of the ``setup.py`` file for MaterialsIO.
-See `stevedore documentation for more information <https://docs.openstack.org/stevedore/latest/user/tutorial/creating_plugins.html#registering-the-plugins>`_.
+MaterialsIO uses ``stevedore`` to simplify access to the parsers. After implementing and
+documenting the parser, add it to the ``[tool.poetry.plugins."materialsio.parser"]`` section of the
+``pyproject.toml`` file for MaterialsIO. See
+`stevedore documentation for more information <https://docs.openstack.org/stevedore/latest/user/tutorial/creating_plugins.html#registering-the-plugins>`_
+(these docs reference ``setup.py``, but the equivalent can be done via plugins in ``pyproject
+.toml``; follow the existing structure if you're unsure, and ask for help from the developers if
+you run into issues).
 
 
 Alternative Route: Including Parsers from Other Libraries
 ---------------------------------------------------------
 
-If a parser would be better suited as part of a different library, you can still register it as a parser with MaterialsIO by altering your ``setup.py`` file.
-Add an entry point with the namespace ``"materialsio.parser"`` and point to the class object following the
+If a parser would be better suited as part of a different library, you can still register it as a
+parser with MaterialsIO by altering your ``pyproject.toml`` file. Add an entry point with the
+namespace ``"materialsio.parser"`` and point to the class object following the
 `stevedore documentation <https://docs.openstack.org/stevedore/latest/user/tutorial/creating_plugins.html#registering-the-plugins>`_.
-Adding the entry point will let MaterialsIO use your parser if your librart is installed in the same Python environment as MaterialsIO.
+Adding the entry point will let MaterialsIO use your parser if your library is installed in the
+same Python environment as MaterialsIO.
 
 .. todo:: Provide a public listing of materials_io-compatible software.
 
diff --git a/docs/source/goals.rst b/docs/source/goals.rst
index 7e1da38..89cacdd 100644
--- a/docs/source/goals.rst
+++ b/docs/source/goals.rst
@@ -1,18 +1,21 @@
 Project Goals
 =============
 
-The goal of MaterialsIO is to minimize the amount of code duplication between data-driven materials software codes.
-Many materials databases at present rely on custom software to extract information from scientific files and transform that data into a standardized format.
-Further, automation or analysis software requires extracting information from files.
-While the data needs of application vary, they all rely on similar algorithms to extract information from the same types of files.
-*MaterialsIO is designed to be a shared repository for these algorithms*.
-
-The core of MaterialsIO is a collection of "parsers" which each generate simplified, standardized data from a certain class of files.
-For example, the :class:`ElectronMicroscopyParser` produces structured data from file types specific to brands of electron microscopes.
-
-The parsers do not necessarily generate data in a format needed by any tool.
-Rather, the parsers are designed to produce *all* of the information needed by all projects that utilitize the libraries.
-In this way, the parsers can service every user without modification.
+The goal of MaterialsIO is to minimize the amount of code duplication between data-driven
+materials software codes. Many materials databases at present rely on custom software to extract
+information from scientific files and transform that data into a standardized format. Further,
+automation or analysis software requires extracting information from files. While the data
+needs of application vary, they all rely on similar algorithms to extract information from the
+same types of files. *MaterialsIO is designed to be a shared repository for these algorithms*.
+
+The core of MaterialsIO is a collection of "parsers" which each generate simplified, standardized
+data from a certain class of files. For example, the
+:class:`~materials_io.electron_microscopy.ElectronMicroscopyParser` produces structured data from
+file types specific to brands of electron microscopes.
+
+The parsers do not necessarily generate data in a format needed by any tool. Rather, the parsers
+are designed to produce *all* of the information needed by all projects that utilize the
+libraries. In this way, the parsers can service every user without modification.
 
 What Does MaterialsIO *Do*?
 ---------------------------
@@ -33,11 +36,14 @@ There are several questions that are specifically out-of-scope for MaterialsIO:
 1. *How do I get access to files that I want to parse?*
     MaterialsIO does not solve the data transfer problem
 2. *How can I parse large numbers of files reliably?*
-    MaterialsIO is not a distributed workflow engine, but is designed to integrate
-    with one for extracting metadata from large filesystems.
+    MaterialsIO is not a distributed workflow engine, but is designed to integrate with one
+    for extracting metadata from large filesystems.
 3. *How can I translate data into the schema needed for my application?*
-    The goal of MaterialsIO is to go from opaque to well-documented formats.
-    We recommend implementing separate "adapter" classes to transform MaterialsIO metadata to your specific requirements.
-
-See our `"how to use MaterialsIO" documentation <user-guide.html#integrating-materialsio-into-applications>`_ for more detail
-on how to integrate MaterialsIO into an application that provides these intentionally-missing features.
+    The goal of MaterialsIO is to go from opaque to well-documented formats. We recommend
+    implementing separate "adapter" classes to transform MaterialsIO metadata to your
+    specific requirements.
+
+See our
+`"how to use MaterialsIO" documentation <user-guide.html#integrating-materialsio-into-applications>`_
+for more detail on how to integrate MaterialsIO into an application that provides these
+intentionally-missing features.
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 473ffec..092fc31 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -1,10 +1,11 @@
 Welcome to MaterialsIO's documentation!
 =======================================
 
-MaterialsIO is a library of tools that generate summaries of the data contained in scientific data files.
-The goal of MaterialsIO is to provide a shared resources of these tool to avoid duplication of effort between the many emerging materials databases.
-Each parser is designed to generate the sum of all data needed by each of these databases with a uniform API so that specific projects can write simple adaptors for their needs.
-
+MaterialsIO is a library of tools that generate summaries of the data contained in scientific
+data files. The goal of MaterialsIO is to provide a shared resources of these tool to avoid
+duplication of effort between the many emerging materials databases. Each parser is designed to
+generate the sum of all data needed by each of these databases with a uniform API so that specific
+projects can write simple adaptors for their needs.
 
 Source Code: https://github.com/materials-data-facility/MaterialsIO
 
diff --git a/docs/source/parsers.rst b/docs/source/parsers.rst
index c1e40a8..903883d 100644
--- a/docs/source/parsers.rst
+++ b/docs/source/parsers.rst
@@ -26,12 +26,18 @@ Parsers that work for any kind of file
 Image Parsers
 -------------
 
-Parsers that read image data (e.g., electron microscopy, computed tomography)
+Parsers that read image data
 
 .. automodule:: materials_io.image
     :members:
     :exclude-members: implementors, schema, version, group
 
+Electron Microscopy Parsers
+---------------------------
+
+Parsers that read electron microscopy data of various sorts (images, spectra, spectrum images,
+etc.) using the `HyperSpy <https://hyperspy.org>`_ package.
+
 .. automodule:: materials_io.electron_microscopy
     :members:
     :exclude-members: implementors, schema, version, group
@@ -47,6 +53,7 @@ Parsers related to data files that encode atom-level structure
 
 .. automodule:: materials_io.ase
     :members:
+    :noindex:
     :exclude-members: implementors, schema, version, group
 
 Calculation Parsers
@@ -60,6 +67,7 @@ Parsers that retrieve results from calculations
 
 .. automodule:: materials_io.ase
     :members:
+    :noindex:
     :exclude-members: implementors, schema, version, group
 
 Structured Data Files
diff --git a/docs/source/user-guide.rst b/docs/source/user-guide.rst
index 1d3cb7f..17927b3 100644
--- a/docs/source/user-guide.rst
+++ b/docs/source/user-guide.rst
@@ -1,53 +1,86 @@
 User Guide
 ==========
 
-In this part of the guide, we show a simple example of using a MaterialsIO parser
-and discuss the full functionality of a parser.
+In this part of the guide, we show a simple example of using a MaterialsIO parser and discuss the
+full functionality of a parser.
+
+Installing MaterialsIO (for users)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Installing MaterialsIO should be as easy as a single ``pip`` command. Assuming you have a
+version of Python that is 3.8 or higher, running::
+
+    pip install git+https://github.com/materials-data-facility/MaterialsIO.git
+
+Should get the basics of MaterialsIO installed. By default however, only a small subset of
+parsers will be installed (this is done so you do not need to install all the dependencies of
+parsers you may never use). To install additional parsers, you can specify "extras" at install time
+using the ``[...]`` syntax for ``pip``. For example, if you want to install all the parsers
+bundled with MaterialsIO (and their dependencies), run::
+
+    pip install "git+https://github.com/materials-data-facility/MaterialsIO.git#egg=materials_io[all]"
+
+This will pull in many more packages, but also enable as many parsers as possible. Check the list
+under ``[tool.poetry.extras]`` in ``pyproject.toml`` to see all the options you can specify in
+the brackets of the ``pip install`` command.
+
+.. note:: In the *hopefully* near future, MaterialsIO should be published on
+    `PyPI <https://pypi.org>`_ (see
+    `this Github issue <https://github.com/materials-data-facility/MaterialsIO/issues/42>`_ for
+    updates), meaning install should be easier via a simple ``pip install materials_io`` or
+    ``pip install materials_io[all]``, rather than having to specify the Git URL as in the above
+    example
 
 Discovering a Parser
 ~~~~~~~~~~~~~~~~~~~~
 
-MaterialsIO uses `stevedore <https://docs.openstack.org/stevedore/latest/index.html>`_ to manage a collection of parsers,
-and has a utility function for listing available parsers::
+MaterialsIO uses `stevedore <https://docs.openstack.org/stevedore/latest/index.html>`_ to manage
+a collection of parsers, and has a utility function for listing available parsers::
 
     from materials_io.utils.interface import get_available_parsers
     print(get_available_parsers())
 
-This snippet will print a dictionary of parsers installed on your system.
-Both parsers that are part of the MaterialsIO base package and those defined by other packages
-will be included in this list.
+This snippet will print a dictionary of parsers installed on your system. Both parsers that are
+part of the MaterialsIO base package and those defined by other packages will be included in this
+list.
 
 Simple Interface
 ~~~~~~~~~~~~~~~~
 
-The methods in :mod:`materials_io.utils.interface` are useful for most applications.
-As an example, we illustrate the use of :class:`materials_io.generic.GenericFileParser`::
+The methods in :mod:`materials_io.utils.interface` are useful for most applications. As an
+example, we illustrate the use of :class:`materials_io.file.GenericFileParser`, which is
+available through the ``'generic'`` parser plugin::
 
     from materials_io.utils.interface import execute_parser
-    print(execute_parser('generic', ['setup.py']))
+    print(execute_parser('generic', ['pyproject.toml']))
 
 
-The above snippet creates the parser object and runs it on a file named ``setup.py``.
-Run in the root directory of the MaterialsIO, it would produce output similar to:
+The above snippet creates the parser object and runs it on a file named ``pyproject.toml``. Run
+in the root directory of the MaterialsIO, it would produce output similar to the following,
+likely with a different ``sha512`` value if the contents of that file have changed since this
+documentation was written:
 
 .. code:: json
 
     [{
-        "mime_type": "text/x-python",
-        "length": 623,
-        "filename": "setup.py",
-        "hash": "[...]"
+        "data_type": "ASCII text",
+        "filename": "pyproject.toml",
+        "length": 2421,
+        "mime_type": "text/plain",
+        "path": "pyproject.toml",
+        "sha512": "a7eb382c4a3e6cf469656453f9ff2e3c1ac2c02c9c2ba31c3d569a09883e2b2471801c39125dafb7c13bfcaf9cf6afbab92afa4c053c0c93a4c8c59acad1b85b"
     }]
 
-The other pre-built parsing function provides the ability to run all parsers on all files in a directory::
+The other pre-built parsing function provides the ability to run all parsers on all files in a
+directory::
 
     from materials_io.utils.interface import run_all_parsers
     gen = run_all_parsers('.')
     for record in gen:
         print(record)
 
-A third route for using ``materials_io`` is to employ the ``get_parser`` operation to access a specific
-parser, and then use its class interface (described below)::
+A third route for using ``materials_io`` is to employ the ``get_parser`` operation to access a
+specific parser, and then use its class interface (described below)::
 
     from materials_io.utils.interface import get_parser
     parser = get_parser('generic')
@@ -59,15 +92,16 @@ parser, and then use its class interface (described below)::
 Advanced Usage: Adding Context
 ++++++++++++++++++++++++++++++
 
-The function interface for MaterialsIO supports using "context" and "adapters" to provide additional infomration
-to a parser or change the output format, respectively.
-Adapters are described in `Integrating MaterialsIO into Applications <#id1>`_.
-Here, we describe the purpose of context and how to use it in our interface.
+The function interface for MaterialsIO supports using "context" and "adapters" to provide
+additional infomration to a parser or change the output format, respectively. Adapters are
+described in `Integrating MaterialsIO into Applications <#id1>`_. Here, we describe the purpose
+of context and how to use it in our interface.
 
-Context is information about the data held in a file that is not contained within the file itself.
-Examples include human-friendly descriptions of columns names or which values actually
-represent a missing measurement in tabular data file (e.g., CSV files).
-A limited number of parsers support context and this information can be provided via the ``execute_parser`` function::
+Context is information about the data held in a file that is not contained within the file itself
+. Examples include human-friendly descriptions of columns names or which values actually
+represent a missing measurement in tabular data file (e.g., CSV files). A limited number of
+parsers support context and this information can be provided via the ``execute_parser``
+function::
 
     execute_parser('csv', 'tests/data/test.csv', context={'na_values': ['N/A']})
 
@@ -75,10 +109,10 @@ A limited number of parsers support context and this information can be provided
 The types of context information used by a parser, if any, is described in the
 `documentation for each parser <parsers.html>`_.
 
-The ``run_all_parsers`` function has several options for providing context to the parsers.
-These options include specifying "global context" to be passed to every parser or adapter
-and ways of limiting the metadata to specific parsers.
-See :meth:`materials_io.utils.interface.run_all_parsers` for further details on the
+The ``run_all_parsers_on_directory`` function has several options for providing context to the
+parsers. These options include specifying "global context" to be passed to every parser or
+adapter and ways of limiting the metadata to specific parsers. See
+:meth:`materials_io.utils.interface.run_all_parsers_on_directory` for further details on the
 syntax for this command.
 
 .. note::
@@ -89,38 +123,40 @@ syntax for this command.
 Class Interface
 ~~~~~~~~~~~~~~~
 
-The class API of parsers provide access to more detailed features of individual parsers.
-The functionality of a parser is broken into several simple operations.
+The class API of parsers provide access to more detailed features of individual parsers. The
+functionality of a parser is broken into several simple operations.
 
 Initializing a Parser
 +++++++++++++++++++++
 
-The first step to using a Parser is to initialize it.
-Most parsers do not have any options for the initializer, so you can create them with::
+The first step to using a Parser is to initialize it. Most parsers do not have any options for
+the initializer, so you can create them with::
 
     parser = Parser()
 
-Some parsers require configuration options that define how the parser runs,
-such as the location of a non-Python executable.
+Some parsers require configuration options that define how the parser runs, such as the location
+of a non-Python executable.
 
 Parsing Method
 ++++++++++++++
 
 The main operation for any parser is the data extraction operation: ``parse``.
 
-In most cases, the ``parse`` operation takes the path to a file and
-and returns a summary of the data the file holds::
+In most cases, the ``parse`` operation takes the path to a file and and returns a summary of the
+data the file holds::
 
     metadata = parser.parse(['/my/file'])
 
-Some parsers take multiple files that describe the same object (e.g., the input and output files of a simulation)
-and use them to generate a single metadata record::
+Some parsers take multiple files that describe the same object (e.g., the input and output files
+of a simulation) and use them to generate a single metadata record::
 
     metadata = parser.parse(['/my/file.in', '/my/file.out'])
 
-The `grouping method <#grouping-files>`_ for these parsers provides logic to identify groups of related files.
+The `grouping method <#grouping-files>`_ for these parsers provides logic to identify groups of
+related files.
 
-Some parsers also can use information that is not contained within the file themselves, which can be provided to the parser as a "context"::
+Some parsers also can use information that is not contained within the file themselves, which can
+be provided to the parser as a "context"::
 
     metadata = parser.parse(['/my/file1'], context={'headers': {'temp': 'temperature'}})
 
@@ -142,15 +178,16 @@ Parsing Entire Directories
 
     metadata = list(parser.parse_directory('.'))
 
-``parse_directory`` is a generator function, so we use ``list`` here to turn the output into a list format.
+``parse_directory`` is a generator function, so we use ``list`` here to turn the output into a list
+format.
 
 Attribution Functions
 +++++++++++++++++++++
 
-Two functions, ``citations`` and ``implementors``, are available to determine who contirbuted a parser.
-``implementors`` returns the list of people who created a parser, who are likely the points-of-contact for support.
-``citations`` indicates if any publications are available that describe the underlying methods and should be reference
-in scientific articles.
+Two functions, ``citations`` and ``implementors``, are available to determine who contirbuted a
+parser. ``implementors`` returns the list of people who created a parser, who are likely the
+points-of-contact for support. ``citations`` indicates if any publications are available that
+describe the underlying methods and should be reference in scientific articles.
 
 Full Parser API
 +++++++++++++++
@@ -164,10 +201,9 @@ The full API for the parsers are described as a Python abstract class:
 Integrating MaterialsIO into Applications
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-MaterialsIO is designed to create a documented, JSON-format version of scientific files,
-but these files might not yet be in a form useful for your application.
-We recommend an "adapter" approach to post-process these "generic JSON" files that
-can actually be used for your application.
+MaterialsIO is designed to create a documented, JSON-format version of scientific files, but
+these files might not yet be in a form useful for your application. We recommend an "adapter"
+approach to post-process these "generic JSON" files that can actually be used for your application.
 
 BaseAdapter
 +++++++++++
@@ -179,29 +215,27 @@ The ``BaseAdapter`` class defines the interface for all adapters.
     :noindex:
     :members:
 
-Adapters must fulfill a single operation, ``transform``, which renders metadata from one of
-the MaterialsIO parsers into a new form.
-There are no restrictions on the output for this function, except that ``None`` indicates
-that there is no valid transformation for an object.
+Adapters must fulfill a single operation, ``transform``, which renders metadata from one of the
+MaterialsIO parsers into a new form. There are no restrictions on the output for this function,
+except that ``None`` indicates that there is no valid transformation for an object.
 
-The ``check_compatibility`` and ``version`` method provide a route for marking which versions
-of a parser are compatible with an adapter.
-``materials_io`` uses the version in utility operations to provide warnings to users
-about when an adapter is out-of-date.
+The ``check_compatibility`` and ``version`` method provide a route for marking which versions of
+a parser are compatible with an adapter. ``materials_io`` uses the version in utility operations
+to provide warnings to users about when an adapter is out-of-date.
 
 Using Adapters
 ++++++++++++++
 
-The same utility operations `described above <#simple-interface>`_ support using adapters.
-The ``execute_parser`` function has an argument, ``adapter``, that takes the name of the adapter
-as an input and causes the parsing operation to run the adapter after parsing.
-The ``run_all_parsers`` function also has arguments (e.g., ``adapter_map``) that associate
-each parser with the adapter needed to run after parsing.
+The same utility operations `described above <#simple-interface>`_ support using adapters. The
+``execute_parser`` function has an argument, ``adapter``, that takes the name of the adapter as
+an input and causes the parsing operation to run the adapter after parsing. The
+``run_all_parsers`` function also has arguments (e.g., ``adapter_map``) that associate each
+parser with the adapter needed to run after parsing.
 
 As an example, we will demonstrate an adapter that comes packaged with MaterialsIO:
 :class:`materials_io.adapters.base.SerializeAdapter`
-The serialize adapter is registered using ``stevedore`` as the name "serialize".
-To use it after all parsers::
+The serialize adapter is registered using ``stevedore`` as the name "serialize". To use it after
+all parsers::
 
     from materials_io.utils.interface import run_all_parsers
     gen = run_all_parsers('.', default_adapter='serialize')
@@ -209,19 +243,22 @@ To use it after all parsers::
 Implementing Adapters
 +++++++++++++++++++++
 
-Any new adapters must inherit from the ``BaseAdapter`` class defined above.
-You only need implement the ``transform`` operation.
+Any new adapters must inherit from the ``BaseAdapter`` class defined above. You only need
+implement the ``transform`` operation.
 
-Once the adapter is implemented, you need to put it in a project that is installable via pip.
-See [python docs](https://docs.python.org/3.7/distutils/setupscript.html) for a detailed tutorial
-or copy the structure used by the `MDF's adapter library <https://github.com/materials-data-facility/mdf-materialsio-adapters>`_.
+Once the adapter is implemented, you need to put it in a project that is installable via pip. See
+[python docs](https://docs.python.org/3.7/distutils/setupscript.html) for a detailed tutorial or
+copy the structure used by the
+`MDF's adapter library <https://github.com/materials-data-facility/mdf-materialsio-adapters>`_.
 
-Then, register the adapter with stevedore by adding it as an entry point in your project's ``setup.py`` file.
-See `stevedore documentation for more detail <https://docs.openstack.org/stevedore/latest/user/tutorial/creating_plugins.html#registering-the-plugins>`_.
-We recommned using the same name for a adapter as the parser it is designed for
-so that ``materials_io`` can auto-detect the adapters associated with each parser.
+Then, register the adapter with ``stevedore`` by adding it as an entry point in your project's
+``setup.py`` or ``pyproject.toml`` file. See the
+`stevedore documentation for more detail <https://docs.openstack.org/stevedore/latest/user/tutorial/creating_plugins.html#registering-the-plugins>`_.
+We recommend using the same name for a adapter as the parser it is designed for so that
+``materials_io`` can auto-detect the adapters associated with each parser.
 
 Examples of Tools Using MaterialsIO
 +++++++++++++++++++++++++++++++++++
 
-Materials Data Facility: https://github.com/materials-data-facility/mdf-materialsio-adapters
+Materials Data Facility:
+https://github.com/materials-data-facility/mdf-materialsio-adapters
diff --git a/materials_io/adapters/base.py b/materials_io/adapters/base.py
index 980e1c0..085920a 100644
--- a/materials_io/adapters/base.py
+++ b/materials_io/adapters/base.py
@@ -1,8 +1,10 @@
 """Base classes for adapters"""
 
+import json
 from abc import abstractmethod
 from typing import Any, Union
-import json
+
+import numpy as np
 
 from materials_io.base import BaseParser
 
@@ -62,3 +64,30 @@ class SerializeAdapter(BaseAdapter):
 
     def transform(self, metadata: dict, context=None) -> str:
         return json.dumps(metadata)
+
+
+class GreedySerializeAdapter(BaseAdapter):
+    """Converts the metadata to a string by serializing with JSON, making some (hopefully) informed
+    choices about what to do with various types commonly seen, and otherwise reporting that the
+    data type could not be serialized. May not work in all situations, but should cover a large
+    number of cases."""
+    @staticmethod
+    def default(o):
+        success = False
+        if isinstance(o, np.void):
+            return None
+        elif isinstance(o, (np.ndarray, np.generic)):
+            return o.tolist()
+        elif isinstance(o, bytes):
+            try:
+                return o.decode()
+            except UnicodeDecodeError:
+                pass
+
+        if not success:
+            type_name = o.__class__.__name__
+            return f"<<Unserializable type: {type_name}>>"
+
+    def transform(self, metadata: dict, context=None) -> str:
+        s = json.dumps(metadata, default=GreedySerializeAdapter.default)
+        return s
diff --git a/materials_io/base.py b/materials_io/base.py
index c710bcb..9a827e5 100644
--- a/materials_io/base.py
+++ b/materials_io/base.py
@@ -11,22 +11,20 @@
 class BaseParser(ABC):
     """Abstract base class for a file parser
 
-    This class defines the interface for all parsers in MaterialsIO.
-    Each new parser must implement the :meth:`parse`, :meth:`version`,
-    and :meth:`implementors` functions.
-    The :meth:`group` method should be overrode to generate smart groups of file (e.g., associating
-    the inputs and outputs to the same calculation)
-    :meth:`citations` can be used if there are papers that should be cited if the parser is used
-    as part of a scientific publication.
-
-    See `MaterialsIO Contributor Guide <contributor-guide.html>`_ for further details.
+    This class defines the interface for all parsers in MaterialsIO. Each new parser must
+    implement the :meth:`parse`, :meth:`version`, and :meth:`implementors` functions. The
+    :meth:`group` method should be overridden to generate smart groups of file (e.g., associating
+    the inputs and outputs to the same calculation) :meth:`citations` can be used if there
+    are papers that should be cited if the parser is used as part of a scientific publication.
+
+    See the `MaterialsIO Contributor Guide <contributor-guide.html>`_ for further details.
     """
 
-    def identify_files(self, path: str, context: dict = None) -> Iterator[Tuple[str]]:
+    def identify_files(self, path: str, context: dict = None) -> \
+            Iterator[Tuple[str]]:
         """Identify all groups of files likely to be compatible with this parser
 
-        Uses the :meth:`group` function to determine groups of files
-        that should be parsed together.
+        Uses the :meth:`group` function to determine groups of files that should be parsed together.
 
         Args:
             path (str): Root of directory to parser
@@ -45,7 +43,8 @@ def identify_files(self, path: str, context: dict = None) -> Iterator[Tuple[str]
             for group in self.group(files, dirs, context):
                 yield group
 
-    def parse_directory(self, path: str, context: dict = None) -> Iterator[Tuple[Tuple[str], dict]]:
+    def parse_directory(self, path: str, context: dict = None) -> \
+            Iterator[Tuple[Tuple[str], dict]]:
         """Run a parser on all appropriate files in a directory
 
         Skips files that throw exceptions while parsing
@@ -73,7 +72,7 @@ def parse(self, group: Iterable[str], context: dict = None) -> dict:
         be used together to create s single summary record.
 
         Arguments:
-            group (list of str):  A list of one or more files that should be parsed together
+            group ([str]):  A list of one or more files that should be parsed together
             context (dict): Context about the files
 
         Returns:
@@ -86,8 +85,8 @@ def group(self, files: Union[str, List[str]], directories: List[str] = None,
 
         Will create groups using only the files and directories included as input.
 
-        The files of files are _all_ files that could be read by this parser,
-        which may include many false positives.
+        The files of files are _all_ files that could be read by this parser, which may include
+        many false positives.
 
         Args:
             files (str or [str]): List of files to consider grouping
diff --git a/materials_io/csv.py b/materials_io/csv.py
index 5ac28b1..189ee28 100644
--- a/materials_io/csv.py
+++ b/materials_io/csv.py
@@ -12,7 +12,7 @@ class CSVParser(BaseSingleFileParser):
 
     The context dictionary for the CSV parser includes several fields:
         - ``schema``: Dictionary defining the schema for this dataset, following that of
-        FrictionlessIO
+          FrictionlessIO
         - ``na_values``: Any values that should be interpreted as missing
 
     """
@@ -23,8 +23,7 @@ def __init__(self, return_records=True, **kwargs):
              return_records (bool): Whether to return each row in the CSV file
         Keyword:
             All kwargs as passed to
-            `TableSchema's infer <https://github.com/frictionlessdata/tableschema-py#infer>`_
-            method
+            `TableSchema's infer <https://github.com/frictionlessdata/tableschema-py#infer>`_ method
         """
         self.return_records = return_records
         self.infer_kwargs = kwargs
diff --git a/materials_io/dft.py b/materials_io/dft.py
index de32295..11638b4 100644
--- a/materials_io/dft.py
+++ b/materials_io/dft.py
@@ -8,9 +8,8 @@
 
 
 # List of files that are known to the VASP parser
-_vasp_file_names = ["outcar", "incar", "chgcar", "wavecar", "wavcar",
-                    "oszicar", "ibzcar", "kpoints", "doscar", "poscar",
-                    "contcar", "vasp_run.xml", "xdatcar"]
+_vasp_file_names = ["outcar", "incar", "chgcar", "wavecar", "wavcar", "oszicar", "ibzcar",
+                    "kpoints", "doscar", "poscar", "contcar", "vasp_run.xml", "xdatcar"]
 
 
 class DFTParser(BaseParser):
@@ -44,14 +43,14 @@ def group(self, files: Union[str, List[str]], directories: List[str] = None,
     def _group_vasp(self, files: Iterable[str]) -> Iterable[Tuple[str, ...]]:
         """Find groupings of files associated with VASP calculations
 
-        Finds files that start with the name "OUTCAR" (not case sensitive) and groups
-        those files together with any file that share the same postfix
-        (e.g., "OUTCAR.1" and "INCAR.1" are grouped together)
+        Find files that start with the name "OUTCAR" (not case sensitive) and groups those files
+        together with any file that share the same postfix (e.g., "OUTCAR.1" and "INCAR.1" are
+        grouped together)
 
         Args:
             files ([str]): List of files to be grouped
         Yields:
-            ((files]): List of VASP files from the same calculation
+            ((files)): List of VASP files from the same calculation
         """
 
         for group in group_by_postfix(files, _vasp_file_names):
diff --git a/materials_io/electron_microscopy.py b/materials_io/electron_microscopy.py
index 1d3b5a7..6501f94 100644
--- a/materials_io/electron_microscopy.py
+++ b/materials_io/electron_microscopy.py
@@ -1,5 +1,7 @@
 import logging
 import re
+import json
+import pathlib
 from typing import Tuple, Dict, Optional
 
 from hyperspy.io import load as hs_load
@@ -15,20 +17,19 @@
 
 
 class ElectronMicroscopyParser(BaseSingleFileParser):
-    """Parse metadata specific to electron microscopy, meaning any file
-    supported by HyperSpy's I/O capabilities. Extract both the metadata
-    interpreted by HyperSpy directly, but also any important values we can
-    pick out manually.
-
-    For each value (if known), return the subdict:
-      {
-        "value": numeric/str value,
-        "unit": unit name from http://qudt.org/vocab/unit/ (see 
-                http://www.qudt.org/doc/DOC_VOCAB-UNITS.html for details)
-      }
-    
-    The allowed metadata values are controlled by the
-    ../schemas/electron_microscopy.json JSONSchema specification
+    """Parse metadata specific to electron microscopy.
+
+    This parser handles any file supported by HyperSpy's I/O capabilities. Extract both the
+    metadata interpreted by HyperSpy directly, but also any important values we can pick out
+    manually.
+
+    For each value (if it is known), return a subdict with two keys: ``value``, containing the
+    actual value of the metadata parameter, and ``unit``, a string containing a unit name from the
+    `QUDT <http://www.qudt.org/doc/DOC_VOCAB-UNITS.html>`_ vocabulary. Including a ``unit`` is
+    optional, but highly recommended, if it is known.
+
+    The allowed metadata values are controlled by the JSONSchema specification in the
+    ``schemas/electron_microscopy.json`` file.
     """
 
     def _parse_file(self, file_path: str, context: Dict = None) -> Dict:
@@ -81,16 +82,15 @@ def _process_hs_data(self) -> None:
             self.inst = 'None'
 
         # HS data
-        self.inst_data = get_val(self.meta, ('Acquisition_instrument',
-                                             self.inst))
+        self.inst_data = get_val(self.meta, ('Acquisition_instrument', self.inst))
         if self.inst_data is not None:
             source = self.inst_data
             dest = self.em
+
             mapping = [
                 MappingElements(
                     source_dict=source, source_path='acquisition_mode',
-                    dest_dict=dest, dest_path=('General_EM',
-                                               'acquisition_mode'),
+                    dest_dict=dest, dest_path=('General_EM', 'acquisition_mode'),
                     cast_fn=str, units=None, conv_fn=None, override=False),
                 MappingElements(
                     source_dict=source, source_path='beam_current',
@@ -103,16 +103,9 @@ def _process_hs_data(self) -> None:
                     override=False),
                 MappingElements(
                     source_dict=source, source_path='convergence_angle',
-                    dest_dict=dest, dest_path=('General_EM',
-                                               'convergence_angle'),
+                    dest_dict=dest, dest_path=('General_EM', 'convergence_angle'),
                     cast_fn=float, units='MilliRAD', conv_fn=None,
                     override=False),
-                MappingElements(
-                    source_dict=source, source_path='magnification',
-                    dest_dict=dest, dest_path=('General_EM',
-                                               'magnification_indicated'),
-                    cast_fn=float, units='UNITLESS', conv_fn=None,
-                    override=False),
                 MappingElements(
                     source_dict=source, source_path='microscope',
                     dest_dict=dest, dest_path=('General_EM', 'microscope_name'),
@@ -125,41 +118,29 @@ def _process_hs_data(self) -> None:
 
                 # stage positions
                 MappingElements(
-                    source_dict=source,
-                    source_path=('Stage', 'rotation'),
-                    dest_dict=dest,
+                    source_dict=source, source_path=('Stage', 'rotation'), dest_dict=dest,
                     dest_path=('General_EM', 'stage_position', 'rotation'),
                     cast_fn=float, units='DEG', conv_fn=None, override=False),
                 MappingElements(
-                    source_dict=source,
-                    source_path=('Stage', 'tilt_alpha'),
-                    dest_dict=dest,
+                    source_dict=source, source_path=('Stage', 'tilt_alpha'), dest_dict=dest,
                     dest_path=('General_EM', 'stage_position', 'tilt_alpha'),
                     cast_fn=float, units='DEG', conv_fn=None, override=False),
                 MappingElements(
-                    source_dict=source,
-                    source_path=('Stage', 'tilt_beta'),
-                    dest_dict=dest,
+                    source_dict=source, source_path=('Stage', 'tilt_beta'), dest_dict=dest,
                     dest_path=('General_EM', 'stage_position', 'tilt_beta'),
                     cast_fn=float, units='DEG', conv_fn=None, override=False),
                 MappingElements(
-                    source_dict=source,
-                    dest_dict=dest,
-                    source_path=('Stage', 'x'),
+                    source_dict=source, dest_dict=dest, source_path=('Stage', 'x'),
                     dest_path=('General_EM', 'stage_position', 'x'),
                     cast_fn=float, units='MilliM', conv_fn=None,
                     override=False),
                 MappingElements(
-                    source_dict=source,
-                    source_path=('Stage', 'y'),
-                    dest_dict=dest,
+                    source_dict=source, source_path=('Stage', 'y'), dest_dict=dest,
                     dest_path=('General_EM', 'stage_position', 'y'),
                     cast_fn=float, units='MilliM', conv_fn=None,
                     override=False),
                 MappingElements(
-                    source_dict=source,
-                    source_path=('Stage', 'z'),
-                    dest_dict=dest,
+                    source_dict=source, source_path=('Stage', 'z'), dest_dict=dest,
                     dest_path=('General_EM', 'stage_position', 'z'),
                     cast_fn=float, units='MilliM', conv_fn=None,
                     override=False),
@@ -176,6 +157,24 @@ def _process_hs_data(self) -> None:
                     cast_fn=float, units='MilliM', conv_fn=None,
                     override=False)]
 
+            # some logic to parse how Zeiss stores floats in their SEM tifs:
+            mag = get_val(source, path='magnification')
+            if mag and isinstance(mag, str):
+                if ' K X' in mag:
+                    mag = mag.replace(' K X', '')
+                    try:
+                        mag = float(mag)
+                        mag *= 1000
+                    except ValueError:
+                        # don't do anything if we can't coerce the value to a float
+                        pass
+
+            mapping += [MappingElements(
+                source_dict={'magnification': mag}, source_path='magnification',
+                dest_dict=dest, dest_path=('General_EM', 'magnification_indicated'),
+                cast_fn=float, units='UNITLESS', conv_fn=None,
+                override=False)]
+
             map_dict_values(mapping)
 
             self._process_hs_detectors()
@@ -185,20 +184,17 @@ def _process_hs_data(self) -> None:
         mapping = [
             # Elements present (if known)
             MappingElements(
-                source_dict=source, dest_dict=dest,
-                source_path=('Sample', 'elements'),
+                source_dict=source, dest_dict=dest, source_path=('Sample', 'elements'),
                 dest_path=('General_EM', 'elements'),
                 cast_fn=list, units=None, conv_fn=None, override=False),
             # General metadata
             MappingElements(
                 source_dict=source, dest_dict=dest,
-                source_path=('General', 'date'),
-                dest_path=('General', 'date'),
+                source_path=('General', 'date'), dest_path=('General', 'date'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
                 source_dict=source, dest_dict=dest,
-                source_path=('General', 'doi'),
-                dest_path=('General', 'doi'),
+                source_path=('General', 'doi'), dest_path=('General', 'doi'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
                 source_dict=source, dest_dict=dest,
@@ -207,32 +203,28 @@ def _process_hs_data(self) -> None:
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
                 source_dict=source, dest_dict=dest,
-                source_path=('General', 'notes'),
-                dest_path=('General', 'notes'),
+                source_path=('General', 'notes'), dest_path=('General', 'notes'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
                 source_dict=source, dest_dict=dest,
-                source_path=('General', 'time'),
-                dest_path=('General', 'time'),
+                source_path=('General', 'time'), dest_path=('General', 'time'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
                 source_dict=source, dest_dict=dest,
-                source_path=('General', 'time_zone'),
-                dest_path=('General', 'time_zone'),
+                source_path=('General', 'time_zone'), dest_path=('General', 'time_zone'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
                 source_dict=source, dest_dict=dest,
-                source_path=('General', 'title'),
-                dest_path=('General', 'title'),
+                source_path=('General', 'title'), dest_path=('General', 'title'),
                 cast_fn=str, units=None, conv_fn=None, override=False)]
 
         map_dict_values(mapping)
         self._process_hs_axes()
 
     def _process_hs_axes(self) -> None:
-        """Parses the HyperSpy signal axis calibrations into a format that can
-        be stored with the metadata. Make sure to remove "Undefined" traits
-        from any axis values, since that value cannot be serialized to JSON
+        """Parses the HyperSpy signal axis calibrations into a format that can be stored with the
+        metadata. Make sure to remove "Undefined" traits from any axis values, since that value
+        cannot be serialized to JSON
         """
         axes = self.hs_data.axes_manager.as_dictionary()
 
@@ -252,14 +244,12 @@ def _process_hs_axes(self) -> None:
                 axes[k]['units'] = standardize_unit(axes[k]['units'])
 
         self.em['General']['axis_calibration'] = axes
-        self.em['General']['data_dimensions'] = \
-            [v['size'] for v in
-             self.hs_data.axes_manager.as_dictionary().values()]
+        self.em['General']['data_dimensions'] = [v['size'] for v in
+                                                 self.hs_data.axes_manager.as_dictionary().values()]
 
     def _process_hs_detectors(self) -> None:
-        """Parses HyperSpy-formatted metadata specific to detectors as
-        specified by http://hyperspy.org/hyperspy-doc/current/user_guide
-        /metadata_structure.html
+        """Parses HyperSpy-formatted metadata specific to detectors as specified by
+        http://hyperspy.org/hyperspy-doc/current/user_guide/metadata_structure.html
         """
         detector_node = get_val(self.inst_data, 'Detector')
         dest_dict = self.em
@@ -275,20 +265,16 @@ def _process_hs_detectors(self) -> None:
             mapping += [
                 # EDS
                 MappingElements(
-                    source_dict=detector_node,
-                    source_path=('EDS', 'azimuth_angle'),
+                    source_dict=detector_node, source_path=('EDS', 'azimuth_angle'),
                     dest_dict=dest_dict, dest_path=('EDS', 'azimuth_angle'),
                     cast_fn=float, units='DEG', conv_fn=None, override=False),
                 MappingElements(
-                    source_dict=detector_node,
-                    source_path=('EDS', 'elevation_angle'),
+                    source_dict=detector_node, source_path=('EDS', 'elevation_angle'),
                     dest_dict=dest_dict, dest_path=('EDS', 'elevation_angle'),
                     cast_fn=float, units='DEG', conv_fn=None, override=False),
                 MappingElements(
-                    source_dict=detector_node,
-                    source_path=('EDS', 'energy_resolution_MnKa'),
-                    dest_dict=dest_dict,
-                    dest_path=('EDS', 'energy_resolution_MnKa'),
+                    source_dict=detector_node, source_path=('EDS', 'energy_resolution_MnKa'),
+                    dest_dict=dest_dict, dest_path=('EDS', 'energy_resolution_MnKa'),
                     cast_fn=float, units='EV', conv_fn=None, override=False),
                 MappingElements(
                     source_dict=detector_node, source_path=('EDS', 'live_time'),
@@ -301,39 +287,30 @@ def _process_hs_detectors(self) -> None:
 
                 # EELS
                 MappingElements(
-                    source_dict=detector_node,
-                    source_path=('EELS', 'aperture_size'),
+                    source_dict=detector_node, source_path=('EELS', 'aperture_size'),
                     dest_dict=dest_dict, dest_path=('EELS', 'aperture_size'),
                     cast_fn=float, units='MilliM', conv_fn=None,
                     override=False),
                 MappingElements(
-                    source_dict=detector_node,
-                    source_path=('EELS', 'collection_angle'),
+                    source_dict=detector_node, source_path=('EELS', 'collection_angle'),
                     dest_dict=dest_dict, dest_path=('EELS', 'collection_angle'),
                     cast_fn=float, units='MilliRAD', conv_fn=None,
                     override=False),
                 MappingElements(
-                    source_dict=detector_node,
-                    source_path=('EELS', 'dwell_time'),
+                    source_dict=detector_node, source_path=('EELS', 'dwell_time'),
                     dest_dict=dest_dict, dest_path=('General_EM', 'dwell_time'),
                     cast_fn=float, units='SEC', conv_fn=None, override=False),
                 MappingElements(
-                    source_dict=detector_node,
-                    source_path=('EELS', 'exposure'),
-                    dest_dict=dest_dict,
-                    dest_path=('General_EM', 'exposure_time'),
+                    source_dict=detector_node, source_path=('EELS', 'exposure'),
+                    dest_dict=dest_dict, dest_path=('General_EM', 'exposure_time'),
                     cast_fn=float, units='SEC', conv_fn=None, override=False),
                 MappingElements(
-                    source_dict=detector_node,
-                    source_path=('EELS', 'frame_number'),
-                    dest_dict=dest_dict,
-                    dest_path=('EELS', 'number_of_samples'),
+                    source_dict=detector_node, source_path=('EELS', 'frame_number'),
+                    dest_dict=dest_dict, dest_path=('EELS', 'number_of_samples'),
                     cast_fn=int, units='NUM', conv_fn=None, override=False),
                 MappingElements(
-                    source_dict=detector_node,
-                    source_path=('EELS', 'spectrometer'),
-                    dest_dict=dest_dict,
-                    dest_path=('EELS', 'spectrometer_name'),
+                    source_dict=detector_node, source_path=('EELS', 'spectrometer'),
+                    dest_dict=dest_dict, dest_path=('EELS', 'spectrometer_name'),
                     cast_fn=str, units=None, conv_fn=None, override=False),
             ]
         map_dict_values(mapping)
@@ -345,88 +322,60 @@ def _dm3_general_info(self) -> None:
         dest_dict = self.em
         mapping = [
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Indicated Magnification',),
-                dest_dict=dest_dict,
-                dest_path=('General_EM', 'magnification_indicated'),
+                source_dict=self.raw_meta, source_path=base + ('Indicated Magnification',),
+                dest_dict=dest_dict, dest_path=('General_EM', 'magnification_indicated'),
                 cast_fn=float, units='UNITLESS', conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Actual Magnification',),
-                dest_dict=dest_dict,
-                dest_path=('General_EM', 'magnification_actual'),
+                source_dict=self.raw_meta, source_path=base + ('Actual Magnification',),
+                dest_dict=dest_dict, dest_path=('General_EM', 'magnification_actual'),
                 cast_fn=float, units='UNITLESS', conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Cs(mm)',),
-                dest_dict=dest_dict,
-                dest_path=('TEM', 'spherical_aberration_coefficient'),
+                source_dict=self.raw_meta, source_path=base + ('Cs(mm)',),
+                dest_dict=dest_dict, dest_path=('TEM', 'spherical_aberration_coefficient'),
                 cast_fn=float, units='MilliM', conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('STEM Camera Length',),
-                dest_dict=dest_dict,
-                dest_path=('TEM', 'camera_length'),
+                source_dict=self.raw_meta, source_path=base + ('STEM Camera Length',),
+                dest_dict=dest_dict, dest_path=('TEM', 'camera_length'),
                 cast_fn=float, units='MilliM', conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Operation Mode',),
+                source_dict=self.raw_meta, source_path=base + ('Operation Mode',),
                 dest_dict=dest_dict, dest_path=('TEM', 'operation_mode'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Imaging Mode',),
+                source_dict=self.raw_meta, source_path=base + ('Imaging Mode',),
                 dest_dict=dest_dict, dest_path=('TEM', 'imaging_mode'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Illumination Mode',),
+                source_dict=self.raw_meta, source_path=base + ('Illumination Mode',),
                 dest_dict=dest_dict, dest_path=('TEM', 'illumination_mode'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Microscope',),
-                dest_dict=dest_dict,
-                dest_path=('General_EM', 'microscope_name'),
+                source_dict=self.raw_meta, source_path=base + ('Microscope',),
+                dest_dict=dest_dict, dest_path=('General_EM', 'microscope_name'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Stage Position', 'Stage X'),
-                dest_dict=dest_dict,
-                dest_path=('General_EM', 'stage_position', 'x'),
-                cast_fn=float, units='MilliM', conv_fn=lambda x: x/1000,
-                override=False),
+                source_dict=self.raw_meta, source_path=base + ('Stage Position', 'Stage X'),
+                dest_dict=dest_dict, dest_path=('General_EM', 'stage_position', 'x'),
+                cast_fn=float, units='MilliM', conv_fn=lambda x: x/1000, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Stage Position', 'Stage Y'),
-                dest_dict=dest_dict,
-                dest_path=('General_EM', 'stage_position', 'y'),
-                cast_fn=float, units='MilliM', conv_fn=lambda x: x / 1000,
-                override=False),
+                source_dict=self.raw_meta, source_path=base + ('Stage Position', 'Stage Y'),
+                dest_dict=dest_dict, dest_path=('General_EM', 'stage_position', 'y'),
+                cast_fn=float, units='MilliM', conv_fn=lambda x: x / 1000, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Stage Position', 'Stage Z'),
-                dest_dict=dest_dict,
-                dest_path=('General_EM', 'stage_position', 'z'),
-                cast_fn=float, units='MilliM', conv_fn=lambda x: x / 1000,
-                override=False),
+                source_dict=self.raw_meta, source_path=base + ('Stage Position', 'Stage Z'),
+                dest_dict=dest_dict, dest_path=('General_EM', 'stage_position', 'z'),
+                cast_fn=float, units='MilliM', conv_fn=lambda x: x / 1000, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Stage Position', 'Stage Alpha'),
-                dest_dict=dest_dict,
-                dest_path=('General_EM', 'stage_position', 'tilt_alpha'),
+                source_dict=self.raw_meta, source_path=base + ('Stage Position', 'Stage Alpha'),
+                dest_dict=dest_dict, dest_path=('General_EM', 'stage_position', 'tilt_alpha'),
                 cast_fn=float, units='DEG', conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Stage Position', 'Stage Beta'),
-                dest_dict=dest_dict,
-                dest_path=('General_EM', 'stage_position', 'tilt_beta'),
+                source_dict=self.raw_meta, source_path=base + ('Stage Position', 'Stage Beta'),
+                dest_dict=dest_dict, dest_path=('General_EM', 'stage_position', 'tilt_beta'),
                 cast_fn=float, units='DEG', conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Emission Current (µA)',),
-                dest_dict=dest_dict,
-                dest_path=('General_EM', 'emission_current'),
+                source_dict=self.raw_meta, source_path=base + ('Emission Current (µA)',),
+                dest_dict=dest_dict, dest_path=('General_EM', 'emission_current'),
                 cast_fn=float, units='MicroA', conv_fn=None, override=False),
         ]
 
@@ -438,8 +387,7 @@ def _dm3_general_info(self) -> None:
                     source_path=base + ('Voltage',), cast_fn=float,
                     dest_path=('General_EM', 'accelerating_voltage'),
                     units='KiloV' if voltage >= 1000 else 'V',
-                    conv_fn=lambda x: x / 1000 if voltage >= 1000 else x,
-                    override=False)
+                    conv_fn=lambda x: x / 1000 if voltage >= 1000 else x, override=False)
             ]
 
         # "Session Info"
@@ -451,33 +399,28 @@ def _dm3_general_info(self) -> None:
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta, source_path=base + ('Microscope',),
-                dest_dict=dest_dict,
-                dest_path=('General_EM', 'microscope_name'),
+                dest_dict=dest_dict, dest_path=('General_EM', 'microscope_name'),
                 cast_fn=str, units=None, conv_fn=None, override=False)]
 
         # "Meta Data"
         base = self.__get_dm3_tag_pre_path() + ('Meta Data',)
         mapping += [
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Acquisition Mode',),
+                source_dict=self.raw_meta, source_path=base + ('Acquisition Mode',),
                 dest_dict=dest_dict, dest_path=('TEM', 'acquisition_mode'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Format',),
+                source_dict=self.raw_meta, source_path=base + ('Format',),
                 dest_dict=dest_dict, dest_path=('TEM', 'acquisition_format'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Signal',),
+                source_dict=self.raw_meta, source_path=base + ('Signal',),
                 dest_dict=dest_dict, dest_path=('TEM', 'acquisition_signal'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             # sometimes the EDS signal label is in a different place
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=base + ('Experiment keywords', 'TagGroup1',
-                                    'Label'),
+                source_path=base + ('Experiment keywords', 'TagGroup1', 'Label'),
                 dest_dict=dest_dict, dest_path=('TEM', 'acquisition_signal'),
                 cast_fn=str, units=None, conv_fn=None, override=False)
         ]
@@ -486,64 +429,53 @@ def _dm3_general_info(self) -> None:
         base = self.__get_dm3_tag_pre_path()
         mapping += [
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('Acquisition', 'Device', 'Name'),
+                source_dict=self.raw_meta, source_path=base + ('Acquisition', 'Device', 'Name'),
                 dest_dict=dest_dict, dest_path=('TEM', 'acquisition_device'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('DataBar', 'Device Name'),
+                source_dict=self.raw_meta, source_path=base + ('DataBar', 'Device Name'),
                 dest_dict=dest_dict, dest_path=('TEM', 'acquisition_device'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=base + ('Acquisition', 'Parameters', 'High Level',
-                                    'Exposure (s)'),
+                source_path=base + ('Acquisition', 'Parameters', 'High Level', 'Exposure (s)'),
                 dest_dict=dest_dict, dest_path=('General_EM', 'exposure_time'),
                 cast_fn=float, units='SEC', conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('DataBar', 'Exposure Time (s)'),
+                source_dict=self.raw_meta, source_path=base + ('DataBar', 'Exposure Time (s)'),
                 dest_dict=dest_dict, dest_path=('General_EM', 'exposure_time'),
                 cast_fn=float, units='SEC', conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=base + ('GMS Version', 'Created'),
-                dest_dict=dest_dict,
-                dest_path=('General_EM', 'acquisition_software_version'),
+                source_dict=self.raw_meta, source_path=base + ('GMS Version', 'Created'),
+                dest_dict=dest_dict, dest_path=('General_EM', 'acquisition_software_version'),
                 cast_fn=str, units=None, conv_fn=None, override=False)
         ]
 
-        if get_val(self.raw_meta, ('ImageList', 'TagGroup0', 'ImageTags')) is\
-                not None:
+        if get_val(self.raw_meta, ('ImageList', 'TagGroup0', 'ImageTags')) is not None:
             # we have DigitalMicrograph tags, so set acquisition software name
-            set_val_units(nest_dict=dest_dict,
-                          path=('General_EM', 'acquisition_software_name'),
+            set_val_units(nest_dict=dest_dict, path=('General_EM', 'acquisition_software_name'),
                           value='DigitalMicrograph')
 
         map_dict_values(mapping)
 
     def __get_dm3_tag_pre_path(self) -> Tuple:
-        """Get the path into a dictionary where the important DigitalMicrograph
-        metadata is expected to be found. If the .dm3/.dm4 file contains a stack
-        of images, the metadata to extract is instead under a `plane info`
-        tag, so this method will determine if the stack metadata is present
-        and return the correct path. ``pre_path`` will be something
-        like ``('ImageList', 'TagGroup0', 'ImageTags', 'plane info',
-        'TagGroup0', 'source tags')``.
+        """Get the path into a dictionary where the important DigitalMicrograph metadata is
+        expected to be found. If the .dm3/.dm4 file contains a stack of images, the metadata to
+        extract is instead under a `plane info` tag, so this method will determine if the stack
+        metadata is present and return the correct path. ``pre_path`` will be something
+        like ``('ImageList', 'TagGroup0', 'ImageTags', 'plane info', 'TagGroup0', 'source tags')``.
 
         Returns:
-            A tuple containing the subsequent keys that need to be traversed
-            to get to the point in the ``raw_metadata`` where the important
-            metadata is stored
+            A tuple containing the subsequent keys that need to be traversed to get to the point
+            in the ``raw_metadata`` where the important metadata is stored
         """
         # test if we have a stack
         stack_path = ('ImageList', 'TagGroup0', 'ImageTags', 'plane info')
         stack_val = get_val(self.raw_meta, stack_path)
         if stack_val is not None:
             # we're in a stack
-            pre_path = ('ImageList', 'TagGroup0', 'ImageTags', 'plane info',
-                        'TagGroup0', 'source tags')
+            pre_path = ('ImageList', 'TagGroup0', 'ImageTags', 'plane info', 'TagGroup0',
+                        'source tags')
         else:
             pre_path = ('ImageList', 'TagGroup0', 'ImageTags')
 
@@ -573,21 +505,18 @@ def _dm3_eels_info(self) -> None:
                 conv_fn=None, cast_fn=int, override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
-                source_path=base + ('Experimental Conditions',
-                                    'Collection semi-angle (mrad)'),
+                source_path=base + ('Experimental Conditions', 'Collection semi-angle (mrad)'),
                 dest_path=('EELS', 'collection_angle'), units='MilliRAD',
                 conv_fn=None, cast_fn=float, override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
-                source_path=base + ('Experimental Conditions',
-                                    'Convergence semi-angle (mrad)'),
+                source_path=base + ('Experimental Conditions', 'Convergence semi-angle (mrad)'),
                 dest_path=('General_EM', 'convergence_angle'), units='MilliRAD',
                 conv_fn=None, cast_fn=float, override=False)]
 
         # spectrometer metadata
         # is usually at one of two places, so try both
-        spect_dict = get_val(self.raw_meta,
-                             pre_path + ('EELS', 'Acquisition', 'Spectrometer'))
+        spect_dict = get_val(self.raw_meta, pre_path + ('EELS', 'Acquisition', 'Spectrometer'))
         if spect_dict is not None:
             spect_path = pre_path + ('EELS', 'Acquisition', 'Spectrometer')
         else:
@@ -596,57 +525,55 @@ def _dm3_eels_info(self) -> None:
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=spect_path + ('Aperture label',),
-                dest_path=('EELS', 'aperture_size'), units='MilliM',
-                conv_fn=None,
-                cast_fn=lambda s: float(s.replace('mm', '')),
-                override=False),
+                dest_path=('EELS', 'aperture_size'), units='MilliM', conv_fn=None,
+                cast_fn=lambda s: float(s.replace('mm', '')), override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=spect_path + ('Dispersion (eV/ch)',),
-                dest_path=('EELS', 'dispersion_per_channel'), units='EV',
-                conv_fn=None, cast_fn=float, override=False),
+                dest_path=('EELS', 'dispersion_per_channel'), units='EV', conv_fn=None,
+                cast_fn=float, override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=spect_path + ('Energy loss (eV)',),
-                dest_path=('EELS', 'energy_loss_offset'), units='EV',
-                conv_fn=None, cast_fn=float, override=False),
+                dest_path=('EELS', 'energy_loss_offset'), units='EV', conv_fn=None,
+                cast_fn=float, override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=spect_path + ('Instrument name',),
-                dest_path=('EELS', 'spectrometer_name'), units=None,
-                conv_fn=None, cast_fn=str, override=False),
+                dest_path=('EELS', 'spectrometer_name'), units=None, conv_fn=None, cast_fn=str,
+                override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=spect_path + ('Drift tube voltage (V)',),
-                dest_path=('EELS', 'drift_tube_voltage'), units='V',
-                conv_fn=None, cast_fn=float, override=False),
+                dest_path=('EELS', 'drift_tube_voltage'), units='V', conv_fn=None, cast_fn=float,
+                override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=spect_path + ('Drift tube enabled',),
-                dest_path=('EELS', 'drift_tube_enabled'), units=None,
-                conv_fn=None, cast_fn=bool, override=False),
+                dest_path=('EELS', 'drift_tube_enabled'), units=None, conv_fn=None, cast_fn=bool,
+                override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=spect_path + ('Prism offset (V)',),
-                dest_path=('EELS', 'prism_shift_voltage'), units='V',
-                conv_fn=None, cast_fn=float, override=False),
+                dest_path=('EELS', 'prism_shift_voltage'), units='V', conv_fn=None,
+                cast_fn=float, override=False),
             # note space at end of "Prism offset enabled " because that's how
             # it gets loaded in from DigitalMicrograph...
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=spect_path + ('Prism offset enabled ',),
-                dest_path=('EELS', 'prism_shift_enabled'), units=None,
-                conv_fn=None, cast_fn=bool, override=False),
+                dest_path=('EELS', 'prism_shift_enabled'), units=None, conv_fn=None,
+                cast_fn=bool, override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=spect_path + ('Slit width (eV)',),
-                dest_path=('EELS', 'filter_slit_width'), units='EV',
-                conv_fn=None, cast_fn=float, override=False),
+                dest_path=('EELS', 'filter_slit_width'), units='EV', conv_fn=None, cast_fn=float,
+                override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=spect_path + ('Slit inserted',),
-                dest_path=('EELS', 'filter_slit_inserted'), units=None,
-                conv_fn=None, cast_fn=bool, override=False),
+                dest_path=('EELS', 'filter_slit_inserted'), units=None, conv_fn=None,
+                cast_fn=bool, override=False),
         ]
         map_dict_values(mapping)
 
@@ -658,71 +585,69 @@ def _dm3_eds_info(self) -> None:
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=base + ('Detector Info', 'Azimuthal angle'),
-                dest_path=('EDS', 'azimuth_angle'), units='DEG',
-                conv_fn=None, cast_fn=float, override=False),
+                dest_path=('EDS', 'azimuth_angle'), units='DEG', conv_fn=None, cast_fn=float,
+                override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=base + ('Detector Info', 'Detector type'),
-                dest_path=('EDS', 'detector_type'), units=None,
-                conv_fn=None, cast_fn=str, override=False),
+                dest_path=('EDS', 'detector_type'), units=None, conv_fn=None, cast_fn=str,
+                override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=base + ('Acquisition', 'Dispersion (eV)'),
-                dest_path=('EDS', 'dispersion_per_channel'), units='EV',
-                conv_fn=None, cast_fn=float, override=False),
+                dest_path=('EDS', 'dispersion_per_channel'), units='EV', conv_fn=None,
+                cast_fn=float, override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=base + ('Detector Info', 'Elevation angle'),
-                dest_path=('EDS', 'elevation_angle'), units='DEG',
-                conv_fn=None, cast_fn=float, override=False),
+                dest_path=('EDS', 'elevation_angle'), units='DEG', conv_fn=None, cast_fn=float,
+                override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=base + ('Detector Info', 'Incidence angle'),
-                dest_path=('EDS', 'incidence_angle'), units='DEG',
-                conv_fn=None, cast_fn=float, override=False),
+                dest_path=('EDS', 'incidence_angle'), units='DEG', conv_fn=None, cast_fn=float,
+                override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=base + ('Live time',),
-                dest_path=('EDS', 'live_time'), units='SEC',
-                conv_fn=None, cast_fn=float, override=False),
+                dest_path=('EDS', 'live_time'), units='SEC', conv_fn=None, cast_fn=float,
+                override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=base + ('Real time',),
-                dest_path=('EDS', 'real_time'), units='SEC',
-                conv_fn=None, cast_fn=float, override=False),
+                dest_path=('EDS', 'real_time'), units='SEC', conv_fn=None, cast_fn=float,
+                override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=base + ('Detector Info', 'Solid angle'),
-                dest_path=('EDS', 'solid_angle'), units='SR',
-                conv_fn=None, cast_fn=float, override=False),
+                dest_path=('EDS', 'solid_angle'), units='SR', conv_fn=None, cast_fn=float,
+                override=False),
             MappingElements(
                 source_dict=self.raw_meta, dest_dict=self.em,
                 source_path=base + ('Detector Info', 'Stage tilt'),
-                dest_path=('EDS', 'stage_tilt'), units='DEG',
-                conv_fn=None, cast_fn=float, override=False)
+                dest_path=('EDS', 'stage_tilt'), units='DEG', conv_fn=None, cast_fn=float,
+                override=False)
         ]
 
         map_dict_values(mapping)
 
     def _dm3_tecnai_info(self, delimiter: Optional[str] = u'\u2028') -> None:
-        """Some FEI Microscopes will write additional metadata into dm3 files
-        in a long string separated by a unicode delimiter (u'\u2028'),
-        present at ``ImageList.TagGroup0.ImageTags.Tecnai.Microscope_Info``.
-        This method parses that information.  Adapted from the
-        implementation in https://github.com/usnistgov/NexusLIMS
+        """Some FEI Microscopes will write additional metadata into dm3 files in a long string
+        separated by a unicode delimiter (u'\u2028'), present at
+        ``ImageList.TagGroup0.ImageTags.Tecnai.Microscope_Info``. This method parses that
+        information.  Adapted from the implementation in https://github.com/usnistgov/NexusLIMS
 
         args:
-            delimiter: The value (a unicode string) used to split the
-                ``microscope_info`` string. Should not need to be provided (
-                this value is hard-coded in DigitalMicrograph), but specified
-                as a parameter for future flexibility
+            delimiter: The value (a unicode string) used to split the ``microscope_info`` string.
+                Should not need to be provided (this value is hard-coded in DigitalMicrograph), but
+                specified as a parameter for future flexibility
         """
         def __find_val(s_to_find, list_to_search):
-            """Return the first value in ``list_to_search`` that contains
-            ``s_to_find``, or ``None`` if it is not found
+            """Return the first value in ``list_to_search`` that contains ``s_to_find``,
+            or ``None`` if it is not found
 
-            Note: If needed, this could be improved to use regex instead,
-            which would provide more control over the patterns to return
+            Note: If needed, this could be improved to use regex instead, which would provide
+            more control over the patterns to return
             """
             res = [x for x in list_to_search if s_to_find in x]
             if len(res) > 0:
@@ -733,8 +658,7 @@ def __find_val(s_to_find, list_to_search):
             else:
                 return None
 
-        def __extract_val(regex: str, str_to_search: str,
-                          match_num : int = 1) -> Optional[str]:
+        def __extract_val(regex: str, str_to_search: str, match_num: int = 1) -> Optional[str]:
             """Extract a value from a string based on a grouped regex
             """
             result = re.compile(regex).search(str_to_search)
@@ -742,8 +666,7 @@ def __extract_val(regex: str, str_to_search: str,
                 result = result[match_num]
             return result
 
-        path_to_tecnai = ('ImageList', 'TagGroup0', 'ImageTags', 'Tecnai',
-                          'Microscope Info')
+        path_to_tecnai = ('ImageList', 'TagGroup0', 'ImageTags', 'Tecnai', 'Microscope Info')
         self.tecnai_info = get_val(self.raw_meta, path_to_tecnai)
 
         if self.tecnai_info is None:
@@ -757,35 +680,30 @@ def __extract_val(regex: str, str_to_search: str,
             mapping = [
                 MappingElements(
                     source_dict={
-                        'Microscope_Name': __find_val('Microscope ',
-                                                      self.tecnai_info)},
+                        'Microscope_Name': __find_val('Microscope ', self.tecnai_info)},
                     source_path='Microscope_Name', dest_dict=self.em,
                     dest_path=('General_EM', 'microscope_name'), cast_fn=str,
                     units=None, conv_fn=None, override=True),
                 MappingElements(
                     source_dict={
                         'Extractor_Voltage':
-                            __extract_val(r'Extr volt (\d*) V',
-                                          __find_val('Extr volt ',
-                                                     self.tecnai_info))},
+                            __extract_val(r'Extr volt (\d*) V', __find_val('Extr volt ',
+                                                                           self.tecnai_info))},
                     source_path='Extractor_Voltage', dest_dict=self.em,
                     dest_path=('TEM', 'extractor_voltage'), cast_fn=int,
                     units='V', conv_fn=None, override=True),
                 MappingElements(
                     source_dict={
                         'Emission_Current':
-                            __extract_val(r'Emission ([\d|\.]*)uA',
-                                          __find_val('Emission ',
-                                                     self.tecnai_info))},
+                            __extract_val(r'Emission ([\d|\.]*)uA', __find_val('Emission ',
+                                                                               self.tecnai_info))},
                     source_path='Emission_Current', dest_dict=self.em,
                     dest_path=('General_EM', 'emission_current'), cast_fn=float,
                     units='MicroA', conv_fn=None, override=True),
                 MappingElements(
                     source_dict={
                         'Operation_Mode':
-                            __extract_val(r'(.*) Defocus',
-                                          __find_val('Mode ',
-                                                     self.tecnai_info))},
+                            __extract_val(r'(.*) Defocus', __find_val('Mode ', self.tecnai_info))},
                     source_path='Operation_Mode', dest_dict=self.em,
                     dest_path=('TEM', 'operation_mode'), cast_fn=str,
                     units=None, conv_fn=None, override=True),
@@ -796,8 +714,7 @@ def __extract_val(regex: str, str_to_search: str,
                     source_dict={
                         'Defocus':
                             __extract_val(r'Defocus \(um\) (.*) Magn',
-                                          __find_val('Mode ',
-                                                     self.tecnai_info))},
+                                          __find_val('Mode ', self.tecnai_info))},
                     source_path='Defocus', dest_dict=self.em,
                     dest_path=('TEM', 'defocus'), cast_fn=float,
                     units='MicroM', conv_fn=None, override=True),
@@ -805,8 +722,7 @@ def __extract_val(regex: str, str_to_search: str,
                     source_dict={
                         'Defocus':
                             __extract_val(r'Defocus ([\d|\.]*) CL',
-                                          __find_val('Mode ',
-                                                     self.tecnai_info))},
+                                          __find_val('Mode ', self.tecnai_info))},
                     source_path='Defocus', dest_dict=self.em,
                     dest_path=('TEM', 'defocus'), cast_fn=float,
                     units='MicroM', conv_fn=None, override=True),
@@ -814,9 +730,7 @@ def __extract_val(regex: str, str_to_search: str,
                 MappingElements(
                     source_dict={
                         'Magnification':
-                            __extract_val(r'Magn (\d*)x',
-                                          __find_val('Mode ',
-                                                     self.tecnai_info))},
+                            __extract_val(r'Magn (\d*)x', __find_val('Mode ', self.tecnai_info))},
                     source_path='Magnification', dest_dict=self.em,
                     dest_path=('General_EM', 'magnification_indicated'),
                     cast_fn=int, units='UNITLESS', conv_fn=None,
@@ -824,16 +738,13 @@ def __extract_val(regex: str, str_to_search: str,
                 MappingElements(
                     source_dict={
                         'Camera_Length':
-                            __extract_val(r'CL (.*)m',
-                                          __find_val('Mode ',
-                                                     self.tecnai_info))},
+                            __extract_val(r'CL (.*)m', __find_val('Mode ', self.tecnai_info))},
                     source_path='Camera_Length', dest_dict=self.em,
                     dest_path=('TEM', 'camera_length'), cast_fn=float,
                     units='MilliM', conv_fn=lambda x: x*1000, override=True),
                 # spot size
                 MappingElements(
-                    source_dict={'Spot_Size':
-                                     __find_val('Spot ', self.tecnai_info)},
+                    source_dict={'Spot_Size': __find_val('Spot ', self.tecnai_info)},
                     source_path='Spot_Size', dest_dict=self.em,
                     dest_path=('TEM', 'spot_size'), cast_fn=int,
                     units='UNITLESS', conv_fn=None, override=True),
@@ -849,93 +760,78 @@ def __extract_val(regex: str, str_to_search: str,
                     MappingElements(
                         source_dict=stage, source_path='x', dest_dict=self.em,
                         dest_path=('General_EM', 'stage_position', 'x'),
-                        cast_fn=float, units='MicroM', conv_fn=None,
-                        override=True),
+                        cast_fn=float, units='MicroM', conv_fn=None, override=True),
                     MappingElements(
                         source_dict=stage, source_path='y', dest_dict=self.em,
                         dest_path=('General_EM', 'stage_position', 'y'),
-                        cast_fn=float, units='MicroM', conv_fn=None,
-                        override=True),
+                        cast_fn=float, units='MicroM', conv_fn=None, override=True),
                     MappingElements(
                         source_dict=stage, source_path='z', dest_dict=self.em,
                         dest_path=('General_EM', 'stage_position', 'z'),
-                        cast_fn=float, units='MicroM', conv_fn=None,
-                        override=True),
+                        cast_fn=float, units='MicroM', conv_fn=None, override=True),
                     MappingElements(
                         source_dict=stage, source_path='a', dest_dict=self.em,
-                        dest_path=('General_EM', 'stage_position',
-                                   'tilt_alpha'), cast_fn=float, units='DEG',
-                        conv_fn=None, override=True),
+                        dest_path=('General_EM', 'stage_position', 'tilt_alpha'),
+                        cast_fn=float, units='DEG', conv_fn=None, override=True),
                     MappingElements(
                         source_dict=stage, source_path='b', dest_dict=self.em,
                         dest_path=('General_EM', 'stage_position', 'tilt_beta'),
-                        cast_fn=float, units='DEG', conv_fn=None,
-                        override=True),
+                        cast_fn=float, units='DEG', conv_fn=None, override=True),
                 ]
 
             # process EELS spectrometer info from Tecnai string
             if __find_val('Filter related settings', self.tecnai_info):
                 filter_dict = {
                     'Mode': __find_val('Mode: ', self.tecnai_info),
-                    'Dispersion': __extract_val(
-                        r'(.*)\[eV/Channel\]',
-                        __find_val('Selected dispersion: ', self.tecnai_info)),
-                    'Aperture': __extract_val(
-                        r'(\d*)mm', __find_val('Selected aperture: ',
-                                               self.tecnai_info)),
-                    'Prism': __extract_val(
-                        r'(.*)\[eV\]',
-                        __find_val('Prism shift: ', self.tecnai_info)),
-                    'Drift': __extract_val(
-                        r'(.*)\[eV\]',
-                        __find_val('Drift tube: ', self.tecnai_info)),
-                    'TotalLoss': __extract_val(
-                        r'(.*)\[eV\]',
-                        __find_val('Total energy loss: ', self.tecnai_info))
+                    'Dispersion': __extract_val(r'(.*)\[eV/Channel\]',
+                                                __find_val('Selected dispersion: ',
+                                                           self.tecnai_info)),
+                    'Aperture': __extract_val(r'(\d*)mm',
+                                              __find_val('Selected aperture: ',
+                                                         self.tecnai_info)),
+                    'Prism': __extract_val(r'(.*)\[eV\]',
+                                           __find_val('Prism shift: ', self.tecnai_info)),
+                    'Drift': __extract_val(r'(.*)\[eV\]',
+                                           __find_val('Drift tube: ', self.tecnai_info)),
+                    'TotalLoss': __extract_val(r'(.*)\[eV\]',
+                                               __find_val('Total energy loss: ', self.tecnai_info))
                 }
                 mapping += [
                     MappingElements(
                         source_dict=filter_dict, source_path='Mode',
-                        dest_dict=self.em,
-                        dest_path=('EELS', 'spectrometer_mode'),
+                        dest_dict=self.em, dest_path=('EELS', 'spectrometer_mode'),
                         cast_fn=str, units=None, conv_fn=None, override=True),
                     MappingElements(
                         source_dict=filter_dict, source_path='Dispersion',
-                        dest_dict=self.em,
-                        dest_path=('EELS', 'dispersion_per_channel'),
+                        dest_dict=self.em, dest_path=('EELS', 'dispersion_per_channel'),
                         cast_fn=float, units='EV', conv_fn=None, override=True),
                     MappingElements(
                         source_dict=filter_dict, source_path='Aperture',
-                        dest_dict=self.em,
-                        dest_path=('EELS', 'aperture_size'),
-                        cast_fn=float, units='MilliM', conv_fn=None,
-                        override=True),
+                        dest_dict=self.em, dest_path=('EELS', 'aperture_size'),
+                        cast_fn=float, units='MilliM', conv_fn=None, override=True),
                     MappingElements(
                         source_dict=filter_dict, source_path='Drift',
-                        dest_dict=self.em, dest_path=('EELS',
-                                                      'drift_tube_energy'),
+                        dest_dict=self.em, dest_path=('EELS', 'drift_tube_energy'),
                         cast_fn=float, units='EV', conv_fn=None, override=True),
                     MappingElements(
                         source_dict=filter_dict, source_path='Prism',
-                        dest_dict=self.em, dest_path=('EELS',
-                                                      'prism_shift_energy'),
+                        dest_dict=self.em, dest_path=('EELS', 'prism_shift_energy'),
                         cast_fn=float, units='EV', conv_fn=None, override=True),
                     MappingElements(
                         source_dict=filter_dict, source_path='TotalLoss',
-                        dest_dict=self.em, dest_path=('EELS',
-                                                      'total_energy_loss'),
+                        dest_dict=self.em, dest_path=('EELS', 'total_energy_loss'),
                         cast_fn=float, units='EV', conv_fn=None, override=True),
                 ]
 
             map_dict_values(mapping)
 
     def _tia_info(self) -> None:
-        """Parses information commonly found in .ser/.emi files produced by the
-        "Tecnai Imaging and Analysis" (TIA) software
+        """Parses information commonly found in .ser/.emi files produced by the "Tecnai Imaging
+        and Analysis" (TIA) software
 
-        Terms such as ``IntegrationTime`` and ``EnergyResolution`` appear to be
-        non-specific as to acqusition modality (i.e. could be EELS or EDS), so
-        we do not extract those into our metadata hierarchy 
+        Terms such as ``IntegrationTime`` and ``EnergyResolution`` appear to be non-specific as
+        to acquisition modality (i.e. could be EELS or EDS), so we do not extract those into our
+        metadata hierarchy
         """
 
         mapping = [
@@ -943,8 +839,7 @@ def _tia_info(self) -> None:
                 source_dict=self.raw_meta,
                 source_path=('ObjectInfo', 'ExperimentalConditions',
                              'MicroscopeConditions', 'AcceleratingVoltage'),
-                dest_dict=self.em, dest_path=('General_EM',
-                                              'accelerating_voltage'),
+                dest_dict=self.em, dest_path=('General_EM', 'accelerating_voltage'),
                 cast_fn=float, units='V', conv_fn=None, override=False),
 
             MappingElements(
@@ -960,286 +855,220 @@ def _tia_info(self) -> None:
 
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=('ObjectInfo', 'ExperimentalDescription',
-                             'Microscope'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Microscope'),
                 dest_dict=self.em, dest_path=('General_EM', 'microscope_name'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=('ObjectInfo', 'ExperimentalDescription',
-                             'High tension_kV'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'High tension_kV'),
                 dest_dict=self.em, dest_path=('General_EM',
                                               'accelerating_voltage'),
                 cast_fn=float, units='KiloV', conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=('ObjectInfo', 'ExperimentalDescription',
-                             'Emission_uA'), dest_dict=self.em,
-                dest_path=('General_EM', 'emission_current'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Emission_uA'),
+                dest_dict=self.em, dest_path=('General_EM', 'emission_current'),
                 cast_fn=float, units='MicroA', conv_fn=None, override=False),
             # this value is often more specific than the one from HyperSpy,
             # so override acquisition mode:
             MappingElements(
                 source_dict=self.raw_meta,
                 source_path=('ObjectInfo', 'ExperimentalDescription', 'Mode'),
-                dest_dict=self.em,
-                dest_path=('General_EM', 'acquisition_mode'),
-                cast_fn=str, units=None, conv_fn=lambda x: x.strip(),
-                override=True),
+                dest_dict=self.em, dest_path=('General_EM', 'acquisition_mode'),
+                cast_fn=str, units=None, conv_fn=lambda x: x.strip(), override=True),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=('ObjectInfo', 'ExperimentalDescription',
-                             'Defocus_um'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Defocus_um'),
                 dest_dict=self.em, dest_path=('TEM', 'defocus'),
                 cast_fn=float, units='MicroM', conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=('ObjectInfo', 'ExperimentalDescription',
-                             'Magnification_x'),
-                dest_dict=self.em,
-                dest_path=('General_EM', 'magnification_indicated'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Magnification_x'),
+                dest_dict=self.em, dest_path=('General_EM', 'magnification_indicated'),
                 cast_fn=float, units='UNITLESS', conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=('ObjectInfo', 'ExperimentalDescription',
-                             'Camera length_m'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Camera length_m'),
                 dest_dict=self.em, dest_path=('TEM', 'camera_length'),
                 cast_fn=float, units='M', conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=('ObjectInfo', 'ExperimentalDescription',
-                             'Spot size'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Spot size'),
                 dest_dict=self.em, dest_path=('TEM', 'spot_size'),
                 cast_fn=int, units='UNITLESS', conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=(
-                    'ObjectInfo', 'ExperimentalDescription', 'Stage X_um'),
-                dest_dict=self.em,
-                dest_path=('General_EM', 'stage_position', 'x'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Stage X_um'),
+                dest_dict=self.em, dest_path=('General_EM', 'stage_position', 'x'),
                 cast_fn=float, units='MicroM', conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=(
-                    'ObjectInfo', 'ExperimentalDescription', 'Stage Y_um'),
-                dest_dict=self.em,
-                dest_path=('General_EM', 'stage_position', 'y'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Stage Y_um'),
+                dest_dict=self.em, dest_path=('General_EM', 'stage_position', 'y'),
                 cast_fn=float, units='MicroM', conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=(
-                    'ObjectInfo', 'ExperimentalDescription', 'Stage Z_um'),
-                dest_dict=self.em,
-                dest_path=('General_EM', 'stage_position', 'z'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Stage Z_um'),
+                dest_dict=self.em, dest_path=('General_EM', 'stage_position', 'z'),
                 cast_fn=float, units='MicroM', conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=(
-                    'ObjectInfo', 'ExperimentalDescription', 'Stage A_deg'),
-                dest_dict=self.em,
-                dest_path=('General_EM', 'stage_position', 'tilt_alpha'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Stage A_deg'),
+                dest_dict=self.em, dest_path=('General_EM', 'stage_position', 'tilt_alpha'),
                 cast_fn=float, units='DEG', conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=(
-                    'ObjectInfo', 'ExperimentalDescription', 'Stage B_deg'),
-                dest_dict=self.em,
-                dest_path=('General_EM', 'stage_position', 'tilt_beta'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Stage B_deg'),
+                dest_dict=self.em, dest_path=('General_EM', 'stage_position', 'tilt_beta'),
                 cast_fn=float, units='DEG', conv_fn=None, override=False),
 
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=(
-                    'ObjectInfo', 'ExperimentalDescription', 'Filter mode'),
-                dest_dict=self.em,
-                dest_path=('EELS', 'spectrometer_mode'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Filter mode'),
+                dest_dict=self.em, dest_path=('EELS', 'spectrometer_mode'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=(
-                    'ObjectInfo', 'ExperimentalDescription',
-                    'Filter selected dispersion_eV/Channel'),
-                dest_dict=self.em,
-                dest_path=('EELS', 'dispersion_per_channel'),
+                source_path=('ObjectInfo', 'ExperimentalDescription',
+                             'Filter selected dispersion_eV/Channel'),
+                dest_dict=self.em, dest_path=('EELS', 'dispersion_per_channel'),
                 cast_fn=float, units='EV', conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=(
-                    'ObjectInfo', 'ExperimentalDescription',
-                    'Filter selected aperture'),
-                dest_dict=self.em,
-                dest_path=('EELS', 'aperture_size'),
-                cast_fn=lambda x: float(x.replace('mm', '')),
-                units='MilliM', conv_fn=None,  override=False),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Filter selected aperture'),
+                dest_dict=self.em, dest_path=('EELS', 'aperture_size'),
+                cast_fn=lambda x: float(x.replace('mm', '')), units='MilliM', conv_fn=None,
+                override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=(
-                    'ObjectInfo', 'ExperimentalDescription',
-                    'Filter prism shift_eV'),
-                dest_dict=self.em,
-                dest_path=('EELS', 'prism_shift_energy'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Filter prism shift_eV'),
+                dest_dict=self.em, dest_path=('EELS', 'prism_shift_energy'),
                 cast_fn=float, units='EV', conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=(
-                    'ObjectInfo', 'ExperimentalDescription',
-                    'Filter drift tube_eV'),
-                dest_dict=self.em,
-                dest_path=('EELS', 'drift_tube_energy'),
+                source_path=('ObjectInfo', 'ExperimentalDescription', 'Filter drift tube_eV'),
+                dest_dict=self.em, dest_path=('EELS', 'drift_tube_energy'),
                 cast_fn=float, units='EV', conv_fn=None, override=False),
             MappingElements(
                 source_dict=self.raw_meta,
-                source_path=(
-                    'ObjectInfo', 'ExperimentalDescription',
-                    'Filter total energy loss_eV'),
-                dest_dict=self.em,
-                dest_path=('EELS', 'total_energy_loss'),
+                source_path=('ObjectInfo', 'ExperimentalDescription',
+                             'Filter total energy loss_eV'),
+                dest_dict=self.em, dest_path=('EELS', 'total_energy_loss'),
                 cast_fn=float, units='EV', conv_fn=None, override=False)
         ]
         map_dict_values(mapping)
 
     def _tiff_info(self) -> None:
-        """Parses metadata found in FEI/ThermoFisher tiff formats (and perhaps
-        others in the future), produced by SEM and dual beam tools
+        """Parses metadata found in FEI/ThermoFisher tiff formats (and perhaps others in the
+        future), produced by SEM and dual beam tools
         """
         mapping = [
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'System', 'Software'),
-                dest_dict=self.em, dest_path=('General_EM',
-                                              'acquisition_software_version'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'System', 'Software'),
+                dest_dict=self.em, dest_path=('General_EM', 'acquisition_software_version'),
                 cast_fn=str, units=None, conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Beam', 'Spot'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Beam', 'Spot'),
                 dest_dict=self.em, dest_path=('SEM', 'spot_size'),
-                cast_fn=lambda x: int(x) if x != '' else None, units=None,
-                conv_fn=None, override=False),
+                cast_fn=lambda x: int(x) if x != '' else None, units=None, conv_fn=None,
+                override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Beam', 'HV'),
-                dest_dict=self.em, dest_path=('General_EM',
-                                              'accelerating_voltage'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Beam', 'HV'),
+                dest_dict=self.em, dest_path=('General_EM', 'accelerating_voltage'),
                 cast_fn=lambda x: float(x) if x != '' else None, units='KiloV',
                 conv_fn=lambda x: x/1000 if x != '' else None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'EBeam', 'HV'),
-                dest_dict=self.em, dest_path=('General_EM',
-                                              'accelerating_voltage'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'EBeam', 'HV'),
+                dest_dict=self.em, dest_path=('General_EM', 'accelerating_voltage'),
                 cast_fn=lambda x: float(x) if x != '' else None,
                 units='KiloV', conv_fn=lambda x: x / 1000 if x != '' else None,
                 override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'EBeam', 'HFW'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'EBeam', 'HFW'),
                 dest_dict=self.em, dest_path=('SEM', 'horizontal_field_width'),
-                cast_fn=lambda x: float(x) if x != '' else None,
-                units='M', conv_fn=None, override=False),
+                cast_fn=lambda x: float(x) if x != '' else None, units='M', conv_fn=None,
+                override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'EBeam', 'VFW'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'EBeam', 'VFW'),
                 dest_dict=self.em, dest_path=('SEM', 'vertical_field_width'),
-                cast_fn=lambda x: float(x) if x != '' else None, units='M',
-                conv_fn=None, override=False),
+                cast_fn=lambda x: float(x) if x != '' else None, units='M', conv_fn=None,
+                override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'EBeam', 'WD'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'EBeam', 'WD'),
                 dest_dict=self.em, dest_path=('SEM', 'working_distance'),
-                cast_fn=lambda x: float(x) if x != '' else None, units='M',
-                conv_fn=None, override=False),
+                cast_fn=lambda x: float(x) if x != '' else None, units='M', conv_fn=None,
+                override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'EBeam', 'BeamCurrent'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'EBeam', 'BeamCurrent'),
                 dest_dict=self.em, dest_path=('General_EM', 'beam_current'),
-                cast_fn=lambda x: float(x) if x != '' else None, units='A',
-                conv_fn=None, override=False),
+                cast_fn=lambda x: float(x) if x != '' else None, units='A', conv_fn=None,
+                override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Stage', 'StageX'),
-                dest_dict=self.em,
-                dest_path=('General_EM', 'stage_position', 'x'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Stage', 'StageX'),
+                dest_dict=self.em, dest_path=('General_EM', 'stage_position', 'x'),
                 cast_fn=lambda x: float(x) if x != '' else None, units='MilliM',
                 conv_fn=lambda x: x * 1000 if x != '' else None, override=True),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Stage', 'StageY'),
-                dest_dict=self.em,
-                dest_path=('General_EM', 'stage_position', 'y'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Stage', 'StageY'),
+                dest_dict=self.em, dest_path=('General_EM', 'stage_position', 'y'),
                 cast_fn=lambda x: float(x) if x != '' else None, units='MilliM',
                 conv_fn=lambda x: x * 1000 if x != '' else None, override=True),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Stage', 'StageZ'),
-                dest_dict=self.em,
-                dest_path=('General_EM', 'stage_position', 'z'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Stage', 'StageZ'),
+                dest_dict=self.em, dest_path=('General_EM', 'stage_position', 'z'),
                 cast_fn=lambda x: float(x) if x != '' else None, units='MilliM',
                 conv_fn=lambda x: x * 1000 if x != '' else None, override=True),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Stage', 'StageR'),
-                dest_dict=self.em,
-                dest_path=('General_EM', 'stage_position', 'rotation'),
-                cast_fn=lambda x: float(x) if x != '' else None, units='DEG',
-                conv_fn=None, override=True),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Stage', 'StageR'),
+                dest_dict=self.em, dest_path=('General_EM', 'stage_position', 'rotation'),
+                cast_fn=lambda x: float(x) if x != '' else None, units='DEG', conv_fn=None,
+                override=True),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Stage', 'StageT'),
-                dest_dict=self.em,
-                dest_path=('General_EM', 'stage_position', 'tilt_alpha'),
-                cast_fn=lambda x: float(x) if x != '' else None, units='DEG',
-                conv_fn=None, override=True),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Stage', 'StageT'),
+                dest_dict=self.em, dest_path=('General_EM', 'stage_position', 'tilt_alpha'),
+                cast_fn=lambda x: float(x) if x != '' else None, units='DEG', conv_fn=None,
+                override=True),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Stage', 'StageTb'),
-                dest_dict=self.em,
-                dest_path=('General_EM', 'stage_position', 'tilt_beta'),
-                cast_fn=lambda x: float(x) if x != '' else None,
-                units='DEG',
-                conv_fn=None, override=True),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Stage', 'StageTb'),
+                dest_dict=self.em, dest_path=('General_EM', 'stage_position', 'tilt_beta'),
+                cast_fn=lambda x: float(x) if x != '' else None, units='DEG', conv_fn=None,
+                override=True),
 
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Scan', 'PixelWidth'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Scan', 'PixelWidth'),
                 dest_dict=self.em, dest_path=('SEM', 'pixel_width'),
-                cast_fn=lambda x: float(x) if x != '' else None,
-                units='M', conv_fn=None, override=False),
+                cast_fn=lambda x: float(x) if x != '' else None, units='M', conv_fn=None,
+                override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Scan', 'PixelHeight'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Scan', 'PixelHeight'),
                 dest_dict=self.em, dest_path=('SEM', 'pixel_height'),
-                cast_fn=lambda x: float(x) if x != '' else None,
-                units='M', conv_fn=None, override=False),
+                cast_fn=lambda x: float(x) if x != '' else None, units='M', conv_fn=None,
+                override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Scan', 'HorFieldsize'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Scan', 'HorFieldsize'),
                 dest_dict=self.em, dest_path=('SEM', 'horizontal_field_width'),
                 cast_fn=lambda x: float(x) if x != '' else None,
                 units='M', conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Scan', 'VerFieldsize'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Scan', 'VerFieldsize'),
                 dest_dict=self.em, dest_path=('SEM', 'vertical_field_width'),
                 cast_fn=lambda x: float(x) if x != '' else None,
                 units='M', conv_fn=None, override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Scan', 'FrameTime'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Scan', 'FrameTime'),
                 dest_dict=self.em, dest_path=('General_EM', 'frame_time'),
-                cast_fn=lambda x: float(x) if x else None, units='SEC',
-                conv_fn=None, override=False),
+                cast_fn=lambda x: float(x) if x else None, units='SEC', conv_fn=None,
+                override=False),
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Image', 'MagnificationMode'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Image',
+                                                        'MagnificationMode'),
                 dest_dict=self.em, dest_path=('SEM', 'magnification_mode'),
                 cast_fn=None, units=None, conv_fn=None, override=False),
             # confirmed in Quanta SEM manual that the pressure units are Pascals
             MappingElements(
-                source_dict=self.raw_meta,
-                source_path=('fei_metadata', 'Vacuum', 'ChPressure'),
+                source_dict=self.raw_meta, source_path=('fei_metadata', 'Vacuum', 'ChPressure'),
                 dest_dict=self.em, dest_path=('SEM', 'chamber_pressure'),
-                cast_fn=lambda x: float(x) if x else None, units='PA',
-                conv_fn=None, override=False)
+                cast_fn=lambda x: float(x) if x else None, units='PA', conv_fn=None, override=False)
         ]
         map_dict_values(mapping)
 
@@ -1248,4 +1077,11 @@ def implementors(self):
                 'Joshua Taillon <joshua.taillon@nist.gov>']
 
     def version(self):
-        return '0.1.0'
+        return '0.1.2'
+
+    @property
+    def schema(self) -> dict:
+        """Schema for the output of the parser"""
+        with open(pathlib.Path(__file__).parent / 'schemas' /
+                  'electron_microscopy.json') as f:
+            return json.load(f)
diff --git a/materials_io/schemas/electron_microscopy.json b/materials_io/schemas/electron_microscopy.json
index 9c3ec52..c619fd0 100644
--- a/materials_io/schemas/electron_microscopy.json
+++ b/materials_io/schemas/electron_microscopy.json
@@ -45,6 +45,20 @@
         }
       }
     },
+    "single_value_string_or_number_type": {
+      "type": "object",
+      "required": ["value"],
+      "additionalProperties": false,
+      "properties": {
+        "value": {
+          "oneOf": [
+            {"type": "number"},
+            {"type": "string"}
+          ]
+        },
+        "units": {"type": "string"}
+      }
+    },
     "single_value_boolean_type": {
       "type": "object",
       "required": ["value"],
@@ -356,12 +370,12 @@
           "description": "The total amount of time the beam exposed the sample during a data collection (the sum of all pixels' dwell times)"
         },
         "magnification_actual": {
-          "$ref": "#/definitions/single_value_number_type",
-          "description": "The actual calibrated magnification of the collected data"
+          "$ref": "#/definitions/single_value_string_or_number_type",
+          "description": "The actual calibrated magnification of the collected data. Preference is a number, but string values are accepted"
         },
         "magnification_indicated": {
-          "$ref": "#/definitions/single_value_number_type",
-          "description": "The magnification indicated by the acquisition software in this collected data"
+          "$ref": "#/definitions/single_value_string_or_number_type",
+          "description": "The magnification indicated by the acquisition software in this collected data. Preference is a number, but string values are accepted"
         },
         "microscope_name": {
           "$ref": "#/definitions/single_value_string_type",
@@ -419,15 +433,15 @@
         },
         "defocus": {
           "$ref": "#/definitions/single_value_number_type",
-          "description": "The focus shift (a length) of the objective lens used to acquire the data"
+          "description": "The focus shift (a length) of the objective lens from the focal point of the examined object used to acquire the data"
         },
         "spot_size": {
           "$ref": "#/definitions/single_value_integer_type",
-          "description": "A manufacturer-specific indication of the strength of the first condenser lens, which generally determines the diameter of the electron beam impinging on the sample"
+          "description": "A manufacturer-specific indication of the strength of the first condenser lens, which generally determines the diameter and current of the electron beam impinging on the sample"
         },
         "camera_length": {
           "$ref": "#/definitions/single_value_number_type",
-          "description": "The effective length between the sample and the imaging plane (controlled by projector lenses)"
+          "description": "The effective length between the sample and the back focal plane (controlled by projector lenses)"
         }
       }
     },
diff --git a/materials_io/utils/__init__.py b/materials_io/utils/__init__.py
index 0c8ffb2..35a3643 100644
--- a/materials_io/utils/__init__.py
+++ b/materials_io/utils/__init__.py
@@ -1,5 +1,7 @@
-from typing import Dict, Union, Tuple, Any, Callable, Optional, List
-from typing_extensions import TypedDict
+from typing import Dict, Union, Tuple, Any, Callable, Optional, List, TypedDict
+import logging
+
+logger = logging.getLogger(__name__)
 
 
 def get_nested_dict_value_by_path(nest_dict: Dict,
@@ -14,7 +16,8 @@ def get_nested_dict_value_by_path(nest_dict: Dict,
             get to a value within `nest_dict`. If a string, the value will
             return just from the first level (mostly for convenience)
         cast: A function that (if provided) will be applied to the value. This
-            helps with serialization.
+            helps with serialization. If it returns an error, the value will be returned as is
+            without conversion
 
     Returns:
         The value at the path within the nested dictionary; if there's no
@@ -36,7 +39,13 @@ def get_nested_dict_value_by_path(nest_dict: Dict,
         return None
 
     if cast is not None:
-        return cast(sub_dict)
+        # noinspection PyBroadException
+        try:
+            return cast(sub_dict)
+        except Exception as e:
+            logger.warning(f"Exception encountered when casting value using {cast}: {e}; returning "
+                           f"value as is without casting")
+            return sub_dict
     else:
         return sub_dict
 
@@ -109,7 +118,7 @@ def set_nested_dict_value_with_units(nest_dict: Dict, path: Tuple,
                              'units': Optional[Union[None, str]],
                              'conv_fn': Optional[Union[None, Callable]],
                              'override': Optional[bool]})
-"""TypedDict: A TypedDict to specify the exact types expected when creating a 
+"""TypedDict: A TypedDict to specify the exact types expected when creating a
 mapping dictionary to map metadata from one place to another.
 """
 
@@ -120,7 +129,7 @@ def map_dict_values(mapping: List[MappingElements]):
     Inspired by the implementation in :func:`hyperspy.io.dict2signal`
 
     For each mapping we need a source dict and destination dict, then for
-    eaqch term, the source path, the destination path, the cast function,
+    each term, the source path, the destination path, the cast function,
     the units to set, and potentially a conversion function
 
     Args:
diff --git a/materials_io/version.py b/materials_io/version.py
index af1d19e..31b4a72 100644
--- a/materials_io/version.py
+++ b/materials_io/version.py
@@ -1,3 +1,7 @@
+# we target 3.8+, so this should be okay without fallback to importlib_metadata
+import importlib.metadata
+
 # single source of truth for package version,
 # see https://packaging.python.org/en/latest/single_source_version/
-__version__ = "0.0.1"
+
+__version__ = importlib.metadata.version('materials_io')
diff --git a/poetry.lock b/poetry.lock
index 6811ec5..71b15fd 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,6 +1,14 @@
+[[package]]
+name = "alabaster"
+version = "0.7.12"
+description = "A configurable sidebar-enabled Sphinx theme"
+category = "dev"
+optional = false
+python-versions = "*"
+
 [[package]]
 name = "appnope"
-version = "0.1.2"
+version = "0.1.3"
 description = "Disable App Nap on macOS >= 10.9"
 category = "main"
 optional = true
@@ -22,6 +30,20 @@ scipy = "*"
 [package.extras]
 docs = ["sphinx", "sphinx-rtd-theme", "pillow"]
 
+[[package]]
+name = "asttokens"
+version = "2.0.5"
+description = "Annotate AST trees with source code positions"
+category = "main"
+optional = true
+python-versions = "*"
+
+[package.dependencies]
+six = "*"
+
+[package.extras]
+test = ["astroid", "pytest"]
+
 [[package]]
 name = "atomicwrites"
 version = "1.4.0"
@@ -44,6 +66,17 @@ docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
 tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"]
 tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"]
 
+[[package]]
+name = "babel"
+version = "2.9.1"
+description = "Internationalization utilities"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[package.dependencies]
+pytz = ">=2015.7"
+
 [[package]]
 name = "backcall"
 version = "0.2.0"
@@ -54,15 +87,15 @@ python-versions = "*"
 
 [[package]]
 name = "boto3"
-version = "1.20.37"
+version = "1.21.38"
 description = "The AWS SDK for Python"
 category = "main"
 optional = true
 python-versions = ">= 3.6"
 
 [package.dependencies]
-botocore = ">=1.23.37,<1.24.0"
-jmespath = ">=0.7.1,<1.0.0"
+botocore = ">=1.24.38,<1.25.0"
+jmespath = ">=0.7.1,<2.0.0"
 s3transfer = ">=0.5.0,<0.6.0"
 
 [package.extras]
@@ -70,19 +103,19 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
 
 [[package]]
 name = "botocore"
-version = "1.23.37"
+version = "1.24.38"
 description = "Low-level, data-driven core of boto 3."
 category = "main"
 optional = true
 python-versions = ">= 3.6"
 
 [package.dependencies]
-jmespath = ">=0.7.1,<1.0.0"
+jmespath = ">=0.7.1,<2.0.0"
 python-dateutil = ">=2.1,<3.0.0"
 urllib3 = ">=1.25.4,<1.27"
 
 [package.extras]
-crt = ["awscrt (==0.12.5)"]
+crt = ["awscrt (==0.13.8)"]
 
 [[package]]
 name = "cached-property"
@@ -116,12 +149,12 @@ name = "chardet"
 version = "4.0.0"
 description = "Universal encoding detector for Python 2 and 3"
 category = "main"
-optional = true
+optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
 [[package]]
 name = "charset-normalizer"
-version = "2.0.10"
+version = "2.0.12"
 description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
 category = "main"
 optional = false
@@ -132,15 +165,14 @@ unicode_backport = ["unicodedata2"]
 
 [[package]]
 name = "click"
-version = "8.0.3"
+version = "8.1.2"
 description = "Composable command line interface toolkit"
 category = "main"
 optional = true
-python-versions = ">=3.6"
+python-versions = ">=3.7"
 
 [package.dependencies]
 colorama = {version = "*", markers = "platform_system == \"Windows\""}
-importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
 
 [[package]]
 name = "cloudpickle"
@@ -160,11 +192,14 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
 [[package]]
 name = "coverage"
-version = "6.2"
+version = "6.3.2"
 description = "Code coverage measurement for Python"
 category = "main"
 optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
+
+[package.dependencies]
+tomli = {version = "*", optional = true, markers = "extra == \"toml\""}
 
 [package.extras]
 toml = ["tomli"]
@@ -187,7 +222,7 @@ yaml = ["PyYAML (>=3.10)"]
 
 [[package]]
 name = "cryptography"
-version = "36.0.1"
+version = "36.0.2"
 description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
 category = "main"
 optional = false
@@ -212,21 +247,13 @@ category = "main"
 optional = true
 python-versions = ">=3.6"
 
-[[package]]
-name = "cython"
-version = "0.29.26"
-description = "The Cython compiler for writing C extensions for the Python language."
-category = "main"
-optional = true
-python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
-
 [[package]]
 name = "dask"
-version = "2022.1.0"
+version = "2022.4.0"
 description = "Parallel PyData with Task Scheduling"
 category = "main"
 optional = true
-python-versions = ">=3.7"
+python-versions = ">=3.8"
 
 [package.dependencies]
 cloudpickle = ">=1.1.1"
@@ -239,19 +266,19 @@ toolz = ">=0.8.2"
 
 [package.extras]
 array = ["numpy (>=1.18)"]
-complete = ["bokeh (>=2.1.1)", "distributed (==2022.01.0)", "jinja2", "numpy (>=1.18)", "pandas (>=1.0)"]
+complete = ["bokeh (>=2.4.2)", "distributed (==2022.04.0)", "jinja2", "numpy (>=1.18)", "pandas (>=1.0)"]
 dataframe = ["numpy (>=1.18)", "pandas (>=1.0)"]
-diagnostics = ["bokeh (>=2.1.1)", "jinja2"]
-distributed = ["distributed (==2022.01.0)"]
+diagnostics = ["bokeh (>=2.4.2)", "jinja2"]
+distributed = ["distributed (==2022.04.0)"]
 test = ["pytest", "pytest-rerunfailures", "pytest-xdist", "pre-commit"]
 
 [[package]]
 name = "debugpy"
-version = "1.5.1"
+version = "1.6.0"
 description = "An implementation of the Debug Adapter Protocol for Python"
 category = "main"
 optional = true
-python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
+python-versions = ">=3.7"
 
 [[package]]
 name = "decorator"
@@ -285,6 +312,23 @@ pypif = ">=2.0.1,<3"
 [package.extras]
 report = ["requests"]
 
+[[package]]
+name = "diff-cover"
+version = "6.4.5"
+description = "Run coverage and linting reports on diffs"
+category = "dev"
+optional = false
+python-versions = ">=3.6.2,<4.0.0"
+
+[package.dependencies]
+chardet = ">=3.0.0"
+Jinja2 = ">=2.7.1"
+pluggy = ">=0.13.1,<2"
+Pygments = ">=2.9.0,<3.0.0"
+
+[package.extras]
+toml = ["tomli (>=1.2.1)"]
+
 [[package]]
 name = "dill"
 version = "0.3.4"
@@ -296,6 +340,14 @@ python-versions = ">=2.7, !=3.0.*"
 [package.extras]
 graph = ["objgraph (>=1.7.2)"]
 
+[[package]]
+name = "distlib"
+version = "0.3.4"
+description = "Distribution utilities"
+category = "dev"
+optional = false
+python-versions = "*"
+
 [[package]]
 name = "docopt"
 version = "0.6.2"
@@ -304,13 +356,21 @@ category = "dev"
 optional = false
 python-versions = "*"
 
+[[package]]
+name = "docutils"
+version = "0.17.1"
+description = "Docutils -- Python Documentation Utilities"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
 [[package]]
 name = "entrypoints"
-version = "0.3"
+version = "0.4"
 description = "Discover and load entry points from installed packages."
 category = "main"
 optional = true
-python-versions = ">=2.7"
+python-versions = ">=3.6"
 
 [[package]]
 name = "et-xmlfile"
@@ -320,6 +380,14 @@ category = "main"
 optional = true
 python-versions = ">=3.6"
 
+[[package]]
+name = "executing"
+version = "0.8.3"
+description = "Get the currently executing AST node of a frame, and other information"
+category = "main"
+optional = true
+python-versions = "*"
+
 [[package]]
 name = "fair-research-login"
 version = "0.2.6"
@@ -332,27 +400,38 @@ python-versions = "*"
 globus-sdk = "<4.0.0"
 six = "*"
 
+[[package]]
+name = "filelock"
+version = "3.6.0"
+description = "A platform independent file lock."
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+
+[package.extras]
+docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"]
+testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"]
+
 [[package]]
 name = "flake8"
-version = "4.0.1"
+version = "3.9.2"
 description = "the modular source code checker: pep8 pyflakes and co"
 category = "dev"
 optional = false
-python-versions = ">=3.6"
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
 
 [package.dependencies]
-importlib-metadata = {version = "<4.3", markers = "python_version < \"3.8\""}
 mccabe = ">=0.6.0,<0.7.0"
-pycodestyle = ">=2.8.0,<2.9.0"
-pyflakes = ">=2.4.0,<2.5.0"
+pycodestyle = ">=2.7.0,<2.8.0"
+pyflakes = ">=2.3.0,<2.4.0"
 
 [[package]]
 name = "fsspec"
-version = "2022.1.0"
+version = "2022.3.0"
 description = "File-system specification"
 category = "main"
 optional = true
-python-versions = ">=3.6"
+python-versions = ">=3.7"
 
 [package.extras]
 abfs = ["adlfs"]
@@ -375,6 +454,15 @@ s3 = ["s3fs"]
 sftp = ["paramiko"]
 smb = ["smbprotocol"]
 ssh = ["paramiko"]
+tqdm = ["tqdm"]
+
+[[package]]
+name = "future"
+version = "0.18.2"
+description = "Clean single-source support for Python 3 and 2"
+category = "main"
+optional = true
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
 
 [[package]]
 name = "globus-nexus-client"
@@ -389,7 +477,7 @@ globus-sdk = ">=3.0.0,<4"
 
 [[package]]
 name = "globus-sdk"
-version = "3.2.1"
+version = "3.7.0"
 description = "Globus SDK for Python"
 category = "main"
 optional = false
@@ -399,9 +487,10 @@ python-versions = ">=3.6"
 cryptography = ">=3.3.1,<3.4.0 || >3.4.0"
 pyjwt = {version = ">=2.0.0,<3.0.0", extras = ["crypto"]}
 requests = ">=2.19.1,<3.0.0"
+typing-extensions = {version = ">=4.0", markers = "python_version < \"3.10\""}
 
 [package.extras]
-dev = ["pytest (<7)", "pytest-cov (<3)", "pytest-xdist (<3)", "responses (==0.16.0)", "flake8 (<5)", "isort (<6)", "black (==21.12b0)", "flake8-bugbear (==21.11.29)", "mypy (==0.910)", "types-docutils", "types-jwt", "types-requests", "typing-extensions", "sphinx (<5)", "sphinx-issues (<2)", "furo (==2021.11.23)"]
+dev = ["pytest (<7)", "coverage (<7)", "pytest-xdist (<3)", "responses (==0.17.0)", "flake8 (<5)", "isort (<6)", "black (==21.12b0)", "flake8-bugbear (==21.11.29)", "mypy (==0.940)", "types-docutils", "types-jwt", "types-requests", "typing-extensions", "sphinx (<5)", "sphinx-issues (<3)", "furo (==2022.1.2)"]
 
 [[package]]
 name = "greenlet"
@@ -423,7 +512,6 @@ optional = true
 python-versions = ">=3.7"
 
 [package.dependencies]
-cached-property = {version = "*", markers = "python_version < \"3.8\""}
 numpy = ">=1.14.5"
 
 [[package]]
@@ -491,57 +579,79 @@ python-versions = "*"
 
 [[package]]
 name = "imageio"
-version = "2.9.0"
+version = "2.16.2"
 description = "Library for reading and writing a wide range of image, video, scientific, and volumetric data formats."
 category = "main"
 optional = true
-python-versions = ">=3.5"
+python-versions = ">=3.7"
 
 [package.dependencies]
-numpy = "*"
-pillow = "*"
+numpy = ">=1.20.0"
+pillow = ">=8.3.2"
 
 [package.extras]
-ffmpeg = ["imageio-ffmpeg"]
+build = ["wheel"]
+dev = ["invoke", "pytest", "pytest-cov", "fsspec", "black", "flake8"]
+docs = ["sphinx", "numpydoc", "pydata-sphinx-theme"]
+ffmpeg = ["imageio-ffmpeg", "psutil"]
 fits = ["astropy"]
-full = ["astropy", "gdal", "imageio-ffmpeg", "itk"]
+full = ["astropy", "black", "flake8", "fsspec", "gdal", "imageio-ffmpeg", "invoke", "itk", "numpydoc", "psutil", "pydata-sphinx-theme", "pytest", "pytest-cov", "sphinx", "tifffile", "wheel"]
 gdal = ["gdal"]
 itk = ["itk"]
+linting = ["black", "flake8"]
+test = ["invoke", "pytest", "pytest-cov", "fsspec"]
+tifffile = ["tifffile"]
+
+[[package]]
+name = "imagesize"
+version = "1.3.0"
+description = "Getting image size from png/jpeg/jpeg2000/gif file"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
 [[package]]
 name = "importlib-metadata"
-version = "4.2.0"
+version = "4.11.3"
 description = "Read metadata from Python packages"
 category = "main"
 optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
 
 [package.dependencies]
-typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
 zipp = ">=0.5"
 
 [package.extras]
-docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
-testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"]
+docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
+perf = ["ipython"]
+testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"]
 
 [[package]]
 name = "importlib-resources"
-version = "5.4.0"
+version = "5.6.0"
 description = "Read resources from Python packages"
 category = "main"
 optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
 
 [package.dependencies]
 zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""}
 
 [package.extras]
-docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
-testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"]
+docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
+testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"]
+
+[[package]]
+name = "iniconfig"
+version = "1.1.1"
+description = "iniconfig: brain-dead simple config-ini parsing"
+category = "main"
+optional = false
+python-versions = "*"
 
 [[package]]
 name = "ipykernel"
-version = "6.7.0"
+version = "6.13.0"
 description = "IPython Kernel for Jupyter"
 category = "main"
 optional = true
@@ -549,20 +659,22 @@ python-versions = ">=3.7"
 
 [package.dependencies]
 appnope = {version = "*", markers = "platform_system == \"Darwin\""}
-debugpy = ">=1.0.0,<2.0"
+debugpy = ">=1.0"
 ipython = ">=7.23.1"
-jupyter-client = "<8.0"
-matplotlib-inline = ">=0.1.0,<0.2.0"
+jupyter-client = ">=6.1.12"
+matplotlib-inline = ">=0.1"
 nest-asyncio = "*"
-tornado = ">=4.2,<7.0"
-traitlets = ">=5.1.0,<6.0"
+packaging = "*"
+psutil = "*"
+tornado = ">=6.1"
+traitlets = ">=5.1.0"
 
 [package.extras]
-test = ["pytest (!=5.3.4)", "pytest-cov", "flaky", "ipyparallel"]
+test = ["pytest (>=6.0)", "pytest-cov", "flaky", "ipyparallel", "pre-commit", "pytest-timeout"]
 
 [[package]]
 name = "ipyparallel"
-version = "8.1.0"
+version = "8.2.1"
 description = "Interactive Parallel Computing with IPython"
 category = "main"
 optional = true
@@ -591,11 +703,11 @@ test = ["pytest", "pytest-cov", "pytest-asyncio", "pytest-tornado", "ipython", "
 
 [[package]]
 name = "ipython"
-version = "7.31.0"
+version = "8.2.0"
 description = "IPython: Productive Interactive Computing"
 category = "main"
 optional = true
-python-versions = ">=3.7"
+python-versions = ">=3.8"
 
 [package.dependencies]
 appnope = {version = "*", markers = "sys_platform == \"darwin\""}
@@ -607,19 +719,22 @@ matplotlib-inline = "*"
 pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""}
 pickleshare = "*"
 prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0"
-pygments = "*"
-traitlets = ">=4.2"
+pygments = ">=2.4.0"
+stack-data = "*"
+traitlets = ">=5"
 
 [package.extras]
-all = ["Sphinx (>=1.3)", "ipykernel", "ipyparallel", "ipywidgets", "nbconvert", "nbformat", "nose (>=0.10.1)", "notebook", "numpy (>=1.17)", "pygments", "qtconsole", "requests", "testpath"]
+all = ["black", "Sphinx (>=1.3)", "ipykernel", "nbconvert", "nbformat", "ipywidgets", "notebook", "ipyparallel", "qtconsole", "pytest (<7.1)", "pytest-asyncio", "testpath", "curio", "matplotlib (!=3.2.0)", "numpy (>=1.19)", "pandas", "trio"]
+black = ["black"]
 doc = ["Sphinx (>=1.3)"]
 kernel = ["ipykernel"]
 nbconvert = ["nbconvert"]
 nbformat = ["nbformat"]
-notebook = ["notebook", "ipywidgets"]
+notebook = ["ipywidgets", "notebook"]
 parallel = ["ipyparallel"]
 qtconsole = ["qtconsole"]
-test = ["nose (>=0.10.1)", "requests", "testpath", "pygments", "nbformat", "ipykernel", "numpy (>=1.17)"]
+test = ["pytest (<7.1)", "pytest-asyncio", "testpath"]
+test_extra = ["pytest (<7.1)", "pytest-asyncio", "testpath", "curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.19)", "pandas", "trio"]
 
 [[package]]
 name = "isodate"
@@ -647,13 +762,27 @@ parso = ">=0.8.0,<0.9.0"
 qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
 testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"]
 
+[[package]]
+name = "jinja2"
+version = "3.1.1"
+description = "A very fast and expressive template engine."
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+
+[package.dependencies]
+MarkupSafe = ">=2.0"
+
+[package.extras]
+i18n = ["Babel (>=2.7)"]
+
 [[package]]
 name = "jmespath"
-version = "0.10.0"
+version = "1.0.0"
 description = "JSON Matching Expressions"
 category = "main"
 optional = true
-python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+python-versions = ">=3.7"
 
 [[package]]
 name = "jsonlines"
@@ -665,7 +794,6 @@ python-versions = ">=3.6"
 
 [package.dependencies]
 attrs = ">=19.2.0"
-typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
 
 [[package]]
 name = "jsonschema"
@@ -677,10 +805,8 @@ python-versions = ">=3.7"
 
 [package.dependencies]
 attrs = ">=17.4.0"
-importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
 importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""}
 pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2"
-typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
 
 [package.extras]
 format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"]
@@ -688,28 +814,28 @@ format_nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-
 
 [[package]]
 name = "jupyter-client"
-version = "7.1.1"
+version = "7.2.2"
 description = "Jupyter protocol implementation and client libraries"
 category = "main"
 optional = true
-python-versions = ">=3.6.1"
+python-versions = ">=3.7"
 
 [package.dependencies]
 entrypoints = "*"
-jupyter-core = ">=4.6.0"
-nest-asyncio = ">=1.5"
-python-dateutil = ">=2.1"
-pyzmq = ">=13"
-tornado = ">=4.1"
+jupyter-core = ">=4.9.2"
+nest-asyncio = ">=1.5.4"
+python-dateutil = ">=2.8.2"
+pyzmq = ">=22.3"
+tornado = ">=6.0"
 traitlets = "*"
 
 [package.extras]
-doc = ["myst-parser", "sphinx (>=1.3.6)", "sphinx-rtd-theme", "sphinxcontrib-github-alt"]
-test = ["codecov", "coverage", "ipykernel", "ipython", "mock", "mypy", "pre-commit", "pytest", "pytest-asyncio", "pytest-cov", "pytest-timeout", "jedi (<0.18)"]
+doc = ["ipykernel", "myst-parser", "sphinx (>=1.3.6)", "sphinx-rtd-theme", "sphinxcontrib-github-alt"]
+test = ["codecov", "coverage", "ipykernel (>=6.5)", "ipython", "mypy", "pre-commit", "pytest", "pytest-asyncio (>=0.18)", "pytest-cov", "pytest-timeout"]
 
 [[package]]
 name = "jupyter-core"
-version = "4.9.1"
+version = "4.9.2"
 description = "Jupyter core package. A base package on which Jupyter projects rely."
 category = "main"
 optional = true
@@ -721,12 +847,23 @@ traitlets = "*"
 
 [[package]]
 name = "kiwisolver"
-version = "1.3.2"
+version = "1.4.2"
 description = "A fast implementation of the Cassowary constraint solver"
 category = "main"
 optional = true
 python-versions = ">=3.7"
 
+[[package]]
+name = "latexcodec"
+version = "2.0.1"
+description = "A lexer and codec to work with LaTeX code in Python."
+category = "main"
+optional = true
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[package.dependencies]
+six = ">=1.4.1"
+
 [[package]]
 name = "linear-tsv"
 version = "1.1.0"
@@ -743,11 +880,11 @@ develop = ["tox"]
 
 [[package]]
 name = "llvmlite"
-version = "0.34.0"
+version = "0.38.0"
 description = "lightweight wrapper around basic LLVM functionality"
 category = "main"
-optional = true
-python-versions = ">=3.6"
+optional = false
+python-versions = ">=3.7,<3.11"
 
 [[package]]
 name = "locket"
@@ -757,6 +894,14 @@ category = "main"
 optional = true
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
+[[package]]
+name = "markupsafe"
+version = "2.1.1"
+description = "Safely add untrusted strings to HTML/XML markup."
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+
 [[package]]
 name = "matplotlib"
 version = "3.4.3"
@@ -809,7 +954,7 @@ requests = ">=2.26.0"
 
 [[package]]
 name = "monty"
-version = "2022.1.12.1"
+version = "2022.3.12"
 description = "Monty is the missing complement to Python."
 category = "main"
 optional = true
@@ -818,14 +963,6 @@ python-versions = ">=3.5"
 [package.extras]
 yaml = ["ruamel.yaml"]
 
-[[package]]
-name = "more-itertools"
-version = "8.12.0"
-description = "More routines for operating on iterables, beyond itertools"
-category = "main"
-optional = false
-python-versions = ">=3.5"
-
 [[package]]
 name = "mpmath"
 version = "1.2.1"
@@ -840,7 +977,7 @@ tests = ["pytest (>=4.6)"]
 
 [[package]]
 name = "natsort"
-version = "8.0.2"
+version = "8.1.0"
 description = "Simple yet flexible natural sorting in Python."
 category = "main"
 optional = true
@@ -852,7 +989,7 @@ icu = ["PyICU (>=1.0.0)"]
 
 [[package]]
 name = "nest-asyncio"
-version = "1.5.4"
+version = "1.5.5"
 description = "Patch asyncio to allow nested event loops"
 category = "main"
 optional = true
@@ -860,30 +997,30 @@ python-versions = ">=3.5"
 
 [[package]]
 name = "networkx"
-version = "2.6.3"
+version = "2.8"
 description = "Python package for creating and manipulating graphs and networks"
 category = "main"
 optional = true
-python-versions = ">=3.7"
+python-versions = ">=3.8"
 
 [package.extras]
-default = ["numpy (>=1.19)", "scipy (>=1.5,!=1.6.1)", "matplotlib (>=3.3)", "pandas (>=1.1)"]
-developer = ["black (==21.5b1)", "pre-commit (>=2.12)"]
-doc = ["sphinx (>=4.0,<5.0)", "pydata-sphinx-theme (>=0.6,<1.0)", "sphinx-gallery (>=0.9,<1.0)", "numpydoc (>=1.1)", "pillow (>=8.2)", "nb2plots (>=0.6)", "texext (>=0.6.6)"]
-extra = ["lxml (>=4.5)", "pygraphviz (>=1.7)", "pydot (>=1.4.1)"]
-test = ["pytest (>=6.2)", "pytest-cov (>=2.12)", "codecov (>=2.1)"]
+default = ["numpy (>=1.19)", "scipy (>=1.8)", "matplotlib (>=3.4)", "pandas (>=1.3)"]
+developer = ["pre-commit (>=2.18)", "mypy (>=0.942)"]
+doc = ["sphinx (>=4.5)", "pydata-sphinx-theme (>=0.8.1)", "sphinx-gallery (>=0.10)", "numpydoc (>=1.2)", "pillow (>=9.1)", "nb2plots (>=0.6)", "texext (>=0.6.6)"]
+extra = ["lxml (>=4.6)", "pygraphviz (>=1.9)", "pydot (>=1.4.2)", "sympy (>=1.10)"]
+test = ["pytest (>=7.1)", "pytest-cov (>=3.0)", "codecov (>=2.1)"]
 
 [[package]]
 name = "numba"
-version = "0.51.2"
+version = "0.55.1"
 description = "compiling Python code using LLVM"
 category = "main"
-optional = true
-python-versions = ">=3.6"
+optional = false
+python-versions = ">=3.7,<3.11"
 
 [package.dependencies]
-llvmlite = ">=0.34.0.dev0,<0.35"
-numpy = ">=1.15"
+llvmlite = ">=0.38.0rc1,<0.39"
+numpy = ">=1.18,<1.22"
 
 [[package]]
 name = "numexpr"
@@ -899,11 +1036,11 @@ packaging = "*"
 
 [[package]]
 name = "numpy"
-version = "1.21.1"
+version = "1.21.5"
 description = "NumPy is the fundamental package for array computing with Python."
 category = "main"
-optional = true
-python-versions = ">=3.7"
+optional = false
+python-versions = ">=3.7,<3.11"
 
 [[package]]
 name = "openpyxl"
@@ -921,7 +1058,7 @@ name = "packaging"
 version = "21.3"
 description = "Core utilities for Python packages"
 category = "main"
-optional = true
+optional = false
 python-versions = ">=3.6"
 
 [package.dependencies]
@@ -937,19 +1074,24 @@ python-versions = "*"
 
 [[package]]
 name = "pandas"
-version = "1.1.5"
+version = "1.4.2"
 description = "Powerful data structures for data analysis, time series, and statistics"
 category = "main"
-optional = true
-python-versions = ">=3.6.1"
+optional = false
+python-versions = ">=3.8"
 
 [package.dependencies]
-numpy = ">=1.15.4"
-python-dateutil = ">=2.7.3"
-pytz = ">=2017.2"
+numpy = [
+    {version = ">=1.18.5", markers = "platform_machine != \"aarch64\" and platform_machine != \"arm64\" and python_version < \"3.10\""},
+    {version = ">=1.19.2", markers = "platform_machine == \"aarch64\" and python_version < \"3.10\""},
+    {version = ">=1.20.0", markers = "platform_machine == \"arm64\" and python_version < \"3.10\""},
+    {version = ">=1.21.0", markers = "python_version >= \"3.10\""},
+]
+python-dateutil = ">=2.8.1"
+pytz = ">=2020.1"
 
 [package.extras]
-test = ["pytest (>=4.0.2)", "pytest-xdist", "hypothesis (>=3.58)"]
+test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"]
 
 [[package]]
 name = "parso"
@@ -980,7 +1122,7 @@ complete = ["numpy (>=1.9.0)", "pandas (>=0.19.0)", "pyzmq", "blosc"]
 
 [[package]]
 name = "pbr"
-version = "5.8.0"
+version = "5.8.1"
 description = "Python Build Reasonableness"
 category = "main"
 optional = false
@@ -1007,28 +1149,52 @@ python-versions = "*"
 
 [[package]]
 name = "pillow"
-version = "7.2.0"
+version = "9.1.0"
 description = "Python Imaging Library (Fork)"
 category = "main"
 optional = true
-python-versions = ">=3.5"
+python-versions = ">=3.7"
+
+[package.extras]
+docs = ["olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinx-rtd-theme (>=1.0)", "sphinxext-opengraph"]
+tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
 
 [[package]]
 name = "pint"
-version = "0.18"
+version = "0.19.1"
 description = "Physical quantities module"
 category = "main"
 optional = true
-python-versions = ">=3.7"
-
-[package.dependencies]
-importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
-packaging = "*"
+python-versions = ">=3.8"
 
 [package.extras]
-numpy = ["numpy (>=1.17)"]
+numpy = ["numpy (>=1.19.5)"]
 test = ["pytest", "pytest-mpl", "pytest-cov", "pytest-subtests"]
-uncertainties = ["uncertainties (>=3.0)"]
+uncertainties = ["uncertainties (>=3.1.6)"]
+
+[[package]]
+name = "platformdirs"
+version = "2.5.1"
+description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+
+[package.extras]
+docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
+test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
+
+[[package]]
+name = "plotly"
+version = "5.7.0"
+description = "An open-source, interactive data visualization library for Python"
+category = "main"
+optional = true
+python-versions = ">=3.6"
+
+[package.dependencies]
+six = "*"
+tenacity = ">=6.2.0"
 
 [[package]]
 name = "pluggy"
@@ -1038,23 +1204,19 @@ category = "main"
 optional = false
 python-versions = ">=3.6"
 
-[package.dependencies]
-importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
-
 [package.extras]
 dev = ["pre-commit", "tox"]
 testing = ["pytest", "pytest-benchmark"]
 
 [[package]]
 name = "prettytable"
-version = "3.0.0"
+version = "3.2.0"
 description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format"
 category = "main"
 optional = true
 python-versions = ">=3.7"
 
 [package.dependencies]
-importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
 wcwidth = "*"
 
 [package.extras]
@@ -1062,7 +1224,7 @@ tests = ["pytest", "pytest-cov", "pytest-lazy-fixture"]
 
 [[package]]
 name = "prompt-toolkit"
-version = "3.0.24"
+version = "3.0.29"
 description = "Library for building powerful interactive command lines in Python"
 category = "main"
 optional = true
@@ -1090,6 +1252,17 @@ category = "main"
 optional = true
 python-versions = "*"
 
+[[package]]
+name = "pure-eval"
+version = "0.2.2"
+description = "Safely evaluate AST nodes without side effects"
+category = "main"
+optional = true
+python-versions = "*"
+
+[package.extras]
+tests = ["pytest"]
+
 [[package]]
 name = "py"
 version = "1.11.0"
@@ -1098,16 +1271,31 @@ category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
+[[package]]
+name = "pybtex"
+version = "0.24.0"
+description = "A BibTeX-compatible bibliography processor in Python"
+category = "main"
+optional = true
+python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*"
+
+[package.dependencies]
+latexcodec = ">=1.0.4"
+PyYAML = ">=3.01"
+six = "*"
+
+[package.extras]
+test = ["pytest"]
+
 [[package]]
 name = "pycalphad"
-version = "0.9.2"
+version = "0.10.0"
 description = "CALPHAD tools for designing thermodynamic models, calculating phase diagrams and investigating phase equilibria."
 category = "main"
 optional = true
 python-versions = "*"
 
 [package.dependencies]
-Cython = ">=0.24"
 importlib-metadata = "*"
 matplotlib = ">=3.3"
 numpy = ">=1.13"
@@ -1116,18 +1304,17 @@ pytest = "*"
 pytest-cov = "*"
 scipy = "*"
 setuptools-scm = {version = ">=6.0", extras = ["toml"]}
-symengine = "0.7.2"
-sympy = "1.8"
+symengine = "0.9.0"
 tinydb = ">=3.8"
 xarray = ">=0.11.2"
 
 [[package]]
 name = "pycodestyle"
-version = "2.8.0"
+version = "2.7.0"
 description = "Python style guide checker"
 category = "dev"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
 [[package]]
 name = "pycparser"
@@ -1137,17 +1324,9 @@ category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
-[[package]]
-name = "pydispatcher"
-version = "2.0.5"
-description = "Multi-producer-multi-consumer signal dispatching mechanism"
-category = "main"
-optional = true
-python-versions = "*"
-
 [[package]]
 name = "pyflakes"
-version = "2.4.0"
+version = "2.3.1"
 description = "passive checker of Python programs"
 category = "dev"
 optional = false
@@ -1158,7 +1337,7 @@ name = "pygments"
 version = "2.11.2"
 description = "Pygments is a syntax highlighting package written in Python."
 category = "main"
-optional = true
+optional = false
 python-versions = ">=3.5"
 
 [[package]]
@@ -1180,44 +1359,45 @@ tests = ["pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)"]
 
 [[package]]
 name = "pymatgen"
-version = "2018.12.12"
+version = "2022.3.29"
 description = "Python Materials Genomics is a robust materials analysis code that defines core object representations for structures and molecules with support for many electronic structure codes. It is currently the core analysis code powering the Materials Project (https://www.materialsproject.org)."
 category = "main"
 optional = true
-python-versions = "*"
+python-versions = ">=3.8"
 
 [package.dependencies]
 matplotlib = ">=1.5"
-monty = ">=0.9.6"
-networkx = ">=2.1"
-numpy = ">=1.14.3"
-palettable = ">=2.1.1"
+monty = ">=3.0.2"
+networkx = ">=2.2"
+numpy = ">=1.20.1"
+palettable = ">=3.1.1"
 pandas = "*"
-pydispatcher = ">=2.0.5"
+plotly = ">=4.5.0"
+pybtex = "*"
 requests = "*"
 "ruamel.yaml" = ">=0.15.6"
-scipy = ">=1.0.1"
-six = "*"
+scipy = ">=1.5.0"
 spglib = ">=1.9.9.44"
 sympy = "*"
 tabulate = "*"
+tqdm = "*"
+uncertainties = ">=3.1.4"
 
 [package.extras]
-abinit = ["apscheduler (==2.1.0)"]
+abinit = ["netcdf4"]
 ase = ["ase (>=3.3)"]
-provenance = ["pybtex"]
 vis = ["vtk (>=6.0.0)"]
 
 [[package]]
 name = "pyparsing"
-version = "3.0.6"
-description = "Python parsing module"
+version = "3.0.8"
+description = "pyparsing module - Classes and methods to define and execute parsing grammars"
 category = "main"
-optional = true
-python-versions = ">=3.6"
+optional = false
+python-versions = ">=3.6.8"
 
 [package.extras]
-diagrams = ["jinja2", "railroad-diagrams"]
+diagrams = ["railroad-diagrams", "jinja2"]
 
 [[package]]
 name = "pypif"
@@ -1241,42 +1421,46 @@ python-versions = ">=3.7"
 
 [[package]]
 name = "pytest"
-version = "3.10.1"
+version = "7.1.1"
 description = "pytest: simple powerful testing with Python"
 category = "main"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=3.7"
 
 [package.dependencies]
-atomicwrites = ">=1.0"
-attrs = ">=17.4.0"
+atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
+attrs = ">=19.2.0"
 colorama = {version = "*", markers = "sys_platform == \"win32\""}
-more-itertools = ">=4.0.0"
-pluggy = ">=0.7"
-py = ">=1.5.0"
-six = ">=1.10.0"
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<2.0"
+py = ">=1.8.2"
+tomli = ">=1.0.0"
+
+[package.extras]
+testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
 
 [[package]]
 name = "pytest-cov"
-version = "2.9.0"
+version = "3.0.0"
 description = "Pytest plugin for measuring coverage."
 category = "main"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+python-versions = ">=3.6"
 
 [package.dependencies]
-coverage = ">=4.4"
-pytest = ">=3.6"
+coverage = {version = ">=5.2.1", extras = ["toml"]}
+pytest = ">=4.6"
 
 [package.extras]
-testing = ["fields", "hunter", "process-tests (==2.0.2)", "six", "pytest-xdist", "virtualenv"]
+testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"]
 
 [[package]]
 name = "python-dateutil"
 version = "2.8.2"
 description = "Extensions to the standard Python datetime module"
 category = "main"
-optional = true
+optional = false
 python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
 
 [package.dependencies]
@@ -1284,7 +1468,7 @@ six = ">=1.5"
 
 [[package]]
 name = "python-magic"
-version = "0.4.24"
+version = "0.4.25"
 description = "File type identification using libmagic"
 category = "main"
 optional = true
@@ -1292,15 +1476,15 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
 [[package]]
 name = "pytz"
-version = "2021.3"
+version = "2022.1"
 description = "World timezone definitions, modern and historical"
 category = "main"
-optional = true
+optional = false
 python-versions = "*"
 
 [[package]]
 name = "pywavelets"
-version = "1.2.0"
+version = "1.3.0"
 description = "PyWavelets, wavelet transform module"
 category = "main"
 optional = true
@@ -1368,7 +1552,7 @@ idna2008 = ["idna"]
 
 [[package]]
 name = "ruamel.yaml"
-version = "0.17.20"
+version = "0.17.21"
 description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order"
 category = "main"
 optional = true
@@ -1391,7 +1575,7 @@ python-versions = ">=3.5"
 
 [[package]]
 name = "s3transfer"
-version = "0.5.0"
+version = "0.5.2"
 description = "An Amazon S3 Transfer Manager"
 category = "main"
 optional = true
@@ -1405,7 +1589,7 @@ crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"]
 
 [[package]]
 name = "scikit-image"
-version = "0.19.1"
+version = "0.19.2"
 description = "Image processing in Python"
 category = "main"
 optional = true
@@ -1429,18 +1613,18 @@ test = ["asv", "codecov", "flake8", "matplotlib (>=3.0.3)", "pooch (>=1.3.0)", "
 
 [[package]]
 name = "scipy"
-version = "1.6.1"
+version = "1.8.0"
 description = "SciPy: Scientific Library for Python"
 category = "main"
 optional = true
-python-versions = ">=3.7"
+python-versions = ">=3.8,<3.11"
 
 [package.dependencies]
-numpy = ">=1.16.5"
+numpy = ">=1.17.3,<1.25.0"
 
 [[package]]
 name = "setuptools-scm"
-version = "6.4.1"
+version = "6.4.2"
 description = "the blessed package to manage your versions by scm tags"
 category = "main"
 optional = true
@@ -1462,6 +1646,14 @@ category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
 
+[[package]]
+name = "snowballstemmer"
+version = "2.2.0"
+description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
+category = "dev"
+optional = false
+python-versions = "*"
+
 [[package]]
 name = "sparse"
 version = "0.13.0"
@@ -1492,9 +1684,127 @@ python-versions = "*"
 [package.dependencies]
 numpy = "*"
 
+[[package]]
+name = "sphinx"
+version = "4.5.0"
+description = "Python documentation generator"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+alabaster = ">=0.7,<0.8"
+babel = ">=1.3"
+colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""}
+docutils = ">=0.14,<0.18"
+imagesize = "*"
+importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""}
+Jinja2 = ">=2.3"
+packaging = "*"
+Pygments = ">=2.0"
+requests = ">=2.5.0"
+snowballstemmer = ">=1.1"
+sphinxcontrib-applehelp = "*"
+sphinxcontrib-devhelp = "*"
+sphinxcontrib-htmlhelp = ">=2.0.0"
+sphinxcontrib-jsmath = "*"
+sphinxcontrib-qthelp = "*"
+sphinxcontrib-serializinghtml = ">=1.1.5"
+
+[package.extras]
+docs = ["sphinxcontrib-websupport"]
+lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.931)", "docutils-stubs", "types-typed-ast", "types-requests"]
+test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"]
+
+[[package]]
+name = "sphinx-rtd-theme"
+version = "1.0.0"
+description = "Read the Docs theme for Sphinx"
+category = "dev"
+optional = false
+python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
+
+[package.dependencies]
+docutils = "<0.18"
+sphinx = ">=1.6"
+
+[package.extras]
+dev = ["transifex-client", "sphinxcontrib-httpdomain", "bump2version"]
+
+[[package]]
+name = "sphinxcontrib-applehelp"
+version = "1.0.2"
+description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books"
+category = "dev"
+optional = false
+python-versions = ">=3.5"
+
+[package.extras]
+lint = ["flake8", "mypy", "docutils-stubs"]
+test = ["pytest"]
+
+[[package]]
+name = "sphinxcontrib-devhelp"
+version = "1.0.2"
+description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document."
+category = "dev"
+optional = false
+python-versions = ">=3.5"
+
+[package.extras]
+lint = ["flake8", "mypy", "docutils-stubs"]
+test = ["pytest"]
+
+[[package]]
+name = "sphinxcontrib-htmlhelp"
+version = "2.0.0"
+description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.extras]
+lint = ["flake8", "mypy", "docutils-stubs"]
+test = ["pytest", "html5lib"]
+
+[[package]]
+name = "sphinxcontrib-jsmath"
+version = "1.0.1"
+description = "A sphinx extension which renders display math in HTML via JavaScript"
+category = "dev"
+optional = false
+python-versions = ">=3.5"
+
+[package.extras]
+test = ["pytest", "flake8", "mypy"]
+
+[[package]]
+name = "sphinxcontrib-qthelp"
+version = "1.0.3"
+description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document."
+category = "dev"
+optional = false
+python-versions = ">=3.5"
+
+[package.extras]
+lint = ["flake8", "mypy", "docutils-stubs"]
+test = ["pytest"]
+
+[[package]]
+name = "sphinxcontrib-serializinghtml"
+version = "1.1.5"
+description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)."
+category = "dev"
+optional = false
+python-versions = ">=3.5"
+
+[package.extras]
+lint = ["flake8", "mypy", "docutils-stubs"]
+test = ["pytest"]
+
 [[package]]
 name = "sqlalchemy"
-version = "1.4.29"
+version = "1.4.35"
 description = "Database Abstraction Library"
 category = "main"
 optional = true
@@ -1502,13 +1812,12 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
 
 [package.dependencies]
 greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"}
-importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
 
 [package.extras]
 aiomysql = ["greenlet (!=0.4.17)", "aiomysql"]
 aiosqlite = ["typing_extensions (!=3.10.0.1)", "greenlet (!=0.4.17)", "aiosqlite"]
 asyncio = ["greenlet (!=0.4.17)"]
-asyncmy = ["greenlet (!=0.4.17)", "asyncmy (>=0.2.3)"]
+asyncmy = ["greenlet (!=0.4.17)", "asyncmy (>=0.2.3,!=0.2.4)"]
 mariadb_connector = ["mariadb (>=1.0.1)"]
 mssql = ["pyodbc"]
 mssql_pymssql = ["pymssql"]
@@ -1525,33 +1834,48 @@ postgresql_psycopg2cffi = ["psycopg2cffi"]
 pymysql = ["pymysql (<1)", "pymysql"]
 sqlcipher = ["sqlcipher3-binary"]
 
+[[package]]
+name = "stack-data"
+version = "0.2.0"
+description = "Extract data from python stack frames and tracebacks for informative displays"
+category = "main"
+optional = true
+python-versions = "*"
+
+[package.dependencies]
+asttokens = "*"
+executing = "*"
+pure-eval = "*"
+
+[package.extras]
+tests = ["pytest", "typeguard", "pygments", "littleutils", "cython"]
+
 [[package]]
 name = "stevedore"
-version = "1.32.0"
+version = "3.5.0"
 description = "Manage dynamic plugins for Python applications"
 category = "main"
 optional = false
-python-versions = "*"
+python-versions = ">=3.6"
 
 [package.dependencies]
 pbr = ">=2.0.0,<2.1.0 || >2.1.0"
-six = ">=1.10.0"
 
 [[package]]
 name = "symengine"
-version = "0.7.2"
+version = "0.9.0"
 description = "Python library providing wrappers to SymEngine"
 category = "main"
 optional = true
-python-versions = ">=3.6.*,<4"
+python-versions = ">=3.7,<4"
 
 [[package]]
 name = "sympy"
-version = "1.8"
+version = "1.10.1"
 description = "Computer algebra system (CAS) in Python"
 category = "main"
 optional = true
-python-versions = ">=3.6"
+python-versions = ">=3.7"
 
 [package.dependencies]
 mpmath = ">=0.19"
@@ -1619,37 +1943,53 @@ develop = ["mock", "pylama", "pytest", "pytest-cov", "moto"]
 html = ["pyquery (<1.4.2)"]
 ods = ["ezodf (>=0.3)", "lxml (>=3.0)"]
 
+[[package]]
+name = "tenacity"
+version = "8.0.1"
+description = "Retry code until it succeeds"
+category = "main"
+optional = true
+python-versions = ">=3.6"
+
+[package.extras]
+doc = ["reno", "sphinx", "tornado (>=4.5)"]
+
 [[package]]
 name = "tifffile"
-version = "2021.11.2"
+version = "2022.4.8"
 description = "Read and write TIFF files"
 category = "main"
 optional = true
-python-versions = ">=3.7"
+python-versions = ">=3.8"
 
 [package.dependencies]
-numpy = ">=1.15.1"
+numpy = ">=1.19.2"
 
 [package.extras]
-all = ["imagecodecs (>=2021.7.30)", "matplotlib (>=3.2)", "lxml"]
+all = ["imagecodecs (>=2021.11.20)", "matplotlib (>=3.3)", "lxml"]
 
 [[package]]
 name = "tinydb"
-version = "4.6.1"
+version = "4.7.0"
 description = "TinyDB is a tiny, document oriented database optimized for your happiness :)"
 category = "main"
 optional = true
 python-versions = ">=3.6,<4.0"
 
-[package.dependencies]
-typing-extensions = {version = ">=3.10.0,<5.0.0", markers = "python_version <= \"3.7\""}
+[[package]]
+name = "toml"
+version = "0.10.2"
+description = "Python Library for Tom's Obvious, Minimal Language"
+category = "dev"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
 
 [[package]]
 name = "tomli"
-version = "2.0.0"
+version = "2.0.1"
 description = "A lil' TOML parser"
 category = "main"
-optional = true
+optional = false
 python-versions = ">=3.7"
 
 [[package]]
@@ -1668,9 +2008,31 @@ category = "main"
 optional = true
 python-versions = ">= 3.5"
 
+[[package]]
+name = "tox"
+version = "3.25.0"
+description = "tox is a generic virtualenv management and test command line tool"
+category = "dev"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
+
+[package.dependencies]
+colorama = {version = ">=0.4.1", markers = "platform_system == \"Windows\""}
+filelock = ">=3.0.0"
+packaging = ">=14"
+pluggy = ">=0.12.0"
+py = ">=1.4.17"
+six = ">=1.14.0"
+toml = ">=0.9.4"
+virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2,<20.0.3 || >20.0.3,<20.0.4 || >20.0.4,<20.0.5 || >20.0.5,<20.0.6 || >20.0.6,<20.0.7 || >20.0.7"
+
+[package.extras]
+docs = ["pygments-github-lexers (>=0.0.5)", "sphinx (>=2.0.0)", "sphinxcontrib-autoprogram (>=0.1.5)", "towncrier (>=18.5.0)"]
+testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)", "psutil (>=5.6.1)", "pathlib2 (>=2.3.3)"]
+
 [[package]]
 name = "tqdm"
-version = "4.62.3"
+version = "4.64.0"
 description = "Fast, Extensible Progress Meter"
 category = "main"
 optional = true
@@ -1682,6 +2044,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
 [package.extras]
 dev = ["py-make (>=0.1.0)", "twine", "wheel"]
 notebook = ["ipywidgets (>=6)"]
+slack = ["slack-sdk"]
 telegram = ["requests"]
 
 [[package]]
@@ -1710,12 +2073,29 @@ test = ["cython", "flake8", "flake8-ets", "mypy", "pyface", "setuptools", "Sphin
 
 [[package]]
 name = "typing-extensions"
-version = "4.0.1"
+version = "4.1.1"
 description = "Backported and Experimental Type Hints for Python 3.6+"
 category = "main"
 optional = false
 python-versions = ">=3.6"
 
+[[package]]
+name = "uncertainties"
+version = "3.1.6"
+description = "Transparent calculations with uncertainties on the quantities involved (aka error propagation); fast calculation of derivatives"
+category = "main"
+optional = true
+python-versions = "*"
+
+[package.dependencies]
+future = "*"
+
+[package.extras]
+all = ["numpy", "sphinx", "nose"]
+docs = ["sphinx"]
+optional = ["numpy"]
+tests = ["nose", "numpy"]
+
 [[package]]
 name = "unicodecsv"
 version = "0.14.1"
@@ -1726,17 +2106,35 @@ python-versions = "*"
 
 [[package]]
 name = "urllib3"
-version = "1.26.8"
+version = "1.26.9"
 description = "HTTP library with thread-safe connection pooling, file post, and more."
 category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
 
 [package.extras]
-brotli = ["brotlipy (>=0.6.0)"]
+brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"]
 secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
 socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
 
+[[package]]
+name = "virtualenv"
+version = "20.14.1"
+description = "Virtual Python Environment builder"
+category = "dev"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
+
+[package.dependencies]
+distlib = ">=0.3.1,<1"
+filelock = ">=3.2,<4"
+platformdirs = ">=2,<3"
+six = ">=1.9.0,<2"
+
+[package.extras]
+docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"]
+testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"]
+
 [[package]]
 name = "wcwidth"
 version = "0.2.5"
@@ -1747,17 +2145,16 @@ python-versions = "*"
 
 [[package]]
 name = "xarray"
-version = "0.20.2"
+version = "2022.3.0"
 description = "N-D labeled arrays and datasets in Python"
 category = "main"
 optional = true
-python-versions = ">=3.7"
+python-versions = ">=3.8"
 
 [package.dependencies]
-importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
 numpy = ">=1.18"
+packaging = ">=20.0"
 pandas = ">=1.1"
-typing-extensions = {version = ">=3.7", markers = "python_version < \"3.8\""}
 
 [package.extras]
 accel = ["scipy", "bottleneck", "numbagg"]
@@ -1790,15 +2187,15 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
 [[package]]
 name = "zipp"
-version = "3.7.0"
+version = "3.8.0"
 description = "Backport of pathlib-compatible object wrapper for zip files"
 category = "main"
 optional = false
 python-versions = ">=3.7"
 
 [package.extras]
-docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
-testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"]
+docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
+testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"]
 
 [extras]
 all = ["ase", "pymatgen", "tableschema", "dfttopif", "hyperspy", "python-magic", "Pillow", "xmltodict", "pycalphad"]
@@ -1814,18 +2211,26 @@ xml = ["xmltodict"]
 
 [metadata]
 lock-version = "1.1"
-python-versions = "^3.7"
-content-hash = "780ef63037effe28f8bdf541936535a1093e28b6abc3508cee4935603a09d3d8"
+python-versions = ">=3.8.0,<3.11"
+content-hash = "78b40f8d9b29b93e1d886cd6800309e83b3f26cd05c4e80a004aad905bf766a6"
 
 [metadata.files]
+alabaster = [
+    {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"},
+    {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"},
+]
 appnope = [
-    {file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"},
-    {file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"},
+    {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"},
+    {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"},
 ]
 ase = [
     {file = "ase-3.19.3-py3-none-any.whl", hash = "sha256:4cb2dc9c9c7a2724d17e0da09d3e02defb42214ff11952a243b3dcf3875dafdf"},
     {file = "ase-3.19.3.tar.gz", hash = "sha256:27c378b983dfacd49398236e7232c28590c218c31bb2205695818552c772bc4b"},
 ]
+asttokens = [
+    {file = "asttokens-2.0.5-py2.py3-none-any.whl", hash = "sha256:0844691e88552595a6f4a4281a9f7f79b8dd45ca4ccea82e5e05b4bbdb76705c"},
+    {file = "asttokens-2.0.5.tar.gz", hash = "sha256:9a54c114f02c7a9480d56550932546a3f1fe71d8a02f1bc7ccd0ee3ee35cf4d5"},
+]
 atomicwrites = [
     {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
     {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
@@ -1834,17 +2239,21 @@ attrs = [
     {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"},
     {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"},
 ]
+babel = [
+    {file = "Babel-2.9.1-py2.py3-none-any.whl", hash = "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9"},
+    {file = "Babel-2.9.1.tar.gz", hash = "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0"},
+]
 backcall = [
     {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"},
     {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"},
 ]
 boto3 = [
-    {file = "boto3-1.20.37-py3-none-any.whl", hash = "sha256:55c7004af4296648ee497417dfc454d9c39770c265f67e28e1c5f10e11f3b644"},
-    {file = "boto3-1.20.37.tar.gz", hash = "sha256:0e2f8aa8ee71f144d8afbe9ff7d0bb40525b94535e0695bdb200687970c9f452"},
+    {file = "boto3-1.21.38-py3-none-any.whl", hash = "sha256:4bc11350b4d8ebd81bacfb5b2a9613a419dfe05468a61ccafdcaf3fcd2a6d319"},
+    {file = "boto3-1.21.38.tar.gz", hash = "sha256:62dde36a57697b40b4693e0ad0d39013f1e187e5a3c52fdb50dbe710633061bb"},
 ]
 botocore = [
-    {file = "botocore-1.23.37-py3-none-any.whl", hash = "sha256:9ea3eb6e507684900418ad100e5accd1d98979d41c49bacf15f970f0d72f75d4"},
-    {file = "botocore-1.23.37.tar.gz", hash = "sha256:f3077f1ca19e6ab6b7a84c61e01e136a97c7732078a8d806908aee44f1042f5f"},
+    {file = "botocore-1.24.38-py3-none-any.whl", hash = "sha256:91d3be3f961b35e80e6eb314c54b0c2563f6c3efbf0615e5822d4f291c551851"},
+    {file = "botocore-1.24.38.tar.gz", hash = "sha256:e39af0eea4dea96c643fb899207d945b04a0d1bc6ba4535ce03488fdb165a497"},
 ]
 cached-property = [
     {file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"},
@@ -1911,12 +2320,12 @@ chardet = [
     {file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"},
 ]
 charset-normalizer = [
-    {file = "charset-normalizer-2.0.10.tar.gz", hash = "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd"},
-    {file = "charset_normalizer-2.0.10-py3-none-any.whl", hash = "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455"},
+    {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"},
+    {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"},
 ]
 click = [
-    {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"},
-    {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"},
+    {file = "click-8.1.2-py3-none-any.whl", hash = "sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e"},
+    {file = "click-8.1.2.tar.gz", hash = "sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72"},
 ]
 cloudpickle = [
     {file = "cloudpickle-2.0.0-py3-none-any.whl", hash = "sha256:6b2df9741d06f43839a3275c4e6632f7df6487a1f181f5f46a052d3c917c3d11"},
@@ -1927,158 +2336,101 @@ colorama = [
     {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
 ]
 coverage = [
-    {file = "coverage-6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6dbc1536e105adda7a6312c778f15aaabe583b0e9a0b0a324990334fd458c94b"},
-    {file = "coverage-6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:174cf9b4bef0db2e8244f82059a5a72bd47e1d40e71c68ab055425172b16b7d0"},
-    {file = "coverage-6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92b8c845527eae547a2a6617d336adc56394050c3ed8a6918683646328fbb6da"},
-    {file = "coverage-6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c7912d1526299cb04c88288e148c6c87c0df600eca76efd99d84396cfe00ef1d"},
-    {file = "coverage-6.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d2033d5db1d58ae2d62f095e1aefb6988af65b4b12cb8987af409587cc0739"},
-    {file = "coverage-6.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3feac4084291642165c3a0d9eaebedf19ffa505016c4d3db15bfe235718d4971"},
-    {file = "coverage-6.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:276651978c94a8c5672ea60a2656e95a3cce2a3f31e9fb2d5ebd4c215d095840"},
-    {file = "coverage-6.2-cp310-cp310-win32.whl", hash = "sha256:f506af4f27def639ba45789fa6fde45f9a217da0be05f8910458e4557eed020c"},
-    {file = "coverage-6.2-cp310-cp310-win_amd64.whl", hash = "sha256:3f7c17209eef285c86f819ff04a6d4cbee9b33ef05cbcaae4c0b4e8e06b3ec8f"},
-    {file = "coverage-6.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:13362889b2d46e8d9f97c421539c97c963e34031ab0cb89e8ca83a10cc71ac76"},
-    {file = "coverage-6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:22e60a3ca5acba37d1d4a2ee66e051f5b0e1b9ac950b5b0cf4aa5366eda41d47"},
-    {file = "coverage-6.2-cp311-cp311-win_amd64.whl", hash = "sha256:b637c57fdb8be84e91fac60d9325a66a5981f8086c954ea2772efe28425eaf64"},
-    {file = "coverage-6.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f467bbb837691ab5a8ca359199d3429a11a01e6dfb3d9dcc676dc035ca93c0a9"},
-    {file = "coverage-6.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2641f803ee9f95b1f387f3e8f3bf28d83d9b69a39e9911e5bfee832bea75240d"},
-    {file = "coverage-6.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1219d760ccfafc03c0822ae2e06e3b1248a8e6d1a70928966bafc6838d3c9e48"},
-    {file = "coverage-6.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9a2b5b52be0a8626fcbffd7e689781bf8c2ac01613e77feda93d96184949a98e"},
-    {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8e2c35a4c1f269704e90888e56f794e2d9c0262fb0c1b1c8c4ee44d9b9e77b5d"},
-    {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:5d6b09c972ce9200264c35a1d53d43ca55ef61836d9ec60f0d44273a31aa9f17"},
-    {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e3db840a4dee542e37e09f30859f1612da90e1c5239a6a2498c473183a50e781"},
-    {file = "coverage-6.2-cp36-cp36m-win32.whl", hash = "sha256:4e547122ca2d244f7c090fe3f4b5a5861255ff66b7ab6d98f44a0222aaf8671a"},
-    {file = "coverage-6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:01774a2c2c729619760320270e42cd9e797427ecfddd32c2a7b639cdc481f3c0"},
-    {file = "coverage-6.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fb8b8ee99b3fffe4fd86f4c81b35a6bf7e4462cba019997af2fe679365db0c49"},
-    {file = "coverage-6.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:619346d57c7126ae49ac95b11b0dc8e36c1dd49d148477461bb66c8cf13bb521"},
-    {file = "coverage-6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0a7726f74ff63f41e95ed3a89fef002916c828bb5fcae83b505b49d81a066884"},
-    {file = "coverage-6.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cfd9386c1d6f13b37e05a91a8583e802f8059bebfccde61a418c5808dea6bbfa"},
-    {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:17e6c11038d4ed6e8af1407d9e89a2904d573be29d51515f14262d7f10ef0a64"},
-    {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c254b03032d5a06de049ce8bca8338a5185f07fb76600afff3c161e053d88617"},
-    {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dca38a21e4423f3edb821292e97cec7ad38086f84313462098568baedf4331f8"},
-    {file = "coverage-6.2-cp37-cp37m-win32.whl", hash = "sha256:600617008aa82032ddeace2535626d1bc212dfff32b43989539deda63b3f36e4"},
-    {file = "coverage-6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:bf154ba7ee2fd613eb541c2bc03d3d9ac667080a737449d1a3fb342740eb1a74"},
-    {file = "coverage-6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f9afb5b746781fc2abce26193d1c817b7eb0e11459510fba65d2bd77fe161d9e"},
-    {file = "coverage-6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edcada2e24ed68f019175c2b2af2a8b481d3d084798b8c20d15d34f5c733fa58"},
-    {file = "coverage-6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a9c8c4283e17690ff1a7427123ffb428ad6a52ed720d550e299e8291e33184dc"},
-    {file = "coverage-6.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f614fc9956d76d8a88a88bb41ddc12709caa755666f580af3a688899721efecd"},
-    {file = "coverage-6.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9365ed5cce5d0cf2c10afc6add145c5037d3148585b8ae0e77cc1efdd6aa2953"},
-    {file = "coverage-6.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8bdfe9ff3a4ea37d17f172ac0dff1e1c383aec17a636b9b35906babc9f0f5475"},
-    {file = "coverage-6.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:63c424e6f5b4ab1cf1e23a43b12f542b0ec2e54f99ec9f11b75382152981df57"},
-    {file = "coverage-6.2-cp38-cp38-win32.whl", hash = "sha256:49dbff64961bc9bdd2289a2bda6a3a5a331964ba5497f694e2cbd540d656dc1c"},
-    {file = "coverage-6.2-cp38-cp38-win_amd64.whl", hash = "sha256:9a29311bd6429be317c1f3fe4bc06c4c5ee45e2fa61b2a19d4d1d6111cb94af2"},
-    {file = "coverage-6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03b20e52b7d31be571c9c06b74746746d4eb82fc260e594dc662ed48145e9efd"},
-    {file = "coverage-6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:215f8afcc02a24c2d9a10d3790b21054b58d71f4b3c6f055d4bb1b15cecce685"},
-    {file = "coverage-6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a4bdeb0a52d1d04123b41d90a4390b096f3ef38eee35e11f0b22c2d031222c6c"},
-    {file = "coverage-6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c332d8f8d448ded473b97fefe4a0983265af21917d8b0cdcb8bb06b2afe632c3"},
-    {file = "coverage-6.2-cp39-cp39-win32.whl", hash = "sha256:6e1394d24d5938e561fbeaa0cd3d356207579c28bd1792f25a068743f2d5b282"},
-    {file = "coverage-6.2-cp39-cp39-win_amd64.whl", hash = "sha256:86f2e78b1eff847609b1ca8050c9e1fa3bd44ce755b2ec30e70f2d3ba3844644"},
-    {file = "coverage-6.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:5829192582c0ec8ca4a2532407bc14c2f338d9878a10442f5d03804a95fac9de"},
-    {file = "coverage-6.2.tar.gz", hash = "sha256:e2cad8093172b7d1595b4ad66f24270808658e11acf43a8f95b41276162eb5b8"},
+    {file = "coverage-6.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b27d894748475fa858f9597c0ee1d4829f44683f3813633aaf94b19cb5453cf"},
+    {file = "coverage-6.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37d1141ad6b2466a7b53a22e08fe76994c2d35a5b6b469590424a9953155afac"},
+    {file = "coverage-6.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9987b0354b06d4df0f4d3e0ec1ae76d7ce7cbca9a2f98c25041eb79eec766f1"},
+    {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26e2deacd414fc2f97dd9f7676ee3eaecd299ca751412d89f40bc01557a6b1b4"},
+    {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd8bafa458b5c7d061540f1ee9f18025a68e2d8471b3e858a9dad47c8d41903"},
+    {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:46191097ebc381fbf89bdce207a6c107ac4ec0890d8d20f3360345ff5976155c"},
+    {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6f89d05e028d274ce4fa1a86887b071ae1755082ef94a6740238cd7a8178804f"},
+    {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:58303469e9a272b4abdb9e302a780072c0633cdcc0165db7eec0f9e32f901e05"},
+    {file = "coverage-6.3.2-cp310-cp310-win32.whl", hash = "sha256:2fea046bfb455510e05be95e879f0e768d45c10c11509e20e06d8fcaa31d9e39"},
+    {file = "coverage-6.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:a2a8b8bcc399edb4347a5ca8b9b87e7524c0967b335fbb08a83c8421489ddee1"},
+    {file = "coverage-6.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f1555ea6d6da108e1999b2463ea1003fe03f29213e459145e70edbaf3e004aaa"},
+    {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5f4e1edcf57ce94e5475fe09e5afa3e3145081318e5fd1a43a6b4539a97e518"},
+    {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a15dc0a14008f1da3d1ebd44bdda3e357dbabdf5a0b5034d38fcde0b5c234b7"},
+    {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21b7745788866028adeb1e0eca3bf1101109e2dc58456cb49d2d9b99a8c516e6"},
+    {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8ce257cac556cb03be4a248d92ed36904a59a4a5ff55a994e92214cde15c5bad"},
+    {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b0be84e5a6209858a1d3e8d1806c46214e867ce1b0fd32e4ea03f4bd8b2e3359"},
+    {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:acf53bc2cf7282ab9b8ba346746afe703474004d9e566ad164c91a7a59f188a4"},
+    {file = "coverage-6.3.2-cp37-cp37m-win32.whl", hash = "sha256:8bdde1177f2311ee552f47ae6e5aa7750c0e3291ca6b75f71f7ffe1f1dab3dca"},
+    {file = "coverage-6.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b31651d018b23ec463e95cf10070d0b2c548aa950a03d0b559eaa11c7e5a6fa3"},
+    {file = "coverage-6.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07e6db90cd9686c767dcc593dff16c8c09f9814f5e9c51034066cad3373b914d"},
+    {file = "coverage-6.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c6dbb42f3ad25760010c45191e9757e7dce981cbfb90e42feef301d71540059"},
+    {file = "coverage-6.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c76aeef1b95aff3905fb2ae2d96e319caca5b76fa41d3470b19d4e4a3a313512"},
+    {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cf5cfcb1521dc3255d845d9dca3ff204b3229401994ef8d1984b32746bb45ca"},
+    {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fbbdc8d55990eac1b0919ca69eb5a988a802b854488c34b8f37f3e2025fa90d"},
+    {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ec6bc7fe73a938933d4178c9b23c4e0568e43e220aef9472c4f6044bfc6dd0f0"},
+    {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9baff2a45ae1f17c8078452e9e5962e518eab705e50a0aa8083733ea7d45f3a6"},
+    {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd9e830e9d8d89b20ab1e5af09b32d33e1a08ef4c4e14411e559556fd788e6b2"},
+    {file = "coverage-6.3.2-cp38-cp38-win32.whl", hash = "sha256:f7331dbf301b7289013175087636bbaf5b2405e57259dd2c42fdcc9fcc47325e"},
+    {file = "coverage-6.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:68353fe7cdf91f109fc7d474461b46e7f1f14e533e911a2a2cbb8b0fc8613cf1"},
+    {file = "coverage-6.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b78e5afb39941572209f71866aa0b206c12f0109835aa0d601e41552f9b3e620"},
+    {file = "coverage-6.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e21876082ed887baed0146fe222f861b5815455ada3b33b890f4105d806128d"},
+    {file = "coverage-6.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34626a7eee2a3da12af0507780bb51eb52dca0e1751fd1471d0810539cefb536"},
+    {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ebf730d2381158ecf3dfd4453fbca0613e16eaa547b4170e2450c9707665ce7"},
+    {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd6fe30bd519694b356cbfcaca9bd5c1737cddd20778c6a581ae20dc8c04def2"},
+    {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96f8a1cb43ca1422f36492bebe63312d396491a9165ed3b9231e778d43a7fca4"},
+    {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dd035edafefee4d573140a76fdc785dc38829fe5a455c4bb12bac8c20cfc3d69"},
+    {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ca5aeb4344b30d0bec47481536b8ba1181d50dbe783b0e4ad03c95dc1296684"},
+    {file = "coverage-6.3.2-cp39-cp39-win32.whl", hash = "sha256:f5fa5803f47e095d7ad8443d28b01d48c0359484fec1b9d8606d0e3282084bc4"},
+    {file = "coverage-6.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:9548f10d8be799551eb3a9c74bbf2b4934ddb330e08a73320123c07f95cc2d92"},
+    {file = "coverage-6.3.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:18d520c6860515a771708937d2f78f63cc47ab3b80cb78e86573b0a760161faf"},
+    {file = "coverage-6.3.2.tar.gz", hash = "sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9"},
 ]
 coveralls = [
     {file = "coveralls-3.3.1-py2.py3-none-any.whl", hash = "sha256:f42015f31d386b351d4226389b387ae173207058832fbf5c8ec4b40e27b16026"},
     {file = "coveralls-3.3.1.tar.gz", hash = "sha256:b32a8bb5d2df585207c119d6c01567b81fba690c9c10a753bfe27a335bfc43ea"},
 ]
 cryptography = [
-    {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:73bc2d3f2444bcfeac67dd130ff2ea598ea5f20b40e36d19821b4df8c9c5037b"},
-    {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:2d87cdcb378d3cfed944dac30596da1968f88fb96d7fc34fdae30a99054b2e31"},
-    {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74d6c7e80609c0f4c2434b97b80c7f8fdfaa072ca4baab7e239a15d6d70ed73a"},
-    {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:6c0c021f35b421ebf5976abf2daacc47e235f8b6082d3396a2fe3ccd537ab173"},
-    {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d59a9d55027a8b88fd9fd2826c4392bd487d74bf628bb9d39beecc62a644c12"},
-    {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a817b961b46894c5ca8a66b599c745b9a3d9f822725221f0e0fe49dc043a3a3"},
-    {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:94ae132f0e40fe48f310bba63f477f14a43116f05ddb69d6fa31e93f05848ae2"},
-    {file = "cryptography-36.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7be0eec337359c155df191d6ae00a5e8bbb63933883f4f5dffc439dac5348c3f"},
-    {file = "cryptography-36.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:e0344c14c9cb89e76eb6a060e67980c9e35b3f36691e15e1b7a9e58a0a6c6dc3"},
-    {file = "cryptography-36.0.1-cp36-abi3-win32.whl", hash = "sha256:4caa4b893d8fad33cf1964d3e51842cd78ba87401ab1d2e44556826df849a8ca"},
-    {file = "cryptography-36.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:391432971a66cfaf94b21c24ab465a4cc3e8bf4a939c1ca5c3e3a6e0abebdbcf"},
-    {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bb5829d027ff82aa872d76158919045a7c1e91fbf241aec32cb07956e9ebd3c9"},
-    {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc15b1c22e55c4d5566e3ca4db8689470a0ca2babef8e3a9ee057a8b82ce4b1"},
-    {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:596f3cd67e1b950bc372c33f1a28a0692080625592ea6392987dba7f09f17a94"},
-    {file = "cryptography-36.0.1-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:30ee1eb3ebe1644d1c3f183d115a8c04e4e603ed6ce8e394ed39eea4a98469ac"},
-    {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec63da4e7e4a5f924b90af42eddf20b698a70e58d86a72d943857c4c6045b3ee"},
-    {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca238ceb7ba0bdf6ce88c1b74a87bffcee5afbfa1e41e173b1ceb095b39add46"},
-    {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:ca28641954f767f9822c24e927ad894d45d5a1e501767599647259cbf030b903"},
-    {file = "cryptography-36.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:39bdf8e70eee6b1c7b289ec6e5d84d49a6bfa11f8b8646b5b3dfe41219153316"},
-    {file = "cryptography-36.0.1.tar.gz", hash = "sha256:53e5c1dc3d7a953de055d77bef2ff607ceef7a2aac0353b5d630ab67f7423638"},
+    {file = "cryptography-36.0.2-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:4e2dddd38a5ba733be6a025a1475a9f45e4e41139d1321f412c6b360b19070b6"},
+    {file = "cryptography-36.0.2-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:4881d09298cd0b669bb15b9cfe6166f16fc1277b4ed0d04a22f3d6430cb30f1d"},
+    {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea634401ca02367c1567f012317502ef3437522e2fc44a3ea1844de028fa4b84"},
+    {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:7be666cc4599b415f320839e36367b273db8501127b38316f3b9f22f17a0b815"},
+    {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8241cac0aae90b82d6b5c443b853723bcc66963970c67e56e71a2609dc4b5eaf"},
+    {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b2d54e787a884ffc6e187262823b6feb06c338084bbe80d45166a1cb1c6c5bf"},
+    {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:c2c5250ff0d36fd58550252f54915776940e4e866f38f3a7866d92b32a654b86"},
+    {file = "cryptography-36.0.2-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ec6597aa85ce03f3e507566b8bcdf9da2227ec86c4266bd5e6ab4d9e0cc8dab2"},
+    {file = "cryptography-36.0.2-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ca9f686517ec2c4a4ce930207f75c00bf03d94e5063cbc00a1dc42531511b7eb"},
+    {file = "cryptography-36.0.2-cp36-abi3-win32.whl", hash = "sha256:f64b232348ee82f13aac22856515ce0195837f6968aeaa94a3d0353ea2ec06a6"},
+    {file = "cryptography-36.0.2-cp36-abi3-win_amd64.whl", hash = "sha256:53e0285b49fd0ab6e604f4c5d9c5ddd98de77018542e88366923f152dbeb3c29"},
+    {file = "cryptography-36.0.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:32db5cc49c73f39aac27574522cecd0a4bb7384e71198bc65a0d23f901e89bb7"},
+    {file = "cryptography-36.0.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b3d199647468d410994dbeb8cec5816fb74feb9368aedf300af709ef507e3e"},
+    {file = "cryptography-36.0.2-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:da73d095f8590ad437cd5e9faf6628a218aa7c387e1fdf67b888b47ba56a17f0"},
+    {file = "cryptography-36.0.2-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:0a3bf09bb0b7a2c93ce7b98cb107e9170a90c51a0162a20af1c61c765b90e60b"},
+    {file = "cryptography-36.0.2-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8897b7b7ec077c819187a123174b645eb680c13df68354ed99f9b40a50898f77"},
+    {file = "cryptography-36.0.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82740818f2f240a5da8dfb8943b360e4f24022b093207160c77cadade47d7c85"},
+    {file = "cryptography-36.0.2-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:1f64a62b3b75e4005df19d3b5235abd43fa6358d5516cfc43d87aeba8d08dd51"},
+    {file = "cryptography-36.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e167b6b710c7f7bc54e67ef593f8731e1f45aa35f8a8a7b72d6e42ec76afd4b3"},
+    {file = "cryptography-36.0.2.tar.gz", hash = "sha256:70f8f4f7bb2ac9f340655cbac89d68c527af5bb4387522a8413e841e3e6628c9"},
 ]
 cycler = [
     {file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"},
     {file = "cycler-0.11.0.tar.gz", hash = "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"},
 ]
-cython = [
-    {file = "Cython-0.29.26-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c4b003b6b7aa9e74552ef8d4e6009b3e3c3e8fa585710b3a6d062e088e460c1b"},
-    {file = "Cython-0.29.26-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ce804a021c92fea66c8c100781a111706f21bade7a546895c5a9c57fe2df8b24"},
-    {file = "Cython-0.29.26-cp27-cp27m-win32.whl", hash = "sha256:8e07121b34221458a2151d37e137b8f5b011a9c51dd38db2499a6198590aa319"},
-    {file = "Cython-0.29.26-cp27-cp27m-win_amd64.whl", hash = "sha256:233a87db76941626f1db08f4b25a4a5b425b13b64ed0e673c3641f7b650a48d8"},
-    {file = "Cython-0.29.26-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:93840f2071c1f15e613509eadee1fbcd335e8666772437fe5038e24059edd48c"},
-    {file = "Cython-0.29.26-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:10402f0f1564ffc6ecb9c45e07f995771d05bb0b0e1d151e40574638292ee3a5"},
-    {file = "Cython-0.29.26-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:6773cce9d4b3b6168d8feb2b6f06b658ef1e11cbfec075041745666d8e2a5e45"},
-    {file = "Cython-0.29.26-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c813799d533194b7d85203d881d8b4f567a8c644a67f50d47f1ffbf316df412f"},
-    {file = "Cython-0.29.26-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:362fbb9cb4627c7786231429768b54aaba5459a2a0e46c25e59f202ca6155437"},
-    {file = "Cython-0.29.26-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2b834ff6e4d10ba6d7a0d676dd71c1b427a181ddbbbbf79e91d1861557aab59f"},
-    {file = "Cython-0.29.26-cp34-cp34m-win32.whl", hash = "sha256:0c3093bc99facfc97e5019f6c5bc39987663792265c1334d9fc9e37c3a3dcd6f"},
-    {file = "Cython-0.29.26-cp34-cp34m-win_amd64.whl", hash = "sha256:bbf0149680c1fca07200a3ed372b22e6bad7851d191b717a61f9a68af370e180"},
-    {file = "Cython-0.29.26-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a1cc55db32cd39474081d478263b96e036552cdbbab8831c90ea43fb385a9b66"},
-    {file = "Cython-0.29.26-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ebe32e002a9e6553de399033e259ece72aa17c77f740b265e66f122572a8a278"},
-    {file = "Cython-0.29.26-cp35-cp35m-win32.whl", hash = "sha256:6b385f68789c3e8a75b4827e8a4970ff04605ad3cb1c0b41005cc69368dad65d"},
-    {file = "Cython-0.29.26-cp35-cp35m-win_amd64.whl", hash = "sha256:1519eb639de308f5763eb0666b4cc7bd3958268f3f6228cc610b7b4d6c94b68b"},
-    {file = "Cython-0.29.26-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:e118525defec3f67471d8ee5ce04340d43195410a87e5d7ec8a1a9e953c0066a"},
-    {file = "Cython-0.29.26-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:706ea55f58c2722206e51cd9a8754ed0995c4c4231d24b095875d2641d745222"},
-    {file = "Cython-0.29.26-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:77913fe27c5e22c995bac090d01e200ff91e5f58aa944e2d2e94cbf67ea2ae34"},
-    {file = "Cython-0.29.26-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:51923120f57a42c59f5ee6bba9e89a31a394ae8cd419c753f64d8a3aea1ee8b7"},
-    {file = "Cython-0.29.26-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:82881565d04027728d7762edd8c085927a840873af7ee049d703e0ca226bc08d"},
-    {file = "Cython-0.29.26-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:531303085503959338e6cdac630626280ef111aecbb22d48321673a8c3897c0a"},
-    {file = "Cython-0.29.26-cp36-cp36m-win32.whl", hash = "sha256:0205b685802eb4c039b14f67b7ac3f00c55ff04b9e3871df2249576d3e59ba42"},
-    {file = "Cython-0.29.26-cp36-cp36m-win_amd64.whl", hash = "sha256:7df94e56872df8f396ca669466fee60256f69f678654239f706b1e643c2ac4a5"},
-    {file = "Cython-0.29.26-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4b7d04b393d9a4b5fec0cbc4b0f29fe083a9d862d95231a6e7608978bd661d7e"},
-    {file = "Cython-0.29.26-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:af91dd63ac5f1f7fc70dc91ea063f727db42b5eb934d1f3832611be18e25171e"},
-    {file = "Cython-0.29.26-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:d83dad8dc6c63706cb3178dc79010b3865b1345090727189d2cd61758a825ee8"},
-    {file = "Cython-0.29.26-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca10e9fde0eaba1407ab353ff07a26daaa3e4dbe356108a149e482d441f070dd"},
-    {file = "Cython-0.29.26-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fec66cd0a48697fab903854566235aecf1084f62e3163d6589ae7335a1b4d448"},
-    {file = "Cython-0.29.26-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b3041e45aefaa4449fd671902132c0ac1f72eedaedac745c0e1a70a13bf990bb"},
-    {file = "Cython-0.29.26-cp37-cp37m-win32.whl", hash = "sha256:ed76fb98979f02b5e89079906071983a36f3634d3028b86f935cf0196f24fcaa"},
-    {file = "Cython-0.29.26-cp37-cp37m-win_amd64.whl", hash = "sha256:4d868e1a41f5123f51a20c1b8e82f7cb6fa3370c104e98e707f7c910e8cadad1"},
-    {file = "Cython-0.29.26-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:868f309095e557f06dc58723ae865e8c65cfedb2646a562bd8080c92d69e4e4b"},
-    {file = "Cython-0.29.26-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:be550b566345bf53b95616334793ce42a128cf1d9dcde1e28cbf7ce52ea61d6d"},
-    {file = "Cython-0.29.26-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:be13be1e2b9b7395588f2a23bfa692f2f3e6f7936ccf7825c83431b8c8c3452b"},
-    {file = "Cython-0.29.26-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:41ee918480371ae5e5851ba9b1ead5a183e24aedb27bf807c7405d124e943f40"},
-    {file = "Cython-0.29.26-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c91b1ba0d43f7f7ccde8121c672207c7891735ddcc83496af1e0ab617ddc4aba"},
-    {file = "Cython-0.29.26-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5ecf5cf5b57086cc6c1cfc76d6353bbd7023e95da32e0883f1302ca50e481c33"},
-    {file = "Cython-0.29.26-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:0ffce25bf50fa926ec6bf8d6f29650e7cb33fae445938c9880e1ce9b776353ef"},
-    {file = "Cython-0.29.26-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:5041adfef502d67ecd5e291a7cf645a37fed7a9dac557f40d491053f35204d00"},
-    {file = "Cython-0.29.26-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:5fd5db458c9d3d2c2abd047f3190624d9cce8a80a8e0ca0baa69cfd133a523bc"},
-    {file = "Cython-0.29.26-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:75eaa22911d2ec37a3841f77b710b178c805cd378b5e1c4fb82dbc35620d2062"},
-    {file = "Cython-0.29.26-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3aed8c642e8fb27024bca46830b7f62335a44a92354acf708d6b8d050f945a3a"},
-    {file = "Cython-0.29.26-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b5ca05c2bfba0c2480b5fd390ecffe46b8da574d887d600388d6e3caf3f99a88"},
-    {file = "Cython-0.29.26-py2.py3-none-any.whl", hash = "sha256:f5e15ff892c8afad64931ee3dd723c4755c2c516606f9aae7613bebfac62b0f6"},
-    {file = "Cython-0.29.26.tar.gz", hash = "sha256:af377d543a762867da11fcf6e558f7a4a535ff8693f30cce123fab10c00fa312"},
-]
 dask = [
-    {file = "dask-2022.1.0-py3-none-any.whl", hash = "sha256:36e3765ef7800451deff87b3fe90cbc8a4963e65b3fd4e2a73c112c243f88608"},
-    {file = "dask-2022.1.0.tar.gz", hash = "sha256:aee6eb6517f13dc00a3cc7ed9e13c728baa5850b8a35a2b93793d593a23ecbb8"},
+    {file = "dask-2022.4.0-py3-none-any.whl", hash = "sha256:b689cb0ab40c042c5445b886c2136f42966aa57bf6c86561916ab6449b5bad1a"},
+    {file = "dask-2022.4.0.tar.gz", hash = "sha256:e8d0f5840c9df56c60a48b1b3ca326a7a9597a19175b7cd55e12709ccf13ac78"},
 ]
 debugpy = [
-    {file = "debugpy-1.5.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:70b422c63a833630c33e3f9cdbd9b6971f8c5afd452697e464339a21bbe862ba"},
-    {file = "debugpy-1.5.1-cp310-cp310-win32.whl", hash = "sha256:3a457ad9c0059a21a6c7d563c1f18e924f5cf90278c722bd50ede6f56b77c7fe"},
-    {file = "debugpy-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:5d76a4fd028d8009c3faf1185b4b78ceb2273dd2499447664b03939e0368bb90"},
-    {file = "debugpy-1.5.1-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:16db27b4b91991442f91d73604d32080b30de655aca9ba821b1972ea8171021b"},
-    {file = "debugpy-1.5.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2b073ad5e8d8c488fbb6a116986858bab0c9c4558f28deb8832c7a5a27405bd6"},
-    {file = "debugpy-1.5.1-cp36-cp36m-win32.whl", hash = "sha256:318f81f37341e4e054b4267d39896b73cddb3612ca13b39d7eea45af65165e1d"},
-    {file = "debugpy-1.5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b5b3157372e0e0a1297a8b6b5280bcf1d35a40f436c7973771c972726d1e32d5"},
-    {file = "debugpy-1.5.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:1ec3a086e14bba6c472632025b8fe5bdfbaef2afa1ebd5c6615ce6ed8d89bc67"},
-    {file = "debugpy-1.5.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:26fbe53cca45a608679094791ce587b6e2798acd1d4777a8b303b07622e85182"},
-    {file = "debugpy-1.5.1-cp37-cp37m-win32.whl", hash = "sha256:d876db8c312eeb02d85611e0f696abe66a2c1515e6405943609e725d5ff36f2a"},
-    {file = "debugpy-1.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4404a62fb5332ea5c8c9132290eef50b3a0ba38cecacad5529e969a783bcbdd7"},
-    {file = "debugpy-1.5.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f3a3dca9104aa14fd4210edcce6d9ce2b65bd9618c0b222135a40b9d6e2a9eeb"},
-    {file = "debugpy-1.5.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2df2c373e85871086bd55271c929670cd4e1dba63e94a08d442db830646203b"},
-    {file = "debugpy-1.5.1-cp38-cp38-win32.whl", hash = "sha256:82f5f9ce93af6861a0713f804e62ab390bb12a17f113153e47fea8bbb1dfbe36"},
-    {file = "debugpy-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:17a25ce9d7714f92fc97ef00cc06269d7c2b163094990ada30156ed31d9a5030"},
-    {file = "debugpy-1.5.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:01e98c594b3e66d529e40edf314f849cd1a21f7a013298df58cd8e263bf8e184"},
-    {file = "debugpy-1.5.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f73988422b17f071ad3c4383551ace1ba5ed810cbab5f9c362783d22d40a08dc"},
-    {file = "debugpy-1.5.1-cp39-cp39-win32.whl", hash = "sha256:23df67fc56d59e386c342428a7953c2c06cc226d8525b11319153e96afb65b0c"},
-    {file = "debugpy-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:a2aa64f6d2ca7ded8a7e8a4e7cae3bc71866b09876b7b05cecad231779cb9156"},
-    {file = "debugpy-1.5.1-py2.py3-none-any.whl", hash = "sha256:194f95dd3e84568b5489aab5689a3a2c044e8fdc06f1890b8b4f70b6b89f2778"},
-    {file = "debugpy-1.5.1.zip", hash = "sha256:d2b09e91fbd1efa4f4fda121d49af89501beda50c18ed7499712c71a4bf3452e"},
+    {file = "debugpy-1.6.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:eb1946efac0c0c3d411cea0b5ac772fbde744109fd9520fb0c5a51979faf05ad"},
+    {file = "debugpy-1.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e3513399177dd37af4c1332df52da5da1d0c387e5927dc4c0709e26ee7302e8f"},
+    {file = "debugpy-1.6.0-cp310-cp310-win32.whl", hash = "sha256:5c492235d6b68f879df3bdbdb01f25c15be15682665517c2c7d0420e5658d71f"},
+    {file = "debugpy-1.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:40de9ba137d355538432209d05e0f5fe5d0498dce761c39119ad4b950b51db31"},
+    {file = "debugpy-1.6.0-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:0d383b91efee57dbb923ba20801130cf60450a0eda60bce25bccd937de8e323a"},
+    {file = "debugpy-1.6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1ff853e60e77e1c16f85a31adb8360bb2d98ca588d7ed645b7f0985b240bdb5e"},
+    {file = "debugpy-1.6.0-cp37-cp37m-win32.whl", hash = "sha256:8e972c717d95f56b6a3a7a29a5ede1ee8f2c3802f6f0e678203b0778eb322bf1"},
+    {file = "debugpy-1.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:a8aaeb53e87225141fda7b9081bd87155c1debc13e2f5a532d341112d1983b65"},
+    {file = "debugpy-1.6.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:132defb585b518955358321d0f42f6aa815aa15b432be27db654807707c70b2f"},
+    {file = "debugpy-1.6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8ee75844242b4537beb5899f3e60a578454d1f136b99e8d57ac424573797b94a"},
+    {file = "debugpy-1.6.0-cp38-cp38-win32.whl", hash = "sha256:a65a2499761d47df3e9ea9567109be6e73d412e00ac3ffcf74839f3ddfcdf028"},
+    {file = "debugpy-1.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:bd980d533d0ddfc451e03a3bb32acb2900049fec39afc3425b944ebf0889be62"},
+    {file = "debugpy-1.6.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:245c7789a012f86210847ec7ee9f38c30a30d4c2223c3e111829a76c9006a5d0"},
+    {file = "debugpy-1.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0e3aa2368883e83e7b689ddff3cafb595f7b711f6a065886b46a96a7fef874e7"},
+    {file = "debugpy-1.6.0-cp39-cp39-win32.whl", hash = "sha256:72bcfa97f3afa0064afc77ab811f48ad4a06ac330f290b675082c24437730366"},
+    {file = "debugpy-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:30abefefd2ff5a5481162d613cb70e60e2fa80a5eb4c994717c0f008ed25d2e1"},
+    {file = "debugpy-1.6.0-py2.py3-none-any.whl", hash = "sha256:4de7777842da7e08652f2776c552070bbdd758557fdec73a15d7be0e4aab95ce"},
+    {file = "debugpy-1.6.0.zip", hash = "sha256:7b79c40852991f7b6c3ea65845ed0f5f6b731c37f4f9ad9c61e2ab4bd48a9275"},
 ]
 decorator = [
     {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"},
@@ -2090,40 +2442,63 @@ dftparse = [
 dfttopif = [
     {file = "dfttopif-1.1.0.tar.gz", hash = "sha256:45c82f341ea3c2cff3f4cc128d49743466968b498b5681d0defeaa1b98d34cb7"},
 ]
+diff-cover = [
+    {file = "diff_cover-6.4.5-py3-none-any.whl", hash = "sha256:b51356163ab1f93592dd7e45adb169cc8c7044ad8c2fe19b2bacc0ac90e70336"},
+    {file = "diff_cover-6.4.5.tar.gz", hash = "sha256:a94b8c1c17dc24498917f7289fe383b457d8ad4ef2a3ffca80a892a41c8b58a6"},
+]
 dill = [
     {file = "dill-0.3.4-py2.py3-none-any.whl", hash = "sha256:7e40e4a70304fd9ceab3535d36e58791d9c4a776b38ec7f7ec9afc8d3dca4d4f"},
     {file = "dill-0.3.4.zip", hash = "sha256:9f9734205146b2b353ab3fec9af0070237b6ddae78452af83d2fca84d739e675"},
 ]
+distlib = [
+    {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"},
+    {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"},
+]
 docopt = [
     {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"},
 ]
+docutils = [
+    {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"},
+    {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"},
+]
 entrypoints = [
-    {file = "entrypoints-0.3-py2.py3-none-any.whl", hash = "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19"},
-    {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"},
+    {file = "entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f"},
+    {file = "entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4"},
 ]
 et-xmlfile = [
     {file = "et_xmlfile-1.1.0-py3-none-any.whl", hash = "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada"},
     {file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"},
 ]
+executing = [
+    {file = "executing-0.8.3-py2.py3-none-any.whl", hash = "sha256:d1eef132db1b83649a3905ca6dd8897f71ac6f8cac79a7e58a1a09cf137546c9"},
+    {file = "executing-0.8.3.tar.gz", hash = "sha256:c6554e21c6b060590a6d3be4b82fb78f8f0194d809de5ea7df1c093763311501"},
+]
 fair-research-login = [
     {file = "fair-research-login-0.2.6.tar.gz", hash = "sha256:ad54267a2731ddfd550451945092753156a05398b04db575024700ed6c933070"},
     {file = "fair_research_login-0.2.6-py2.py3-none-any.whl", hash = "sha256:bebacf7a565175243fc77afdacc3d8002fff518ead8b53c955b13fe0d6f2cd0c"},
 ]
+filelock = [
+    {file = "filelock-3.6.0-py3-none-any.whl", hash = "sha256:f8314284bfffbdcfa0ff3d7992b023d4c628ced6feb957351d4c48d059f56bc0"},
+    {file = "filelock-3.6.0.tar.gz", hash = "sha256:9cd540a9352e432c7246a48fe4e8712b10acb1df2ad1f30e8c070b82ae1fed85"},
+]
 flake8 = [
-    {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"},
-    {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"},
+    {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"},
+    {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"},
 ]
 fsspec = [
-    {file = "fsspec-2022.1.0-py3-none-any.whl", hash = "sha256:256e2be44e62430c9ca8dac2e480384b00a3c52aef4e2b0b7204163fdc861d37"},
-    {file = "fsspec-2022.1.0.tar.gz", hash = "sha256:0bdd519bbf4d8c9a1d893a50b5ebacc89acd0e1fe0045d2f7b0e0c1af5990edc"},
+    {file = "fsspec-2022.3.0-py3-none-any.whl", hash = "sha256:a53491b003210fce6911dd8f2d37e20c41a27ce52a655eef11b885d1578ed4cf"},
+    {file = "fsspec-2022.3.0.tar.gz", hash = "sha256:fd582cc4aa0db5968bad9317cae513450eddd08b2193c4428d9349265a995523"},
+]
+future = [
+    {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"},
 ]
 globus-nexus-client = [
     {file = "globus-nexus-client-0.4.1.tar.gz", hash = "sha256:156ff3a3dc5e07fe30b41856aad54d25129efcff913ec17669edc24c9fa755cd"},
     {file = "globus_nexus_client-0.4.1-py3-none-any.whl", hash = "sha256:4ed05b304530ae363772e4f2af2b6c9f3c63849a1427fc6b2e315ed864416e8e"},
 ]
 globus-sdk = [
-    {file = "globus-sdk-3.2.1.tar.gz", hash = "sha256:8458de9ab0ac2296b1e27c715d565767c634aa95021ef133d90c5d95d3f64785"},
-    {file = "globus_sdk-3.2.1-py3-none-any.whl", hash = "sha256:a9bcc684198bd891dd0c70df485e66124d90693b7cf38315667ec72d308b16fd"},
+    {file = "globus-sdk-3.7.0.tar.gz", hash = "sha256:81dbcb7bb7072bf9a5f730becc65e4a0f15f0fa0e2022faf2d943a99b5ce1fb5"},
+    {file = "globus_sdk-3.7.0-py3-none-any.whl", hash = "sha256:ba2d85b61374394a096814cbddee510b89883b68803e47e6cf4247324ea57fa6"},
 ]
 greenlet = [
     {file = "greenlet-1.1.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:58df5c2a0e293bf665a51f8a100d3e9956febfbf1d9aaf8c0677cf70218910c6"},
@@ -2283,28 +2658,36 @@ ijson = [
     {file = "ijson-3.1.4.tar.gz", hash = "sha256:1d1003ae3c6115ec9b587d29dd136860a81a23c7626b682e2b5b12c9fd30e4ea"},
 ]
 imageio = [
-    {file = "imageio-2.9.0-py3-none-any.whl", hash = "sha256:3604d751f03002e8e0e7650aa71d8d9148144a87daf17cb1f3228e80747f2e6b"},
-    {file = "imageio-2.9.0.tar.gz", hash = "sha256:52ddbaeca2dccf53ba2d6dec5676ca7bc3b2403ef8b37f7da78b7654bb3e10f0"},
+    {file = "imageio-2.16.2-py3-none-any.whl", hash = "sha256:4757b5bc41158feb89529721bc14b738c3a0e17284dbdfc3f09ac4ad9dc00a08"},
+    {file = "imageio-2.16.2.tar.gz", hash = "sha256:8fea761d51a53c150cabd82ed36011252c17580c752216b8222f078630dfb9ba"},
+]
+imagesize = [
+    {file = "imagesize-1.3.0-py2.py3-none-any.whl", hash = "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c"},
+    {file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"},
 ]
 importlib-metadata = [
-    {file = "importlib_metadata-4.2.0-py3-none-any.whl", hash = "sha256:057e92c15bc8d9e8109738a48db0ccb31b4d9d5cfbee5a8670879a30be66304b"},
-    {file = "importlib_metadata-4.2.0.tar.gz", hash = "sha256:b7e52a1f8dec14a75ea73e0891f3060099ca1d8e6a462a4dff11c3e119ea1b31"},
+    {file = "importlib_metadata-4.11.3-py3-none-any.whl", hash = "sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6"},
+    {file = "importlib_metadata-4.11.3.tar.gz", hash = "sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539"},
 ]
 importlib-resources = [
-    {file = "importlib_resources-5.4.0-py3-none-any.whl", hash = "sha256:33a95faed5fc19b4bc16b29a6eeae248a3fe69dd55d4d229d2b480e23eeaad45"},
-    {file = "importlib_resources-5.4.0.tar.gz", hash = "sha256:d756e2f85dd4de2ba89be0b21dba2a3bbec2e871a42a3a16719258a11f87506b"},
+    {file = "importlib_resources-5.6.0-py3-none-any.whl", hash = "sha256:a9dd72f6cc106aeb50f6e66b86b69b454766dd6e39b69ac68450253058706bcc"},
+    {file = "importlib_resources-5.6.0.tar.gz", hash = "sha256:1b93238cbf23b4cde34240dd8321d99e9bf2eb4bc91c0c99b2886283e7baad85"},
+]
+iniconfig = [
+    {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
+    {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
 ]
 ipykernel = [
-    {file = "ipykernel-6.7.0-py3-none-any.whl", hash = "sha256:6203ccd5510ff148e9433fd4a2707c5ce8d688f026427f46e13d7ebf9b3e9787"},
-    {file = "ipykernel-6.7.0.tar.gz", hash = "sha256:d82b904fdc2fd8c7b1fbe0fa481c68a11b4cd4c8ef07e6517da1f10cc3114d24"},
+    {file = "ipykernel-6.13.0-py3-none-any.whl", hash = "sha256:2b0987af43c0d4b62cecb13c592755f599f96f29aafe36c01731aaa96df30d39"},
+    {file = "ipykernel-6.13.0.tar.gz", hash = "sha256:0e28273e290858393e86e152b104e5506a79c13d25b951ac6eca220051b4be60"},
 ]
 ipyparallel = [
-    {file = "ipyparallel-8.1.0-py3-none-any.whl", hash = "sha256:83bdbfe1f9dc6c3487aaa645dbba1a4effa9101e14e255f3291b862cc0d696cf"},
-    {file = "ipyparallel-8.1.0.tar.gz", hash = "sha256:63f7e136e88f890e9802522fa5475dd81e7614ba06a8cfe4f80cc3056fdb7d73"},
+    {file = "ipyparallel-8.2.1-py3-none-any.whl", hash = "sha256:8509448670cdc3c3961e29a827c6bdacbee29ee9c9e8c50f70032c8714f731fb"},
+    {file = "ipyparallel-8.2.1.tar.gz", hash = "sha256:f267473c52fc6a886c6b816adb155bec0b277bc7d224fb3fabeb83834e733c72"},
 ]
 ipython = [
-    {file = "ipython-7.31.0-py3-none-any.whl", hash = "sha256:4c4234cdcc6b8f87c5b5c7af9899aa696ac5cfcf0e9f6d0688018bbee5c73bce"},
-    {file = "ipython-7.31.0.tar.gz", hash = "sha256:346c74db7312c41fa566d3be45d2e759a528dcc2994fe48aac1a03a70cd668a3"},
+    {file = "ipython-8.2.0-py3-none-any.whl", hash = "sha256:1b672bfd7a48d87ab203d9af8727a3b0174a4566b4091e9447c22fb63ea32857"},
+    {file = "ipython-8.2.0.tar.gz", hash = "sha256:70e5eb132cac594a34b5f799bd252589009905f05104728aea6a403ec2519dc1"},
 ]
 isodate = [
     {file = "isodate-0.6.1-py2.py3-none-any.whl", hash = "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96"},
@@ -2314,9 +2697,13 @@ jedi = [
     {file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"},
     {file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"},
 ]
+jinja2 = [
+    {file = "Jinja2-3.1.1-py3-none-any.whl", hash = "sha256:539835f51a74a69f41b848a9645dbdc35b4f20a3b601e2d9a7e22947b15ff119"},
+    {file = "Jinja2-3.1.1.tar.gz", hash = "sha256:640bed4bb501cbd17194b3cace1dc2126f5b619cf068a726b98192a0fde74ae9"},
+]
 jmespath = [
-    {file = "jmespath-0.10.0-py2.py3-none-any.whl", hash = "sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f"},
-    {file = "jmespath-0.10.0.tar.gz", hash = "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9"},
+    {file = "jmespath-1.0.0-py3-none-any.whl", hash = "sha256:e8dcd576ed616f14ec02eed0005c85973b5890083313860136657e24784e4c04"},
+    {file = "jmespath-1.0.0.tar.gz", hash = "sha256:a490e280edd1f57d6de88636992d05b71e97d69a26a19f058ecf7d304474bf5e"},
 ]
 jsonlines = [
     {file = "jsonlines-3.0.0-py3-none-any.whl", hash = "sha256:15f93e1817162c85bc268c7428952beec4fc4a41f118abf891c4bedf5653624f"},
@@ -2327,84 +2714,138 @@ jsonschema = [
     {file = "jsonschema-4.3.0.tar.gz", hash = "sha256:cb7f57b40f870409d7571844d0623f66d8078c90a9c255d9a4d4314b5ec3fc7c"},
 ]
 jupyter-client = [
-    {file = "jupyter_client-7.1.1-py3-none-any.whl", hash = "sha256:f0c576cce235c727e30b0a0da88c2755d0947d0070fa1bc45f195079ffd64e66"},
-    {file = "jupyter_client-7.1.1.tar.gz", hash = "sha256:540ca35e57e83c5ece81abd9b781a57cba39a37c60a2a30c8c1b2f6663544343"},
+    {file = "jupyter_client-7.2.2-py3-none-any.whl", hash = "sha256:44045448eadc12493d819d965eb1dc9d10d1927698adbb9b14eb9a3a4a45ba53"},
+    {file = "jupyter_client-7.2.2.tar.gz", hash = "sha256:8fdbad344a8baa6a413d86d25bbf87ce21cb2b4aa5a8e0413863b9754eb8eb8a"},
 ]
 jupyter-core = [
-    {file = "jupyter_core-4.9.1-py3-none-any.whl", hash = "sha256:1c091f3bbefd6f2a8782f2c1db662ca8478ac240e962ae2c66f0b87c818154ea"},
-    {file = "jupyter_core-4.9.1.tar.gz", hash = "sha256:dce8a7499da5a53ae3afd5a9f4b02e5df1d57250cf48f3ad79da23b4778cd6fa"},
+    {file = "jupyter_core-4.9.2-py3-none-any.whl", hash = "sha256:f875e4d27e202590311d468fa55f90c575f201490bd0c18acabe4e318db4a46d"},
+    {file = "jupyter_core-4.9.2.tar.gz", hash = "sha256:d69baeb9ffb128b8cd2657fcf2703f89c769d1673c851812119e3a2a0e93ad9a"},
 ]
 kiwisolver = [
-    {file = "kiwisolver-1.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1d819553730d3c2724582124aee8a03c846ec4362ded1034c16fb3ef309264e6"},
-    {file = "kiwisolver-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d93a1095f83e908fc253f2fb569c2711414c0bfd451cab580466465b235b470"},
-    {file = "kiwisolver-1.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4550a359c5157aaf8507e6820d98682872b9100ce7607f8aa070b4b8af6c298"},
-    {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2210f28778c7d2ee13f3c2a20a3a22db889e75f4ec13a21072eabb5693801e84"},
-    {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:82f49c5a79d3839bc8f38cb5f4bfc87e15f04cbafa5fbd12fb32c941cb529cfb"},
-    {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9661a04ca3c950a8ac8c47f53cbc0b530bce1b52f516a1e87b7736fec24bfff0"},
-    {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ddb500a2808c100e72c075cbb00bf32e62763c82b6a882d403f01a119e3f402"},
-    {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72be6ebb4e92520b9726d7146bc9c9b277513a57a38efcf66db0620aec0097e0"},
-    {file = "kiwisolver-1.3.2-cp310-cp310-win32.whl", hash = "sha256:83d2c9db5dfc537d0171e32de160461230eb14663299b7e6d18ca6dca21e4977"},
-    {file = "kiwisolver-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:cba430db673c29376135e695c6e2501c44c256a81495da849e85d1793ee975ad"},
-    {file = "kiwisolver-1.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4116ba9a58109ed5e4cb315bdcbff9838f3159d099ba5259c7c7fb77f8537492"},
-    {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19554bd8d54cf41139f376753af1a644b63c9ca93f8f72009d50a2080f870f77"},
-    {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a4cf5bbdc861987a7745aed7a536c6405256853c94abc9f3287c3fa401b174"},
-    {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0007840186bacfaa0aba4466d5890334ea5938e0bb7e28078a0eb0e63b5b59d5"},
-    {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec2eba188c1906b05b9b49ae55aae4efd8150c61ba450e6721f64620c50b59eb"},
-    {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3dbb3cea20b4af4f49f84cffaf45dd5f88e8594d18568e0225e6ad9dec0e7967"},
-    {file = "kiwisolver-1.3.2-cp37-cp37m-win32.whl", hash = "sha256:5326ddfacbe51abf9469fe668944bc2e399181a2158cb5d45e1d40856b2a0589"},
-    {file = "kiwisolver-1.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:c6572c2dab23c86a14e82c245473d45b4c515314f1f859e92608dcafbd2f19b8"},
-    {file = "kiwisolver-1.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b5074fb09429f2b7bc82b6fb4be8645dcbac14e592128beeff5461dcde0af09f"},
-    {file = "kiwisolver-1.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:22521219ca739654a296eea6d4367703558fba16f98688bd8ce65abff36eaa84"},
-    {file = "kiwisolver-1.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c358721aebd40c243894298f685a19eb0491a5c3e0b923b9f887ef1193ddf829"},
-    {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ba5a1041480c6e0a8b11a9544d53562abc2d19220bfa14133e0cdd9967e97af"},
-    {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44e6adf67577dbdfa2d9f06db9fbc5639afefdb5bf2b4dfec25c3a7fbc619536"},
-    {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d45d1c74f88b9f41062716c727f78f2a59a5476ecbe74956fafb423c5c87a76"},
-    {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70adc3658138bc77a36ce769f5f183169bc0a2906a4f61f09673f7181255ac9b"},
-    {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6a5431940f28b6de123de42f0eb47b84a073ee3c3345dc109ad550a3307dd28"},
-    {file = "kiwisolver-1.3.2-cp38-cp38-win32.whl", hash = "sha256:ee040a7de8d295dbd261ef2d6d3192f13e2b08ec4a954de34a6fb8ff6422e24c"},
-    {file = "kiwisolver-1.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:8dc3d842fa41a33fe83d9f5c66c0cc1f28756530cd89944b63b072281e852031"},
-    {file = "kiwisolver-1.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a498bcd005e8a3fedd0022bb30ee0ad92728154a8798b703f394484452550507"},
-    {file = "kiwisolver-1.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:80efd202108c3a4150e042b269f7c78643420cc232a0a771743bb96b742f838f"},
-    {file = "kiwisolver-1.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f8eb7b6716f5b50e9c06207a14172cf2de201e41912ebe732846c02c830455b9"},
-    {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f441422bb313ab25de7b3dbfd388e790eceb76ce01a18199ec4944b369017009"},
-    {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:30fa008c172355c7768159983a7270cb23838c4d7db73d6c0f6b60dde0d432c6"},
-    {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f8f6c8f4f1cff93ca5058d6ec5f0efda922ecb3f4c5fb76181f327decff98b8"},
-    {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba677bcaff9429fd1bf01648ad0901cea56c0d068df383d5f5856d88221fe75b"},
-    {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7843b1624d6ccca403a610d1277f7c28ad184c5aa88a1750c1a999754e65b439"},
-    {file = "kiwisolver-1.3.2-cp39-cp39-win32.whl", hash = "sha256:e6f5eb2f53fac7d408a45fbcdeda7224b1cfff64919d0f95473420a931347ae9"},
-    {file = "kiwisolver-1.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:eedd3b59190885d1ebdf6c5e0ca56828beb1949b4dfe6e5d0256a461429ac386"},
-    {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:dedc71c8eb9c5096037766390172c34fb86ef048b8e8958b4e484b9e505d66bc"},
-    {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:bf7eb45d14fc036514c09554bf983f2a72323254912ed0c3c8e697b62c4c158f"},
-    {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2b65bd35f3e06a47b5c30ea99e0c2b88f72c6476eedaf8cfbc8e66adb5479dcf"},
-    {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25405f88a37c5f5bcba01c6e350086d65e7465fd1caaf986333d2a045045a223"},
-    {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:bcadb05c3d4794eb9eee1dddf1c24215c92fb7b55a80beae7a60530a91060560"},
-    {file = "kiwisolver-1.3.2.tar.gz", hash = "sha256:fc4453705b81d03568d5b808ad8f09c77c47534f6ac2e72e733f9ca4714aa75c"},
+    {file = "kiwisolver-1.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6e395ece147f0692ca7cdb05a028d31b83b72c369f7b4a2c1798f4b96af1e3d8"},
+    {file = "kiwisolver-1.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0b7f50a1a25361da3440f07c58cd1d79957c2244209e4f166990e770256b6b0b"},
+    {file = "kiwisolver-1.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3c032c41ae4c3a321b43a3650e6ecc7406b99ff3e5279f24c9b310f41bc98479"},
+    {file = "kiwisolver-1.4.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1dcade8f6fe12a2bb4efe2cbe22116556e3b6899728d3b2a0d3b367db323eacc"},
+    {file = "kiwisolver-1.4.2-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0e45e780a74416ef2f173189ef4387e44b5494f45e290bcb1f03735faa6779bf"},
+    {file = "kiwisolver-1.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d2bb56309fb75a811d81ed55fbe2208aa77a3a09ff5f546ca95e7bb5fac6eff"},
+    {file = "kiwisolver-1.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69b2d6c12f2ad5f55104a36a356192cfb680c049fe5e7c1f6620fc37f119cdc2"},
+    {file = "kiwisolver-1.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:262c248c60f22c2b547683ad521e8a3db5909c71f679b93876921549107a0c24"},
+    {file = "kiwisolver-1.4.2-cp310-cp310-win32.whl", hash = "sha256:1008346a7741620ab9cc6c96e8ad9b46f7a74ce839dbb8805ddf6b119d5fc6c2"},
+    {file = "kiwisolver-1.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:6ece2e12e4b57bc5646b354f436416cd2a6f090c1dadcd92b0ca4542190d7190"},
+    {file = "kiwisolver-1.4.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b978afdb913ca953cf128d57181da2e8798e8b6153be866ae2a9c446c6162f40"},
+    {file = "kiwisolver-1.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f88c4b8e449908eeddb3bbd4242bd4dc2c7a15a7aa44bb33df893203f02dc2d"},
+    {file = "kiwisolver-1.4.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e348f1904a4fab4153407f7ccc27e43b2a139752e8acf12e6640ba683093dd96"},
+    {file = "kiwisolver-1.4.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c839bf28e45d7ddad4ae8f986928dbf5a6d42ff79760d54ec8ada8fb263e097c"},
+    {file = "kiwisolver-1.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8ae5a071185f1a93777c79a9a1e67ac46544d4607f18d07131eece08d415083a"},
+    {file = "kiwisolver-1.4.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c222f91a45da9e01a9bc4f760727ae49050f8e8345c4ff6525495f7a164c8973"},
+    {file = "kiwisolver-1.4.2-cp37-cp37m-win32.whl", hash = "sha256:a4e8f072db1d6fb7a7cc05a6dbef8442c93001f4bb604f1081d8c2db3ca97159"},
+    {file = "kiwisolver-1.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:be9a650890fb60393e60aacb65878c4a38bb334720aa5ecb1c13d0dac54dd73b"},
+    {file = "kiwisolver-1.4.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8ec2e55bf31b43aabe32089125dca3b46fdfe9f50afbf0756ae11e14c97b80ca"},
+    {file = "kiwisolver-1.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d1078ba770d6165abed3d9a1be1f9e79b61515de1dd00d942fa53bba79f01ae"},
+    {file = "kiwisolver-1.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cbb5eb4a2ea1ffec26268d49766cafa8f957fe5c1b41ad00733763fae77f9436"},
+    {file = "kiwisolver-1.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e6cda72db409eefad6b021e8a4f964965a629f577812afc7860c69df7bdb84a"},
+    {file = "kiwisolver-1.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b1605c7c38cc6a85212dfd6a641f3905a33412e49f7c003f35f9ac6d71f67720"},
+    {file = "kiwisolver-1.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81237957b15469ea9151ec8ca08ce05656090ffabc476a752ef5ad7e2644c526"},
+    {file = "kiwisolver-1.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:240009fdf4fa87844f805e23f48995537a8cb8f8c361e35fda6b5ac97fcb906f"},
+    {file = "kiwisolver-1.4.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:240c2d51d098395c012ddbcb9bd7b3ba5de412a1d11840698859f51d0e643c4f"},
+    {file = "kiwisolver-1.4.2-cp38-cp38-win32.whl", hash = "sha256:8b6086aa6936865962b2cee0e7aaecf01ab6778ce099288354a7229b4d9f1408"},
+    {file = "kiwisolver-1.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:0d98dca86f77b851350c250f0149aa5852b36572514d20feeadd3c6b1efe38d0"},
+    {file = "kiwisolver-1.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:91eb4916271655dfe3a952249cb37a5c00b6ba68b4417ee15af9ba549b5ba61d"},
+    {file = "kiwisolver-1.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa4d97d7d2b2c082e67907c0b8d9f31b85aa5d3ba0d33096b7116f03f8061261"},
+    {file = "kiwisolver-1.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:71469b5845b9876b8d3d252e201bef6f47bf7456804d2fbe9a1d6e19e78a1e65"},
+    {file = "kiwisolver-1.4.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8ff3033e43e7ca1389ee59fb7ecb8303abb8713c008a1da49b00869e92e3dd7c"},
+    {file = "kiwisolver-1.4.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89b57c2984f4464840e4b768affeff6b6809c6150d1166938ade3e22fbe22db8"},
+    {file = "kiwisolver-1.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffbdb9a96c536f0405895b5e21ee39ec579cb0ed97bdbd169ae2b55f41d73219"},
+    {file = "kiwisolver-1.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a830a03970c462d1a2311c90e05679da56d3bd8e78a4ba9985cb78ef7836c9f"},
+    {file = "kiwisolver-1.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f74f2a13af201559e3d32b9ddfc303c94ae63d63d7f4326d06ce6fe67e7a8255"},
+    {file = "kiwisolver-1.4.2-cp39-cp39-win32.whl", hash = "sha256:e677cc3626287f343de751e11b1e8a5b915a6ac897e8aecdbc996cd34de753a0"},
+    {file = "kiwisolver-1.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:b3e251e5c38ac623c5d786adb21477f018712f8c6fa54781bd38aa1c60b60fc2"},
+    {file = "kiwisolver-1.4.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0c380bb5ae20d829c1a5473cfcae64267b73aaa4060adc091f6df1743784aae0"},
+    {file = "kiwisolver-1.4.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:484f2a5f0307bc944bc79db235f41048bae4106ffa764168a068d88b644b305d"},
+    {file = "kiwisolver-1.4.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e8afdf533b613122e4bbaf3c1e42c2a5e9e2d1dd3a0a017749a7658757cb377"},
+    {file = "kiwisolver-1.4.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:42f6ef9b640deb6f7d438e0a371aedd8bef6ddfde30683491b2e6f568b4e884e"},
+    {file = "kiwisolver-1.4.2.tar.gz", hash = "sha256:7f606d91b8a8816be476513a77fd30abe66227039bd6f8b406c348cb0247dcc9"},
+]
+latexcodec = [
+    {file = "latexcodec-2.0.1-py2.py3-none-any.whl", hash = "sha256:c277a193638dc7683c4c30f6684e3db728a06efb0dc9cf346db8bd0aa6c5d271"},
+    {file = "latexcodec-2.0.1.tar.gz", hash = "sha256:2aa2551c373261cefe2ad3a8953a6d6533e68238d180eb4bb91d7964adb3fe9a"},
 ]
 linear-tsv = [
     {file = "linear-tsv-1.1.0.tar.gz", hash = "sha256:b504d78f4075615ae75de86a16e5680701a441fc84da2a2cf9f94351ab1ccbf5"},
 ]
 llvmlite = [
-    {file = "llvmlite-0.34.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:11342e5ac320c953590bdd9d0dec8c52f4b5252c4c6335ba25f1e7b9f91f9325"},
-    {file = "llvmlite-0.34.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:5bdf0ce430adfaf938ced5844d12f80616eb8321b5b9edfc45ef84ada5c5242c"},
-    {file = "llvmlite-0.34.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:e08d9d2dc5a31636bfc6b516d2d7daba95632afa3419eb8730dc76a7951e9558"},
-    {file = "llvmlite-0.34.0-cp36-cp36m-win32.whl", hash = "sha256:9ff1dcdad03be0cf953aca5fc8cffdca25ccee2ec9e8ec7e95571722cdc02d55"},
-    {file = "llvmlite-0.34.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5acdc3c3c7ea0ef7a1a6b442272e05d695bc8492e5b07666135ed1cfbf4ab9d2"},
-    {file = "llvmlite-0.34.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bb96989bc57a1ccb131e7a0e061d07b68139b6f81a98912345d53d9239e231e1"},
-    {file = "llvmlite-0.34.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:6d3f81992f52a94077e7b9b16497029daf5b5eebb2cce56f3c8345bbc9c6308e"},
-    {file = "llvmlite-0.34.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:d841248d1c630426c93e3eb3f8c45bca0dab77c09faeb7553b1a500220e362ce"},
-    {file = "llvmlite-0.34.0-cp37-cp37m-win32.whl", hash = "sha256:408b15ffec30696406e821c89da010f1bb1eb0aa572be4561c98eb2536d610ab"},
-    {file = "llvmlite-0.34.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5d1f370bf150db7239204f09cf6a0603292ea28bac984e69b167e16fe160d803"},
-    {file = "llvmlite-0.34.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:132322bc084abf336c80dd106f9357978c8c085911fb656898d3be0d9ff057ea"},
-    {file = "llvmlite-0.34.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:8f344102745fceba6eb5bf03c228bb290e9bc79157e9506a4a72878d636f9b3c"},
-    {file = "llvmlite-0.34.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:05253f3f44fab0148276335b2c1b2c4a78143dfa78e6bafd7f937d6248f297cc"},
-    {file = "llvmlite-0.34.0-cp38-cp38-win32.whl", hash = "sha256:28264f9e2b3df4135cbcfca5a91c5b0b31dd3fc02fa623b4bb13327f0cd4fc80"},
-    {file = "llvmlite-0.34.0-cp38-cp38-win_amd64.whl", hash = "sha256:964f8f7a2184963cb3617d057c2382575953e488b7bb061b632ee014cfef110a"},
-    {file = "llvmlite-0.34.0.tar.gz", hash = "sha256:f03ee0d19bca8f2fe922bb424a909d05c28411983b0c2bc58b020032a0d11f63"},
+    {file = "llvmlite-0.38.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0497a19428083a0544663732a925994d74e3b15c3c94946c6e7b6bf21a391264"},
+    {file = "llvmlite-0.38.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b040d392e998582883cd680e81afb4cd2d331d69cb93d605c735bfd2caa09805"},
+    {file = "llvmlite-0.38.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8b88cc3c6c0010df8a720c777ef1c0879d304404e0727c4ac9e3dc98d5815e10"},
+    {file = "llvmlite-0.38.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87805405ccdd1add51f51d85997fbff01c920adf4da600dbe197e1f3eebd1e57"},
+    {file = "llvmlite-0.38.0-cp310-cp310-win32.whl", hash = "sha256:17140e1462aa7f9250428fff7dd24187ea30498034a832bdb7385cbdc28fd4bf"},
+    {file = "llvmlite-0.38.0-cp310-cp310-win_amd64.whl", hash = "sha256:c0f11feda33f2b49abf5acc11828eebb3098050bbf6cd1cd75e2b05eb7676cb1"},
+    {file = "llvmlite-0.38.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f7a438917c30e87ac79bb89c773c100560dc346e0f0b03aabd88a6f6de3556c6"},
+    {file = "llvmlite-0.38.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e8bbb8e97d7cc0b6d124ba9f8577955fdc7639715f925c410abe02d2bc92862"},
+    {file = "llvmlite-0.38.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5845432b4660c530d27c46434b9669290f205d9b1c1e02e52f43f6d11782b4be"},
+    {file = "llvmlite-0.38.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a91e25488609cc91db91de206e023b7fe0889ac007adb31c713e685384497ba"},
+    {file = "llvmlite-0.38.0-cp37-cp37m-win32.whl", hash = "sha256:2426bfff67fdab577c7d5321c252d880434911caa6f9152f5be98da71b30e084"},
+    {file = "llvmlite-0.38.0-cp37-cp37m-win_amd64.whl", hash = "sha256:6b48c8fffc3512a2e97c6f70deb09eb49c419af66ced79e317cc2323117dcec6"},
+    {file = "llvmlite-0.38.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e1095557a27b041f1217036e568a5449d4b385c2415cb4316b2f5476f96e9a58"},
+    {file = "llvmlite-0.38.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:081d9c36d8e012b86bac02af49e225d883975ab5978ba33c3cc291474620c84d"},
+    {file = "llvmlite-0.38.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:63e178c6f7872a39572e210cb266fb6db6386f5e622e2d8c79491b6d8c7aa942"},
+    {file = "llvmlite-0.38.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48558fddce5ff351f9de98beff35888aa351598e5635b3b91d67ec9e10d458cc"},
+    {file = "llvmlite-0.38.0-cp38-cp38-win32.whl", hash = "sha256:7e07bacc2bb2ef1bf33dbf64d4bd13330baeae2287902100b144e43bcd1b066b"},
+    {file = "llvmlite-0.38.0-cp38-cp38-win_amd64.whl", hash = "sha256:37b66bf3624dd0b3739b4cf1b3cc3735dbe7799bc90d2a7a79a54b0ce37e1a38"},
+    {file = "llvmlite-0.38.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f43861f382b954fbf2ff88db5f13b00ac11ec4353445d3ba80e1eadcdd06c149"},
+    {file = "llvmlite-0.38.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fb7cb2907814dd03a152549d1c4dfee4854881d9cc7da85414b77903a681aa6"},
+    {file = "llvmlite-0.38.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c967b96d708556597e003217fd99f0c20e73d09c91d6d5054c538becc396ba79"},
+    {file = "llvmlite-0.38.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b2838898c80557e959f83fb28d260e5e2301396f34830f3ec6811ae53f6be"},
+    {file = "llvmlite-0.38.0-cp39-cp39-win32.whl", hash = "sha256:de321a680690d1ce040f34294d215ed0ac5fdcf7c98f044d11ac9b9d9ebc969f"},
+    {file = "llvmlite-0.38.0-cp39-cp39-win_amd64.whl", hash = "sha256:70734d46c2611f3fe765985fe356aaec393dc79bbd735f7f4d23f910b5148dc3"},
+    {file = "llvmlite-0.38.0.tar.gz", hash = "sha256:a99d166ccf3b116f3b9ed23b9b70ba2415640a9c978f3aaa13fad49c58f4965c"},
 ]
 locket = [
     {file = "locket-0.2.1-py2.py3-none-any.whl", hash = "sha256:12b6ada59d1f50710bca9704dbadd3f447dbf8dac6664575c1281cadab8e6449"},
     {file = "locket-0.2.1.tar.gz", hash = "sha256:3e1faba403619fe201552f083f1ecbf23f550941bc51985ac6ed4d02d25056dd"},
 ]
+markupsafe = [
+    {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"},
+    {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"},
+]
 matplotlib = [
     {file = "matplotlib-3.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c988bb43414c7c2b0a31bd5187b4d27fd625c080371b463a6d422047df78913"},
     {file = "matplotlib-3.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f1c5efc278d996af8a251b2ce0b07bbeccb821f25c8c9846bdcb00ffc7f158aa"},
@@ -2441,46 +2882,51 @@ mdf-toolbox = [
     {file = "mdf_toolbox-0.5.12.tar.gz", hash = "sha256:1373404afaf4e3247f348daeeba2b8b7e8f9d1acbd834aeb782329326f0f6e9a"},
 ]
 monty = [
-    {file = "monty-2022.1.12.1-py3-none-any.whl", hash = "sha256:40ebfcfdc08a843e30126dcb73507b6998d3a50cc24c691e5dcb21dca9d7bab6"},
-    {file = "monty-2022.1.12.1.tar.gz", hash = "sha256:54cbf726bddbb310665dc014dc79bf4c86fc6cc704e59470ccce5247050d255a"},
-]
-more-itertools = [
-    {file = "more-itertools-8.12.0.tar.gz", hash = "sha256:7dc6ad46f05f545f900dd59e8dfb4e84a4827b97b3cfecb175ea0c7d247f6064"},
-    {file = "more_itertools-8.12.0-py3-none-any.whl", hash = "sha256:43e6dd9942dffd72661a2c4ef383ad7da1e6a3e968a927ad7a6083ab410a688b"},
+    {file = "monty-2022.3.12-py3-none-any.whl", hash = "sha256:4c10a10c7147f4ca4173afbe346c0eb2245e9de75fd88ddbc26e9b36fe2ce516"},
+    {file = "monty-2022.3.12.tar.gz", hash = "sha256:43a542af553cde7ba9a9614e33e859100615d42e75fb877ee12f9805d56635df"},
 ]
 mpmath = [
     {file = "mpmath-1.2.1-py3-none-any.whl", hash = "sha256:604bc21bd22d2322a177c73bdb573994ef76e62edd595d17e00aff24b0667e5c"},
     {file = "mpmath-1.2.1.tar.gz", hash = "sha256:79ffb45cf9f4b101a807595bcb3e72e0396202e0b1d25d689134b48c4216a81a"},
 ]
 natsort = [
-    {file = "natsort-8.0.2-py3-none-any.whl", hash = "sha256:09cff3cabb617f9794f643758ab5b337c1c0af1a6df11edf5c04de496fd7fb26"},
-    {file = "natsort-8.0.2.tar.gz", hash = "sha256:feb87e0ce1dc1f8f3f21e18a85216c790e746d76a5ff6889563394605f504a2b"},
+    {file = "natsort-8.1.0-py3-none-any.whl", hash = "sha256:f59988d2f24e77b6b56f8a8f882d5df6b3b637e09e075abc67b486d59fba1a4b"},
+    {file = "natsort-8.1.0.tar.gz", hash = "sha256:c7c1f3f27c375719a4dfcab353909fe39f26c2032a062a8c80cc844eaaca0445"},
 ]
 nest-asyncio = [
-    {file = "nest_asyncio-1.5.4-py3-none-any.whl", hash = "sha256:3fdd0d6061a2bb16f21fe8a9c6a7945be83521d81a0d15cff52e9edee50101d6"},
-    {file = "nest_asyncio-1.5.4.tar.gz", hash = "sha256:f969f6013a16fadb4adcf09d11a68a4f617c6049d7af7ac2c676110169a63abd"},
+    {file = "nest_asyncio-1.5.5-py3-none-any.whl", hash = "sha256:b98e3ec1b246135e4642eceffa5a6c23a3ab12c82ff816a92c612d68205813b2"},
+    {file = "nest_asyncio-1.5.5.tar.gz", hash = "sha256:e442291cd942698be619823a17a86a5759eabe1f8613084790de189fe9e16d65"},
 ]
 networkx = [
-    {file = "networkx-2.6.3-py3-none-any.whl", hash = "sha256:80b6b89c77d1dfb64a4c7854981b60aeea6360ac02c6d4e4913319e0a313abef"},
-    {file = "networkx-2.6.3.tar.gz", hash = "sha256:c0946ed31d71f1b732b5aaa6da5a0388a345019af232ce2f49c766e2d6795c51"},
+    {file = "networkx-2.8-py3-none-any.whl", hash = "sha256:1a1e8fe052cc1b4e0339b998f6795099562a264a13a5af7a32cad45ab9d4e126"},
+    {file = "networkx-2.8.tar.gz", hash = "sha256:4a52cf66aed221955420e11b3e2e05ca44196b4829aab9576d4d439212b0a14f"},
 ]
 numba = [
-    {file = "numba-0.51.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:af798310eeb318c56cdb83254abbe9a938cc0182d08671d7f9f032dc817e064d"},
-    {file = "numba-0.51.2-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:93e18350f2094e7432321c1275730a3143b94af012fb609cc180fa376c44867f"},
-    {file = "numba-0.51.2-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:9e2bb1f129bfadd757ad7a9c18ab79c3ab25ce6d6a68e58565d6c52ad07b3566"},
-    {file = "numba-0.51.2-cp36-cp36m-win32.whl", hash = "sha256:31cdf6b6d1301d5fb6c4fcb8b4c711ba5c9f60ba2fca008b550da9b56185367c"},
-    {file = "numba-0.51.2-cp36-cp36m-win_amd64.whl", hash = "sha256:df6edca13c04a31fdb5addf5205199478a7da372712829157ef491e8a6e7031f"},
-    {file = "numba-0.51.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:a628122dacfcba9a3ea68a9e95578c6b6391016e34962c46550ea8e189e0412e"},
-    {file = "numba-0.51.2-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:106736d5a8dab6bebce989d4ab1b3f169c264582598f172e6e5b736210d2e834"},
-    {file = "numba-0.51.2-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:a12f16fdb4ca5edc94e2ef412e4e768c29217ef9b6fdfc237d064ebe30acfe14"},
-    {file = "numba-0.51.2-cp37-cp37m-win32.whl", hash = "sha256:025b033fd31c44bba17802293c81270084b5454b5b055b8c10c394385c232f00"},
-    {file = "numba-0.51.2-cp37-cp37m-win_amd64.whl", hash = "sha256:081788f584fa500339e9b74bf02e3c5029d408c114e555ada19cae0b92721416"},
-    {file = "numba-0.51.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:5416b584183fd599afda11b947b64f89450fcf26a9c15b408167f412b98a3a94"},
-    {file = "numba-0.51.2-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:05da65dca2ac28a192c9d8f20e9e477eb1237205cfc4d131c414f5f8092c6639"},
-    {file = "numba-0.51.2-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:aee435e3b7e465dd49971f8ea76aa414532a87736916cb399534e017334d1138"},
-    {file = "numba-0.51.2-cp38-cp38-win32.whl", hash = "sha256:bbbe2432433b11d3fadab0226a84c1a81918cb905ba1aeb022249e8d2ba8856c"},
-    {file = "numba-0.51.2-cp38-cp38-win_amd64.whl", hash = "sha256:259e7c15b24feec4a99fb41eb8c47b5ad49b544d1a5ad40ad0252ef531ba06fd"},
-    {file = "numba-0.51.2.tar.gz", hash = "sha256:16bd59572114adbf5f600ea383880d7b2071ae45477e84a24994e089ea390768"},
+    {file = "numba-0.55.1-1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:be56fb78303973e6c19c7c2759996a5863bac69ca87570543d9f18f2f287a441"},
+    {file = "numba-0.55.1-1-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:ee71407be9cba09b4f68afa668317e97d66d5f83c37ab4caa20d8abcf5fad32b"},
+    {file = "numba-0.55.1-1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:39a109efc317e8eb786feff0a29476036971ce08e3280be8153c3b6c1ccba415"},
+    {file = "numba-0.55.1-1-cp37-cp37m-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0dc8294b2b6b2dbe3a709787bbb1e6f9dcef62197429de8daaa714d77052eefe"},
+    {file = "numba-0.55.1-1-cp37-cp37m-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:bcd5e09dba5e19ff7a1b9716a1ce58f0931cec09515683011e57415c6a33ac3d"},
+    {file = "numba-0.55.1-1-cp37-cp37m-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:64209d71b1e33415d5b1b177ed218d679062f844667dd279ee9094c4e3e2babc"},
+    {file = "numba-0.55.1-1-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff5ed5c7665f8a5405af53332d224caca68358909abde9ca8dfef3495cdea789"},
+    {file = "numba-0.55.1-1-cp38-cp38-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:d80afc5618e66af2d101eff0e6214acb865136ae886d8b01414ca3dedd9166d6"},
+    {file = "numba-0.55.1-1-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6d0042371880fa56ed58be27502b11a08bff0b6335f0ebde82af1a7aef5e1287"},
+    {file = "numba-0.55.1-1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4a5cb8930e729aeed96809524ca4df41b6f2432b379f220014ef4fdff21dbfe6"},
+    {file = "numba-0.55.1-1-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:fee529ddc9c0584b932f7885735162e52344eded8c01c78c17e2768aa6787780"},
+    {file = "numba-0.55.1-1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:230e542649c7087454bc851d2e22b5e15694b6cf0549a27234d1baea6c2e0a87"},
+    {file = "numba-0.55.1-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:adc88fe64f5235c8b1e7230ae29476a08ffb61a65e9f79f745bd357f215e2d52"},
+    {file = "numba-0.55.1-cp310-cp310-win32.whl", hash = "sha256:a5af7f1d30f56029d1b9ea288372f924f9dcb322f0e6358f6d5203b20eb6f7a0"},
+    {file = "numba-0.55.1-cp310-cp310-win_amd64.whl", hash = "sha256:71815c501b2f6309c432e98ff93a582a9bfb61da943e0cb9a52595fadbb1131d"},
+    {file = "numba-0.55.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:53909143917ea4962cfbfae7038ac882987ff54cb2c408538ce71f83b356f106"},
+    {file = "numba-0.55.1-cp37-cp37m-win32.whl", hash = "sha256:cddc13939e2b27782258826686800ae9c2e90b35c36ef1ab5ccfae7cedca0516"},
+    {file = "numba-0.55.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ac6ae19ff5093a42bf8b365550322a2e39650d608daa379dff71571272d88d93"},
+    {file = "numba-0.55.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:77187ed09e6b25ae24b840e1acc4b5f9886b551cdc5f919ddad8e5933a6027d5"},
+    {file = "numba-0.55.1-cp38-cp38-win32.whl", hash = "sha256:53ee562b873e00eaa26390690ac5d36b706782d429e5a18b255161f607f13c17"},
+    {file = "numba-0.55.1-cp38-cp38-win_amd64.whl", hash = "sha256:02fb0ecd218ab1e1171cbaee11235a3a1f7dcf79dee3fa786243a2a6411f2fea"},
+    {file = "numba-0.55.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:6aa8f18a003a0e4876826fe080e6038fc6da083899873b77172ec29c32e49b56"},
+    {file = "numba-0.55.1-cp39-cp39-win32.whl", hash = "sha256:d5ee721ce884f8313802295633fdd3e7c83541e0917bafea2bdfed6aabab93bf"},
+    {file = "numba-0.55.1-cp39-cp39-win_amd64.whl", hash = "sha256:b72350160eb9a73a36aa17d808f954353a263a0295d495497c87439d79bdaec7"},
+    {file = "numba-0.55.1.tar.gz", hash = "sha256:03e9069a2666d1c84f93b00dbd716fb8fedde8bb2c6efafa2f04842a46442ea3"},
 ]
 numexpr = [
     {file = "numexpr-2.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d148e99483e15de22d0acd5100136d39a336e91c8f8d37bf2e84e9f0ab4c0610"},
@@ -2511,34 +2957,36 @@ numexpr = [
     {file = "numexpr-2.8.1.tar.gz", hash = "sha256:cd779aa44dd986c4ef10163519239602b027be06a527946656207acf1f58113b"},
 ]
 numpy = [
-    {file = "numpy-1.21.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38e8648f9449a549a7dfe8d8755a5979b45b3538520d1e735637ef28e8c2dc50"},
-    {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fd7d7409fa643a91d0a05c7554dd68aa9c9bb16e186f6ccfe40d6e003156e33a"},
-    {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a75b4498b1e93d8b700282dc8e655b8bd559c0904b3910b144646dbbbc03e062"},
-    {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1412aa0aec3e00bc23fbb8664d76552b4efde98fb71f60737c83efbac24112f1"},
-    {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e46ceaff65609b5399163de5893d8f2a82d3c77d5e56d976c8b5fb01faa6b671"},
-    {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c6a2324085dd52f96498419ba95b5777e40b6bcbc20088fddb9e8cbb58885e8e"},
-    {file = "numpy-1.21.1-cp37-cp37m-win32.whl", hash = "sha256:73101b2a1fef16602696d133db402a7e7586654682244344b8329cdcbbb82172"},
-    {file = "numpy-1.21.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7a708a79c9a9d26904d1cca8d383bf869edf6f8e7650d85dbc77b041e8c5a0f8"},
-    {file = "numpy-1.21.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95b995d0c413f5d0428b3f880e8fe1660ff9396dcd1f9eedbc311f37b5652e16"},
-    {file = "numpy-1.21.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:635e6bd31c9fb3d475c8f44a089569070d10a9ef18ed13738b03049280281267"},
-    {file = "numpy-1.21.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a3d5fb89bfe21be2ef47c0614b9c9c707b7362386c9a3ff1feae63e0267ccb6"},
-    {file = "numpy-1.21.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a326af80e86d0e9ce92bcc1e65c8ff88297de4fa14ee936cb2293d414c9ec63"},
-    {file = "numpy-1.21.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:791492091744b0fe390a6ce85cc1bf5149968ac7d5f0477288f78c89b385d9af"},
-    {file = "numpy-1.21.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0318c465786c1f63ac05d7c4dbcecd4d2d7e13f0959b01b534ea1e92202235c5"},
-    {file = "numpy-1.21.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a513bd9c1551894ee3d31369f9b07460ef223694098cf27d399513415855b68"},
-    {file = "numpy-1.21.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:91c6f5fc58df1e0a3cc0c3a717bb3308ff850abdaa6d2d802573ee2b11f674a8"},
-    {file = "numpy-1.21.1-cp38-cp38-win32.whl", hash = "sha256:978010b68e17150db8765355d1ccdd450f9fc916824e8c4e35ee620590e234cd"},
-    {file = "numpy-1.21.1-cp38-cp38-win_amd64.whl", hash = "sha256:9749a40a5b22333467f02fe11edc98f022133ee1bfa8ab99bda5e5437b831214"},
-    {file = "numpy-1.21.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d7a4aeac3b94af92a9373d6e77b37691b86411f9745190d2c351f410ab3a791f"},
-    {file = "numpy-1.21.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d9e7912a56108aba9b31df688a4c4f5cb0d9d3787386b87d504762b6754fbb1b"},
-    {file = "numpy-1.21.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:25b40b98ebdd272bc3020935427a4530b7d60dfbe1ab9381a39147834e985eac"},
-    {file = "numpy-1.21.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a92c5aea763d14ba9d6475803fc7904bda7decc2a0a68153f587ad82941fec1"},
-    {file = "numpy-1.21.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05a0f648eb28bae4bcb204e6fd14603de2908de982e761a2fc78efe0f19e96e1"},
-    {file = "numpy-1.21.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f01f28075a92eede918b965e86e8f0ba7b7797a95aa8d35e1cc8821f5fc3ad6a"},
-    {file = "numpy-1.21.1-cp39-cp39-win32.whl", hash = "sha256:88c0b89ad1cc24a5efbb99ff9ab5db0f9a86e9cc50240177a571fbe9c2860ac2"},
-    {file = "numpy-1.21.1-cp39-cp39-win_amd64.whl", hash = "sha256:01721eefe70544d548425a07c80be8377096a54118070b8a62476866d5208e33"},
-    {file = "numpy-1.21.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2d4d1de6e6fb3d28781c73fbde702ac97f03d79e4ffd6598b880b2d95d62ead4"},
-    {file = "numpy-1.21.1.zip", hash = "sha256:dff4af63638afcc57a3dfb9e4b26d434a7a602d225b42d746ea7fe2edf1342fd"},
+    {file = "numpy-1.21.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:301e408a052fdcda5cdcf03021ebafc3c6ea093021bf9d1aa47c54d48bdad166"},
+    {file = "numpy-1.21.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a7e8f6216f180f3fd4efb73de5d1eaefb5f5a1ee5b645c67333033e39440e63a"},
+    {file = "numpy-1.21.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fc7a7d7b0ed72589fd8b8486b9b42a564f10b8762be8bd4d9df94b807af4a089"},
+    {file = "numpy-1.21.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58ca1d7c8aef6e996112d0ce873ac9dfa1eaf4a1196b4ff7ff73880a09923ba7"},
+    {file = "numpy-1.21.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc4b2fb01f1b4ddbe2453468ea0719f4dbb1f5caa712c8b21bb3dd1480cd30d9"},
+    {file = "numpy-1.21.5-cp310-cp310-win_amd64.whl", hash = "sha256:cc1b30205d138d1005adb52087ff45708febbef0e420386f58664f984ef56954"},
+    {file = "numpy-1.21.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:08de8472d9f7571f9d51b27b75e827f5296295fa78817032e84464be8bb905bc"},
+    {file = "numpy-1.21.5-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4fe6a006557b87b352c04596a6e3f12a57d6e5f401d804947bd3188e6b0e0e76"},
+    {file = "numpy-1.21.5-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3d893b0871322eaa2f8c7072cdb552d8e2b27645b7875a70833c31e9274d4611"},
+    {file = "numpy-1.21.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:341dddcfe3b7b6427a28a27baa59af5ad51baa59bfec3264f1ab287aa3b30b13"},
+    {file = "numpy-1.21.5-cp37-cp37m-win32.whl", hash = "sha256:ca9c23848292c6fe0a19d212790e62f398fd9609aaa838859be8459bfbe558aa"},
+    {file = "numpy-1.21.5-cp37-cp37m-win_amd64.whl", hash = "sha256:025b497014bc33fc23897859350f284323f32a2fff7654697f5a5fc2a19e9939"},
+    {file = "numpy-1.21.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3a5098df115340fb17fc93867317a947e1dcd978c3888c5ddb118366095851f8"},
+    {file = "numpy-1.21.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:311283acf880cfcc20369201bd75da907909afc4666966c7895cbed6f9d2c640"},
+    {file = "numpy-1.21.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b545ebadaa2b878c8630e5bcdb97fc4096e779f335fc0f943547c1c91540c815"},
+    {file = "numpy-1.21.5-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c5562bcc1a9b61960fc8950ade44d00e3de28f891af0acc96307c73613d18f6e"},
+    {file = "numpy-1.21.5-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:eed2afaa97ec33b4411995be12f8bdb95c87984eaa28d76cf628970c8a2d689a"},
+    {file = "numpy-1.21.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61bada43d494515d5b122f4532af226fdb5ee08fe5b5918b111279843dc6836a"},
+    {file = "numpy-1.21.5-cp38-cp38-win32.whl", hash = "sha256:7b9d6b14fc9a4864b08d1ba57d732b248f0e482c7b2ff55c313137e3ed4d8449"},
+    {file = "numpy-1.21.5-cp38-cp38-win_amd64.whl", hash = "sha256:dbce7adeb66b895c6aaa1fad796aaefc299ced597f6fbd9ceddb0dd735245354"},
+    {file = "numpy-1.21.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:507c05c7a37b3683eb08a3ff993bd1ee1e6c752f77c2f275260533b265ecdb6c"},
+    {file = "numpy-1.21.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:00c9fa73a6989895b8815d98300a20ac993c49ac36c8277e8ffeaa3631c0dbbb"},
+    {file = "numpy-1.21.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:69a5a8d71c308d7ef33ef72371c2388a90e3495dbb7993430e674006f94797d5"},
+    {file = "numpy-1.21.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2d8adfca843bc46ac199a4645233f13abf2011a0b2f4affc5c37cd552626f27b"},
+    {file = "numpy-1.21.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c293d3c0321996cd8ffe84215ffe5d269fd9d1d12c6f4ffe2b597a7c30d3e593"},
+    {file = "numpy-1.21.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c978544be9e04ed12016dd295a74283773149b48f507d69b36f91aa90a643e5"},
+    {file = "numpy-1.21.5-cp39-cp39-win32.whl", hash = "sha256:2a9add27d7fc0fdb572abc3b2486eb3b1395da71e0254c5552b2aad2a18b5441"},
+    {file = "numpy-1.21.5-cp39-cp39-win_amd64.whl", hash = "sha256:1964db2d4a00348b7a60ee9d013c8cb0c566644a589eaa80995126eac3b99ced"},
+    {file = "numpy-1.21.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a7c4b701ca418cd39e28ec3b496e6388fe06de83f5f0cb74794fa31cfa384c02"},
+    {file = "numpy-1.21.5.zip", hash = "sha256:6a5928bc6241264dce5ed509e66f33676fc97f464e7a919edc672fb5532221ee"},
 ]
 openpyxl = [
     {file = "openpyxl-3.0.9-py2.py3-none-any.whl", hash = "sha256:8f3b11bd896a95468a4ab162fc4fcd260d46157155d1f8bfaabb99d88cfcf79f"},
@@ -2553,30 +3001,27 @@ palettable = [
     {file = "palettable-3.3.0.tar.gz", hash = "sha256:72feca71cf7d79830cd6d9181b02edf227b867d503bec953cf9fa91bf44896bd"},
 ]
 pandas = [
-    {file = "pandas-1.1.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:bf23a3b54d128b50f4f9d4675b3c1857a688cc6731a32f931837d72effb2698d"},
-    {file = "pandas-1.1.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5a780260afc88268a9d3ac3511d8f494fdcf637eece62fb9eb656a63d53eb7ca"},
-    {file = "pandas-1.1.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:b61080750d19a0122469ab59b087380721d6b72a4e7d962e4d7e63e0c4504814"},
-    {file = "pandas-1.1.5-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:0de3ddb414d30798cbf56e642d82cac30a80223ad6fe484d66c0ce01a84d6f2f"},
-    {file = "pandas-1.1.5-cp36-cp36m-win32.whl", hash = "sha256:70865f96bb38fec46f7ebd66d4b5cfd0aa6b842073f298d621385ae3898d28b5"},
-    {file = "pandas-1.1.5-cp36-cp36m-win_amd64.whl", hash = "sha256:19a2148a1d02791352e9fa637899a78e371a3516ac6da5c4edc718f60cbae648"},
-    {file = "pandas-1.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:26fa92d3ac743a149a31b21d6f4337b0594b6302ea5575b37af9ca9611e8981a"},
-    {file = "pandas-1.1.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c16d59c15d946111d2716856dd5479221c9e4f2f5c7bc2d617f39d870031e086"},
-    {file = "pandas-1.1.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3be7a7a0ca71a2640e81d9276f526bca63505850add10206d0da2e8a0a325dae"},
-    {file = "pandas-1.1.5-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:573fba5b05bf2c69271a32e52399c8de599e4a15ab7cec47d3b9c904125ab788"},
-    {file = "pandas-1.1.5-cp37-cp37m-win32.whl", hash = "sha256:21b5a2b033380adbdd36b3116faaf9a4663e375325831dac1b519a44f9e439bb"},
-    {file = "pandas-1.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:24c7f8d4aee71bfa6401faeba367dd654f696a77151a8a28bc2013f7ced4af98"},
-    {file = "pandas-1.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2860a97cbb25444ffc0088b457da0a79dc79f9c601238a3e0644312fcc14bf11"},
-    {file = "pandas-1.1.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5008374ebb990dad9ed48b0f5d0038124c73748f5384cc8c46904dace27082d9"},
-    {file = "pandas-1.1.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2c2f7c670ea4e60318e4b7e474d56447cf0c7d83b3c2a5405a0dbb2600b9c48e"},
-    {file = "pandas-1.1.5-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:0a643bae4283a37732ddfcecab3f62dd082996021b980f580903f4e8e01b3c5b"},
-    {file = "pandas-1.1.5-cp38-cp38-win32.whl", hash = "sha256:5447ea7af4005b0daf695a316a423b96374c9c73ffbd4533209c5ddc369e644b"},
-    {file = "pandas-1.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:4c62e94d5d49db116bef1bd5c2486723a292d79409fc9abd51adf9e05329101d"},
-    {file = "pandas-1.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:731568be71fba1e13cae212c362f3d2ca8932e83cb1b85e3f1b4dd77d019254a"},
-    {file = "pandas-1.1.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:c61c043aafb69329d0f961b19faa30b1dab709dd34c9388143fc55680059e55a"},
-    {file = "pandas-1.1.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:2b1c6cd28a0dfda75c7b5957363333f01d370936e4c6276b7b8e696dd500582a"},
-    {file = "pandas-1.1.5-cp39-cp39-win32.whl", hash = "sha256:c94ff2780a1fd89f190390130d6d36173ca59fcfb3fe0ff596f9a56518191ccb"},
-    {file = "pandas-1.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:edda9bacc3843dfbeebaf7a701763e68e741b08fccb889c003b0a52f0ee95782"},
-    {file = "pandas-1.1.5.tar.gz", hash = "sha256:f10fc41ee3c75a474d3bdf68d396f10782d013d7f67db99c0efbfd0acb99701b"},
+    {file = "pandas-1.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:be67c782c4f1b1f24c2f16a157e12c2693fd510f8df18e3287c77f33d124ed07"},
+    {file = "pandas-1.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5a206afa84ed20e07603f50d22b5f0db3fb556486d8c2462d8bc364831a4b417"},
+    {file = "pandas-1.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0010771bd9223f7afe5f051eb47c4a49534345dfa144f2f5470b27189a4dd3b5"},
+    {file = "pandas-1.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3228198333dd13c90b6434ddf61aa6d57deaca98cf7b654f4ad68a2db84f8cfe"},
+    {file = "pandas-1.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b79af3a69e5175c6fa7b4e046b21a646c8b74e92c6581a9d825687d92071b51"},
+    {file = "pandas-1.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:5586cc95692564b441f4747c47c8a9746792e87b40a4680a2feb7794defb1ce3"},
+    {file = "pandas-1.4.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:061609334a8182ab500a90fe66d46f6f387de62d3a9cb9aa7e62e3146c712167"},
+    {file = "pandas-1.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b8134651258bce418cb79c71adeff0a44090c98d955f6953168ba16cc285d9f7"},
+    {file = "pandas-1.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:df82739e00bb6daf4bba4479a40f38c718b598a84654cbd8bb498fd6b0aa8c16"},
+    {file = "pandas-1.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:385c52e85aaa8ea6a4c600a9b2821181a51f8be0aee3af6f2dcb41dafc4fc1d0"},
+    {file = "pandas-1.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:295872bf1a09758aba199992c3ecde455f01caf32266d50abc1a073e828a7b9d"},
+    {file = "pandas-1.4.2-cp38-cp38-win32.whl", hash = "sha256:95c1e422ced0199cf4a34385ff124b69412c4bc912011ce895582bee620dfcaa"},
+    {file = "pandas-1.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:5c54ea4ef3823108cd4ec7fb27ccba4c3a775e0f83e39c5e17f5094cb17748bc"},
+    {file = "pandas-1.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c072c7f06b9242c855ed8021ff970c0e8f8b10b35e2640c657d2a541c5950f59"},
+    {file = "pandas-1.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f549097993744ff8c41b5e8f2f0d3cbfaabe89b4ae32c8c08ead6cc535b80139"},
+    {file = "pandas-1.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ff08a14ef21d94cdf18eef7c569d66f2e24e0bc89350bcd7d243dd804e3b5eb2"},
+    {file = "pandas-1.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c5bf555b6b0075294b73965adaafb39cf71c312e38c5935c93d78f41c19828a"},
+    {file = "pandas-1.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51649ef604a945f781105a6d2ecf88db7da0f4868ac5d45c51cb66081c4d9c73"},
+    {file = "pandas-1.4.2-cp39-cp39-win32.whl", hash = "sha256:d0d4f13e4be7ce89d7057a786023c461dd9370040bdb5efa0a7fe76b556867a0"},
+    {file = "pandas-1.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:09d8be7dd9e1c4c98224c4dfe8abd60d145d934e9fc1f5f411266308ae683e6a"},
+    {file = "pandas-1.4.2.tar.gz", hash = "sha256:92bc1fc585f1463ca827b45535957815b7deb218c549b7c18402c322c7549a12"},
 ]
 parso = [
     {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"},
@@ -2587,8 +3032,8 @@ partd = [
     {file = "partd-1.2.0.tar.gz", hash = "sha256:aa67897b84d522dcbc86a98b942afab8c6aa2f7f677d904a616b74ef5ddbc3eb"},
 ]
 pbr = [
-    {file = "pbr-5.8.0-py2.py3-none-any.whl", hash = "sha256:176e8560eaf61e127817ef93d8a844803abb27a4d4637f0ff3bb783129be2e0a"},
-    {file = "pbr-5.8.0.tar.gz", hash = "sha256:672d8ebee84921862110f23fcec2acea191ef58543d34dfe9ef3d9f13c31cddf"},
+    {file = "pbr-5.8.1-py2.py3-none-any.whl", hash = "sha256:27108648368782d07bbf1cb468ad2e2eeef29086affd14087a6d04b7de8af4ec"},
+    {file = "pbr-5.8.1.tar.gz", hash = "sha256:66bc5a34912f408bb3925bf21231cb6f59206267b7f63f3503ef865c1a292e25"},
 ]
 pexpect = [
     {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"},
@@ -2599,50 +3044,67 @@ pickleshare = [
     {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"},
 ]
 pillow = [
-    {file = "Pillow-7.2.0-cp35-cp35m-macosx_10_10_intel.whl", hash = "sha256:1ca594126d3c4def54babee699c055a913efb01e106c309fa6b04405d474d5ae"},
-    {file = "Pillow-7.2.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c92302a33138409e8f1ad16731568c55c9053eee71bb05b6b744067e1b62380f"},
-    {file = "Pillow-7.2.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:8dad18b69f710bf3a001d2bf3afab7c432785d94fcf819c16b5207b1cfd17d38"},
-    {file = "Pillow-7.2.0-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:431b15cffbf949e89df2f7b48528be18b78bfa5177cb3036284a5508159492b5"},
-    {file = "Pillow-7.2.0-cp35-cp35m-win32.whl", hash = "sha256:09d7f9e64289cb40c2c8d7ad674b2ed6105f55dc3b09aa8e4918e20a0311e7ad"},
-    {file = "Pillow-7.2.0-cp35-cp35m-win_amd64.whl", hash = "sha256:0295442429645fa16d05bd567ef5cff178482439c9aad0411d3f0ce9b88b3a6f"},
-    {file = "Pillow-7.2.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:ec29604081f10f16a7aea809ad42e27764188fc258b02259a03a8ff7ded3808d"},
-    {file = "Pillow-7.2.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:612cfda94e9c8346f239bf1a4b082fdd5c8143cf82d685ba2dba76e7adeeb233"},
-    {file = "Pillow-7.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0a80dd307a5d8440b0a08bd7b81617e04d870e40a3e46a32d9c246e54705e86f"},
-    {file = "Pillow-7.2.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:06aba4169e78c439d528fdeb34762c3b61a70813527a2c57f0540541e9f433a8"},
-    {file = "Pillow-7.2.0-cp36-cp36m-win32.whl", hash = "sha256:f7e30c27477dffc3e85c2463b3e649f751789e0f6c8456099eea7ddd53be4a8a"},
-    {file = "Pillow-7.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:ffe538682dc19cc542ae7c3e504fdf54ca7f86fb8a135e59dd6bc8627eae6cce"},
-    {file = "Pillow-7.2.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:94cf49723928eb6070a892cb39d6c156f7b5a2db4e8971cb958f7b6b104fb4c4"},
-    {file = "Pillow-7.2.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6edb5446f44d901e8683ffb25ebdfc26988ee813da3bf91e12252b57ac163727"},
-    {file = "Pillow-7.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:52125833b070791fcb5710fabc640fc1df07d087fc0c0f02d3661f76c23c5b8b"},
-    {file = "Pillow-7.2.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:9ad7f865eebde135d526bb3163d0b23ffff365cf87e767c649550964ad72785d"},
-    {file = "Pillow-7.2.0-cp37-cp37m-win32.whl", hash = "sha256:c79f9c5fb846285f943aafeafda3358992d64f0ef58566e23484132ecd8d7d63"},
-    {file = "Pillow-7.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d350f0f2c2421e65fbc62690f26b59b0bcda1b614beb318c81e38647e0f673a1"},
-    {file = "Pillow-7.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:6d7741e65835716ceea0fd13a7d0192961212fd59e741a46bbed7a473c634ed6"},
-    {file = "Pillow-7.2.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:edf31f1150778abd4322444c393ab9c7bd2af271dd4dafb4208fb613b1f3cdc9"},
-    {file = "Pillow-7.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:d08b23fdb388c0715990cbc06866db554e1822c4bdcf6d4166cf30ac82df8c41"},
-    {file = "Pillow-7.2.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:5e51ee2b8114def244384eda1c82b10e307ad9778dac5c83fb0943775a653cd8"},
-    {file = "Pillow-7.2.0-cp38-cp38-win32.whl", hash = "sha256:725aa6cfc66ce2857d585f06e9519a1cc0ef6d13f186ff3447ab6dff0a09bc7f"},
-    {file = "Pillow-7.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:a060cf8aa332052df2158e5a119303965be92c3da6f2d93b6878f0ebca80b2f6"},
-    {file = "Pillow-7.2.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:9c87ef410a58dd54b92424ffd7e28fd2ec65d2f7fc02b76f5e9b2067e355ebf6"},
-    {file = "Pillow-7.2.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:e901964262a56d9ea3c2693df68bc9860b8bdda2b04768821e4c44ae797de117"},
-    {file = "Pillow-7.2.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:25930fadde8019f374400f7986e8404c8b781ce519da27792cbe46eabec00c4d"},
-    {file = "Pillow-7.2.0.tar.gz", hash = "sha256:97f9e7953a77d5a70f49b9a48da7776dc51e9b738151b22dacf101641594a626"},
+    {file = "Pillow-9.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:af79d3fde1fc2e33561166d62e3b63f0cc3e47b5a3a2e5fea40d4917754734ea"},
+    {file = "Pillow-9.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:55dd1cf09a1fd7c7b78425967aacae9b0d70125f7d3ab973fadc7b5abc3de652"},
+    {file = "Pillow-9.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66822d01e82506a19407d1afc104c3fcea3b81d5eb11485e593ad6b8492f995a"},
+    {file = "Pillow-9.1.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5eaf3b42df2bcda61c53a742ee2c6e63f777d0e085bbc6b2ab7ed57deb13db7"},
+    {file = "Pillow-9.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01ce45deec9df310cbbee11104bae1a2a43308dd9c317f99235b6d3080ddd66e"},
+    {file = "Pillow-9.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aea7ce61328e15943d7b9eaca87e81f7c62ff90f669116f857262e9da4057ba3"},
+    {file = "Pillow-9.1.0-cp310-cp310-win32.whl", hash = "sha256:7a053bd4d65a3294b153bdd7724dce864a1d548416a5ef61f6d03bf149205160"},
+    {file = "Pillow-9.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:97bda660702a856c2c9e12ec26fc6d187631ddfd896ff685814ab21ef0597033"},
+    {file = "Pillow-9.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:21dee8466b42912335151d24c1665fcf44dc2ee47e021d233a40c3ca5adae59c"},
+    {file = "Pillow-9.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b6d4050b208c8ff886fd3db6690bf04f9a48749d78b41b7a5bf24c236ab0165"},
+    {file = "Pillow-9.1.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5cfca31ab4c13552a0f354c87fbd7f162a4fafd25e6b521bba93a57fe6a3700a"},
+    {file = "Pillow-9.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed742214068efa95e9844c2d9129e209ed63f61baa4d54dbf4cf8b5e2d30ccf2"},
+    {file = "Pillow-9.1.0-cp37-cp37m-win32.whl", hash = "sha256:c9efef876c21788366ea1f50ecb39d5d6f65febe25ad1d4c0b8dff98843ac244"},
+    {file = "Pillow-9.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:de344bcf6e2463bb25179d74d6e7989e375f906bcec8cb86edb8b12acbc7dfef"},
+    {file = "Pillow-9.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:17869489de2fce6c36690a0c721bd3db176194af5f39249c1ac56d0bb0fcc512"},
+    {file = "Pillow-9.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:25023a6209a4d7c42154073144608c9a71d3512b648a2f5d4465182cb93d3477"},
+    {file = "Pillow-9.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8782189c796eff29dbb37dd87afa4ad4d40fc90b2742704f94812851b725964b"},
+    {file = "Pillow-9.1.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:463acf531f5d0925ca55904fa668bb3461c3ef6bc779e1d6d8a488092bdee378"},
+    {file = "Pillow-9.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f42364485bfdab19c1373b5cd62f7c5ab7cc052e19644862ec8f15bb8af289e"},
+    {file = "Pillow-9.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3fddcdb619ba04491e8f771636583a7cc5a5051cd193ff1aa1ee8616d2a692c5"},
+    {file = "Pillow-9.1.0-cp38-cp38-win32.whl", hash = "sha256:4fe29a070de394e449fd88ebe1624d1e2d7ddeed4c12e0b31624561b58948d9a"},
+    {file = "Pillow-9.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:c24f718f9dd73bb2b31a6201e6db5ea4a61fdd1d1c200f43ee585fc6dcd21b34"},
+    {file = "Pillow-9.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fb89397013cf302f282f0fc998bb7abf11d49dcff72c8ecb320f76ea6e2c5717"},
+    {file = "Pillow-9.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c870193cce4b76713a2b29be5d8327c8ccbe0d4a49bc22968aa1e680930f5581"},
+    {file = "Pillow-9.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69e5ddc609230d4408277af135c5b5c8fe7a54b2bdb8ad7c5100b86b3aab04c6"},
+    {file = "Pillow-9.1.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35be4a9f65441d9982240e6966c1eaa1c654c4e5e931eaf580130409e31804d4"},
+    {file = "Pillow-9.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82283af99c1c3a5ba1da44c67296d5aad19f11c535b551a5ae55328a317ce331"},
+    {file = "Pillow-9.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a325ac71914c5c043fa50441b36606e64a10cd262de12f7a179620f579752ff8"},
+    {file = "Pillow-9.1.0-cp39-cp39-win32.whl", hash = "sha256:a598d8830f6ef5501002ae85c7dbfcd9c27cc4efc02a1989369303ba85573e58"},
+    {file = "Pillow-9.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:0c51cb9edac8a5abd069fd0758ac0a8bfe52c261ee0e330f363548aca6893595"},
+    {file = "Pillow-9.1.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a336a4f74baf67e26f3acc4d61c913e378e931817cd1e2ef4dfb79d3e051b481"},
+    {file = "Pillow-9.1.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb1b89b11256b5b6cad5e7593f9061ac4624f7651f7a8eb4dfa37caa1dfaa4d0"},
+    {file = "Pillow-9.1.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:255c9d69754a4c90b0ee484967fc8818c7ff8311c6dddcc43a4340e10cd1636a"},
+    {file = "Pillow-9.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5a3ecc026ea0e14d0ad7cd990ea7f48bfcb3eb4271034657dc9d06933c6629a7"},
+    {file = "Pillow-9.1.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5b0ff59785d93b3437c3703e3c64c178aabada51dea2a7f2c5eccf1bcf565a3"},
+    {file = "Pillow-9.1.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7110ec1701b0bf8df569a7592a196c9d07c764a0a74f65471ea56816f10e2c8"},
+    {file = "Pillow-9.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:8d79c6f468215d1a8415aa53d9868a6b40c4682165b8cb62a221b1baa47db458"},
+    {file = "Pillow-9.1.0.tar.gz", hash = "sha256:f401ed2bbb155e1ade150ccc63db1a4f6c1909d3d378f7d1235a44e90d75fb97"},
 ]
 pint = [
-    {file = "Pint-0.18-py2.py3-none-any.whl", hash = "sha256:4b37f3c470639ea6f96b0026c3364bde30631fa737092bdaf18ad3f4f76f252f"},
-    {file = "Pint-0.18.tar.gz", hash = "sha256:8c4bce884c269051feb7abc69dbfd18403c0c764abc83da132e8a7222f8ba801"},
+    {file = "Pint-0.19.1.tar.gz", hash = "sha256:3e5913e4ad125f672f72e19e06a8cb1f6d36a4922b6e5a49e04ff882511f82c8"},
+]
+platformdirs = [
+    {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"},
+    {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"},
+]
+plotly = [
+    {file = "plotly-5.7.0-py2.py3-none-any.whl", hash = "sha256:3a35131762c6567813012462e1d496e1d3898f56ab3d386b32f103f7f0c79cf1"},
+    {file = "plotly-5.7.0.tar.gz", hash = "sha256:15ab20e9ed8b55f669b3d35e186eb48f9e1fe07321a1337b8b7df8d3573d265a"},
 ]
 pluggy = [
     {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
     {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
 ]
 prettytable = [
-    {file = "prettytable-3.0.0-py3-none-any.whl", hash = "sha256:d55bc2547611bd8c40f1c69bbb8daf1b6b2c326214a265d211ec9c57fc252093"},
-    {file = "prettytable-3.0.0.tar.gz", hash = "sha256:69fe75d78ac8651e16dd61265b9e19626df5d630ae294fc31687aa6037b97a58"},
+    {file = "prettytable-3.2.0-py3-none-any.whl", hash = "sha256:f6c5ec87c3ef9df5bba1d32d826c1b862ecad0344dddb6082e3562caf71fe085"},
+    {file = "prettytable-3.2.0.tar.gz", hash = "sha256:ae7d96c64100543dc61662b40a28f3b03c0f94a503ed121c6fca2782c5816f81"},
 ]
 prompt-toolkit = [
-    {file = "prompt_toolkit-3.0.24-py3-none-any.whl", hash = "sha256:e56f2ff799bacecd3e88165b1e2f5ebf9bcd59e80e06d395fa0cc4b8bd7bb506"},
-    {file = "prompt_toolkit-3.0.24.tar.gz", hash = "sha256:1bb05628c7d87b645974a1bad3f17612be0c29fa39af9f7688030163f680bad6"},
+    {file = "prompt_toolkit-3.0.29-py3-none-any.whl", hash = "sha256:62291dad495e665fca0bda814e342c69952086afb0f4094d0893d357e5c78752"},
+    {file = "prompt_toolkit-3.0.29.tar.gz", hash = "sha256:bd640f60e8cecd74f0dc249713d433ace2ddc62b65ee07f96d358e0b152b6ea7"},
 ]
 psutil = [
     {file = "psutil-5.9.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:55ce319452e3d139e25d6c3f85a1acf12d1607ddedea5e35fb47a552c051161b"},
@@ -2682,47 +3144,50 @@ ptyprocess = [
     {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"},
     {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"},
 ]
+pure-eval = [
+    {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"},
+    {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"},
+]
 py = [
     {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
     {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
 ]
+pybtex = [
+    {file = "pybtex-0.24.0-py2.py3-none-any.whl", hash = "sha256:e1e0c8c69998452fea90e9179aa2a98ab103f3eed894405b7264e517cc2fcc0f"},
+    {file = "pybtex-0.24.0.tar.gz", hash = "sha256:818eae35b61733e5c007c3fcd2cfb75ed1bc8b4173c1f70b56cc4c0802d34755"},
+]
 pycalphad = [
-    {file = "pycalphad-0.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8ddcad22651ffa9d448a6ed765bdcc0691820689b107efc62816389e8320aa3"},
-    {file = "pycalphad-0.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:399e0745d3367dec451475d1156a8a4c7fc55d7997133155094c27a776dda61f"},
-    {file = "pycalphad-0.9.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f9868c901251eda9e6fc03a8b45fd7d0efed205cfdab38636eb7e606a7348c2e"},
-    {file = "pycalphad-0.9.2-cp37-cp37m-win32.whl", hash = "sha256:36b027df2c9e63946c15f6b3a86af469e356abc1bfabaf1011e8bcee2b05c4d7"},
-    {file = "pycalphad-0.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:e6f04c9b57f6cf1e9c507c62187ad95b70b3008e0dc20b22c86662b712a6e39e"},
-    {file = "pycalphad-0.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ae8b16f154d0b60647f987217c0acd50013f7f03cef0c89b74c47edabef3330c"},
-    {file = "pycalphad-0.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ad2c0836923282361b9a44363ff04ce0ef7e8f5205867ca2ee6ea6392fe890d0"},
-    {file = "pycalphad-0.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ab8ce524cfcff8c65cfb36df52e1bbd0b323f1731eb70a98a077c0255c1cc9c8"},
-    {file = "pycalphad-0.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b7d1e50bd1ba13760546140afb0bc380dabbd88c8baf57655c65393e056772b8"},
-    {file = "pycalphad-0.9.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7221cd88b6556353a412e79bdad101bf4d8ec80647aca18d56f5efb681a4e2cc"},
-    {file = "pycalphad-0.9.2-cp38-cp38-win32.whl", hash = "sha256:c4a2b8744e2482c60caf98a788c3f05018d4b0c7554b0527a5f714a2d08bd01e"},
-    {file = "pycalphad-0.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:2c67f0867c7b97a0f36140e8bdc98585ae2f86baef6a28cff0836b6272706c3e"},
-    {file = "pycalphad-0.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0a983355a7c8861c448bfa3b71b5841db6316d5ade7417beb4e959385aede3b6"},
-    {file = "pycalphad-0.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b5136229ab5d918218000fced93b7bfbd2a733596e655b801e96cb7ff36ab867"},
-    {file = "pycalphad-0.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fce55bb8d357dd99619de945a53cdc684421c3f0e93843530069a2bb60c21a0a"},
-    {file = "pycalphad-0.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:355770bf01f63e821e0b4cc59c65e3da9f7f4ddd1e9908c8bdbe8beaace94cff"},
-    {file = "pycalphad-0.9.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:71e24d564687c5da581bce6f728c7fa8e77448150542418fcd3677b6674769b1"},
-    {file = "pycalphad-0.9.2-cp39-cp39-win32.whl", hash = "sha256:fa9208f2f6448dd1aa8553a90709a0244d6fd3b2a8c15b63607a8d14f9a8f875"},
-    {file = "pycalphad-0.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:3f7793d770b055e34e95f6067518164f500218bfb4002804219dc5bfa3febe2c"},
-    {file = "pycalphad-0.9.2.tar.gz", hash = "sha256:18686d48b3cd609f9ba92358badc6d0159cf1bf987add97b78481dbacc7957c4"},
+    {file = "pycalphad-0.10.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b6ef20e9d9e4f9ee3f41a2c113023570b5ecfbc52f2b18b6438918bb347f7c24"},
+    {file = "pycalphad-0.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:55ba6cd852d3937b0d85e6b3307e69da1cbb89d8461367e0a1abdbd1154bf9cf"},
+    {file = "pycalphad-0.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5afb90180d47e2c35ffe4682b9fbde1ba160318a1a69f8820cdfd221cf9e4cc6"},
+    {file = "pycalphad-0.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30a7a514e0c8c8d645340ddc5f372524832bb65dd98f0107e95409ba9d96e785"},
+    {file = "pycalphad-0.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:02086869970082c2f2149a30097b56841fd9cc5460b13f1f8b9e02ea102b0d03"},
+    {file = "pycalphad-0.10.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ffa124c0abde244065ea9e555f98b8a1937f8fc0856c017eb0778e236915cdf2"},
+    {file = "pycalphad-0.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b40736b024d4171f5f6049ccffd19e0dcd66f01d2af47bf9187daaa7e80aadb"},
+    {file = "pycalphad-0.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4af7999ca86e86a403ec903544236c00b9ae8f4bdfb99ca256ff40cc396d2a8c"},
+    {file = "pycalphad-0.10.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b145d82961f066c52365eaca68c90d4703e638a2ce7447669331b8539565d280"},
+    {file = "pycalphad-0.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f738c2d36a6a5732cce2e772344c7f363362a3ddcf764810db96441e1ed6a5d2"},
+    {file = "pycalphad-0.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:396de9660cfcac90e019ed0be2d63b51a08428323b37ab7d218443e9d82da09a"},
+    {file = "pycalphad-0.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7541afcf16a13c05f52e99ddcfe6899189959b25b2ff2049f3e03c71cb538032"},
+    {file = "pycalphad-0.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:a3cc5b574b02fad18114172700ec7db9de8abdb129a9a03cb8684a103d1a2adb"},
+    {file = "pycalphad-0.10.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:94d7d98e423ae1341e355974bc9b9cfcfa5117214fde1fb0230201d156c7c452"},
+    {file = "pycalphad-0.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7fe240bca4f82f0f0c10445ad1c6e2b0fc4a75b004cb083f3f6fad4479ebff4"},
+    {file = "pycalphad-0.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f08ff70e046afd556c144db69bdb49e0dd2246df67b7c97908b3e7ef21d6e7c"},
+    {file = "pycalphad-0.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a907d4079dee2b86300070e8659b6f9a2095104c078c0dd5dd1e6a65d110c92a"},
+    {file = "pycalphad-0.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:56c7faa5dce7d135542faaf0c7231e48a986d3ad46a37627865021489f5449a2"},
+    {file = "pycalphad-0.10.0.tar.gz", hash = "sha256:1138da53f5e2c0c68e98033e38bee18c9c6242e55bab42d75d8164ec7159b4d9"},
 ]
 pycodestyle = [
-    {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"},
-    {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"},
+    {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
+    {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
 ]
 pycparser = [
     {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
     {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
 ]
-pydispatcher = [
-    {file = "PyDispatcher-2.0.5.tar.gz", hash = "sha256:5570069e1b1769af1fe481de6dd1d3a388492acddd2cdad7a3bde145615d5caf"},
-    {file = "PyDispatcher-2.0.5.zip", hash = "sha256:5be4a8be12805ef7d712dd9a93284fb8bc53f309867e573f653a72e5fd10e433"},
-]
 pyflakes = [
-    {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"},
-    {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"},
+    {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
+    {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
 ]
 pygments = [
     {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"},
@@ -2733,14 +3198,17 @@ pyjwt = [
     {file = "PyJWT-2.3.0.tar.gz", hash = "sha256:b888b4d56f06f6dcd777210c334e69c737be74755d3e5e9ee3fe67dc18a0ee41"},
 ]
 pymatgen = [
-    {file = "pymatgen-2018.12.12-cp27-cp27m-macosx_10_6_x86_64.whl", hash = "sha256:a9302b605d12d4545a77b1ac41c72d793c8cbe79fa35d49a31019d3b7882addb"},
-    {file = "pymatgen-2018.12.12-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:32798081906f071fa4d5e60b5e5dca7ed810227fca1a9a179d0247ad64f04df0"},
-    {file = "pymatgen-2018.12.12-cp37-cp37m-win_amd64.whl", hash = "sha256:af34860e54843ad8a095d082d6048a77f87b72d8a30ba008afb46ceade769769"},
-    {file = "pymatgen-2018.12.12.tar.gz", hash = "sha256:520cdf326f25dd62cb99590e081e32a0b38588740c71f4432c2d13713be64fc7"},
+    {file = "pymatgen-2022.3.29-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:d98a8309b30fb62da7af6706b526f55932b1fd87e25ce72a94a30e4e8901c53f"},
+    {file = "pymatgen-2022.3.29-cp310-cp310-win_amd64.whl", hash = "sha256:7aa2a0e2126d9b5148ae321e811bbaa0d2f995d8892ce0c146a327d483bd189d"},
+    {file = "pymatgen-2022.3.29-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:3f1afcd127a7d9e9fa37b80db0c65465ab27e685f81de386cd554c7fad48a97b"},
+    {file = "pymatgen-2022.3.29-cp38-cp38-win_amd64.whl", hash = "sha256:c5f789d03618cd5fd9d03a47ad932730b57f8a28510bcb100752241c54c53296"},
+    {file = "pymatgen-2022.3.29-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:623a990701863156c31bcb7d47a172244182f697156604959fd702c8679c53e6"},
+    {file = "pymatgen-2022.3.29-cp39-cp39-win_amd64.whl", hash = "sha256:35ef2d52e35135ea6ae7ddab7461ca53a16b7d8e4b94e657161936e05dab21cb"},
+    {file = "pymatgen-2022.3.29.tar.gz", hash = "sha256:7da740a99fe61d78b0adfa70d0e902d5f5525148eeb1297eae9c4f6ff98014d2"},
 ]
 pyparsing = [
-    {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"},
-    {file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"},
+    {file = "pyparsing-3.0.8-py3-none-any.whl", hash = "sha256:ef7b523f6356f763771559412c0d7134753f037822dad1b16945b7b846f7ad06"},
+    {file = "pyparsing-3.0.8.tar.gz", hash = "sha256:7bf433498c016c4314268d95df76c81b842a4cb2b276fa3312cfb1e1d85f6954"},
 ]
 pypif = [
     {file = "pypif-2.1.2.tar.gz", hash = "sha256:f426a4f58157b44727a2fdbe821000d98b5a64951b9ebe8a300d38db7804eefd"},
@@ -2769,64 +3237,56 @@ pyrsistent = [
     {file = "pyrsistent-0.18.1.tar.gz", hash = "sha256:d4d61f8b993a7255ba714df3aca52700f8125289f84f704cf80916517c46eb96"},
 ]
 pytest = [
-    {file = "pytest-3.10.1-py2.py3-none-any.whl", hash = "sha256:3f193df1cfe1d1609d4c583838bea3d532b18d6160fd3f55c9447fdca30848ec"},
-    {file = "pytest-3.10.1.tar.gz", hash = "sha256:e246cf173c01169b9617fc07264b7b1316e78d7a650055235d6d897bc80d9660"},
+    {file = "pytest-7.1.1-py3-none-any.whl", hash = "sha256:92f723789a8fdd7180b6b06483874feca4c48a5c76968e03bb3e7f806a1869ea"},
+    {file = "pytest-7.1.1.tar.gz", hash = "sha256:841132caef6b1ad17a9afde46dc4f6cfa59a05f9555aae5151f73bdf2820ca63"},
 ]
 pytest-cov = [
-    {file = "pytest-cov-2.9.0.tar.gz", hash = "sha256:b6a814b8ed6247bd81ff47f038511b57fe1ce7f4cc25b9106f1a4b106f1d9322"},
-    {file = "pytest_cov-2.9.0-py2.py3-none-any.whl", hash = "sha256:c87dfd8465d865655a8213859f1b4749b43448b5fae465cb981e16d52a811424"},
+    {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"},
+    {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"},
 ]
 python-dateutil = [
     {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
     {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
 ]
 python-magic = [
-    {file = "python-magic-0.4.24.tar.gz", hash = "sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf"},
-    {file = "python_magic-0.4.24-py2.py3-none-any.whl", hash = "sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626"},
+    {file = "python-magic-0.4.25.tar.gz", hash = "sha256:21f5f542aa0330f5c8a64442528542f6215c8e18d2466b399b0d9d39356d83fc"},
+    {file = "python_magic-0.4.25-py2.py3-none-any.whl", hash = "sha256:1a2c81e8f395c744536369790bd75094665e9644110a6623bcc3bbea30f03973"},
 ]
 pytz = [
-    {file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"},
-    {file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"},
+    {file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"},
+    {file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"},
 ]
 pywavelets = [
-    {file = "PyWavelets-1.2.0-cp310-cp310-macosx_10_13_universal2.whl", hash = "sha256:4c29efb581245e4ba3e76b23b1bf254a7c79821d7e63f432e68044cf2d233e9e"},
-    {file = "PyWavelets-1.2.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:3089aa6b4962e1f5dbd0434a10f174f7a50f80bf64cb7d33cc725af07bd30ecc"},
-    {file = "PyWavelets-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:16c30e98f52e1a5d0a06b4b8f294114aaa94a0e95445b4056b6ca0a7a5535a42"},
-    {file = "PyWavelets-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79386f4d8518e344487acf22b1c130e5907b3c45852aa50c18df5e19895aa92e"},
-    {file = "PyWavelets-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9bf543d552d20cf6ddfd690c5c18afacc8440cfb09b7515b2242bb9abfcc5eb"},
-    {file = "PyWavelets-1.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28bb3d7d411ffbcfaa5a81a5a32044805893752c1641b39f6544b7e0a24661c3"},
-    {file = "PyWavelets-1.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:333e1370167b0a2b963df82e42968000734bfa23b2ce88191e8ce9d24fc4cc57"},
-    {file = "PyWavelets-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2ec1fc92573f56c1b129006d109e7518a098f3c8c6a2183b495619faca931461"},
-    {file = "PyWavelets-1.2.0-cp310-cp310-win32.whl", hash = "sha256:d30c09fa805533bf7c8a5d06aa8babda5ae6c1541cd652cb2ebe6ab0b9536c0e"},
-    {file = "PyWavelets-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:73805016353a47c5b5f9cea547ea6ae07cd3520abfd7888916ff56b01e71307a"},
-    {file = "PyWavelets-1.2.0-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:ec670e78be2c3193e26c4bfa31dff1edd89ee8d7e2f4219782f3ef3f6daf37f0"},
-    {file = "PyWavelets-1.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:151a7f3d3db36baffe640d691403b7cd3938a1886c8a387b719e7e8b580dd4b1"},
-    {file = "PyWavelets-1.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:616fd2967dd153c3f539b1e0979168969f3702125caae4caa769efc5621cc2b7"},
-    {file = "PyWavelets-1.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:abedc0b49273a734d4592e325a5fb32f0741e115d6722e0c59964ecf21344640"},
-    {file = "PyWavelets-1.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9b05d2f21da666f918692f0313484002307794b5380f7291a395b9271abdda5c"},
-    {file = "PyWavelets-1.2.0-cp37-cp37m-win32.whl", hash = "sha256:537b5a8a8a3e9e5b931d34b517aa2312a3d8385937f98c4f8ffa668483329cfb"},
-    {file = "PyWavelets-1.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:7a725030682bf891ced9819b4b21d6ef356fa11b70399d2d3adb319aead1efb0"},
-    {file = "PyWavelets-1.2.0-cp38-cp38-macosx_10_13_universal2.whl", hash = "sha256:d9831b251f63460302811607f80a20285292ed0a0a046f95b4648edc0ed90f9c"},
-    {file = "PyWavelets-1.2.0-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:7e4749ff324e8e01a2fdc859ac9714c4be1cbc6e8a34d5ddedb28fc9513b31a1"},
-    {file = "PyWavelets-1.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:333684cc0d0e89cf6cb3a8b3ea68528790e1a3edc565a100cda47e29860f892d"},
-    {file = "PyWavelets-1.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71415f2c376ae3e1331249043dddb63370c92fed162ebcb108fd87e12a956d89"},
-    {file = "PyWavelets-1.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:44315d197bad9564210ef42f2d5a01c07ee6fd456c679d4a6d0f4e23ec9930cf"},
-    {file = "PyWavelets-1.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c8b388652b6afb4bf7be313be057240386de93817c6744c2aaf43a22890733c8"},
-    {file = "PyWavelets-1.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a1131c27b9f79ca56dd6347d5585a609f51ed3cad0cfb6c17419b1733d3b6acd"},
-    {file = "PyWavelets-1.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:df4d950be507a68d107c8f618ef7a9e0d9071789cfc1a840f89d0c985448880f"},
-    {file = "PyWavelets-1.2.0-cp38-cp38-win32.whl", hash = "sha256:8a72f11c4d23f8ed8544def0003f500e98598e7a1efce892e6f964c430469c05"},
-    {file = "PyWavelets-1.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:be231e4bc569f2b1177711390d406d08ce388c1e01ab864f89be8928db234856"},
-    {file = "PyWavelets-1.2.0-cp39-cp39-macosx_10_13_universal2.whl", hash = "sha256:90d53119f4b518236ad9a8a6be96d86efb1b4eeb73c28e3ed33824ae601ce7b1"},
-    {file = "PyWavelets-1.2.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:351937e4fc6f3df3555cd2813e73bfc344885c5d994fd621d13dd004d05a4cb7"},
-    {file = "PyWavelets-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33375e3e6e361659f2519d412de2b50e2527a97c3946ffd66ca20a8ea1346fea"},
-    {file = "PyWavelets-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:449d2d5f9c1f28a1bce01f714f9f742d9fdbce90f66de0a92cad39d98d24477b"},
-    {file = "PyWavelets-1.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:18d84982417790a645f74cb0f968e89fb8af575dbf17a52c64af5075aa5528b8"},
-    {file = "PyWavelets-1.2.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b3d9dab8223d0ce30e7480751f526ce1e97a1dcf5242875f8206e4449953116c"},
-    {file = "PyWavelets-1.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a82e8c307b98d65737b286e0b458343ecee8505dfb519cd314a5f211f4fb92b9"},
-    {file = "PyWavelets-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:663d265cb433653ef6335973edd13c66cd86c85fbe9c09e4bd138119bac15974"},
-    {file = "PyWavelets-1.2.0-cp39-cp39-win32.whl", hash = "sha256:fd5ca221ac7bedb2a9aebcf3b05020827564db5a979b25005b3a2c7ba84069a2"},
-    {file = "PyWavelets-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:69cfc7f2ceb0a1097e7e8d1a026cbb2ff1afecc2d79820856f1abccb6cb59cc4"},
-    {file = "PyWavelets-1.2.0.tar.gz", hash = "sha256:6cbd69b047bb4e00873097472133425f5f08a4e6bc8b3f0ae709274d4d5e9a8d"},
+    {file = "PyWavelets-1.3.0-cp310-cp310-macosx_10_13_universal2.whl", hash = "sha256:eebaa9c28600da336743fefd650332460c132792660e70eb09abf343b0664b87"},
+    {file = "PyWavelets-1.3.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:3eeffcf2f7eebae5cc27cb11a7d0d96118e2e9f75ac38ff1a05373d5fe75accb"},
+    {file = "PyWavelets-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:35a945bea9da6db9755e42e06e871846514ae91bde3ae24a08a1d090b003a23b"},
+    {file = "PyWavelets-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8876764e349673ee8d48bc3cd0afd2f9f7b65378998e2665af12c277c8a56de"},
+    {file = "PyWavelets-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c98ac1cee6276db05768e450dc3002033be6c2819c906103a974e0fb0d436f41"},
+    {file = "PyWavelets-1.3.0-cp310-cp310-win32.whl", hash = "sha256:6ecfe051ccb097c2dcdcb0977e0a684e76144d6694a202badf0780143d8536f0"},
+    {file = "PyWavelets-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:437806465cfa5f2d91809ec13154be050b84a11025784a6b6ce04ac452872b36"},
+    {file = "PyWavelets-1.3.0-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:3c4ebe7ff2c9092f6bdd1f8bf98ce2745f5d43a9936d6e342ee83fbcae548116"},
+    {file = "PyWavelets-1.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4f9ed4f175c66c9b8646a93fd54c588fd8f4b2517f53c59aea5cdf370f9c9ba"},
+    {file = "PyWavelets-1.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:41e4f0a3a6a088e955006513fe72f863cea3ce293033131cacb8a1a3068ed228"},
+    {file = "PyWavelets-1.3.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5b76731d2077242611b32f2e11c72adbf126b432ceae92e2ce8d0f693974c96d"},
+    {file = "PyWavelets-1.3.0-cp37-cp37m-win32.whl", hash = "sha256:3d3ecc2ee87be94fb2dc8c2d35bcae3f24708677196e80028d24ba0fd2f6a70a"},
+    {file = "PyWavelets-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:91e1b220f0ddd4c127bab718363c2c4a07dbcd95b9c4bfed09a3cdae47dbba43"},
+    {file = "PyWavelets-1.3.0-cp38-cp38-macosx_10_13_universal2.whl", hash = "sha256:8a5941d1f4eb1bc9569c655b63ecb31aa15b3ef0fc9b57df275892c39bccc59e"},
+    {file = "PyWavelets-1.3.0-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:a555a7a85da01357d8258cb45f751881f69013f8920f8738718c60cf8a47b755"},
+    {file = "PyWavelets-1.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:69e9a46facf89b51e5700d10f6d831f29745471c1ab42917f2f849a257b9fd77"},
+    {file = "PyWavelets-1.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a51225d24811ba7ef5184c03bb7072db0aa9651c4370a115d4069dedfb8d2f7a"},
+    {file = "PyWavelets-1.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7369597e1b1d125eb4b458a36cef052beed188444e55ed21445c1196008e200"},
+    {file = "PyWavelets-1.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:307ab8a4c3e5c2b8f7d3d371de4a5f019cf4b030b897c3394a4a7ad157369367"},
+    {file = "PyWavelets-1.3.0-cp38-cp38-win32.whl", hash = "sha256:27e99818d3c26481de3c68dbe880a7fcafe661cc031b22eff4a64237fe17a7ff"},
+    {file = "PyWavelets-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:3383d106fa8da0c2df30401ad056cd7a11b76d885f4bfa16ca7bcc6b4ca2831c"},
+    {file = "PyWavelets-1.3.0-cp39-cp39-macosx_10_13_universal2.whl", hash = "sha256:84c58a179bdb9fc71039b1f68bcd0718a7d9814b5e3741d7681d3e027bb81b52"},
+    {file = "PyWavelets-1.3.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:fccf468c55427828a3c534b651311f2759210836491c1112e1548e1babe368a5"},
+    {file = "PyWavelets-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ed3afbda88498b3ea3c861bf5b55e4feca41747730a71a22102ed5a74d1e453"},
+    {file = "PyWavelets-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38cc635c08a050e175a492e66c9b63a8e1f42254e6879e614b6c9d8d69e0887f"},
+    {file = "PyWavelets-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a486160f83efd8517cd748796adbab7c445ee8a3e1d168b4b8b60ed0f5aee3a0"},
+    {file = "PyWavelets-1.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f6e7d969a6ef64ae8be1766b0b0e32debb13424543d331911b8d7e967d60dd42"},
+    {file = "PyWavelets-1.3.0-cp39-cp39-win32.whl", hash = "sha256:de67deb275474094e160900ab7e07f2a721b9cd351cf3826c4a3ab89bb71d4b3"},
+    {file = "PyWavelets-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:a354979e2ee8cd71a8952ded381f3d9f981692b73c6842bcc6c9f64047e0a5be"},
+    {file = "PyWavelets-1.3.0.tar.gz", hash = "sha256:cbaa9d62052d9daf8da765fc8e7c30c38ea2b8e9e1c18841913dfb4aec671ee5"},
 ]
 pywin32 = [
     {file = "pywin32-303-cp310-cp310-win32.whl", hash = "sha256:6fed4af057039f309263fd3285d7b8042d41507343cd5fa781d98fcc5b90e8bb"},
@@ -2935,8 +3395,8 @@ rfc3986 = [
     {file = "rfc3986-2.0.0.tar.gz", hash = "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c"},
 ]
 "ruamel.yaml" = [
-    {file = "ruamel.yaml-0.17.20-py3-none-any.whl", hash = "sha256:810eef9c46523a3f77479c66267a4708255ebe806a2d540078408c2227f011af"},
-    {file = "ruamel.yaml-0.17.20.tar.gz", hash = "sha256:4b8a33c1efb2b443a93fcaafcfa4d2e445f8e8c29c528d9f5cdafb7cc9e4004c"},
+    {file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"},
+    {file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"},
 ]
 "ruamel.yaml.clib" = [
     {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6e7be2c5bcb297f5b82fee9c665eb2eb7001d1050deaba8471842979293a80b0"},
@@ -2966,66 +3426,74 @@ rfc3986 = [
     {file = "ruamel.yaml.clib-0.2.6.tar.gz", hash = "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd"},
 ]
 s3transfer = [
-    {file = "s3transfer-0.5.0-py3-none-any.whl", hash = "sha256:9c1dc369814391a6bda20ebbf4b70a0f34630592c9aa520856bf384916af2803"},
-    {file = "s3transfer-0.5.0.tar.gz", hash = "sha256:50ed823e1dc5868ad40c8dc92072f757aa0e653a192845c94a3b676f4a62da4c"},
+    {file = "s3transfer-0.5.2-py3-none-any.whl", hash = "sha256:7a6f4c4d1fdb9a2b640244008e142cbc2cd3ae34b386584ef044dd0f27101971"},
+    {file = "s3transfer-0.5.2.tar.gz", hash = "sha256:95c58c194ce657a5f4fb0b9e60a84968c808888aed628cd98ab8771fe1db98ed"},
 ]
 scikit-image = [
-    {file = "scikit-image-0.19.1.tar.gz", hash = "sha256:48f00ee1e8ec2818ae6a152c72df15f4db7f566e839f5c34e1a0c3c9e5210138"},
-    {file = "scikit_image-0.19.1-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:ce144d21792560a69536c2f64ba7ecd28542a6a8ac9fd6f856465d11a4eb8648"},
-    {file = "scikit_image-0.19.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:42ab5a6d516fced19ae317b3fbbfeb7d63434d531cb36317ad5b555c3f34c5f3"},
-    {file = "scikit_image-0.19.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ec06bee79685d17b94889bb028baea0f34ea171be200885cc9a1b808d96ebf6"},
-    {file = "scikit_image-0.19.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8385c0f9a02698048129654feb4f136d213127fbcf1d99f28e4cdd6669984f53"},
-    {file = "scikit_image-0.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:64da56c7d3098b91429b3070908e5c2b6534791f3ec516d1396fbe8fa51d1170"},
-    {file = "scikit_image-0.19.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:5264f20f8940b852b46cf579bd9a6343dc80c2277cda78a7442efeaa68198c4f"},
-    {file = "scikit_image-0.19.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92266b2eb498ebac9de50768a296e111e95752b6070344d98c2f5fd06c1e7635"},
-    {file = "scikit_image-0.19.1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d86387e0ba4713a460499e1d063e59a4ab16144836f6d3a5ff940316be24d07b"},
-    {file = "scikit_image-0.19.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66411fa085aa5e1ac98daeda1f596ae1396041ee70ea0f2081d6260b803ad1a6"},
-    {file = "scikit_image-0.19.1-cp37-cp37m-win32.whl", hash = "sha256:9f88ff2f00d1bf0f6f4d3bba07530c857ba53fa3b2284dd685762514b299f734"},
-    {file = "scikit_image-0.19.1-cp37-cp37m-win_amd64.whl", hash = "sha256:8dda7a82f83296a2fcbe6ee0684d84e0ee4477cae57200117f5a55c80f8ec844"},
-    {file = "scikit_image-0.19.1-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:f1d8fd2989430768e2cdc30cc2a69642de67d7ddfc1c80e1977eab199aedc0a1"},
-    {file = "scikit_image-0.19.1-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:3c6a4d9ac342c7a58b3f1d0559cd47e393619a538e03eb22f696d6df821c7d37"},
-    {file = "scikit_image-0.19.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2ab64c66ac0c7ad4d5da167eff7c9af04770e445f9242dbe43f12d005f48107"},
-    {file = "scikit_image-0.19.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4849352b2dffd9f5cdf2efae99dabe14d7b2880331387826445f31d9148650f6"},
-    {file = "scikit_image-0.19.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26ecb813e4d34874ff5f7f49216e217367db273ad8a99e556c77d616121ab219"},
-    {file = "scikit_image-0.19.1-cp38-cp38-win32.whl", hash = "sha256:50611d5dac964bc5593457b96860bd93079984376466173800e97401a5de4ec2"},
-    {file = "scikit_image-0.19.1-cp38-cp38-win_amd64.whl", hash = "sha256:058af6453644ab68a0e0018b830ef38ec4285a4d14791a28fd62e2ee2d66ff6f"},
-    {file = "scikit_image-0.19.1-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:ad997e0fce1492855bd19e76c4a1609eecc29328623ddda8c6297ca137999055"},
-    {file = "scikit_image-0.19.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:b516764deb0780feb861c99c1e8503f8804a04f02f0ffcb0f0310672467ed520"},
-    {file = "scikit_image-0.19.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:43bfe99f839367c954b670ffe635c3789c3e0957b2fab18cfa25c8b9ed85f6e0"},
-    {file = "scikit_image-0.19.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f97bfeaf844b45711834ff4afeb5c7ce9dcf33f33a8d8b110fb14f6bd3cd82bc"},
-    {file = "scikit_image-0.19.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63dc34bbd46425c78f6760f348c90fcccb4169ada60857b71db3f18fabe5620a"},
-    {file = "scikit_image-0.19.1-cp39-cp39-win32.whl", hash = "sha256:97a6b82e1286f4d2a602e1362edaf0f14da417f2b4208576f6455dd01283880f"},
-    {file = "scikit_image-0.19.1-cp39-cp39-win_amd64.whl", hash = "sha256:c3d012c861792b2baec07118ecf31b246cd27051035f527dc2618ad28c6ac29e"},
+    {file = "scikit-image-0.19.2.tar.gz", hash = "sha256:d433b4642a6f8219e749dfbbe4b5e742d560996540c9749ede510274d061866d"},
+    {file = "scikit_image-0.19.2-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:935c95d207c9bcaff20b69164401089ef2efd7f89dbbbf13ab75a5f65ff695b5"},
+    {file = "scikit_image-0.19.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:956cb8b60f6668974cadb70b0c4f5e13dd4673ffff3d5906d5d23333c76350e9"},
+    {file = "scikit_image-0.19.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ce41df8e06724f8fdb20c555988666520c322d47df7c898422330d4e3cd3900"},
+    {file = "scikit_image-0.19.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2a0a3df8ab2e862fda4363551801d630dc2fd7f1036f14479acde418315a38b"},
+    {file = "scikit_image-0.19.2-cp310-cp310-win_amd64.whl", hash = "sha256:0af44a48bb369be936303680511cea3c717b51218275ea5ea339a2aefa25c0ac"},
+    {file = "scikit_image-0.19.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:9b88590c243692d21f2b772bc83ad1aacdc7d605fbf0be32ea60b1e96aac920e"},
+    {file = "scikit_image-0.19.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:498d0e4fe70776238c7d1362dea7c2b41bf4a40617f6a742ffa3f59aa0392bb7"},
+    {file = "scikit_image-0.19.2-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:66bb26ca1e9c0924557ef3e6aee9fd8c21da96c7d5ba2b8864868c53723b45df"},
+    {file = "scikit_image-0.19.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56ffd1394aacd994963774e927a16f1ba2c094a9254b230da2c50147c661362a"},
+    {file = "scikit_image-0.19.2-cp37-cp37m-win32.whl", hash = "sha256:1bba9378cd77e7ff57b0f7a60ca167a728cffcac56d3e283ca7423e0c7d5e4a0"},
+    {file = "scikit_image-0.19.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b98cfa8aa9aa31519d5510973362748753c5d420d5cc60112a65e000fe3d3068"},
+    {file = "scikit_image-0.19.2-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:5ab19b11bd5f836a3de07f087d24db5ea734365122956f53dc5c5c9e018e2ec0"},
+    {file = "scikit_image-0.19.2-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:cabf07a7886861510d4a39ed64fc121708fb7d72a6fe601d87388d36240f4242"},
+    {file = "scikit_image-0.19.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa40f84383961a1a4afebb92f373e42a3d86e2540f012a4f7d2661a417f9e995"},
+    {file = "scikit_image-0.19.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3d0a85c6f53f0d4f704e67b35b3e8c6570846ec37eaeb1ca0f47a1088708cb8"},
+    {file = "scikit_image-0.19.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd115a4412b4561d62036e309c8cb543bfc2ca6b7b184ac23a65f6350959a716"},
+    {file = "scikit_image-0.19.2-cp38-cp38-win32.whl", hash = "sha256:d2c022044eb762d3f03ed6e08a3e06c067953393036e4ca2bf16b0bffde36acb"},
+    {file = "scikit_image-0.19.2-cp38-cp38-win_amd64.whl", hash = "sha256:b0f294ed7f0ea1e90fb6c764d04b8c298096b3403fad7539b9c6f22777d879c6"},
+    {file = "scikit_image-0.19.2-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:ad89c6ddbcc4d8ea8b7ebe1ae587be2067dad7927276576fe4097e42e370dadc"},
+    {file = "scikit_image-0.19.2-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:52c683e8615e28bfe5fe6fa2ac2563898d0c0b37f231d5b59e18abb8ed3805a2"},
+    {file = "scikit_image-0.19.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0025edbe1412c413d6b3251cc8ff94530cf45b31819daed1811340b93f51e38"},
+    {file = "scikit_image-0.19.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:477d3166da104b4914920d6db84183dd3af46430d13a0a3451a92eb58b5c9259"},
+    {file = "scikit_image-0.19.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0e5c6e7c7c54c0b827e6288d9f44ae6d290c0aef979e7de1511d2f5fc6f9c0f"},
+    {file = "scikit_image-0.19.2-cp39-cp39-win32.whl", hash = "sha256:99696479cf6fd19bb06ea43269c0728bb75c2ce9cd3710829ac0f1590eecf0dc"},
+    {file = "scikit_image-0.19.2-cp39-cp39-win_amd64.whl", hash = "sha256:9d3fd65ec424de83e6fee22480db5431a9b91d280a34ab3e6bf83528e4289f5c"},
 ]
 scipy = [
-    {file = "scipy-1.6.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a15a1f3fc0abff33e792d6049161b7795909b40b97c6cc2934ed54384017ab76"},
-    {file = "scipy-1.6.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:e79570979ccdc3d165456dd62041d9556fb9733b86b4b6d818af7a0afc15f092"},
-    {file = "scipy-1.6.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a423533c55fec61456dedee7b6ee7dce0bb6bfa395424ea374d25afa262be261"},
-    {file = "scipy-1.6.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:33d6b7df40d197bdd3049d64e8e680227151673465e5d85723b3b8f6b15a6ced"},
-    {file = "scipy-1.6.1-cp37-cp37m-win32.whl", hash = "sha256:6725e3fbb47da428794f243864f2297462e9ee448297c93ed1dcbc44335feb78"},
-    {file = "scipy-1.6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:5fa9c6530b1661f1370bcd332a1e62ca7881785cc0f80c0d559b636567fab63c"},
-    {file = "scipy-1.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bd50daf727f7c195e26f27467c85ce653d41df4358a25b32434a50d8870fc519"},
-    {file = "scipy-1.6.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:f46dd15335e8a320b0fb4685f58b7471702234cba8bb3442b69a3e1dc329c345"},
-    {file = "scipy-1.6.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0e5b0ccf63155d90da576edd2768b66fb276446c371b73841e3503be1d63fb5d"},
-    {file = "scipy-1.6.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:2481efbb3740977e3c831edfd0bd9867be26387cacf24eb5e366a6a374d3d00d"},
-    {file = "scipy-1.6.1-cp38-cp38-win32.whl", hash = "sha256:68cb4c424112cd4be886b4d979c5497fba190714085f46b8ae67a5e4416c32b4"},
-    {file = "scipy-1.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:5f331eeed0297232d2e6eea51b54e8278ed8bb10b099f69c44e2558c090d06bf"},
-    {file = "scipy-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8a51d33556bf70367452d4d601d1742c0e806cd0194785914daf19775f0e67"},
-    {file = "scipy-1.6.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:83bf7c16245c15bc58ee76c5418e46ea1811edcc2e2b03041b804e46084ab627"},
-    {file = "scipy-1.6.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:794e768cc5f779736593046c9714e0f3a5940bc6dcc1dba885ad64cbfb28e9f0"},
-    {file = "scipy-1.6.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5da5471aed911fe7e52b86bf9ea32fb55ae93e2f0fac66c32e58897cfb02fa07"},
-    {file = "scipy-1.6.1-cp39-cp39-win32.whl", hash = "sha256:8e403a337749ed40af60e537cc4d4c03febddcc56cd26e774c9b1b600a70d3e4"},
-    {file = "scipy-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:a5193a098ae9f29af283dcf0041f762601faf2e595c0db1da929875b7570353f"},
-    {file = "scipy-1.6.1.tar.gz", hash = "sha256:c4fceb864890b6168e79b0e714c585dbe2fd4222768ee90bc1aa0f8218691b11"},
+    {file = "scipy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:87b01c7d5761e8a266a0fbdb9d88dcba0910d63c1c671bdb4d99d29f469e9e03"},
+    {file = "scipy-1.8.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ae3e327da323d82e918e593460e23babdce40d7ab21490ddf9fc06dec6b91a18"},
+    {file = "scipy-1.8.0-cp310-cp310-macosx_12_0_universal2.macosx_10_9_x86_64.whl", hash = "sha256:16e09ef68b352d73befa8bcaf3ebe25d3941fe1a58c82909d5589856e6bc8174"},
+    {file = "scipy-1.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c17a1878d00a5dd2797ccd73623ceca9d02375328f6218ee6d921e1325e61aff"},
+    {file = "scipy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:937d28722f13302febde29847bbe554b89073fbb924a30475e5ed7b028898b5f"},
+    {file = "scipy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:8f4d059a97b29c91afad46b1737274cb282357a305a80bdd9e8adf3b0ca6a3f0"},
+    {file = "scipy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:38aa39b6724cb65271e469013aeb6f2ce66fd44f093e241c28a9c6bc64fd79ed"},
+    {file = "scipy-1.8.0-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:559a8a4c03a5ba9fe3232f39ed24f86457e4f3f6c0abbeae1fb945029f092720"},
+    {file = "scipy-1.8.0-cp38-cp38-macosx_12_0_universal2.macosx_10_9_x86_64.whl", hash = "sha256:f4a6d3b9f9797eb2d43938ac2c5d96d02aed17ef170c8b38f11798717523ddba"},
+    {file = "scipy-1.8.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92b2c2af4183ed09afb595709a8ef5783b2baf7f41e26ece24e1329c109691a7"},
+    {file = "scipy-1.8.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a279e27c7f4566ef18bab1b1e2c37d168e365080974758d107e7d237d3f0f484"},
+    {file = "scipy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad5be4039147c808e64f99c0e8a9641eb5d2fa079ff5894dcd8240e94e347af4"},
+    {file = "scipy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:3d9dd6c8b93a22bf9a3a52d1327aca7e092b1299fb3afc4f89e8eba381be7b59"},
+    {file = "scipy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:5e73343c5e0d413c1f937302b2e04fb07872f5843041bcfd50699aef6e95e399"},
+    {file = "scipy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:de2e80ee1d925984c2504812a310841c241791c5279352be4707cdcd7c255039"},
+    {file = "scipy-1.8.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:c2bae431d127bf0b1da81fc24e4bba0a84d058e3a96b9dd6475dfcb3c5e8761e"},
+    {file = "scipy-1.8.0-cp39-cp39-macosx_12_0_universal2.macosx_10_9_x86_64.whl", hash = "sha256:723b9f878095ed994756fa4ee3060c450e2db0139c5ba248ee3f9628bd64e735"},
+    {file = "scipy-1.8.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:011d4386b53b933142f58a652aa0f149c9b9242abd4f900b9f4ea5fbafc86b89"},
+    {file = "scipy-1.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6f0cd9c0bd374ef834ee1e0f0999678d49dcc400ea6209113d81528958f97c7"},
+    {file = "scipy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3720d0124aced49f6f2198a6900304411dbbeed12f56951d7c66ebef05e3df6"},
+    {file = "scipy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:3d573228c10a3a8c32b9037be982e6440e411b443a6267b067cac72f690b8d56"},
+    {file = "scipy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:bb7088e89cd751acf66195d2f00cf009a1ea113f3019664032d9075b1e727b6c"},
+    {file = "scipy-1.8.0.tar.gz", hash = "sha256:31d4f2d6b724bc9a98e527b5849b8a7e589bf1ea630c33aa563eda912c9ff0bd"},
 ]
 setuptools-scm = [
-    {file = "setuptools_scm-6.4.1-py3-none-any.whl", hash = "sha256:93bbcc1d3e92f20eaef42df31e4b5e5a348f8cb0e48eaff3e060184a57e94b07"},
-    {file = "setuptools_scm-6.4.1.tar.gz", hash = "sha256:9bd9ff7fd5fa1cf469fe28a632336b9cfd351476c6d09379ff676d3945f669b9"},
+    {file = "setuptools_scm-6.4.2-py3-none-any.whl", hash = "sha256:acea13255093849de7ccb11af9e1fb8bde7067783450cee9ef7a93139bddf6d4"},
+    {file = "setuptools_scm-6.4.2.tar.gz", hash = "sha256:6833ac65c6ed9711a4d5d2266f8024cfa07c533a0e55f4c12f6eff280a5a9e30"},
 ]
 six = [
     {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
     {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
 ]
+snowballstemmer = [
+    {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
+    {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
+]
 sparse = [
     {file = "sparse-0.13.0-py2.py3-none-any.whl", hash = "sha256:95ed0b649a0663b1488756ad4cf242b0a9bb2c9a25bc752a7c6ca9fbe8258966"},
     {file = "sparse-0.13.0.tar.gz", hash = "sha256:685dc994aa770ee1b23f2d5392819c8429f27958771f8dceb2c4fb80210d5915"},
@@ -3048,80 +3516,115 @@ spglib = [
     {file = "spglib-1.16.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:120fafcba184914f32b0fa7d1a7efd4ca7b4db3061d49cf8da1ac14adf7a0cac"},
     {file = "spglib-1.16.3.tar.gz", hash = "sha256:ff1420967d64c2d4f0d747886116a6836d9b473454cdd73d560dbfe973a8a038"},
 ]
+sphinx = [
+    {file = "Sphinx-4.5.0-py3-none-any.whl", hash = "sha256:ebf612653238bcc8f4359627a9b7ce44ede6fdd75d9d30f68255c7383d3a6226"},
+    {file = "Sphinx-4.5.0.tar.gz", hash = "sha256:7bf8ca9637a4ee15af412d1a1d9689fec70523a68ca9bb9127c2f3eeb344e2e6"},
+]
+sphinx-rtd-theme = [
+    {file = "sphinx_rtd_theme-1.0.0-py2.py3-none-any.whl", hash = "sha256:4d35a56f4508cfee4c4fb604373ede6feae2a306731d533f409ef5c3496fdbd8"},
+    {file = "sphinx_rtd_theme-1.0.0.tar.gz", hash = "sha256:eec6d497e4c2195fa0e8b2016b337532b8a699a68bcb22a512870e16925c6a5c"},
+]
+sphinxcontrib-applehelp = [
+    {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"},
+    {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"},
+]
+sphinxcontrib-devhelp = [
+    {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"},
+    {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"},
+]
+sphinxcontrib-htmlhelp = [
+    {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"},
+    {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"},
+]
+sphinxcontrib-jsmath = [
+    {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"},
+    {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"},
+]
+sphinxcontrib-qthelp = [
+    {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"},
+    {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"},
+]
+sphinxcontrib-serializinghtml = [
+    {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"},
+    {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"},
+]
 sqlalchemy = [
-    {file = "SQLAlchemy-1.4.29-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:da64423c05256f4ab8c0058b90202053b201cbe3a081f3a43eb590cd554395ab"},
-    {file = "SQLAlchemy-1.4.29-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0fc4eec2f46b40bdd42112b3be3fbbf88e194bcf02950fbb88bcdc1b32f07dc7"},
-    {file = "SQLAlchemy-1.4.29-cp27-cp27m-win32.whl", hash = "sha256:101d2e100ba9182c9039699588e0b2d833c54b3bad46c67c192159876c9f27ea"},
-    {file = "SQLAlchemy-1.4.29-cp27-cp27m-win_amd64.whl", hash = "sha256:ceac84dd9abbbe115e8be0c817bed85d9fa639b4d294e7817f9e61162d5f766c"},
-    {file = "SQLAlchemy-1.4.29-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:15b65887b6c324cad638c7671cb95985817b733242a7eb69edd7cdf6953be1e0"},
-    {file = "SQLAlchemy-1.4.29-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:78abc507d17753ed434b6cc0c0693126279723d5656d9775bfcac966a99a899b"},
-    {file = "SQLAlchemy-1.4.29-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb8c993706e86178ce15a6b86a335a2064f52254b640e7f53365e716423d33f4"},
-    {file = "SQLAlchemy-1.4.29-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:804e22d5b6165a4f3f019dd9c94bec5687de985a9c54286b93ded9f7846b8c82"},
-    {file = "SQLAlchemy-1.4.29-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56d9d62021946263d4478c9ca012fbd1805f10994cb615c88e7bfd1ae14604d8"},
-    {file = "SQLAlchemy-1.4.29-cp310-cp310-win32.whl", hash = "sha256:027f356c727db24f3c75828c7feb426f87ce1241242d08958e454bd025810660"},
-    {file = "SQLAlchemy-1.4.29-cp310-cp310-win_amd64.whl", hash = "sha256:debaf09a823061f88a8dee04949814cf7e82fb394c5bca22c780cb03172ca23b"},
-    {file = "SQLAlchemy-1.4.29-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:dc27dcc6c72eb38be7f144e9c2c4372d35a3684d3a6dd43bd98c1238358ee17c"},
-    {file = "SQLAlchemy-1.4.29-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4ddd4f2e247128c58bb3dd4489922874afce157d2cff0b2295d67fcd0f22494"},
-    {file = "SQLAlchemy-1.4.29-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9ce960a1dc60524136cf6f75621588e2508a117e04a6e3eedb0968bd13b8c824"},
-    {file = "SQLAlchemy-1.4.29-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5919e647e1d4805867ea556ed4967c68b4d8b266059fa35020dbaed8ffdd60f3"},
-    {file = "SQLAlchemy-1.4.29-cp36-cp36m-win32.whl", hash = "sha256:886359f734b95ad1ef443b13bb4518bcade4db4f9553c9ce33d6d04ebda8d44e"},
-    {file = "SQLAlchemy-1.4.29-cp36-cp36m-win_amd64.whl", hash = "sha256:e9cc6d844e24c307c3272677982a9b33816aeb45e4977791c3bdd47637a8d810"},
-    {file = "SQLAlchemy-1.4.29-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:5e9cd33459afa69c88fa648e803d1f1245e3caa60bfe8b80a9595e5edd3bda9c"},
-    {file = "SQLAlchemy-1.4.29-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eeaebceb24b46e884c4ad3c04f37feb178b81f6ce720af19bfa2592ca32fdef7"},
-    {file = "SQLAlchemy-1.4.29-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e89347d3bd2ef873832b47e85f4bbd810a5e626c5e749d90a07638da100eb1c8"},
-    {file = "SQLAlchemy-1.4.29-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a717c2e70fd1bb477161c4cc85258e41d978584fbe5522613618195f7e87d9b"},
-    {file = "SQLAlchemy-1.4.29-cp37-cp37m-win32.whl", hash = "sha256:f74d6c05d2d163464adbdfbc1ab85048cc15462ff7d134b8aed22bd521e1faa5"},
-    {file = "SQLAlchemy-1.4.29-cp37-cp37m-win_amd64.whl", hash = "sha256:621854dbb4d2413c759a5571564170de45ef37299df52e78e62b42e2880192e1"},
-    {file = "SQLAlchemy-1.4.29-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:f3909194751bb6cb7c5511dd18bcf77e6e3f0b31604ed4004dffa9461f71e737"},
-    {file = "SQLAlchemy-1.4.29-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd49d21d1f03c81fbec9080ecdc4486d5ddda67e7fbb75ebf48294465c022cdc"},
-    {file = "SQLAlchemy-1.4.29-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e5f6959466a42b6569774c257e55f9cd85200d5b0ba09f0f5d8b5845349c5822"},
-    {file = "SQLAlchemy-1.4.29-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0072f9887aabe66db23f818bbe950cfa1b6127c5cb769b00bcc07935b3adb0ad"},
-    {file = "SQLAlchemy-1.4.29-cp38-cp38-win32.whl", hash = "sha256:ad618d687d26d4cbfa9c6fa6141d59e05bcdfc60cb6e1f1d3baa18d8c62fef5f"},
-    {file = "SQLAlchemy-1.4.29-cp38-cp38-win_amd64.whl", hash = "sha256:878daecb6405e786b07f97e1c77a9cfbbbec17432e8a90c487967e32cfdecb33"},
-    {file = "SQLAlchemy-1.4.29-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:e027bdf0a4cf6bd0a3ad3b998643ea374d7991bd117b90bf9982e41ceb742941"},
-    {file = "SQLAlchemy-1.4.29-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5de7adfb91d351f44062b8dedf29f49d4af7cb765be65816e79223a4e31062b"},
-    {file = "SQLAlchemy-1.4.29-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fbc6e63e481fa323036f305ada96a3362e1d60dd2bfa026cac10c3553e6880e9"},
-    {file = "SQLAlchemy-1.4.29-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7dd0502cb091660ad0d89c5e95a29825f37cde2a5249957838e975871fbffaad"},
-    {file = "SQLAlchemy-1.4.29-cp39-cp39-win32.whl", hash = "sha256:37b46bfc4af3dc226acb6fa28ecd2e1fd223433dc5e15a2bad62bf0a0cbb4e8b"},
-    {file = "SQLAlchemy-1.4.29-cp39-cp39-win_amd64.whl", hash = "sha256:08cfd35eecaba79be930c9bfd2e1f0c67a7e1314355d83a378f9a512b1cf7587"},
-    {file = "SQLAlchemy-1.4.29.tar.gz", hash = "sha256:fa2bad14e1474ba649cfc969c1d2ec915dd3e79677f346bbfe08e93ef9020b39"},
+    {file = "SQLAlchemy-1.4.35-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:093b3109c2747d5dc0fa4314b1caf4c7ca336d5c8c831e3cfbec06a7e861e1e6"},
+    {file = "SQLAlchemy-1.4.35-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c6fb6b9ed1d0be7fa2c90be8ad2442c14cbf84eb0709dd1afeeff1e511550041"},
+    {file = "SQLAlchemy-1.4.35-cp27-cp27m-win32.whl", hash = "sha256:d38a49aa75a5759d0d118e26701d70c70a37b896379115f8386e91b0444bfa70"},
+    {file = "SQLAlchemy-1.4.35-cp27-cp27m-win_amd64.whl", hash = "sha256:70e571ae9ee0ff36ed37e2b2765445d54981e4d600eccdf6fe3838bc2538d157"},
+    {file = "SQLAlchemy-1.4.35-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:48036698f20080462e981b18d77d574631a3d1fc2c33b416c6df299ec1d10b99"},
+    {file = "SQLAlchemy-1.4.35-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:4ba2c1f368bcf8551cdaa27eac525022471015633d5bdafbc4297e0511f62f51"},
+    {file = "SQLAlchemy-1.4.35-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d17316100fcd0b6371ac9211351cb976fd0c2e12a859c1a57965e3ef7f3ed2bc"},
+    {file = "SQLAlchemy-1.4.35-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9837133b89ad017e50a02a3b46419869cf4e9aa02743e911b2a9e25fa6b05403"},
+    {file = "SQLAlchemy-1.4.35-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4efb70a62cbbbc052c67dc66b5448b0053b509732184af3e7859d05fdf6223c"},
+    {file = "SQLAlchemy-1.4.35-cp310-cp310-win32.whl", hash = "sha256:1ff9f84b2098ef1b96255a80981ee10f4b5d49b6cfeeccf9632c2078cd86052e"},
+    {file = "SQLAlchemy-1.4.35-cp310-cp310-win_amd64.whl", hash = "sha256:48f0eb5bcc87a9b2a95b345ed18d6400daaa86ca414f6840961ed85c342af8f4"},
+    {file = "SQLAlchemy-1.4.35-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:da25e75ba9f3fabc271673b6b413ca234994e6d3453424bea36bb5549c5bbaec"},
+    {file = "SQLAlchemy-1.4.35-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeea6ace30603ca9a8869853bb4a04c7446856d7789e36694cd887967b7621f6"},
+    {file = "SQLAlchemy-1.4.35-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a5dbdbb39c1b100df4d182c78949158073ca46ba2850c64fe02ffb1eb5b70903"},
+    {file = "SQLAlchemy-1.4.35-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfd8e4c64c30a5219032e64404d468c425bdbc13b397da906fc9bee6591fc0dd"},
+    {file = "SQLAlchemy-1.4.35-cp36-cp36m-win32.whl", hash = "sha256:9dac1924611698f8fe5b2e58601156c01da2b6c0758ba519003013a78280cf4d"},
+    {file = "SQLAlchemy-1.4.35-cp36-cp36m-win_amd64.whl", hash = "sha256:e8b09e2d90267717d850f2e2323919ea32004f55c40e5d53b41267e382446044"},
+    {file = "SQLAlchemy-1.4.35-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:63c82c9e8ccc2fb4bfd87c24ffbac320f70b7c93b78f206c1f9c441fa3013a5f"},
+    {file = "SQLAlchemy-1.4.35-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:effadcda9a129cc56408dd5b2ea20ee9edcea24bd58e6a1489fa27672d733182"},
+    {file = "SQLAlchemy-1.4.35-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2c6c411d8c59afba95abccd2b418f30ade674186660a2d310d364843049fb2c1"},
+    {file = "SQLAlchemy-1.4.35-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2489e70bfa2356f2d421106794507daccf6cc8711753c442fc97272437fc606"},
+    {file = "SQLAlchemy-1.4.35-cp37-cp37m-win32.whl", hash = "sha256:186cb3bd77abf2ddcf722f755659559bfb157647b3fd3f32ea1c70e8311e8f6b"},
+    {file = "SQLAlchemy-1.4.35-cp37-cp37m-win_amd64.whl", hash = "sha256:babd63fb7cb6b0440abb6d16aca2be63342a6eea3dc7b613bb7a9357dc36920f"},
+    {file = "SQLAlchemy-1.4.35-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:9e1a72197529ea00357640f21d92ffc7024e156ef9ac36edf271c8335facbc1a"},
+    {file = "SQLAlchemy-1.4.35-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e255a8dd5572b0c66d6ee53597d36157ad6cf3bc1114f61c54a65189f996ab03"},
+    {file = "SQLAlchemy-1.4.35-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9bec63b1e20ef69484f530fb4b4837e050450637ff9acd6dccc7003c5013abf8"},
+    {file = "SQLAlchemy-1.4.35-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95411abc0e36d18f54fa5e24d42960ea3f144fb16caaa5a8c2e492b5424cc82c"},
+    {file = "SQLAlchemy-1.4.35-cp38-cp38-win32.whl", hash = "sha256:28b17ebbaee6587013be2f78dc4f6e95115e1ec8dd7647c4e7be048da749e48b"},
+    {file = "SQLAlchemy-1.4.35-cp38-cp38-win_amd64.whl", hash = "sha256:9e7094cf04e6042c4210a185fa7b9b8b3b789dd6d1de7b4f19452290838e48bd"},
+    {file = "SQLAlchemy-1.4.35-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:1b4eac3933c335d7f375639885765722534bb4e52e51cdc01a667eea822af9b6"},
+    {file = "SQLAlchemy-1.4.35-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d8edfb09ed2b865485530c13e269833dab62ab2d582fde21026c9039d4d0e62"},
+    {file = "SQLAlchemy-1.4.35-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6204d06bfa85f87625e1831ca663f9dba91ac8aec24b8c65d02fb25cbaf4b4d7"},
+    {file = "SQLAlchemy-1.4.35-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28aa2ef06c904729620cc735262192e622db9136c26d8587f71f29ec7715628a"},
+    {file = "SQLAlchemy-1.4.35-cp39-cp39-win32.whl", hash = "sha256:ecc81336b46e31ae9c9bdfa220082079914e31a476d088d3337ecf531d861228"},
+    {file = "SQLAlchemy-1.4.35-cp39-cp39-win_amd64.whl", hash = "sha256:53c7469b86a60fe2babca4f70111357e6e3d5150373bc85eb3b914356983e89a"},
+    {file = "SQLAlchemy-1.4.35.tar.gz", hash = "sha256:2ffc813b01dc6473990f5e575f210ca5ac2f5465ace3908b78ffd6d20058aab5"},
+]
+stack-data = [
+    {file = "stack_data-0.2.0-py3-none-any.whl", hash = "sha256:999762f9c3132308789affa03e9271bbbe947bf78311851f4d485d8402ed858e"},
+    {file = "stack_data-0.2.0.tar.gz", hash = "sha256:45692d41bd633a9503a5195552df22b583caf16f0b27c4e58c98d88c8b648e12"},
 ]
 stevedore = [
-    {file = "stevedore-1.32.0-py2.py3-none-any.whl", hash = "sha256:a4e7dc759fb0f2e3e2f7d8ffe2358c19d45b9b8297f393ef1256858d82f69c9b"},
-    {file = "stevedore-1.32.0.tar.gz", hash = "sha256:18afaf1d623af5950cc0f7e75e70f917784c73b652a34a12d90b309451b5500b"},
+    {file = "stevedore-3.5.0-py3-none-any.whl", hash = "sha256:a547de73308fd7e90075bb4d301405bebf705292fa90a90fc3bcf9133f58616c"},
+    {file = "stevedore-3.5.0.tar.gz", hash = "sha256:f40253887d8712eaa2bb0ea3830374416736dc8ec0e22f5a65092c1174c44335"},
 ]
 symengine = [
-    {file = "symengine-0.7.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ec42ca5e7c71b3d2daceea8fd77f94f4a39d509883f31cb75dea9d2e210a44d4"},
-    {file = "symengine-0.7.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:53eef7df58e5e39ff5aecbbdf8244abd0bc438dc8b71900df6db13a87f1c7060"},
-    {file = "symengine-0.7.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:d25fe71fd42be081b09c1b939aa01268e484c85eee7a182228bb3c5d643ba90e"},
-    {file = "symengine-0.7.2-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:400ad6322feb88141c0490867d791f51268d3643266bb0f1260741d8c809bd95"},
-    {file = "symengine-0.7.2-cp36-cp36m-win_amd64.whl", hash = "sha256:d15d44b125afa93359dda9ce0174671f478b94ea7946140e8df0a483fd2e252b"},
-    {file = "symengine-0.7.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:544d3748764b4d66d2e341b9ba8e16bfcd8aebc15e95701067ba5225f6882d34"},
-    {file = "symengine-0.7.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:18d54d6cb37e891d6f74d933630ec6c4e75aab6ad4bd94d22a6adc00afb26a85"},
-    {file = "symengine-0.7.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:15a86d9bfbe5d588047851955924d1ff21c4081f939aeaea26cdbed88f13fd75"},
-    {file = "symengine-0.7.2-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:dcea2a1e5f047138e6049c99480b334746422136d1de84944fcf6c083ae159a9"},
-    {file = "symengine-0.7.2-cp37-cp37m-win_amd64.whl", hash = "sha256:3f5b96e95c2df698fb568cb692df781bf4c032072dde882f9f99f24eed26fdd9"},
-    {file = "symengine-0.7.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:211855ee8ea2d1921569f1d4c5bb0396e86b9796edabb4f9d97fd99afaf83730"},
-    {file = "symengine-0.7.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5f009c6e0fcb31a403b3e990060a9d2011bc1341e0710ed24a72af07ea74b102"},
-    {file = "symengine-0.7.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:dd40fded754e14bd9d02d7181c419c8b91209f4ea18d54f4589ef7f582988bb6"},
-    {file = "symengine-0.7.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:9e5ff62782cc1b450b6bc46f758b1faec08413ae82ef1c7d7141821a0101ccc3"},
-    {file = "symengine-0.7.2-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:cf9997ad0b78e6c7b7c9d9efe406b2b5a8cc179266c71a4ba28772b7de2f4350"},
-    {file = "symengine-0.7.2-cp38-cp38-win_amd64.whl", hash = "sha256:4726795eaf21bb67f55cf7288269ec0d4f936525b6772474f36f80f7f1d5cf82"},
-    {file = "symengine-0.7.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a2a2c18808c6a8de39c7089cb50a09af7e99354cde4be8408c9b084916a185d8"},
-    {file = "symengine-0.7.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0b36ff364647d50c645a9b807e508c474af20a80e5d37a7271ad5366691b6904"},
-    {file = "symengine-0.7.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:066fe182099e4dbf67fbfc3d686a1f4a23837e08668d5ac7b264e6ef06b2c6db"},
-    {file = "symengine-0.7.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d9a07694a37098542f14fbbe233ece2d5180a72b44ab9c7210f9744c9f50b059"},
-    {file = "symengine-0.7.2-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:0f61a5c23f921071a339ff9b798a47a23e50232807b980f8cda37128d4a34980"},
-    {file = "symengine-0.7.2-cp39-cp39-win_amd64.whl", hash = "sha256:56d4cbba3b97f3d1596e9c25e49fba111d519d6a8969881e10094fa1c20afc48"},
-    {file = "symengine-0.7.2-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:dc1be8a3ef1b8a2663a65972dbc8f00c6e3d2c6f6c741eee289383cb88b6202e"},
-    {file = "symengine-0.7.2-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:b92fe01d5bbcb564c0452a272be503a0bd2b12c20d16f5daef9ce878ca9e43e9"},
-    {file = "symengine-0.7.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4f4e86ac3a80587f9d1758b97cb0a1bd487690afaee0b144e177002286ed841a"},
-    {file = "symengine-0.7.2-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:da12c29ec1982041523b2bea98539b0f656740268ca51f16742ade692b047990"},
-    {file = "symengine-0.7.2.tar.gz", hash = "sha256:d033a091bc041fbe62fd271c0d873b1f4c129bc6528165b1517c3e11bcd48842"},
+    {file = "symengine-0.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4262ff3d58a8d2cf865d446ab774e396617a74349ae317dbdaf153508e39b935"},
+    {file = "symengine-0.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3f12abe264360c1dc96f4f655f3248fee025ece3a28d581e43534b9ea384ba75"},
+    {file = "symengine-0.9.0-cp310-cp310-manylinux2010_x86_64.whl", hash = "sha256:7c58c5ed1e992bba2fe77116193a275bfde8970995b4743067a4c56d16103e5b"},
+    {file = "symengine-0.9.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:4b26b664583bb7b057960fd651da99d186775b60e7ab65949a5f6ef26e8d425e"},
+    {file = "symengine-0.9.0-cp310-cp310-manylinux2014_ppc64le.whl", hash = "sha256:1f016dd582adf76f39896305cb3651af98eb46a3f8470510d3e3c5b78c36304e"},
+    {file = "symengine-0.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:6ee3fbe9b74422c16e773e62bc768c3bce0cc0439a97d3f61e9846d7e60a1604"},
+    {file = "symengine-0.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3d6b8243c27ae3eb02f018a5c2d3890b78c8ec8c16c661cb93e1102a065d3589"},
+    {file = "symengine-0.9.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:a0d7833ce718a157f9f76df9d638860e88aad354b250285ab35d7105090e3342"},
+    {file = "symengine-0.9.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:be60f210bbe274f4ddbd566a73f37f28ffa7d02fcd24382983c2e1834fde3d8a"},
+    {file = "symengine-0.9.0-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:d487e144167d9b9ac1038db42fb728779731781d9a070773ade1b797e19f1dc2"},
+    {file = "symengine-0.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:7bedc7cf0f7bcd581af525be278857f0ed90755285e88d5f90a901f7b58b089f"},
+    {file = "symengine-0.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6e86deec6ce3624b9a5beb513ecb2454d172dd2f1ce70436e9b7bbe58246c34a"},
+    {file = "symengine-0.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0f1227805c8ea76804d0a672da8976851b7082c7afea76c8c835cf3d02bf25d9"},
+    {file = "symengine-0.9.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:8cc94ec6eeefe538b10a78b575186b8382bbeea455212d4e716b1dd1c7d313ac"},
+    {file = "symengine-0.9.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8a5ce974c90e9c65dac52afe8597e375eadf01d4675dd61d8a3c55521aa842c1"},
+    {file = "symengine-0.9.0-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:d2b18ff182eec514fbe8c025b417fe6a1243de61b66690fbe2a0f33626f018d6"},
+    {file = "symengine-0.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:8ecd0ac6da619d35ddd80714b633b7ea9d6f428571bfb8a76d404f74222b50cf"},
+    {file = "symengine-0.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:64adb181032f935cfedc28a475d8748f2e560c9338470c3ce269650af47ac842"},
+    {file = "symengine-0.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e69831f7e5e9beb8785beeb7b950d455084b226fbeafbe027d88474679019b5"},
+    {file = "symengine-0.9.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:7f9eb79fcd19959353468160b798cb0ce11cb13dcb955c5757cc90069ee060bf"},
+    {file = "symengine-0.9.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:428df3675bb14e2460d0503d6f728a69a7a4ae4704d145f2e1b07f7d255eed50"},
+    {file = "symengine-0.9.0-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:2426075180573d6520c64f79b5a367c5e8c4c6255f600056da3fe28504654527"},
+    {file = "symengine-0.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:4aa002b6f4b29e34cce9712ed227a46f4243907a96ff907fc843c9f5bd0b829d"},
+    {file = "symengine-0.9.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e102ccbb3a5dba7b20fb62877c14dcdbd5d03066c5e39514c765166fd7c6c7f3"},
+    {file = "symengine-0.9.0-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:f7a0cad319398d075704ecd580f5d0bc2dd1782a347c31236e20670a54c37f19"},
+    {file = "symengine-0.9.0.tar.gz", hash = "sha256:a0c9374666ef12f67d013c4b14fec92e315cf6579c8537c78f053a8bd3402b24"},
 ]
 sympy = [
-    {file = "sympy-1.8-py3-none-any.whl", hash = "sha256:3b0b3776e357f789951bb14776c6a841f931680f20d5f8fe55977885657c9b7a"},
-    {file = "sympy-1.8.tar.gz", hash = "sha256:1ca588a9f6ce6a323c5592f9635159c2093572826668a1022c75c75bdf0297cb"},
+    {file = "sympy-1.10.1-py3-none-any.whl", hash = "sha256:df75d738930f6fe9ebe7034e59d56698f29e85f443f743e51e47df0caccc2130"},
+    {file = "sympy-1.10.1.tar.gz", hash = "sha256:5939eeffdf9e152172601463626c022a2c27e75cf6278de8d401d50c9d58787b"},
 ]
 tableschema = [
     {file = "tableschema-1.20.2-py2.py3-none-any.whl", hash = "sha256:676948747ec8964c6e27e12ce45e203201191bb7e81a26f2eb09a1fdbe130d5c"},
@@ -3135,17 +3638,25 @@ tabulator = [
     {file = "tabulator-1.53.5-py2.py3-none-any.whl", hash = "sha256:6de83026f9dc8ac34dbc9e60cced1785ed2f4022ae0250eeaa59e92b5090f477"},
     {file = "tabulator-1.53.5.tar.gz", hash = "sha256:0e2887d0b36483a292e75b118d7f03e710c1337435553b5f62d2a7a891b7fe55"},
 ]
+tenacity = [
+    {file = "tenacity-8.0.1-py3-none-any.whl", hash = "sha256:f78f4ea81b0fabc06728c11dc2a8c01277bfc5181b321a4770471902e3eb844a"},
+    {file = "tenacity-8.0.1.tar.gz", hash = "sha256:43242a20e3e73291a28bcbcacfd6e000b02d3857a9a9fff56b297a27afdc932f"},
+]
 tifffile = [
-    {file = "tifffile-2021.11.2-py3-none-any.whl", hash = "sha256:2e0066f90e2dbeb3e6a287cfd78bafbd2f142fabbca4a76a8ff809573baf5ad5"},
-    {file = "tifffile-2021.11.2.tar.gz", hash = "sha256:153e31fa1d892f482fabb2ae9f2561fa429ee42d01a6f67e58cee13637d9285b"},
+    {file = "tifffile-2022.4.8-py3-none-any.whl", hash = "sha256:00795738af6ebaf98da456eca2c637febde4fd467477c4ef2e09482883d44aed"},
+    {file = "tifffile-2022.4.8.tar.gz", hash = "sha256:d4a4057e5cb7afe6e24cf7bde42a163970b593afe44c17249894ede755cf3faa"},
 ]
 tinydb = [
-    {file = "tinydb-4.6.1-py3-none-any.whl", hash = "sha256:ac1fdae2a7d5d7e2ca915d2666e685d63982991827c5dd097b6be4a3b5822dbc"},
-    {file = "tinydb-4.6.1.tar.gz", hash = "sha256:0d5400f5e5ae368a84d57cb234456f1cf70430fd39bcd77ccd568fea91ff2a4e"},
+    {file = "tinydb-4.7.0-py3-none-any.whl", hash = "sha256:e2cdf6e2dad49813e9b5fceb3c7943387309a8738125fbff0b58d248a033f7a9"},
+    {file = "tinydb-4.7.0.tar.gz", hash = "sha256:357eb7383dee6915f17b00596ec6dd2a890f3117bf52be28a4c516aeee581100"},
+]
+toml = [
+    {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
+    {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
 ]
 tomli = [
-    {file = "tomli-2.0.0-py3-none-any.whl", hash = "sha256:b5bde28da1fed24b9bd1d4d2b8cba62300bfb4ec9a6187a957e8ddb9434c5224"},
-    {file = "tomli-2.0.0.tar.gz", hash = "sha256:c292c34f58502a1eb2bbb9f5bbc9a5ebc37bee10ffb8c2d6bbdfa8eb13cc14e1"},
+    {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
+    {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
 ]
 toolz = [
     {file = "toolz-0.11.2-py3-none-any.whl", hash = "sha256:a5700ce83414c64514d82d60bcda8aabfde092d1c1a8663f9200c07fdcc6da8f"},
@@ -3194,9 +3705,13 @@ tornado = [
     {file = "tornado-6.1-cp39-cp39-win_amd64.whl", hash = "sha256:548430be2740e327b3fe0201abe471f314741efcb0067ec4f2d7dcfb4825f3e4"},
     {file = "tornado-6.1.tar.gz", hash = "sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791"},
 ]
+tox = [
+    {file = "tox-3.25.0-py2.py3-none-any.whl", hash = "sha256:0805727eb4d6b049de304977dfc9ce315a1938e6619c3ab9f38682bb04662a5a"},
+    {file = "tox-3.25.0.tar.gz", hash = "sha256:37888f3092aa4e9f835fc8cc6dadbaaa0782651c41ef359e3a5743fcb0308160"},
+]
 tqdm = [
-    {file = "tqdm-4.62.3-py2.py3-none-any.whl", hash = "sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c"},
-    {file = "tqdm-4.62.3.tar.gz", hash = "sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d"},
+    {file = "tqdm-4.64.0-py2.py3-none-any.whl", hash = "sha256:74a2cdefe14d11442cedf3ba4e21a3b84ff9a2dbdc6cfae2c34addb2a14a5ea6"},
+    {file = "tqdm-4.64.0.tar.gz", hash = "sha256:40be55d30e200777a307a7585aee69e4eabb46b4ec6a4b4a5f2d9f11e7d5408d"},
 ]
 traitlets = [
     {file = "traitlets-5.1.1-py3-none-any.whl", hash = "sha256:2d313cc50a42cd6c277e7d7dc8d4d7fedd06a2c215f78766ae7b1a66277e0033"},
@@ -3239,23 +3754,31 @@ traits = [
     {file = "traits-6.3.2.tar.gz", hash = "sha256:4520ef4a675181f38be4a5bab1b1d5472691597fe2cfe4faf91023e89407e2c6"},
 ]
 typing-extensions = [
-    {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"},
-    {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"},
+    {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"},
+    {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"},
+]
+uncertainties = [
+    {file = "uncertainties-3.1.6-py2.py3-none-any.whl", hash = "sha256:cb4a66d5ceda006475ec845bf43ee8956c26138b08f93c41851c25a4ffe19a33"},
+    {file = "uncertainties-3.1.6.tar.gz", hash = "sha256:7c4db5aaafd227e95485b61fba5d235dc8133aeecd98f8fc1224c038ce063e2d"},
 ]
 unicodecsv = [
     {file = "unicodecsv-0.14.1.tar.gz", hash = "sha256:018c08037d48649a0412063ff4eda26eaa81eff1546dbffa51fa5293276ff7fc"},
 ]
 urllib3 = [
-    {file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"},
-    {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"},
+    {file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"},
+    {file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"},
+]
+virtualenv = [
+    {file = "virtualenv-20.14.1-py2.py3-none-any.whl", hash = "sha256:e617f16e25b42eb4f6e74096b9c9e37713cf10bf30168fb4a739f3fa8f898a3a"},
+    {file = "virtualenv-20.14.1.tar.gz", hash = "sha256:ef589a79795589aada0c1c5b319486797c03b67ac3984c48c669c0e4f50df3a5"},
 ]
 wcwidth = [
     {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
     {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
 ]
 xarray = [
-    {file = "xarray-0.20.2-py3-none-any.whl", hash = "sha256:048eee6036efd2a03e7eb3e91b5359c38da9e80aa6fa82def644a102d59bd78f"},
-    {file = "xarray-0.20.2.tar.gz", hash = "sha256:c2ebe80ca81b10a0241f6876dcc34ac9696e5c5cdcdf4758da7cf4bd732c41f7"},
+    {file = "xarray-2022.3.0-py3-none-any.whl", hash = "sha256:560f36eaabe7a989d5583d37ec753dd737357aa6a6453e55c80bb4f92291a69e"},
+    {file = "xarray-2022.3.0.tar.gz", hash = "sha256:398344bf7d170477aaceff70210e11ebd69af6b156fe13978054d25c48729440"},
 ]
 xlrd = [
     {file = "xlrd-2.0.1-py2.py3-none-any.whl", hash = "sha256:6a33ee89877bd9abc1158129f6e94be74e2679636b8a205b43b85206c3f0bbdd"},
@@ -3266,6 +3789,6 @@ xmltodict = [
     {file = "xmltodict-0.12.0.tar.gz", hash = "sha256:50d8c638ed7ecb88d90561beedbf720c9b4e851a9fa6c47ebd64e99d166d8a21"},
 ]
 zipp = [
-    {file = "zipp-3.7.0-py3-none-any.whl", hash = "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"},
-    {file = "zipp-3.7.0.tar.gz", hash = "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d"},
+    {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"},
+    {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"},
 ]
diff --git a/pyproject.toml b/pyproject.toml
index dab1167..669c4e8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,30 +1,37 @@
 [tool.poetry]
 name = "materials_io"
-version = "0.0.1"
+version = "0.1.1"
 description = "A library of tools that generate summaries of the data contained in scientific data files"
 authors = ["Materials Data Facility <materialsdatafacility@uchicago.edu>"]
 license = "Apache"
 
 [tool.poetry.dependencies]
-python = "^3.7"
+python = ">=3.8.0,<3.11"
 mdf-toolbox = "^0.5.3"
-stevedore = "^1.28.0"
+stevedore = "^3.5.0"
+pandas = "^1.4.2"
+llvmlite = "^0.38.0"
+numba = "^0.55"
 
 ase = { version = "~3.19", optional = true }
-pymatgen = { version = "^2018.11.30", optional = true}
+pymatgen = { version = "^2022.3.24", optional = true}
 tableschema = { version = "^1,<2", optional = true }
 dfttopif = { version = "^1.1.0", optional = true }
 hyperspy = { version = "^1.4.1", optional = true }
 python-magic = { version = "^0.4.15", optional = true }
-Pillow = { version = "^7.0.0", optional = true }
+Pillow = { version = "^9.0.1", optional = true }
 xmltodict = { version = "^0.12.0", optional = true }
-pycalphad = { version = "^0.9", optional = true }
+pycalphad = { version = "^0.10.0", optional = true }
 
 [tool.poetry.dev-dependencies]
-flake8 = "^4.0.1"
-pytest = "^3.10.1"
+flake8 = "^3.9.2"   # pinned due to incompatibility with flake8 v4 and sphinx
+pytest = "^7.1.1"
 coveralls = "^3.3.1"
-pytest-cov = "^2.9.0"
+pytest-cov = "^3.0.0"
+tox = "^3.25.0"
+Sphinx = "^4.5.0"
+sphinx-rtd-theme = "^1.0.0"
+diff-cover = "^6.4.5"
 
 [tool.poetry.extras]
 ase = ['ase']
@@ -68,10 +75,48 @@ all = ['ase',
 [tool.poetry.plugins."materialsio.adapter"]
 "noop" = "materials_io.adapters.base:NOOPAdapter"
 "serialize" = "materials_io.adapters.base:SerializeAdapter"
+"greedy_serialize" = "materials_io.adapters.base:GreedySerializeAdapter"
 
 [build-system]
 requires = ["poetry-core>=1.0.0"]
 build-backend = "poetry.core.masonry.api"
 
 [tool.pytest.ini_options]
-addopts = "--ignore=setup.py --ignore=.venv --cov=materials_io"
+addopts = "--ignore=.venv --ignore=.tox --cov=materials_io --cov-report html --cov-report term-missing --cov-report=xml"
+testpaths = ['tests']
+
+[tool.coverage.run]
+omit = [".tox/*"]
+dynamic_context = "test_function"
+
+[tool.coverage.report]
+show_missing = true
+
+[tool.coverage.html]
+directory = "coverage_html"
+show_contexts = true
+
+[tool.tox]
+legacy_tox_ini = """
+[tox]
+isolated_build = true
+envlist = py3{8,9,10}
+
+[testenv]
+passenv = *
+whitelist_externals = poetry
+commands =
+    poetry install -E all
+    poetry run flake8
+    poetry run pytest
+    poetry run diff-cover coverage.xml --compare-branch=origin/master
+
+[testenv:docs]
+passenv = *
+envlist = py310
+description = invoke sphinx-build to build the HTML docs
+commands =
+    poetry install -E all
+    poetry run flake8
+    poetry run python -m sphinx.cmd.build ./docs/source ./docs/_build -n -E -a -j auto -b html
+"""
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index d6d4afc..0000000
--- a/requirements.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-ase>=3.17
-dfttopif>=1.1.0
-mdf_toolbox>=0.5.3
-pymatgen>=2018.11.30
-python-magic>=0.4.15
-sphinx_rtd_theme>=0.4.2
-tableschema>=1,<2
-xmltodict>=0.12.0
diff --git a/setup.cfg b/setup.cfg
index c8b4963..e0e2d34 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,9 +1,6 @@
 [bdist_wheel]
 universal = 1
 
-[tool:pytest]
-addopts = --ignore=setup.py --ignore=.venv --cov=materials_io
-
 [flake8]
-exclude = .git,*.egg*,src/*,.venv
+exclude = .git,*.egg*,src/*,.*
 max-line-length = 100
diff --git a/setup.py b/setup.py
deleted file mode 100644
index aabbd45..0000000
--- a/setup.py
+++ /dev/null
@@ -1,52 +0,0 @@
-import os
-from setuptools import setup, find_packages
-
-# single source of truth for package version
-version_ns = {}
-with open(os.path.join("materials_io", "version.py")) as f:
-    exec(f.read(), version_ns)
-version = version_ns['__version__']
-
-# Requirements for the extras
-extra_reqs = {
-    'ase': ['ase>=3.19'],
-    'crystal_structure': ['pymatgen>=2018.11.30', 'ase>=3'],
-    'csv': ['tableschema>=1<2'],
-    'dft': ['dfttopif>=1.1.0'],
-    'electron_microscopy': ['hyperspy>=1.4.1'],
-    'file': ['python-magic>=0.4.15'],
-    'image': ['Pillow>=5.1.0'],
-    'xml': ['xmltodict>=0.12.0']
-}
-extra_reqs['all'] = set(sum(extra_reqs.values(), []))
-
-setup(
-    name="materials_io",
-    version=version,
-    packages=find_packages(include=['materials_io*']) + ['materials_io.schemas'],
-    install_requires=['mdf_toolbox>=0.5.3', 'stevedore>=1.28.0'],
-    extras_require=extra_reqs,
-    include_package_data=True,
-    package_data={'materials_io.schemas': ['*.json']},
-    entry_points={
-        'materialsio.parser': [
-            'ase = materials_io.ase:AseParser',
-            'crystal = materials_io.crystal_structure:CrystalStructureParser',
-            'csv = materials_io.csv:CSVParser',
-            'dft = materials_io.dft:DFTParser',
-            'em = materials_io.electron_microscopy:ElectronMicroscopyParser',
-            'filename = materials_io.filename:FilenameExtractor',
-            'generic = materials_io.file:GenericFileParser',
-            'image = materials_io.image:ImageParser',
-            'json = materials_io.json:JSONExtractor',
-            'noop = materials_io.testing:NOOPParser',
-            'tdb = materials_io.tdb:TDBExtractor',
-            'xml = materials_io.xml:XMLExtractor',
-            'yaml = materials_io.yaml:YAMLExtractor'
-        ],
-        'materialsio.adapter': [
-            'noop = materials_io.adapters.base:NOOPAdapter',
-            'serialize = materials_io.adapters.base:SerializeAdapter'
-        ]
-    }
-)


Test patch:
diff --git a/.github/workflows/test-suite-and-docs.yml b/.github/workflows/test-suite-and-docs.yml
new file mode 100644
index 0000000..c6bd77d
--- /dev/null
+++ b/.github/workflows/test-suite-and-docs.yml
@@ -0,0 +1,157 @@
+name: Build Status
+on: [push, pull_request]
+jobs:
+  run_test_suite:
+    name: ${{ matrix.os }}-py${{ matrix.python-version }}
+    env:
+      target_dir: './docs/_build'
+    strategy:
+      fail-fast: false
+      matrix:
+        python-version: ["3.8", "3.9", "3.10"]
+        poetry-version: ["1.1.13"]
+        os: [ubuntu-latest, macos-latest] #, windows-latest]
+        include:
+          # add upload coverage report to the highest version of ubuntu for codecov
+          - os: ubuntu-latest
+            python-version: "3.10"
+            upload-coverage: true
+            build-docs: true
+    runs-on: ${{ matrix.os }}
+    steps:
+      - name: Check out the repo at master branch (for diff-cover)
+        uses: actions/checkout@v3
+        with:
+          ref: master
+
+      - uses: actions/checkout@v3
+
+      - uses: actions/setup-python@v2
+        with:
+          python-version: ${{ matrix.python-version }}
+
+      - name: Install poetry
+        run: pip install poetry==${{ matrix.poetry-version }}
+        shell: bash
+
+      - name: View Python version
+        run: poetry run python --version
+
+      - name: Install package
+        run: poetry install -E all
+
+      - name: Flake8
+        run: poetry run flake8
+
+      - name: Echo args
+        run: echo ${{ matrix.upload-coverage }} and ${{ matrix.build-docs }}
+
+      - name: Run tests
+        run: poetry run pytest
+
+      - name: Run diff-cover
+        run: poetry run diff-cover coverage.xml --compare-branch=origin/master --diff-range-notation '..'
+
+      - name: Upload coverage to Codecov
+        if: ${{ matrix.upload-coverage }}
+        uses: codecov/codecov-action@v2
+
+      - name: Build documentation
+        if: ${{ matrix.build-docs }}
+        run: poetry run python -m sphinx.cmd.build ./docs/source ${{ env.target_dir }} -n -E -a -j auto -b html
+
+      - name: Upload built documentation
+        if: ${{ matrix.build-docs }}
+        uses: actions/upload-artifact@v3
+        with:
+          name: doc-build
+          path: ${{ env.target_dir }}
+
+  publish_docs_to_pages:
+    name: Publish pages
+    needs: run_test_suite
+    runs-on: ubuntu-latest
+    env:
+      target_dir: './docs/_build'
+    steps:
+      # create git repository so we can later push to gh-pages branch
+      - uses: actions/checkout@v3
+        with:
+          ref: ${{ github.event.workflow_run.head_branch }}
+      - run: git branch
+      # restore docs built in last step
+      - name: Restore documentation build from artifact
+        uses: actions/download-artifact@v3
+        with:
+          name: doc-build
+          path: ${{ env.target_dir }}
+      # publish documentation to Github pages (mostly cribbed from
+      #  https://github.com/sphinx-notes/pages)
+      - name: Publish sphinx documentation to Github Pages
+        env:
+          INPUT_TARGET_BRANCH: gh-pages
+          INPUT_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          INPUT_TARGET_PATH: '.'
+        run: |
+          echo ::group:: Creating temp directory
+          tmp_dir=$(mktemp -d -t pages-XXXXXXXXXX)
+          echo Temp directory \"$tmp_dir\" is created
+          echo ::endgroup::
+          
+          echo ::group:: Copying built docs to tmp_dir
+          cp -vr ${{ env.target_dir }}/. ${tmp_dir}
+          echo ::endgroup::
+
+          repo_dir=${GITHUB_WORKSPACE}/${INPUT_REPOSITORY_PATH}
+          doc_dir=$repo_dir/${INPUT_DOCUMENTATION_PATH}
+          
+          echo ::group:: Initialize various paths
+          echo Workspace: ${GITHUB_WORKSPACE}
+          echo Repository: ${repo_dir}
+          echo Documentation: ${doc_dir}
+          echo ::endgroup::
+
+          echo ::group:: Setting up git repository
+          echo Setting up git configure
+          cd ${repo_dir}
+          git config --local user.email "action@github.com"
+          git config --local user.name "GitHub Sphinx-to-Pages Action"
+          git stash
+          branch_exist=$(git ls-remote --heads origin refs/heads/${INPUT_TARGET_BRANCH})
+          if [ -z "${branch_exist}" ]; then
+              echo Branch doesn\'t exist, create an empty branch
+              git checkout --force --orphan ${INPUT_TARGET_BRANCH}
+          else
+              echo Branch exists, checkout to it
+              git fetch
+              git checkout --force --track origin/${INPUT_TARGET_BRANCH}
+          fi
+          git clean -fd
+          echo ::endgroup::
+
+          echo ::group:: Committing HTML documentation
+          cd $repo_dir
+          echo Deleting all file in repository
+          rm -vrf *
+          echo Copying HTML documentation to repository
+          # Remove unused doctree
+          rm -rf ${tmp_dir}/.doctrees
+          cp -vr ${tmp_dir}/. $INPUT_TARGET_PATH
+          echo Adding HTML documentation to repository index
+          git add ${INPUT_TARGET_PATH}
+          echo Committing changes to repository
+          git commit --allow-empty -m "Add changes for ${GITHUB_SHA}"
+          echo ::endgroup::
+          
+          echo "Push to branch INPUT_TARGET_BRANCH (${INPUT_TARGET_BRANCH})";
+          [ -z "${INPUT_GITHUB_TOKEN}" ] && {
+              echo 'Missing input "github_token: ${{ secrets.GITHUB_TOKEN }}".';
+              exit 1;
+          };
+          remote_repo="https://${GITHUB_ACTOR}:${INPUT_GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
+          echo "GITHUB_ACTOR: ${GITHUB_ACTOR}"
+          echo "GITHUB_REPOSITORY: ${GITHUB_REPOSITORY}"
+          echo "remote_repo is ${remote_repo}"
+          git push "${remote_repo}" HEAD:${INPUT_TARGET_BRANCH} --follow-tags;
+          REPO_NAME=$()
+          echo "Pages should be viewable at https://${GITHUB_ACTOR}.github.io/${GITHUB_REPOSITORY//$GITHUB_ACTOR\//}"
diff --git a/test_requirements.txt b/test_requirements.txt
deleted file mode 100644
index 9781206..0000000
--- a/test_requirements.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-pytest>=3.6
-flake8
-coveralls
-pytest-cov
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/data/electron_microscopy/test_files.tar.gz b/tests/data/electron_microscopy/test_files.tar.gz
index 0d84807..b003438 100644
Binary files a/tests/data/electron_microscopy/test_files.tar.gz and b/tests/data/electron_microscopy/test_files.tar.gz differ
diff --git a/tests/test_adapter.py b/tests/test_adapter.py
index eb53a30..8cd2916 100644
--- a/tests/test_adapter.py
+++ b/tests/test_adapter.py
@@ -1,4 +1,4 @@
-from materials_io.adapters.base import NOOPAdapter
+from materials_io.adapters.base import NOOPAdapter, GreedySerializeAdapter
 from materials_io.testing import NOOPParser
 
 
@@ -17,3 +17,10 @@ def test_compatibility():
     # Make sure giving it a different version number breaks compatibility
     adapter.version = lambda: parser.version() + '1'
     assert not adapter.check_compatibility(parser)
+
+
+def test_greedy_adapter_unserializable():
+    adapter = GreedySerializeAdapter()
+    unserializable_bytes = {'key': b'\x03\xdd'}
+    s = adapter.transform(unserializable_bytes)
+    assert s == '{"key": "<<Unserializable type: bytes>>"}'
diff --git a/tests/test_electron_microscopy.py b/tests/test_electron_microscopy.py
index 564a3a6..4f535b1 100644
--- a/tests/test_electron_microscopy.py
+++ b/tests/test_electron_microscopy.py
@@ -1,15 +1,13 @@
 import pytest
 import pathlib
-import json
 import jsonschema
 
-from materials_io import electron_microscopy
 from materials_io.electron_microscopy import ElectronMicroscopyParser
+from materials_io.adapters.base import GreedySerializeAdapter
 
 
 def file_path(fname):
-    return pathlib.Path(pathlib.PurePath(__file__).parent,
-                        'data', 'electron_microscopy', fname)
+    return pathlib.Path(pathlib.PurePath(__file__).parent, 'data', 'electron_microscopy', fname)
 
 
 @pytest.fixture
@@ -18,16 +16,11 @@ def parser():
 
 
 @pytest.fixture
-def schema() -> dict:
-    """Return the JSON schema associated with this parser as a dictionary"""
-    p = pathlib.PurePath(electron_microscopy.__file__)
-    schema_path = p.parent / 'schemas' / f"{p.stem}.json"
-    with open(schema_path, 'r') as f:
-        schema = json.load(f)
-    return schema
+def adapter():
+    return GreedySerializeAdapter()
 
 
-def test_dm3(parser, schema):
+def test_dm3(parser, adapter):
     res = parser.parse([file_path('test-1.dm3')])
     assert res['electron_microscopy']['General'] == {
         'original_filename': {'value': 'test-1.dm3'},
@@ -37,10 +30,11 @@ def test_dm3(parser, schema):
                        'size': 2, 'units': ''}},
         'data_dimensions': [2]
     }
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
 
-def test_dm4(parser, schema):
+def test_dm4(parser, adapter):
     res = parser.parse([file_path('test-1.dm4')])
     assert res['electron_microscopy']['General'] == {
         'original_filename': {'value': 'test-1.dm4'},
@@ -51,10 +45,11 @@ def test_dm4(parser, schema):
             'axis-1': {'name': 'x', 'scale': 1.0, 'offset': -0.0,
                        'size': 2, 'units': ''}},
         'data_dimensions': [2, 2]}
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
 
-def test_eds(parser, schema):
+def test_eds(parser, adapter):
     res = parser.parse([file_path('01_test-EDS_spectrum.dm3')])
 
     assert res['electron_microscopy']['General'] == {
@@ -104,7 +99,8 @@ def test_eds(parser, schema):
         'incidence_angle': {'value': 90.0, 'units': 'DEG'},
         'solid_angle': {'value': 0.7, 'units': 'SR'},
         'stage_tilt': {'value': 0.0, 'units': 'DEG'}}
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
     res = parser.parse([file_path('02_EDS_SI_Titan.dm4')])
     assert res['electron_microscopy']['General'] == {
@@ -157,10 +153,11 @@ def test_eds(parser, schema):
         'incidence_angle': {'value': 90.0, 'units': 'DEG'},
         'solid_angle': {'value': 0.002, 'units': 'SR'},
         'stage_tilt': {'value': 0.0, 'units': 'DEG'}}
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
 
-def test_edax_eds(parser, schema):
+def test_edax_eds(parser, adapter):
     res = parser.parse([file_path('03_edax_sem_eds_map_dataZeroed.spd')])
 
     assert res['electron_microscopy']['General'] == {
@@ -188,10 +185,11 @@ def test_edax_eds(parser, schema):
                                    'units': 'EV'},
         'live_time': {'value': 2621.43994140625, 'units': 'SEC'}
     }
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
 
-def test_eels(parser, schema):
+def test_eels(parser, adapter):
     res = parser.parse([file_path('04_Titan_EELS_SI_dataZeroed.dm3')])
     assert res['electron_microscopy']['General'] == {
         'date': {'value': '2016-04-22'},
@@ -249,10 +247,11 @@ def test_eels(parser, schema):
         'prism_shift_enabled': {'value': True},
         'filter_slit_width': {'value': 10.0, 'units': 'EV'},
         'filter_slit_inserted': {'value': False}}
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
 
-def test_non_titan_dm3(parser, schema):
+def test_non_titan_dm3(parser, adapter):
     res = parser.parse([file_path('05_nonTitan_diffraction.dm3')])
     assert res['electron_microscopy']['General'] == {
         'date': {'value': '2019-07-01'},
@@ -270,10 +269,11 @@ def test_non_titan_dm3(parser, schema):
         'exposure_time': {'value': 0.1, 'units': 'SEC'}}
     assert res['electron_microscopy']['TEM'] == {
         'acquisition_device': {'value': 'Orius '}}
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
 
-def test_dm3_tecnai(parser, schema):
+def test_dm3_tecnai(parser, adapter):
     eels_mdata = {
         'spectrometer_mode': {'value': 'Spectroscopy'},
         'dispersion_per_channel': {'value': 0.1, 'units': 'EV'},
@@ -327,7 +327,8 @@ def test_dm3_tecnai(parser, schema):
         'defocus': {'value': -0.0, 'units': 'MicroM'},
         'spot_size': {'value': 2, 'units': 'UNITLESS'}}
     assert res['electron_microscopy']['EELS'] == eels_mdata
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
     # parse diffraction mode tecnai dm3
     res = parser.parse([file_path('07_Titan_Tecnai_diffraction.dm3')])
@@ -374,7 +375,8 @@ def test_dm3_tecnai(parser, schema):
         'defocus': {'value': 0.082, 'units': 'MicroM'},
         'spot_size': {'value': 8, 'units': 'UNITLESS'}}
     assert res['electron_microscopy']['EELS'] == eels_mdata
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
     # parse diffraction mode tecnai with no spectrometer info
     res = parser.parse([file_path(
@@ -420,10 +422,11 @@ def test_dm3_tecnai(parser, schema):
         'extractor_voltage': {'value': 4500, 'units': 'V'},
         'defocus': {'value': 0.0, 'units': 'MicroM'},
         'spot_size': {'value': 3, 'units': 'UNITLESS'}}
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
 
-def test_dm3_stack(parser, schema):
+def test_dm3_stack(parser, adapter):
     res = parser.parse([file_path('09_Titan_STEM_stack.dm3')])
     # note that the axis_calibration values are bogus, but they're not read
     # correctly my DigitalMicrograph, so we cannot expect to do better than
@@ -463,10 +466,11 @@ def test_dm3_stack(parser, schema):
         'imaging_mode': {'value': 'DIFFRACTION'},
         'illumination_mode': {'value': 'STEM NANOPROBE'},
         'acquisition_device': {'value': 'DigiScan'}}
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
 
-def test_eels_acquisition_spectrometer(parser, schema):
+def test_eels_acquisition_spectrometer(parser, adapter):
     res = parser.parse([file_path('10_Titan_EELS_proc.dm3')])
     assert res['electron_microscopy']['General'] == {
         'original_filename': {'value': '10_Titan_EELS_proc.dm3'},
@@ -508,10 +512,11 @@ def test_eels_acquisition_spectrometer(parser, schema):
         'drift_tube_enabled': {'value': True},
         'prism_shift_voltage': {'value': 0.0, 'units': 'V'},
         'prism_shift_enabled': {'value': True}}
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
 
-def test_hs_signal_no_units(parser, schema):
+def test_hs_signal_no_units(parser, adapter):
     res = parser.parse([file_path('11_hs_signal_no_axis_units.hspy')])
     assert res['electron_microscopy']['General'] == {
         'axis_calibration': {
@@ -522,10 +527,11 @@ def test_hs_signal_no_units(parser, schema):
             'axis-2': {'name': None, 'scale': 1.0,
                        'offset': 0.0, 'size': 10, 'units': None}},
         'data_dimensions': [10, 10, 10]}
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
 
-def test_tia_haadf(parser, schema):
+def test_tia_haadf(parser, adapter):
     res = parser.parse([file_path('12_TIA_HAADF.emi')])
     assert res['electron_microscopy']['General'] == {
         'date': {'value': '2019-06-28'},
@@ -566,10 +572,11 @@ def test_tia_haadf(parser, schema):
         'prism_shift_energy': {'value': -0.0, 'units': 'EV'},
         'drift_tube_energy': {'value': 0.0, 'units': 'EV'},
         'total_energy_loss': {'value': 0.0, 'units': 'EV'}}
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
 
-def test_quanta_sem_tif(parser, schema):
+def test_quanta_sem_tif(parser, adapter):
     res = parser.parse([file_path('20_quanta_sem.tif')])
     assert res['electron_microscopy']['General'] == {
         'date': {'value': '2022-03-03'},
@@ -601,7 +608,62 @@ def test_quanta_sem_tif(parser, schema):
         'pixel_height': {'value': 1.25e-09, 'units': 'M'},
         'magnification_mode': {'value': 3},
         'chamber_pressure': {'value': 0.000703102, 'units': 'PA'}}
-    assert jsonschema.validate(res, schema) is None
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
+
+
+def test_zeiss_sem_tif(parser, adapter):
+    res = parser.parse([file_path('21_zeiss_sem.tif')])
+    assert res['electron_microscopy']['General'] == {
+        'date': {'value': '2017-12-15'},
+        'original_filename': {'value': '21_zeiss_sem.tif'},
+        'time': {'value': '10:43:43'},
+        'axis_calibration': {
+            'axis-0': {'name': 'height', 'scale': 1.057033e-09, 'offset': 0.0, 'size': 768,
+                       'units': 'M'},
+            'axis-1': {'name': 'width', 'scale': 1.057033e-09, 'offset': 0.0, 'size': 1024,
+                       'units': 'M'}},
+        'data_dimensions': [768, 1024]}
+    assert res['electron_microscopy']['General_EM'] == {
+        'beam_current': {'value': 0.159, 'units': 'NanoA'},
+        'beam_energy': {'value': 15.0, 'units': 'KiloEV'},
+        'microscope_name': {'value': '1525-XX-XX'},
+        'stage_position': {'rotation': {'value': 4.3, 'units': 'DEG'},
+                           'x': {'value': 56.8511, 'units': 'MilliM'},
+                           'y': {'value': 53.0695, 'units': 'MilliM'},
+                           'z': {'value': 14.996, 'units': 'MilliM'}},
+        'magnification_indicated': {'value': 267430.0, 'units': 'UNITLESS'}}
+    assert res['electron_microscopy']['SEM'] == {
+        'working_distance': {'value': 2.0, 'units': 'MilliM'}}
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
+
+
+def test_zeiss_sem_bad_mag_tif(parser, adapter):
+    res = parser.parse([file_path('22_zeiss_sem_bad_mag.tif')])
+    assert res['electron_microscopy']['General'] == {
+        'date': {'value': '2017-12-15'},
+        'original_filename': {'value': '22_zeiss_sem_bad_mag.tif'},
+        'time': {'value': '10:43:43'},
+        'axis_calibration': {
+            'axis-0': {'name': 'height', 'scale': 1.057033e-09,
+                       'offset': 0.0, 'size': 768, 'units': 'M'},
+            'axis-1': {'name': 'width', 'scale': 1.057033e-09,
+                       'offset': 0.0, 'size': 1024, 'units': 'M'}},
+        'data_dimensions': [768, 1024]}
+    assert res['electron_microscopy']['General_EM'] == {
+        'beam_current': {'value': 0.159, 'units': 'NanoA'},
+        'beam_energy': {'value': 15.0, 'units': 'KiloEV'},
+        'microscope_name': {'value': '1525-XX-XX'},
+        'stage_position': {'rotation': {'value': 4.3, 'units': 'DEG'},
+                           'x': {'value': 56.8511, 'units': 'MilliM'},
+                           'y': {'value': 53.0695, 'units': 'MilliM'},
+                           'z': {'value': 14.996, 'units': 'MilliM'}},
+        'magnification_indicated': {'value': 'TESTER', 'units': 'UNITLESS'}}
+    assert res['electron_microscopy']['SEM'] == {
+        'working_distance': {'value': 2.0, 'units': 'MilliM'}}
+    assert jsonschema.validate(res, parser.schema) is None
+    assert adapter.transform(res)
 
 
 def test_implementors(parser):
@@ -610,4 +672,4 @@ def test_implementors(parser):
 
 
 def test_version(parser):
-    assert parser.version() == '0.1.0'
+    assert parser.version() == '0.1.2'
diff --git a/tests/test_file.py b/tests/test_file.py
index 8643a42..3f91dd0 100644
--- a/tests/test_file.py
+++ b/tests/test_file.py
@@ -1,4 +1,5 @@
 from materials_io.file import GenericFileParser
+import pytest
 import os
 
 
@@ -18,6 +19,16 @@ def test_file():
         'sha512': '1f47ed450ad23e92caf1a0e5307e2af9b13edcd7735ac9685c9f21c'
                   '9faec62cb95892e890a73480b06189ed5b842d8b265c5e47cc6cf27'
                   '9d281270211cff8f90'}
+
+    # be defensive against data_type, which will only be present if the user has libmagic installed
+    if 'data_type' not in output:
+        del expected['data_type']
+        del expected['mime_type']
+        assert output == expected
+        assert isinstance(parser.schema, dict)
+        pytest.xfail("'data_type' was not present in the parser output, most likely because "
+                     "libmagic is not properly installed")
+
     for i in ['JPEG image data', 'density 300x300', 'TIFF image data',
               '1910x1000']:
         assert i in output['data_type']
diff --git a/tests/test_version.py b/tests/test_version.py
new file mode 100644
index 0000000..97269c7
--- /dev/null
+++ b/tests/test_version.py
@@ -0,0 +1,5 @@
+from materials_io import version
+
+
+def test_version():
+    assert version.__version__ == '0.1.1'