Allow PropertyLayerStyle instance in draw_propertylayer
Summary
This PR improves the PropertyLayer visualization API by allowing users to pass a PropertyLayerStyle instance directly to draw_propertylayer. This removes the need to wrap the style in a function for simple, uniform styling cases.
issue #2923
Background / Problem
Previously, even the simplest styling required a callable, like:
def propertylayer_portrayal(layer): return PropertyLayerStyle(colormap="viridis", colorbar=True)
For cases where the style is the same across all layers, this wrapper didn't add any value and made the API feel unnecessarily verbose. This PR addresses feedback suggesting the API should accept both:
-
a direct PropertyLayerStyle instance (for uniform styling)
-
a callable (for conditional or per-layer styling)
This makes the API more intuitive and aligns with common Python patterns.
Implementation
Changes in mesa/visualization/space_renderer.py:
-
Updated draw_propertylayer to detect when propertylayer_portrayal is a PropertyLayerStyle instance.
-
When an instance is provided, it's automatically wrapped in a small lambda so the existing backend logic continues to work without modification.
-
Updated type hints to reflect that the argument may now be either a callable or a style instance.
Testing
-
Added a dedicated test case: test_property_layer_style_instance in tests/test_space_renderer.py to confirm that passing a PropertyLayerStyle instance works correctly.
-
Ran the existing test suite (pytest tests/test_space_renderer.py) to ensure no regressions β all 16 tests passed.
Additional Notes
This change reduces boilerplate for the common simple-use scenario while still supporting the more flexible function-based approach for complex styling. It should make the API easier and more pleasant to use without breaking any existing behavior.
Performance benchmarks:
| Model | Size | Init time [95% CI] | Run time [95% CI] |
|---|---|---|---|
| BoltzmannWealth | small | π΅ -0.5% [-1.1%, +0.1%] | π΅ -1.5% [-1.7%, -1.4%] |
| BoltzmannWealth | large | π΅ -1.3% [-17.5%, +17.1%] | π΅ -1.3% [-2.6%, -0.1%] |
| Schelling | small | π΅ -0.2% [-0.3%, -0.0%] | π΅ -1.2% [-1.4%, -1.1%] |
| Schelling | large | π΅ -0.2% [-17.5%, +21.6%] | π΅ +12.1% [-3.3%, +37.5%] |
| WolfSheep | small | π΅ -0.6% [-0.9%, -0.3%] | π΅ +0.1% [-0.1%, +0.3%] |
| WolfSheep | large | π΅ -17.1% [-40.4%, -0.7%] | π΅ +10.2% [-12.5%, +38.6%] |
| BoidFlockers | small | π΅ -0.7% [-1.6%, +0.1%] | π΅ -0.8% [-1.0%, -0.6%] |
| BoidFlockers | large | π΅ -0.4% [-1.0%, +0.2%] | π΅ -0.4% [-0.6%, -0.3%] |
@EwoutH Please review my PR.
@ShreyasN707 Thanks for this PR! The changes are good and clean, but this PR interferes with #2893 and I personally would like this feature in our new API so in my opinion it's best for #2893 to be merged first, what do you say @EwoutH?
Yes, very fair, letβs get #2893 in first.
@Sahil-Chhoker Sounds good to me! Letβs get #2893 merged first. Once thatβs in, Iβll rebase this PR and fix up anything that needs adjusting.
@ShreyasN707 sorry for the delay, #2893 is merged now so can you update this PR accordingly.
@ShreyasN707 sorry for the delay, #2893 is merged now so can you update this PR accordingly.
@Sahil-Chhoker sure! Will do it by EOD.
@Sahil-Chhoker @EwoutH Please review the changes.