Week 2 Assignment: Agar Plate

I got the idea for this assignment while working with bacterial cultures in the lab. The random generation of shapes we did in class kind of reminded me of how bacterial colonies form on agar plates. So, I started by just getting the color of the agar and the bacterial colonies right, similar to the image below.

Colonies of E. coli growing on agar plate. Colonies appear as off-white dots on the yellowish agar Fig.: E. coli growing on an agar plate

This is when I also started with experimenting with the randomGaussian() function instead of the regular random() function. This allowed the generation of random positions that were more concentrated towards a central position, basically forming what would be a “3D bell curve”, which usually represents biological growth better than true randomness. And adding translucency to the background gave the effect of some colonies gradually “dying” as new ones “grew”.

However, this alone didn’t look good enough. Off-white colonies on a yellowish background could only look somewhat interesting. That’s when I came across photos of microbial art and also remembered work I did in a class with bacteria that were engineered to be bioluminescent using a Green Fluorescent Protein (GFP) from jellyfish.

Microbial Art depicting a beach scene made with fluorescent bacteria2 plates growing E. coli bacteria. Colonies in plate on left express GFP in an LB/Ampicillin/Arabinose medium. Colonies growing in regular LB/Ampicillin medium do not express GFPFig.: (a) Microbial Art from the lab of Prof. Roger Tsien (discoverer of GFP)
(b) Plates with GFP-expressing bacteria under black light grown by me

I wanted to incorporate this in the assignment without losing out on the essence of the original appearance of the colonies. Fortunately, this was easy enough with just an if statement that changed the color variables, and a button that toggled the “UV blacklight” between on/off states.

Next, I wanted to add a bit of interactivity to the project, to allow a user to actually create some microbial art instead of having the colonies just randomly generate in a circle in the centre of the viewport. I decided to create discs that were meant to simulate carbohydrate-impregnated paper discs that can be added to agar plates. These special paper discs gradually diffuse the energy source into the agar, instead of the agar already having an energy source in it. In microbiology, this allows for experiments on how different microbes respond to different energy sources. In this project, it allowed me to easily localize the generation of colonies around multiple user-defined points.

I created a class for the discs, which would allow me to quickly generate them when a mouseClicked() event is triggered, while allowing its properties to be used as a basis for the randomGaussian() functions to generate the colonies. This was my first foray into OOP in JavaScript, and the differences from Python took me by surprise.

The next part was arguably the hardest. I wanted to give the user an option to freeze the plate in time and view their resulting artwork. In the lab, we perform a process called fixation that uses formaldehyde or glutaraldehyde to prevent further growth or death of cells, preserving them for as long as we need them, so it would be cool to give that option to the user too. However, including this feature in a way that did not interfere with the UV toggle was challenging. The easiest way to go about doing this is to use the noLoop() function which interrupts the draw() loop. But in that case, the user was stuck with their last UV setting, whether on or off, as that was also part of the draw loop. Instead, I settled on a compromise, using a multidimensional array to capture colony position and size information for every colony of every disk for the last 2 generations. This data was used to recreate the last 2 generations in the “fixed plate”. While this drastically cut down on the number of visible colonies, I was happy with this compromise as it still allowed to toggle between UV on/off states after the plate was fixed.

