Coverage for .tox/p312/lib/python3.10/site-packages/scicom/historicalletters/interface.py: 0%

1"""Define the solara interface to run and control the HistoricalLetters model."""

2 from __future__ import annotations

3

4 from typing import TYPE_CHECKING

5

6 if TYPE_CHECKING:

7 import mesa

8

9 import contextily as cx

10 import matplotlib.pyplot as plt

11 import numpy as np

12 import solara

13 from matplotlib import colors

14 from mesa.experimental.jupyter_viz import JupyterViz

15

16 from scicom.historicalletters.agents import (

17 RegionAgent,

18 SenderAgent,

19)

20 from scicom.historicalletters.model import HistoricalLetters

21 from scicom.historicalletters.server import (

22 topic_draw,

23)

24

25 model_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}

71

72 def 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)

81

82

83 def 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")

90

91

92 def _draw_layers(space: mesa.Space, space_ax: plt.Axes) -> None:

93 """Draw layers."""

94

95

96 def _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 )

102

103 region_agents.plot(column="averageTopic", alpha=0.5, ax=space_ax)

104

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)

110

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)

114

115

116

117 page = 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)