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

Issue:
Consistently name tools "extractors"
The MaRDA automated extractors group calls tools like ours "extractors," so let's go that way

Some tools are named "extractors," others "parsers." The documentation uses the term "parser."





Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index 3531a04..6faebd2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,7 +9,7 @@ Untitled*.ipynb
 
 */build/*
 docs/_build
-materials_io/schemas/doc/
+scythe/schemas/doc/
 */dist/*
 *.egg*
 src/*
diff --git a/MANIFEST.in b/MANIFEST.in
index b10bae5..9ea4431 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,1 +1,1 @@
-recursive-include materials_io/schemas *.json
+recursive-include scythe/schemas *.json
diff --git a/README.md b/README.md
index 64b997f..e83de7f 100644
--- a/README.md
+++ b/README.md
@@ -1,43 +1,43 @@
-# MaterialsIO
+# Scythe
 
-[![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)
+[![Build Status](https://github.com/materials-data-facility/Scythe/workflows/Build%20Status/badge.svg)](https://github.com/materials-data-facility/Scythe/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/Scythe)
+[![Coverage Status](https://codecov.io/gh/materials-data-facility/Scythe/branch/master/graph/badge.svg)](https://codecov.io/gh/materials-data-facility/Scythe)
+[![GitHub tag checks state](https://img.shields.io/github/checks-status/materials-data-facility/Scythe/master)](https://github.com/materials-data-facility/Scythe/actions)
+[![GitHub last commit](https://img.shields.io/github/last-commit/materials-data-facility/Scythe)](https://github.com/materials-data-facility/Scythe/commits/master)
+[![GitHub contributors](https://img.shields.io/github/contributors/materials-data-facility/Scythe)](https://github.com/materials-data-facility/Scythe/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.
-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.
+Scythe is a library of tools that generate summaries of the data contained in scientific data files.
+The goal of Scythe is to provide a shared resources of these tools ("extractors") to avoid duplication of effort between the many emerging materials databases.
+Each extractor 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.
 
 ## Installation
 
-MaterialsIO is still under early stages of development. 
+Scythe is still under early stages of development. 
 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
-pip install git+https://github.com/materials-data-facility/MaterialsIO.git
+pip install git+https://github.com/materials-data-facility/Scythe.git
 ```
 
-Each specific parser module has its own set of required libraries.
+Each specific extractor 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 "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]"`.
+`pip install "git+https://github.com/materials-data-facility/Scythe.git#egg=scythe[image]"`),
+or install all extractors with 
+`pip install "git+https://github.com/materials-data-facility/Scythe.git#egg=scythe[all]"`.
 
 ## Development/Contribution
 
-If you wish to develop new features using MaterialsIO, please consult the 
+If you wish to develop new features using Scythe, 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.
+walk you through installing [Poetry](https://python-poetry.org/) and the Scythe dependencies.
 
 ## Documentation
 
-* Complete documentation for MaterialsIO is on [Read the Docs](https://materialsio.readthedocs.io/en/latest/).
-* [List of Available Parsers](https://materialsio.readthedocs.io/en/latest/parsers.html)
+* Complete documentation for Scythe is on [Read the Docs](https://materialsio.readthedocs.io/en/latest/).
+* [List of Available Extractors](https://materialsio.readthedocs.io/en/latest/extractors.html)
 
 ## Support 
 
diff --git a/docs/source/api/materials_io.rst b/docs/source/api/materials_io.rst
deleted file mode 100644
index 827382d..0000000
--- a/docs/source/api/materials_io.rst
+++ /dev/null
@@ -1,22 +0,0 @@
-materials_io
-============
-
-Documentation for the non-parser functions in ``materials_io``.
-
-materials_io.adapters.base
---------------------------
-
-.. automodule:: materials_io.adapters.base
-    :members:
-
-materials_io.utils.interface
-----------------------------
-
-.. automodule:: materials_io.utils.interface
-    :members:
-
-materials_io.utils.grouping
----------------------------
-
-.. automodule:: materials_io.utils.grouping
-    :members:
\ No newline at end of file
diff --git a/docs/source/api/scythe.rst b/docs/source/api/scythe.rst
new file mode 100644
index 0000000..7f55e2d
--- /dev/null
+++ b/docs/source/api/scythe.rst
@@ -0,0 +1,22 @@
+scythe
+============
+
+Documentation for the non-parser functions in ``scythe``.
+
+scythe.adapters.base
+--------------------
+
+.. automodule:: scythe.adapters.base
+    :members:
+
+scythe.utils.interface
+----------------------
+
+.. automodule:: scythe.utils.interface
+    :members:
+
+scythe.utils.grouping
+---------------------
+
+.. automodule:: scythe.utils.grouping
+    :members:
\ No newline at end of file
diff --git a/docs/source/conf.py b/docs/source/conf.py
index bf04430..1e32337 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -16,12 +16,12 @@
 # import sys
 # sys.path.insert(0, os.path.abspath('.'))
 
-from materials_io import __version__
+from scythe import __version__
 
 
 # -- Project information -----------------------------------------------------
 
-project = 'MaterialsIO'
+project = 'Scythe'
 copyright = '2019 - 2022, Materials Data Facility Team, Citrine Informatics'
 author = 'Materials Data Facility Team, Citrine Informatics'
 
@@ -68,7 +68,7 @@
 #
 # This is also used if you do content translation via gettext catalogs.
 # Usually you set "language" from the command line for these cases.
-language = None
+language = 'EN-US'
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
@@ -111,7 +111,7 @@
 # -- Options for HTMLHelp output ---------------------------------------------
 
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'MaterialsIOdoc'
+htmlhelp_basename = 'Scythedoc'
 
 
 # -- Options for LaTeX output ------------------------------------------------
@@ -138,7 +138,7 @@
 # (source start file, target name, title,
 #  author, documentclass [howto, manual, or own class]).
 latex_documents = [
-    (master_doc, 'MaterialsIO.tex', 'MaterialsIO Documentation',
+    (master_doc, 'Scythe.tex', 'Scythe Documentation',
      'Materials Data Facility Team, Citrine Informatics', 'manual'),
 ]
 
@@ -148,7 +148,7 @@
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 man_pages = [
-    (master_doc, 'materialsio', 'MaterialsIO Documentation',
+    (master_doc, 'materialsio', 'Scythe Documentation',
      [author], 1)
 ]
 
@@ -159,8 +159,8 @@
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 texinfo_documents = [
-    (master_doc, 'MaterialsIO', 'MaterialsIO Documentation',
-     author, 'MaterialsIO', 'One line description of project.',
+    (master_doc, 'Scythe', 'Scythe Documentation',
+     author, 'Scythe', 'One line description of project.',
      'Miscellaneous'),
 ]
 
diff --git a/docs/source/contributor-guide.rst b/docs/source/contributor-guide.rst
index 063a2de..371d591 100644
--- a/docs/source/contributor-guide.rst
+++ b/docs/source/contributor-guide.rst
@@ -4,26 +4,26 @@ Contributor Guide
 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
+Scythe makes use of the `Poetry <https://python-poetry.org/docs/>`_ project to manage
+dependencies and packaging. To install the latest version of Scythe, 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
+done, clone/download the Scythe repository locally from
+`Github <https://github.com/materials-data-facility/Scythe/>`_. 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
+By default, only a small subset of extractors will be installed (this is done so that you do not
+need to install all the dependencies of extractors you may never use). To install additional
+extractors, 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::
+which will install all bundled extractors and their dependencies. For example::
 
     poetry install -E all
 
-Poetry wil create a dedicated virtual environment for the project and the MaterialsIO code will
+Poetry wil create a dedicated virtual environment for the project and the Scythe 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.
+running tests, importing extractors, etc. It will use the default version of python available.
+Scythe 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
@@ -33,7 +33,7 @@ Additionally, the project uses `tox <https://tox.wiki/en/latest/>`_ to simplify
 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::
+run the full Scythe test suite on all three versions of Python targetd, just run::
 
     poetry run tox
 
@@ -51,45 +51,45 @@ Check out the ``[tool.tox]`` section of the ``pyproject.toml`` file to view how
 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
+Finally, Scythe 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.
+The next part of the Scythe guide details how to add a new extractor to the ecosystem.
 
-Step 1: Implement the Parser
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Step 1: Implement the Extractor
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Creating a new parser is accomplished by implementing the
-`BaseParser <user-guide.html#parser-api>`_ abstract class. If you are new to MaterailsIO, we
+Creating a new extractor is accomplished by implementing the
+`BaseExtractor <user-guide.html#extractor-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
+the available methods of BaseExtractor. Minimally, you need only implement the ``extract``,
+``version``, and ``implementors`` operations for a new extractor. 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.
+behavior of the extractor.
 
-We also have subclasses of ``BaseParser`` that are useful for common types of parsers:
+We also have subclasses of ``BaseExtractor`` that are useful for common types of extractors:
 
-- ``BaseSingleFileParser``: Parsers that only ever evaluate a single file at a time
+- ``BaseSingleFileExtractor``: Extractors that only ever evaluate a single file at a time
 
 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
+The ``BaseExtractor`` class supports configuration options as Python class attributes.
+These options are intended to define the behavior of an extractor 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.
 
-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
+The initializer function should check if an extractor has access to all required external tools, and
+throw exceptions if not. For example, an extractor that relies on calling an external command-line
+tool should check whether the package is installed. In general, extractors should fail during
 initialization and not during the parsing operation if the system in misconfigured.
 
-Implementing ``parse``
-----------------------
+Implementing ``extract``
+------------------------
 
-The ``parse`` method contains the core logic of a MaterialsIO parser: rendering a summary of a
+The ``extract`` method contains the core logic of a Scythe extractor: 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:
 
@@ -105,18 +105,18 @@ best practices:
 
 #. *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.
+    used for parsing. Deviating from already existing formats complicates modifications to an extractor.
 
 #. *Always return a dictionary.*
-    If a parser can return multiple records from a single file group, return the list as an element
+    If an extractor 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:
+We also have a recommendations for the extractor behavior:
 
 #. *Avoid configuration options that change only output format.*
-    Parsers can take configuration options that alter the output format, but configurations
+    Extractors 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
@@ -132,7 +132,7 @@ 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.
+extractor 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
@@ -142,19 +142,19 @@ 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.
 
-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
+It is important to note that that file groups are specific to an extractor. Groupings of files that
+are meaningful to one extractor 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.
+to parse correctly. For example, a PDF extractor 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
+The ``citation`` and ``implementors`` methods identify additional resources describing an extractor
 and provide credit to contributors. ``implementors`` is required, as this operation is also used
 to identify points-of-contact for support requests.
 
@@ -166,64 +166,64 @@ 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.
+We require using `semantic versioning <https://semver.org/>`_ for specifying the version of extractors.
+As the API of the extractor should remain unchanged, use versioning to indicate changes in available
+options or the output schema. The ``version`` operation should return the version of the extractor.
 
 
-Step 2: Document the Parser
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Step 2: Document the Extractor
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The docstring for a parser must start with a short, one sentence summary of the parser, which
+The docstring for an extractor must start with a short, one sentence summary of the extractor, 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
+types of files are compatible, what context information can be used, and
 summarize what types of metadata are generated.
 
-.. todo:: Actually write these descriptors for the available parsers
+.. todo:: Actually write these descriptors for the available extractors
 
-The MaterialsIO project uses JSON documents as the output for all parsers and
+The Scythe project uses JSON documents as the output for all extractors 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.
+BaseExtractor 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>`_
+`GenericFileExtractor source code <https://github.com/materials-data-facility/Scythe/blob/master/scythe/file.py>`_
 for a example.
 
 
-Step 3: Register the Parser
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Step 3: Register the Extractor
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Preferred Route: Adding the Parser to MaterialsIO
--------------------------------------------------
+Preferred Route: Adding the Extractor to Scythe
+-----------------------------------------------
 
-If your parser has the same dependencies as existing parsers, add it to the existing module with
+If your extractor has the same dependencies as existing extractors, 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
+If your extractor has new dependencies, create a new module for your extractor in ``scythe``, 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
+.toml``, following the other extractor examples in that section. Next, add your extractor to
+``docs/source/extractors.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 ``[tool.poetry.plugins."materialsio.parser"]`` section of the
-``pyproject.toml`` file for MaterialsIO. See
+Scythe uses ``stevedore`` to simplify access to the extractors. After implementing and
+documenting the extractor, add it to the ``[tool.poetry.plugins."scythe.extractor"]`` section of the
+``pyproject.toml`` file for Scythe. 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
----------------------------------------------------------
+Alternative Route: Including Extractors 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 ``pyproject.toml`` file. Add an entry point with the
-namespace ``"materialsio.parser"`` and point to the class object following the
+If an extractor would be better suited as part of a different library, you can still register it as a
+extractor with Scythe by altering your ``pyproject.toml`` file. Add an entry point with the
+namespace ``"scythe.extractor"`` 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 library is installed in the
-same Python environment as MaterialsIO.
+Adding the entry point will let Scythe use your extractor if your library is installed in the
+same Python environment as Scythe.
 
-.. todo:: Provide a public listing of materials_io-compatible software.
+.. todo:: Provide a public listing of scythe-compatible software.
 
     So that people know where to find these external libraries
diff --git a/docs/source/extractors.rst b/docs/source/extractors.rst
new file mode 100644
index 0000000..c893958
--- /dev/null
+++ b/docs/source/extractors.rst
@@ -0,0 +1,80 @@
+Available Extractors
+====================
+
+These pages detail all of the extractors currently available in Scythe.
+
+Quick Summary
+~~~~~~~~~~~~~
+
+The extractors that are configured to work with the stevedore plugin are:
+
+.. list-plugins:: scythe.extractor
+
+
+Detailed Listing
+~~~~~~~~~~~~~~~~
+
+Generic File Extractors
+-----------------------
+
+Extractors that work for any kind of file
+
+.. automodule:: scythe.file
+    :members:
+    :exclude-members: implementors, schema, version, group
+
+Image Extractors
+----------------
+
+Extractors that read image data
+
+.. automodule:: scythe.image
+    :members:
+    :exclude-members: implementors, schema, version, group
+
+Electron Microscopy Extractors
+------------------------------
+
+Extractors that read electron microscopy data of various sorts (images, spectra, spectrum images,
+etc.) using the `HyperSpy <https://hyperspy.org>`_ package.
+
+.. automodule:: scythe.electron_microscopy
+    :members:
+    :exclude-members: implementors, schema, version, group
+
+Atomistic Data Extractors
+-------------------------
+
+Extractors related to data files that encode atom-level structure
+
+.. automodule:: scythe.crystal_structure
+    :members:
+    :exclude-members: implementors, schema, version, group
+
+.. automodule:: scythe.ase
+    :members:
+    :noindex:
+    :exclude-members: implementors, schema, version, group
+
+Calculation Extractors
+----------------------
+
+Extractors that retrieve results from calculations
+
+.. automodule:: scythe.dft
+    :members:
+    :exclude-members: implementors, schema, version, group
+
+.. automodule:: scythe.ase
+    :members:
+    :noindex:
+    :exclude-members: implementors, schema, version, group
+
+Structured Data Files
+---------------------
+
+Extractors that read data from structured files
+
+.. automodule:: scythe.csv
+    :members:
+    :exclude-members: implementors, schema, version, group
diff --git a/docs/source/goals.rst b/docs/source/goals.rst
index 89cacdd..909cbed 100644
--- a/docs/source/goals.rst
+++ b/docs/source/goals.rst
@@ -1,49 +1,49 @@
 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
+The goal of Scythe is to minimize the amount of code duplication between scientific databases.
+Many databases rely on custom software to extract information from scientific files and transform that data into a standardized format.
+Automation or analysis software also require 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.
+*Scythe is designed to be a shared repository for these algorithms*.
+
+The core of Scythe is a collection of "extractors" 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
+:class:`~scythe.electron_microscopy.ElectronMicroscopyExtractor` 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
+Each extractor does not necessarily generate data in a format needed by any tool. Rather, the extractors
 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.
+libraries. In this way, the extractors can service every user without modification.
 
-What Does MaterialsIO *Do*?
+What Does Scythe *Do*?
 ---------------------------
 
-MaterialsIO is designed to provide the answer to two limited questions:
+Scythe is designed to provide the answer to two limited questions:
 
 1. *Which files can I parse with a certain tool?*
-    MaterialsIO provides tools for quickly finding files of a certain type
+    Scythe provides tools for quickly finding files of a certain type
 
 2. *What information does a set of files contain?*
-    MaterialsIO provides a library of tools that transform data into a simpler formats
+    Scythe provides a library of tools that transform data into a simpler formats
 
-What Does MaterialsIO *Not Do*?
+What Does Scythe *Not Do*?
 -------------------------------
 
-There are several questions that are specifically out-of-scope for MaterialsIO:
+There are several questions that are specifically out-of-scope for Scythe:
 
 1. *How do I get access to files that I want to parse?*
-    MaterialsIO does not solve the data transfer problem
+    Scythe 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
+    Scythe 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
+    The goal of Scythe is to go from opaque to well-documented formats. We recommend
+    implementing separate "adapter" classes to transform Scythe 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
+`"how to use Scythe" documentation <user-guide.html#integrating-materialsio-into-applications>`_
+for more detail on how to integrate Scythe into an application that provides these
 intentionally-missing features.
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 092fc31..cc69dc9 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -1,13 +1,13 @@
-Welcome to MaterialsIO's documentation!
+Welcome to Scythe'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
+Scythe is a library of tools that generate summaries of the data contained in scientific
+data files. The goal of Scythe is to provide a shared resources of these tool to avoid
+duplication of effort between the many emerging scientific databases. Each extractor 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
+Source Code: https://github.com/materials-data-facility/Scythe
 
 
 
@@ -18,8 +18,8 @@ Source Code: https://github.com/materials-data-facility/MaterialsIO
    goals
    user-guide
    contributor-guide
-   parsers
-   api/materials_io
+   extractors
+   api/scythe
 
 
 
diff --git a/docs/source/parsers.rst b/docs/source/parsers.rst
deleted file mode 100644
index 903883d..0000000
--- a/docs/source/parsers.rst
+++ /dev/null
@@ -1,80 +0,0 @@
-Available Parsers
-=================
-
-These pages detail all of the parsers currently available in MaterialsIO.
-
-Quick Summary
-~~~~~~~~~~~~~
-
-The parsers that are configured to work with the stevedore plugin are:
-
-.. list-plugins:: materialsio.parser
-
-
-Detailed Listing
-~~~~~~~~~~~~~~~~
-
-Generic File Parsers
---------------------
-
-Parsers that work for any kind of file
-
-.. automodule:: materials_io.file
-    :members:
-    :exclude-members: implementors, schema, version, group
-
-Image Parsers
--------------
-
-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
-
-Atomistic Data Parsers
-----------------------
-
-Parsers related to data files that encode atom-level structure
-
-.. automodule:: materials_io.crystal_structure
-    :members:
-    :exclude-members: implementors, schema, version, group
-
-.. automodule:: materials_io.ase
-    :members:
-    :noindex:
-    :exclude-members: implementors, schema, version, group
-
-Calculation Parsers
--------------------
-
-Parsers that retrieve results from calculations
-
-.. automodule:: materials_io.dft
-    :members:
-    :exclude-members: implementors, schema, version, group
-
-.. automodule:: materials_io.ase
-    :members:
-    :noindex:
-    :exclude-members: implementors, schema, version, group
-
-Structured Data Files
----------------------
-
-Parsers that read data from structured files
-
-.. automodule:: materials_io.csv
-    :members:
-    :exclude-members: implementors, schema, version, group
diff --git a/docs/source/user-guide.rst b/docs/source/user-guide.rst
index 17927b3..2b737d4 100644
--- a/docs/source/user-guide.rst
+++ b/docs/source/user-guide.rst
@@ -1,62 +1,62 @@
 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 Scythe extractor and discuss the
+full functionality of an extractor.
 
-Installing MaterialsIO (for users)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Installing Scythe (for users)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Installing MaterialsIO should be as easy as a single ``pip`` command. Assuming you have a
+Installing Scythe 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
+    pip install git+https://github.com/materials-data-facility/Scythe.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::
+Should get the basics of Scythe installed. By default however, only a small subset of
+extractors will be installed (this is done so you do not need to install all the dependencies of
+extractors you may never use). To install additional extractors, you can specify "extras" at install time
+using the ``[...]`` syntax for ``pip``. For example, if you want to install all the extractors
+bundled with Scythe (and their dependencies), run::
 
-    pip install "git+https://github.com/materials-data-facility/MaterialsIO.git#egg=materials_io[all]"
+    pip install "git+https://github.com/materials-data-facility/Scythe.git#egg=scythe[all]"
 
-This will pull in many more packages, but also enable as many parsers as possible. Check the list
+This will pull in many more packages, but also enable as many extractors 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
+.. note:: In the *hopefully* near future, Scythe 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
+    `this Github issue <https://github.com/materials-data-facility/Scythe/issues/42>`_ for
+    updates), meaning install should be easier via a simple ``pip install scythe`` or
+    ``pip install scythe[all]``, rather than having to specify the Git URL as in the above
     example
 
-Discovering a Parser
-~~~~~~~~~~~~~~~~~~~~
+Discovering an extractor
+~~~~~~~~~~~~~~~~~~~~~~~~
 
-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::
+Scythe uses `stevedore <https://docs.openstack.org/stevedore/latest/index.html>`_ to manage
+a collection of extractors, and has a utility function for listing available extractors::
 
-    from materials_io.utils.interface import get_available_parsers
-    print(get_available_parsers())
+    from scythe.utils.interface import get_available_extractors
+    print(get_available_extractors())
 
-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
+This snippet will print a dictionary of extractors installed on your system. Both extractors that are
+part of the Scythe 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.file.GenericFileParser`, which is
-available through the ``'generic'`` parser plugin::
+The methods in :mod:`scythe.utils.interface` are useful for most applications. As an
+example, we illustrate the use of :class:`scythe.file.GenericFileExtractor`, which is
+available through the ``'generic'`` extractor plugin::
 
-    from materials_io.utils.interface import execute_parser
-    print(execute_parser('generic', ['pyproject.toml']))
+    from scythe.utils.interface import execute_extractor
+    print(execute_extractor('generic', ['pyproject.toml']))
 
 
-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,
+The above snippet creates the extractor object and runs it on a file named ``pyproject.toml``. Run
+in the root directory of the Scythe, 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:
 
@@ -71,20 +71,20 @@ documentation was written:
         "sha512": "a7eb382c4a3e6cf469656453f9ff2e3c1ac2c02c9c2ba31c3d569a09883e2b2471801c39125dafb7c13bfcaf9cf6afbab92afa4c053c0c93a4c8c59acad1b85b"
     }]
 
-The other pre-built parsing function provides the ability to run all parsers on all files in a
+The other pre-built parsing function provides the ability to run all extractors on all files in a
 directory::
 
-    from materials_io.utils.interface import run_all_parsers
-    gen = run_all_parsers('.')
+    from scythe.utils.interface import run_all_extractors
+    gen = run_all_extractors('.')
     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 ``scythe`` is to employ the ``get_extractor`` operation to access a
+specific extractor, and then use its class interface (described below)::
 
-    from materials_io.utils.interface import get_parser
-    parser = get_parser('generic')
-    gen = parser.parse_directory('.')
+    from scythe.utils.interface import get_extractor
+    extractor = get_extractor('generic')
+    gen = extractor.parse_directory('.')
     for record in gen:
         print(record)
 
@@ -92,27 +92,26 @@ specific 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
+The function interface for Scythe supports using "context" and "adapters" to provide
+additional information Scythe 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``
+extractors support context and this information can be provided via the ``execute_extractor``
 function::
 
-    execute_parser('csv', 'tests/data/test.csv', context={'na_values': ['N/A']})
+    execute_extractor('csv', 'tests/data/test.csv', context={'na_values': ['N/A']})
 
 
-The types of context information used by a parser, if any, is described in the
-`documentation for each parser <parsers.html>`_.
+The types of context information used by an extractor, if any, is described in the
+`documentation for each extractor <extractors.html>`_.
 
-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
+The ``run_all_extractors_on_directory`` function has several options for providing context to the
+extractors. These options include specifying "global context" to be passed to every extractor or
+adapter and ways of limiting the metadata to specific extractors. See
+:meth:`scythe.utils.interface.run_all_extractors_on_directory` for further details on the
 syntax for this command.
 
 .. note::
@@ -123,60 +122,60 @@ 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 extractors provide access to more detailed features of individual extractors. The
+functionality of an extractor is broken into several simple operations.
 
-Initializing a Parser
-+++++++++++++++++++++
+Initializing an extractor
++++++++++++++++++++++++++
 
-The first step to using a Parser is to initialize it. Most parsers do not have any options for
+The first step to using an extractor is to initialize it. Most extractors do not have any options for
 the initializer, so you can create them with::
 
-    parser = Parser()
+    extractor = Extractor()
 
-Some parsers require configuration options that define how the parser runs, such as the location
+Some extractors require configuration options that define how the extractor runs, such as the location
 of a non-Python executable.
 
 Parsing Method
 ++++++++++++++
 
-The main operation for any parser is the data extraction operation: ``parse``.
+The main operation for any extractor 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::
 
-    metadata = parser.parse(['/my/file'])
+    metadata = extractor.parse(['/my/file'])
 
-Some parsers take multiple files that describe the same object (e.g., the input and output files
+Some extractors 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'])
+    metadata = extractor.parse(['/my/file.in', '/my/file.out'])
 
-The `grouping method <#grouping-files>`_ for these parsers provides logic to identify groups of
+The `grouping method <#grouping-files>`_ for these extractors 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 extractors also can use information that is not contained within the file themselves, which can
+be provided to the extractor as a "context"::
 
-    metadata = parser.parse(['/my/file1'], context={'headers': {'temp': 'temperature'}})
+    metadata = extractor.parse(['/my/file1'], context={'headers': {'temp': 'temperature'}})
 
-The documentation for the parser should indicate valid types of context information.
+The documentation for the extractor should indicate valid types of context information.
 
 Grouping Files
 ++++++++++++++
 
-Parsers also provide the ability to quickly find groups of associated files: ``group``.
+Extractors also provide the ability to quickly find groups of associated files: ``group``.
 The ``group`` operation takes path or list of files and, optionally, directories and generates
 a list of files that should be treated together when parsing::
 
-    parser.group(['input.file', 'output.file', 'unrelated']) # -> [('input.file', 'output.file'), ('unrelated',)]
+    extractor.group(['input.file', 'output.file', 'unrelated']) # -> [('input.file', 'output.file'), ('unrelated',)]
 
 Parsing Entire Directories
 ++++++++++++++++++++++++++
 
-``materials_io`` also provides a utility operation to parse all groups of valid files in a directory::
+``scythe`` also provides a utility operation to parse all groups of valid files in a directory::
 
-    metadata = list(parser.parse_directory('.'))
+    metadata = list(extractor.parse_directory('.'))
 
 ``parse_directory`` is a generator function, so we use ``list`` here to turn the output into a list
 format.
@@ -185,23 +184,23 @@ 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
+extractor. ``implementors`` returns the list of people who created an extractor, 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
-+++++++++++++++
+Full Extractor API
+++++++++++++++++++
 
-The full API for the parsers are described as a Python abstract class:
+The full API for the extractors are described as a Python abstract class:
 
-.. autoclass:: materials_io.base.BaseParser
+.. autoclass:: scythe.base.BaseExtractor
     :members:
     :member-order: bysource
 
-Integrating MaterialsIO into Applications
+Integrating Scythe into Applications
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-MaterialsIO is designed to create a documented, JSON-format version of scientific files, but
+Scythe 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.
 
@@ -210,35 +209,35 @@ BaseAdapter
 
 The ``BaseAdapter`` class defines the interface for all adapters.
 
-.. autoclass:: materials_io.adapters.base.BaseAdapter
+.. autoclass:: scythe.adapters.base.BaseAdapter
     :member-order: bysource
     :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,
+Scythe extractors 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
+an extractor are compatible with an adapter. ``scythe`` 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
+``execute_extractor`` 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.
+``run_all_extractors`` function also has arguments (e.g., ``adapter_map``) that associate each
+extractor 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`
+As an example, we will demonstrate an adapter that comes packaged with Scythe:
+:class:`scythe.adapters.base.SerializeAdapter`
 The serialize adapter is registered using ``stevedore`` as the name "serialize". To use it after
-all parsers::
+all extractors::
 
-    from materials_io.utils.interface import run_all_parsers
-    gen = run_all_parsers('.', default_adapter='serialize')
+    from scythe.utils.interface import run_all_extractors
+    gen = run_all_extractors('.', default_adapter='serialize')
 
 Implementing Adapters
 +++++++++++++++++++++
@@ -254,10 +253,10 @@ copy the structure used by the
 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.
+We recommend using the same name for a adapter as the extractor it is designed for so that
+``scythe`` can auto-detect the adapters associated with each extractor.
 
-Examples of Tools Using MaterialsIO
+Examples of Tools Using Scythe
 +++++++++++++++++++++++++++++++++++
 
 Materials Data Facility:
diff --git a/materials_io/__init__.py b/materials_io/__init__.py
deleted file mode 100644
index d91b81c..0000000
--- a/materials_io/__init__.py
+++ /dev/null
@@ -1,1 +0,0 @@
-from materials_io.version import __version__   # noqa: F401
diff --git a/materials_io/utils/interface.py b/materials_io/utils/interface.py
deleted file mode 100644
index 12fb5a0..0000000
--- a/materials_io/utils/interface.py
+++ /dev/null
@@ -1,323 +0,0 @@
-"""Utilities for working with parsers from other applications"""
-
-from stevedore.extension import ExtensionManager
-from stevedore.driver import DriverManager
-from typing import Iterator, Union, Dict, List
-from collections import namedtuple
-from copy import deepcopy
-
-from materials_io.adapters.base import BaseAdapter
-from materials_io.base import BaseParser
-import logging
-
-logger = logging.getLogger(__name__)
-
-ParseResult = namedtuple('ParseResult', ['group', 'parser', 'metadata'])
-
-
-def _output_plugin_info(mgr: ExtensionManager) -> dict:
-    """Gets information about all plugins attached to a particular manager
-
-    Args:
-        mgr (ExtensionManager): Plugin manager
-    Returns:
-        (dict): Dictionary where keys are plugin ids and values are descriptions
-    """
-
-    output = {}
-    for name, ext in mgr.items():
-        plugin = ext.plugin()
-        output[name] = {
-            'description': plugin.__doc__.split("\n")[0],
-            'version': plugin.version(),
-            'class': ext.entry_point_target
-        }
-    return output
-
-
-def get_available_parsers():
-    """Get information about the available parsers
-
-    Returns:
-        [dict]: Descriptions of available parsers
-    """
-    mgr = ExtensionManager(
-        namespace='materialsio.parser',
-    )
-
-    # Get information about each parser
-    return _output_plugin_info(mgr)
-
-
-def get_available_adapters() -> dict:
-    """Get information on all available adapters
-
-    Returns:
-        (dict) Where keys are adapter names and values are descriptions
-    """
-
-    return _output_plugin_info(ExtensionManager(namespace='materialsio.adapter'))
-
-
-def _get_adapter_map(adapter_map: str, parsers: list) -> dict:
-    """ Helper function to generate 'adapter map'
-            (so different run_all_parsers functions can call it)
-
-    Adapter map is a list of parsers and names of the appropriate adapters
-    to use to format their output.
-
-    Args:
-        adapter_map (str): string argument for adapters.
-            - 'match' means just find adapters with same names as corresponding parsers.
-        parsers ([str]): list of parsers
-    Returns:
-        (dict) where keys are adapter names parser/adapter names and values are adapter objects.
-        """
-    if adapter_map is None:
-        adapter_map = {}
-    elif adapter_map == 'match':
-        adapters = get_available_adapters()
-        adapter_map = dict((x, x) for x in parsers if x in adapters)
-    elif not isinstance(adapter_map, dict):
-        raise ValueError('Adapter map must be a dict, None, or `matching`')
-
-    # Give it to the user
-    return adapter_map
-
-
-def _get_parser_and_adapter_contexts(name, global_context, parser_context, adapter_context):
-    """
-    Helper function to update the helper and adapter contexts and the 'name'
-        of a parser/adapter pair
-    Args:
-        name (str): adapter/parser name.
-        global_context (dict): Context of the files, used for every parser and adapter
-        adapter_context (dict): Context used for adapters. Key is the name of the adapter,
-            value is the context.  The key ``@all`` is used to for context used for every adapter
-        parser_context (dict): Context used for adapters. Key is the name of the parser,
-            value is the context. The key ``@all`` is used to for context used for every parser
-    Returns:
-         (dict, dict): parser_context, my_adapter context tuple
-    """
-
-    # Get the context information for the parser and adapter
-    my_parser_context = deepcopy(global_context)
-    my_parser_context.update(parser_context.get('@all', {}))
-    my_parser_context.update(parser_context.get(name, {}))
-
-    my_adapter_context = deepcopy(global_context)
-    my_adapter_context.update(adapter_context.get('@all', {}))
-    my_adapter_context.update(adapter_context.get(name, {}))
-
-    return my_parser_context, my_adapter_context
-
-
-def _get_parser_list(include_parsers: list, exclude_parsers: list) -> list:
-    """ Helper function to get a list of parsers given lists of parsers to include/exclude
-
-    Args:
-        include_parsers ([str]): Predefined list of parsers to run. Only these will be used.
-            Mutually exclusive with `exclude_parsers`.
-        exclude_parsers ([str]): List of parsers to exclude.
-            Mutually exclusive with `include_parsers`.
-    Returns:
-        parsers (list): list of all applicable parsers.
-
-    """
-
-    parsers = get_available_parsers()
-    if include_parsers is not None and exclude_parsers is not None:
-        raise ValueError('Including and excluding parsers are mutually exclusive')
-    elif include_parsers is not None:
-        missing_parsers = set(include_parsers).difference(parsers.keys())
-        if len(missing_parsers) > 0:
-            raise ValueError('Some parsers are missing: ' + ' '.join(missing_parsers))
-        parsers = include_parsers
-    elif exclude_parsers is not None:
-        parsers = list(set(parsers.keys()).difference(exclude_parsers))
-
-    return parsers
-
-
-def get_parser(name: str) -> BaseParser:
-    """Load a parser object
-
-    Args:
-        name (str): Name of parser
-    Returns:
-        (BaseParser) Requested parser
-    """
-    return DriverManager(
-        namespace='materialsio.parser',
-        name=name,
-        invoke_on_load=True
-    ).driver
-
-
-def get_adapter(name: str) -> BaseAdapter:
-    """Load an adapter
-
-    Args:
-        name (str): Name of adapter
-    Returns:
-        (BaseAdapter) Requested adapter
-    """
-
-    # Load the adapter
-    mgr = DriverManager(
-        namespace='materialsio.adapter',
-        name=name,
-        invoke_on_load=True
-    )
-
-    # Give it to the user
-    return mgr.driver
-
-
-def execute_parser(name, group, context=None,
-                   adapter=None):
-    """Invoke a parser on a certain group of data
-    Args:
-        name (str): Name of the parser
-        group ([str]): Paths to group of files to be parsed
-        context (dict): Context of the files, used in adapter and parser
-        adapter (str): Name of adapter to use to transform metadata
-    Returns:
-        ([dict]): Metadata generated by the parser
-    """
-    metadata = get_parser(name).parse(group, context)
-    if adapter is not None:
-        adapter = get_adapter(adapter)
-        return adapter.transform(metadata, context=context)
-    return metadata
-
-
-def run_all_parsers_on_directory(directory: str, global_context=None,
-                                 adapter_context: Union[None, dict] = None,
-                                 parser_context: Union[None, dict] = None,
-                                 include_parsers: Union[None, List[str]] = None,
-                                 exclude_parsers: Union[None, List] = None,
-                                 adapter_map: Union[None, str, Dict[str, str]] = None,
-                                 default_adapter: Union[None, str] = None) \
-                                                    -> Iterator[ParseResult]:
-    """Run all known files on a directory of files
-
-    Args:
-        directory (str): Path to directory to be parsed
-        global_context (dict): Context of the files, used for every parser and adapter
-        adapter_context (dict): Context used for adapters. Key is the name of the adapter,
-            value is the context.  The key ``@all`` is used to for context used for every adapter
-        parser_context (dict): Context used for adapters. Key is the name of the parser,
-            value is the context. The key ``@all`` is used to for context used for every parser
-        include_parsers ([str]): Predefined list of parsers to run. Only these will be used.
-            Mutually exclusive with `exclude_parsers`.
-        exclude_parsers ([str]): List of parsers to exclude.
-            Mutually exclusive with `include_parsers`.
-        adapter_map (str, dict): Map of parser name to the desired adapter.
-            Use 'match' to find adapters with the same names
-        default_adapter (str): Adapter to use if no other adapter is defined
-    Yields
-        ((str), str, dict) Tuple of (1) group of files, (2) name of parser, (3) metadata
-    """
-
-    # Load in default arguments
-    if global_context is None:
-        global_context = dict()
-    if adapter_context is None:
-        adapter_context = dict()
-    if parser_context is None:
-        parser_context = dict()
-
-    # Get the list of parsers
-    parsers = _get_parser_list(include_parsers, exclude_parsers)
-
-    # Make the adapter map
-    adapter_map = _get_adapter_map(adapter_map=adapter_map, parsers=parsers)
-
-    # Get the list of known parsers
-    for name in parsers:
-        # Get the parser and adapter
-        parser = get_parser(name)
-        adapter_name = adapter_map.get(name, default_adapter)
-        if adapter_name is not None:
-            adapter = get_adapter(adapter_name)
-        else:
-            adapter = None
-
-        my_parser_context, my_adapter_context = _get_parser_and_adapter_contexts(name,
-                                                                                 global_context,
-                                                                                 parser_context,
-                                                                                 adapter_context)
-
-        for group, metadata in parser.parse_directory(directory, context=my_parser_context):
-            # Run the adapter, if defined
-            if adapter is not None:
-                try:
-                    metadata = adapter.transform(metadata, my_adapter_context)
-                except Exception as e:
-                    logger.warning(f'Adapter for {parser} failed with caught exception: {e}')
-                    continue
-                if metadata is None:
-                    continue
-
-            yield ParseResult(group, name, metadata)
-
-
-def run_all_parsers_on_group(group,
-                             adapter_map=None,
-                             global_context=None,
-                             adapter_context: Union[None, dict] = None,
-                             parser_context: Union[None, dict] = None,
-                             include_parsers: Union[None, List[str]] = None,
-                             exclude_parsers: Union[None, List] = None,
-                             default_adapter: Union[None, str] = None):
-    """
-    Parse metadata from a file-group and adapt its metadata per a user-supplied adapter_map.
-
-    This function is effectively a wrapper to execute_parser() that enables us to output metadata
-    in the same format as run_all_parsers_on_directory(), but just on a single file group.
-
-    Args:
-        group ([str]): Paths to group of files to be parsed
-        global_context (dict): Context of the files, used for every parser and adapter
-        adapter_context (dict): Context used for adapters. Key is the name of the adapter,
-            value is the context.  The key ``@all`` is used to for context used for every adapter
-        parser_context (dict): Context used for adapters. Key is the name of the parser,
-            value is the context. The key ``@all`` is used to for context used for every parser
-        include_parsers ([str]): Predefined list of parsers to run. Only these will be used.
-            Mutually exclusive with `exclude_parsers`.
-        exclude_parsers ([str]): List of parsers to exclude.
-            Mutually exclusive with `include_parsers`.
-        adapter_map (str, dict): Map of parser name to the desired adapter.
-            Use 'match' to find adapters with the same names:
-        default_adapter:
-    Yields:
-        ParseResult(group, name, metadata)
-    """
-
-    # Load in default arguments
-    if global_context is None:
-        global_context = dict()
-    if adapter_context is None:
-        adapter_context = dict()
-    if parser_context is None:
-        parser_context = dict()
-
-    # Get the list of parsers
-    parsers = _get_parser_list(include_parsers, exclude_parsers)
-
-    # Make the adapter map
-    adapter_map = _get_adapter_map(adapter_map=adapter_map, parsers=parsers)
-
-    for name in parsers:
-        # Get the parser and adapter
-        adapter_name = adapter_map.get(name, default_adapter)
-
-        my_parser_context, my_adapter_context = _get_parser_and_adapter_contexts(name,
-                                                                                 global_context,
-                                                                                 parser_context,
-                                                                                 adapter_context)
-
-        metadata = execute_parser(name, group, context=my_parser_context, adapter=adapter_name)
-
-        yield ParseResult(group, name, metadata)
diff --git a/pyproject.toml b/pyproject.toml
index 669c4e8..839248f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
-name = "materials_io"
-version = "0.1.1"
+name = "scythe"
+version = "0.1.0"
 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"
@@ -57,32 +57,32 @@ all = ['ase',
 
 [tool.poetry.plugins]
 
-[tool.poetry.plugins."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"
+[tool.poetry.plugins."scythe.extractor"]
+"ase" = "scythe.ase:ASEExtractor"
+"crystal" = "scythe.crystal_structure:CrystalStructureExtractor"
+"csv" = "scythe.csv:CSVExtractor"
+"dft" = "scythe.dft:DFTExtractor"
+"em" = "scythe.electron_microscopy:ElectronMicroscopyExtractor"
+"filename" = "scythe.filename:FilenameExtractor"
+"generic" = "scythe.file:GenericFileExtractor"
+"image" = "scythe.image:ImageExtractor"
+"json" = "scythe.json:JSONExtractor"
+"noop" = "scythe.testing:NOOPExtractor"
+"tdb" = "scythe.tdb:TDBExtractor"
+"xml" = "scythe.xml:XMLExtractor"
+"yaml" = "scythe.yaml:YAMLExtractor"
 
-[tool.poetry.plugins."materialsio.adapter"]
-"noop" = "materials_io.adapters.base:NOOPAdapter"
-"serialize" = "materials_io.adapters.base:SerializeAdapter"
-"greedy_serialize" = "materials_io.adapters.base:GreedySerializeAdapter"
+[tool.poetry.plugins."scythe.adapter"]
+"noop" = "scythe.adapters.base:NOOPAdapter"
+"serialize" = "scythe.adapters.base:SerializeAdapter"
+"greedy_serialize" = "scythe.adapters.base:GreedySerializeAdapter"
 
 [build-system]
 requires = ["poetry-core>=1.0.0"]
 build-backend = "poetry.core.masonry.api"
 
 [tool.pytest.ini_options]
-addopts = "--ignore=.venv --ignore=.tox --cov=materials_io --cov-report html --cov-report term-missing --cov-report=xml"
+addopts = "--ignore=.venv --ignore=.tox --cov=scythe --cov-report html --cov-report term-missing --cov-report=xml"
 testpaths = ['tests']
 
 [tool.coverage.run]
@@ -119,4 +119,4 @@ 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/scythe/__init__.py b/scythe/__init__.py
new file mode 100644
index 0000000..54ed548
--- /dev/null
+++ b/scythe/__init__.py
@@ -0,0 +1,1 @@
+from scythe.version import __version__   # noqa: F401
diff --git a/materials_io/adapters/__init__.py b/scythe/adapters/__init__.py
similarity index 100%
rename from materials_io/adapters/__init__.py
rename to scythe/adapters/__init__.py
diff --git a/materials_io/adapters/base.py b/scythe/adapters/base.py
similarity index 94%
rename from materials_io/adapters/base.py
rename to scythe/adapters/base.py
index 085920a..06aaeb2 100644
--- a/materials_io/adapters/base.py
+++ b/scythe/adapters/base.py
@@ -6,7 +6,7 @@
 
 import numpy as np
 
-from materials_io.base import BaseParser
+from scythe.base import BaseExtractor
 
 
 class BaseAdapter:
@@ -24,11 +24,11 @@ def transform(self, metadata: dict, context: Union[None, dict] = None) -> Any:
             ``None`` corresponding
         """
 
-    def check_compatibility(self, parser: BaseParser) -> bool:
+    def check_compatibility(self, parser: BaseExtractor) -> bool:
         """Evaluate whether an adapter is compatible with a certain parser
 
         Args:
-            parser (BaseParser): Parser to evaluate
+            parser (BaseExtractor): Parser to evaluate
         Returns:
             (bool) Whether this parser is compatible
         """
diff --git a/materials_io/ase.py b/scythe/ase.py
similarity index 82%
rename from materials_io/ase.py
rename to scythe/ase.py
index 3b1a982..657ad90 100644
--- a/materials_io/ase.py
+++ b/scythe/ase.py
@@ -5,7 +5,7 @@
 from io import StringIO
 import numpy as np
 
-from materials_io.base import BaseSingleFileParser
+from scythe.base import BaseSingleFileExtractor
 
 
 def object_hook(dct):
@@ -36,17 +36,15 @@ def object_hook(dct):
     return dct
 
 
-class AseParser(BaseSingleFileParser):
+class ASEExtractor(BaseSingleFileExtractor):
     """Parse information from atomistic simulation input files using ASE.
 
-       ASE can read many file types. These can be found at
-       https://wiki.fysik.dtu.dk/ase/ase/io/io.html
+    ASE can read many file types. These can be found at https://wiki.fysik.dtu.dk/ase/ase/io/io.html
 
-       Metadata are generated as ASE JSON DB format
-       https://wiki.fysik.dtu.dk/ase/ase/db/db.html
+    Metadata are generated as ASE JSON DB format: https://wiki.fysik.dtu.dk/ase/ase/db/db.html
     """
 
-    def _parse_file(self, path, context=None):
+    def _extract_file(self, path, context=None):
         # Attempt to read the file with ASE
         # To return ASE JSON DB requires writing to file.
         # Here we use StringIO instead of a file on disk.
diff --git a/materials_io/base.py b/scythe/base.py
similarity index 68%
rename from materials_io/base.py
rename to scythe/base.py
index 9a827e5..7a70eaa 100644
--- a/materials_io/base.py
+++ b/scythe/base.py
@@ -1,33 +1,33 @@
-from typing import List, Iterator, Tuple, Iterable, Union
+from typing import List, Iterator, Tuple, Iterable, Union, Sequence
 from abc import ABC, abstractmethod
 import logging
 import os
 
-from materials_io.utils.grouping import preprocess_paths
+from scythe.utils.grouping import preprocess_paths
 
 logger = logging.getLogger(__name__)
 
 
-class BaseParser(ABC):
-    """Abstract base class for a file parser
+class BaseExtractor(ABC):
+    """Abstract base class for a metadata extractor
 
-    This class defines the interface for all parsers in MaterialsIO. Each new parser must
+    This class defines the interface for all extractors in Scythe. Each new extractor 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.
+    are papers that should be cited if the extractor is used as part of a scientific publication.
 
-    See the `MaterialsIO Contributor Guide <contributor-guide.html>`_ for further details.
+    See the `Scythe Contributor Guide <contributor-guide.html>`_ for further details.
     """
 
     def identify_files(self, path: str, context: dict = None) -> \
             Iterator[Tuple[str]]:
-        """Identify all groups of files likely to be compatible with this parser
+        """Identify all groups of files likely to be compatible with this extractor
 
         Uses the :meth:`group` function to determine groups of files that should be parsed together.
 
         Args:
-            path (str): Root of directory to parser
+            path (str): Root of directory to group together
             context (dict): Context about the files
         Yields:
             ([str]) Groups of eligible files
@@ -43,14 +43,14 @@ def identify_files(self, path: str, context: dict = None) -> \
             for group in self.group(files, dirs, context):
                 yield group
 
-    def parse_directory(self, path: str, context: dict = None) -> \
+    def extract_directory(self, path: str, context: dict = None) -> \
             Iterator[Tuple[Tuple[str], dict]]:
-        """Run a parser on all appropriate files in a directory
+        """Run extractor on all appropriate files in a directory
 
         Skips files that throw exceptions while parsing
 
         Args:
-            path (str): Root of directory to parser
+            path (str): Root of directory to extract metadata from
             context (dict): Context about the files
         Yields:
             ([str], dict): Tuple of the group identity and the metadata unit
@@ -58,18 +58,18 @@ def parse_directory(self, path: str, context: dict = None) -> \
 
         for group in self.identify_files(path, context):
             try:
-                metadata_unit = self.parse(group, context)
+                metadata_unit = self.extract(group, context)
             except Exception:
                 continue
             else:
-                yield (group, metadata_unit)
+                yield group, metadata_unit
 
     @abstractmethod
-    def parse(self, group: Iterable[str], context: dict = None) -> dict:
+    def extract(self, group: Iterable[str], context: dict = None) -> dict:
         """Extract metadata from a group of files
 
-        A group of files is a set of 1 or more files that describe the same object, and will be
-        be used together to create s single summary record.
+        A group of files is a set of 1 or more files that describe the same object
+        and will be used together to create a single metadata record.
 
         Arguments:
             group ([str]):  A list of one or more files that should be parsed together
@@ -85,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 extractor,
+        which may include many false positives.
 
         Args:
             files (str or [str]): List of files to consider grouping
@@ -101,10 +101,10 @@ def group(self, files: Union[str, List[str]], directories: List[str] = None,
 
         # Default: Every file is in its own group
         for f in files:
-            yield (f,)
+            yield f,
 
     def citations(self) -> List[str]:
-        """Citation(s) and reference(s) for this parser
+        """Citation(s) and reference(s) for this extractor
 
         Returns:
             ([str]): each element should be a string citation in BibTeX format
@@ -113,9 +113,9 @@ def citations(self) -> List[str]:
 
     @abstractmethod
     def implementors(self) -> List[str]:
-        """List of implementors of the parser
+        """List of implementors of the extractor
 
-        These people are the points-of-contact for addressing errors or modifying the parser
+        These people are the points-of-contact for addressing errors or modifying the extractor
 
         Returns:
             ([str]): List of implementors in the form "FirstName LastName <email@provider>"
@@ -123,27 +123,27 @@ def implementors(self) -> List[str]:
 
     @abstractmethod
     def version(self) -> str:
-        """Return the version of the parser
+        """Return the version of the extractor
 
         Returns:
-            (str): Version of the parser
+            (str): Version of the extractor
         """
 
     @property
     def schema(self) -> dict:
-        """Schema for the output of the parser"""
+        """Schema for the output of the extractor"""
         return {
             "$schema": "http://json-schema.org/schema#"
         }
 
 
-class BaseSingleFileParser(BaseParser):
-    """Base class for parsers that only ever considers a single file at a time
+class BaseSingleFileExtractor(BaseExtractor):
+    """Base class for extractors that only ever considers a single file at a time
 
     Instead of implementing :meth:`parse`, implement :meth:`_parse_file`"""
 
     @abstractmethod
-    def _parse_file(self, path: str, context=None):
+    def _extract_file(self, path: str, context=None):
         """Generate the metadata for a single file
 
         Args:
@@ -153,13 +153,13 @@ def _parse_file(self, path: str, context=None):
             (dict): Metadata for the file
         """
 
-    def parse(self, group: Union[str, Iterable[str]], context=None):
+    def extract(self, group: Union[str, Sequence[str]], context=None):
         # Error catching: allows for single files to passed not as list
         if isinstance(group, str):
-            return self._parse_file(group, context)
+            return self._extract_file(group, context)
 
         # Assumes that the group must have exactly one file
         if len(group) > 1:
-            raise ValueError('Parser only takes a single file at a time')
+            raise ValueError('Extractor only takes a single file at a time')
 
-        return self._parse_file(group[0], context)
+        return self._extract_file(group[0], context)
diff --git a/materials_io/crystal_structure.py b/scythe/crystal_structure.py
similarity index 85%
rename from materials_io/crystal_structure.py
rename to scythe/crystal_structure.py
index 799b7c0..09f5029 100644
--- a/materials_io/crystal_structure.py
+++ b/scythe/crystal_structure.py
@@ -2,13 +2,15 @@
 from pymatgen.core import Structure
 from ase.io import read
 
-from materials_io.base import BaseSingleFileParser
+from scythe.base import BaseSingleFileExtractor
 
 
-class CrystalStructureParser(BaseSingleFileParser):
-    """Parse information about a crystal structure"""
+class CrystalStructureExtractor(BaseSingleFileExtractor):
+    """Extract information about a crystal structure from many types of files.
 
-    def _parse_file(self, path, context=None):
+     Uses either ASE or Pymatgen on the back end"""
+
+    def _extract_file(self, path, context=None):
         material = {}
         crystal_structure = {}
         # Attempt to read the file
diff --git a/materials_io/csv.py b/scythe/csv.py
similarity index 87%
rename from materials_io/csv.py
rename to scythe/csv.py
index 189ee28..f47b426 100644
--- a/materials_io/csv.py
+++ b/scythe/csv.py
@@ -1,4 +1,4 @@
-from materials_io.base import BaseSingleFileParser
+from scythe.base import BaseSingleFileExtractor
 from tableschema.exceptions import CastError
 from tableschema import Table
 from typing import List
@@ -7,14 +7,13 @@
 logger = logging.getLogger(__name__)
 
 
-class CSVParser(BaseSingleFileParser):
-    """Reads comma-separated value (CSV) files
+class CSVExtractor(BaseSingleFileExtractor):
+    """Describe the contents of a comma-separated value (CSV) file
 
     The context dictionary for the CSV parser includes several fields:
         - ``schema``: Dictionary defining the schema for this dataset, following that of
           FrictionlessIO
         - ``na_values``: Any values that should be interpreted as missing
-
     """
 
     def __init__(self, return_records=True, **kwargs):
@@ -22,13 +21,12 @@ def __init__(self, return_records=True, **kwargs):
         Args:
              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
+            All kwargs as passed to `TableSchema's infer <https://github.com/frictionlessdata/tableschema-py#infer>`_ method
         """
         self.return_records = return_records
         self.infer_kwargs = kwargs
 
-    def _parse_file(self, path: str, context=None):
+    def _extract_file(self, path: str, context=None):
         # Set the default value
         if context is None:
             context = dict()
diff --git a/materials_io/dft.py b/scythe/dft.py
similarity index 84%
rename from materials_io/dft.py
rename to scythe/dft.py
index 11638b4..1267a3f 100644
--- a/materials_io/dft.py
+++ b/scythe/dft.py
@@ -1,6 +1,6 @@
 from typing import Union, Iterable, Tuple, List
-from materials_io.utils.grouping import preprocess_paths, group_by_postfix
-from materials_io.base import BaseParser
+from scythe.utils.grouping import preprocess_paths, group_by_postfix
+from scythe.base import BaseExtractor
 from dfttopif import files_to_pif
 from operator import itemgetter
 import itertools
@@ -12,15 +12,14 @@
                     "kpoints", "doscar", "poscar", "contcar", "vasp_run.xml", "xdatcar"]
 
 
-class DFTParser(BaseParser):
-    """Extract data from Density Functional Theory calculation results
+class DFTExtractor(BaseExtractor):
+    """Extract metadata from Density Functional Theory calculation results
 
-    Uses the `dfttopif <https://github.com/CitrineInformatics/pif-dft>`_ parser to extract
-    metadata from each file
+    Uses the `dfttopif <https://github.com/CitrineInformatics/pif-dft>`_ parser to extract metadata from each file
     """
 
     def __init__(self, quality_report=False):
-        """Initialize a featurizer
+        """Initialize the extractor
 
         Args:
             quality_report (bool): Whether to generate a quality report
@@ -32,7 +31,7 @@ def group(self, files: Union[str, List[str]], directories: List[str] = None,
         # Convert paths into standardized form
         files = set(preprocess_paths(files))
 
-        # Find all of the files, and attempt to group them
+        # Find all files, and attempt to group them
         for group in self._group_vasp(files):  # VASP grouping logic
             # Remove all files matched as VASP from the matchable files
             files.difference_update(group)
@@ -72,11 +71,11 @@ def _group_pwscf(self, files: Iterable[str]) -> Iterable[Tuple[str, ...]]:
         for k, group in itertools.groupby(sorted(file_and_dir), key=itemgetter(0)):
             yield [x[1] for x in group]
 
-    def parse(self, group: Iterable[str], context: dict = None):
+    def extract(self, group: Iterable[str], context: dict = None):
         return files_to_pif(group, quality_report=self.quality_report).as_dictionary()
 
     def implementors(self):
-        return ['Logan Ward']
+        return ['Logan Ward <lward@anl.gov>']
 
     def version(self):
         return '0.0.1'
diff --git a/materials_io/electron_microscopy.py b/scythe/electron_microscopy.py
similarity index 99%
rename from materials_io/electron_microscopy.py
rename to scythe/electron_microscopy.py
index 6501f94..438329e 100644
--- a/materials_io/electron_microscopy.py
+++ b/scythe/electron_microscopy.py
@@ -7,17 +7,17 @@
 from hyperspy.io import load as hs_load
 from traits.trait_base import Undefined
 
-from materials_io.base import BaseSingleFileParser
-from materials_io.utils import get_nested_dict_value_by_path as get_val
-from materials_io.utils import \
+from scythe.base import BaseSingleFileExtractor
+from scythe.utils import get_nested_dict_value_by_path as get_val
+from scythe.utils import \
     map_dict_values, MappingElements, standardize_unit
-from materials_io.utils import set_nested_dict_value_with_units as set_val_units
+from scythe.utils import set_nested_dict_value_with_units as set_val_units
 
 logger = logging.getLogger(__name__)
 
 
-class ElectronMicroscopyParser(BaseSingleFileParser):
-    """Parse metadata specific to electron microscopy.
+class ElectronMicroscopyExtractor(BaseSingleFileExtractor):
+    """Extract 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
@@ -32,7 +32,7 @@ class ElectronMicroscopyParser(BaseSingleFileParser):
     ``schemas/electron_microscopy.json`` file.
     """
 
-    def _parse_file(self, file_path: str, context: Dict = None) -> Dict:
+    def _extract_file(self, file_path: str, context: Dict = None) -> Dict:
         self.em = {}
         self.inst_data = None
 
diff --git a/materials_io/file.py b/scythe/file.py
similarity index 90%
rename from materials_io/file.py
rename to scythe/file.py
index cb314c3..d41c0ee 100644
--- a/materials_io/file.py
+++ b/scythe/file.py
@@ -1,4 +1,4 @@
-from materials_io.base import BaseSingleFileParser
+from scythe.base import BaseSingleFileExtractor
 from hashlib import sha512
 from warnings import warn
 import json
@@ -17,8 +17,8 @@
     magic = None
 
 
-class GenericFileParser(BaseSingleFileParser):
-    """Gathers basic file information"""
+class GenericFileExtractor(BaseSingleFileExtractor):
+    """Gather basic file information"""
 
     def __init__(self, store_path=True, compute_hash=True):
         """
@@ -30,7 +30,7 @@ def __init__(self, store_path=True, compute_hash=True):
         self.store_path = store_path
         self.compute_hash = compute_hash
 
-    def _parse_file(self, path, context=None):
+    def _extract_file(self, path, context=None):
         output = {
             "length": os.path.getsize(path),
             "filename": os.path.basename(path),
diff --git a/materials_io/filename.py b/scythe/filename.py
similarity index 90%
rename from materials_io/filename.py
rename to scythe/filename.py
index c9abfe5..f5498b3 100644
--- a/materials_io/filename.py
+++ b/scythe/filename.py
@@ -3,13 +3,13 @@
 
 from mdf_toolbox import flatten_json
 
-from materials_io.base import BaseSingleFileParser
+from scythe.base import BaseSingleFileExtractor
 
 
-class FilenameExtractor(BaseSingleFileParser):
+class FilenameExtractor(BaseSingleFileExtractor):
     """Extracts metadata in a filename, according to user-supplied patterns."""
 
-    def _parse_file(self, path, context=None):
+    def _extract_file(self, path, context=None):
         """Context used:
             mapping (dict): Required. The mapping of desired_fields: regex_pattern,
                     using dot notation. For example:
diff --git a/materials_io/image.py b/scythe/image.py
similarity index 80%
rename from materials_io/image.py
rename to scythe/image.py
index 8eb1474..bd02903 100644
--- a/materials_io/image.py
+++ b/scythe/image.py
@@ -1,12 +1,12 @@
 from PIL import Image
 
-from materials_io.base import BaseSingleFileParser
+from scythe.base import BaseSingleFileExtractor
 
 
-class ImageParser(BaseSingleFileParser):
+class ImageExtractor(BaseSingleFileExtractor):
     """Retrieves basic information about an image"""
 
-    def _parse_file(self, file_path, context=None):
+    def _extract_file(self, file_path, context=None):
         im = Image.open(file_path)
         return {
             "image": {
diff --git a/materials_io/json.py b/scythe/json.py
similarity index 86%
rename from materials_io/json.py
rename to scythe/json.py
index ea63dab..661f16a 100644
--- a/materials_io/json.py
+++ b/scythe/json.py
@@ -2,13 +2,13 @@
 
 from mdf_toolbox import translate_json
 
-from materials_io.base import BaseSingleFileParser
+from scythe.base import BaseSingleFileExtractor
 
 
-class JSONExtractor(BaseSingleFileParser):
+class JSONExtractor(BaseSingleFileExtractor):
     """Extracts fields in JSON into a user-defined new schema."""
 
-    def _parse_file(self, path, context=None):
+    def _extract_file(self, path, context=None):
         """Context used:
             mapping (dict): Required. The mapping of desired_fields: existing_fields,
                     using dot notation. For example:
diff --git a/materials_io/schemas/electron_microscopy.json b/scythe/schemas/electron_microscopy.json
similarity index 100%
rename from materials_io/schemas/electron_microscopy.json
rename to scythe/schemas/electron_microscopy.json
diff --git a/materials_io/schemas/file.json b/scythe/schemas/file.json
similarity index 93%
rename from materials_io/schemas/file.json
rename to scythe/schemas/file.json
index 5b20378..2f1e32b 100644
--- a/materials_io/schemas/file.json
+++ b/scythe/schemas/file.json
@@ -1,6 +1,6 @@
 {
   "$schema": "http://json-schema.org/schema#",
-  "description": "Output from the MaterialsIO File Parser",
+  "description": "Output from the Scythe File Parser",
   "type": "object",
   "properties": {
     "mime_type": {
diff --git a/materials_io/tdb.py b/scythe/tdb.py
similarity index 78%
rename from materials_io/tdb.py
rename to scythe/tdb.py
index 56d83a6..a025076 100644
--- a/materials_io/tdb.py
+++ b/scythe/tdb.py
@@ -4,13 +4,16 @@
 os.environ["MPLBACKEND"] = "agg"
 import pycalphad  # noqa: E402
 
-from materials_io.base import BaseSingleFileParser  # noqa: E402
+from scythe.base import BaseSingleFileExtractor  # noqa: E402
 
 
-class TDBExtractor(BaseSingleFileParser):
-    """Extract information from a TDB file."""
+class TDBExtractor(BaseSingleFileExtractor):
+    """Extract metadata from a Thermodynamic Database (TBD) file.
 
-    def _parse_file(self, path, context=None):
+    Built atop `PyCALPHAD <https://pycalphad.org/docs/latest/>`_.
+    """
+
+    def _extract_file(self, path, context=None):
         material = {}
         calphad = {}
         # Attempt to read the file
diff --git a/materials_io/utils/__init__.py b/scythe/utils/__init__.py
similarity index 98%
rename from materials_io/utils/__init__.py
rename to scythe/utils/__init__.py
index 35a3643..e48a50c 100644
--- a/materials_io/utils/__init__.py
+++ b/scythe/utils/__init__.py
@@ -81,7 +81,7 @@ def set_nested_dict_value_with_units(nest_dict: Dict, path: Tuple,
                                      value: Any, units: Optional[str] = None,
                                      override: bool = False,
                                      fn: Optional[Callable] = None):
-    """Same as :func:`~materials_io.utils.set_nested_dict_value`, but sets the
+    """Same as :func:`~scythe.utils.set_nested_dict_value`, but sets the
     value in the format of a dictionary with keys ``'value'`` and ``'units'``
     according to the specified units. If ``fn`` is supplied, it will be
     applied to the value prior to setting it.
diff --git a/materials_io/utils/grouping.py b/scythe/utils/grouping.py
similarity index 97%
rename from materials_io/utils/grouping.py
rename to scythe/utils/grouping.py
index 1038783..ce93e1c 100644
--- a/materials_io/utils/grouping.py
+++ b/scythe/utils/grouping.py
@@ -37,7 +37,7 @@ def group_by_postfix(files: Iterable[str], vocabulary: List[str]) -> Iterable[Tu
     If a user provides a vocabulary of ['A', 'B', 'C'], the parser will
     return groups (A.1, B.1), (A.2, B.2), and (C.1)
 
-    See :class:`materials_io.dft.DFTParser` for an example usage.
+    See :class:`scythe.dft.DFTParser` for an example usage.
 
     Args:
         files ([str]): List of files to be grouped
diff --git a/scythe/utils/interface.py b/scythe/utils/interface.py
new file mode 100644
index 0000000..2a1517b
--- /dev/null
+++ b/scythe/utils/interface.py
@@ -0,0 +1,321 @@
+"""Utilities for working with extractors from other applications"""
+
+from stevedore.extension import ExtensionManager
+from stevedore.driver import DriverManager
+from typing import Iterator, Union, Dict, List
+from collections import namedtuple
+from copy import deepcopy
+
+from scythe.adapters.base import BaseAdapter
+from scythe.base import BaseExtractor
+import logging
+
+logger = logging.getLogger(__name__)
+
+ExtractResult = namedtuple('ExtractResult', ['group', 'extractor', 'metadata'])
+
+
+def _output_plugin_info(mgr: ExtensionManager) -> dict:
+    """Gets information about all plugins attached to a particular manager
+
+    Args:
+        mgr (ExtensionManager): Plugin manager
+    Returns:
+        (dict): Dictionary where keys are plugin ids and values are descriptions
+    """
+
+    output = {}
+    for name, ext in mgr.items():
+        plugin = ext.plugin()
+        output[name] = {
+            'description': plugin.__doc__.split("\n")[0],
+            'version': plugin.version(),
+            'class': ext.entry_point_target
+        }
+    return output
+
+
+def get_available_extractors():
+    """Get information about the available extractors
+
+    Returns:
+        [dict]: Descriptions of available extractors
+    """
+    mgr = ExtensionManager(
+        namespace='scythe.extractor',
+    )
+
+    # Get information about each extractor
+    return _output_plugin_info(mgr)
+
+
+def get_available_adapters() -> dict:
+    """Get information on all available adapters
+
+    Returns:
+        (dict) Where keys are adapter names and values are descriptions
+    """
+
+    return _output_plugin_info(ExtensionManager(namespace='scythe.adapter'))
+
+
+def _get_adapter_map(adapter_map: str, extractors: list) -> dict:
+    """Helper function to generate 'adapter map'
+
+    Adapter map is a list of extractors and names of the appropriate adapters
+    to use to format their output.
+
+    Args:
+        adapter_map (str): string argument for adapters.
+            - 'match' means just find adapters with same names as corresponding extractors.
+        extractors ([str]): list of extractors
+    Returns:
+        (dict) where keys are adapter names extractor/adapter names and values are adapter objects.
+    """
+    if adapter_map is None:
+        adapter_map = {}
+    elif adapter_map == 'match':
+        adapters = get_available_adapters()
+        adapter_map = dict((x, x) for x in extractors if x in adapters)
+    elif not isinstance(adapter_map, dict):
+        raise ValueError('Adapter map must be a dict, None, or `matching`')
+
+    # Give it to the user
+    return adapter_map
+
+
+def get_extractor_and_adapter_contexts(name, global_context, extractor_context, adapter_context):
+    """
+    Helper function to update the helper and adapter contexts and the 'name'
+        of a extractor/adapter pair
+    Args:
+        name (str): adapter/extractor name.
+        global_context (dict): Context of the files, used for every extractor and adapter
+        adapter_context (dict): Context used for adapters. Key is the name of the adapter,
+            value is the context.  The key ``@all`` is used to for context used for every adapter
+        extractor_context (dict): Context used for adapters. Key is the name of the extractor,
+            value is the context. The key ``@all`` is used to for context used for every extractor
+    Returns:
+         (dict, dict): extractor_context, my_adapter context tuple
+    """
+
+    # Get the context information for the extractor and adapter
+    my_extractor_context = deepcopy(global_context)
+    my_extractor_context.update(extractor_context.get('@all', {}))
+    my_extractor_context.update(extractor_context.get(name, {}))
+
+    my_adapter_context = deepcopy(global_context)
+    my_adapter_context.update(adapter_context.get('@all', {}))
+    my_adapter_context.update(adapter_context.get(name, {}))
+
+    return my_extractor_context, my_adapter_context
+
+
+def _get_extractor_list(to_include: list, to_exclude: list) -> list:
+    """ Helper function to get a list of extractors given lists of extractors to include/exclude
+
+    Args:
+        to_include ([str]): Predefined list of extractors to run. Only these will be used.
+            Mutually exclusive with `exclude_extractors`.
+        to_exclude ([str]): List of extractors to exclude.
+            Mutually exclusive with `include_extractors`.
+    Returns:
+        List of all applicable extractors
+    """
+
+    extractors = get_available_extractors()
+    if to_include is not None and to_exclude is not None:
+        raise ValueError('Including and excluding extractors are mutually exclusive')
+    elif to_include is not None:
+        missing_extractors = set(to_include).difference(extractors.keys())
+        if len(missing_extractors) > 0:
+            raise ValueError('Some extractors are missing: ' + ' '.join(missing_extractors))
+        extractors = to_include
+    elif to_exclude is not None:
+        extractors = list(set(extractors.keys()).difference(to_exclude))
+
+    return extractors
+
+
+def get_extractor(name: str) -> BaseExtractor:
+    """Load an extractor object
+
+    Args:
+        name (str): Name of extractor
+    Returns:
+        Requested extractor
+    """
+    return DriverManager(
+        namespace='scythe.extractor',
+        name=name,
+        invoke_on_load=True
+    ).driver
+
+
+def get_adapter(name: str) -> BaseAdapter:
+    """Load an adapter
+
+    Args:
+        name (str): Name of adapter
+    Returns:
+        (BaseAdapter) Requested adapter
+    """
+
+    # Load the adapter
+    mgr = DriverManager(
+        namespace='scythe.adapter',
+        name=name,
+        invoke_on_load=True
+    )
+
+    # Give it to the user
+    return mgr.driver
+
+
+def run_extractor(name, group, context=None, adapter=None):
+    """Invoke a extractor on a certain group of files
+
+    Args:
+        name (str): Name of the extractor
+        group ([str]): Paths to group of files to be parsed
+        context (dict): Context of the files, used in adapter and extractor
+        adapter (str): Name of adapter to use to transform metadata
+    Returns:
+        ([dict]): Metadata generated by the extractor
+    """
+    metadata = get_extractor(name).extract(group, context)
+    if adapter is not None:
+        adapter = get_adapter(adapter)
+        return adapter.transform(metadata, context=context)
+    return metadata
+
+
+def run_all_extractors_on_directory(directory: str, global_context=None,
+                                    adapter_context: Union[None, dict] = None,
+                                    extractor_context: Union[None, dict] = None,
+                                    include_extractors: Union[None, List[str]] = None,
+                                    exclude_extractors: Union[None, List] = None,
+                                    adapter_map: Union[None, str, Dict[str, str]] = None,
+                                    default_adapter: Union[None, str] = None) \
+        -> Iterator[ExtractResult]:
+    """Run all known files on a directory of files
+
+    Args:
+        directory (str): Path to directory to be parsed
+        global_context (dict): Context of the files, used for every extractor and adapter
+        adapter_context (dict): Context used for adapters. Key is the name of the adapter,
+            value is the context.  The key ``@all`` is used to for context used for every adapter
+        extractor_context (dict): Context used for adapters. Key is the name of the extractor,
+            value is the context. The key ``@all`` is used to for context used for every extractor
+        include_extractors ([str]): Predefined list of extractors to run. Only these will be used.
+            Mutually exclusive with `exclude_extractors`.
+        exclude_extractors ([str]): List of extractors to exclude.
+            Mutually exclusive with `include_extractors`.
+        adapter_map (str, dict): Map of extractor name to the desired adapter.
+            Use 'match' to find adapters with the same names
+        default_adapter (str): Adapter to use if no other adapter is defined
+    Yields
+        ((str), str, dict) Tuple of (1) group of files, (2) name of extractor, (3) metadata
+    """
+
+    # Load in default arguments
+    if global_context is None:
+        global_context = dict()
+    if adapter_context is None:
+        adapter_context = dict()
+    if extractor_context is None:
+        extractor_context = dict()
+
+    # Get the list of extractors
+    extractors = _get_extractor_list(include_extractors, exclude_extractors)
+
+    # Make the adapter map
+    adapter_map = _get_adapter_map(adapter_map=adapter_map, extractors=extractors)
+
+    # Get the list of known extractors
+    for name in extractors:
+        # Get the extractor and adapter
+        extractor = get_extractor(name)
+        adapter_name = adapter_map.get(name, default_adapter)
+        if adapter_name is not None:
+            adapter = get_adapter(adapter_name)
+        else:
+            adapter = None
+
+        my_extractor_context, my_adapter_context = get_extractor_and_adapter_contexts(name,
+                                                                                      global_context,
+                                                                                      extractor_context,
+                                                                                      adapter_context)
+
+        for group, metadata in extractor.extract_directory(directory, context=my_extractor_context):
+            # Run the adapter, if defined
+            if adapter is not None:
+                try:
+                    metadata = adapter.transform(metadata, my_adapter_context)
+                except Exception as e:
+                    logger.warning(f'Adapter for {extractor} failed with caught exception: {e}')
+                    continue
+                if metadata is None:
+                    continue
+
+            yield ExtractResult(group, name, metadata)
+
+
+def run_all_extractors_on_group(group,
+                                adapter_map=None,
+                                global_context=None,
+                                adapter_context: Union[None, dict] = None,
+                                extractor_context: Union[None, dict] = None,
+                                include_extractors: Union[None, List[str]] = None,
+                                exclude_extractors: Union[None, List] = None,
+                                default_adapter: Union[None, str] = None):
+    """
+    Parse metadata from a file-group and adapt its metadata per a user-supplied adapter_map.
+
+    This function is effectively a wrapper to execute_extractor() that enables us to output metadata
+    in the same format as run_all_extractors_on_directory(), but just on a single file group.
+
+    Args:
+        group ([str]): Paths to group of files to be parsed
+        global_context (dict): Context of the files, used for every extractor and adapter
+        adapter_context (dict): Context used for adapters. Key is the name of the adapter,
+            value is the context.  The key ``@all`` is used to for context used for every adapter
+        extractor_context (dict): Context used for adapters. Key is the name of the extractor,
+            value is the context. The key ``@all`` is used to for context used for every extractor
+        include_extractors ([str]): Predefined list of extractors to run. Only these will be used.
+            Mutually exclusive with `exclude_extractors`.
+        exclude_extractors ([str]): List of extractors to exclude.
+            Mutually exclusive with `include_extractors`.
+        adapter_map (str, dict): Map of extractor name to the desired adapter.
+            Use 'match' to find adapters with the same names:
+        default_adapter:
+    Yields:
+        Metadata for a certain
+    """
+
+    # Load in default arguments
+    if global_context is None:
+        global_context = dict()
+    if adapter_context is None:
+        adapter_context = dict()
+    if extractor_context is None:
+        extractor_context = dict()
+
+    # Get the list of extractors
+    extractors = _get_extractor_list(include_extractors, exclude_extractors)
+
+    # Make the adapter map
+    adapter_map = _get_adapter_map(adapter_map=adapter_map, extractors=extractors)
+
+    for name in extractors:
+        # Get the extractor and adapter
+        adapter_name = adapter_map.get(name, default_adapter)
+
+        my_extractor_context, my_adapter_context = get_extractor_and_adapter_contexts(name,
+                                                                                      global_context,
+                                                                                      extractor_context,
+                                                                                      adapter_context)
+
+        metadata = run_extractor(name, group, context=my_extractor_context, adapter=adapter_name)
+
+        yield ExtractResult(group, name, metadata)
diff --git a/materials_io/version.py b/scythe/version.py
similarity index 79%
rename from materials_io/version.py
rename to scythe/version.py
index 31b4a72..628878e 100644
--- a/materials_io/version.py
+++ b/scythe/version.py
@@ -4,4 +4,4 @@
 # single source of truth for package version,
 # see https://packaging.python.org/en/latest/single_source_version/
 
-__version__ = importlib.metadata.version('materials_io')
+__version__ = importlib.metadata.version('scythe')
diff --git a/materials_io/xml.py b/scythe/xml.py
similarity index 86%
rename from materials_io/xml.py
rename to scythe/xml.py
index 9890daf..877536a 100644
--- a/materials_io/xml.py
+++ b/scythe/xml.py
@@ -1,13 +1,13 @@
 from mdf_toolbox import translate_json
 import xmltodict
 
-from materials_io.base import BaseSingleFileParser
+from scythe.base import BaseSingleFileExtractor
 
 
-class XMLExtractor(BaseSingleFileParser):
+class XMLExtractor(BaseSingleFileExtractor):
     """Extracts fields in XML into a user-defined new schema in JSON."""
 
-    def _parse_file(self, path, context=None):
+    def _extract_file(self, path, context=None):
         """Context used:
             mapping (dict): Required. The mapping of desired_fields: existing_fields,
                     using dot notation. For example:
diff --git a/materials_io/yaml.py b/scythe/yaml.py
similarity index 86%
rename from materials_io/yaml.py
rename to scythe/yaml.py
index 6194fd3..41b995f 100644
--- a/materials_io/yaml.py
+++ b/scythe/yaml.py
@@ -1,13 +1,13 @@
 from mdf_toolbox import translate_json
 import yaml
 
-from materials_io.base import BaseSingleFileParser
+from scythe.base import BaseSingleFileExtractor
 
 
-class YAMLExtractor(BaseSingleFileParser):
+class YAMLExtractor(BaseSingleFileExtractor):
     """Extracts fields in YAML into a user-defined new schema in JSON."""
 
-    def _parse_file(self, path, context=None):
+    def _extract_file(self, path, context=None):
         """Context used:
             mapping (dict): Required. The mapping of desired_fields: existing_fields,
                     using dot notation. For example:
diff --git a/setup.cfg b/setup.cfg
index e0e2d34..57c8b3f 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -3,4 +3,4 @@ universal = 1
 
 [flake8]
 exclude = .git,*.egg*,src/*,.*
-max-line-length = 100
+max-line-length = 160


Test patch:
diff --git a/materials_io/testing.py b/scythe/testing.py
similarity index 78%
rename from materials_io/testing.py
rename to scythe/testing.py
index ce1a664..837a310 100644
--- a/materials_io/testing.py
+++ b/scythe/testing.py
@@ -1,11 +1,11 @@
 """Parsers used for testing purposes"""
 
-from materials_io.base import BaseParser
+from scythe.base import BaseExtractor
 from typing import Iterable
 import os
 
 
-class NOOPParser(BaseParser):
+class NOOPExtractor(BaseExtractor):
     """Determine whether files exist, used for debugging
 
     Is not truly a "noop" parser, as it does perform a check as to whether the parser
@@ -13,7 +13,7 @@ class NOOPParser(BaseParser):
     nothing" parser.
     """
 
-    def parse(self, group: Iterable[str], context: dict = None):
+    def extract(self, group: Iterable[str], context: dict = None):
         return dict((f, os.path.exists(f)) for f in group)
 
     def version(self):
diff --git a/tests/test_adapter.py b/tests/test_adapter.py
index 8cd2916..1fd4482 100644
--- a/tests/test_adapter.py
+++ b/tests/test_adapter.py
@@ -1,10 +1,10 @@
-from materials_io.adapters.base import NOOPAdapter, GreedySerializeAdapter
-from materials_io.testing import NOOPParser
+from scythe.adapters.base import NOOPAdapter, GreedySerializeAdapter
+from scythe.testing import NOOPExtractor
 
 
 def test_compatibility():
     adapter = NOOPAdapter()
-    parser = NOOPParser()
+    parser = NOOPExtractor()
 
     # Make sure `None` is always compatible
     assert adapter.version() is None
diff --git a/tests/test_ase.py b/tests/test_ase.py
index 59dfed6..3d3c4af 100644
--- a/tests/test_ase.py
+++ b/tests/test_ase.py
@@ -1,4 +1,4 @@
-from materials_io.ase import AseParser
+from scythe.ase import ASEExtractor
 from math import isclose
 import pytest
 import os
@@ -11,11 +11,11 @@ def ase():
 
 @pytest.fixture
 def parser():
-    return AseParser()
+    return ASEExtractor()
 
 
 def test_ase(parser, ase):
-    output = parser.parse(ase)
+    output = parser.extract(ase)
 
     # Check the chemical formula
     assert output['chemical_formula'] == "C38H14N8O12"
diff --git a/tests/test_base.py b/tests/test_base.py
index 431a475..b0df0f4 100644
--- a/tests/test_base.py
+++ b/tests/test_base.py
@@ -1,12 +1,12 @@
-from materials_io.base import BaseParser, BaseSingleFileParser
+from scythe.base import BaseExtractor, BaseSingleFileExtractor
 from glob import glob
 import pytest
 import os
 
 
-class FakeParser(BaseParser):
+class FakeParser(BaseExtractor):
 
-    def parse(self, group, context=None):
+    def extract(self, group, context=None):
         return {'group': list(group)}
 
     def implementors(self):
@@ -16,9 +16,9 @@ def version(self):
         return '0.0.0'
 
 
-class FakeSingleParser(BaseSingleFileParser):
+class FakeSingleParser(BaseSingleFileExtractor):
 
-    def _parse_file(self, path, context=None):
+    def _extract_file(self, path, context=None):
         return {'dirname': os.path.dirname(path)}
 
     def implementors(self):
@@ -50,7 +50,7 @@ def test_group(parser, directory, my_files):
 
 
 def test_parse_dir(caplog, parser, directory, my_files):
-    assert len(list(parser.parse_directory(directory))) == len(my_files)
+    assert len(list(parser.extract_directory(directory))) == len(my_files)
 
 
 def test_citations(parser):
@@ -59,7 +59,7 @@ def test_citations(parser):
 
 def test_single_file(directory):
     parser = FakeSingleParser()
-    assert parser.parse(__file__) == {'dirname': directory}  # Handle sensibly incorrect inputs
-    assert parser.parse([__file__]) == {'dirname': directory}
+    assert parser.extract(__file__) == {'dirname': directory}  # Handle sensibly incorrect inputs
+    assert parser.extract([__file__]) == {'dirname': directory}
     with pytest.raises(ValueError):
-        parser.parse(['/fake/file.in', '/fake/file.out'])
+        parser.extract(['/fake/file.in', '/fake/file.out'])
diff --git a/tests/test_crystal_structure.py b/tests/test_crystal_structure.py
index 990b7b2..d61e212 100644
--- a/tests/test_crystal_structure.py
+++ b/tests/test_crystal_structure.py
@@ -1,4 +1,4 @@
-from materials_io.crystal_structure import CrystalStructureParser
+from scythe.crystal_structure import CrystalStructureExtractor
 from math import isclose
 import pytest
 import os
@@ -11,11 +11,11 @@ def cif():
 
 @pytest.fixture
 def parser():
-    return CrystalStructureParser()
+    return CrystalStructureExtractor()
 
 
 def test_cif(parser, cif):
-    output = parser.parse(cif)
+    output = parser.extract(cif)
 
     # Check the volume and number of atoms, which is a float
     assert isclose(output['crystal_structure']['volume'], 101836.44086588411)
diff --git a/tests/test_csv.py b/tests/test_csv.py
index 622f18d..0527635 100644
--- a/tests/test_csv.py
+++ b/tests/test_csv.py
@@ -1,14 +1,14 @@
-from materials_io.csv import CSVParser
+from scythe.csv import CSVExtractor
 import os
 
 csv_file = os.path.join(os.path.dirname(__file__), 'data', 'test.csv')
 
 
 def test_csv():
-    p = CSVParser()
+    p = CSVExtractor()
 
     # Test with records
-    output = p.parse([csv_file])
+    output = p.extract([csv_file])
     assert len(output['records']) == 4
     assert isinstance(output['records'][0], dict)
     assert isinstance(output['records'][0]['location'], list)
@@ -22,11 +22,11 @@ def test_csv():
 
     # Test without records
     p.return_records = False
-    assert 'records' not in p.parse([csv_file])
+    assert 'records' not in p.extract([csv_file])
 
     # Test with missing values
     p.return_records = True
-    output = p.parse([csv_file], {'na_values': ['N/A']})
+    output = p.extract([csv_file], {'na_values': ['N/A']})
     assert output['schema'] == {'fields': [{'name': 'city', 'type': 'string',
                                             'format': 'default'},
                                            {'name': 'location', 'type': 'geopoint',
diff --git a/tests/test_dft.py b/tests/test_dft.py
index 73b5217..2e572e9 100644
--- a/tests/test_dft.py
+++ b/tests/test_dft.py
@@ -1,4 +1,4 @@
-from materials_io.dft import DFTParser
+from scythe.dft import DFTExtractor
 from shutil import copy
 from glob import glob
 import tarfile
@@ -21,7 +21,7 @@ def vasp_dir(tmpdir):
 
 @pytest.fixture
 def parser():
-    return DFTParser(quality_report=False)
+    return DFTExtractor(quality_report=False)
 
 
 @pytest.fixture
@@ -41,20 +41,20 @@ def pwscf_dir(tmpdir):
 
 
 def test_single_vasp_calc(parser, vasp_dir):
-    metadata = list(parser.parse_directory(vasp_dir))
+    metadata = list(parser.extract_directory(vasp_dir))
     assert len(metadata) == 1
     assert isinstance(metadata[0], tuple)
     assert isinstance(metadata[0][0], list)
     assert isinstance(metadata[0][1], dict)
 
 
-def test_multivasp_calc(parser: DFTParser, multi_vasp_dir):
-    metadata = list(parser.parse_directory(multi_vasp_dir))
+def test_multivasp_calc(parser: DFTExtractor, multi_vasp_dir):
+    metadata = list(parser.extract_directory(multi_vasp_dir))
     assert len(metadata) == 2
     assert isinstance(metadata[0][0], list)
     assert isinstance(metadata[0][1], dict)
 
 
-def test_pwscf(parser: DFTParser, pwscf_dir):
-    metadata = list(parser.parse_directory(pwscf_dir))
+def test_pwscf(parser: DFTExtractor, pwscf_dir):
+    metadata = list(parser.extract_directory(pwscf_dir))
     assert len(metadata) == 1
diff --git a/tests/test_electron_microscopy.py b/tests/test_electron_microscopy.py
index 4f535b1..c86c486 100644
--- a/tests/test_electron_microscopy.py
+++ b/tests/test_electron_microscopy.py
@@ -2,8 +2,8 @@
 import pathlib
 import jsonschema
 
-from materials_io.electron_microscopy import ElectronMicroscopyParser
-from materials_io.adapters.base import GreedySerializeAdapter
+from scythe.electron_microscopy import ElectronMicroscopyExtractor
+from scythe.adapters.base import GreedySerializeAdapter
 
 
 def file_path(fname):
@@ -12,7 +12,7 @@ def file_path(fname):
 
 @pytest.fixture
 def parser():
-    return ElectronMicroscopyParser()
+    return ElectronMicroscopyExtractor()
 
 
 @pytest.fixture
@@ -21,7 +21,7 @@ def adapter():
 
 
 def test_dm3(parser, adapter):
-    res = parser.parse([file_path('test-1.dm3')])
+    res = parser.extract([file_path('test-1.dm3')])
     assert res['electron_microscopy']['General'] == {
         'original_filename': {'value': 'test-1.dm3'},
         'title': {'value': 'test'},
@@ -35,7 +35,7 @@ def test_dm3(parser, adapter):
 
 
 def test_dm4(parser, adapter):
-    res = parser.parse([file_path('test-1.dm4')])
+    res = parser.extract([file_path('test-1.dm4')])
     assert res['electron_microscopy']['General'] == {
         'original_filename': {'value': 'test-1.dm4'},
         'title': {'value': 'test'},
@@ -50,7 +50,7 @@ def test_dm4(parser, adapter):
 
 
 def test_eds(parser, adapter):
-    res = parser.parse([file_path('01_test-EDS_spectrum.dm3')])
+    res = parser.extract([file_path('01_test-EDS_spectrum.dm3')])
 
     assert res['electron_microscopy']['General'] == {
         'date': {'value': '2016-08-08'},
@@ -102,7 +102,7 @@ def test_eds(parser, adapter):
     assert jsonschema.validate(res, parser.schema) is None
     assert adapter.transform(res)
 
-    res = parser.parse([file_path('02_EDS_SI_Titan.dm4')])
+    res = parser.extract([file_path('02_EDS_SI_Titan.dm4')])
     assert res['electron_microscopy']['General'] == {
         'date': {'value': '2019-05-21'},
         'original_filename': {'value': '02_EDS_SI_Titan.dm4'},
@@ -158,7 +158,7 @@ def test_eds(parser, adapter):
 
 
 def test_edax_eds(parser, adapter):
-    res = parser.parse([file_path('03_edax_sem_eds_map_dataZeroed.spd')])
+    res = parser.extract([file_path('03_edax_sem_eds_map_dataZeroed.spd')])
 
     assert res['electron_microscopy']['General'] == {
         'original_filename': {'value': '03_edax_sem_eds_map_dataZeroed.spd'},
@@ -190,7 +190,7 @@ def test_edax_eds(parser, adapter):
 
 
 def test_eels(parser, adapter):
-    res = parser.parse([file_path('04_Titan_EELS_SI_dataZeroed.dm3')])
+    res = parser.extract([file_path('04_Titan_EELS_SI_dataZeroed.dm3')])
     assert res['electron_microscopy']['General'] == {
         'date': {'value': '2016-04-22'},
         'original_filename': {'value': '04_Titan_EELS_SI_dataZeroed.dm3'},
@@ -252,7 +252,7 @@ def test_eels(parser, adapter):
 
 
 def test_non_titan_dm3(parser, adapter):
-    res = parser.parse([file_path('05_nonTitan_diffraction.dm3')])
+    res = parser.extract([file_path('05_nonTitan_diffraction.dm3')])
     assert res['electron_microscopy']['General'] == {
         'date': {'value': '2019-07-01'},
         'original_filename': {'value': '05_nonTitan_diffraction.dm3'},
@@ -284,7 +284,7 @@ def test_dm3_tecnai(parser, adapter):
     }
 
     # parse imaging mode tecnai file
-    res = parser.parse([file_path('06_Titan_Tecnai_image.dm3')])
+    res = parser.extract([file_path('06_Titan_Tecnai_image.dm3')])
 
     assert res['electron_microscopy']['General'] == {
         'date': {'value': '2019-03-13'},
@@ -331,7 +331,7 @@ def test_dm3_tecnai(parser, adapter):
     assert adapter.transform(res)
 
     # parse diffraction mode tecnai dm3
-    res = parser.parse([file_path('07_Titan_Tecnai_diffraction.dm3')])
+    res = parser.extract([file_path('07_Titan_Tecnai_diffraction.dm3')])
     assert res['electron_microscopy']['General'] == {
         'date': {'value': '2019-09-19'},
         'original_filename': {'value': '07_Titan_Tecnai_diffraction.dm3'},
@@ -379,7 +379,7 @@ def test_dm3_tecnai(parser, adapter):
     assert adapter.transform(res)
 
     # parse diffraction mode tecnai with no spectrometer info
-    res = parser.parse([file_path(
+    res = parser.extract([file_path(
         '08_Titan_diffraction_Tecnai_no_spectrometer.dm3')])
     assert res['electron_microscopy']['General'] == {
         'date': {'value': '2019-03-22'}, 'original_filename': {
@@ -427,7 +427,7 @@ def test_dm3_tecnai(parser, adapter):
 
 
 def test_dm3_stack(parser, adapter):
-    res = parser.parse([file_path('09_Titan_STEM_stack.dm3')])
+    res = parser.extract([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
     # the proprietary software. The proper calibration appears to be present
@@ -471,7 +471,7 @@ def test_dm3_stack(parser, adapter):
 
 
 def test_eels_acquisition_spectrometer(parser, adapter):
-    res = parser.parse([file_path('10_Titan_EELS_proc.dm3')])
+    res = parser.extract([file_path('10_Titan_EELS_proc.dm3')])
     assert res['electron_microscopy']['General'] == {
         'original_filename': {'value': '10_Titan_EELS_proc.dm3'},
         'title': {'value': 'SI24 Extracted Spectrum total'},
@@ -517,7 +517,7 @@ def test_eels_acquisition_spectrometer(parser, adapter):
 
 
 def test_hs_signal_no_units(parser, adapter):
-    res = parser.parse([file_path('11_hs_signal_no_axis_units.hspy')])
+    res = parser.extract([file_path('11_hs_signal_no_axis_units.hspy')])
     assert res['electron_microscopy']['General'] == {
         'axis_calibration': {
             'axis-0': {'name': None, 'scale': 1.0,
@@ -532,7 +532,7 @@ def test_hs_signal_no_units(parser, adapter):
 
 
 def test_tia_haadf(parser, adapter):
-    res = parser.parse([file_path('12_TIA_HAADF.emi')])
+    res = parser.extract([file_path('12_TIA_HAADF.emi')])
     assert res['electron_microscopy']['General'] == {
         'date': {'value': '2019-06-28'},
         'original_filename': {'value': '12_TIA_HAADF_1.ser'},
@@ -577,7 +577,7 @@ def test_tia_haadf(parser, adapter):
 
 
 def test_quanta_sem_tif(parser, adapter):
-    res = parser.parse([file_path('20_quanta_sem.tif')])
+    res = parser.extract([file_path('20_quanta_sem.tif')])
     assert res['electron_microscopy']['General'] == {
         'date': {'value': '2022-03-03'},
         'original_filename': {'value': '20_quanta_sem.tif'},
@@ -613,7 +613,7 @@ def test_quanta_sem_tif(parser, adapter):
 
 
 def test_zeiss_sem_tif(parser, adapter):
-    res = parser.parse([file_path('21_zeiss_sem.tif')])
+    res = parser.extract([file_path('21_zeiss_sem.tif')])
     assert res['electron_microscopy']['General'] == {
         'date': {'value': '2017-12-15'},
         'original_filename': {'value': '21_zeiss_sem.tif'},
@@ -640,7 +640,7 @@ def test_zeiss_sem_tif(parser, adapter):
 
 
 def test_zeiss_sem_bad_mag_tif(parser, adapter):
-    res = parser.parse([file_path('22_zeiss_sem_bad_mag.tif')])
+    res = parser.extract([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'},
diff --git a/tests/test_file.py b/tests/test_file.py
index 3f91dd0..e7678b5 100644
--- a/tests/test_file.py
+++ b/tests/test_file.py
@@ -1,12 +1,12 @@
-from materials_io.file import GenericFileParser
+from scythe.file import GenericFileExtractor
 import pytest
 import os
 
 
 def test_file():
     my_file = os.path.join(os.path.dirname(__file__), 'data', 'image', 'dog2.jpeg')
-    parser = GenericFileParser(store_path=True, compute_hash=True)
-    output = parser.parse([my_file])
+    parser = GenericFileExtractor(store_path=True, compute_hash=True)
+    output = parser.extract([my_file])
     expected = {
         'mime_type': 'image/jpeg',
         'length': 269360,
diff --git a/tests/test_filename.py b/tests/test_filename.py
index 35c90dc..acb5c66 100644
--- a/tests/test_filename.py
+++ b/tests/test_filename.py
@@ -2,7 +2,7 @@
 
 import pytest
 
-from materials_io.filename import FilenameExtractor
+from scythe.filename import FilenameExtractor
 
 
 @pytest.fixture
@@ -53,11 +53,11 @@ def test_filename(extractor, test_files, mappings):
         }
     }]
 
-    assert extractor.parse(test_files[0], context={"mapping": mappings[0]}) == outputs[0]
-    assert extractor.parse(test_files[1], context={"mapping": mappings[0]}) == outputs[1]
-    assert extractor.parse(test_files[2], context={"mapping": mappings[0]}) == outputs[2]
+    assert extractor.extract(test_files[0], context={"mapping": mappings[0]}) == outputs[0]
+    assert extractor.extract(test_files[1], context={"mapping": mappings[0]}) == outputs[1]
+    assert extractor.extract(test_files[2], context={"mapping": mappings[0]}) == outputs[2]
 
     # Test failure modes
     # No mapping provided
     with pytest.raises(Exception):
-        extractor.parse(test_files[0])
+        extractor.extract(test_files[0])
diff --git a/tests/test_image.py b/tests/test_image.py
index 98353da..3277551 100644
--- a/tests/test_image.py
+++ b/tests/test_image.py
@@ -1,7 +1,7 @@
 import pytest
 import os
 
-from materials_io.image import ImageParser
+from scythe.image import ImageExtractor
 
 
 @pytest.fixture
@@ -10,7 +10,7 @@ def test_image():
 
 
 def test_parse(test_image):
-    p = ImageParser()
-    assert (p.parse([test_image]) == {'image': {'format': 'JPEG', 'height': 1000,
-                                                'megapixels': 1.91, 'width': 1910,
-                                                'shape': [1000, 1910, 3]}})
+    p = ImageExtractor()
+    assert (p.extract([test_image]) == {'image': {'format': 'JPEG', 'height': 1000,
+                                                  'megapixels': 1.91, 'width': 1910,
+                                                  'shape': [1000, 1910, 3]}})
diff --git a/tests/test_json.py b/tests/test_json.py
index 34dcc58..e0af411 100644
--- a/tests/test_json.py
+++ b/tests/test_json.py
@@ -2,7 +2,7 @@
 
 import pytest
 
-from materials_io.json import JSONExtractor
+from scythe.json import JSONExtractor
 
 
 @pytest.fixture
@@ -61,16 +61,16 @@ def test_json(extractor, test_files, fail_file, mappings):
         }
     }
 
-    assert extractor.parse(test_files[0], context={"mapping": mappings[0]}) == output_na_unset
-    assert extractor.parse(test_files[0], context={"mapping": mappings[1]}) == output_na_unset
-    assert extractor.parse(test_files[0], context={"mapping": mappings[0],
-                                                   "na_values": ["na"]}) == output_na_set
-    assert extractor.parse(test_files[0], context={"mapping": mappings[1],
-                                                   "na_values": "na"}) == output_na_set
+    assert extractor.extract(test_files[0], context={"mapping": mappings[0]}) == output_na_unset
+    assert extractor.extract(test_files[0], context={"mapping": mappings[1]}) == output_na_unset
+    assert extractor.extract(test_files[0], context={"mapping": mappings[0],
+                                                     "na_values": ["na"]}) == output_na_set
+    assert extractor.extract(test_files[0], context={"mapping": mappings[1],
+                                                     "na_values": "na"}) == output_na_set
 
     # Test failure modes
     with pytest.raises(Exception):
-        extractor.parse(fail_file)
+        extractor.extract(fail_file)
     # No mapping provided
     with pytest.raises(Exception):
-        extractor.parse(test_files[0])
+        extractor.extract(test_files[0])
diff --git a/tests/test_tdb.py b/tests/test_tdb.py
index 5ec6e3f..5779bd8 100644
--- a/tests/test_tdb.py
+++ b/tests/test_tdb.py
@@ -3,7 +3,7 @@
 from mdf_toolbox import insensitive_comparison as eqi
 import pytest
 
-from materials_io.tdb import TDBExtractor
+from scythe.tdb import TDBExtractor
 
 
 @pytest.fixture
@@ -25,19 +25,19 @@ def extractor():
 
 def test_tdb(extractor, test_files, fail_file):
     # Run test extractions
-    output0 = extractor.parse(test_files[0])
+    output0 = extractor.extract(test_files[0])
     assert eqi(output0["material"]["composition"], "VaPbSNaTeSe", string_insensitive=True)
     assert eqi(output0["calphad"]["phases"], ['LIQUID', 'FCC_A1', 'HALITE', 'HEXAGONAL_A8',
                                               'ORTHORHOMBIC_S', 'BCC_A2', 'NA2TE', 'NATE', 'NATE3',
                                               'NA2SE', 'NASE', 'NASE2', 'NA2S', 'NAS', 'NAS2'])
-    output1 = extractor.parse(test_files[1])
+    output1 = extractor.extract(test_files[1])
     assert eqi(output1["material"]["composition"], "SiVaAu", string_insensitive=True)
     assert eqi(output1["calphad"]["phases"], ['LIQUID', 'BCC_A2', 'CBCC_A12', 'CUB_A13',
                                               'DIAMOND_A4', 'FCC_A1', 'HCP_A3', 'HCP_ZN'])
-    output2 = extractor.parse(test_files[2])
+    output2 = extractor.extract(test_files[2])
     assert eqi(output2["material"]["composition"], "TeVaPb", string_insensitive=True)
     assert eqi(output2["calphad"]["phases"], ['LIQUID', 'PBTE', 'HEXAGONAL_A8', 'RHOMBOHEDRAL_A7'])
 
     # Test failure modes
     with pytest.raises(Exception):
-        extractor.parse(fail_file)
+        extractor.extract(fail_file)
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 970aa85..ca4c177 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -1,8 +1,8 @@
-from materials_io.utils.interface import (get_available_parsers, execute_parser,
-                                          get_available_adapters, run_all_parsers_on_directory,
-                                          ParseResult)
-from materials_io.utils import set_nested_dict_value
-from materials_io.image import ImageParser
+from scythe.utils.interface import (get_available_extractors, run_extractor,
+                                    get_available_adapters, run_all_extractors_on_directory,
+                                    ExtractResult)
+from scythe.utils import set_nested_dict_value
+from scythe.image import ImageExtractor
 import pytest
 import json
 import os
@@ -12,18 +12,18 @@
 
 
 def test_list_parsers():
-    assert 'image' in get_available_parsers()
+    assert 'image' in get_available_extractors()
 
 
 def test_execute_parser():
     image = os.path.join(cwd, 'data', 'image', 'dog2.jpeg')
-    assert ImageParser().parse([image]) == execute_parser('image', [image])
-    assert execute_parser('image', [image], adapter='noop') == execute_parser('image', [image])
+    assert ImageExtractor().extract([image]) == run_extractor('image', [image])
+    assert run_extractor('image', [image], adapter='noop') == run_extractor('image', [image])
 
 
 def test_run_all_parsers():
     path = os.path.join(cwd, 'data', 'image')
-    output = list(run_all_parsers_on_directory(path))
+    output = list(run_all_extractors_on_directory(path))
     assert len(output) > 0
     assert len(output[0]) == 3
     assert isinstance(output[0][0], tuple)
@@ -31,44 +31,44 @@ def test_run_all_parsers():
     assert isinstance(output[0][2], dict)
 
     # Re-run parsers with adapters
-    output_noop = list(run_all_parsers_on_directory(path, default_adapter='noop'))
+    output_noop = list(run_all_extractors_on_directory(path, default_adapter='noop'))
     assert output == output_noop
-    output_json = list(run_all_parsers_on_directory(path, default_adapter='serialize'))
-    assert output == [ParseResult(x.group, x.parser, json.loads(x.metadata)) for x in output_json]
+    output_json = list(run_all_extractors_on_directory(path, default_adapter='serialize'))
+    assert output == [ExtractResult(x.group, x.extractor, json.loads(x.metadata)) for x in output_json]
 
     # Test the matching
-    output_matching = list(run_all_parsers_on_directory(path, adapter_map={'file': 'serialize'}))
-    assert all(isinstance(x.metadata, str if x.parser == 'file' else dict)
+    output_matching = list(run_all_extractors_on_directory(path, adapter_map={'file': 'serialize'}))
+    assert all(isinstance(x.metadata, str if x.extractor == 'file' else dict)
                for x in output_matching)
-    output_matching = list(run_all_parsers_on_directory(path, adapter_map={'file': 'noop'},
-                                                        default_adapter='serialize'))
-    assert all(isinstance(x.metadata, str if x.parser != 'file' else dict)
+    output_matching = list(run_all_extractors_on_directory(path, adapter_map={'file': 'noop'},
+                                                           default_adapter='serialize'))
+    assert all(isinstance(x.metadata, str if x.extractor != 'file' else dict)
                for x in output_matching)
 
     # This matching test fails if we have other packages with adapters on the system
     adapters = set(get_available_adapters().keys())
     if adapters == {'noop', 'serialize'}:
-        output_matching = list(run_all_parsers_on_directory(path, adapter_map='match',
-                                                            default_adapter='serialize'))
-        assert all(isinstance(x.metadata, str if x.parser != 'noop' else dict)
+        output_matching = list(run_all_extractors_on_directory(path, adapter_map='match',
+                                                               default_adapter='serialize'))
+        assert all(isinstance(x.metadata, str if x.extractor != 'noop' else dict)
                    for x in output_matching)
 
     # Test the error case
     with pytest.raises(ValueError):
-        list(run_all_parsers_on_directory(path, adapter_map='matching',
-                                          default_adapter='serialize'))
+        list(run_all_extractors_on_directory(path, adapter_map='matching',
+                                             default_adapter='serialize'))
 
     # Test specifying parsers
-    assert set([x.parser for x in output]).issuperset(['image', 'generic'])
-    output_limit = list(run_all_parsers_on_directory(path, exclude_parsers=['image']))
-    assert 'image' not in [x.parser for x in output_limit]
-    output_limit = list(run_all_parsers_on_directory(path, include_parsers=['image']))
-    assert set([x.parser for x in output_limit]) == {'image'}
+    assert set([x.extractor for x in output]).issuperset(['image', 'generic'])
+    output_limit = list(run_all_extractors_on_directory(path, exclude_extractors=['image']))
+    assert 'image' not in [x.extractor for x in output_limit]
+    output_limit = list(run_all_extractors_on_directory(path, include_extractors=['image']))
+    assert set([x.extractor for x in output_limit]) == {'image'}
     with pytest.raises(ValueError):
-        list(run_all_parsers_on_directory(path, include_parsers=['image'],
-                                          exclude_parsers=['image']))
+        list(run_all_extractors_on_directory(path, include_extractors=['image'],
+                                             exclude_extractors=['image']))
     with pytest.raises(ValueError):
-        list(run_all_parsers_on_directory(path, include_parsers=['totally-not-a-parser']))
+        list(run_all_extractors_on_directory(path, include_extractors=['totally-not-a-parser']))
 
 
 def test_list_adapters():
diff --git a/tests/test_version.py b/tests/test_version.py
index 97269c7..08597dc 100644
--- a/tests/test_version.py
+++ b/tests/test_version.py
@@ -1,5 +1,5 @@
-from materials_io import version
+from scythe import version
 
 
 def test_version():
-    assert version.__version__ == '0.1.1'
+    assert isinstance(version.__version__, str)
diff --git a/tests/test_xml.py b/tests/test_xml.py
index f8d85e4..cb86f2f 100644
--- a/tests/test_xml.py
+++ b/tests/test_xml.py
@@ -2,7 +2,7 @@
 
 import pytest
 
-from materials_io.xml import XMLExtractor
+from scythe.xml import XMLExtractor
 
 
 @pytest.fixture
@@ -61,16 +61,16 @@ def test_xml(extractor, test_files, fail_file, mappings):
         }
     }
 
-    assert extractor.parse(test_files[0], context={"mapping": mappings[0]}) == output_na_unset
-    assert extractor.parse(test_files[0], context={"mapping": mappings[1]}) == output_na_unset
-    assert extractor.parse(test_files[0], context={"mapping": mappings[0],
-                                                   "na_values": ["na"]}) == output_na_set
-    assert extractor.parse(test_files[0], context={"mapping": mappings[1],
-                                                   "na_values": "na"}) == output_na_set
+    assert extractor.extract(test_files[0], context={"mapping": mappings[0]}) == output_na_unset
+    assert extractor.extract(test_files[0], context={"mapping": mappings[1]}) == output_na_unset
+    assert extractor.extract(test_files[0], context={"mapping": mappings[0],
+                                                     "na_values": ["na"]}) == output_na_set
+    assert extractor.extract(test_files[0], context={"mapping": mappings[1],
+                                                     "na_values": "na"}) == output_na_set
 
     # Test failure modes
     with pytest.raises(Exception):
-        extractor.parse(fail_file)
+        extractor.extract(fail_file)
     # No mapping provided
     with pytest.raises(Exception):
-        extractor.parse(test_files[0])
+        extractor.extract(test_files[0])
diff --git a/tests/test_yaml.py b/tests/test_yaml.py
index 7029099..cc357af 100644
--- a/tests/test_yaml.py
+++ b/tests/test_yaml.py
@@ -2,7 +2,7 @@
 
 import pytest
 
-from materials_io.yaml import YAMLExtractor
+from scythe.yaml import YAMLExtractor
 
 
 @pytest.fixture
@@ -61,16 +61,16 @@ def test_yaml(extractor, test_files, fail_file, mappings):
         }
     }
 
-    assert extractor.parse(test_files[0], context={"mapping": mappings[0]}) == output_na_unset
-    assert extractor.parse(test_files[0], context={"mapping": mappings[1]}) == output_na_unset
-    assert extractor.parse(test_files[0], context={"mapping": mappings[0],
-                                                   "na_values": ["na"]}) == output_na_set
-    assert extractor.parse(test_files[0], context={"mapping": mappings[1],
-                                                   "na_values": "na"}) == output_na_set
+    assert extractor.extract(test_files[0], context={"mapping": mappings[0]}) == output_na_unset
+    assert extractor.extract(test_files[0], context={"mapping": mappings[1]}) == output_na_unset
+    assert extractor.extract(test_files[0], context={"mapping": mappings[0],
+                                                     "na_values": ["na"]}) == output_na_set
+    assert extractor.extract(test_files[0], context={"mapping": mappings[1],
+                                                     "na_values": "na"}) == output_na_set
 
     # Test failure modes
     with pytest.raises(Exception):
-        extractor.parse(fail_file)
+        extractor.extract(fail_file)
     # No mapping provided
     with pytest.raises(Exception):
-        extractor.parse(test_files[0])
+        extractor.extract(test_files[0])