Skip to content

Commit

Permalink
Merge pull request #17 from jameslawlor/chores/migrate-to-config-yaml
Browse files Browse the repository at this point in the history
Chores/migrate to config yaml
  • Loading branch information
jameslawlor authored May 4, 2024
2 parents c5cf552 + 386f259 commit 2e04843
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 63 deletions.
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
ruff==0.3.4
numpy==1.26.4
matplotlib==3.8.3
pytest==8.0.2
pytest==8.0.2
PyYAML==6.0.1
7 changes: 7 additions & 0 deletions src/pyturmite/configs/plotting/animation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cmap: "Oranges"
plot_mode: "animate"
canvas_size: 8
padding_size: 2 # expand in each direction by this amount of cells
animation_interval: 1
save_animation: False
frame_skip: 1
4 changes: 4 additions & 0 deletions src/pyturmite/configs/plotting/static.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cmap: "Oranges"
plot_mode: "static"
canvas_size: 8
padding_size: 2 # expand in each direction by this amount of cells
3 changes: 3 additions & 0 deletions src/pyturmite/configs/turmites/langton.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
n_steps: 20000
ruleset: "classic"
instructions: "RL" # "Classic" instructions format
6 changes: 6 additions & 0 deletions src/pyturmite/configs/turmites/turmite.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
n_steps: 20000
ruleset: "stateful" # 'classic' or 'stateful'
instructions: [ # triplet notation (write colour, turn instruction, next state)
[(1, 'R', 0),(1, 'R', 1)], # one state per row, one colour per tuple
[(0, 'N', 0),(0, 'N', 1)],
]
14 changes: 0 additions & 14 deletions src/pyturmite/constants.py

This file was deleted.

33 changes: 26 additions & 7 deletions src/pyturmite/main.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
from pyturmite.turmites import ClassicTurmite, StatefulTurmite
from pyturmite.utils.plotters import Plotter
from pyturmite.utils.input_handling import parse_args
from pyturmite.utils.input_handling import Config


def main():
args = parse_args()
if args.ruleset == "classic":
config = Config()
config.load()

print(config)

if config.ruleset == "classic":
turmite = ClassicTurmite()
elif args.ruleset == "stateful":
elif config.ruleset == "stateful":
turmite = StatefulTurmite()

turmite.init_grid(canvas_size=args.canvas_size)
plotter = Plotter(mode=args.plot_mode)
plotter.plot(turmite=turmite, n_steps=args.n_steps)
turmite.load(
instructions=config.instructions,
padding_size=config.padding_size,
ruleset=config.ruleset,
cmap_str=config.cmap,
canvas_size=config.canvas_size,
)

plotter = Plotter(
mode=config.plot_mode,
animation_interval=config.animation_interval,
save_animation=config.save_animation,
frame_skip=config.frame_skip,
)
plotter.plot(
turmite=turmite,
n_steps=config.n_steps,
)


if __name__ == "__main__":
Expand Down
42 changes: 21 additions & 21 deletions src/pyturmite/turmites.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import numpy as np
import matplotlib.pylab as plt
from pyturmite.constants import (
CMAP,
RULESET,
PADDING_SIZE,
INSTRUCTIONS,
)


class Direction:
Expand All @@ -22,21 +16,18 @@ class Turmite:

def __init__(
self,
x0=0,
y0=0,
initial_direction=Direction.U,
instructions=INSTRUCTIONS,
ruleset=RULESET,
):
self.x = x0
self.y = y0
self.dir = initial_direction
self.ruleset = ruleset
self.cmap = plt.get_cmap(CMAP)
self.x = 0
self.y = 0
self.dir = Direction.U
self.ruleset = None
self.cmap_str = ""
self.cmap = plt.get_cmap()
self.n_colours = 0
self.parse_instructions(instructions)
self.instructions = None
self.movement_history = []
self.colour_history = []
self.padding_size = 0

def __str__(self):
return str(vars(self))
Expand Down Expand Up @@ -119,9 +110,9 @@ def expand_grid(self):
or (self.y >= self.grid.shape[1])
or (self.y < 0)
):
self.grid = np.pad(self.grid, PADDING_SIZE)
self.x += PADDING_SIZE
self.y += PADDING_SIZE
self.grid = np.pad(self.grid, self.padding_size)
self.x += self.padding_size
self.y += self.padding_size

