Repository: StingraySoftware/stingray

Issue:
Document how to access or download the tutorial notebooks
### Description of the Issue

The majority of narrative documentation is in the form of notebooks. These are presented in the user-documentation as html-rendered notebooks, but actually downloading a notebook to run is not obvious.

### Suggestions regarding the Issue

Somewhere prominent and early in the documentation, there should be clear instructions on how to download the notebook corresponding to a documentation page. 

One simple way would be to instruct users to navigate to: https://github.com/StingraySoftware/stingray/tree/main/docs, then click the `notebooks @ <something>` link and then click through to find the desired notebook.

The fact that the notebooks are a submodule can be a further source of confusion if someone has cloned the repo locally. The magic commands to fetch the submodule might be useful. I think this works but I'm never sure!
```
git submodule init
git submodule update
```


Discussion:

Patch:
diff --git a/.gitignore b/.gitignore
index 752e21dc..fedd87d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,7 @@ __pycache__
 
 # Other generated files
 */version.py
+*/_version.py
 */cython_version.py
 htmlcov
 .coverage
diff --git a/CREDITS.rst b/CREDITS.rst
index fdf0187e..7e1cf3f7 100644
--- a/CREDITS.rst
+++ b/CREDITS.rst
@@ -2,8 +2,8 @@
 Authors and Credits
 *******************
 
-Stingray Project Coordinators
-=============================
+Stingray Founders
+=================
 
 * Matteo Bachetti
 * Paul Balm
@@ -11,9 +11,18 @@ Stingray Project Coordinators
 * Simone Migliari
 * Abigail Stevens
 
+Current Maintainers
+===================
+* Matteo Bachetti
+* Daniela Huppenkothen
+* Guglielmo Mastroserio
+* John Swinbank
+* Matteo Lucchini
+
 Contributors
 ============
 
+* Johannes Buchner
 * Riccardo Campana
 * Meg Davis
 * Amogh Desai
@@ -22,10 +31,16 @@ Contributors
 * Nick Gorgone
 * Anurag Hota
 * Ajit Jadhav
+* Gaurav Joshi
 * Usman Khan
 * Sambhav Kothari
+* Abhinav Kumar
 * Sandeep Kumar
+* Utkarsh Kumar
+* Eleonora Veronica Lai
+* luzpaz
 * Max Mahlke
+* Kartik Mandar
 * Evandro Martinez Ribeiro
 * Himanshu Mishra
 * Sashank Mishra
@@ -33,6 +48,7 @@ Contributors
 * paopaofi
 * parkma99
 * Francesco Pisanu
+* Sri Guru Datta Pisupati
 * Rashmi Raj
 * Haroon Rashid
 * Achilles Rasquinha
@@ -41,17 +57,11 @@ Contributors
 * Swapnil Sharma
 * Brigitta Sipocz
 * Arfon Smith
-* John Swinbank
 * Akash Tandon
 * Marta Mancosu
 * Mihir Tripathi
 * Ricardo Vallés Blanco
 * Dhruv Vats
-* Guglielmo Mastroserio
-* Sri Guru Datta Pisupati
-* Gaurav Joshi
-* luzpaz
-* Abhinav Kumar
 
 If you have contributed to Stingray and your name is missing,
 please send an email to the coordinators, or
diff --git a/MANIFEST.in b/MANIFEST.in
index 41e68f97..44708fea 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,6 +1,5 @@
 include README.rst
 include CHANGES.rst
-include setup.cfg
 include LICENSE.rst
 include pyproject.toml
 
diff --git a/README.rst b/README.rst
index a814048e..ce4c0bbd 100644
--- a/README.rst
+++ b/README.rst
@@ -2,7 +2,15 @@
 Stingray
 ========
 
