1+ """Altair-based renderer for Mesa spaces.
2+
3+ This module provides an Altair-based renderer for visualizing Mesa model spaces,
4+ agents, and property layers with interactive charting capabilities.
5+ """
6+
17import warnings
28from collections .abc import Callable
39from dataclasses import fields
@@ -201,12 +207,21 @@ def collect_agent_data(
201207
202208 return final_data
203209
204-
205-
206210 def draw_agents (
207211 self , arguments , chart_width : int = 450 , chart_height : int = 350 , ** kwargs
208212 ):
209- """Draw agents using Altair backend."""
213+ """Draw agents using Altair backend.
214+
215+ Args:
216+ arguments: Dictionary containing agent data arrays.
217+ chart_width: Width of the chart.
218+ chart_height: Height of the chart.
219+ **kwargs: Additional keyword arguments for customization.
220+ Checkout respective `SpaceDrawer` class on details how to pass **kwargs.
221+
222+ Returns:
223+ alt.Chart: The Altair chart representing the agents, or None if no agents.
224+ """
210225 if arguments ["loc" ].size == 0 :
211226 return None
212227
@@ -219,7 +234,8 @@ def draw_agents(
219234 "size" : arguments ["size" ][i ],
220235 "shape" : arguments ["shape" ][i ],
221236 "opacity" : arguments ["opacity" ][i ],
222- "strokeWidth" : arguments ["strokeWidth" ][i ] / 10 , # Scale for continuous domain
237+ "strokeWidth" : arguments ["strokeWidth" ][i ]
238+ / 10 , # Scale for continuous domain
223239 "original_color" : arguments ["color" ][i ],
224240 }
225241 # Add tooltip data if available
@@ -230,7 +246,11 @@ def draw_agents(
230246 # Determine fill and stroke colors
231247 if arguments ["filled" ][i ]:
232248 record ["viz_fill_color" ] = arguments ["color" ][i ]
233- record ["viz_stroke_color" ] = arguments ["stroke" ][i ] if isinstance (arguments ["stroke" ][i ], str ) else None
249+ record ["viz_stroke_color" ] = (
250+ arguments ["stroke" ][i ]
251+ if isinstance (arguments ["stroke" ][i ], str )
252+ else None
253+ )
234254 else :
235255 record ["viz_fill_color" ] = None
236256 record ["viz_stroke_color" ] = arguments ["color" ][i ]
@@ -240,52 +260,32 @@ def draw_agents(
240260 df = pd .DataFrame (records )
241261
242262 # Ensure all columns that should be numeric are, handling potential Nones
243- numeric_cols = ['x' , 'y' , ' size' , ' opacity' , ' strokeWidth' , ' original_color' ]
263+ numeric_cols = ["x" , "y" , " size" , " opacity" , " strokeWidth" , " original_color" ]
244264 for col in numeric_cols :
245265 if col in df .columns :
246- df [col ] = pd .to_numeric (df [col ], errors = 'coerce' )
247-
266+ df [col ] = pd .to_numeric (df [col ], errors = "coerce" )
248267
249268 # Get tooltip keys from the first valid record
250269 tooltip_list = ["x" , "y" ]
251- # This is the corrected line:
252270 if any (t is not None for t in arguments ["tooltip" ]):
253- first_valid_tooltip = next ((t for t in arguments ["tooltip" ] if t ), None )
254- if first_valid_tooltip :
255- tooltip_list .extend (first_valid_tooltip .keys ())
271+ first_valid_tooltip = next (
272+ (t for t in arguments ["tooltip" ] if t is not None ), None
273+ )
274+ if first_valid_tooltip is not None :
275+ tooltip_list .extend (first_valid_tooltip .keys ())
256276
257277 # Extract additional parameters from kwargs
258278 title = kwargs .pop ("title" , "" )
259279 xlabel = kwargs .pop ("xlabel" , "" )
260280 ylabel = kwargs .pop ("ylabel" , "" )
261- legend_title = kwargs .pop ("legend_title" , "Color" )
262-
263- # Handle custom colormapping
264- cmap = kwargs .pop ("cmap" , "viridis" )
265- vmin = kwargs .pop ("vmin" , None )
266- vmax = kwargs .pop ("vmax" , None )
281+ # FIXME: Add more parameters to kwargs
267282
268283 color_is_numeric = pd .api .types .is_numeric_dtype (df ["original_color" ])
269- if color_is_numeric :
270- color_min = vmin if vmin is not None else df ["original_color" ].min ()
271- color_max = vmax if vmax is not None else df ["original_color" ].max ()
272-
273- fill_encoding = alt .Fill (
274- "original_color:Q" ,
275- scale = alt .Scale (scheme = cmap , domain = [color_min , color_max ]),
276- legend = alt .Legend (
277- title = legend_title ,
278- orient = "right" ,
279- type = "gradient" ,
280- gradientLength = 200 ,
281- ),
282- )
283- else :
284- fill_encoding = alt .Fill (
285- "viz_fill_color:N" ,
286- scale = None ,
287- title = "Color" ,
288- )
284+ fill_encoding = (
285+ alt .Fill ("original_color:Q" )
286+ if color_is_numeric
287+ else alt .Fill ("viz_fill_color:N" , scale = None , title = "Color" )
288+ )
289289
290290 # Determine space dimensions
291291 xmin , xmax , ymin , ymax = self .space_drawer .get_viz_limits ()
@@ -316,10 +316,16 @@ def draw_agents(
316316 ),
317317 title = "Shape" ,
318318 ),
319- opacity = alt .Opacity ("opacity:Q" , title = "Opacity" , scale = alt .Scale (domain = [0 , 1 ], range = [0 , 1 ])),
319+ opacity = alt .Opacity (
320+ "opacity:Q" ,
321+ title = "Opacity" ,
322+ scale = alt .Scale (domain = [0 , 1 ], range = [0 , 1 ]),
323+ ),
320324 fill = fill_encoding ,
321325 stroke = alt .Stroke ("viz_stroke_color:N" , scale = None ),
322- strokeWidth = alt .StrokeWidth ("strokeWidth:Q" , scale = alt .Scale (domain = [0 , 1 ])),
326+ strokeWidth = alt .StrokeWidth (
327+ "strokeWidth:Q" , scale = alt .Scale (domain = [0 , 1 ])
328+ ),
323329 tooltip = tooltip_list ,
324330 )
325331 .properties (title = title , width = chart_width , height = chart_height )
@@ -431,4 +437,4 @@ def draw_propertylayer(
431437 main_charts .append (current_chart )
432438
433439 base = alt .layer (* main_charts ).resolve_scale (color = "independent" )
434- return base
440+ return base
0 commit comments