def update(self):
raise NotImplementedError(
Expand All @@ -134,6 +125,15 @@ def parse_instructions(self, *args):
def turn(self, *args):
raise NotImplementedError("turn method not implemented in base turmite class!")

def load(self, instructions, padding_size, ruleset, cmap_str, canvas_size):
self.instructions = instructions
self.parse_instructions(instructions)
self.padding_size = padding_size
self.ruleset = ruleset
self.cmap = plt.get_cmap(cmap_str)
self.canvas_size = canvas_size
self.init_grid(canvas_size)


class ClassicTurmite(Turmite):
"""
Expand Down Expand Up @@ -193,7 +193,7 @@ def parse_instructions(self, input_instructions):
col = colour
"""
# TODO: Check validity
self.cmap = plt.get_cmap(CMAP)
self.cmap = plt.get_cmap(self.cmap)
colours = self.cmap(np.linspace(0.0, 1, len(input_instructions[0])))
self.n_colours = len(colours)
self.n_states = len(input_instructions)
Expand Down
50 changes: 38 additions & 12 deletions src/pyturmite/utils/input_handling.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,48 @@
import argparse
from pyturmite.constants import (
CANVAS_SIZE,
N_STEPS,
PLOT_MODE,
RULESET,
)
import yaml


def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("--ant_config_path", required=True, type=str)
parser.add_argument("--plotting_config_path", required=True, type=str)
args = parser.parse_args()
return args

parser.add_argument("--n_steps", required=False, type=int, default=N_STEPS)

parser.add_argument("--canvas_size", required=False, type=int, default=CANVAS_SIZE)
def load_yaml_file_to_json(path):
with open(path, "r") as stream:
return yaml.safe_load(stream)

parser.add_argument("--plot_mode", required=False, type=str, default=PLOT_MODE)

parser.add_argument("--ruleset", required=False, type=str, default=RULESET)
class Config:
def __init__(self):
input_args = parse_args()
self.ant_config_path = input_args.ant_config_path
self.plotting_config_path = input_args.plotting_config_path

args = parser.parse_args()
return args
self.instructions = None
self.ruleset = ""
self.padding_size = 0
self.canvas_size = 0
self.cmap = ""
self.plot_mode = ""
self.n_steps = 0
self.animation_interval = 0
self.frame_skip = 0
self.save_animation = False

def __str__(self):
return str(vars(self))

def _set_attributes_from_dictionary(self, dictionary):
for k, v in dictionary.items():
setattr(self, k, v)

def _load_config_from_path(self, path):
raw_config = load_yaml_file_to_json(path)
self._set_attributes_from_dictionary(raw_config)

def load(self):
self._load_config_from_path(self.ant_config_path)
self._load_config_from_path(self.plotting_config_path)
20 changes: 12 additions & 8 deletions src/pyturmite/utils/plotters.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
from functools import partial
import numpy as np

from pyturmite.constants import ANIMATION_INTERVAL, SAVE_ANIMATION, FRAME_SKIP


class Plotter:
def __init__(self, mode):
def __init__(self, mode, animation_interval, save_animation, frame_skip):
self.turmite = None
self.mode = mode
self.animation_interval = animation_interval
self.save_animation = save_animation
self.frame_skip = frame_skip
self.plot = self.get_plotting_function()

def get_plotting_function(self):
Expand Down Expand Up @@ -78,13 +79,16 @@ def animate(self, turmite, n_steps):
)
plt.axis("off")

def update(step, turmite, skip=FRAME_SKIP):
for _ in range(skip):
def update(
step,
turmite,
):
for _ in range(self.frame_skip):
turmite.update()
data = np.array(turmite.grid)
data[turmite.x][turmite.y] = turmite.n_colours + 1
im.set_data(data)
frame_num.set_text(f"Step: {step*skip:,}")
frame_num.set_text(f"Step: {step*self.frame_skip:,}")
return [im, frame_num]

anim = FuncAnimation( # noqa: F841
Expand All @@ -94,12 +98,12 @@ def update(step, turmite, skip=FRAME_SKIP):
turmite=turmite,
),
frames=n_steps,
interval=ANIMATION_INTERVAL,
interval=self.animation_interval,
blit=True,
repeat=False,
)

if SAVE_ANIMATION:
if self.save_animation:
anim.save(
"example.mp4",
writer="ffmpeg",
Expand Down

0 comments on commit 2e04843

Please sign in to comment.