diff --git a/docs/apis/experimental.md b/docs/apis/experimental.md index c74b4fe43a4..2eb4c302aaf 100644 --- a/docs/apis/experimental.md +++ b/docs/apis/experimental.md @@ -3,6 +3,11 @@ This namespace contains experimental features. These are under development, and ## Cell Space +```{eval-rst} +.. automodule:: experimental.cell_space.__init__ + :members: +``` + ```{eval-rst} .. automodule:: experimental.cell_space.cell :members: @@ -33,6 +38,11 @@ This namespace contains experimental features. These are under development, and :members: ``` +```{eval-rst} +.. automodule:: experimental.cell_space.voronoi + :members: +``` + ## Devs ```{eval-rst} diff --git a/docs/apis/visualization.md b/docs/apis/visualization.md index 7c39dae5b01..27841f72fb4 100644 --- a/docs/apis/visualization.md +++ b/docs/apis/visualization.md @@ -14,7 +14,7 @@ For a detailed tutorial, please refer to our [Visualization Tutorial](../tutoria ## User Parameters ```{eval-rst} -.. automodule:: mesa.visualization.UserParam +.. automodule:: mesa.visualization.user_param :members: :undoc-members: :show-inheritance: diff --git a/docs/best-practices.md b/docs/best-practices.md index 115b25de56c..322e71691cd 100644 --- a/docs/best-practices.md +++ b/docs/best-practices.md @@ -24,7 +24,7 @@ All our [examples](examples) follow this layout. ## Randomization If your model involves some random choice, you can use the built-in `random` -property that Mesa `Model` and `Agent` objects have. This works exactly +property that many Mesa objects have, including `Model`, `Agent`, and `AgentSet`. This works exactly like the built-in `random` library. ```python @@ -45,20 +45,24 @@ class AwesomeAgent(Agent): random_number = self.random.randint(0, 100) ``` -(The agent's random property is just a reference to its parent model's -`random` property). +`Agent.random` is just a convenient shorthand in the Agent class to `self.model.random`. If you create your own `AgentSet` +instances, you have to pass `random` explicitly. Typically, you can simply do, in a Model instance, +`my_agentset = AgentSet([], random=self.random)`. This ensures that `my_agentset` uses the same random +number generator as the rest of the model. + When a model object is created, its random property is automatically seeded with the current time. The seed determines the sequence of random numbers; if you instantiate a model with the same seed, you will get the same results. To allow you to set the seed, make sure your model has a `seed` argument in its -constructor. +`__init__`. ```python class AwesomeModel(Model): def __init__(self, seed=None): - pass + super().__init__(seed=seed) + ... def cool_method(self): interesting_number = self.random.random() diff --git a/docs/conf.py b/docs/conf.py index 2193ef236e8..24dfa07b786 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -175,7 +175,9 @@ # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -# html_sidebars = {} +html_sidebars = { + 'migration_guide': [], # No sidebar migration +} # Additional templates that should be rendered to pages, maps page names to # template names. @@ -338,7 +340,7 @@ def setup_examples_pages(): app_filename = os.path.join(example, "app.py") md_filename = f"{base_name}.md" - examples_md.append(base_name) + examples_md.append((base_name, f"{kind}/{base_name}")) md_filepath = os.path.join(HERE, "examples", kind, md_filename) write_example_md_file(agent_filename, model_filename, readme_filename, app_filename, md_filepath, template) @@ -354,7 +356,7 @@ def setup_examples_pages(): content = template.substitute( dict( readme=readme_md, - # examples="\n".join([f"{' '.join(base_name.split('_'))} " for base_name in examples_md]), + example_paths="\n".join([f"{' '.join(a.split('_'))} " for a, b in examples_md]), ) ) fh.write(content) diff --git a/docs/examples_overview_template.txt b/docs/examples_overview_template.txt index 60b7461dc6c..2161e83a370 100644 --- a/docs/examples_overview_template.txt +++ b/docs/examples_overview_template.txt @@ -1,3 +1,13 @@ $readme + + +```{toctree} +:hidden: true +:maxdepth: 2 + +$example_paths + + +``` \ No newline at end of file diff --git a/docs/overview.md b/docs/getting_started.md similarity index 89% rename from docs/overview.md rename to docs/getting_started.md index 37735760920..e2202ecee8f 100644 --- a/docs/overview.md +++ b/docs/getting_started.md @@ -1,9 +1,20 @@ -# Mesa Overview +# Getting started Mesa is a modular framework for building, analyzing and visualizing agent-based models. **Agent-based models** are computer simulations involving multiple entities (the agents) acting and interacting with one another based on their programmed behavior. Agents can be used to represent living cells, animals, individual humans, even entire organizations or abstract entities. Sometimes, we may have an understanding of how the individual components of a system behave, and want to see what system-level behaviors and effects emerge from their interaction. Other times, we may have a good idea of how the system overall behaves, and want to figure out what individual behaviors explain it. Or we may want to see how to get agents to cooperate or compete most effectively. Or we may just want to build a cool toy with colorful little dots moving around. -## Mesa Modules + +## Tutorials +If you want to get a quick start on how to build agent based models with MESA, check the tutorials: + +- [Introductory Tutorial](tutorials/intro_tutorial): Learn how to create your first Mesa model. +- [Visualization Tutorial](tutorials/visualization_tutorial.html): Learn how to create interactive visualizations for your models. + +## Examples +Mesa ships with a collection of example models. These are classic ABMs, so if you are familiar with ABMs and want to get a quick sense of how MESA works, these examples are great place to start. You can find them [here](examples). + + +## Overview of the MESA library Mesa is modular, meaning that its modeling, analysis and visualization components are kept separate but intended to work together. The modules are grouped into three categories: @@ -165,10 +176,14 @@ results = mesa.batch_run( The results are returned as a list of dictionaries, which can be easily converted to a pandas DataFrame for further analysis. ### Visualization -Mesa now uses a new browser-based visualization system called SolaraViz. This allows for interactive, customizable visualizations of your models. Here's a basic example of how to set up a visualization: +Mesa now uses a new browser-based visualization system called SolaraViz. This allows for interactive, customizable visualizations of your models. > **Note:** SolaraViz is experimental and still in active development for Mesa 3.0. While we attempt to minimize them, there might be API breaking changes between Mesa 3.0 and 3.1. There won't be breaking changes between Mesa 3.0.x patch releases. +The core functionality for building your own visualizations resides in the [`mesa.visualization`](apis/visualization) namespace + +Here's a basic example of how to set up a visualization: + ```python from mesa.visualization import SolaraViz, make_space_component, make_plot_component @@ -206,28 +221,42 @@ This will create an interactive visualization of your model, including: You can also create custom visualization components using Matplotlib. For more advanced usage and customization options, please refer to the [visualization tutorial](tutorials/visualization_tutorial). -### Further resources +## Further resources To further explore Mesa and its features, we have the following resources available: -#### Tutorials -- [Introductory Tutorial](tutorials/intro_tutorial): Learn how to create your first Mesa model. -- [Visualization Tutorial](tutorials/visualization_tutorial.html): Learn how to create interactive visualizations for your models. +### Best practices +- [Mesa best practices](best-practices): an overview of tips and guidelines for using MESA. -#### API documentation +### API documentation - [Mesa API reference](apis): Detailed documentation of Mesa's classes and functions. -#### Example models +### Repository of models built using MESA - [Mesa Examples repository](https://github.com/projectmesa/mesa-examples): A collection of example models demonstrating various Mesa features and modeling techniques. -#### Migration guide +### Migration guide - [Mesa 3.0 Migration guide](migration_guide): If you're upgrading from an earlier version of Mesa, this guide will help you navigate the changes in Mesa 3.0. -#### Source Ccode and development +### Source Ccode and development - [Mesa GitHub repository](https://github.com/projectmesa/mesa): Access the full source code of Mesa, contribute to its development, or report issues. - [Mesa release notes](https://github.com/projectmesa/mesa/releases): View the detailed changelog of Mesa, including all past releases and their features. -#### Community and support +### Community and support - [Mesa GitHub Discussions](https://github.com/projectmesa/mesa/discussions): Join discussions, ask questions, and connect with other Mesa users. - [Matrix Chat](https://matrix.to/#/#project-mesa:matrix.org): Real-time chat for quick questions and community interaction. Enjoy modelling with Mesa, and feel free to reach out! + + + + + +```{toctree} +:hidden: true +:maxdepth: 7 + +tutorials/intro_tutorial +tutorials/visualization_tutorial +Best Practices + + +``` \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index 3124f488140..a0227e1ae91 100644 --- a/docs/index.md +++ b/docs/index.md @@ -50,9 +50,7 @@ pip install -U --pre mesa[rec] For help getting started with Mesa, check out these resources: -- [Mesa Overview] - Learn about Mesa's core concepts and components -- [Mesa Introductory Tutorial] - Build your first agent-based model -- [Mesa Visualization Tutorial] - Learn how to create interactive visualizations with Solara +- [Getting started] - Learn about Mesa's core concepts and components - [Migration Guide] - Upgrade to Mesa 3.0 - [Mesa Examples] - Browse user-contributed models and implementations - [GitHub Discussions] - Ask questions and discuss Mesa @@ -72,14 +70,11 @@ The original Mesa conference paper is [available here](http://conference.scipy.o :hidden: true :maxdepth: 7 -Mesa Overview -tutorials/intro_tutorial -tutorials/visualization_tutorial +Getting started Examples Migration guide -Best Practices API Documentation -Mesa Packages + ``` # Indices and tables @@ -99,3 +94,5 @@ Mesa Packages [mesa introductory tutorial]: tutorials/intro_tutorial [mesa visualization tutorial]: tutorials/visualization_tutorial [migration guide]: migration_guide +[Getting started]: getting_started + diff --git a/docs/packages.md b/docs/packages.md deleted file mode 100644 index 1ad6e10d906..00000000000 --- a/docs/packages.md +++ /dev/null @@ -1,110 +0,0 @@ -# "How To" Mesa Packages - -The Mesa core functionality is just a subset of what we believe researchers creating Agent Based Models (ABMs) will use. We designed Mesa to be extensible, so that individuals from various domains can build, maintain, and share their own packages that work with Mesa in pursuit of "unifying algorithmic theories of the relation between adaptive behavior and system complexity (Volker Grimm et al 2005)." - -**DRY Principle** - -This decoupling of code to create building blocks is a best practice in software engineering. Specifically, it exercises the [DRY principle (or don't repeat yourself)](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) (Hunt and Thomas 2010). The creators of Mesa designed Mesa in order for this principle to be exercised in the development of agent-based models (ABMs). For example, a group of health experts may create a library of human interactions on top of core Mesa. That library then is used by other health experts. So, those health experts don't have to rewrite the same basic behaviors. - -**Benefits to Scientists** - -Besides a best practice of the software engineering community, there are other benefits for the scientific community. - -1. **Reproducibility and Replicability.** Decoupled shared packages also allows for reproducibility and replicability. Having a package that is shared allows others to reproduce the model results. It also allows others to apply the model to similar phenomenon and replicate the results over a diversity of data. Both are essential part of the scientific method (Leek and Peng 2015). -2. **Accepted truths.** Once results are reproduced and replicated, a library could be considered an accepted truth, meaning that the community agrees the library does what the library intends to do and the library can be trusted to do this. Part of the idea behind 'accepted truths' is that subject matter experts are the ones that write and maintain the library. -3. **Building blocks.** Think of libraries like Legos. The researcher can borrow a piece from here or there to pull together the base of their model, so they can focus on the value add that they bring. For example, someone might pull from a human interactions library and a decision-making library and combine the two to look at how human cognitive function effects the physical spread of disease. - -**Mesa and Mesa Packages** - -Because of the possibilities of nuanced libraries, few things will actually make it into core Mesa. Mesa is intended to only include core functionality that everyone uses. However, it is not impossible that something written on the outside is brought into core at a later date if the value to everyone is proven through adoption. - -An example that is analogous to Mesa and Mesa packages is [Django](https://www.djangoproject.com/) and [Django Packages](https://djangopackages.org/). Django is a web framework that allows you to build a website in Python, but there are lots of things besides a basic website that you might want. For example, you might want authentication functionality. It would be inefficient for everyone to write their own authentication functionality, so one person writes it (or a group of people). They share it with the world and then many people can use it. - -This process isn't perfect. Just because you write something doesn't mean people are going to use it. Sometimes two different packages will be created that do similar things, but one of them does it better or is easier to use. That is the one that will get more adoption. In the world of academia, often researchers hold on to their content until they are ready to publish it. In the world of open source software, this can backfire. The sooner you open source something the more likely it will be a success, because you will build consensus and engagement. Another thing that can happen is that while you are working on perfecting it, someone else is building in the open and establishes the audience you were looking for. So, don't be afraid to start working directly out in the open and then release it to the world. - -**What is in this doc** - -There are two sections in this documentation. The first is the User Guide, which is aimed at users of packages. The section is a package development guide, which is aimed at those who want to develop packages. Without further ado, let's get started! - -## User Guide - -- Note: MESA does not endorse or verify any of the code shared through MESA packages. This is left to the domain experts of the community that created the code.\* - -**Step 1: Select a package** - -Currently, a central list of compatible packages is located on the [Mesa Wiki Packages Page](https://github.com/projectmesa/mesa/wiki/Mesa-Packages). - -**Step 2: Establish an environment** - -Create a virtual environment for the ABM you are building. The purpose of a virtual environment is to isolate the packages for your project from other projects. This is helpful when you need to use two different versions of a package or if you are running one version in production but want to test out another version. You can do with either virtualenv or Anaconda. - -> - [Why a virtual environment](https://realpython.com/blog/python/python-virtual-environments-a-primer/#why-the-need-for-virtual-environments) -> - [Virtualenv and Virtualenv Wrapper](http://docs.python-guide.org/en/latest/#python-development-environments) -> - [Creating a virtual environment with Anaconda](https://conda.io/docs/user-guide/tasks/manage-environments.html) - -**Step 3: Install the packages** - -Install the package(s) into your environment via pip/conda or GitHub. If the package is a mature package that is hosted in the Python package repository, then you can install it just like you did Mesa: - -> ```bash -> pip install package_name -> ``` - -However, sometimes it takes a little bit for projects to reach that level of maturity. In that case to use the library, you would install from GitHub (or other code repository) with something like the following: - -> ```bash -> pip install https://github.com/ -> ``` - -The commands above should also work with Anaconda, just replace the `pip` with `conda`. - -## Package Development: A "How-to Guide" - -The purpose of this section is to help you understand, setup, and distribute your Mesa package as quickly as possible. A Mesa package is just a Python package or repo. We just call it a Mesa package, because we are talking about a Python package in the context of Mesa. These instructions assume that you are a little familiar with development, but that you have little knowledge of the packaging process. - -There are two ways to share a package: - -> 1. Via GitHub or other service (e.g. GitLab, Bitbucket, etc.) -> 2. Via PyPI, the Python package manager - -Sharing a package via PyPI make it easier to install for users but is more overhead for whomever is maintaining it. However, if you are truly intending for a wider/longer-term adoption, then PyPI should be your goal. - -Most likely you created an ABM that has the code that you want to share in it, which is what the steps below describe. - -**Sharing your package** - -> 1. Layout a new file structure to move the code into and then make sure it is callable from Mesa, in a simple, easy to understand way. For example, `from example_package import foo`. See [Creating the Scaffolding](https://python-packaging.readthedocs.io/latest/minimal.html#creating-the-scaffolding). -> -> 2. [Pick a name](https://python-packaging.readthedocs.io/latest/minimal.html#picking-a-name). -> -> 3. [Create a repo on GitHub](https://help.github.com/articles/create-a-repo/). -> -> - Enter the name of the repo. -> - Select a license (not sure-- click the blue 'i' next to the i for a great run down of licenses). We recommend something permissive Apache 2.0, BSD, or MIT so that others can freely adopt it. The more permissive the more likely it will gain followers and adoption. If you do not include a license, it is our belief that you will retain all rights, which means that people can't use your project, but it should be noted that we are also not lawyers. -> - Create a readme.md file (this contains a description of the package) see an example: [Bilateral Shapley](https://github.com/tpike3/bilateralshapley/blob/master/README.md) -> -> 4. [Clone the repo to your computer](https://help.github.com/articles/cloning-a-repository/#platform-linux). -> -> 5. Copy your code directory into the repo that you cloned on your computer. -> -> 6. Add a requirements.txt file, which lets people know which external Python packages are needed to run the code in your repo. To create a file, run: `pip freeze > requirements.txt`. Note, if you are running Anaconda, you will need to install pip first: `conda install pip`. -> -> 7. `git add` all the files to the repo, which means the repo starts to track the files. Then `git commit` the files with a meaningful message. To learn more about this see: [Saving changes](https://www.atlassian.com/git/tutorials/saving-changes). Finally, you will want to `git push` all your changes to GitHub, see: [Git Push](https://help.github.com/articles/pushing-to-a-remote/). -> -> 8. Let people know about your package on the [MESA Wiki Page](https://github.com/projectmesa/mesa/wiki) and share it in the [matrix chat room](https://matrix.to/#/#project-mesa:matrix.org). In the future, we will create more of a directory, but at this point we are not there yet. - -From this point, someone can clone your repo and then add your repo to their Python path and use it in their project. However, if you want to take your package to the next level, you will want to add more structure to your package and share it on PyPI. - -**Next Level: PyPI** - -You want to do even more. The authoritative guide for python package development is through the [Python Packaging User Guide](https://packaging.python.org/). This will take you through the entire process necessary for getting your package on the Python Package Index. - -The [Python Package Index](https://pypi.org) is the main repository of software for Python Packages and following this guide will ensure your code and documentation meets the standards for distribution across the Python community. - -# References - -Grimm, Volker, Eloy Revilla, Uta Berger, Florian Jeltsch, Wolf M. Mooij, Steven F. Railsback, Hans-Hermann Thulke, Jacob Weiner, Thorsten Wiegand, and Donald L. DeAngelis. 2005. “Pattern-Oriented Modeling of Agent Based Complex Systems: Lessons from Ecology.” American Association for the Advancement of Science 310 (5750): 987–91. doi:10.1126/science.1116681. - -Hunt, Andrew, and David Thomas. 2010. The Pragmatic Programmer: From Journeyman to Master. Reading, Massachusetts: Addison-Wesley. - -Leek, Jeffrey T., and Roger D. Peng. 2015. “Reproducible Research Can Still Be Wrong: Adopting a Prevention Approach.” Proceedings of the National Academy of Sciences 112 (6): 1645–46. doi:10.1073/pnas.1421412111. diff --git a/mesa/examples/advanced/pd_grid/app.py b/mesa/examples/advanced/pd_grid/app.py index 6664e2c132f..94c2d71f482 100644 --- a/mesa/examples/advanced/pd_grid/app.py +++ b/mesa/examples/advanced/pd_grid/app.py @@ -4,11 +4,11 @@ from mesa.examples.advanced.pd_grid.model import PdGrid from mesa.visualization import ( + Slider, SolaraViz, make_plot_component, make_space_component, ) -from mesa.visualization.UserParam import Slider def pd_agent_portrayal(agent): diff --git a/mesa/visualization/__init__.py b/mesa/visualization/__init__.py index 9c2e74a2afc..bde36903be9 100644 --- a/mesa/visualization/__init__.py +++ b/mesa/visualization/__init__.py @@ -13,7 +13,7 @@ from .components import make_plot_component, make_space_component from .components.altair_components import make_space_altair from .solara_viz import JupyterViz, SolaraViz -from .UserParam import Slider +from .user_param import Slider __all__ = [ "JupyterViz", diff --git a/mesa/visualization/mpl_space_drawing.py b/mesa/visualization/mpl_space_drawing.py index 6353d8106b8..cfa1fa23a8b 100644 --- a/mesa/visualization/mpl_space_drawing.py +++ b/mesa/visualization/mpl_space_drawing.py @@ -127,7 +127,7 @@ def draw_space( case mesa.space.ContinuousSpace(): draw_continuous_space(space, agent_portrayal, ax=ax) case VoronoiGrid(): - draw_voroinoi_grid(space, agent_portrayal, ax=ax) + draw_voronoi_grid(space, agent_portrayal, ax=ax) if propertylayer_portrayal: draw_property_layers(space, propertylayer_portrayal, ax=ax) @@ -473,7 +473,7 @@ def draw_continuous_space( return ax -def draw_voroinoi_grid( +def draw_voronoi_grid( space: VoronoiGrid, agent_portrayal: Callable, ax: Axes | None = None, **kwargs ): """Visualize a voronoi grid. diff --git a/mesa/visualization/solara_viz.py b/mesa/visualization/solara_viz.py index 92ce85fa318..023d449faf2 100644 --- a/mesa/visualization/solara_viz.py +++ b/mesa/visualization/solara_viz.py @@ -32,7 +32,7 @@ import solara import mesa.visualization.components.altair_components as components_altair -from mesa.visualization.UserParam import Slider +from mesa.visualization.user_param import Slider from mesa.visualization.utils import force_update, update_counter if TYPE_CHECKING: diff --git a/mesa/visualization/UserParam.py b/mesa/visualization/user_param.py similarity index 100% rename from mesa/visualization/UserParam.py rename to mesa/visualization/user_param.py diff --git a/tests/test_components_matplotlib.py b/tests/test_components_matplotlib.py index 9c454e77b2e..78e3c33639e 100644 --- a/tests/test_components_matplotlib.py +++ b/tests/test_components_matplotlib.py @@ -23,7 +23,7 @@ draw_network, draw_orthogonal_grid, draw_property_layers, - draw_voroinoi_grid, + draw_voronoi_grid, ) @@ -74,7 +74,7 @@ def test_draw_voroinoi_grid(): agent.cell = grid.select_random_empty_cell() fig, ax = plt.subplots() - draw_voroinoi_grid(grid, agent_portrayal, ax) + draw_voronoi_grid(grid, agent_portrayal, ax) def test_draw_orthogonal_grid():