Final Project Proposal by Maya Pruitt


Based on my undergrad Thesis - Beyond Seeing: Differences Between Experts and Novices in Observational Drawing

I collected A LOT of data, and different kinds:

  • videos of the drawings themselves

  • in-process screenshots

  • audio files of the participants’ thought processes

  • transcriptions of said audio files

  • image difference statistics

  • time (for total drawing , to map objects)

 Example of word data. These are different phrases from the transcriptions categorized by a topic of my choosing with expert or novice status indicated.

Example of word data. These are different phrases from the transcriptions categorized by a topic of my choosing with expert or novice status indicated.

Can I visualize this word data? Can I improving upon the presentation of common phrases/repeated words/similarities in thought processes?

After presenting my ideas in class, I was encouraged to start with counting the frequency of certain words. I like this suggestion, but my hesitation is that I had already done word counts for this project and found the results were not very revealing. Data visualizations like word clouds can definitely demonstrate word frequency but don’t really tell you the relationship between words, which if I’m trying to present the inner thought processes of my participants, this might not be very illuminating.

BUT it is a good way to start. Maybe I can add and interactive element where rolling over a word can show you actual phrases of the participants? Or the fact that it is a comparison between expert and novice may add more interest

word cloud.jpg

What I would ideally like to do is a second experiment….or at least set myself up for a second experiment. For part two, I would like to look at how Expert & Novices might view art differently.

Prediction: Expert are more likely to imagine how an artwork would have been made and visualize the process

I thought an interesting way to do this would be to use EYE TRACKING! → Would like to have people look at artworks, & log their eye movements onto a sort of map….I think the outcomes for the two groups may look very different and would be fun to compare

However, feedback in class seemed less enthused about this…so maybe its not a good idea or there isn’t enough time.

Who's it for?

Myself and anyone interested in the mind of artists drawing from observation

How will people experience it?

Visually seeing data instead of reading a 75 page thesis.

Is it interactive?


Is it practical? Is it for fun? Is it emotional?

It is practical, hopefully the visualization presents information clearly.

Is it to provoke something?

Educate more than provoke. My hope would be to communicate a topic I feel passionate about in an interesting way that makes people consider the effects of skill learnings in the arts.


This week, I wanted to do something a little silly. Using microphone input and external images, I thought it would be kind of funny, if the user’s voice could move a mouth on an existing image.

I used the iconic meme legend himself, Mr. Bubz and gave him a human mouth, by loading different images into p5.js.

Creating microphone input, was surprisingly the easiest part of this project. Following Dan’s tutorial it was pretty straightforward creating a mic object, starting it, and retrieving the volume value by using getLevel(). These functions were similar to the FFT ones I used last week in that to analyze sound in a certain way, you need o create a specific p5 object from the sound library, initialize it (start vs. analyze) and then can used a more specific function to retrieve data (getEnergy() vs. getLevel()).

The challenge came in creating a realistic mouth to move to the volume of microphone input. I started by using an ellipse to represent the mouth, but I didn’t like how awkward it was. This led to uploading a second image and delving a little into the 3D modeling functions. I thought if I could map the mouth to an ellipse that would give me more control. I wasn’t sure if I could just use map() though, so a friend suggested texturizing an ellipse.

I only wanted the height of the mouth image to move to emulate opening and closing in a funny way, so I added the volume of the mc input to the height of the teeth image.

However, this distortion is really off and now the mouth seems to grow on an diagonal. I’m not sure what is causing this. Maybe there is an actual distortion function that would be better? How can I fix this?

Check out the sketch here.


This week’s assignment was to create a sketch that uses an external data source.

For a while now, I wanted to create a visual that changes to the rhythm of music, so this seemed like the perfect opportunity to play with that.

Music is data.

An mp3 file compresses sound sequences into a digital format. If we parse through this sequence we can extract really interesting information. When we think of music, we can often break down the sounds we hear ourselves, the heavy deep notes are the bass, the higher notes are called treble, we can distinguish the sounds of different instruments versus vocals, etc.

My goal was to have my data visualization represent these different parts of a song and change with the song as it played. It is kind of an ode to the familiar visual of audio meters.

maxresdefault (6).jpg