-|Build Status Master| |Docs| |Slack| |joss| |doi| |Coverage Status Master| |GitHub release|
+.. csv-table::
+   :header: "Usage", "Release", "Development", "Community"
+   :widths: 50, 50, 50, 50
+
+   |Python version|, |GitHub release|, |Build Status Master|, |Slack|
+   |Docs|, |joss|, |Repo status|,  " "
+   |License|, |doi|, |Coverage Status Master|, " "
+
+
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 X-Ray Spectral Timing Made Easy
@@ -66,9 +74,11 @@ If you find this package useful in your research, please provide appropriate ack
 Copyright & Licensing
 ---------------------
 
-All content © 2015 The Authors.
+All content © 2024 The Authors.
 The code is distributed under the MIT license; see `LICENSE.rst <LICENSE.rst>`_ for details.
 
+.. |Python version| image:: https://img.shields.io/python/required-version-toml?tomlFilePath=https://raw.githubusercontent.com/stingraysoftware/stingray/main/pyproject.toml
+   :alt: Python Version from PEP 621 TOML
 .. |Build Status Master| image:: https://github.com/StingraySoftware/stingray/workflows/CI%20Tests/badge.svg
    :target: https://github.com/StingraySoftware/stingray/actions/
 .. |Docs| image:: https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat
@@ -83,6 +93,12 @@ The code is distributed under the MIT license; see `LICENSE.rst <LICENSE.rst>`_
    :target: https://doi.org/10.21105/joss.01393
 .. |doi| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.1490116.svg
    :target: https://doi.org/10.5281/zenodo.1490116
+.. |Repo status| image:: https://www.repostatus.org/badges/latest/active.svg
+   :alt: Project Status: Active – The project has reached a stable, usable state and is being actively developed.
+   :target: https://www.repostatus.org/#active
+.. |License| image:: https://img.shields.io/badge/License-MIT-yellow.svg
+   :target: https://opensource.org/licenses/MIT
+
 .. _Astropy: https://www.github.com/astropy/astropy
 .. _Issues: https://www.github.com/stingraysoftware/stingray/issues
 .. _Issue: https://www.github.com/stingraysoftware/stingray/issues
diff --git a/docs/changes/842.trivial.rst b/docs/changes/842.trivial.rst
new file mode 100644
index 00000000..97849048
--- /dev/null
+++ b/docs/changes/842.trivial.rst
@@ -0,0 +1,1 @@
+Moved configuration to pyproject.toml as recommended by PEP 621
diff --git a/docs/conf.py b/docs/conf.py
index dc0ced1b..a3866d87 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -37,11 +37,17 @@ except ImportError:
     print("ERROR: the documentation requires the sphinx-astropy package to be installed")
     sys.exit(1)
 
-# Get configuration information from setup.cfg
-conf = ConfigParser()
+try:
+    import tomllib
+except ImportError:
+    # Help users on older alphas
+    import tomli as tomllib
+from pathlib import Path
+
+# Grab minversion from pyproject.toml
+with (Path(__file__).parents[1] / "pyproject.toml").open("rb") as f:
+    pyproject = tomllib.load(f)
 
-conf.read([os.path.join(os.path.dirname(__file__), "..", "setup.cfg")])
-setup_cfg = dict(conf.items("metadata"))
 
 # -- General configuration ----------------------------------------------------
 
