Mesa 3.0.2__py3-none-any.whl → 3.1.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 +4 -6
- mesa/agent.py +48 -25
- mesa/batchrunner.py +14 -1
- mesa/datacollection.py +1 -6
- mesa/examples/__init__.py +2 -2
- mesa/examples/advanced/epstein_civil_violence/app.py +5 -0
- mesa/examples/advanced/pd_grid/app.py +5 -0
- mesa/examples/advanced/sugarscape_g1mt/app.py +7 -2
- mesa/examples/basic/boid_flockers/app.py +5 -0
- mesa/examples/basic/boltzmann_wealth_model/app.py +8 -5
- mesa/examples/basic/boltzmann_wealth_model/st_app.py +1 -1
- mesa/examples/basic/conways_game_of_life/app.py +5 -0
- mesa/examples/basic/conways_game_of_life/st_app.py +2 -2
- mesa/examples/basic/schelling/app.py +5 -0
- mesa/examples/basic/virus_on_network/app.py +5 -0
- mesa/experimental/__init__.py +17 -10
- mesa/experimental/cell_space/__init__.py +19 -7
- mesa/experimental/cell_space/cell.py +22 -37
- mesa/experimental/cell_space/cell_agent.py +12 -1
- mesa/experimental/cell_space/cell_collection.py +18 -3
- mesa/experimental/cell_space/discrete_space.py +15 -64
- mesa/experimental/cell_space/grid.py +74 -4
- mesa/experimental/cell_space/network.py +13 -1
- mesa/experimental/cell_space/property_layer.py +444 -0
- mesa/experimental/cell_space/voronoi.py +13 -1
- mesa/experimental/devs/__init__.py +20 -2
- mesa/experimental/devs/eventlist.py +19 -1
- mesa/experimental/devs/simulator.py +24 -8
- mesa/experimental/mesa_signals/__init__.py +23 -0
- mesa/experimental/mesa_signals/mesa_signal.py +485 -0
- mesa/experimental/mesa_signals/observable_collections.py +133 -0
- mesa/experimental/mesa_signals/signals_util.py +52 -0
- mesa/mesa_logging.py +190 -0
- mesa/model.py +17 -74
- mesa/visualization/__init__.py +2 -2
- mesa/visualization/mpl_space_drawing.py +2 -2
- mesa/visualization/solara_viz.py +23 -5
- {mesa-3.0.2.dist-info → mesa-3.1.0.dist-info}/METADATA +3 -4
- {mesa-3.0.2.dist-info → mesa-3.1.0.dist-info}/RECORD +43 -44
- {mesa-3.0.2.dist-info → mesa-3.1.0.dist-info}/WHEEL +1 -1
- mesa/experimental/UserParam.py +0 -67
- mesa/experimental/components/altair.py +0 -81
- mesa/experimental/components/matplotlib.py +0 -242
- mesa/experimental/devs/examples/epstein_civil_violence.py +0 -305
- mesa/experimental/devs/examples/wolf_sheep.py +0 -250
- mesa/experimental/solara_viz.py +0 -453
- mesa/time.py +0 -391
- {mesa-3.0.2.dist-info → mesa-3.1.0.dist-info}/entry_points.txt +0 -0
- {mesa-3.0.2.dist-info → mesa-3.1.0.dist-info}/licenses/LICENSE +0 -0
- {mesa-3.0.2.dist-info → mesa-3.1.0.dist-info}/licenses/NOTICE +0 -0
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
mesa/__init__.py,sha256=
|
|
2
|
-
mesa/agent.py,sha256=
|
|
3
|
-
mesa/batchrunner.py,sha256=
|
|
4
|
-
mesa/datacollection.py,sha256=
|
|
5
|
-
mesa/
|
|
1
|
+
mesa/__init__.py,sha256=9xQiRsNGK_hXnSjJI0S4NHuTB8ai9XtY6Jp3R44YbTA,611
|
|
2
|
+
mesa/agent.py,sha256=4CXMOFA9KhvTypaV_OHZGqxOR4GVwyX4x8DOtQENUQA,26130
|
|
3
|
+
mesa/batchrunner.py,sha256=w8StV82F_7DAAVQc5V7_Ggp0EL1NYn__UcBE-Nwrgv4,7771
|
|
4
|
+
mesa/datacollection.py,sha256=8loT4pQsXcHArxHSsbRc7HTc2GP5gsEIeKFKr3xya4I,15991
|
|
5
|
+
mesa/mesa_logging.py,sha256=PEDqUaQ2Y4bkYBkrHVkGT0sF86gUdbSH1T3vCg3qQeE,4949
|
|
6
|
+
mesa/model.py,sha256=oVcV-_OZ3GVv1sb3KqyGA9TAWCDQu9qEDWwRi_AXR40,8353
|
|
6
7
|
mesa/space.py,sha256=cfzlRfy9chegp8d89k2aqI29jo9cb18USlz2G2iOZU4,64082
|
|
7
|
-
mesa/time.py,sha256=KXwDqZHHvYbuqzB8zRbHglN23qVMfj8RXD-T_kJ3DfY,15022
|
|
8
8
|
mesa/examples/README.md,sha256=dNn8kv0BNQem3NNhO5mbOANQoK8UUYOo7rnkCFV9tnE,2882
|
|
9
|
-
mesa/examples/__init__.py,sha256=
|
|
9
|
+
mesa/examples/__init__.py,sha256=pyPWFRUxyYtQilJECbH7LY1eYBk8VB0Yg-_SbFEEvFA,825
|
|
10
10
|
mesa/examples/advanced/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
mesa/examples/advanced/epstein_civil_violence/Epstein Civil Violence.ipynb,sha256=yh50ZAK2BVJyJIKsQTTxywnasqWn1IiQUVrwmZKue4w,29032
|
|
12
12
|
mesa/examples/advanced/epstein_civil_violence/Readme.md,sha256=RXuGIZAibz3KVkP51PGjwzcRx2R9Ettmh3qbDTPqDcg,1735
|
|
13
13
|
mesa/examples/advanced/epstein_civil_violence/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
mesa/examples/advanced/epstein_civil_violence/agents.py,sha256=0X4JLj2K2cl1bACkFLI6-K6tKbr2SLZlAy_kjgUDjzA,5863
|
|
15
|
-
mesa/examples/advanced/epstein_civil_violence/app.py,sha256=
|
|
15
|
+
mesa/examples/advanced/epstein_civil_violence/app.py,sha256=fFlPijAUDLs_WfROGIlUXRakkkfbWnytcXFTAzdRplU,1890
|
|
16
16
|
mesa/examples/advanced/epstein_civil_violence/model.py,sha256=fcTkjCRhEhDerDC1W_lrezdoWD1y5xIublkGIhCak8w,3918
|
|
17
17
|
mesa/examples/advanced/pd_grid/Readme.md,sha256=UVUQxZRFdfymCKDdQEn3ZEwgSqgp9cKJPsU8oZpLFnY,2367
|
|
18
18
|
mesa/examples/advanced/pd_grid/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
19
|
mesa/examples/advanced/pd_grid/agents.py,sha256=DzGj4LZUjV0xMQAwkRsv2Aoap1cUvLscJswfA1PdVDs,1716
|
|
20
20
|
mesa/examples/advanced/pd_grid/analysis.ipynb,sha256=ReYtRe2JVyCCXoMBONvynXDQ_eGtQSWhNcuJY3CYTTI,82323
|
|
21
|
-
mesa/examples/advanced/pd_grid/app.py,sha256
|
|
21
|
+
mesa/examples/advanced/pd_grid/app.py,sha256=-_fTP7f_oITKHt7dDVJou7Oa7u7v_C4Ml5yw7D1sbx8,1457
|
|
22
22
|
mesa/examples/advanced/pd_grid/model.py,sha256=DiHGeX7fR1slvcAzbmDCxnmXJ2Txjmju_gII3e-EJgY,2345
|
|
23
23
|
mesa/examples/advanced/sugarscape_g1mt/Readme.md,sha256=x3kKw1Rre2FPkNhGDLtdzeThmH089mxsGYUPZUeu26k,3595
|
|
24
24
|
mesa/examples/advanced/sugarscape_g1mt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
25
|
mesa/examples/advanced/sugarscape_g1mt/agents.py,sha256=zE7zbO2_OaQiFDq_-t-0hv4ButBWv26dnS1zaPc3_ZE,10183
|
|
26
|
-
mesa/examples/advanced/sugarscape_g1mt/app.py,sha256=
|
|
26
|
+
mesa/examples/advanced/sugarscape_g1mt/app.py,sha256=zXwD_zSGmE3M4JN4qexV7OfiF2rtd1rJYszSSpTiceA,2882
|
|
27
27
|
mesa/examples/advanced/sugarscape_g1mt/model.py,sha256=NFQRqwuOwP3kz1fNNPEm2XkdbS0G3-TgneiJdQZHqck,6111
|
|
28
28
|
mesa/examples/advanced/sugarscape_g1mt/sugar-map.txt,sha256=zZtGYciBPT4miZVnbVuoQ5TugTmGrbDWV9yb5KH6tnU,5000
|
|
29
29
|
mesa/examples/advanced/sugarscape_g1mt/tests.py,sha256=UNahmZTgLquSqmoi_9GcE3JP0qBHjkrHFZ15NMm0ce8,2517
|
|
@@ -36,60 +36,59 @@ mesa/examples/basic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
|
|
|
36
36
|
mesa/examples/basic/boid_flockers/Readme.md,sha256=4KJinsLPtUciQSMzvaX3tU5r1HTUg3AFOFDKy73W5RE,894
|
|
37
37
|
mesa/examples/basic/boid_flockers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
38
|
mesa/examples/basic/boid_flockers/agents.py,sha256=72oL4jWEiJfSgshSEcL44irptIY6WAQDRAQ0cO2MxS8,3827
|
|
39
|
-
mesa/examples/basic/boid_flockers/app.py,sha256=
|
|
39
|
+
mesa/examples/basic/boid_flockers/app.py,sha256=oJbv_CbeiXu97q1W_2xlsXIVAqqLvfxshn2Y70_7PyA,1244
|
|
40
40
|
mesa/examples/basic/boid_flockers/model.py,sha256=scy0OaYzQVY5vVarsI7dUydynwoH3-uYoYcsBTtwtyA,3399
|
|
41
41
|
mesa/examples/basic/boltzmann_wealth_model/Readme.md,sha256=wl1ylO9KWoTiuIJKOnk2FGdcmyVUqJ5wiSbVUa3WWAc,2725
|
|
42
42
|
mesa/examples/basic/boltzmann_wealth_model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
43
|
mesa/examples/basic/boltzmann_wealth_model/agents.py,sha256=Jol2aspw--UtQn0EiReXVmlWtzpdC2o_YUTAyu1sDk4,1546
|
|
44
|
-
mesa/examples/basic/boltzmann_wealth_model/app.py,sha256=
|
|
44
|
+
mesa/examples/basic/boltzmann_wealth_model/app.py,sha256=wTQBu9A3uscTZSPqZ5jYssykGPiseye2YBjMngYI48A,2233
|
|
45
45
|
mesa/examples/basic/boltzmann_wealth_model/model.py,sha256=ED4EFHJlrrcF12WYOEpXpPt5asK2T6uzpq_S97EtfHo,2941
|
|
46
|
-
mesa/examples/basic/boltzmann_wealth_model/st_app.py,sha256=
|
|
46
|
+
mesa/examples/basic/boltzmann_wealth_model/st_app.py,sha256=PQ65LkYPXn-lx4lCfXuFJmzcmAfVB3oEEdIyuq9a7iU,3454
|
|
47
47
|
mesa/examples/basic/conways_game_of_life/Readme.md,sha256=VRgN6roF6leQ_IMYwxFypSfFjZo9jnCd-rkPTjpp7II,1453
|
|
48
48
|
mesa/examples/basic/conways_game_of_life/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
49
49
|
mesa/examples/basic/conways_game_of_life/agents.py,sha256=ETn87GV8it9p0nlSn6f1qu5CDEmqokkr6Rq7KWaT-5U,1627
|
|
50
|
-
mesa/examples/basic/conways_game_of_life/app.py,sha256=
|
|
50
|
+
mesa/examples/basic/conways_game_of_life/app.py,sha256=HPzss2X3ntTOgdmg0C0EWw3lmAF7WiN9MZEgGdLW-xU,1997
|
|
51
51
|
mesa/examples/basic/conways_game_of_life/model.py,sha256=8L88m8F_YauwWeDef6UA2myQoAwC0B5sH5jsfyLn-u8,1221
|
|
52
|
-
mesa/examples/basic/conways_game_of_life/st_app.py,sha256=
|
|
52
|
+
mesa/examples/basic/conways_game_of_life/st_app.py,sha256=9qz3o0pOuvLZR-_aPPVHN-RIwFSNzvwWWfxCaD2K5cs,2402
|
|
53
53
|
mesa/examples/basic/schelling/Readme.md,sha256=CRKBfYtnLJLlTKLsTRQ-7gsQRxVxDooOBN5uP8PEtaU,2296
|
|
54
54
|
mesa/examples/basic/schelling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
55
|
mesa/examples/basic/schelling/agents.py,sha256=BzipyAU5d_H4DoTm3xkeZLDazsr49rbaVr_kyk1rDJA,937
|
|
56
56
|
mesa/examples/basic/schelling/analysis.ipynb,sha256=JDJy6-U6eO-LrHWxZr1c3lkvtoY0DNHa-kJ4J-Z-wwo,5804
|
|
57
|
-
mesa/examples/basic/schelling/app.py,sha256=
|
|
57
|
+
mesa/examples/basic/schelling/app.py,sha256=dT0wfZVr2SbHrnlP_O0NNm3wKIYX-vtfD70L0blgils,1057
|
|
58
58
|
mesa/examples/basic/schelling/model.py,sha256=ruqiMNBBsWV81srYZgdsfDVwgMWYuw2VAzSQhsK5E98,2762
|
|
59
59
|
mesa/examples/basic/virus_on_network/Readme.md,sha256=qmXGx4Fo0tRBvJiiJ684bkWJPn2gcFaiikLwgc5APWI,2336
|
|
60
60
|
mesa/examples/basic/virus_on_network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
61
61
|
mesa/examples/basic/virus_on_network/agents.py,sha256=a_WhqYblJlW6od67eXfU-nb7IMRyYpgxtf0le--VYoA,1975
|
|
62
|
-
mesa/examples/basic/virus_on_network/app.py,sha256=
|
|
62
|
+
mesa/examples/basic/virus_on_network/app.py,sha256=8I8VWQ7pBcOaNGyLDEO4IbNSTRy161-eWg-iEUVQ3-I,2553
|
|
63
63
|
mesa/examples/basic/virus_on_network/model.py,sha256=jQoCmvygwCvhUrlL0l7V8GcDLv94CgwtuK7DDGU8q8g,2813
|
|
64
|
-
mesa/experimental/
|
|
65
|
-
mesa/experimental/__init__.py,sha256=
|
|
66
|
-
mesa/experimental/
|
|
67
|
-
mesa/experimental/cell_space/
|
|
68
|
-
mesa/experimental/cell_space/
|
|
69
|
-
mesa/experimental/cell_space/
|
|
70
|
-
mesa/experimental/cell_space/
|
|
71
|
-
mesa/experimental/cell_space/
|
|
72
|
-
mesa/experimental/cell_space/
|
|
73
|
-
mesa/experimental/cell_space/
|
|
74
|
-
mesa/experimental/
|
|
75
|
-
mesa/experimental/
|
|
76
|
-
mesa/experimental/
|
|
77
|
-
mesa/experimental/
|
|
78
|
-
mesa/experimental/
|
|
79
|
-
mesa/experimental/
|
|
80
|
-
mesa/experimental/
|
|
81
|
-
mesa/
|
|
82
|
-
mesa/visualization/
|
|
83
|
-
mesa/visualization/
|
|
84
|
-
mesa/visualization/solara_viz.py,sha256=pGtfjFfFMLwF9vmy5btiHRZww6NGoiKu0tzNdhZaYj4,17947
|
|
64
|
+
mesa/experimental/__init__.py,sha256=32D_blj5droexwyh83MjPska0_xYzL1ncJFgyuyBaWs,905
|
|
65
|
+
mesa/experimental/cell_space/__init__.py,sha256=0A3YTen0Lk-e3Q73VEXK7N2UEHb9f50gW11H_jx7DXc,1744
|
|
66
|
+
mesa/experimental/cell_space/cell.py,sha256=Dl0ek7W_vgAZOp6zXBvkwYTG7E36OQ-4zZ5bW43mKtw,6600
|
|
67
|
+
mesa/experimental/cell_space/cell_agent.py,sha256=LOTLKR2To9hU-igKsauA5sikS7k8wgwlt-Pi0C7lGU0,4262
|
|
68
|
+
mesa/experimental/cell_space/cell_collection.py,sha256=VnD3I4bqnwgFxKSzTElYYJIBFJGdaEaNTggrbFKgPrc,4715
|
|
69
|
+
mesa/experimental/cell_space/discrete_space.py,sha256=qNGez9SV4E83Outs_12suuS0ZtTHcwyv6ZB1xzTXUWk,3846
|
|
70
|
+
mesa/experimental/cell_space/grid.py,sha256=d-1S2iXijGkoJ9yc271pB8iXlzsX13usJjcjevCs_rU,10432
|
|
71
|
+
mesa/experimental/cell_space/network.py,sha256=ujN2dV1i9hcXh6H0s7gwTuPT6gh7BCaziOUYPCybQKk,1862
|
|
72
|
+
mesa/experimental/cell_space/property_layer.py,sha256=HFpBWOjI7PFU_K8VDb_pl9h62MftCBWL7PUKQNT3Ke8,17379
|
|
73
|
+
mesa/experimental/cell_space/voronoi.py,sha256=5D9j45FW2IVPcZrp-hskw_z84QwHIdduwXLdTKeqWMQ,10472
|
|
74
|
+
mesa/experimental/devs/__init__.py,sha256=wkDrpqQ3qHGqrsOSTD-UOj-qOw0oFgnCw_ZXr9xFs90,1200
|
|
75
|
+
mesa/experimental/devs/eventlist.py,sha256=6igPkHJt-syLcdpFV14_n6HGej2F1cM9giDQo85fHPw,7217
|
|
76
|
+
mesa/experimental/devs/simulator.py,sha256=UiVRIlNodSIveD2mS_8-vj0T_FulU8vhXxSxCfsK1Vc,12991
|
|
77
|
+
mesa/experimental/mesa_signals/__init__.py,sha256=QjG4FSKQl5ZSzV9ctiaB7UqYDR3FARAyUc7HbGtQjX4,840
|
|
78
|
+
mesa/experimental/mesa_signals/mesa_signal.py,sha256=Vxo4gIV6a959MANL3RMANsGh0R9lkZTNO19XIYzvKSM,16860
|
|
79
|
+
mesa/experimental/mesa_signals/observable_collections.py,sha256=rHEj6BYxLHFFGzSdoDKAdtzJ6y-IHHfcP3qEDJJsY6Y,3917
|
|
80
|
+
mesa/experimental/mesa_signals/signals_util.py,sha256=fmq_FsIxsIvGjtmc4A9TGdBUtdliMHhEOpjRXivRDjA,1618
|
|
81
|
+
mesa/visualization/__init__.py,sha256=YW-oHEOTjbtDKD_TylAMtVnt8mrsz1Fw7ifdc4WeHxA,743
|
|
82
|
+
mesa/visualization/mpl_space_drawing.py,sha256=lFUQY5G7x2dNqxqTBfF6CjnGHMI_R7xGM1bskqPU68c,20066
|
|
83
|
+
mesa/visualization/solara_viz.py,sha256=-OHf6E8sTrnCaPROo9_feK7e3dv8yl_SHzidlRhZ6P8,18519
|
|
85
84
|
mesa/visualization/user_param.py,sha256=Dl2WOwLYLf0pfLpabCZtIdFRyKZrK6Qtc3utZx5GPYg,2139
|
|
86
85
|
mesa/visualization/utils.py,sha256=lJHgRKF5BHLf72Tw3YpwyiWuRoIimaTKQ7xBCw_Rx3A,146
|
|
87
86
|
mesa/visualization/components/__init__.py,sha256=Bq3nrPikcaIo9BSs0O3zptWVLlUmAkLo3s0mEmpH1RE,3022
|
|
88
87
|
mesa/visualization/components/altair_components.py,sha256=wotpFFQgMY-ZR3lNVm_fRos-iDg0Wjnj6Tk67_7f1SQ,5847
|
|
89
88
|
mesa/visualization/components/matplotlib_components.py,sha256=xQETaFyHIfmL_9JwrLIgubuIQ7-pp7TMoXT1WMmozus,5441
|
|
90
|
-
mesa-3.0.
|
|
91
|
-
mesa-3.0.
|
|
92
|
-
mesa-3.0.
|
|
93
|
-
mesa-3.0.
|
|
94
|
-
mesa-3.0.
|
|
95
|
-
mesa-3.0.
|
|
89
|
+
mesa-3.1.0.dist-info/METADATA,sha256=p5S8DvlFII035nqJgdSg_Iqc3tZVQfKzGWwtgXTWgkw,9906
|
|
90
|
+
mesa-3.1.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
|
91
|
+
mesa-3.1.0.dist-info/entry_points.txt,sha256=IOcQtetGF8l4wHpOs_hGb19Rz-FS__BMXOJR10IBPsA,39
|
|
92
|
+
mesa-3.1.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
93
|
+
mesa-3.1.0.dist-info/licenses/NOTICE,sha256=GbsWoK0QWv1JyZ_xer2s-jNilv0RtWl-0UrtlJANHPg,578
|
|
94
|
+
mesa-3.1.0.dist-info/RECORD,,
|
mesa/experimental/UserParam.py
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
"""helper classes."""
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class UserParam: # noqa: D101
|
|
5
|
-
_ERROR_MESSAGE = "Missing or malformed inputs for '{}' Option '{}'"
|
|
6
|
-
|
|
7
|
-
def maybe_raise_error(self, param_type, valid): # noqa: D102
|
|
8
|
-
if valid:
|
|
9
|
-
return
|
|
10
|
-
msg = self._ERROR_MESSAGE.format(param_type, self.label)
|
|
11
|
-
raise ValueError(msg)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class Slider(UserParam):
|
|
15
|
-
"""A number-based slider input with settable increment.
|
|
16
|
-
|
|
17
|
-
Example:
|
|
18
|
-
slider_option = Slider("My Slider", value=123, min=10, max=200, step=0.1)
|
|
19
|
-
|
|
20
|
-
Args:
|
|
21
|
-
label: The displayed label in the UI
|
|
22
|
-
value: The initial value of the slider
|
|
23
|
-
min: The minimum possible value of the slider
|
|
24
|
-
max: The maximum possible value of the slider
|
|
25
|
-
step: The step between min and max for a range of possible values
|
|
26
|
-
dtype: either int or float
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
def __init__(
|
|
30
|
-
self,
|
|
31
|
-
label="",
|
|
32
|
-
value=None,
|
|
33
|
-
min=None,
|
|
34
|
-
max=None,
|
|
35
|
-
step=1,
|
|
36
|
-
dtype=None,
|
|
37
|
-
):
|
|
38
|
-
"""Slider class.
|
|
39
|
-
|
|
40
|
-
Args:
|
|
41
|
-
label: The displayed label in the UI
|
|
42
|
-
value: The initial value of the slider
|
|
43
|
-
min: The minimum possible value of the slider
|
|
44
|
-
max: The maximum possible value of the slider
|
|
45
|
-
step: The step between min and max for a range of possible values
|
|
46
|
-
dtype: either int or float
|
|
47
|
-
"""
|
|
48
|
-
self.label = label
|
|
49
|
-
self.value = value
|
|
50
|
-
self.min = min
|
|
51
|
-
self.max = max
|
|
52
|
-
self.step = step
|
|
53
|
-
|
|
54
|
-
# Validate option type to make sure values are supplied properly
|
|
55
|
-
valid = not (self.value is None or self.min is None or self.max is None)
|
|
56
|
-
self.maybe_raise_error("slider", valid)
|
|
57
|
-
|
|
58
|
-
if dtype is None:
|
|
59
|
-
self.is_float_slider = self._check_values_are_float(value, min, max, step)
|
|
60
|
-
else:
|
|
61
|
-
self.is_float_slider = dtype is float
|
|
62
|
-
|
|
63
|
-
def _check_values_are_float(self, value, min, max, step):
|
|
64
|
-
return any(isinstance(n, float) for n in (value, min, max, step))
|
|
65
|
-
|
|
66
|
-
def get(self, attr): # noqa: D102
|
|
67
|
-
return getattr(self, attr)
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
"""Altair components."""
|
|
2
|
-
|
|
3
|
-
import contextlib
|
|
4
|
-
|
|
5
|
-
import solara
|
|
6
|
-
|
|
7
|
-
with contextlib.suppress(ImportError):
|
|
8
|
-
import altair as alt
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@solara.component
|
|
12
|
-
def SpaceAltair(model, agent_portrayal, dependencies: list[any] | None = None):
|
|
13
|
-
"""A component that renders a Space using Altair.
|
|
14
|
-
|
|
15
|
-
Args:
|
|
16
|
-
model: a model instance
|
|
17
|
-
agent_portrayal: agent portray specification
|
|
18
|
-
dependencies: optional list of dependencies (currently not used)
|
|
19
|
-
|
|
20
|
-
"""
|
|
21
|
-
space = getattr(model, "grid", None)
|
|
22
|
-
if space is None:
|
|
23
|
-
# Sometimes the space is defined as model.space instead of model.grid
|
|
24
|
-
space = model.space
|
|
25
|
-
chart = _draw_grid(space, agent_portrayal)
|
|
26
|
-
solara.FigureAltair(chart)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def _draw_grid(space, agent_portrayal):
|
|
30
|
-
def portray(g):
|
|
31
|
-
all_agent_data = []
|
|
32
|
-
for content, (x, y) in g.coord_iter():
|
|
33
|
-
if not content:
|
|
34
|
-
continue
|
|
35
|
-
if not hasattr(content, "__iter__"):
|
|
36
|
-
# Is a single grid
|
|
37
|
-
content = [content] # noqa: PLW2901
|
|
38
|
-
for agent in content:
|
|
39
|
-
# use all data from agent portrayal, and add x,y coordinates
|
|
40
|
-
agent_data = agent_portrayal(agent)
|
|
41
|
-
agent_data["x"] = x
|
|
42
|
-
agent_data["y"] = y
|
|
43
|
-
all_agent_data.append(agent_data)
|
|
44
|
-
return all_agent_data
|
|
45
|
-
|
|
46
|
-
all_agent_data = portray(space)
|
|
47
|
-
invalid_tooltips = ["color", "size", "x", "y"]
|
|
48
|
-
|
|
49
|
-
encoding_dict = {
|
|
50
|
-
# no x-axis label
|
|
51
|
-
"x": alt.X("x", axis=None, type="ordinal"),
|
|
52
|
-
# no y-axis label
|
|
53
|
-
"y": alt.Y("y", axis=None, type="ordinal"),
|
|
54
|
-
"tooltip": [
|
|
55
|
-
alt.Tooltip(key, type=alt.utils.infer_vegalite_type([value]))
|
|
56
|
-
for key, value in all_agent_data[0].items()
|
|
57
|
-
if key not in invalid_tooltips
|
|
58
|
-
],
|
|
59
|
-
}
|
|
60
|
-
has_color = "color" in all_agent_data[0]
|
|
61
|
-
if has_color:
|
|
62
|
-
encoding_dict["color"] = alt.Color("color", type="nominal")
|
|
63
|
-
has_size = "size" in all_agent_data[0]
|
|
64
|
-
if has_size:
|
|
65
|
-
encoding_dict["size"] = alt.Size("size", type="quantitative")
|
|
66
|
-
|
|
67
|
-
chart = (
|
|
68
|
-
alt.Chart(
|
|
69
|
-
alt.Data(values=all_agent_data), encoding=alt.Encoding(**encoding_dict)
|
|
70
|
-
)
|
|
71
|
-
.mark_point(filled=True)
|
|
72
|
-
.properties(width=280, height=280)
|
|
73
|
-
# .configure_view(strokeOpacity=0) # hide grid/chart lines
|
|
74
|
-
)
|
|
75
|
-
# This is the default value for the marker size, which auto-scales
|
|
76
|
-
# according to the grid area.
|
|
77
|
-
if not has_size:
|
|
78
|
-
length = min(space.width, space.height)
|
|
79
|
-
chart = chart.mark_point(size=30000 / length**2, filled=True)
|
|
80
|
-
|
|
81
|
-
return chart
|
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
"""Support for using matplotlib to draw spaces."""
|
|
2
|
-
|
|
3
|
-
from collections import defaultdict
|
|
4
|
-
|
|
5
|
-
import networkx as nx
|
|
6
|
-
import solara
|
|
7
|
-
from matplotlib.figure import Figure
|
|
8
|
-
from matplotlib.ticker import MaxNLocator
|
|
9
|
-
|
|
10
|
-
import mesa
|
|
11
|
-
from mesa.experimental.cell_space import VoronoiGrid
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@solara.component
|
|
15
|
-
def SpaceMatplotlib(model, agent_portrayal, dependencies: list[any] | None = None):
|
|
16
|
-
"""A component for rendering a space using Matplotlib.
|
|
17
|
-
|
|
18
|
-
Args:
|
|
19
|
-
model: a model instance
|
|
20
|
-
agent_portrayal: a specification of how to portray an agent.
|
|
21
|
-
dependencies: list of dependencies.
|
|
22
|
-
|
|
23
|
-
"""
|
|
24
|
-
space_fig = Figure()
|
|
25
|
-
space_ax = space_fig.subplots()
|
|
26
|
-
space = getattr(model, "grid", None)
|
|
27
|
-
if space is None:
|
|
28
|
-
# Sometimes the space is defined as model.space instead of model.grid
|
|
29
|
-
space = model.space
|
|
30
|
-
if isinstance(space, mesa.space.NetworkGrid):
|
|
31
|
-
_draw_network_grid(space, space_ax, agent_portrayal)
|
|
32
|
-
elif isinstance(space, mesa.space.ContinuousSpace):
|
|
33
|
-
_draw_continuous_space(space, space_ax, agent_portrayal)
|
|
34
|
-
elif isinstance(space, VoronoiGrid):
|
|
35
|
-
_draw_voronoi(space, space_ax, agent_portrayal)
|
|
36
|
-
else:
|
|
37
|
-
_draw_grid(space, space_ax, agent_portrayal)
|
|
38
|
-
solara.FigureMatplotlib(space_fig, format="png", dependencies=dependencies)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
# matplotlib scatter does not allow for multiple shapes in one call
|
|
42
|
-
def _split_and_scatter(portray_data, space_ax):
|
|
43
|
-
grouped_data = defaultdict(lambda: {"x": [], "y": [], "s": [], "c": []})
|
|
44
|
-
|
|
45
|
-
# Extract data from the dictionary
|
|
46
|
-
x = portray_data["x"]
|
|
47
|
-
y = portray_data["y"]
|
|
48
|
-
s = portray_data["s"]
|
|
49
|
-
c = portray_data["c"]
|
|
50
|
-
m = portray_data["m"]
|
|
51
|
-
|
|
52
|
-
if not (len(x) == len(y) == len(s) == len(c) == len(m)):
|
|
53
|
-
raise ValueError(
|
|
54
|
-
"Length mismatch in portrayal data lists: "
|
|
55
|
-
f"x: {len(x)}, y: {len(y)}, size: {len(s)}, "
|
|
56
|
-
f"color: {len(c)}, marker: {len(m)}"
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
# Group the data by marker
|
|
60
|
-
for i in range(len(x)):
|
|
61
|
-
marker = m[i]
|
|
62
|
-
grouped_data[marker]["x"].append(x[i])
|
|
63
|
-
grouped_data[marker]["y"].append(y[i])
|
|
64
|
-
grouped_data[marker]["s"].append(s[i])
|
|
65
|
-
grouped_data[marker]["c"].append(c[i])
|
|
66
|
-
|
|
67
|
-
# Plot each group with the same marker
|
|
68
|
-
for marker, data in grouped_data.items():
|
|
69
|
-
space_ax.scatter(data["x"], data["y"], s=data["s"], c=data["c"], marker=marker)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def _draw_grid(space, space_ax, agent_portrayal):
|
|
73
|
-
def portray(g):
|
|
74
|
-
x = []
|
|
75
|
-
y = []
|
|
76
|
-
s = [] # size
|
|
77
|
-
c = [] # color
|
|
78
|
-
m = [] # shape
|
|
79
|
-
for i in range(g.width):
|
|
80
|
-
for j in range(g.height):
|
|
81
|
-
content = g._grid[i][j]
|
|
82
|
-
if not content:
|
|
83
|
-
continue
|
|
84
|
-
if not hasattr(content, "__iter__"):
|
|
85
|
-
# Is a single grid
|
|
86
|
-
content = [content]
|
|
87
|
-
for agent in content:
|
|
88
|
-
data = agent_portrayal(agent)
|
|
89
|
-
x.append(i)
|
|
90
|
-
y.append(j)
|
|
91
|
-
|
|
92
|
-
# This is the default value for the marker size, which auto-scales
|
|
93
|
-
# according to the grid area.
|
|
94
|
-
default_size = (180 / max(g.width, g.height)) ** 2
|
|
95
|
-
# establishing a default prevents misalignment if some agents are not given size, color, etc.
|
|
96
|
-
size = data.get("size", default_size)
|
|
97
|
-
s.append(size)
|
|
98
|
-
color = data.get("color", "tab:blue")
|
|
99
|
-
c.append(color)
|
|
100
|
-
mark = data.get("shape", "o")
|
|
101
|
-
m.append(mark)
|
|
102
|
-
out = {"x": x, "y": y, "s": s, "c": c, "m": m}
|
|
103
|
-
return out
|
|
104
|
-
|
|
105
|
-
space_ax.set_xlim(-1, space.width)
|
|
106
|
-
space_ax.set_ylim(-1, space.height)
|
|
107
|
-
_split_and_scatter(portray(space), space_ax)
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
def _draw_network_grid(space, space_ax, agent_portrayal):
|
|
111
|
-
graph = space.G
|
|
112
|
-
pos = nx.spring_layout(graph, seed=0)
|
|
113
|
-
nx.draw(
|
|
114
|
-
graph,
|
|
115
|
-
ax=space_ax,
|
|
116
|
-
pos=pos,
|
|
117
|
-
**agent_portrayal(graph),
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
def _draw_continuous_space(space, space_ax, agent_portrayal):
|
|
122
|
-
def portray(space):
|
|
123
|
-
x = []
|
|
124
|
-
y = []
|
|
125
|
-
s = [] # size
|
|
126
|
-
c = [] # color
|
|
127
|
-
m = [] # shape
|
|
128
|
-
for agent in space._agent_to_index:
|
|
129
|
-
data = agent_portrayal(agent)
|
|
130
|
-
_x, _y = agent.pos
|
|
131
|
-
x.append(_x)
|
|
132
|
-
y.append(_y)
|
|
133
|
-
|
|
134
|
-
# This is matplotlib's default marker size
|
|
135
|
-
default_size = 20
|
|
136
|
-
# establishing a default prevents misalignment if some agents are not given size, color, etc.
|
|
137
|
-
size = data.get("size", default_size)
|
|
138
|
-
s.append(size)
|
|
139
|
-
color = data.get("color", "tab:blue")
|
|
140
|
-
c.append(color)
|
|
141
|
-
mark = data.get("shape", "o")
|
|
142
|
-
m.append(mark)
|
|
143
|
-
out = {"x": x, "y": y, "s": s, "c": c, "m": m}
|
|
144
|
-
return out
|
|
145
|
-
|
|
146
|
-
# Determine border style based on space.torus
|
|
147
|
-
border_style = "solid" if not space.torus else (0, (5, 10))
|
|
148
|
-
|
|
149
|
-
# Set the border of the plot
|
|
150
|
-
for spine in space_ax.spines.values():
|
|
151
|
-
spine.set_linewidth(1.5)
|
|
152
|
-
spine.set_color("black")
|
|
153
|
-
spine.set_linestyle(border_style)
|
|
154
|
-
|
|
155
|
-
width = space.x_max - space.x_min
|
|
156
|
-
x_padding = width / 20
|
|
157
|
-
height = space.y_max - space.y_min
|
|
158
|
-
y_padding = height / 20
|
|
159
|
-
space_ax.set_xlim(space.x_min - x_padding, space.x_max + x_padding)
|
|
160
|
-
space_ax.set_ylim(space.y_min - y_padding, space.y_max + y_padding)
|
|
161
|
-
|
|
162
|
-
# Portray and scatter the agents in the space
|
|
163
|
-
_split_and_scatter(portray(space), space_ax)
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
def _draw_voronoi(space, space_ax, agent_portrayal):
|
|
167
|
-
def portray(g):
|
|
168
|
-
x = []
|
|
169
|
-
y = []
|
|
170
|
-
s = [] # size
|
|
171
|
-
c = [] # color
|
|
172
|
-
|
|
173
|
-
for cell in g.all_cells:
|
|
174
|
-
for agent in cell.agents:
|
|
175
|
-
data = agent_portrayal(agent)
|
|
176
|
-
x.append(cell.coordinate[0])
|
|
177
|
-
y.append(cell.coordinate[1])
|
|
178
|
-
if "size" in data:
|
|
179
|
-
s.append(data["size"])
|
|
180
|
-
if "color" in data:
|
|
181
|
-
c.append(data["color"])
|
|
182
|
-
out = {"x": x, "y": y}
|
|
183
|
-
# This is the default value for the marker size, which auto-scales
|
|
184
|
-
# according to the grid area.
|
|
185
|
-
out["s"] = s
|
|
186
|
-
if len(c) > 0:
|
|
187
|
-
out["c"] = c
|
|
188
|
-
|
|
189
|
-
return out
|
|
190
|
-
|
|
191
|
-
x_list = [i[0] for i in space.centroids_coordinates]
|
|
192
|
-
y_list = [i[1] for i in space.centroids_coordinates]
|
|
193
|
-
x_max = max(x_list)
|
|
194
|
-
x_min = min(x_list)
|
|
195
|
-
y_max = max(y_list)
|
|
196
|
-
y_min = min(y_list)
|
|
197
|
-
|
|
198
|
-
width = x_max - x_min
|
|
199
|
-
x_padding = width / 20
|
|
200
|
-
height = y_max - y_min
|
|
201
|
-
y_padding = height / 20
|
|
202
|
-
space_ax.set_xlim(x_min - x_padding, x_max + x_padding)
|
|
203
|
-
space_ax.set_ylim(y_min - y_padding, y_max + y_padding)
|
|
204
|
-
space_ax.scatter(**portray(space))
|
|
205
|
-
|
|
206
|
-
for cell in space.all_cells:
|
|
207
|
-
polygon = cell.properties["polygon"]
|
|
208
|
-
space_ax.fill(
|
|
209
|
-
*zip(*polygon),
|
|
210
|
-
alpha=min(1, cell.properties[space.cell_coloring_property]),
|
|
211
|
-
c="red",
|
|
212
|
-
) # Plot filled polygon
|
|
213
|
-
space_ax.plot(*zip(*polygon), color="black") # Plot polygon edges in red
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
@solara.component
|
|
217
|
-
def PlotMatplotlib(model, measure, dependencies: list[any] | None = None):
|
|
218
|
-
"""A solara component for creating a matplotlib figure.
|
|
219
|
-
|
|
220
|
-
Args:
|
|
221
|
-
model: Model instance
|
|
222
|
-
measure: measure to plot
|
|
223
|
-
dependencies: list of additional dependencies
|
|
224
|
-
|
|
225
|
-
"""
|
|
226
|
-
fig = Figure()
|
|
227
|
-
ax = fig.subplots()
|
|
228
|
-
df = model.datacollector.get_model_vars_dataframe()
|
|
229
|
-
if isinstance(measure, str):
|
|
230
|
-
ax.plot(df.loc[:, measure])
|
|
231
|
-
ax.set_ylabel(measure)
|
|
232
|
-
elif isinstance(measure, dict):
|
|
233
|
-
for m, color in measure.items():
|
|
234
|
-
ax.plot(df.loc[:, m], label=m, color=color)
|
|
235
|
-
fig.legend()
|
|
236
|
-
elif isinstance(measure, list | tuple):
|
|
237
|
-
for m in measure:
|
|
238
|
-
ax.plot(df.loc[:, m], label=m)
|
|
239
|
-
fig.legend()
|
|
240
|
-
# Set integer x axis
|
|
241
|
-
ax.xaxis.set_major_locator(MaxNLocator(integer=True))
|
|
242
|
-
solara.FigureMatplotlib(fig, dependencies=dependencies)
|