By consulting the p5 sound API, there is a perfect function to parse through the data of an mp3 file: p5.FFT or Fast Fourier Transform. FFT is an algorithm that analyzes sound and can isolate individual audio frequencies.

In addition, the function getEnergy() returns the value of the energy/volume of a specific frequency. There are even 5 predefined frequency ranges: bass, lowMid, mid, highMid, and treble.

With FFT, fft.analyze(), and getEnergy() I could begin breaking down the parts of any given song. Place these functions in the draw() loop and they constantly break down and return frequency values as the song plays.

For the visualization part, I wanted to keep it simple. I used the values received from the predefined frequencies to determine the width and height of ellipses. The result is concentric circles (I love me some ripples) that grow and shrink as the song plays. Each frequency range is represented by a different color. It is quite mesmerizing.

Screen Shot 2018-10-23 at 1.30.37 AM.png

I placed the frequency values in order will bass being the outside circle and treble the inside, because the values of the frequency range increase as the notes get lower on the scale.

What’s really cool about this visualization, however, is that you don’t necessarily need to know anything about music to understand what’s happening. It’s kind of fun to focus in on a part of a song you hear and see what circle corresponds to it. To add a little more dynamics, I have the bass circle grow more intensely to emphasize the drops. Something about the synchronization of audio and visual is very appealing. I definitely want to look into some cog sci studies of why that is. Anyway, I digress, link to the sketch below.

Screen Shot 2018-10-23 at 1.32.26 AM.png

Ready to be hypnotized? Check it out here. SOUND ON!

WEEK SIX: THE DOM by Maya Pruitt

Usually I use my blog posts to describe my homework sketches, but I also need to air out some grievances. I found working with the developer tools on the New York Times home page to be extremely frustrating. On one hand it’s very empowering to make changes to an existing site and see it displayed in real time, but with so much content on the NYT site, I found google’s display of the developer tools to be overwhelming. I had a hard time figuring out what parts were even adjustable.

To Mimi, can we do a quick re-review of this and its parts? And maybe discuss the applications of the developer tools, why do programmers use that? What is its true purpose?

Now back to the fun part - this week’s sketch:

Our assignment was to create our own webpage using HTML, CSS, and P5 javascript. This was fun for me, because I got to start to bring to life a design I had done in the past. In the Graphic Design/UX section of my portfolio, you can see my design for ZODIAPP: an app about the Chinese Zodiac. I had sketched out the look of the app and even animated the types of interactions it could have. While there are tools like InDesign, that allow UX designers to prototype these interactions for user testing, it is a whole new world being able to actually create the code behind them. This assignment allowed me to do just that!

 Original design

Original design

 Translating into HTML

Translating into HTML

We had a few parameters to meet:

  1. Pre-defined HTML Elements

  2. Pre-defined CSS Styles

  3. HTML Elements generated by your p5 sketch

  4. Some kind of mouse interaction with an HTML Element using a callback function you write.

1. I used a bunch of pre-defined HTML elements, such as <div> <h3> and <font>. These elements allowed me to create the navigation bar at the top and gave me quite a bit of control. I could change the font color to white, as well as type the actual text to display. H3 gave me a default size that I liked best. Fun fact: spaces won’t change the way text displays. If you want actual white space, say in between each phrase in a navigation bar, you can use the special characters “&nbsp”.

<img id="logo" src="zodiapp_logo.png" />
<div id="navbar">
  <h3> <font color="white"> Horoscope &nbsp &nbsp &nbsp Story of the Zodiac &nbsp &nbsp &nbsp Animal Gallery &nbsp &nbsp &nbsp 2018</font>

(lines 11-15 in index.html)

I also used the predefined <img> element to load my logo image.

2. CSS styles allowed me to give properties to the HTML elements I created. For example, this is where I could give the navigation bar its background color and center align the text. In addition, I could modify the logo image. I learned a cool trick that if you want to adjust the scale of an image, you can set one dimension to a specific value and then the other dimension to “auto”. This will maintain the original dimensions of the image and prevent any weird stretching. Lastly, I set the entire background color of my webpage here.

