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

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

2from __future__ import annotations 

3 

4from typing import TYPE_CHECKING 

5 

6if TYPE_CHECKING: 

7 import mesa 

8 

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 

15 

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) 

24 

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} 

71 

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) 

81 

82 

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

90 

91 

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

93 """Draw layers.""" 

94 

95 

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 ) 

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 

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)