diff --git a/.isort.cfg b/.isort.cfg
new file mode 100644
index 00000000..e0926f42
--- /dev/null
+++ b/.isort.cfg
@@ -0,0 +1,4 @@
+[settings]
+line_length = 115
+multi_line_output = 3
+include_trailing_comma = True
diff --git a/AUTHORS.txt b/AUTHORS.rst
similarity index 81%
rename from AUTHORS.txt
rename to AUTHORS.rst
index a6b9bc57..c942b8dd 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.rst
@@ -1,3 +1,16 @@
+Authors
+=======
+
+DiffPy was initiated as part of the Distributed Data Analysis of Neutron
+Scattering Experiments (DANSE) project, funded by the National Science
+Foundation under grant DMR-0520547.  More information on DANSE can be
+found at http://danse.us.  Any opinions, findings, and conclusions or
+recommendations expressed in this material are those of the author(s)
+and do not necessarily reflect the views of the NSF.
+
+Main Contributors
+-----------------
+
 This code was developed as part of the DiffPy project to create python
 modules for structure investigations from diffraction data.  The main
 contributors to this package were
@@ -7,18 +20,19 @@ contributors to this package were
     Pavol Juhas
     Dmitriy Bryndin
 
-The DiffPy team is located in the Billinge-group at the Applied Physics
-and Applied Mathematics Department of the Columbia University in New York.
-Currently the team consists of
+Other current and former contributors of the DiffPy project include
 
     Simon Billinge
-    Pavol Juhas
     Chris Farrow
     Emil Bozin
     Wenduo Zhou
     Peng Tian
-    Timur Dykhne
 
+The DiffPy team is part of the Billinge Group at Columbia University in New York,
+within the Department of Applied Physics and Applied Mathematics.
+
+Contributors
+------------
 Please see the header of each source file for a detailed list of
 contributors.  This is an open-source project and we hope and expect
 that the list of contributors will expand with time.  Many thanks to
@@ -26,14 +40,11 @@ all current and future contributors!
 
 For more information on the DiffPy project email sb2896@columbia.edu
 
-DiffPy was initiated as part of the Distributed Data Analysis of Neutron
-Scattering Experiments (DANSE) project, funded by the National Science
-Foundation under grant DMR-0520547.  More information on DANSE can be
-found at http://danse.us.  Any opinions, findings, and conclusions or
-recommendations expressed in this material are those of the author(s)
-and do not necessarily reflect the views of the NSF.
+For a list of contributors, visit
+https://github.com/diffpy/diffpy.pdfgui/graphs/contributors
 
-Acknowledgments:
+Acknowledgments
+---------------
 
 We are truly grateful to all the people who have contributed, in all
 different ways, to this project:  Thomas Proffen, Xiangyun Qiu, Pete
diff --git a/CODE_OF_CONDUCT.rst b/CODE_OF_CONDUCT.rst
new file mode 100644
index 00000000..ff9c3561
--- /dev/null
+++ b/CODE_OF_CONDUCT.rst
@@ -0,0 +1,133 @@
+=====================================
+ Contributor Covenant Code of Conduct
+=====================================
+
+Our Pledge
+----------
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual
+identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+Our Standards
+-------------
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+  and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the overall
+  community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or advances of
+  any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email address,
+  without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+
+Enforcement Responsibilities
+----------------------------
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+Scope
+-----
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official email address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+Enforcement
+-----------
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+sb2896@columbia.edu. All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+Enforcement Guidelines
+----------------------
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+1. Correction
+****************
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+2. Warning
+*************
+
+**Community Impact**: A violation through a single incident or series of
+actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or permanent
+ban.
+
+3. Temporary Ban
+******************
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+4. Permanent Ban
+******************
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the
+community.
+
+Attribution
+-----------
+
+This Code of Conduct is adapted from the `Contributor Covenant <https://www.contributor-covenant.org/version/2/1/code_of_conduct.html>`_.
+
+Community Impact Guidelines were inspired by `Mozilla's code of conduct enforcement ladder <https://github.com/mozilla/inclusion>`_.
+
+For answers to common questions about this code of conduct, see the `FAQ <https://www.contributor-covenant.org/faq>`_. `Translations are available <https://www.contributor-covenant.org/translations>`_
diff --git a/LICENSE.txt b/LICENSE.rst
similarity index 64%
rename from LICENSE.txt
rename to LICENSE.rst
index f451dcb7..0cebd08f 100644
--- a/LICENSE.txt
+++ b/LICENSE.rst
@@ -1,3 +1,7 @@
+Copyright (c) 2024, The Trustees of Columbia University
+in the City of New York.
+All rights reserved.
+
 This software was originally developed by the Billinge group as part
 of the Distributed Data Analysis of Neutron Scattering Experiments
 (DANSE) project funded by the US National Science Foundation under
