diff --git a/Project Reflection MP 2.ipynb b/Project Reflection MP 2.ipynb new file mode 100644 index 0000000..e24388a --- /dev/null +++ b/Project Reflection MP 2.ipynb @@ -0,0 +1,44 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Project Reflection:\n", + "\n", + "What went well?\n", + "With a little bit of help/new perspectives from the ninjas, I always made a big step towards the goal, so starting early paid off.\n", + "\n", + "What could you improve?\n", + "Work in longer stretches. I probably wasted a lot of time, because I had to get into the system again. Also I'm still not feeling confident with the application of recursion.\n", + "\n", + "How will you use what you learned going forward?\n", + "First of all, some ways to use recursion. Also, that there are ways to generate a graphic output, not just numbers an letters\n", + "\n", + "What do you wish you knew before you started that would have helped you succeed?\n", + "I don't know if this was the plan, but -in comparison to the first project- the instruction were really long, sometimes a little confusing and not as clear. Sometimes" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/example1.png b/example1.png new file mode 100644 index 0000000..9a85b7c Binary files /dev/null and b/example1.png differ diff --git a/example2.png b/example2.png new file mode 100644 index 0000000..09d6963 Binary files /dev/null and b/example2.png differ diff --git a/recursive_art.py b/recursive_art.py index 6292170..7bbe640 100644 --- a/recursive_art.py +++ b/recursive_art.py @@ -1,171 +1,201 @@ -"""TODO: Put your header comment here.""" - -import random -from PIL import Image - - -def build_random_function(min_depth, max_depth): - """Build a random function. - - Builds a random function of depth at least min_depth and depth at most - max_depth. (See the assignment write-up for the definition of depth - in this context) - - Args: - min_depth: the minimum depth of the random function - max_depth: the maximum depth of the random function - - Returns: - The randomly generated function represented as a nested list. - (See the assignment writ-eup for details on the representation of - these functions) - """ - # TODO: implement this - pass - - -def evaluate_random_function(f, x, y): - """Evaluate the random function f with inputs x,y. - - The representation of the function f is defined in the assignment write-up. - - Args: - f: the function to evaluate - x: the value of x to be used to evaluate the function - y: the value of y to be used to evaluate the function - - Returns: - The function value - - Examples: - >>> evaluate_random_function(["x"],-0.5, 0.75) - -0.5 - >>> evaluate_random_function(["y"],0.1,0.02) - 0.02 - """ - # TODO: implement this - pass - - -def remap_interval(val, - input_interval_start, - input_interval_end, - output_interval_start, - output_interval_end): - """Remap a value from one interval to another. - - Given an input value in the interval [input_interval_start, - input_interval_end], return an output value scaled to fall within - the output interval [output_interval_start, output_interval_end]. - - Args: - val: the value to remap - input_interval_start: the start of the interval that contains all - possible values for val - input_interval_end: the end of the interval that contains all possible - values for val - output_interval_start: the start of the interval that contains all - possible output values - output_inteval_end: the end of the interval that contains all possible - output values - - Returns: - The value remapped from the input to the output interval - - Examples: - >>> remap_interval(0.5, 0, 1, 0, 10) - 5.0 - >>> remap_interval(5, 4, 6, 0, 2) - 1.0 - >>> remap_interval(5, 4, 6, 1, 2) - 1.5 - """ - # TODO: implement this - pass - - -def color_map(val): - """Maps input value between -1 and 1 to an integer 0-255, suitable for use as an RGB color code. - - Args: - val: value to remap, must be a float in the interval [-1, 1] - - Returns: - An integer in the interval [0,255] - - Examples: - >>> color_map(-1.0) - 0 - >>> color_map(1.0) - 255 - >>> color_map(0.0) - 127 - >>> color_map(0.5) - 191 - """ - # NOTE: This relies on remap_interval, which you must provide - color_code = remap_interval(val, -1, 1, 0, 255) - return int(color_code) - - -def test_image(filename, x_size=350, y_size=350): - """Generate a test image with random pixels and save as an image file. - - Args: - filename: string filename for image (should be .png) - x_size, y_size: optional args to set image dimensions (default: 350) - """ - # Create image and loop over all pixels - im = Image.new("RGB", (x_size, y_size)) - pixels = im.load() - for i in range(x_size): - for j in range(y_size): - x = remap_interval(i, 0, x_size, -1, 1) - y = remap_interval(j, 0, y_size, -1, 1) - pixels[i, j] = (random.randint(0, 255), # Red channel - random.randint(0, 255), # Green channel - random.randint(0, 255)) # Blue channel - - im.save(filename) - - -def generate_art(filename, x_size=350, y_size=350): - """Generate computational art and save as an image file. - - Args: - filename: string filename for image (should be .png) - x_size, y_size: optional args to set image dimensions (default: 350) - """ - # Functions for red, green, and blue channels - where the magic happens! - red_function = ["x"] - green_function = ["y"] - blue_function = ["x"] - - # Create image and loop over all pixels - im = Image.new("RGB", (x_size, y_size)) - pixels = im.load() - for i in range(x_size): - for j in range(y_size): - x = remap_interval(i, 0, x_size, -1, 1) - y = remap_interval(j, 0, y_size, -1, 1) - pixels[i, j] = ( - color_map(evaluate_random_function(red_function, x, y)), - color_map(evaluate_random_function(green_function, x, y)), - color_map(evaluate_random_function(blue_function, x, y)) - ) - - im.save(filename) - - -if __name__ == '__main__': - import doctest - doctest.testmod() - - # Create some computational art! - # TODO: Un-comment the generate_art function call after you - # implement remap_interval and evaluate_random_function - # generate_art("myart.png") - - # Test that PIL is installed correctly - # TODO: Comment or remove this function call after testing PIL install - test_image("noise.png") +"""TODO: Put your header comment here.""" + +import random +import math +from PIL import Image + + +def build_random_function(min_depth, max_depth): + """Build a random function. + + Builds a random function of depth at least min_depth and depth at most + max_depth. (See the assignment write-up for the definition of depth + in this context) + + Args: + min_depth: the minimum depth of the random function + max_depth: the maximum depth of the random function + + Returns: + The randomly generated function represented as a nested list. + (See the assignment writ-eup for details on the representation of + these functions) + """ + + if max_depth > 1: + func = random.choice([1, 2, 3, 4]) + if func == 1: + return ["prod", build_random_function(min_depth - 1, max_depth - 1), build_random_function(min_depth - 1, max_depth - 1)] + if func==2: + return ["cos_pi", build_random_function(min_depth - 1, max_depth - 1)] + if func == 3: + return ["sin_pi", build_random_function(min_depth - 1, max_depth - 1)] + if func == 4: + return ["avg", build_random_function(min_depth - 1, max_depth - 1), build_random_function(min_depth - 1, max_depth - 1)] + elif max_depth == 1: #Basecase + x = ["x"] + y = ["y"] + return random.choice([x, y]) + return random.choice([prod, cos, sin, avg]) + + + +def evaluate_random_function(f, x, y): #WORKS + """Evaluate the random function f with inputs x,y. + + The representation of the function f is defined in the assignment write-up. + + Args: + f: the function to evaluate + x: the value of x to be used to evaluate the function + y: the value of y to be used to evaluate the function + + Returns: + The function value + + Examples: + >>> evaluate_random_function(["x"],-0.5, 0.75) + -0.5 + >>> evaluate_random_function(["y"],0.1,0.02) + 0.02 + """ + + if f[0] == "prod": + return evaluate_random_function(f[1], x, y) * evaluate_random_function(f[2], x, y) + elif f[0] == "avg": + return (evaluate_random_function(f[1], x, y) + evaluate_random_function(f[2], x, y))/2 + elif f[0] == "cos_pi": + return math.cos(math.pi * evaluate_random_function(f[1], x, y)) + elif f[0] == "sin_pi": + return math.sin(math.pi * evaluate_random_function(f[1], x, y)) + elif f[0] == "x": # Basecase + return x + elif f[0] == "y": + return y + + + + +def remap_interval(val, input_interval_start, input_interval_end, output_interval_start, output_interval_end): + + """Remap a value from one interval to another. + + Given an input value in the interval [input_interval_start, + input_interval_end], return an output value scaled to fall within + the output interval [output_interval_start, output_interval_end]. + + Args: + val: the value to remap + input_interval_start: the start of the interval that contains all + possible values for val + input_interval_end: the end of the interval that contains all possible + values for val + output_interval_start: the start of the interval that contains all + possible output values + output_inteval_end: the end of the interval that contains all possible + output values + + Returns: + The value remapped from the input to the output interval + + Examples: + >>> remap_interval(0.5, 0, 1, 0, 10) + 5.0 + >>> remap_interval(5, 4, 6, 0, 2) + 1.0 + >>> remap_interval(5, 4, 6, 1, 2) + 1.5 + """ + interval_old = input_interval_end - input_interval_start #calculate the old interval + interval_new = output_interval_end - output_interval_start #calculate the new interval_new + val_percentage = (val-input_interval_start )/interval_old #See where the value is in there + val_new = val_percentage*interval_new + output_interval_start #calculate the new interva + return (val_new) + +def color_map(val): #WORKS + """Maps input value between -1 and 1 to an integer 0-255, suitable for use as an RGB color code. + + Args: + val: value to remap, must be a float in the interval [-1, 1] + + Returns: + An integer in the interval [0,255] + + Examples: + >>> color_map(-1.0) + 0 + >>> color_map(1.0) + 255 + >>> color_map(0.0) + 127 + >>> color_map(0.5) + 191 + """ + + # NOTE: This relies on remap_interval, which you must provide + color_code = remap_interval(val, -1, 1, 0, 255) + return int(color_code) + + +def test_image(filename, x_size=50, y_size=50): + """Generate a test image with random pixels and save as an image file. + + Args: + filename: string filename for image (should be .png) + x_size, y_size: optional args to set image dimensions (default: 350) + """ + # Create image and loop over all pixels + im = Image.new("RGB", (x_size, y_size)) + pixels = im.load() + for i in range(x_size): + for j in range(y_size): + x = remap_interval(i, 0, x_size, -1, 1) + y = remap_interval(j, 0, y_size, -1, 1) + pixels[i, j] = (random.randint(0, 255), # Red channel + random.randint(0, 255), # Green channel + random.randint(0, 255)) # Blue channel + im.save(filename) + + +def generate_art(filename, x_size, y_size): + """Generate computational art and save as an image file. + + Args: + filename: string filename for image (should be .png) + x_size, y_size: optional args to set image dimensions (default: 350) + """ + # Functions for red, green, and blue channels - where the magic happens! + red_function = build_random_function(1, 4) + green_function = build_random_function(2, 3) + blue_function = build_random_function(2, 3) + + # Create image and loop over all pixels + im = Image.new("RGB", (x_size, y_size)) + pixels = im.load() + for i in range(x_size): + for j in range(y_size): + x = remap_interval(i, 0, x_size, -1, 1) + y = remap_interval(j, 0, y_size, -1, 1) + pixels[i, j] = ( + color_map(evaluate_random_function(red_function, x, y)), + color_map(evaluate_random_function(green_function, x, y)), + color_map(evaluate_random_function(blue_function, x, y)) + ) + + im.save(filename) + +generate_art("example1.png", 500, 500) + + +# if __name__ == '__main__': +# import doctest +# doctest.testmod(verbose=True) + + # Create some computational art! + # TODO: Un-comment the generate_art function call after you + # implement remap_interval and evaluate_random_functions +# generate_art("myart.png") +# + # Test that PIL is installed correctly + # TODO: Comment or remove this function call after testing PIL install + # test_image("noise.png")