Coverage for .tox/p311/lib/python3.10/site-packages/scicom/historicalletters/interface.py: 0%
39 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-26 13:41 +0200
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-26 13:41 +0200
1"""Define the solara interface to run and control the HistoricalLetters model."""
2from __future__ import annotations
4from typing import TYPE_CHECKING
6if TYPE_CHECKING:
7 import mesa
9import contextily as cx
10import matplotlib.pyplot as plt
11import numpy as np
12import solara
13from matplotlib import colors
14from mesa.experimental.jupyter_viz import JupyterViz
16from scicom.historicalletters.agents import (
17 RegionAgent,
18 SenderAgent,
19)
20from scicom.historicalletters.model import HistoricalLetters
21from scicom.historicalletters.server import (
22 topic_draw,
23)
25model_params = {
26 "population": {
27 "type": "SliderInt",
28 "value": 50,
29 "label": "Number of agents",
30 "min": 10,
31 "max": 200,
32 "step": 10,
33 },
34 "useSocialNetwork": {
35 "type": "Select",
36 "value": False,
37 "label": "Choose if an initial social network exists.",
38 "values": [True, False],
39 },
40 "useActivation": {
41 "type": "Select",
42 "value": False,
43 "label": "Choose if agents have heterogeneous acitvations.",
44 "values": [True, False],
45 },
46 "similarityThreshold": {
47 "type": "SliderFloat",
48 "value": 0.5,
49 "label": "Threshold for similarity of topics.",
50 "min": 0.0,
51 "max": 1.0,
52 "step": 0.1,
53 },
54 "moveRange": {
55 "type": "SliderFloat",
56 "value": 0.05,
57 "label": "Range defining targets for movements.",
58 "min": 0.0,
59 "max": 0.5,
60 "step": 0.1,
61 },
62 "letterRange": {
63 "type": "SliderFloat",
64 "value": 0.2,
65 "label": "Range for sending letters.",
66 "min": 0.0,
67 "max": 0.5,
68 "step": 0.1,
69 },
70}
72def has_main_topic(data:dict) -> tuple:
73 """Return weighted average topics of agents in region."""
74 if len(data) > 0:
75 topics = [y[0] for x, y in data.items()]
76 total = [y[1] for x, y in data.items()]
77 weight = [x / sum(total) for x in total] if sum(total) > 0 else [1 / len(topics)] * len(topics)
78 mixed_colors = np.sum([np.multiply(weight[i], topics[i]) for i in range(len(topics))], axis=0)
79 return np.subtract((1, 1, 1), mixed_colors)
80 return (0.5, 0.5, 0.5)
83def make_geospace(model:mesa.Model, agent_portrayal:dict | None = None) -> solara.FigureMatplotlib:
84 """Create the geo figure."""
85 space_fig, space_ax = plt.subplots()
86 # _draw_layers(model.space, space_ax)
87 _draw_agents(model.space, space_ax)
88 space_ax.set_axis_off()
89 solara.FigureMatplotlib(space_fig, format="png")
92def _draw_layers(space:mesa.Space, space_ax:plt.Axes) -> None:
93 """Draw layers."""
96def _draw_agents(space:mesa.Space, space_ax:plt.Axes) -> plt.Axes:
97 """Draw the Region and SenderAgents."""
98 region_agents = space.get_agents_as_GeoDataFrame(agent_cls=RegionAgent)
99 region_agents["averageTopic"] = region_agents["senders_in_region"].apply(
100 lambda x: colors.to_hex(has_main_topic(x)),
101 )
103 region_agents.plot(column="averageTopic", alpha=0.5, ax=space_ax)
105 person_agents = space.get_agents_as_GeoDataFrame(agent_cls=SenderAgent)
106 person_agents["color"] = person_agents["topicVec"].apply(
107 lambda x: colors.to_hex(x),
108 )
109 person_agents.plot(column="color", markersize=1, ax=space_ax)
111 space_ax.set_xlim([-1e6, 4e6])
112 space_ax.set_ylim([4.3e6, 9.3e6])
113 cx.add_basemap(space_ax, source=cx.providers.CartoDB.Positron)
117page = JupyterViz(
118 HistoricalLetters,
119 model_params,
120 measures=["Movements", "Clusters", "Letters"],
121 name="Historical Letters ABM",
122 agent_portrayal=topic_draw,
123 space_drawer=make_geospace,
124)