diff --git a/.gitignore b/.gitignore
index fe1ef1eb62f..e82b6c6b6d9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,4 +56,8 @@ docs/_build/
# PyBuilder
target/
+# Jupyter and iPython notebook checkpoints
*.ipynb_checkpoints
+
+# Spyder app workspace config file
+.spyderworkspace
diff --git a/examples/ColorPatches/Readme.md b/examples/ColorPatches/Readme.md
new file mode 100644
index 00000000000..b63725e8c44
--- /dev/null
+++ b/examples/ColorPatches/Readme.md
@@ -0,0 +1,33 @@
+## Color Patches:
+Is a cellulat automaton model where each agent lives in a cell on a 2D grid, and never moves.
+An agent's state represents its "opinion" and is shown by the color of the cell the agent lives in. Each color represents an opinion - there are 16 of them.
+At each time step, an agent's opinion is influenced by that of its neighbors, and changes to the most common one found; ties are randomly arbitrated.
+As an agent adapts its thinking to that of its neighbors, the cell color changes.
+
+
+### Parameters you can play with:
+(you must change the code to alter the parameters at this stage)
+* Vary the number of opinions.
+* Vary the size of the grid
+* Change the grid from fixed borders to a torus continuum
+
+
+### Observe
+* how groups of like minded agents form and evolve
+* how sometimes a single opinion prevails
+* how some minority or fragmented opinions rapidly disappear
+
+
+### Sources and Attribution
+Inspired from [this model](http://www.cs.sjsu.edu/~pearce/modules/lectures/abs/as/ca.htm) from San Jose University
+Other similar models: [Schelling Segregation Model](https://github.com/projectmesa/mesa/tree/master/examples/Schelling)
+
+
+### To run this example
+
+* Launch the model
+```python
+python color_patches.py
+```
+* Visit your browser: http://127.0.0.1:8888/
+* In your browser hit *reset*, then *run*
diff --git a/examples/ColorPatches/color_cell.py b/examples/ColorPatches/color_cell.py
new file mode 100644
index 00000000000..e3b86789f09
--- /dev/null
+++ b/examples/ColorPatches/color_cell.py
@@ -0,0 +1,67 @@
+"""
+Subclassing Agent to represent a cell
+"""
+
+
+from collections import Counter
+import random
+
+from mesa import Agent
+
+
+
+class ColorCell(Agent):
+ '''
+ Represents a cell's opinion (visualized by a color)
+ '''
+
+ OPINIONS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
+
+
+ def __init__(self, pos, model, initial_state):
+ '''
+ Create a cell, in the given state, at the given row, col position.
+ '''
+ Agent.__init__(self, pos, model)
+ self._row = pos[1]
+ self._col = pos[0]
+ self._state = initial_state
+ self._next_state = None
+
+ def get_col(self):
+ '''Return the col location of this cell.'''
+ return self._col
+
+ def get_row(self):
+ '''Return the row location of this cell.'''
+ return self._row
+
+ def get_state(self):
+ '''Return the current state (OPINION) of this cell.'''
+ return self._state
+
+ def step(self, model):
+ '''
+ Determines the agent opinion for the next step by polling its neighbors
+ The opinion is determined by the majority of the 8 neighbors' opinion
+ A choice is made at random in case of a tie
+ The next state is stored until all cells have been polled
+ '''
+ neighbors_opinion = Counter(n.get_state() \
+ for n in model.grid.neighbor_iter((self._col, self._row), True))
+ polled_opinions = neighbors_opinion.most_common() #a tuple (attribute, occurrences)
+ tied_opinions = []
+ for neighbor in polled_opinions:
+ if neighbor[1] == polled_opinions[0][1]:
+ tied_opinions.append(neighbor)
+
+ self._next_state = random.choice(tied_opinions)[0]
+
+
+ # model argument is unused
+ def advance(self, model):
+ '''
+ Set the state of the agent to the next state
+ '''
+ self._state = self._next_state
+
diff --git a/examples/ColorPatches/color_patch_model.py b/examples/ColorPatches/color_patch_model.py
new file mode 100644
index 00000000000..921c973f8af
--- /dev/null
+++ b/examples/ColorPatches/color_patch_model.py
@@ -0,0 +1,80 @@
+"""
+The model - a 2D lattice where agents live and have an opinion
+"""
+
+
+import random
+
+from mesa import Model
+from mesa.time import SimultaneousActivation
+from mesa.space import Grid
+from color_cell import ColorCell
+
+
+
+class ColorPatchModel(Model):
+ '''
+ represents a 2D lattice where agents live
+ '''
+
+ def __init__(self, height, width):
+ '''
+ Create a 2D lattice with strict borders where agents live
+ The agents next state is first determined before updating the grid
+ '''
+
+ self._grid = Grid(height, width, torus=False)
+ self._schedule = SimultaneousActivation(self)
+
+ # self._grid.coord_iter()
+ # --> should really not return content + col + row
+ # -->but only col & row
+ # for (contents, col, row) in self._grid.coord_iter():
+ # replaced content with _ to appease linter
+ for (_, col, row) in self._grid.coord_iter():
+ cell = ColorCell((col, row), self, ColorCell.OPINIONS[random.randrange(0, 16)])
+ self._grid.place_agent(cell, (col, row))
+ self._schedule.add(cell)
+
+ self.running = True
+
+ def step(self):
+ '''
+ Advance the model one step.
+ '''
+ self._schedule.step()
+
+
+
+ # the following is a temporary fix for the framework classes accessing model
+ # attributes directly
+ # I don't think it should
+ # --> it imposes upon the model builder to use the attributes names that
+ # the framework expects.
+ #
+ # Traceback included in docstrings
+
+ @property
+ def grid(self):
+ """
+ /mesa/visualization/modules/CanvasGridVisualization.py
+ is directly accessing Model.grid
+ 76 def render(self, model):
+ 77 grid_state = defaultdict(list)
+ ---> 78 for y in range(model.grid.height):
+ 79 for x in range(model.grid.width):
+ 80 cell_objects = model.grid.get_cell_list_contents([(x, y)])
+
+ AttributeError: 'ColorPatchModel' object has no attribute 'grid'
+ """
+ return self._grid
+
+ @property
+ def schedule(self):
+ """
+ mesa_ABM/examples_ABM/color_patches/mesa/visualization/ModularVisualization.py",
+ line 278, in run_model
+ while self.model.schedule.steps < self.max_steps and self.model.running:
+ AttributeError: 'NoneType' object has no attribute 'steps'
+ """
+ return self._schedule
diff --git a/examples/ColorPatches/color_patches.py b/examples/ColorPatches/color_patches.py
new file mode 100644
index 00000000000..02713e19088
--- /dev/null
+++ b/examples/ColorPatches/color_patches.py
@@ -0,0 +1,50 @@
+"""
+handles the definition of the canvas parameters and
+the drawing of the model representation on the canvas
+"""
+
+
+from color_patch_model import ColorPatchModel
+from mesa.visualization.modules import CanvasGrid
+from mesa.visualization.ModularVisualization import ModularServer
+
+
+_COLORS = ['Aqua', 'Blue', 'Fuchsia', 'Gray', 'Green',
+ 'Lime', 'Maroon', 'Navy', 'Olive', 'Orange', 'Purple',
+ 'Red', 'Silver', 'Teal', 'White', 'Yellow']
+
+
+GRID_ROWS = 25
+GRID_COLS = 50
+CELL_SIZE = 10
+CANVAS_HEIGHT = GRID_ROWS * CELL_SIZE
+CANVAS_WIDTH = GRID_COLS * CELL_SIZE
+
+
+def color_patch_draw(cell):
+ '''
+ This function is registered with the visualization server to be called
+ each tick to indicate how to draw the cell in its current state.
+
+ :param cell: the cell in the simulation
+
+ :return: the portrayal dictionary.
+
+ '''
+ assert cell is not None
+ portrayal = {"Shape": "rect", "w": 1, "h": 1, "Filled": "true", "Layer": 0}
+ portrayal["x"] = cell.get_col()
+ portrayal["y"] = cell.get_row()
+ portrayal["Color"] = _COLORS[cell.get_state()]
+ return portrayal
+
+
+CANVAS_ELEMENT = CanvasGrid(color_patch_draw,
+ GRID_COLS, GRID_ROWS,
+ CANVAS_HEIGHT, CANVAS_WIDTH)
+
+SERVER = ModularServer(ColorPatchModel,
+ [CANVAS_ELEMENT], "Color Patches",
+ GRID_ROWS, GRID_COLS)
+
+SERVER.launch()
diff --git a/examples/Readme.md b/examples/Readme.md
index 0b46a9962c6..04719f670a3 100644
--- a/examples/Readme.md
+++ b/examples/Readme.md
@@ -2,6 +2,9 @@
This directory contains example models meant to test and demonstrate Mesa's features, and provide demonstrations for how to build and analyze agent-based models. For more information on each model, see its own Readme and documentation.
+### Color Patches
+A cellular automaton model where agents opinions are influenced by that of their neighbors. As the model evolves, color patches representing the prevailing opinion in a given area expand, contract, and sometimes disappear.
+
### Conway's Game Of Life
An implementation of the Famous Pr. Conway's Game Of Life