@@ -67,16 +73,16 @@ rst_epilog += """
 # -- Project information ------------------------------------------------------
 
 # This does not *have* to match the package name, but typically does
-project = setup_cfg["name"]
-author = setup_cfg["author"]
-copyright = "{0}, {1}".format(datetime.datetime.now().year, setup_cfg["author"])
+project = pyproject["project"]["name"]
+author = ",".join(pyproject["project"]["authors"][0]["name"])
+copyright = "{0}, {1}".format(datetime.datetime.now().year, pyproject["project"]["authors"])
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 
-import_module(setup_cfg["name"])
-package = sys.modules[setup_cfg["name"]]
+import_module(pyproject["project"]["name"])
+package = sys.modules[pyproject["project"]["name"]]
 
 # The short X.Y version.
 version = package.__version__.split("-", 1)[0]
@@ -157,17 +163,13 @@ linkcheck_ignore = [r"https://doi.org/"]
 
 # -- Options for the edit_on_github extension ---------------------------------
 
-if setup_cfg.get("edit_on_github").lower() == "true":
-    extensions += ["sphinx_astropy.ext.edit_on_github"]
-
-    edit_on_github_project = setup_cfg["github_project"]
-    edit_on_github_branch = "master"
+edit_on_github_branch = "main"
 
-    edit_on_github_source_root = ""
-    edit_on_github_doc_root = "docs"
 
 # -- Resolving issue number to links in changelog -----------------------------
-github_issues_url = "https://github.com/{0}/issues/".format(setup_cfg["github_project"])
+github_issues_url = "https://github.com/{0}/issues/".format(
+    pyproject["project"]["urls"]["repository"]
+)
 
 # -- Configuration for nbsphinx -----------------------------------------------
 # disable notebook execution
diff --git a/docs/index.rst b/docs/index.rst
index 2169dd1d..14034087 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -97,7 +97,6 @@ A **minimal installation** of Stingray requires the following dependencies:
 In **typical** uses, requiring input/output, caching of results, and faster processing, we **recommend the following dependencies**:
 
 + numba (**highly** recommended)
-+ tbb (needed by numba)
 + tqdm (for progress bars, always useful)
 + pyfftw (for the fastest FFT in the West)
 + h5py (for input/output)
@@ -125,6 +124,8 @@ For the Gaussian Process modeling in `stingray.modeling.gpmodeling`, you'll need
 + etils
 + typing_extensions
 
+For the Bexvar calculations in `stingray.bexvar` and `stingray.lightcurve`, you'll need `UltraNest <https://johannesbuchner.github.io/UltraNest/index.html>`_.
+
 Most of these are installed via ``pip``, but if you have an Nvidia GPU available, you'll want to take special care
 following the installation instructions for jax and tensorflow(-probability) in order to enable GPU support and
 take advantage of those speed-ups.
@@ -271,6 +272,9 @@ the stingray source directory.
 Using Stingray
 ===============
 
+The documentation below is built on top of Jupyter notebooks that can be run locally.
+The easiest way to retrieve the notebooks is by `cloning the notebooks repository <https://github.com/StingraySoftware/notebooks>`_ and browsing the directories, which are conveniently divided by topic.
+
 A Spectral timing exploration
 -----------------------------
 
diff --git a/pyproject.toml b/pyproject.toml
index 802df28a..d7fa7ec0 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,11 +1,190 @@
-[build-system]
+[project]
+name = "stingray"
+dynamic = [
+    "version"
+]
+description = "Time Series Methods For Astronomical X-ray Data"
+readme = "README.rst"
+authors = [
+    { name = "Stingray Developers", email = "spectraltiming-stingray@googlegroups.com" }
+]
+license = { text = "MIT" }
+requires-python = ">=3.8"
+classifiers = [
+    "Intended Audience :: Science/Research",
+    "License :: OSI Approved :: MIT License",
+    "Operating System :: OS Independent",
+    "Programming Language :: Python :: 3",
+    "Programming Language :: Python :: Implementation :: CPython",
+    "Topic :: Scientific/Engineering :: Astronomy",
+    "Topic :: Scientific/Engineering :: Physics",
+]
+keywords = [
+    "astronomy",
+    "astrophysics",
+    "time series",
+    "X-ray",
+    "data analysis",
+    "black holes",
+    "neutron stars",
+    "pulsars",
+    "space",
+    "science",
+]
+dependencies = [
+    "numpy>=1.17",
+    "astropy>=4.0",
+    "setuptools",
+    "setuptools_scm",
+    "scipy>=1.1.0",
+    "matplotlib>=3.0,!=3.4.00",
+]
+
+
+[project.optional-dependencies]
+test = [
+    "pytest",
+    "pytest-astropy",
+]
+test_all = [
+    "astropy[test]",  # installs the [test] dependencies
+    "objgraph",
+    "ipython>=4.2",
+    "coverage[toml]",
+    "skyfield>=1.20",
+    "sgp4>=2.3",
+]
+recommended = [
+    "numba",
+    "h5py",
+    "pyyaml",
+    "statsmodels",
+    "pyfftw",
+]
+all = [
+    "stingray[recommended]",  # installs the [recommended] dependencies
+    "jplephem",
+    "emcee>=3.0.0",
+    "corner",
+    "lightkurve",
+    "pint-pulsar",
+    "numcodecs",
+    "xarray",
+    "pyarrow",
+    "pandas",
+    "ultranest",
+    "jax",
+    "tinygp",
+    "jaxns",
+    "etils",
+    "tensorflow_probability",
+    "typing_extensions",
+]
+docs = [
+    "tomli>=1.1.0; python_version < '3.11'",
+    "jinja2==3.1.3",
+    "docutils",
+    "sphinx-astropy",
+    "nbsphinx>=0.8.3,!=0.8.8",
+    "nbconvert<7.14",
+    "pandoc",
+    "ipython",
+    "towncrier<22.12.0",
+]
+
+[project.urls]
+homepage = "https://stingray.science"
+documentation = "https://docs.stingray.science"
+repository = "https://github.com/stingraysoftware/stingray"
 
+[build-system]
 requires = ["setuptools",
             "setuptools_scm",
             "wheel"]
 
 build-backend = 'setuptools.build_meta'
 
+[tool.setuptools]
+include-package-data = true
+license-files = ["LICENSE.rst"]
+
+[tool.setuptools.packages.find]
+include = ["stingray*"]
+exclude = ["stingray._dev*"]
+namespaces = false
+
+[tool.setuptools.package-data]
+"*" = [
+    "data/*",
+    "*.fits",
+    "*.evt",
+    "*.rmf",
+    "*.txt",
+]
+"stingray" = ["datasets/*"]
+
+[tool.setuptools_scm]
+write_to = "stingray/_version.py"
+
+[tool.pytest.ini_options]
+minversion = 7.0
+testpaths = [
+    "stingray",
+    "docs",
+]
+norecursedirs = [
+    "docs[\\/]_build",
+    "docs[\\/]generated",
+]
+astropy_header = true
+doctest_plus = "enabled"
+text_file_format = "rst"
+remote_data_strict = true
+addopts = "--color=yes --doctest-rst"
+filterwarnings = [
+    "error",
+    "ignore:Unrecognized parfile line:UserWarning",
+    "ignore:.*:ResourceWarning",
+    "ignore:distutils Version classes are deprecated.:DeprecationWarning",
+    "ignore:unclosed .ssl.SSLSocket:ResourceWarning",
+    "ignore:.*set self.value directly:DeprecationWarning",
+    "ignore:On Windows, the size of an integer is 32 bits:UserWarning",
+    "ignore:.*Number of segments used in averaging.*:UserWarning",
+    "ignore:.*:astropy.units.core.UnitsWarning",
+    "ignore:.*cannot be added to FITS Header:astropy.utils.exceptions.AstropyUserWarning",
+    "ignore:Numba not installed:UserWarning",
+    "ignore:More than 20 figures have been opened.:RuntimeWarning",
+    "ignore:This platform does not support:RuntimeWarning",
+    "ignore:Some error bars in the Averaged:UserWarning",
+    "ignore:n_ave is below 30:UserWarning",
+    "ignore:pyfftw not installed:UserWarning",
+    "ignore:SIMON says. Errorbars on cross spectra are not thoroughly tested.:UserWarning",
+    "ignore:SIMON says. Stingray only uses poisson err_dist at the moment.:UserWarning",
+    "ignore:SIMON says. Looks like your lightcurve:UserWarning",
+    "ignore:Matplotlib is currently using agg, which is a:UserWarning",
+    "ignore:Using or importing the ABCs from 'collections':DeprecationWarning",
+    "ignore:unclosed file:ResourceWarning",
+    "ignore:numpy.ufunc size changed:RuntimeWarning",
+    "ignore:numpy.ndarray size changed:RuntimeWarning",
+    "ignore:invalid value encountered:RuntimeWarning",
+    "ignore:divide by zero encountered:RuntimeWarning",
+    "ignore:underflow encountered:RuntimeWarning",
+    "ignore:overflow encountered:RuntimeWarning",
+    "ignore:table path was not set via the path= argument; using default path:UserWarning",
+    "ignore:Large Datasets may not be processed efficiently:UserWarning",
+    "ignore:.*is a deprecated alias for:DeprecationWarning",
+    "ignore:.*HIERARCH card will be created.*:",
+    "ignore:.*FigureCanvasAgg is non-interactive.*:UserWarning",
+    "ignore:.*jax.* deprecated:DeprecationWarning:",
+    "ignore:.*Converting to lower precision.*:UserWarning",
+    "ignore:.*is_categorical_dtype is deprecated.*:DeprecationWarning",
+    "ignore:.*datetime.datetime.utcfromtimestamp.*:DeprecationWarning",
+    "ignore:.*__array_wrap__ must accept context and return_scalar arguments:DeprecationWarning",
+    "ignore:.*Pyarrow:",
+    "ignore:.*Creating an ndarray from ragged nested sequences:",
+
+]
+
 [tool.towncrier]
     package = "stingray"
     filename = "CHANGELOG.rst"
@@ -51,3 +230,49 @@ build-backend = 'setuptools.build_meta'
 
 [tool.black]
 line-length = 100
+
+[tool.coverage]
+
+    [tool.coverage.run]
+        omit = [
+            "stingray/_astropy_init*",
+            "stingray/conftest.py",
+            "stingray/*setup_package*",
+            "stingray/tests/*",
+            "stingray/*/tests/*",
+            "stingray/extern/*",
+            "stingray/version*",
+            "*/stingray/_astropy_init*",
+            "*/stingray/conftest.py",
+            "*/stingray/*setup_package*",
+            "*/stingray/tests/*",
+            "*/stingray/*/tests/*",
+            "*/stingray/extern/*",
+            "*/stingray/version*",
+        ]
+
+    [tool.coverage.report]
+        exclude_lines = [
+            # Have to re-enable the standard pragma
+            "pragma: no cover",
+            # Don't complain about packages we have installed
+            "except ImportError",
+            # Don't complain if tests don't hit defensive assertion code:
+            "raise AssertionError",
+            "raise NotImplementedError",
+            # Don't complain about script hooks
+            "'def main(.*):'",
+            # Ignore branches that don't pertain to this version of Python
+            "pragma: py{ignore_python_version}",
+            # Don't complain about IPython completion helper
+            "def _ipython_key_completions_",
+        ]
+
+[tool.flake8]
+max-line-length = 100
+exclude = ".git,__pycache__,docs/source/conf.py,old,build,dist,*.egg-info"
+extend-ignore = "E203, W503, W605"
+
+[tool.pycodestyle]
+max-line-length = 100
+exclude = ".git,__pycache__,docs/source/conf.py,old,build,dist,*.egg-info"
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 9a480a5e..00000000
--- a/setup.cfg
+++ /dev/null
@@ -1,165 +0,0 @@
-[metadata]
-name = stingray
-author = Stingray Developers
-author_email = spectraltiming-stingray@googlegroups.com
-license = MIT
-license_file = LICENSE.rst
-url = https://docs.stingray.science
-description = Time Series Methods For Astronomical X-ray Data
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-edit_on_github = False
-github_project = StingraySoftware/stingray
-
-[options]
-zip_safe = False
-packages = find:
-python_requires = >=3.8
-setup_requires = setuptools_scm
-install_requires =
-    setuptools
-    astropy>=4.0
-    numpy>=1.17.0
-    scipy>=1.1.0
-; Matplotlib 3.4.0 is incompatible with Astropy
-    matplotlib>=3.0,!=3.4.0
-
-[options.entry_points]
-console_scripts =
-    astropy-package-template-example = packagename.example_mod:main
-
-[options.extras_require]
-all =
-    tbb
-    numba
-    jplephem
-    emcee>=3.0.0
-    statsmodels
-    corner
-    lightkurve
-    pyfftw
-    h5py
-    pint-pulsar
-    numcodecs
-    pyyaml
-    xarray
-    pyarrow
-    pandas
-    ultranest
-    jax
-    tinygp
-    jaxns
-    etils
-    tensorflow_probability
-    typing_extensions
-test =
-    pytest
-    pytest-astropy
-docs =
-    jinja2==3.1.3
-    docutils
-    sphinx-astropy
-    nbsphinx>=0.8.3,!=0.8.8
-    nbconvert<7.14
-    pandoc
-    ipython
-    towncrier<22.12.0
-
-[options.package_data]
-stingray.tests = data/*
-stingray.pulse.tests = data/*
-stingray = datasets/*
-* = *.fits, *.evt, *.rmf, *.txt
-
-[tool:pytest]
-testpaths = "stingray" "docs"
-doctest_plus = enabled
-text_file_format = rst
-addopts = --doctest-rst
-filterwarnings =
-    error
-    ignore:Unrecognized parfile line:UserWarning
-    ignore:.*:ResourceWarning
-    ignore:distutils Version classes are deprecated.:DeprecationWarning
-    ignore:unclosed .ssl.SSLSocket:ResourceWarning
-    ignore:.*set self.value directly:DeprecationWarning
-    ignore:On Windows, the size of an integer is 32 bits:UserWarning
-    ignore:.*Number of segments used in averaging.*:UserWarning
-    ignore:.*:astropy.units.core.UnitsWarning
-    ignore:.*cannot be added to FITS Header:astropy.utils.exceptions.AstropyUserWarning
-    ignore:Numba not installed:UserWarning
-    ignore:More than 20 figures have been opened.:RuntimeWarning
-    ignore:This platform does not support:RuntimeWarning
-    ignore:Some error bars in the Averaged:UserWarning
-    ignore:n_ave is below 30:UserWarning
-    ignore:pyfftw not installed:UserWarning
-    ignore:SIMON says. Errorbars on cross spectra are not thoroughly tested.:UserWarning
-    ignore:SIMON says. Stingray only uses poisson err_dist at the moment.:UserWarning
-    ignore:SIMON says. Looks like your lightcurve:UserWarning
-    ignore:Matplotlib is currently using agg, which is a:UserWarning
-    ignore:Using or importing the ABCs from 'collections':DeprecationWarning
-    ignore:unclosed file:ResourceWarning
-    ignore:numpy.ufunc size changed:RuntimeWarning
-    ignore:numpy.ndarray size changed:RuntimeWarning
-    ignore:invalid value encountered:RuntimeWarning
-    ignore:divide by zero encountered:RuntimeWarning
-    ignore:underflow encountered:RuntimeWarning
-    ignore:overflow encountered:RuntimeWarning
-    ignore:table path was not set via the path= argument; using default path:UserWarning
-    ignore:Large Datasets may not be processed efficiently:UserWarning
-    ignore:.*is a deprecated alias for:DeprecationWarning
-    ignore:.*HIERARCH card will be created.*:
-    ignore:.*FigureCanvasAgg is non-interactive.*:UserWarning
-    ignore:.*jax.* deprecated:DeprecationWarning:
-    ignore:.*Converting to lower precision.*:UserWarning
-    ignore:.*is_categorical_dtype is deprecated.*:DeprecationWarning
-    ignore:.*datetime.datetime.utcfromtimestamp.*:DeprecationWarning
-    ignore:.*__array_wrap__ must accept context and return_scalar arguments:DeprecationWarning
-    ignore:.*Pyarrow:
-    ignore:.*Creating an ndarray from ragged nested sequences:
-
-;addopts = --disable-warnings
-
-[coverage:run]
-omit =
-    stingray/_astropy_init*
-    stingray/conftest.py
-    stingray/*setup_package*
-    stingray/tests/*
-    stingray/*/tests/*
-    stingray/extern/*
-    stingray/version*
-    */stingray/_astropy_init*
-    */stingray/conftest.py
-    */stingray/*setup_package*
-    */stingray/tests/*
-    */stingray/*/tests/*
-    */stingray/extern/*
-    */stingray/version*
-
-[coverage:report]
-exclude_lines =
-    # Have to re-enable the standard pragma
-    pragma: no cover
-    # Don't complain about packages we have installed
-    except ImportError
-    # Don't complain if tests don't hit assertions
-    raise AssertionError
-    raise NotImplementedError
-    # Don't complain about script hooks
-    def main\(.*\):
-    # Ignore branches that don't pertain to this version of Python
-    pragma: py{ignore_python_version}
-    # Don't complain about IPython completion helper
-    def _ipython_key_completions_
-
-
-[pycodestyle]
-max-line-length = 100
-exclude = extern,*parsetab.py,*lextab.py,test_*.py,__*.py
-
-
-[flake8]
-max-line-length = 100
-exclude = extern,*parsetab.py,*lextab.py,test_*.py,__*.py
-extend-ignore = E203, W503, W605
diff --git a/stingray/crosscorrelation.py b/stingray/crosscorrelation.py
index dbb3716c..f1a74f1c 100644
--- a/stingray/crosscorrelation.py
+++ b/stingray/crosscorrelation.py
@@ -246,6 +246,11 @@ class CrossCorrelation(object):
                     self._make_corr(self.lc1, self.lc2)
 
         self.n = len(self.corr)
+        n1 = n2 = self.n
+        if self.lc1 is not None:
+            n1 = np.size(self.lc1.counts)
+        if self.lc2 is not None:
+            n2 = np.size(self.lc2.counts)
 
         if self.cross is not None:
             # Obtains correlation lags if a cross spectrum object is given
@@ -257,9 +262,7 @@ class CrossCorrelation(object):
             # Obtains correlation lags if two light curves are provided
             # Correlation against all possible lags, positive as well as negative lags are stored
             # signal.correlation_lags() method uses SciPy versions >= 1.6.1
-            x_lags = signal.correlation_lags(
-                np.size(self.lc1.counts), np.size(self.lc2.counts), self.mode
-            )
+            x_lags = signal.correlation_lags(n1, n2, self.mode)
 
         self.time_lags = x_lags * self.dt
         # time_shift is the time lag for max. correlation
diff --git a/stingray/modeling/parameterestimation.py b/stingray/modeling/parameterestimation.py
index c17d7a1f..050d20bb 100644
--- a/stingray/modeling/parameterestimation.py
+++ b/stingray/modeling/parameterestimation.py
@@ -452,7 +452,7 @@ class ParameterEstimation(object):
                         args=args,
                         tol=1.0e-10,
                         bounds=bounds,
-                        **scipy_optimize_options
+                        **scipy_optimize_options,
                     )
 
                 else:
@@ -462,7 +462,7 @@ class ParameterEstimation(object):
                         method=self.fitmethod,
                         args=args,
                         tol=1.0e-10,
-                        **scipy_optimize_options
+                        **scipy_optimize_options,
                     )
 
             # if max_post is False, then do a Maximum Likelihood Fit
@@ -477,7 +477,7 @@ class ParameterEstimation(object):
                             args=args,
                             tol=1.0e-10,
                             bounds=bounds,
-                            **scipy_optimize_options
+                            **scipy_optimize_options,
                         )
                     else:
                         opt = scipy.optimize.minimize(
@@ -486,7 +486,7 @@ class ParameterEstimation(object):
                             method=self.fitmethod,
                             args=args,
                             tol=1.0e-10,
-                            **scipy_optimize_options
+                            **scipy_optimize_options,
                         )
 
                 elif isinstance(lpost, LogLikelihood):
@@ -501,7 +501,7 @@ class ParameterEstimation(object):
                             args=args,
                             tol=1.0e-10,
                             # bounds=bounds,
-                            **scipy_optimize_options
+                            **scipy_optimize_options,
                         )
 
                     else:
@@ -511,7 +511,7 @@ class ParameterEstimation(object):
                             method=self.fitmethod,
                             args=args,
                             tol=1.0e-10,
-                            **scipy_optimize_options
+                            **scipy_optimize_options,
                         )
 
             funcval = opt.fun
diff --git a/stingray/power_colors.py b/stingray/power_colors.py
index 48c7e196..2a56dd85 100644
--- a/stingray/power_colors.py
+++ b/stingray/power_colors.py
@@ -151,7 +151,7 @@ def _trace_states(ax, configuration=DEFAULT_COLOR_CONFIGURATION, **kwargs):
                 ls=None,
                 lw=0,
                 color=color,
-                **kwargs
+                **kwargs,
             )
             ax.add_patch(t1)
             next_angle += 5.0
diff --git a/stingray/pulse/overlapandsave/ols.py b/stingray/pulse/overlapandsave/ols.py
index d6ac909b..eaef2cc1 100644
--- a/stingray/pulse/overlapandsave/ols.py
+++ b/stingray/pulse/overlapandsave/ols.py
@@ -286,7 +286,7 @@ def olsStep(
     rfftn=None,
     irfftn=None,
     mode="constant",
-    **kwargs
+    **kwargs,
 ):
     """Implements a single step of the overlap-save algorithm
 
