Repository: networkx/networkx

Issue:
Problem with spiral layout with `equidistant=True`
`nx.spiral_layout` has an `equidistant` kwarg that is False by default. According to the docstring parameter description, this is supposed to enforce that the laid out nodes are all equidistant from one another when True. However, the iterative implementation is such that the node in the first iteration is handled differently than all the rest, resulting in the following behavior:

### Current Behavior

```python
>>> G = nx.path_graph(5)
>>> nx.draw(G, pos=nx.spiral_layout(G, equidistant=True))
```

![fi](https://user-images.githubusercontent.com/1268991/144682663-1655099a-b524-4cfc-a101-68f2ef97865a.png)

### Expected Behavior

The "first" node should (presumably) also be equidistant from it's neighbor

### Environment
Python version: Python 3.9.7
NetworkX version: 2.7rc1.dev0 (766becc1)

### Additional context

`spiral_layout` was added in #3534

Discussion:
anutosh491: This is my first code related pr for `networkx` , I've contributed to documentation before. I contribute to `sympy` which is a Cas library on a daily basis where we are expected to explain the fix in detail , hence the long description above haha ! 

I wish to contribute to `networkx `regularly in the future hence will try to get myself habituated with the workflow as soon as possible. I wanted to commit a test too but wasn't sure of it . Would something like this do ?
```
--- a/networkx/drawing/tests/test_layout.py
+++ b/networkx/drawing/tests/test_layout.py
@@ -371,6 +371,15 @@ class TestLayout:
             distances_equidistant[1:], distances_equidistant[-1], atol=0.01
         )

+    @pytest.mark.mpl_image_compare
+    def test_paramter_equidistant_for_spiral_layout():
+        import matplotlib.pyplot as plt
+        fig = plt.figure()
+        G = nx.path_graph(5)
+        pos = nx.spiral_layout(G, equidistant=True)
+        nx.draw(G, pos=pos)
+        return fig
+
```
anutosh491: Also as mentioned in the issue reported above @dschult pointed out that some documentation would also be good for showing the change , will try to address that in the next commit ! thanks 

Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index eb85c36c4..d56391ba8 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -84,6 +84,7 @@ jobs:
             source venv/bin/activate
             pip install --upgrade pip wheel setuptools
             pip install -r requirements/default.txt -r requirements/test.txt
+            pip install pytest-mpl  # NOTE: specified here to avoid confusing conda
             pip list
 
       - run:
diff --git a/networkx/convert_matrix.py b/networkx/convert_matrix.py
index c38762d31..2ccaf01a8 100644
--- a/networkx/convert_matrix.py
+++ b/networkx/convert_matrix.py
@@ -1,21 +1,24 @@
 """Functions to convert NetworkX graphs to and from common data containers
-like numpy arrays, scipy sparse matrices, and pandas DataFrames.
+like numpy arrays, scipy sparse arrays, and pandas DataFrames.
 
 The preferred way of converting data to a NetworkX graph is through the
-graph constructor.  The constructor calls the to_networkx_graph() function
-which attempts to guess the input type and convert it automatically.
+graph constructor.  The constructor calls the `~networkx.convert.to_networkx_graph`
+function which attempts to guess the input type and convert it automatically.
 
 Examples
 --------
 Create a 10 node random graph from a numpy array
 
 >>> import numpy as np
->>> a = np.random.randint(0, 2, size=(10, 10))
->>> D = nx.DiGraph(a)
+>>> rng = np.random.default_rng()
+>>> a = rng.integers(low=0, high=2, size=(10, 10))
+>>> DG = nx.from_numpy_array(a, create_using=nx.DiGraph)
 
-or equivalently
+or equivalently:
 
->>> D = nx.to_networkx_graph(a, create_using=nx.DiGraph)
+>>> DG = nx.DiGraph(a)
+
+which calls `from_numpy_array` internally based on the type of ``a``.
 
 See Also
 --------
diff --git a/networkx/drawing/layout.py b/networkx/drawing/layout.py
index 1aa9b0e53..b4946c71a 100644
--- a/networkx/drawing/layout.py
+++ b/networkx/drawing/layout.py
@@ -957,14 +957,17 @@ def spiral_layout(G, scale=1, center=None, dim=2, resolution=0.35, equidistant=F
         Scale factor for positions.
     center : array-like or None
         Coordinate pair around which to center the layout.
-    dim : int
+    dim : int, default=2
         Dimension of layout, currently only dim=2 is supported.
         Other dimension values result in a ValueError.
-    resolution : float
+    resolution : float, default=0.35
         The compactness of the spiral layout returned.
         Lower values result in more compressed spiral layouts.
-    equidistant : bool
-        If True, nodes will be plotted equidistant from each other.
+    equidistant : bool, default=False
+        If True, nodes will be positioned equidistant from each other
+        by decreasing angle further from center.
+        If False, nodes will be positioned at equal angles
+        from each other by increasing separation further from center.
 
     Returns
     -------
@@ -1003,6 +1006,7 @@ def spiral_layout(G, scale=1, center=None, dim=2, resolution=0.35, equidistant=F
         chord = 1
         step = 0.5
         theta = resolution
+        theta += chord / (step * theta)
         for _ in range(len(G)):
             r = step * theta
             theta += chord / r
diff --git a/requirements/developer.txt b/requirements/developer.txt
index 152a28bac..057e25ee5 100644
--- a/requirements/developer.txt
+++ b/requirements/developer.txt
@@ -1,4 +1,4 @@
-black~=22.1
+black==22.1
 pyupgrade>=2.31
 pre-commit>=2.17
 mypy>=0.931
diff --git a/requirements/doc.txt b/requirements/doc.txt
index 81fe4d495..945e31955 100644
--- a/requirements/doc.txt
+++ b/requirements/doc.txt
@@ -1,6 +1,6 @@
-sphinx~=4.4
-pydata-sphinx-theme~=0.8
-sphinx-gallery~=0.10
+sphinx>=4.4
+pydata-sphinx-theme>=0.8
+sphinx-gallery>=0.10
 numpydoc>=1.2
 pillow>=9.0
 nb2plots>=0.6


Test patch:
diff --git a/networkx/drawing/tests/test_layout.py b/networkx/drawing/tests/test_layout.py
index 686188f51..2626c70ac 100644
--- a/networkx/drawing/tests/test_layout.py
+++ b/networkx/drawing/tests/test_layout.py
@@ -371,6 +371,15 @@ class TestLayout:
             distances_equidistant[1:], distances_equidistant[-1], atol=0.01
         )
 
+    def test_spiral_layout_equidistant(self):
+        G = nx.path_graph(10)
+        pos = nx.spiral_layout(G, equidistant=True)
+        # Extract individual node positions as an array
+        p = np.array(list(pos.values()))
+        # Elementwise-distance between node positions
+        dist = np.linalg.norm(p[1:] - p[:-1], axis=1)
+        assert np.allclose(np.diff(dist), 0, atol=1e-3)
+
     def test_rescale_layout_dict(self):
         G = nx.empty_graph()
         vpos = nx.random_layout(G, center=(1, 1))
diff --git a/requirements/test.txt b/requirements/test.txt
index 5e623e78c..0c7996171 100644
--- a/requirements/test.txt
+++ b/requirements/test.txt
@@ -1,4 +1,3 @@
 pytest>=7.0
 pytest-cov>=3.0
-pytest-mpl>=0.14; platform_python_implementation!='PyPy' and python_version<='3.10'
 codecov>=2.1