Skip to content

Commit

Permalink
Merge pull request #370 from djmitche/issue333
Browse files Browse the repository at this point in the history
Update tutorial to follow new model standards
  • Loading branch information
jackiekazil committed May 22, 2017
2 parents 4c7297f + 3deb576 commit 40bfbb2
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 128 deletions.
5 changes: 4 additions & 1 deletion docs/best-practices.rst
Expand Up @@ -17,7 +17,10 @@ underscores, such as ``thunder_cats``. Within that directory:

* ``model.py`` should contain the model class. If the file gets large, it may
make sense to move the complex bits into other files, but this is the first
place readers will look to figure out how the model lworks.
place readers will look to figure out how the model works.

* ``server.py`` should contain the visualization support, including the server
class.

* ``run.py`` is a Python script that will run the model when invoked as
``python run.py``.
Expand Down
85 changes: 50 additions & 35 deletions docs/tutorials/adv_tutorial.rst
Expand Up @@ -34,20 +34,19 @@ Grid Visualization
^^^^^^^^^^^^^^^^^^

To start with, let's have a visualization where we can watch the agents
moving around the grid. For this, you will need to put your model code
in a separate Python source file; for example, ``MoneyModel.py``. Next,
either in the same file or in a new one (e.g. ``MoneyModel_Viz.py``)
import the server class and the Canvas Grid class (so-called because it
uses HTML5 canvas to draw a grid). If you're in a new file, you'll also
need to import the actual model object.
moving around the grid. For this, you will need to create a server that
will support visualization in a web browser. Set that up in ``server.py``.

Import the server class and the Canvas Grid class (so-called because it uses
HTML5 canvas to draw a grid). If you're in a new file, you'll also need to
import the actual model object.

.. code:: python
# server.py
from mesa.visualization.modules import CanvasGrid
from mesa.visualization.ModularVisualization import ModularServer
# If MoneyModel.py is where your code is:
# from MoneyModel import MoneyModel
from model import MoneyModel
``CanvasGrid`` works by looping over every cell in a grid, and
generating a portrayal for every agent it finds. A portrayal is a
Expand All @@ -59,6 +58,7 @@ fills half of each cell.

.. code:: python
# server.py
def agent_portrayal(agent):
portrayal = {"Shape": "circle",
"Color": "red",
Expand Down Expand Up @@ -88,26 +88,34 @@ following arguments:

Once we create the server, we set the port for it to listen on (you can
treat this as just a piece of the URL you'll open in the browser).
Finally, when you're ready to run the visualization, use the server's
``launch()`` method.

.. code:: python
# server.py
server = ModularServer(MoneyModel,
[grid],
"Money Model",
100, 10, 10)
Finally, when you're ready to run the visualization, use the server's
``launch()`` method, in ``run.py``. In this arrangmenet, ``run.py`` is
very short!

.. code:: python
# run.py
from server import server
server.port = 8521 # The default
server.launch()
The full code should now look like:

.. code:: python
from MoneyModel import *
# server.py
from mesa.visualization.modules import CanvasGrid
from mesa.visualization.ModularVisualization import ModularServer
from model import MoneyModel
def agent_portrayal(agent):
portrayal = {"Shape": "circle",
Expand All @@ -122,8 +130,6 @@ The full code should now look like:
[grid],
"Money Model",
100, 10, 10)
server.port = 8521 # The default
server.launch()
Now run this file; this should launch the interactive visualization
server and open your web browser automatically. (If the browser doesn't
Expand Down Expand Up @@ -171,6 +177,7 @@ to change the portrayal based on the agent properties.

.. code:: python
# server.py
def agent_portrayal(agent):
portrayal = {"Shape": "circle",
"Filled": "true",
Expand Down Expand Up @@ -205,6 +212,7 @@ provides.

.. code:: python
# server.py
from mesa.visualization.modules import ChartModule
The basic chart pulls data from the model's DataCollector, and draws it
Expand All @@ -221,6 +229,7 @@ chart will appear underneath the grid.

.. code:: python
# server.py
chart = ChartModule([{"Label": "Gini",
"Color": "Black"}],
data_collector_name='datacollector')
Expand Down Expand Up @@ -297,6 +306,7 @@ the class itself:

.. code:: javascript
// HistogramModule.js
var HistogramModule = function(bins, canvas_width, canvas_height) {
// The actual code will go here.
};
Expand All @@ -314,6 +324,7 @@ context, which is required for doing anything with it.

.. code:: javascript
// HistogramModule.js
var HistogramModule = function(bins, canvas_width, canvas_height) {
// Create the tag:
var canvas_tag = "<canvas width='" + canvas_width + "' height='" + canvas_height + "' ";
Expand All @@ -337,6 +348,7 @@ created, we can create the chart object.

.. code:: javascript
// HistogramModule.js
var HistogramModule = function(bins, canvas_width, canvas_height) {
// Create the elements
Expand Down Expand Up @@ -394,6 +406,7 @@ With that in mind, we can add these two methods to the class:

.. code:: javascript
// HistogramModule.js
var HistogramModule = function(bins, canvas_width, canvas_height) {
// ...Everything from above...
this.render = function(data) {
Expand Down Expand Up @@ -431,21 +444,22 @@ inherit from, and create the new visualization class.

.. code:: python
from mesa.visualization.ModularVisualization import VisualizationElement
# server.py
from mesa.visualization.ModularVisualization import VisualizationElement
class HistogramModule(VisualizationElement):
package_includes = ["Chart.min.js"]
local_includes = ["HistogramModule.js"]
def __init__(self, bins, canvas_height, canvas_width):
self.canvas_height = canvas_height
self.canvas_width = canvas_width
self.bins = bins
new_element = "new HistogramModule({}, {}, {})"
new_element = new_element.format(bins,
canvas_width,
canvas_height)
self.js_code = "elements.push(" + new_element + ");"
class HistogramModule(VisualizationElement):
package_includes = ["Chart.min.js"]
local_includes = ["HistogramModule.js"]
def __init__(self, bins, canvas_height, canvas_width):
self.canvas_height = canvas_height
self.canvas_width = canvas_width
self.bins = bins
new_element = "new HistogramModule({}, {}, {})"
new_element = new_element.format(bins,
canvas_width,
canvas_height)
self.js_code = "elements.push(" + new_element + ");"
There are a few things going on here. ``package_includes`` is a list of
JavaScript files that are part of Mesa itself that the visualization
Expand All @@ -471,6 +485,7 @@ general, but in this case we can hard-code it to our model.

.. code:: python
# server.py
import numpy as np
class HistogramModule(VisualizationElement):
Expand All @@ -493,12 +508,12 @@ Now, you can create your new HistogramModule and add it to the server:

.. code:: python
histogram = HistogramModule(list(range(10)), 200, 500)
server = ModularServer(MoneyModel,
[grid, histogram, chart],
"Money Model",
100, 10, 10)
server.launch()
# server.py
histogram = HistogramModule(list(range(10)), 200, 500)
server = ModularServer(MoneyModel,
[grid, histogram, chart],
"Money Model",
100, 10, 10)
Run this code, and you should see your brand-new histogram added to the
visualization and updating along with the model!
Expand Down

0 comments on commit 40bfbb2

Please sign in to comment.