@@ -469,6 +469,6 @@ def ols(x, h, size=None, nfft=None, out=None, rfftn=None, irfftn=None, mode="con
             rfftn=rfftn,
             irfftn=irfftn,
             mode=mode,
-            **kwargs
+            **kwargs,
         )
     return out
diff --git a/stingray/pulse/search.py b/stingray/pulse/search.py
index 1906cb15..5c6ca21e 100644
--- a/stingray/pulse/search.py
+++ b/stingray/pulse/search.py
@@ -510,7 +510,7 @@ def phaseogram(
     plot=False,
     phaseogram_ax=None,
     weights=None,
-    **plot_kwargs
+    **plot_kwargs,
 ):
     """
     Calculate and plot the phaseogram of a pulsar observation.
diff --git a/tox.ini b/tox.ini
index f30cd9cc..c4640ba7 100644
--- a/tox.ini
+++ b/tox.ini
@@ -55,7 +55,7 @@ deps =
     devdeps: pyerfa>=0.0.dev
     devdeps: git+https://github.com/nanograv/pint.git#egg=pint-pulsar
 
-# The following indicates which extras_require from setup.cfg will be installed
+# The following indicates which extras_require from pyproject.toml will be installed
 extras =
     test
     alldeps: all
@@ -66,7 +66,7 @@ commands =
 
     pip freeze
     !cov: pytest --pyargs stingray {toxinidir}/docs {posargs}
-    cov: pytest --pyargs stingray {toxinidir}/docs --cov stingray --cov-config={toxinidir}/setup.cfg {posargs}
+    cov: pytest --pyargs stingray {toxinidir}/docs --cov stingray --cov-config={toxinidir}/pyproject.toml {posargs}
     cov: coverage xml -o {toxinidir}/coverage.xml
 
 [testenv:build_docs]


Test patch:
diff --git a/stingray/tests/test_crosscorrelation.py b/stingray/tests/test_crosscorrelation.py
index b1862322..6545bc27 100644
--- a/stingray/tests/test_crosscorrelation.py
+++ b/stingray/tests/test_crosscorrelation.py
@@ -63,6 +63,11 @@ class TestCrossCorrelation(object):
         assert cr.n is None
         assert cr.auto is False
 
+    def test_almost_empty_works(self):
+        cs = CrossCorrelation()
+        cs.corr = np.array([660, 1790, 3026, 4019, 5164, 6647, 8105, 7023, 6012, 5162])
+        _ = cs.cal_timeshift(dt=0.5)
+
     def test_empty_cross_correlation_with_dt(self):
         cr = CrossCorrelation()
         with pytest.raises(StingrayError):