6
6
7
7
"""
8
8
9
+ import contextlib
9
10
import itertools
10
11
import math
11
12
import warnings
@@ -61,10 +62,19 @@ def collect_agent_data(
61
62
zorder: default zorder
62
63
63
64
agent_portrayal should return a dict, limited to size (size of marker), color (color of marker), zorder (z-order),
64
- and marker (marker style)
65
+ marker (marker style), alpha, linewidths, and edgecolors
65
66
66
67
"""
67
- arguments = {"s" : [], "c" : [], "marker" : [], "zorder" : [], "loc" : []}
68
+ arguments = {
69
+ "s" : [],
70
+ "c" : [],
71
+ "marker" : [],
72
+ "zorder" : [],
73
+ "loc" : [],
74
+ "alpha" : [],
75
+ "edgecolors" : [],
76
+ "linewidths" : [],
77
+ }
68
78
69
79
for agent in space .agents :
70
80
portray = agent_portrayal (agent )
@@ -78,6 +88,10 @@ def collect_agent_data(
78
88
arguments ["marker" ].append (portray .pop ("marker" , marker ))
79
89
arguments ["zorder" ].append (portray .pop ("zorder" , zorder ))
80
90
91
+ for entry in ["alpha" , "edgecolors" , "linewidths" ]:
92
+ with contextlib .suppress (KeyError ):
93
+ arguments [entry ].append (portray .pop (entry ))
94
+
81
95
if len (portray ) > 0 :
82
96
ignored_fields = list (portray .keys ())
83
97
msg = ", " .join (ignored_fields )
@@ -110,24 +124,32 @@ def draw_space(
110
124
Returns the Axes object with the plot drawn onto it.
111
125
112
126
``agent_portrayal`` is called with an agent and should return a dict. Valid fields in this dict are "color",
113
- "size", "marker", and "zorder". Other field are ignored and will result in a user warning.
127
+ "size", "marker", "zorder", alpha, linewidths, and edgecolors . Other field are ignored and will result in a user warning.
114
128
115
129
"""
116
130
if ax is None :
117
131
fig , ax = plt .subplots ()
118
132
119
133
# https://stackoverflow.com/questions/67524641/convert-multiple-isinstance-checks-to-structural-pattern-matching
120
134
match space :
121
- case mesa .space ._Grid () | OrthogonalMooreGrid () | OrthogonalVonNeumannGrid ():
122
- draw_orthogonal_grid (space , agent_portrayal , ax = ax , ** space_drawing_kwargs )
135
+ # order matters here given the class structure of old-style grid spaces
123
136
case HexSingleGrid () | HexMultiGrid () | mesa .experimental .cell_space .HexGrid ():
124
137
draw_hex_grid (space , agent_portrayal , ax = ax , ** space_drawing_kwargs )
138
+ case (
139
+ mesa .space .SingleGrid ()
140
+ | OrthogonalMooreGrid ()
141
+ | OrthogonalVonNeumannGrid ()
142
+ | mesa .space .MultiGrid ()
143
+ ):
144
+ draw_orthogonal_grid (space , agent_portrayal , ax = ax , ** space_drawing_kwargs )
125
145
case mesa .space .NetworkGrid () | mesa .experimental .cell_space .Network ():
126
146
draw_network (space , agent_portrayal , ax = ax , ** space_drawing_kwargs )
127
147
case mesa .space .ContinuousSpace ():
128
148
draw_continuous_space (space , agent_portrayal , ax = ax )
129
149
case VoronoiGrid ():
130
150
draw_voronoi_grid (space , agent_portrayal , ax = ax )
151
+ case _:
152
+ raise ValueError (f"Unknown space type: { type (space )} " )
131
153
132
154
if propertylayer_portrayal :
133
155
draw_property_layers (space , propertylayer_portrayal , ax = ax )
@@ -543,11 +565,24 @@ def _scatter(ax: Axes, arguments, **kwargs):
543
565
marker = arguments .pop ("marker" )
544
566
zorder = arguments .pop ("zorder" )
545
567
568
+ # we check if edgecolor, linewidth, and alpha are specified
569
+ # at the agent level, if not, we remove them from the arguments dict
570
+ # and fallback to the default value in ax.scatter / use what is passed via **kwargs
571
+ for entry in ["edgecolors" , "linewidths" , "alpha" ]:
572
+ if len (arguments [entry ]) == 0 :
573
+ arguments .pop (entry )
574
+ else :
575
+ if entry in kwargs :
576
+ raise ValueError (
577
+ f"{ entry } is specified in agent portrayal and via plotting kwargs, you can only use one or the other"
578
+ )
579
+
546
580
for mark in np .unique (marker ):
547
581
mark_mask = marker == mark
548
582
for z_order in np .unique (zorder ):
549
583
zorder_mask = z_order == zorder
550
584
logical = mark_mask & zorder_mask
585
+
551
586
ax .scatter (
552
587
x [logical ],
553
588
y [logical ],
0 commit comments