@@ -47,32 +51,26 @@ For more information please visit the project web-page:
 or email Prof. Simon Billinge at sb2896@columbia.edu
 
 Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
+modification, are permitted provided that the following conditions are met:
 
-  * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
 
-  * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
 
-  * Neither the name of the copyright holder nor the names of its
-    contributors may be used to endorse or promote products derived from
-    this software without specific prior written permission.
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
 
-THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER "AS IS".  COPYRIGHT HOLDER
-EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES AND CONDITIONS, EITHER
-EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY, TITLE, FITNESS, ADEQUACY OR SUITABILITY
-FOR A PARTICULAR PURPOSE, AND ANY WARRANTIES OF FREEDOM FROM
-INFRINGEMENT OF ANY DOMESTIC OR FOREIGN PATENT, COPYRIGHTS, TRADE
-SECRETS OR OTHER PROPRIETARY RIGHTS OF ANY PARTY.  IN NO EVENT SHALL
-COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE OR RELATING TO THIS AGREEMENT, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/requirements/build.txt b/requirements/build.txt
new file mode 100644
index 00000000..f72d870d
--- /dev/null
+++ b/requirements/build.txt
@@ -0,0 +1,2 @@
+python
+setuptools
diff --git a/requirements/docs.txt b/requirements/docs.txt
new file mode 100644
index 00000000..ab17b1c8
--- /dev/null
+++ b/requirements/docs.txt
@@ -0,0 +1,4 @@
+sphinx
+sphinx_rtd_theme
+doctr
+m2r
diff --git a/requirements/pip.txt b/requirements/pip.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/requirements/run.txt b/requirements/run.txt
index 40bce3f0..1bad6988 100644
--- a/requirements/run.txt
+++ b/requirements/run.txt
@@ -1,5 +1,5 @@
-numpy==1.26
-wxpython
-diffpy.pdffit2
-diffpy.utils
-matplotlib-base
+numpy==1.26
+wxpython
+diffpy.pdffit2
+diffpy.utils
+matplotlib-base
diff --git a/requirements/test.txt b/requirements/test.txt
index 628a048a..977a5764 100644
--- a/requirements/test.txt
+++ b/requirements/test.txt
@@ -1,4 +1,6 @@
-pytest
+flake8
 freezegun
-coverage
+pytest
 codecov
+coverage
+pytest-env
diff --git a/src/diffpy/pdfgui/control/calculation.py b/src/diffpy/pdfgui/control/calculation.py
index 2cab84a3..13819b81 100644
--- a/src/diffpy/pdfgui/control/calculation.py
+++ b/src/diffpy/pdfgui/control/calculation.py
@@ -19,11 +19,7 @@
 import copy
 import math
 
-from diffpy.pdfgui.control.controlerrors import (
-    ControlConfigError,
-    ControlKeyError,
-    ControlValueError,
-)
+from diffpy.pdfgui.control.controlerrors import ControlConfigError, ControlKeyError, ControlValueError
 from diffpy.pdfgui.control.pdfcomponent import PDFComponent
 from diffpy.pdfgui.utils import pickle_loads, safeCPickleDumps
 