html, body {
  margin: 0;
  padding: 0;
  background-color: #f9f4d9;

  /* auto keeps the dimensions of the original image*/

  background-color: gray;
  text-align: center;

(lines 1-16 in style.css)

3. It is also possible to create HTML elements within p5 itself, which allows for a whole different set of controls. It makes sense to generate HTML elements with p5 if you want to manipulate them in some way, so createButton() seemed perfect for this. In addition, I created the footer in p5. I thought this would give me more control for customizing the div element, but I couldn’t figure it out as easily as I did the HTML way. However, in the future if I wanted to create rollover (mouseOver() / mouseOut) events with the navigation bar and footer, say highlighting each word to a different color to indicate a link, maybe p5 would be the best place to create these elements.

  let button = createButton("SPIN");
  let footer = createDiv("About | Help | Contact Us");
  footer.position(275, 850);

(lines 12-16 in sketch.js)

4. Creating the mouse interaction was my favorite part because making a wheel of zodiac animals spin has been a part of my concept for this since day one. My goal was to have the wheel spin when the mouse clicked on the button. Here is where javascript ties it all together and puts an animated element on the webpage. I uploaded another image into the sketch.js file using the preload() function. I created a function called spin() which creates the spinning behavior. In order to get the button working correctly, I had to create a toggle switch, like we learned with the bouncing ball. This was stored in another function called spinOn(). The button can then use mousePressed to callback to the spinOn() switch function. Ideally I wanted this to look more like: wheel.spin() and button.mousePressed(spin), but I couldn't get it working like that. Would I need to create a wheel class? I’m pretty sure I could make a class for the wheel image and turn it into an object. It would be fun to expand on this in the future to make it more dynamic.


Oh, also to my non-ITP readers, in case you were wondering, DOM stands for The Document Object Model. It’s a kind of hierarchal way of organizing website programing/HTML . But to me “The DOM” sounds like a fancy ass queen, which is why it seemed like a sufficient title. k Yamz out.

Try dat spin button for yourself here.


This week was especially exciting because I finally got to create the program I originally conceptualized in week two. Learning arrays is what truly made this vision possible, so I was itching to finally implement it.

By creating the ripple class last week, I already understood the concept of constructing objects with distinct properties. I also experimented with creating multiple ripple objects manually, but this was not the main objective.

The time had finally come. An array to the rescue!

With my object class already in place, it was pretty easy to build my program following Dan’s format for his bubble example in video 7.3 Arrays of Objects. This exercised again solidified the importance of order and placement of code within the program. What I mean is that code is quite logical. If I want a new ripple to be created with the click of the mouse, then the constructor code needs to be placed within the MouseClicked function:

function mouseClicked() {
  let ripple = new Ripple(mouseX, mouseY, 0, 0);

Here a new ripple is created (at mouseX and mouseY, size of 0 width and 0 height) with each click of the mouse. The ripple object is then stored in the array and placed (“pushed”) to the end of the array.

In a continuous loop, I want the array to grow in length, and I need each ripple object to run (which is just a function containing display() and grow() functions). This translates into a for loop inside the draw() function.

function mouseClicked() {
  let ripple = new Ripple(mouseX, mouseY, 0, 0);

Sound on if you want to hear the satisfying click of the mouse!


Writing about this program and my process here in the blog, makes it sound like building it was so easy, but in reality, it truly took me until this week to really grasp these concepts. It’s crazy how difficult this idea felt at week two…in fact, more than difficult, it felt impossible. Arrays open up the possibilities. While I am super pleased to have finally executed this original idea, I look at it now and think it’s too simple. I tried to spruce it up with minor aesthetic changes, but the future goal would definitely be to create some sort of realism. How do I make real looking water in code?

Interact with my sketch here.


This week, our assignment was to revisit past projects and reorganize our code based on our new knowledge of creating functions.

Determined to get the Ripple program running the way I originally envisioned it, I saw this as a good opportunity to expand on it, reorganize it, and set it up for when we learn arrays this coming week.

I chose to make the expansion of the ripple its own function. What is kind of liberating about code is that though there are rules in terms of syntax, or how certain elements are defined, in the end, how we want to do something or what we want to do is up to the programmer. I could have made a modifiable function that takes parameters, or have it do a calculation that returns a value. However, I decided I just wanted a standard rate of growth, so the resulting function looks pretty simple:

 grow() { += 2;

The cool part is that now any shape can have grow applied to it. Check that out here.

To challenge myself, I created a Ripple class. I know this will serve me in the long run, because the goal is to create a new ripple object with each click of the mouse.

Defining what it means to be a ripple:

class Ripple {
  constructor(clickX, clickY, rw, rh) {
    this.clickX = clickX;
    this.clickY = clickY; = rw;
    this.rh = rh;

  display() {
    ellipse(this.clickX, this.clickY,, this.rh);

  grow() { += 2;

With the class I am able to make multiple ripple objects. However, because the position of a ripple is determined by a mouse click, there is no way now to make two different ripples starting at different positions or different times of growth. In other words, ripple size is modifiable (fig.A) and position only if ClickX or ClickY is changed with equation. The former will show two ripples inside one another, and the latter scenario will have two ripples grow at the same time in different locations.

  Fig A. Line 32 &amp; 33 show two ripple objects, the only difference between them is the size of ripple width and height. This creates concentric ripples upon a mouse click.

Fig A. Line 32 & 33 show two ripple objects, the only difference between them is the size of ripple width and height. This creates concentric ripples upon a mouse click.

  Fig B.   Line 33 indicates that position is being modified when clickX and clickY are multiplied by two. This causes both ripple objects to appear at the same time, but at different positions with the click of the mouse.

Fig B. Line 33 indicates that position is being modified when clickX and clickY are multiplied by two. This causes both ripple objects to appear at the same time, but at different positions with the click of the mouse.

Final thoughts:

Location, location, location! This applies to code as well. My biggest take away from this week is that where functions are placed in the program truly determines what will or will not happen. Watching Dan’s videos, we see our first example of a class object being run by putting the constructor in the setup() function. I quickly learned that my program wouldn’t run that way. If I want a ripple created when a mouse is clicked, then that is where the constructor function should be placed – inside mouseClicked! A simple order change can be a determining factor too. This reinforces why having variables at the top makes sense. The computer won’t be able to use variables if i doesn’t know what they are, or what they have initially been set to.

I constantly have to remind myself that the computer doesn’t think like a human does. So abandon your humanity, it’s the only way to code! Jk jk.

See the final organized ripple program here.


Creating an interactive sketch

This week, the challenge was to create our own buttons/roll-overs/ or sliders that then interact or change the sketch.

I had something different in mind, but felt the easiest way to accomplish the above tasks, was to combine different things we’ve learned and practice.

I started by creating a grid like in our quiz, but with squares instead of lines, so I could fill portions of it and create a checkerboard. My variable names were really important here, because they helped be sort out how to think about the grid. I didn’t want it to just be x and y when we’re dealing with rows and columns. In addition, it is important to note that the for loops create rows vertically and columns horizontally. The num variable allows you to change the number of squares in the gird (num x num).

Including mod was a cool breakthrough. I knew the best way to alternate fill was to identify which squares were in an even or odd position for both row and column. Mod does just this. If a number is mod 2 (N%2) == 0 this means that after being divided by 2 there is no remainder. Even numbers divided by 2 leave no remainder. Conversely, odd numbers will create a remainder of 1 ( N%2 == 1). This set the rules for my conditional statements. It took a couple tries and a couple if statements to make the whole grid cooperate with these rules.

 Just a condition to fill when row and column are both even.

Just a condition to fill when row and column are both even.

 But the board should also fill when row and col are both odd.

But the board should also fill when row and col are both odd.

Creating a button:

Using what we learned about toggle switches, I thought an easy interaction with the checkerboard, would be to make the checkerboard switch its configuration upon a mouse click – turn what were black squares into white squares and white squares to black squares.

Inside the for loops, I had to create a sort of “state” condition. If the switch is on, fill this way, if it is off, fill the opposite. This concept allowed a lot of copying of code with minor changes. I think its a good way to see how the loops really work.

Inside the mousePressed () function, I indicate where the mouse should be in order to turn on/off this switch. So essentially this creates the button.


Creating a hover/rollover:

Although the sketch at this point had a button, I wanted to create another visual cue that the top left corner square is indeed the button. I did this by turning it into a rollover as well. The top left square changes color when the mouse is placed over it, but only switches the checkerboard if clicked. This whole piece had to be placed outside the for loops and required the addition of identifying what row and column the mouse should be in in the conditional statement, otherwise the whole board filled.

 Bad teal fill.

Bad teal fill.

 Adding the parameters of row == 0 &amp;&amp; col == ), keeps the teal fill within the top left square.

Adding the parameters of row == 0 && col == ), keeps the teal fill within the top left square.

Interact with the checkerboard switch with teal hover button here.

Adding animation:

I wanted the mouseclicked button to stimulate some sort of movement, but I wasn’t sure how to incorporate this. In fact, adding in the animated part was the most difficult part for me. It was hard to figure out where in the for loops to place it, which is why I ended up borrowing our bouncing ball code (lines 37-41) from class and just plopping it in the program until I could see a moving square.

checkerboard_moving square.gif

Try checkerboard switch with moving square for yourself here.

Final thoughts:

Moving forward, I would like to more logically attempt the animation. Maybe have the square move to the right from the top left, row by row leaving a trail and filling the whole sketch a different color. I can picture where to place movement so that it moves to the right along one row, but I’m not sure how to get it to drop down the the next row and continually do that. My instinct is that it would go inside the nested for loop, because the loop already makes both rows and columns. However, that is also where the issue lies, because on top of creating the grid, I want to make another moving square. My brain hurts just thinking about this.

Final final thoughts:

I am struggling with programming right now. I can see the creativity in it and the potential to make such interesting things. But if I have an idea, I often don’t even know how to begin turning it into code. It feels like instead of being a tool for me, it’s a hinderance. Hopefully with more practice and knowledge, this will go away. It’s truly a different way of thinking because I have to “make” within certain rules and parameters.


Week One proved to be a difficult one, and since I felt very restricted by my drawing with 2D primitives, I decided to abandon it completely and try something new for week two. The criteria of this week’s sketch made me think of ripples. My goal was to have each click of the mouse create an ellipse. The ellipse would grow until it is not visible on the screen. Here was my plan of how to satisfy each criteria:

  1. One element controlled by the mouse: A clicked mouse initializes the start of the ripple.

  2. One element that changes over time, independently of the mouse: The ripple enlarges by itself.

  3. One element that is different every time you run the sketch: The background color is a different shade of blue at each start of the program.

Step 1: make a circle grow

I started with the element that I thought would be the easiest - making an ellipse grow, since we have had a bit of practice in class changing objects on the canvas over time. This program uses variables and the looping draw() function in p5.js.


With this code, the ellipse is a perfect circle starting in the center of the canvas. The width and height increase by 1 pixel every frame as indicated by lines 13 and 14. BUT How can I make the mouse trigger this event/growing circle?

Step 2: mousePressed()

This is a function I didn’t know how to use before, so I had to read up from the p5.js documentation about different functions used to cause events. The mousePressed() or mouseClicked() functions do just this. The former triggers an even when the mouse is clicked, the latter after a mouse is clicked and released. Either would work for what I was trying to do.

In a separate program I wrote code that would create an ellipse when the mouse was clicked to practice this element of my future ripple program.


This code creates an ellipse of 80 width and 80 height anywhere the mouse indicates position using built in variables mouseX and mouseY. With each click, a new ellipse is created. Next I needed to figure out how to combine these two events, so that the mouse created an ellipse that would then grow on its own.

Step 3: mouse triggered ripple

In order to combine the two programs above, the draw() function would have to contain the ellipse making instructions, otherwise mousePressed() or mouseClicked() wouldn’t trigger a growing ellipse, just a stagnant one. With the help of this code, I learned that you can create a sort of on/off switch in the mouseClicked() function. Line 24 “start = !start;” indicates this start or stop of the drawing loop with each click of the mouse. It is setting the variable “start” to not start, meaning that mouseClicked() triggers the opposite of the current state. If start is true, mouse click will produce false start or stop. If at stop, the mouse click will produce start.

Although, I was able to make the animation of the ripple begin with a mouseClick, I faced a huge challenge of knowing where to place mouseX and mouse Y. I didn’t want the ellipse to follow my mouse every frame as shown below:


My goal was to be able to click the mouse to indicate position and essentially leave the ellipse in that place. Ironically, it wasn’t until I wrote some things down on paper that I started to make sense of it all. I realized that I wanted where mouse indicated starting position to happen ONLY ONCE. That was my epiphany. If the mouse indicates the position of the ellipse only once, I could move the mouse and the ellipse would grow from the originally clicked place.


When I figured out that the position of mouseX and mouseY should occur only once and be indicated by the mouse click, I realized that I could create my own variables for mouse x and y position and these should be set in the mouseClicked() function as opposed to the looping draw() function. This changed everything and allowed me to move my cursor away from its initial start, but the ripple would continue to expand on its own from that postion.

Step 4: creating an element that is different every time

This step was made for the random() function. I applied this to the background color. By randomizing just the red and green values but keeping blue the same, the background color varies from shades of pinks, purples, and blues, kind of like water at sunset. See the final program in the p5.js web editor here.


This program is not complete, but I’ve reached a standstill in my current knowledge. My eventual goal is to have the mouse move anywhere and create new ripples with each click. This would make the program constantly interactive. However, to achieve this I need the mouse click to trigger the same animation over and over again. It’s kind of like I need to loop the loop. But I also need to store each ripple so that it finishes out its expansion and doesn’t disappear with a new click. Initial research has shown that an array would be able to accomplish such a task, but I don’t know how to implement this yet. I would love to come back to this program and add this last element to truly make it what I wanted it to be.


How does computation relate to your interests?

Before thinking about the applications of computation, I think that its important to define 'computation', so here is its meaning according to the dictionary: 

com·pu·ta·tion (ˌkämpyəˈtāSH(ə)n/) noun

  1. the action of mathematical calculation.

    • the use of computers, especially as a subject of research or study.

  2. a system of reckoning

I particularly like the second definition. Computation is a way of understanding, mainly using mathematical calculation or computers. Makes sense why in orientation ICM was called "fancy programing". To sum this up, computation and computer programming mean to me, that you can be creative, using math as a method or tool for that creation. Tasks can be automated, we can take complicated actions and reduce them to simple logic. It is another way of thinking. 

In my quest to combine art and science, I think animation is a perfect blend of the two. The art of story telling, illustration, etc illuminated by algorithms that produce 3D models, actions, and graphics. Whether for a movie or a simple gif on a website, I can see coding applying heavily in those creations, and I want to learn how to do them. 

This term, I hope to start exploring 3D animation, game design, AR and VR. On a less artistic side, I am also really interested in how to use coding to organize and collect data, i.e. to make sense of the results of an experiment.


HW #1: Sketch

For this assignment we had to create any sort of sketch using p5.js. While not limited to 2D primitive shapes, I tried to stay within this constraint. I began by coming up with my idea, which took a while! For things like this, it is often best to just pick something and commit.

I was inspired by the awesome instagram feed of @henrythecoloradodog, which features adorable images of an adventurous cat and dog pair. The cat, Baloo, enjoys laying on Henry’s head. *heart eyes* Go follow!

Screen Shot 2018-09-11 at 12.56.41 AM.png

I started by sketching out a simple drawing of “Cat as Hat”, mocking a rudimentary grid. I picked a point and just took off from there. Usually I am one to really figure things out by mapping it out on paper first, but because the p5.js wed editor has an “Auto-refresh” feature, I found I was able to quickly trial and error. I plugged in numbers, did simple math, and could see the drawing change as I was thinking. My biggest considerations while sketching, were the order of each shape so that things were properly overlapped or hidden, and color choices - the fun part. This is a link to the RGB Color Codes I used.

This feature of the web editor is a great example of strong UX in and of itself. It is so interactive and efficient that I can see the results of code changes instantly. I’m learning how functions work and evolving my image simultaneously.

Below is a screen recording of my process: [UNCENSORED: all typos exposed]

The biggest pitfall for me was that I didn’t really have a great plan for execution. For a drawing as symmetrical as mine, I feel there are probably much faster ways to create identical (but mirrored) shapes. Without delving too deep into more sophisticated functions, I felt I had to compromise my image a lot, or change things because I couldn’t get it exactly how I wanted. I feel like coding should make things easier. Looking forward to repeatability and automation! Bring on the loops!

Screen Shot 2018-09-11 at 1.06.04 AM.png