Repository: projectmesa/mesa
Pull request #1830 (2023-10-07 08:37:34)

solara: Implement drawer for continuous space

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/projectmesa/mesa/pull/1830?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa) Report
Attention: `30 lines` in your changes are missing coverage. Please review.
> Comparison is base [(`d888a8c`)](https://app.codecov.io/gh/projectmesa/mesa/commit/d888a8cab397286c8fb3b496f1af8e79bb1b844d?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa) 81.38% compared to head [(`71705a4`)](https://app.codecov.io/gh/projectmesa/mesa/pull/1830?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa) 78.96%.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #1830      +/-   ##
==========================================
- Coverage   81.38%   78.96%   -2.43%     
==========================================
  Files          15       15              
  Lines         881      908      +27     
  Branches      186      193       +7     
==========================================
  Hits          717      717              
- Misses        141      168      +27     
  Partials       23       23              
```


| [Files](https://app.codecov.io/gh/projectmesa/mesa/pull/1830?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa) | Coverage Δ | |
|---|---|---|
| [mesa/experimental/jupyter\_viz.py](https://app.codecov.io/gh/projectmesa/mesa/pull/1830?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa#diff-bWVzYS9leHBlcmltZW50YWwvanVweXRlcl92aXoucHk=) | `29.37% <6.25%> (-5.29%)` | :arrow_down: |


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/projectmesa/mesa/pull/1830?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa).


Patch:
diff --git a/mesa/experimental/jupyter_viz.py b/mesa/experimental/jupyter_viz.py
index d3bc9c0d..3408ba11 100644
--- a/mesa/experimental/jupyter_viz.py
+++ b/mesa/experimental/jupyter_viz.py
@@ -235,6 +235,23 @@ def UserInputs(user_params, on_change=None):
 
 
 def make_space(model, agent_portrayal):
+    space_fig = Figure()
+    space_ax = space_fig.subplots()
+    space = getattr(model, "grid", None)
+    if space is None:
+        # Sometimes the space is defined as model.space instead of model.grid
+        space = model.space
+    if isinstance(space, mesa.space.NetworkGrid):
+        _draw_network_grid(space, space_ax, agent_portrayal)
+    elif isinstance(space, mesa.space.ContinuousSpace):
+        _draw_continuous_space(space, space_ax, agent_portrayal)
+    else:
+        _draw_grid(space, space_ax, agent_portrayal)
+    space_ax.set_axis_off()
+    solara.FigureMatplotlib(space_fig, format="png")
+
+
+def _draw_grid(space, space_ax, agent_portrayal):
     def portray(g):
         x = []
         y = []
@@ -263,18 +280,11 @@ def make_space(model, agent_portrayal):
             out["c"] = c
         return out
 
-    space_fig = Figure()
-    space_ax = space_fig.subplots()
-    if isinstance(model.grid, mesa.space.NetworkGrid):
-        _draw_network_grid(model, space_ax, agent_portrayal)
-    else:
-        space_ax.scatter(**portray(model.grid))
-    space_ax.set_axis_off()
-    solara.FigureMatplotlib(space_fig, format="png")
+    space_ax.scatter(**portray(space))
 
 
-def _draw_network_grid(model, space_ax, agent_portrayal):
-    graph = model.grid.G
+def _draw_network_grid(space, space_ax, agent_portrayal):
+    graph = space.G
     pos = nx.spring_layout(graph, seed=0)
     nx.draw(
         graph,
@@ -284,6 +294,31 @@ def _draw_network_grid(model, space_ax, agent_portrayal):
     )
 
 
+def _draw_continuous_space(space, space_ax, agent_portrayal):
+    def portray(space):
+        x = []
+        y = []
+        s = []  # size
+        c = []  # color
+        for agent in space._agent_to_index:
+            data = agent_portrayal(agent)
+            _x, _y = agent.pos
+            x.append(_x)
+            y.append(_y)
+            if "size" in data:
+                s.append(data["size"])
+            if "color" in data:
+                c.append(data["color"])
+        out = {"x": x, "y": y}
+        if len(s) > 0:
+            out["s"] = s
+        if len(c) > 0:
+            out["c"] = c
+        return out
+
+    space_ax.scatter(**portray(space))
+
+
 def make_plot(model, measure):
     fig = Figure()
     ax = fig.subplots()
diff --git a/mesa/space.py b/mesa/space.py
index 286f63c8..6ed7c096 100644
--- a/mesa/space.py
+++ b/mesa/space.py
@@ -68,10 +68,9 @@ def accept_tuple_argument(wrapped_function: F) -> F:
     single-item list rather than forcing user to do it."""
 
     def wrapper(grid_instance, positions) -> Any:
-        if isinstance(positions, tuple) and len(positions) == 2:
-            return wrapped_function(grid_instance, [positions])
-        else:
-            return wrapped_function(grid_instance, positions)
+        if len(positions) == 2 and not isinstance(positions[0], tuple):
+            positions = [positions]
+        return wrapped_function(grid_instance, positions)
 
     return cast(F, wrapper)
 


Test patch:
diff --git a/tests/test_space.py b/tests/test_space.py
index 8691dc45..f8f2cc94 100644
--- a/tests/test_space.py
+++ b/tests/test_space.py
@@ -327,6 +327,28 @@ class TestSingleGrid(unittest.TestCase):
         assert self.space[initial_pos[0]][initial_pos[1]] is None
         assert self.space[final_pos[0]][final_pos[1]] == _agent
 
+    def test_iter_cell_list_contents(self):
+        """
+        Test neighborhood retrieval
+        """
+        cell_list_1 = list(self.space.iter_cell_list_contents(TEST_AGENTS_GRID[0]))
+        assert len(cell_list_1) == 1
+
+        cell_list_2 = list(
+            self.space.iter_cell_list_contents(
+                (TEST_AGENTS_GRID[0], TEST_AGENTS_GRID[1])
+            )
+        )
+        assert len(cell_list_2) == 2
+
+        cell_list_3 = list(self.space.iter_cell_list_contents(tuple(TEST_AGENTS_GRID)))
+        assert len(cell_list_3) == 3
+
+        cell_list_4 = list(
+            self.space.iter_cell_list_contents((TEST_AGENTS_GRID[0], (0, 0)))
+        )
+        assert len(cell_list_4) == 1
+
 
 class TestSingleNetworkGrid(unittest.TestCase):
     GRAPH_SIZE = 10