if (!fixed) {
    background(plateColor);
    // create arrays to store colony position and size information
    prevColonies = colonies;
    colonies = [];
    for (
      let d = 0, colonyX, colonyY, colonyR, colonySpecs;
      d < discs.length;
      d++
    ) {
      // discs
      fill(discColor);
      discs[d].display();
      // create sub-array to store specific info for each disc
      colonies.push([]);
      // bacterial colonies
      for (let i = 0; i < numColonies; i++) {
        // Gaussian random to ensure aggregation towards discs
        colonyX = randomGaussian(discs[d].x, spread);
        colonyY = randomGaussian(discs[d].y, spread);
        colonyR = random(2, 15);
        colonySpecs = { x: colonyX, y: colonyY, r: colonyR }; // dictionary containing colony info
        colonies[d].push(colonySpecs);
        stroke(colonyBorder);
        strokeWeight(3);
        fill(colonyColor);
        ellipse(colonyX, colonyY, colonyR);
      }
}

The finishing touches were just adding another button to clear the plate (basically a reset button that resets everything to setup state), tweaking the colors, adding conditions for when the discs could be placed (with warnings for when they couldn’t), and setting up simple counters that would very slowly increase the number of generated colonies and how spread out they were from the disc.

The final result can be seen below. Remember that you cannot interact with the plate when it is being irradiated with UV (that’s a skin cancer risk waiting to happen) or when it’s fixed (well, the bacteria are dead already).

Overall, I am very happy with this assignment. It feels like I found a creative way to present laboratory processes that I work with on a regular basis as a Biology major. If there were any changes I would like to make to it in the future, it would probably be in converting the bacteria to objects as well for easier manipulation. I would also like to include a feature to choose the agar and species growing on it, which can allow experimentation with various interesting colors, such as those produced by some bacteria on blood agar, or by various purple, blue, and other colored bacteria or fungi.

Reading Reflection – Week 2

 

Reas’ collaborative artwork with Ben Fry visualizing biology data from MIT.

The first thing about Casey Reas’ speech that caught my attention was his collaboration with Ben Fry, which focused on visualizing biology data from MIT and the way that proteins communicate back and forth – positive or negative signals within a cancer cell (randomness was used but in a slight manner). This example proved to me that an artwork truly becomes a piece of art when it is shaped by the story it holds, something to which we can relate.

Reas’ creation of conceptual vehicles influenced by anatomist Valentino Braitenberg.

Another project I found interesting was his creation of conceptual vehicles and software, each color-coded based on their wiring, which was influenced by anatomist Valentino Braitenberg’s hypothetical vehicles, whether inverse or positive, straight connection or cross-connection. A quote that then stood out to me was “a little bit of randomness and a lot of decision-making” (11:43), which showed the complexity in art that many see as “simple.”

Further in the video, the reference to random graphics reminded me of Skip Lists in Data Structures where the reliance is on a 50/50 chance serves as a technique to ensure efficient performance. This validates the deep integration of math, computer science, and physics in art. Further, Reas broke down the barriers between these disciplines, emphasizing how randomness, far from being blind, is a planned element that adds an unexpected dimension to the artistic output, an argument with which I completely agree!

Personally, this speech has solidified my belief in the interdisciplinary nature of art. The combination of several distinct disciplines showcased in the work Reas displayed challenged preconceptions that even I had about the simplicity of digital art. That being said, the speech left a question surrounding the impact of technological advancements on art: Is there ever a line to be drawn as to the art is no longer by the artist but rather a computer, and have we reached that age yet, especially with AI generative art, although different from the work displayed in the video?

 

Assignment 1 : Self-portrait | Aadil

Concept

I wanted to create a simple image of myself with some level of user interaction . I started off by trying to use basic shapes to create the eyes, ears, nose and mouth of the self portrait . I realized knowing the coordinates accurately would save a lot of time spent in trial and error , so I added a small piece of code to display the mouse coordinates at the bottom of the canvas . This was very useful and saved a lot of time in positioning the shapes. For user interaction , I implemented two types of backgrounds – day and night –  that switch when mouse is clicked.

The Embedded Sketch is below :

 

Highlight of Code I am Proud of 

The code for generating stars in a different random pattern every time the scene shifts to night is something that I thought was cool to implement .

 //What happens when mouse is clicked
function mouseClicked(){
  isDay=!isDay;
  //The following piece of code ensures that the stars are at new positions 
  //everytime the mouse is clicked
  Stars=[];
  for(let i=0;i<50;i++){
    let x= random(height);
    let y=random(width);
    Stars.push(createVector(x,y));
  }
}

.
.
.
//draw() function
//Stars
    fill(250);
    noStroke();
    for(let i=0;i<Stars.length;i++){
      let Star=Stars[i]; //Star is variable of type Vector
      ellipse(Star.x,Star.y,2,2)
    }

Another Implementation that I am proud of is the drawClouds() function that takes cloud coordinates and size as inputs and draws clouds accordingly .

function drawCloud(x, y, size) {
  fill(255);
  noStroke();
  ellipse(x, y, size, size * 0.7);
  ellipse(x + size * 0.5, y, size, size * 0.7);
  ellipse(x - size * 0.5, y, size, size * 0.7);
  ellipse(x, y + size * 0.3, size, size * 0.7);
}

Reflections and Ideas for Future Work

Overall, I think it turned out to be a good initial exercise with p5 and I got a simplistic self image using basic geometry which is what  I had envisioned while starting with the project  . In future projects, I would love to add animations and even more user interaction . Maybe different backgrounds could also be added and something about the portrait itself can be changed when the background changes .

I look forward to improving my skills and making more realistic images /graphics  .

Assignment 2: Emergent Flowers

Inspiration and Concept

I was looking through some of the works in ProgrammInformation21_PI21 when I came across the sketch below. I immediately thought about the curves I used in last week’s assignment and how noise could be introduced to create this effect of slightly vibrating circles. Essentially, if I drew a circle with curves and then introduced controlled deviations in the vertices’ x and y-coordinates away from the perfect circular path, I would then be able to recreate this piece. In the process of conceptualizing the animation, I also imagined that drawing a curve in each frame would give the illusion of a blossoming flower and add some character and movement to the work. That latter thought effectively lingered in my mind and I found myself experimenting with symmetry, eventually creating an expanding flower animation.

 

Embedded Sketch

Implementation and Code Highlights

The animation was created by a for loop that creates the curves, nested within another that symmetrically partitions the curve lines to generate petal shapes. I used the Perlin noise() function to allow the curves to wiggle a bit utilizing the iterating variable in the nested for loop and an auxiliary control variable to set the x and y-coordinates in the noise space. This elicited the pattern of organic folds of a flower existing in nature. I referred to the way I created my hair in the last assignment and the examples of using Perlin noise in this article to create the curves. The number of partitions (petals) of the flower is determined by a number that is randomly generated from a finite set of integers. Additionally, the stroke color of each curve is also randomly generated. When set against a black backdrop, the eccentric fluctuations in stroke color produce a glowing effect, which I loved. The animation is replayed when the flower expands to the width of the canvas. Additionally, the animation is repeated with a different number of petals when the mouse is clicked for added interactivity.

// partition the circle based on the variable, petal_partitions_control, to create flower petal effect 
for (var j = 0; j < petal_partitions_control; j += 1 / petal_partitions_control) {
  beginShape(); // draw curves 
  for (var i = 0; i < 30; i++) {
    // map angle based on current partition iteration
    // inner loop implementation inspiration: https://genekogan.com/code/p5js-perlin-noise/
    var ang = map(i, 0, 30, j * PI, j * PI + PI / petal_partitions_control);
    // generate x and y coordinates using noise for organic shapes
    var x = radius * cos(ang) * noise(i * 0.1,  perlin_noise_control * 0.05);
    var y = radius * sin(ang) * noise(i * 0.1,  perlin_noise_control * 0.05);
    
    // draw curve
    curveVertex(x, y);
  }
  endShape();
}

The outer for loop, I would say, is the one I am most proud of as it creates the emergent pattern of flower petals. Admittedly, I do owe Casey Reas and his talk some credit for helping me get inspired to add the symmetry needed to pull this animation together.

Reflection and ideas for future work or improvements

I really enjoyed the process of expanding upon my earlier work and integrating the concepts we discussed in class in the making of this piece. I also loved the process of experimenting with different noise values and stumbling upon the often happy surprises that come with working with randomness and geometry. In the future, I would like to perhaps add more of these flower shapes and give the user some more control in defining the parameters that control the randomness behind the shape (by adding a slider, for example). Additionally, I would love to exploit the same concept to recreate other symmetric shapes – like butterflies – in nature.

 

Assignment 2 – Shereena AlNuaimi

After further browsing the artworks that were posted to help inspire this assignments idea. My inspiration stemmed from the artwork by Bill Kolomyjec’s “Random Squares.”

At first, I fully convinced myself that it would be rather simple to recreate just a collection of squares. Nevertheless, I was shockingly mistaken. I discovered that my code seems blank after fiddling around with it and making squares within squares. Furthermore, I went ahead and made the decision to push myself simply because I know that if I set my mind to something, I’ll do all in my power to make it happen. I made the decision to attempt to program the squares to change color when the mouse is over them.

To solve the task I set for myself, I began reviewing tutorials on YouTube right away. I wanted to learn how to improvise for the if else statement I used and avoid making my code too long or complicated. and put the map statement into practice so that the code could detect if the mouse was hovering over the squares and alter its color accordingly.

In a realistic sense, the task itself was both difficult and instructive. I came to the realization that I do need to practice a little myself in order for me to find coding to be rather straightforward, so hopefully I will keep doing that. In the future, I do plan to push myself more than I did on this project, but I also want to make sure that I don’t put too much pressure on myself and take my time enjoying the process of producing. Overall, I’m somewhat proud of the outcome.

let squares = [];
let numSquares = 6; // Total number of larger squares
let nestedSquares = 4; // Number of nested squares within each larger square
let squareSize;
let maxSize, minSize;
let spacing; // Spacing between larger squares

function setup() {
  createCanvas(560, 372);
  squareSize = width / (numSquares / 2); // Assuming 3 squares in a row
  maxSize = squareSize;
  minSize = squareSize / 10;
  spacing = squareSize / 50;

  // Initialize properties for each large square
  for (let i = 0; i < numSquares; i++) {
    let x = (i % 3) * squareSize + squareSize / 2;
    let y = floor(i / 3) * squareSize + squareSize / 2;
    squares.push({ x, y, size: maxSize, hovered: false });
  }
}

function draw() {
  background(255);

  for (let i = 0; i < squares.length; i++) {
    let sq = squares[i];

    // Determine if the mouse is over the square
    sq.hovered = (mouseX > sq.x - sq.size / 2 && mouseX < sq.x + sq.size / 2 &&
                  mouseY > sq.y - sq.size / 2 && mouseY < sq.y + sq.size / 2);

    // Draw the nested squares
    for (let n = 0; n < nestedSquares; n++) {
      let nestedSize = sq.size - n * (sq.size - minSize) / nestedSquares;

      // Color change based on mouse position
      let colorValue = sq.hovered ? map(mouseY, 0, height, 255, 0) : 255 - (n * (255 / nestedSquares));

      fill(
        colorValue,
        255 - colorValue,
        map(mouseX, 0, width, 0, 255)
      );

      // Draw each nested square
      rectMode(CENTER);
      rect(sq.x, sq.y, nestedSize - n * spacing, nestedSize - n * spacing);
    }
  }
}

Assignment #2 – Reading Response

This talk was very interesting to me, particularly the parts about chance in art and code.

The second Reas started talking about Jean Arp’s artwork, the one about dropping the pieces of paper and just leaving them there, I immediately thought of the concept of “happenings”. Allan Kaprow introduced “happenings” in the 50s as an artistic event which employs randomness and improvisation, particularly in performance art. They typically required the participation of the audience, so the spontaneity of the happenings and the random environments in which they unfolded created an unpredictable result – one that Arp’s work resonates with. I was happy to see that Reas mentioned John Cage and Marcel Duchamp, as they are the predecessors of happenings. John Cage invented the technique of “prepared piano”, in which he would place different items on piano strings in order to change the way they sound. Marcel Duchamp emphasized the role of the viewer in art, affecting the way audience participation contributed to the artwork. His idea, which Reas evokes, that this kind of randomness and chance allows in a way to take a stand against authority, power, and order and to come back to our chaotic nature, is very striking to me.

Moving on to chance in code, I had actually never thought about it. Although I cannot say that chance in code is a happening, I really felt like it resonated with this “fight” against order and rationality. Reas says: “the idea of using a rational machine to do something unexpected was at the time very subversive”. In the demos he shows next, it is then interesting to see how the slightest randomizing in code impacts the images generated. Although codes are very structured, it is then very easy to create something completely unpredictable. This, then, echoes the very unpredictable nature of the results that happenings tried to achieve. In one of the demos, he mentions how one of the codes once mirrored creates images that we start giving meaning to, whether we see a face, a skull, an animal… It reveals how we as a society can make meaning out of art that perhaps was meant to have another meaning, or no meaning at all.

Assignment 2 – “Random Squares” by Sara Al Mehairi

RECREATION & CONCEPTUALIZATION

This picture is of the original art piece, Random Squares.

For this assignment, my goal was to recreate Herbert Franke’s artwork, “Random Square” from COMPUTER GRAPHICS AND ART May1976 (page 6), using p5.js as accurately as possible. Inspired by Franke’s collaboration with Georg Färber, where Färber utilized computer systems at the University of Munich to generate intricate plots based on dates provided by the artist, my goal was to capture the nature of the original piece by utilizing loops based on random coordinates within a specific range.

Code Highlight

function checkOverlap(x, y, rectangles) {
  for (let i = 0; i < rectangles.length; i++) {
    let { x: rectX, y: rectY, w: rectW, h: rectH } = rectangles[i];
    if (dist(x, y, rectX, rectY) < (rectW + rectH) / 2) {
      return true; //this means overlapping
    }
  }
  return false; //this means not overlapping
}

One aspect of the code that I take pride in is the implementation of a function that checks for (coordinate) overlaps using boolean statements. Initially, the large black rectangles were overlapping, which, to me, was distracting and not aesthetically pleasing, as they are naturally the first thing you see. This function is triggered every time the screen is clicked, causing the rectangles, both large and small, to rearrange themselves according to the specified conditions.

Challenges & Reflection

Initially, I generated black squares of different sizes at randomized locations, relying solely on the provided PDF link. However, with further research about the art piece, I realized it wasn’t a black & white piece but rather a colorful one, resembling the colors of a Starburst in my opinion! Once I came to the realization, I used the colors yellow, pink, and black and played with the opacity of the pink squares to achieve a similar effect when overlapped with yellow. Also, as I was randomizing the size of each square, I later noticed that each color had a specific size, with pink being the smallest and black the largest. You could see that every time I thought I was done, I noticed a slight detail that I had missed.

At first glance, the artwork didn’t seem to have much depth; it appeared like random squares on the screen. However, after looking into the artist’s background and understanding the process behind the artwork, I realized the significant time investment required to create such a piece. One aspect I would like to improve or explore in the next iteration of my attempt is to move away from the literal randomization of coordinates. Instead, I would like to make them dependent on meaningful factors such as dates, NETids, or other elements that can add more meaning.

 

Assignment #2 – Code – ☆Trichromatic Dance☆

For this assignment, I was inspired by one of the films I watched in my first film studies class: Synchromy (dir. Norman McLaren, 1971). This film is  a series of rectangles/squares/lines that vary in position, size, and color – each corresponding to the specific part of the soundtrack. I liked this film as it redefined art for me, particularly avant-garde/experimental film which is the field I lean towards nowadays. I just never thought this is what film could look like until I watched this. Here is the link to the film so you can have an idea:

The visuals were actually not made with a PC. In fact, they were done by scratching over the soundtrack of the film (impressive!), and I thought it could be cool to see how this would work through code instead. Obviously, my artwork is much less elaborate and has no music, but I was visually inspired:

For the color transitions, I used chatGPT to help me understand how to do them. Here is a snippet of the code I incorporated:

let r = sin(frameCount * 0.012 + PI / 2) * 127 + 128;
let g = sin(frameCount * 0.06) * 127 + 128;
let b = sin(frameCount * 0.03 + PI / 2) * 127 + 128;

fill(r, g, b);

First, I set the variables ‘r’, ‘g’, and ‘b’ to animate the three colors (which I then plugged into the ‘fill’ function). I then understood that using the sine function is what will create the oscillation of the colors between 0 and 255. The ‘frameCount’ argument, which is then modified, accounts for the frame rate. As we have seen in class, the generic frame rate is usually 60. By multiplying it, this changes the speed at which the colors transition. The smaller the number by which it is multiplied, the greater the frame rate will be, the quicker the colors will change. For each series (column) of rectangles, I just picked random numbers between 0.01 and 0.09 to multiply ‘frameCount’ with, in order to have different speeds for each ‘r’,’g’, and ‘b’ components of each series. Then, the ‘PI’, ‘PI/2’, and ‘PI/4’ arguments allowed to determine at which phase the sine wave would start. Modifying the phase offset in each series (randomly too) also allowed me to vary the starting color of each column. Finally, the ‘sin()’ function is all multiplied by ‘127+128’. At first, I didn’t really understand why I had to write ‘127+128’ instead of just ‘255’. Then, I used chatGPT to understand that because the sine wave oscillates between -1 and 1, first multiplying it by 127 allowed to get a range between -127 and 127. Then, 128 would be added, and because 128-127=1 and 128+127=255, we could get the range of 1 to 255 which fits the color components of RGB.

It was overall super interesting to learn how to make this, as well as to try and understand how the ‘sin()’ function works altogether in order to create the color transitions. Unfortunately, I accidentally wrote ‘y >= 0’ in one of the for loops at some point towards the end of my code, and I think it sent my code into an infinite loop as the sketch completely froze and I was unable to retrieve any of it. But well, it was a lesson that I had to learn eventually and honestly I had fun practicing all over again.

Reflection on Casey Reas’ Eyeo talk on chance operations

Casey Reas’ Eyeo talk on chance operations opened my eyes to a fascinating realm where art and randomness converge. The discussion around the dynamic interplay between order and chaos in art challenges conventional perceptions. Reas introduces the concept of “controlled randomness,” emphasizing the artist’s ability to set rules while allowing for surprises, ultimately contributing a unique twist to the art produced.

What struck me was the initial concern about digital art disrupting artistic expression due to its unpredictability. However, Reas showcases the idea of “ordered randomness,” demonstrating how artists can maintain control over the code while infusing an element of surprise. This not only adds diversity and excitement to art but also challenges preconceived notions about the medium.

The reading also sparked a thoughtful reflection on the difference between traditional hand-drawn art and algorithmically generated digital art. Casey Reas’ Eyeo talk not only expanded my understanding of the intricate relationship between order and chaos in art but also inspired me to explore the creative possibilities within the realm of digital art and coding. The presentation challenged stereotypes, fostering a deeper appreciation for the intentional and meaningful aspects of randomness in artistic expression.

Reading Reflection Week 3: Eyeo2012_Casey Reas

Jihad Jammal

Intro to IM

Professor Aaron Sherwood

Reading Reflection Week 3

Feb. 5, 2024

 

Controlled Randomness at the Intersection of Programming and Creativity

 

After watching the video, my understanding of digital art has been significantly broadened by the concept of “controlled randomness”, especially with the intersection of computer programming and creative exploration. Reas’s explanation, where he describes the process of “simply flipping a coin and drawing a left or right but it creates this pattern where we have open areas and closed areas; it becomes vaguely maze-like, and we are able to approach computing from many different angles just from using a single program,” (31:10 – 32:00) eloquently captures the essence of this innovative method. Because the “controlled randomness” methodology uses unpredictability as a basis for creativity in a digital world that is normally perceived as a rigid and unchanging medium, it has changed my understanding of what may be deemed artistic creation/expression. While I understood that art might be highly personal to the individual, I had always thought of art as a clear expression of the artist’s intention, as seen in the brushstrokes or the chiseled stone. Reas’s work, on the other hand, offers a convincing alternative by demonstrating how artists can create the conditions for chance to occur within limitations, so questioning traditional ideas of artistry and emphasizing the special possibilities that arise from the collaboration of computational processes and human creativity.

Furthermore, Reas’s assertion sheds light on how well-managed randomness can act as a link between the fluidity of artistic expression and the deterministic character of code. This combination elevates programming languages from being only tools to being active players in the creation of art, encouraging a deeper reflection on the creative possibilities they possess. It is both illuminating and encouraging to see that intricate, visually beautiful patterns with substantial artistic value can be produced by basic code. It opens up new avenues for artists to investigate the dynamics of order and chaos, intention, and chance by extending the creative canvas beyond conventional media. As such there is a great deal of room for creativity at any skill level when it comes to transforming computer engineering tools for creative expression, especially now that it is known that specialized equipment is not necessary.

 

Citations:

Festival, E. (2012). Eyeo2012 – Casey Reas. [online] Vimeo. Available at: https://vimeo.com/45851523 [Accessed 5 Feb. 2024].