Mesa 2.4.0__py3-none-any.whl → 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of Mesa might be problematic. Click here for more details.
- mesa/__init__.py +3 -5
- mesa/agent.py +105 -92
- mesa/batchrunner.py +55 -31
- mesa/datacollection.py +10 -14
- mesa/examples/README.md +37 -0
- mesa/examples/__init__.py +21 -0
- mesa/examples/advanced/epstein_civil_violence/Epstein Civil Violence.ipynb +116 -0
- mesa/examples/advanced/epstein_civil_violence/Readme.md +34 -0
- mesa/examples/advanced/epstein_civil_violence/__init__.py +0 -0
- mesa/examples/advanced/epstein_civil_violence/agents.py +164 -0
- mesa/examples/advanced/epstein_civil_violence/app.py +73 -0
- mesa/examples/advanced/epstein_civil_violence/model.py +114 -0
- mesa/examples/advanced/pd_grid/Readme.md +43 -0
- mesa/examples/advanced/pd_grid/__init__.py +0 -0
- mesa/examples/advanced/pd_grid/agents.py +50 -0
- mesa/examples/advanced/pd_grid/analysis.ipynb +228 -0
- mesa/examples/advanced/pd_grid/app.py +54 -0
- mesa/examples/advanced/pd_grid/model.py +71 -0
- mesa/examples/advanced/sugarscape_g1mt/Readme.md +64 -0
- mesa/examples/advanced/sugarscape_g1mt/__init__.py +0 -0
- mesa/examples/advanced/sugarscape_g1mt/agents.py +344 -0
- mesa/examples/advanced/sugarscape_g1mt/app.py +62 -0
- mesa/examples/advanced/sugarscape_g1mt/model.py +180 -0
- mesa/examples/advanced/sugarscape_g1mt/sugar-map.txt +50 -0
- mesa/examples/advanced/sugarscape_g1mt/tests.py +69 -0
- mesa/examples/advanced/wolf_sheep/Readme.md +57 -0
- mesa/examples/advanced/wolf_sheep/__init__.py +0 -0
- mesa/examples/advanced/wolf_sheep/agents.py +102 -0
- mesa/examples/advanced/wolf_sheep/app.py +84 -0
- mesa/examples/advanced/wolf_sheep/model.py +137 -0
- mesa/examples/basic/__init__.py +0 -0
- mesa/examples/basic/boid_flockers/Readme.md +22 -0
- mesa/examples/basic/boid_flockers/__init__.py +0 -0
- mesa/examples/basic/boid_flockers/agents.py +71 -0
- mesa/examples/basic/boid_flockers/app.py +58 -0
- mesa/examples/basic/boid_flockers/model.py +69 -0
- mesa/examples/basic/boltzmann_wealth_model/Readme.md +56 -0
- mesa/examples/basic/boltzmann_wealth_model/__init__.py +0 -0
- mesa/examples/basic/boltzmann_wealth_model/agents.py +31 -0
- mesa/examples/basic/boltzmann_wealth_model/app.py +74 -0
- mesa/examples/basic/boltzmann_wealth_model/model.py +43 -0
- mesa/examples/basic/boltzmann_wealth_model/st_app.py +115 -0
- mesa/examples/basic/conways_game_of_life/Readme.md +39 -0
- mesa/examples/basic/conways_game_of_life/__init__.py +0 -0
- mesa/examples/basic/conways_game_of_life/agents.py +47 -0
- mesa/examples/basic/conways_game_of_life/app.py +51 -0
- mesa/examples/basic/conways_game_of_life/model.py +31 -0
- mesa/examples/basic/conways_game_of_life/st_app.py +72 -0
- mesa/examples/basic/schelling/Readme.md +40 -0
- mesa/examples/basic/schelling/__init__.py +0 -0
- mesa/examples/basic/schelling/agents.py +26 -0
- mesa/examples/basic/schelling/analysis.ipynb +205 -0
- mesa/examples/basic/schelling/app.py +42 -0
- mesa/examples/basic/schelling/model.py +59 -0
- mesa/examples/basic/virus_on_network/Readme.md +61 -0
- mesa/examples/basic/virus_on_network/__init__.py +0 -0
- mesa/examples/basic/virus_on_network/agents.py +69 -0
- mesa/examples/basic/virus_on_network/app.py +114 -0
- mesa/examples/basic/virus_on_network/model.py +96 -0
- mesa/experimental/UserParam.py +18 -7
- mesa/experimental/__init__.py +10 -2
- mesa/experimental/cell_space/__init__.py +16 -1
- mesa/experimental/cell_space/cell.py +93 -23
- mesa/experimental/cell_space/cell_agent.py +117 -21
- mesa/experimental/cell_space/cell_collection.py +56 -19
- mesa/experimental/cell_space/discrete_space.py +92 -8
- mesa/experimental/cell_space/grid.py +33 -9
- mesa/experimental/cell_space/network.py +15 -10
- mesa/experimental/cell_space/voronoi.py +257 -0
- mesa/experimental/components/altair.py +11 -2
- mesa/experimental/components/matplotlib.py +132 -26
- mesa/experimental/devs/__init__.py +2 -0
- mesa/experimental/devs/eventlist.py +54 -15
- mesa/experimental/devs/examples/epstein_civil_violence.py +69 -38
- mesa/experimental/devs/examples/wolf_sheep.py +42 -43
- mesa/experimental/devs/simulator.py +57 -16
- mesa/experimental/{jupyter_viz.py → solara_viz.py} +151 -99
- mesa/model.py +136 -78
- mesa/space.py +208 -148
- mesa/time.py +63 -80
- mesa/visualization/__init__.py +25 -6
- mesa/visualization/components/__init__.py +83 -0
- mesa/visualization/components/altair_components.py +188 -0
- mesa/visualization/components/matplotlib_components.py +175 -0
- mesa/visualization/mpl_space_drawing.py +593 -0
- mesa/visualization/solara_viz.py +458 -0
- mesa/visualization/user_param.py +69 -0
- mesa/visualization/utils.py +9 -0
- {mesa-2.4.0.dist-info → mesa-3.0.0.dist-info}/METADATA +62 -17
- mesa-3.0.0.dist-info/RECORD +95 -0
- mesa-3.0.0.dist-info/licenses/LICENSE +202 -0
- mesa-2.4.0.dist-info/licenses/LICENSE → mesa-3.0.0.dist-info/licenses/NOTICE +2 -2
- mesa/cookiecutter-mesa/cookiecutter.json +0 -8
- mesa/cookiecutter-mesa/hooks/post_gen_project.py +0 -11
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/README.md +0 -4
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/run.pytemplate +0 -3
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/setup.pytemplate +0 -11
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/model.pytemplate +0 -60
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/server.pytemplate +0 -36
- mesa/flat/__init__.py +0 -6
- mesa/flat/visualization.py +0 -5
- mesa/main.py +0 -63
- mesa/visualization/ModularVisualization.py +0 -1
- mesa/visualization/TextVisualization.py +0 -1
- mesa/visualization/UserParam.py +0 -1
- mesa/visualization/modules.py +0 -1
- mesa-2.4.0.dist-info/RECORD +0 -45
- /mesa/{cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}} → examples/advanced}/__init__.py +0 -0
- {mesa-2.4.0.dist-info → mesa-3.0.0.dist-info}/WHEEL +0 -0
- {mesa-2.4.0.dist-info → mesa-3.0.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,7 +1,29 @@
|
|
|
1
|
-
|
|
1
|
+
"""Mesa visualization module for creating interactive model visualizations.
|
|
2
|
+
|
|
3
|
+
This module provides components to create browser- and Jupyter notebook-based visualizations of
|
|
4
|
+
Mesa models, allowing users to watch models run step-by-step and interact with model parameters.
|
|
5
|
+
|
|
6
|
+
Key features:
|
|
7
|
+
- SolaraViz: Main component for creating visualizations, supporting grid displays and plots
|
|
8
|
+
- ModelController: Handles model execution controls (step, play, pause, reset)
|
|
9
|
+
- UserInputs: Generates UI elements for adjusting model parameters
|
|
10
|
+
- Card: Renders individual visualization elements (space, measures)
|
|
11
|
+
|
|
12
|
+
The module uses Solara for rendering in Jupyter notebooks or as standalone web applications.
|
|
13
|
+
It supports various types of visualizations including matplotlib plots, agent grids, and
|
|
14
|
+
custom visualization components.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
1. Define an agent_portrayal function to specify how agents should be displayed
|
|
18
|
+
2. Set up model_params to define adjustable parameters
|
|
19
|
+
3. Create a SolaraViz instance with your model, parameters, and desired measures
|
|
20
|
+
4. Display the visualization in a Jupyter notebook or run as a Solara app
|
|
21
|
+
|
|
22
|
+
See the Visualization Tutorial and example models for more details.
|
|
23
|
+
"""
|
|
24
|
+
|
|
2
25
|
import threading
|
|
3
26
|
|
|
4
|
-
import matplotlib.pyplot as plt
|
|
5
27
|
import reacton.ipywidgets as widgets
|
|
6
28
|
import solara
|
|
7
29
|
from solara.alias import rv
|
|
@@ -10,15 +32,26 @@ import mesa.experimental.components.altair as components_altair
|
|
|
10
32
|
import mesa.experimental.components.matplotlib as components_matplotlib
|
|
11
33
|
from mesa.experimental.UserParam import Slider
|
|
12
34
|
|
|
13
|
-
# Avoid interactive backend
|
|
14
|
-
plt.switch_backend("agg")
|
|
15
|
-
|
|
16
35
|
|
|
17
36
|
# TODO: Turn this function into a Solara component once the current_step.value
|
|
18
37
|
# dependency is passed to measure()
|
|
19
38
|
def Card(
|
|
20
39
|
model, measures, agent_portrayal, space_drawer, dependencies, color, layout_type
|
|
21
40
|
):
|
|
41
|
+
"""Create a card component for visualizing model space or measures.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
model: The Mesa model instance
|
|
45
|
+
measures: List of measures to be plotted
|
|
46
|
+
agent_portrayal: Function to define agent appearance
|
|
47
|
+
space_drawer: Method to render agent space
|
|
48
|
+
dependencies: List of dependencies for updating the visualization
|
|
49
|
+
color: Background color of the card
|
|
50
|
+
layout_type: Type of layout (Space or Measure)
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
rv.Card: A card component containing the visualization
|
|
54
|
+
"""
|
|
22
55
|
with rv.Card(
|
|
23
56
|
style_=f"background-color: {color}; width: 100%; height: 100%"
|
|
24
57
|
) as main:
|
|
@@ -35,7 +68,7 @@ def Card(
|
|
|
35
68
|
)
|
|
36
69
|
elif space_drawer:
|
|
37
70
|
# if specified, draw agent space with an alternate renderer
|
|
38
|
-
space_drawer(model, agent_portrayal)
|
|
71
|
+
space_drawer(model, agent_portrayal, dependencies=dependencies)
|
|
39
72
|
elif "Measure" in layout_type:
|
|
40
73
|
rv.CardTitle(children=["Measure"])
|
|
41
74
|
measure = measures[layout_type["Measure"]]
|
|
@@ -50,7 +83,7 @@ def Card(
|
|
|
50
83
|
|
|
51
84
|
|
|
52
85
|
@solara.component
|
|
53
|
-
def
|
|
86
|
+
def SolaraViz(
|
|
54
87
|
model_class,
|
|
55
88
|
model_params,
|
|
56
89
|
measures=None,
|
|
@@ -61,18 +94,20 @@ def JupyterViz(
|
|
|
61
94
|
seed=None,
|
|
62
95
|
):
|
|
63
96
|
"""Initialize a component to visualize a model.
|
|
97
|
+
|
|
64
98
|
Args:
|
|
65
|
-
model_class:
|
|
66
|
-
model_params:
|
|
67
|
-
measures:
|
|
68
|
-
name:
|
|
69
|
-
agent_portrayal:
|
|
70
|
-
|
|
99
|
+
model_class: Class of the model to instantiate
|
|
100
|
+
model_params: Parameters for initializing the model
|
|
101
|
+
measures: List of callables or data attributes to plot
|
|
102
|
+
name: Name for display
|
|
103
|
+
agent_portrayal: Options for rendering agents (dictionary);
|
|
104
|
+
Default drawer supports custom `"size"`, `"color"`, and `"shape"`.
|
|
105
|
+
space_drawer: Method to render the agent space for
|
|
71
106
|
the model; default implementation is the `SpaceMatplotlib` component;
|
|
72
107
|
simulations with no space to visualize should
|
|
73
108
|
specify `space_drawer=False`
|
|
74
|
-
play_interval:
|
|
75
|
-
seed:
|
|
109
|
+
play_interval: Play interval (default: 150)
|
|
110
|
+
seed: The random seed used to initialize the model
|
|
76
111
|
"""
|
|
77
112
|
if name is None:
|
|
78
113
|
name = model_class.__name__
|
|
@@ -88,6 +123,7 @@ def JupyterViz(
|
|
|
88
123
|
|
|
89
124
|
# 2. Set up Model
|
|
90
125
|
def make_model():
|
|
126
|
+
"""Create a new model instance with current parameters and seed."""
|
|
91
127
|
model = model_class.__new__(
|
|
92
128
|
model_class, **model_parameters, seed=reactive_seed.value
|
|
93
129
|
)
|
|
@@ -106,6 +142,7 @@ def JupyterViz(
|
|
|
106
142
|
)
|
|
107
143
|
|
|
108
144
|
def handle_change_model_params(name: str, value: any):
|
|
145
|
+
"""Update model parameters when user input changes."""
|
|
109
146
|
set_model_parameters({**model_parameters, name: value})
|
|
110
147
|
|
|
111
148
|
# 3. Set up UI
|
|
@@ -115,96 +152,71 @@ def JupyterViz(
|
|
|
115
152
|
|
|
116
153
|
# render layout and plot
|
|
117
154
|
def do_reseed():
|
|
155
|
+
"""Update the random seed for the model."""
|
|
118
156
|
reactive_seed.value = model.random.random()
|
|
119
157
|
|
|
120
|
-
|
|
121
|
-
|
|
158
|
+
dependencies = [
|
|
159
|
+
*list(model_parameters.values()),
|
|
160
|
+
current_step.value,
|
|
161
|
+
reactive_seed.value,
|
|
162
|
+
]
|
|
122
163
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
UserInputs(user_params, on_change=handle_change_model_params)
|
|
126
|
-
ModelController(model, play_interval, current_step, reset_counter)
|
|
127
|
-
solara.Markdown(md_text=f"###Step - {current_step}")
|
|
164
|
+
# if space drawer is disabled, do not include it
|
|
165
|
+
layout_types = [{"Space": "default"}] if space_drawer else []
|
|
128
166
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
# if specified, draw agent space with an alternate renderer
|
|
142
|
-
space_drawer(model, agent_portrayal)
|
|
143
|
-
# otherwise, do nothing (do not draw space)
|
|
144
|
-
|
|
145
|
-
# 5. Plots
|
|
146
|
-
if measures:
|
|
147
|
-
for measure in measures:
|
|
148
|
-
if callable(measure):
|
|
149
|
-
# Is a custom object
|
|
150
|
-
measure(model)
|
|
151
|
-
else:
|
|
152
|
-
components_matplotlib.PlotMatplotlib(
|
|
153
|
-
model, measure, dependencies=dependencies
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
def render_in_browser():
|
|
157
|
-
# if space drawer is disabled, do not include it
|
|
158
|
-
layout_types = [{"Space": "default"}] if space_drawer else []
|
|
159
|
-
|
|
160
|
-
if measures:
|
|
161
|
-
layout_types += [{"Measure": elem} for elem in range(len(measures))]
|
|
162
|
-
|
|
163
|
-
grid_layout_initial = make_initial_grid_layout(layout_types=layout_types)
|
|
164
|
-
grid_layout, set_grid_layout = solara.use_state(grid_layout_initial)
|
|
165
|
-
|
|
166
|
-
with solara.Sidebar():
|
|
167
|
-
with solara.Card("Controls", margin=1, elevation=2):
|
|
168
|
-
solara.InputText(
|
|
169
|
-
label="Seed",
|
|
170
|
-
value=reactive_seed,
|
|
171
|
-
continuous_update=True,
|
|
172
|
-
)
|
|
173
|
-
UserInputs(user_params, on_change=handle_change_model_params)
|
|
174
|
-
ModelController(model, play_interval, current_step, reset_counter)
|
|
175
|
-
solara.Button(label="Reseed", color="primary", on_click=do_reseed)
|
|
176
|
-
with solara.Card("Information", margin=1, elevation=2):
|
|
177
|
-
solara.Markdown(md_text=f"Step - {current_step}")
|
|
178
|
-
|
|
179
|
-
items = [
|
|
180
|
-
Card(
|
|
181
|
-
model,
|
|
182
|
-
measures,
|
|
183
|
-
agent_portrayal,
|
|
184
|
-
space_drawer,
|
|
185
|
-
dependencies,
|
|
186
|
-
color="white",
|
|
187
|
-
layout_type=layout_types[i],
|
|
167
|
+
if measures:
|
|
168
|
+
layout_types += [{"Measure": elem} for elem in range(len(measures))]
|
|
169
|
+
|
|
170
|
+
grid_layout_initial = make_initial_grid_layout(layout_types=layout_types)
|
|
171
|
+
grid_layout, set_grid_layout = solara.use_state(grid_layout_initial)
|
|
172
|
+
|
|
173
|
+
with solara.Sidebar():
|
|
174
|
+
with solara.Card("Controls", margin=1, elevation=2):
|
|
175
|
+
solara.InputText(
|
|
176
|
+
label="Seed",
|
|
177
|
+
value=reactive_seed,
|
|
178
|
+
continuous_update=True,
|
|
188
179
|
)
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
180
|
+
UserInputs(user_params, on_change=handle_change_model_params)
|
|
181
|
+
ModelController(model, play_interval, current_step, reset_counter)
|
|
182
|
+
solara.Button(label="Reseed", color="primary", on_click=do_reseed)
|
|
183
|
+
with solara.Card("Information", margin=1, elevation=2):
|
|
184
|
+
solara.Markdown(md_text=f"Step - {current_step}")
|
|
185
|
+
|
|
186
|
+
items = [
|
|
187
|
+
Card(
|
|
188
|
+
model,
|
|
189
|
+
measures,
|
|
190
|
+
agent_portrayal,
|
|
191
|
+
space_drawer,
|
|
192
|
+
dependencies,
|
|
193
|
+
color="white",
|
|
194
|
+
layout_type=layout_types[i],
|
|
197
195
|
)
|
|
196
|
+
for i in range(len(layout_types))
|
|
197
|
+
]
|
|
198
|
+
solara.GridDraggable(
|
|
199
|
+
items=items,
|
|
200
|
+
grid_layout=grid_layout,
|
|
201
|
+
resizable=True,
|
|
202
|
+
draggable=True,
|
|
203
|
+
on_grid_layout=set_grid_layout,
|
|
204
|
+
)
|
|
198
205
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
render_in_jupyter()
|
|
202
|
-
else:
|
|
203
|
-
render_in_browser()
|
|
206
|
+
|
|
207
|
+
JupyterViz = SolaraViz
|
|
204
208
|
|
|
205
209
|
|
|
206
210
|
@solara.component
|
|
207
211
|
def ModelController(model, play_interval, current_step, reset_counter):
|
|
212
|
+
"""Create controls for model execution (step, play, pause, reset).
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
model: The model being visualized
|
|
216
|
+
play_interval: Interval between steps during play
|
|
217
|
+
current_step: Reactive value for the current step
|
|
218
|
+
reset_counter: Counter to trigger model reset
|
|
219
|
+
"""
|
|
208
220
|
playing = solara.use_reactive(False)
|
|
209
221
|
thread = solara.use_reactive(None)
|
|
210
222
|
# We track the previous step to detect if user resets the model via
|
|
@@ -214,6 +226,7 @@ def ModelController(model, play_interval, current_step, reset_counter):
|
|
|
214
226
|
previous_step = solara.use_reactive(0)
|
|
215
227
|
|
|
216
228
|
def on_value_play(change):
|
|
229
|
+
"""Handle play/pause state changes."""
|
|
217
230
|
if previous_step.value > current_step.value and current_step.value == 0:
|
|
218
231
|
# We add extra checks for current_step.value == 0, just to be sure.
|
|
219
232
|
# We automatically stop the playing if a model is reset.
|
|
@@ -224,31 +237,37 @@ def ModelController(model, play_interval, current_step, reset_counter):
|
|
|
224
237
|
playing.value = False
|
|
225
238
|
|
|
226
239
|
def do_step():
|
|
240
|
+
"""Advance the model by one step."""
|
|
227
241
|
model.step()
|
|
228
242
|
previous_step.value = current_step.value
|
|
229
|
-
current_step.value = model.
|
|
243
|
+
current_step.value = model.steps
|
|
230
244
|
|
|
231
245
|
def do_play():
|
|
246
|
+
"""Run the model continuously."""
|
|
232
247
|
model.running = True
|
|
233
248
|
while model.running:
|
|
234
249
|
do_step()
|
|
235
250
|
|
|
236
251
|
def threaded_do_play():
|
|
252
|
+
"""Start a new thread for continuous model execution."""
|
|
237
253
|
if thread is not None and thread.is_alive():
|
|
238
254
|
return
|
|
239
255
|
thread.value = threading.Thread(target=do_play)
|
|
240
256
|
thread.start()
|
|
241
257
|
|
|
242
258
|
def do_pause():
|
|
259
|
+
"""Pause the model execution."""
|
|
243
260
|
if (thread is None) or (not thread.is_alive()):
|
|
244
261
|
return
|
|
245
262
|
model.running = False
|
|
246
263
|
thread.join()
|
|
247
264
|
|
|
248
265
|
def do_reset():
|
|
266
|
+
"""Reset the model."""
|
|
249
267
|
reset_counter.value += 1
|
|
250
268
|
|
|
251
269
|
def do_set_playing(value):
|
|
270
|
+
"""Set the playing state."""
|
|
252
271
|
if current_step.value == 0:
|
|
253
272
|
# This means the model has been recreated, and the step resets to
|
|
254
273
|
# 0. We want to avoid triggering the playing.value = False in the
|
|
@@ -292,6 +311,14 @@ def ModelController(model, play_interval, current_step, reset_counter):
|
|
|
292
311
|
|
|
293
312
|
|
|
294
313
|
def split_model_params(model_params):
|
|
314
|
+
"""Split model parameters into user-adjustable and fixed parameters.
|
|
315
|
+
|
|
316
|
+
Args:
|
|
317
|
+
model_params: Dictionary of all model parameters
|
|
318
|
+
|
|
319
|
+
Returns:
|
|
320
|
+
tuple: (user_adjustable_params, fixed_params)
|
|
321
|
+
"""
|
|
295
322
|
model_params_input = {}
|
|
296
323
|
model_params_fixed = {}
|
|
297
324
|
for k, v in model_params.items():
|
|
@@ -303,6 +330,14 @@ def split_model_params(model_params):
|
|
|
303
330
|
|
|
304
331
|
|
|
305
332
|
def check_param_is_fixed(param):
|
|
333
|
+
"""Check if a parameter is fixed (not user-adjustable).
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
param: Parameter to check
|
|
337
|
+
|
|
338
|
+
Returns:
|
|
339
|
+
bool: True if parameter is fixed, False otherwise
|
|
340
|
+
"""
|
|
306
341
|
if isinstance(param, Slider):
|
|
307
342
|
return False
|
|
308
343
|
if not isinstance(param, dict):
|
|
@@ -314,15 +349,15 @@ def check_param_is_fixed(param):
|
|
|
314
349
|
@solara.component
|
|
315
350
|
def UserInputs(user_params, on_change=None):
|
|
316
351
|
"""Initialize user inputs for configurable model parameters.
|
|
352
|
+
|
|
317
353
|
Currently supports :class:`solara.SliderInt`, :class:`solara.SliderFloat`,
|
|
318
354
|
:class:`solara.Select`, and :class:`solara.Checkbox`.
|
|
319
355
|
|
|
320
|
-
|
|
321
|
-
user_params:
|
|
356
|
+
Args:
|
|
357
|
+
user_params: Dictionary with options for the input, including label,
|
|
322
358
|
min and max values, and other fields specific to the input type.
|
|
323
|
-
on_change:
|
|
359
|
+
on_change: Function to be called with (name, value) when the value of an input changes.
|
|
324
360
|
"""
|
|
325
|
-
|
|
326
361
|
for name, options in user_params.items():
|
|
327
362
|
|
|
328
363
|
def change_handler(value, name=name):
|
|
@@ -381,6 +416,15 @@ def UserInputs(user_params, on_change=None):
|
|
|
381
416
|
|
|
382
417
|
|
|
383
418
|
def make_text(renderer):
|
|
419
|
+
"""Create a function that renders text using Markdown.
|
|
420
|
+
|
|
421
|
+
Args:
|
|
422
|
+
renderer: Function that takes a model and returns a string
|
|
423
|
+
|
|
424
|
+
Returns:
|
|
425
|
+
function: A function that renders the text as Markdown
|
|
426
|
+
"""
|
|
427
|
+
|
|
384
428
|
def function(model):
|
|
385
429
|
solara.Markdown(renderer(model))
|
|
386
430
|
|
|
@@ -388,6 +432,14 @@ def make_text(renderer):
|
|
|
388
432
|
|
|
389
433
|
|
|
390
434
|
def make_initial_grid_layout(layout_types):
|
|
435
|
+
"""Create an initial grid layout for visualization components.
|
|
436
|
+
|
|
437
|
+
Args:
|
|
438
|
+
layout_types: List of layout types (Space or Measure)
|
|
439
|
+
|
|
440
|
+
Returns:
|
|
441
|
+
list: Initial grid layout configuration
|
|
442
|
+
"""
|
|
391
443
|
return [
|
|
392
444
|
{
|
|
393
445
|
"i": i,
|