Skip to content

Commit

Permalink
Merge pull request #383 from TaylorMutch/bootstrap-ui
Browse files Browse the repository at this point in the history
Bootstrap UI starter
  • Loading branch information
dmasad committed Jul 2, 2017
2 parents c38681a + f4afad6 commit bce8322
Show file tree
Hide file tree
Showing 58 changed files with 14,135 additions and 304 deletions.
5 changes: 4 additions & 1 deletion MANIFEST.in
Expand Up @@ -3,4 +3,7 @@ include LICENSE
include HISTORY.rst
include README.rst
include setup.py
include mesa/visualization/templates/*
include mesa/visualization/templates/*.html
include mesa/visualization/templates/css/*
include mesa/visualization/templates/fonts/*
include mesa/visualization/templates/js/*
75 changes: 55 additions & 20 deletions docs/tutorials/adv_tutorial.rst
Expand Up @@ -83,8 +83,7 @@ following arguments:
- A list of module objects to include in the visualization; here, just
``[grid]``
- The title of the model: "Money Model"
- Any inputs or arguments for the model itself. In this case, 100
agents, and height and width of 10.
- A dictionary of arguments for the model itself. In this case, ``{"N": 100, "width": 10, "height": 10}``

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).
Expand All @@ -95,7 +94,7 @@ treat this as just a piece of the URL you'll open in the browser).
server = ModularServer(MoneyModel,
[grid],
"Money Model",
100, 10, 10)
{"N": 100, "width": 10, "height": 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
Expand Down Expand Up @@ -129,25 +128,16 @@ The full code should now look like:
server = ModularServer(MoneyModel,
[grid],
"Money Model",
100, 10, 10)
{"N": 100, "width": 10, "height": 10})
Now run this file; this should launch the interactive visualization
server and open your web browser automatically. (If the browser doesn't
open automatically, try pointing it at http://127.0.0.1:8521 manually.
If this doesn't show you the visualization, something may have gone
wrong with the server launch.)

You should see something like the figure below: the model title, an
empty space where the grid will be, and a control panel off to the
right.

.. figure:: files/viz_empty.png
:alt: Empty Visualization

Empty Visualization

Click the 'reset' button on the control panel, and you should see the
grid fill up with red circles, representing agents.
You should see something like the figure below: the model title, a grid with
red circles respresenting the agents, and the model controls at the top.

.. figure:: files/viz_redcircles.png
:alt: Redcircles Visualization
Expand Down Expand Up @@ -237,7 +227,7 @@ chart will appear underneath the grid.
server = ModularServer(MoneyModel,
[grid, chart],
"Money Model",
100, 10, 10)
{"N": 100, "width": 10, "height": 10})
Launch the visualization and start a model run, and you'll see a line
chart underneath the grid. Every step of the model, the line chart
Expand All @@ -248,9 +238,54 @@ updates along with the grid. Reset the model, and the chart resets too.

Chart Visualization

**Note:** You might notice that the chart line only starts after a
couple of steps; this is due to a bug in Charts.js which will hopefully
be fixed soon.

Making a parameter interactive
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

One of the reasons we want to be able to watch a model run is to conduct ad-hoc
experiments -- for example, to get an idea of how the model changes with
different parameter values. Having to stop the simulation, edit a parameter
value, and relaunch isn't an ideal way to go about it. That's why Mesa lets you
set any parameter to be interactive, using the ``UserSettableParameter`` class.

For this example, we'll add a slider that controls how ``N``, many agents there
are in the model. To do this, we need to choose the starting value (let's keep
this at 100); the minimum parameter value we'll allow (let's do 2, since one
agent alone will have nobody to trade with) and the maximum (we'll say 200);
and the increment the slider will go in (set this to 1, since there's no such
thing as a fraction of an agent). This looks like this:

.. code:: python
from mesa.visualization.UserParam import UserSettableParameter
n_slider = UserSettableParameter('slider', "Number of Agents", 100, 2, 200, 1)
To incorporate it into the model visualization interface, we make the slider
one of the model inputs, replacing the static parameter:

.. code:: python
# server.py
chart = ChartModule([{"Label": "Gini",
"Color": "Black"}],
data_collector_name='datacollector')
server = ModularServer(MoneyModel,
[grid, chart],
"Money Model",
{"N": n_slider, "width": 10, "height": 10})
When you launch the model, you'll see a slider, labeled "Number of Agents", on
the left side of the interface. Try moving the slider around, then press Reset
to restart the model with the number of agents you set. Parameter changes don't
take effect until you reset the model.

.. figure:: files/viz_slider.png
:alt: User-settable slider for parameter

User-Settable Parameter Slider


Building your own visualization component
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -513,7 +548,7 @@ Now, you can create your new HistogramModule and add it to the server:
server = ModularServer(MoneyModel,
[grid, histogram, chart],
"Money Model",
100, 10, 10)
{"N": n_slider, "width": 10, "height": 10})
Run this code, and you should see your brand-new histogram added to the
visualization and updating along with the model!
Expand Down
Binary file modified docs/tutorials/files/viz_chart.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/tutorials/files/viz_greycircles.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/tutorials/files/viz_redcircles.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/tutorials/files/viz_slider.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 10 additions & 2 deletions examples/Flockers/flockers/server.py
Expand Up @@ -8,5 +8,13 @@ def boid_draw(agent):
return {"Shape": "circle", "r": 2, "Filled": "true", "Color": "Red"}

boid_canvas = SimpleCanvas(boid_draw, 500, 500)
server = ModularServer(BoidModel, [boid_canvas], "Boids",
100, 100, 100, 1, 10, 2)
model_params = {
"N": 100,
"width": 100,
"height": 100,
"speed": 5,
"vision": 10,
"separation": 2
}

server = ModularServer(BoidModel, [boid_canvas], "Boids", model_params)
2 changes: 1 addition & 1 deletion examples/Flockers/flockers/simple_continuous_canvas.js
Expand Up @@ -65,7 +65,7 @@ var Simple_Continuous_Module = function(canvas_width, canvas_height) {
canvas_tag += "style='border:1px dotted'></canvas>";
// Append it to body:
var canvas = $(canvas_tag)[0];
$("body").append(canvas);
$("#elements").append(canvas);

// Create the context and the drawing controller:
var context = canvas.getContext("2d");
Expand Down
13 changes: 12 additions & 1 deletion examples/Schelling/server.py
@@ -1,5 +1,7 @@
from mesa.visualization.ModularVisualization import ModularServer
from mesa.visualization.modules import CanvasGrid, ChartModule, TextElement
from mesa.visualization.UserParam import UserSettableParameter

from mesa.visualization.TextVisualization import (
TextData, TextGrid, TextVisualization
)
Expand Down Expand Up @@ -61,7 +63,16 @@ def schelling_draw(agent):
happy_element = HappyElement()
canvas_element = CanvasGrid(schelling_draw, 20, 20, 500, 500)
happy_chart = ChartModule([{"Label": "happy", "Color": "Black"}])

model_params = {
"height": 20,
"width": 20,
"density": UserSettableParameter("slider", "Agent density", 0.8, 0.1, 1.0, 0.1),
"minority_pc": UserSettableParameter("slider", "Fraction minority", 0.2, 0.00, 1.0, 0.05),
"homophily": UserSettableParameter("slider", "Homophily", 3, 0, 8, 1)
}

server = ModularServer(SchellingModel,
[canvas_element, happy_element, happy_chart],
"Schelling", 20, 20, 0.8, 0.2, 4)
"Schelling", model_params)
server.launch()
7 changes: 6 additions & 1 deletion examples/boltzmann_wealth_model/wealth_model/model.py
Expand Up @@ -15,7 +15,12 @@ def compute_gini(model):


class MoneyModel(Model):
"""A model with some number of agents."""
"""A simple model of an economy where agents exchange currency at random.
All the agents begin with one unit of currency, and each time step can give
a unit of currency to another agent. Note how, over time, this produces a
highly skewed distribution of wealth.
"""

def __init__(self, N, width, height):
self.num_agents = N
Expand Down
10 changes: 9 additions & 1 deletion examples/boltzmann_wealth_model/wealth_model/server.py
Expand Up @@ -3,6 +3,7 @@

from mesa.visualization.modules import CanvasGrid
from mesa.visualization.modules import ChartModule
from mesa.visualization.UserParam import UserSettableParameter


def agent_portrayal(agent):
Expand All @@ -25,5 +26,12 @@ def agent_portrayal(agent):
data_collector_name='datacollector'
)

server = ModularServer(MoneyModel, [grid, chart], "Money Model", 100, 10, 10)
model_params = {
"N": UserSettableParameter('slider', "Number of agents", 100, 2, 200, 1,
description="Choose how many agents to include in the model"),
"width": 10,
"height": 10
}

server = ModularServer(MoneyModel, [grid, chart], "Money Model", model_params)
server.port = 8521
20 changes: 10 additions & 10 deletions examples/color_patches/color_patches/server.py
Expand Up @@ -14,11 +14,11 @@
'Red', 'Silver', 'Teal', 'White', 'Yellow']


GRID_ROWS = 50
GRID_COLS = 25
CELL_SIZE = 10
CANVAS_WIDTH = GRID_ROWS * CELL_SIZE
CANVAS_HEIGHT = GRID_COLS * CELL_SIZE
grid_rows = 50
grid_cols = 25
cell_size = 10
canvas_width = grid_rows * cell_size
canvas_height = grid_cols * cell_size


def color_patch_draw(cell):
Expand All @@ -39,12 +39,12 @@ def color_patch_draw(cell):
return portrayal


CANVAS_ELEMENT = CanvasGrid(color_patch_draw,
GRID_ROWS, GRID_COLS,
CANVAS_WIDTH, CANVAS_HEIGHT)
canvas_element = CanvasGrid(color_patch_draw,
grid_rows, grid_cols,
canvas_width, canvas_height)

server = ModularServer(ColorPatchModel,
[CANVAS_ELEMENT], "Color Patches",
GRID_ROWS, GRID_COLS)
[canvas_element], "Color Patches",
{"width": canvas_width, "height": canvas_height})

# webbrowser.open('http://127.0.0.1:8521') # TODO: make this configurable
2 changes: 1 addition & 1 deletion examples/conways_game_of_life/game_of_life/server.py
Expand Up @@ -9,4 +9,4 @@
canvas_element = CanvasGrid(portrayCell, 50, 50, 250, 250)

server = ModularServer(GameOfLife, [canvas_element], "Game of Life",
50, 50)
{"height": 50, "width": 50})
20 changes: 11 additions & 9 deletions examples/epstein_civil_violence/civil_violence/server.py
Expand Up @@ -33,14 +33,16 @@ def citizen_cop_portrayal(agent):
portrayal["Layer"] = 1
return portrayal


model_params = dict(height=40,
width=40,
citizen_density=.7,
cop_density=.074,
citizen_vision=7,
cop_vision=7,
legitimacy=.8,
max_jail_term=1000)

canvas_element = CanvasGrid(citizen_cop_portrayal, 40, 40, 500, 500)
server = ModularServer(CivilViolenceModel, [canvas_element],
"Epstein Civil Violence",
height=40,
width=40,
citizen_density=.7,
cop_density=.074,
citizen_vision=7,
cop_vision=7,
legitimacy=.8,
max_jail_term=1000)
"Epstein Civil Violence", model_params)
10 changes: 9 additions & 1 deletion examples/forest_fire/forest_fire/server.py
@@ -1,5 +1,7 @@
from mesa.visualization.modules import CanvasGrid, ChartModule
from mesa.visualization.ModularVisualization import ModularServer
from mesa.visualization.UserParam import UserSettableParameter


from forest_fire.model import ForestFire

Expand All @@ -22,5 +24,11 @@ def forest_fire_portrayal(tree):
{"Label": "On Fire", "Color": "red"},
{"Label": "Burned Out", "Color": "black"}])


model_params = {
"height": 100,
"width": 100,
"density": UserSettableParameter("slider", "Tree density", 0.65, 0.01, 1.0, 0.01)
}
server = ModularServer(ForestFire, [canvas_element, tree_chart], "Forest Fire",
100, 100, 0.65)
model_params)
12 changes: 10 additions & 2 deletions examples/pd_grid/pd_grid/server.py
@@ -1,5 +1,6 @@
from mesa.visualization.ModularVisualization import ModularServer
from mesa.visualization.modules import CanvasGrid
from mesa.visualization.UserParam import UserSettableParameter

from .portrayal import portrayPDAgent
from .model import PDModel
Expand All @@ -8,5 +9,12 @@
# Make a world that is 50x50, on a 500x500 display.
canvas_element = CanvasGrid(portrayPDAgent, 50, 50, 500, 500)

server = ModularServer(PDModel, [canvas_element], "Prisoner's Dilemma", 50, 50,
'Random')
model_params = {
"height": 50,
"width": 50,
"schedule_type": UserSettableParameter("choice", "Scheduler type", value="Random",
choices=list(PDModel.schedule_types.keys()))
}

server = ModularServer(PDModel, [canvas_element], "Prisoner's Dilemma",
model_params)
2 changes: 1 addition & 1 deletion examples/shape_example/shape_model/server.py
Expand Up @@ -36,7 +36,7 @@ def launch_shape_model():
grid = CanvasGrid(agent_draw, width, height,
width * pixel_ratio, height * pixel_ratio)
server = ModularServer(ShapesModel, [grid], "Shape Model Example",
num_agents, width, height)
{"N": num_agents, "width": width, "height": height})
server.max_steps = 0
server.port = 8521
server.launch()
Expand Down
2 changes: 2 additions & 0 deletions examples/wolf_sheep/wolf_sheep/model.py
Expand Up @@ -41,6 +41,8 @@ class WolfSheepPredation(Model):

verbose = False # Print-monitoring

description = 'A model for simulating wolf and sheep (predator-prey) ecosystem modelling.'

def __init__(self, height=20, width=20,
initial_sheep=100, initial_wolves=50,
sheep_reproduce=0.04, wolf_reproduce=0.05,
Expand Down
15 changes: 14 additions & 1 deletion examples/wolf_sheep/wolf_sheep/server.py
@@ -1,5 +1,6 @@
from mesa.visualization.ModularVisualization import ModularServer
from mesa.visualization.modules import CanvasGrid, ChartModule
from mesa.visualization.UserParam import UserSettableParameter

from wolf_sheep.agents import Wolf, Sheep, GrassPatch
from wolf_sheep.model import WolfSheepPredation
Expand Down Expand Up @@ -43,5 +44,17 @@ def wolf_sheep_portrayal(agent):
{"Label": "Sheep", "Color": "#666666"}])

server = ModularServer(WolfSheepPredation, [canvas_element, chart_element],
"WolfSheep", grass=True)
"Wolf Sheep Predation",
model_params=dict(
grass=UserSettableParameter('checkbox', 'Grass Enabled', True),
grass_regrowth_time=UserSettableParameter('slider', 'Grass Regrowth Time', 20, 1, 50),
initial_sheep=UserSettableParameter('slider', 'Initial Sheep Population', 100, 10, 300),
sheep_reproduce=UserSettableParameter('slider', 'Sheep Reproduction Rate', 0.04, 0.01, 1.0, 0.01),
initial_wolves=UserSettableParameter('slider', 'Initial Wolf Population', 50, 10, 300),
wolf_reproduce=UserSettableParameter('slider', 'Wolf Reproduction Rate', 0.05, 0.01, 1.0, 0.01,
description="The rate at which wolf agents reproduce."),
wolf_gain_from_food=UserSettableParameter('slider', 'Wolf Gain From Food Rate', 20, 1, 50),
sheep_gain_from_food=UserSettableParameter('slider', 'Sheep Gain From Food', 4, 1, 10)
)
)
# server.launch()

0 comments on commit bce8322

Please sign in to comment.