|
| 1 | +import contextlib |
| 2 | +from typing import Optional |
| 3 | + |
| 4 | +import pandas as pd |
| 5 | +import solara |
| 6 | + |
| 7 | +with contextlib.suppress(ImportError): |
| 8 | + import altair as alt |
| 9 | + |
| 10 | +@solara.component |
| 11 | +def SpaceAltair(model, agent_portrayal, dependencies: Optional[list[any]] = None): |
| 12 | + space = getattr(model, "grid", None) |
| 13 | + if space is None: |
| 14 | + # Sometimes the space is defined as model.space instead of model.grid |
| 15 | + space = model.space |
| 16 | + chart = _draw_grid(space, agent_portrayal) |
| 17 | + solara.FigureAltair(chart) |
| 18 | + |
| 19 | +# _draw_grid is derived from |
| 20 | +# https://github.com/Princeton-CDH/simulating-risk/blob/907c290e12c97b28aa9ce9c80ea7fc52a4f280ae/simulatingrisk/hawkdove/server.py#L114-L171 |
| 21 | +# Copyright 2023 The Center for Digital Humanities of Princeton |
| 22 | +# |
| 23 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
| 24 | +# you may not use this file except in compliance with the License. |
| 25 | +# You may obtain a copy of the License at |
| 26 | +# |
| 27 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 28 | +# |
| 29 | +# Unless required by applicable law or agreed to in writing, software |
| 30 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 31 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 32 | +# See the License for the specific language governing permissions and |
| 33 | +# limitations under the License. |
| 34 | +def _draw_grid(space, agent_portrayal): |
| 35 | + def portray(g): |
| 36 | + all_agent_data = [] |
| 37 | + for content, (x, y) in space.coord_iter(): |
| 38 | + if not content: |
| 39 | + continue |
| 40 | + if not hasattr(content, "__iter__"): |
| 41 | + # Is a single grid |
| 42 | + content = [content] |
| 43 | + for agent in content: |
| 44 | + # use all data from agent portrayal, and add x,y coordinates |
| 45 | + agent_data = agent_portrayal(agent) |
| 46 | + agent_data["x"] = x |
| 47 | + agent_data["y"] = y |
| 48 | + all_agent_data.append(agent_data) |
| 49 | + return all_agent_data |
| 50 | + |
| 51 | + all_agent_data = portray(space) |
| 52 | + df = pd.DataFrame(all_agent_data) |
| 53 | + chart = ( |
| 54 | + alt.Chart(df) |
| 55 | + .mark_point(filled=True) |
| 56 | + .encode( |
| 57 | + # no x-axis label |
| 58 | + x=alt.X("x", axis=None), |
| 59 | + # no y-axis label |
| 60 | + y=alt.Y("y", axis=None), |
| 61 | + size=alt.Size("size"), |
| 62 | + color=alt.Color("color"), |
| 63 | + ) |
| 64 | + # .configure_view(strokeOpacity=0) # hide grid/chart lines |
| 65 | + ) |
| 66 | + return chart |
0 commit comments