@@ -124,10 +120,7 @@ def setRGrid(self, rmin=None, rstep=None, rmax=None):
 
     def start(self):
         """entry function for calculation"""
-        from diffpy.pdfgui.control.fitting import (
-            getEngineExceptions,
-            handleEngineException,
-        )
+        from diffpy.pdfgui.control.fitting import getEngineExceptions, handleEngineException
 
         try:
             self.calculate()
diff --git a/src/diffpy/pdfgui/control/fitting.py b/src/diffpy/pdfgui/control/fitting.py
index 8e24aed5..0d56df89 100644
--- a/src/diffpy/pdfgui/control/fitting.py
+++ b/src/diffpy/pdfgui/control/fitting.py
@@ -18,11 +18,7 @@
 import threading
 import time
 
-from diffpy.pdfgui.control.controlerrors import (
-    ControlError,
-    ControlStatusError,
-    ControlValueError,
-)
+from diffpy.pdfgui.control.controlerrors import ControlError, ControlStatusError, ControlValueError
 from diffpy.pdfgui.control.organizer import Organizer
 from diffpy.pdfgui.utils import pickle_loads, safeCPickleDumps
 
diff --git a/src/diffpy/pdfgui/control/pdfguicontrol.py b/src/diffpy/pdfgui/control/pdfguicontrol.py
index 15632a0d..c6619417 100644
--- a/src/diffpy/pdfgui/control/pdfguicontrol.py
+++ b/src/diffpy/pdfgui/control/pdfguicontrol.py
@@ -24,11 +24,7 @@
 import six.moves.cPickle as pickle
 
 from diffpy.pdfgui.control.calculation import Calculation
-from diffpy.pdfgui.control.controlerrors import (
-    ControlError,
-    ControlFileError,
-    ControlTypeError,
-)
+from diffpy.pdfgui.control.controlerrors import ControlError, ControlFileError, ControlTypeError
 from diffpy.pdfgui.control.fitdataset import FitDataSet
 from diffpy.pdfgui.control.fitstructure import FitStructure
 from diffpy.pdfgui.control.fitting import Fitting
diff --git a/src/diffpy/pdfgui/tests/conftest.py b/src/diffpy/pdfgui/tests/conftest.py
new file mode 100644
index 00000000..e3b63139
--- /dev/null
+++ b/src/diffpy/pdfgui/tests/conftest.py
@@ -0,0 +1,19 @@
+import json
+from pathlib import Path
+
+import pytest
+
+
+@pytest.fixture
+def user_filesystem(tmp_path):
+    base_dir = Path(tmp_path)
+    home_dir = base_dir / "home_dir"
+    home_dir.mkdir(parents=True, exist_ok=True)
+    cwd_dir = base_dir / "cwd_dir"
+    cwd_dir.mkdir(parents=True, exist_ok=True)
+
+    home_config_data = {"username": "home_username", "email": "home@email.com"}
+    with open(home_dir / "diffpyconfig.json", "w") as f:
+        json.dump(home_config_data, f)
+
+    yield tmp_path
diff --git a/src/diffpy/pdfgui/tests/testphaseconfigurepanel.py b/src/diffpy/pdfgui/tests/testphaseconfigurepanel.py
index 5f41f64e..acc01ec6 100644
--- a/src/diffpy/pdfgui/tests/testphaseconfigurepanel.py
+++ b/src/diffpy/pdfgui/tests/testphaseconfigurepanel.py
@@ -23,13 +23,7 @@
 
 from diffpy.pdfgui.gui.mainframe import MainFrame
 from diffpy.pdfgui.gui.phaseconfigurepanel import PhaseConfigurePanel
-from diffpy.pdfgui.tests.testutils import (
-    GUITestCase,
-    clickcell,
-    datafile,
-    overrideclipboard,
-    tooltiptext,
-)
+from diffpy.pdfgui.tests.testutils import GUITestCase, clickcell, datafile, overrideclipboard, tooltiptext
 
 # ----------------------------------------------------------------------------