I found this read extremely fascinating. I really liked the section where the author discussed the economics behind digitization, the way digitization appeals to non-rivalry and zero marginal cost of reproduction. I also thought his discussion of free products was interesting. It is truly captivating how so many creators devote so much time producing amazing online content without expecting anything in return. Although he claimed that free content wasn’t necessarily a bad thing, he didn’t really elaborate on why it was beneficial either. I was hoping he would further unpack this discussion. Lastly, I thought some of the facts he laid down was really interesting. Facts such as if digitization growth grows at the pace it has been growing at, we will run out of the metric system. Or, how the combined level of robotic chatter is soon likely to exceed the sum of all human voice conversations taking place on wireless grids. This read had some really engaging material.
Data Visualization
First, I should note that I could not find the correct library to access the data I was trying to use in Java, so I am using random data.
When presented with this prompt, my first thought was my capstone, which is largely data visualization. However, it uses software I could not recreate in less than a couple years, so I decided to process data similar to my capstone in a visually interesting way. In other words, I wanted to take a large set of floats mapped to 2d space, and group them into maxima. This is a very simple way to describe how stars are found in a digital image, which is roughly what I seek to recreate. I did this, but it was a bit boring, so I also set it up to make a more dynamic image that follows similar logic. These are the two modes in my program, mode 0 is more interesting but mode 1 is more intuitive.
float[][] visualization; float[][] tempVisualization; float max=0; float min=255; float range=255; float growthfactor=255; int mode= 0; //loat[] data; ImageHDU imageHdu; void setup(){ size(100,100); frameRate(15); //data = getImageHDUDataInFloatArray(imageHdu); visualization= new float[width][height]; tempVisualization= new float[width][height]; for(int x= 0; x< width; x++){ for(int y= 0; y< height; y++){ visualization[x][y]= random(25); //println(visualization[x][y]); } } } void draw(){ min=255; max=0; for(int x= 1; x< width-1; x++){ for(int y= 1; y< height-1; y++){ if(mode==0){ if(visualization[x][y]>visualization[x][y+1]&& visualization[x][y]>visualization[x][y-1]&& visualization[x][y]>visualization[x+1][y+1]&& visualization[x][y]>visualization[x-1][y+1]&& visualization[x][y]>visualization[x+1][y-1]&& visualization[x][y]>visualization[x-1][y-1]&& visualization[x][y]>visualization[x-1][y]&& visualization[x][y]>visualization[x+1][y]){ tempVisualization[x][y]=visualization[x][y]+ (visualization[x-1][y]+ visualization[x-1][y-1]+ visualization[x][y-1]+ visualization[x+1][y-1]+ visualization[x-1][y+1]+ visualization[x][y+1]+ visualization[x+1][y+1]+ visualization[x+1][y])/2; } else{ tempVisualization[x][y]=visualization[x][y]- (visualization[x-1][y]+ visualization[x-1][y-1]+ visualization[x][y-1]+ visualization[x+1][y-1]+ visualization[x-1][y+1]+ visualization[x][y+1]+ visualization[x+1][y+1]+ visualization[x+1][y])/9; } } if(mode==1){ for(int x2=-1; x2<2; x2++){ for(int y2=-1; y2<2; y2++){ if(x2!=0||y2!=0){ process(x,y,x+x2,y+y2); } } } } max=max(max,tempVisualization[x][y]); min=min(min,tempVisualization[x][y]); stroke(tempVisualization[x][y]); point(x,y); } } range=max-min; range=min(range,254); if(mode==1){ growthfactor=range*0.7; } if(mode==0){ for(int x= 0; x< width; x++){ for(int y= 0; y< height; y++){ visualization[x][y]= visualization[x][y]*growthfactor/range; } } } println("looped"); visualization=tempVisualization; } public void process(int largeX, int largeY, int smallX, int smallY){ if(visualization[largeX][largeY]>visualization[smallX][smallY]){ tempVisualization[largeX][largeY]+=visualization[smallX][smallY]; } else{ tempVisualization[largeX][largeY]=tempVisualization[largeX][largeY]*growthfactor/range; } }
The file type I was attempting to use if fits, which I know the library for in python but not java.
Women’s share of the workforce
First of all, for data visualization, you need data. So I had previously downloaded and scrubbed a database from the United Nations containing data for women’s share of the workforce in a 189 countries from 1985 to 2006. The list of countries included in the database can be found here: https://github.com/AdhamChakohi/IntrotoIm/blob/master/list%20of%20countries.txt
The original database can be found here: http://data.un.org/Data.aspx?d=GenderStat&f=inID%3a107
I had previously ran the database through a python script to clean it up and remove the unnecessary data, and also add the average and medians across the years for each country. Here’s the python script:
# gets median and average for each country def hasNumbers(inputString): return any(char.isdigit() for char in inputString) def getStats(file, country): country = country.lower() fp = open(file, 'r') listSum = 0 counter = 0 medianList = [] for i in fp: i = i.strip().split(',') if i[0][1:-1].lower() == country: print(i) medianList.append(float(i[5][1:-1])) counter += 1 listSum += float(i[5][1:-1]) mid = findMiddle(medianList) return round(listSum/counter,1), mid # finds the middle of the list for the purpose of finding the median def findMiddle(x): mid = float(len(x))/2 if mid%2 == 0: return (x[int(mid)]+x[int(mid-1)])/2 else: return x[int(mid-.5)] def main(): file_name = "dataset.csv" fp = open(file_name,'r') target = file_name[:-4]+"_out.csv" t = open(target,'w') lines_read,lines_written = 0,0 t.write('country,year,percentage,average across the years,median\n') for i in fp: current = i.strip().split(",") # print(current[0]) if any(j.isdigit() for j in i) and not hasNumbers(current[0][1:-1]): #the [1:-1] indexes are the remove the quotation marks that the data entries come in average, median = getStats(file_name,current[0][1:-1]) written = current[0][1:-1]+","+current[2][1:-1]+","+current[5][1:-1]+","+str(average)+","+str(median)+"\n" # print(written) t.write(written) main()
This is code that I have written months ago, and I just found out I had a bug that was removing the data for around 50 countries from the database, so I fixed that. Moving on, the data visualization:
I made this sort of applet, that visualizes women’s share of the workforce for the country that is entered, and with the ability to scroll through the different years available by pressing the left and right keys. There are a 100 squares displayed, the red squares representing female workers, and blue representing the male workers.
more pictures:
The code :
String countryInput = "Palestinian Territory Occupied"; Table table; float[][] stats = new float[22][3]; int counter = 0; int pointer = 0; void setup() { size(800, 800); table = loadTable("dataset_out.csv", "header,csv"); for (TableRow row : table.rows()) { String country = trim(row.getString("country")); if (country.equals(countryInput)) { float year = row.getFloat("year"); float percentage = row.getFloat("percentage"); float median = row.getFloat("median"); stats[counter][0] = year; stats[counter][1] = percentage; stats[counter][2] = median; counter++; } } rectMode(CENTER); } void draw() { int count2 = 0; int percent = round((stats[pointer%22][1]/100)*100); //println(stats[pointer][1],count2,conv); background(0); fill(255,0,0); rect(20,20,20,20); fill(0,0,255); rect(20,50,20,20); fill(255, 255, 255); textAlign(LEFT); textSize(16); text("Female",40,27); text("Male",40,57); textSize(20); textAlign(RIGHT); text("Median across the years: "+str(round(stats[pointer%22][2]))+"%",750,40); textAlign(CENTER); textSize(36); text(str(round(stats[pointer%22][0])), 380, 700); text(countryInput, 380, 100); stroke(10); text("\u2190", 200,700); text("\u2192", 560,700); for (int i = 200; i<600; i+=40) { for (int j = 200; j<600; j+=40) { if (count2<=percent) { fill(255, 0, 0); } else { fill(0, 0, 255); } stroke(0); rect(i, j, 20, 20); count2++; } } } void keyPressed() { println(pointer); if (key==CODED) { if (keyCode == LEFT) { pointer++; } else if (keyCode == RIGHT) { if (pointer == 0) { pointer = 21; } else { pointer--; } } } }
All the files can be downloaded from here:
https://github.com/AdhamChakohi/IntrotoIm
The Digitalization of Just About Everything Response
If we told our ancestors from 100 years ago that many many products (especially those in the information/entertainment industry) would be made free, perfect, instantaneous, and easily accessible, they’d probably laugh and tell us to stop dreaming.
With the advancement of dynamic digital data storage solutions, it has become so much easier to record and share media. Take photography as an example. Before the invention of digital cameras, each and every photo had to be burned onto a physical piece of film. A roll of film that costs about the same as a standard 8 or 16GB SD card could only store less than 1% of the photos that that SD card could, not to mention that it can only be used once. Today, we literally just hold down the shutter and take 100 photos of the same thing just so we can choose the “best” looking one. Life must be hard before digitalization became a thing.
Generative Text Design
For this week’s assignment, I decided to make a generative text design rather than making a data visualisation – don’t really know why, I just thought it would be cooler.
In class, when we were going through examples, I wanted to do do something so that each letter of the word would be its own object, meaning that I could manipulate each letter and not have it so that it is bound by the whole word. I started by making each letter go under a class. I used Aaron’s example of inputting texts and the text formatting, though I changed the text font into another monospaced font.
Using a Processing example on processing.org, I was able to manipulate pieces of code so that I got my letters to vibrate, move and shake in a fashion that, to me, resembled what it would be like in an earthquake. I, therefore, decided to change the word to “Earthquake”, instead of the original “Ivory” that I had inputted. The soil background was just for more of an “earthy” effect – not much reason to it.
Originally, I programmed it so that when the mouse was pressed, the letters would move in arbitrary directions (like an earthquake where things go everywhere) and then when released, would move back to the home position. However, I felt like this quick and instant movement into the home position did not resemble a real earthquake and so I attempted to write some code so that the movement towards the home position would be slower and more subtle. I tried to mimic Aaron’s use of speed and acceleration in his project that he showed us, but didn’t get that to work no matter how much I tried. I then resorted to google to find out what other functions I could use.
After experimenting with many different types of functions, I resorted to asking a friend for help. He suggested I used some maths, where I would write a function that would get the difference between the x position and the home x position (and the difference between the y position and the home y position) and divide that by a certain number and then equate that to x, so that there would be a movement back towards the initial home position that is slower. I tried to implement what he suggested, but I couldn’t get it to work.
After thinking about what other functions I could try and use, my friend asked me if I had used the lerp () function before. I said that I have, but only when drawing lines and not for moving objects around. He said that the concept is the same and would probably work in the case of my project. I, therefore, started playing around with the lerp function in the hopes that I could finally get the letters to do what I wanted it to do.
Before I explain the next process that I took, I feel that it’s important for me to include my code so that I could refer to it whilst describing.
Here is the main setup tab:
import geomerative.*; RFont font; PImage bg; String message = "EARTHQUAKE"; Letter[] letters; void setup() { size(900, 600); bg = loadImage ("soil.jpg"); background(255); textSize (70); RG.init(this); font = new RFont("Courier New Bold.ttf", 1000); letters = new Letter[message.length()]; int x = 250; for (int i = 0; i < message.length(); i++) { letters[i] = new Letter(x,310,message.charAt(i)); x += textWidth(message.charAt(i)); } } void draw() { background(bg); for (int i = 0; i < letters.length; i++) { letters[i].display(); // Display all letters if (mousePressed) { letters[i].shake(); } else { letters[i].secondPosition(); } if (keyPressed) { letters[i].home(); } } }
Here is the letters class tab:
class Letter { char letter; float homex, homey; float x, y; Letter (float _x, float _y, char _letter) { homex = x = _x; homey = y =_y; letter = _letter; } void display() { fill(255); textAlign(CENTER); text(letter, x, y); } void shake() { x += random(-8, 8); y += random(-8, 8); } void secondPosition() { lerp(x, homex, 0.07); lerp(y, homey, 0.07); } void home() { x = lerp(x, homex, 0.02); y = lerp(y, homey, 0.02); } }
The first lerp functions that I got to work were the ones seen in under the void secondPosition () function, where I did not equate x and y to the lerp functions. This meant that rather than moving back to the home positions, when I clicked the mouse and the letters started moving haphazardly around and I released the mouse, the letters would stay in the place where I released the mouse. I thought that this was pretty cool and represented the reality of the earthquake well – if we were to imagine the letters being actual objects (like furniture for example), after an earthquake happens, the furniture would not move back by itself and would require some sort of other movement to move it back (humans moving it) or to move it around even more (aftershocks of the earthquakes, perhaps). I wanted to keep the code, but it wasn’t what I originally wanted to do, I still wanted a function that would move my letters back to the original position.
I realised that I needed more than a mousePressed () function if I wanted to to do two different things with the lerp () function. At this point, after experimenting with the lerp () function even more, I realised that equating x and y to the lerp functions would move the letters back. I wanted to keep the two ideas of 1) allowing for aftershocks to happen (continued shaking away from initial position) and 2) allowing for “clean-up” to happen (smoother movement towards initial letter position). I decided to allocate movement 1 to mouse press and movement 2 to key press.
This produced the effect shown in the video below:
If I were to improve this project, I would change and play around with the colour of the text. I played around with the lerpColor () function but couldn’t get it to work.
DISCLAIMER: Maybe I should have put this at the top…sorry that there’s a lot of words in this post but I’m pretty proud of the process that I took to finish this project and was able to use code that I actually understand and found to not be complicated and I was able to debug my own code when it didn’t work and I’m just very thankful for friends (shoutout to Navya and Abdullah) who directed me in the way that allowed me to discover things myself and help me realise that I could do something cool! I shall end the blog post now.
Digitize Everything – Response
I really enjoyed this reading, not only because it was simple to understand but also because the main example used hit close to home. Waze improved the safety of my family a lot. Back in Brazil, there are some shady neighborhoods where people just should not drive through. Actually, many of the streets shouldn’t be driven through at night anyways. Google maps always gives the quickest way to get from point A to B. Waze on the other hand takes into account the favelas and the intense traffic that is inevitable in Brazil. It allows my family members to be safe and also to avoid being stuck in the same spot for 4 hours.
Not to sound more like an advertisement, but it I think that the concept of the language being built upon itself is extremely interesting. Regardless of human interaction with the application, the language is still being expanded upon which maximizes efficiency and the quality of Waze.
These types of computing languages are extremely ‘smart’ which will definitely advance in this ever more connected world.
Digitize Everything: Response
I think that this reading was fairly simple and easy to understand. The examples he used to get across the ideas were very normal, simple examples such as the GPS and the photocopying. These simple examples make it easy to visualize the concepts he is trying to explain because the reader does not feel pressured to first try and understand the concept.
I really liked the Machine to Machine concept, where machines have developed their own network of communication that requires no human intervention.
Digitization has been useful and productive in the creation and spreading of information and knowledge. It has helped in everyday life tasks, as well as research and statistical analysis of lifestyle, money, interests, etc.
The Digitization of Just About Everything
This is perhaps the most straightforward reading we have had, that finally outlines the basic differences between digital and physical products. It is not particularly exciting or revolutionary, but is important in that it clearly explains that it clearly identifies why the digital economy is consuming the physical one at every opportunity. Unlike physical goods, it costs next to nothing to continue to reproduce the product. I have seen this to a large extent myself in video games. When I was younger games came on physical disks, and consistently cost about 60 dollars. While the standard price has not changed, most games are now sold digitally, and at least on steam frequently go on sale for up to 90% off, since any sale at all is a profit.
Digitise Everything – Response
Reading about the digitisation of “everything” reminded me a lot of another class I’m in that I keep on referencing in my responses to readings, ‘Future of Medicine’. Within that class we talk about how medicine is evolving in a way that requires data and information to become digitalised and therefore, more widely accessible. In this reading, this idea becomes clear on page 86, where the author notes that digitisation increases levels of understanding. Something that I have not really thought about, however, is the idea shown on page 88 that digitalisation can help us better understand the past. Although digitalisation may potentially decrease the value of some aspects of the past (e.g. the value of the knowledge on some piece of information), what digitalisation can also do is not only understand the past but also preserve bits of the past. I think that in this age, preservation and conservation are two very important actions that we should take – digitalisation of everything aids us in this process.
Interactive Name Design – Ross Jiang
For my project,I want to display my name and enable user to interact with the design. I watched a few videos on steering behaviours. Basically all “vehicles” behave independently and move towards a certain point on the text. I referenced Aaron’s textLine example on how to turn a text to points and I modified a Vehicle class from a Daniel Shiffman’s example.
If any “vehicle” is within a certain range of the cursor provided the cursor is moving, the target would change from a point on the text to the cursor and that is how user is able to interact and change the text.
the font and full code can be found on:
https://github.com/ross67/IntroToIm/tree/master/interactiveName
//Thanks to Daniel Shiffman for explanation on steering behaviors on his Youtube Channel:https://www.youtube.com/user/shiffman // the vehicle class is modified from his coding example on https://www.youtube.com/watch?v=4zhJlkGQTvU import geomerative.*; String fontName = "IndieFlower.ttf"; String textTyped = "Ross Jiang"; RFont font; RPoint[] pnts; Vehicle[] vehicles = new Vehicle[600]; void setup(){ //size(800, 600); size(1440,900); background(51); noFill(); stroke(255); RG.init(this); font = new RFont(fontName, 230, RFont.LEFT); RCommand.setSegmentLength (10); RCommand.setSegmentator(RCommand.UNIFORMLENGTH); RGroup grp; grp = font.toGroup(textTyped); grp = grp.toPolygonGroup(); pnts = grp.getPoints(); //define the vehicles for (int i=0; i<150; i++){ //left Vehicle v = new Vehicle(0, i*9.6); vehicles[i] = v; } for (int j=150; j<300; j++){ //right Vehicle v = new Vehicle(1440, (j-150)*9.6); vehicles[j] = v; } for (int k=300; k<450; k++){ //top Vehicle v = new Vehicle((k-300)*6, 0); vehicles[k] = v; } for (int l=450; l<600; l++){ //bot Vehicle v = new Vehicle((l-450)*6, 900); vehicles[l] = v; } } void draw(){ background(51); int index = 0; for (Vehicle v: vehicles){ PVector p = new PVector(pnts[index].x+250,pnts[index].y+400); v.arrive(p); v.update(); v.display(); index++; } }
class Vehicle{ PVector position; PVector velocity; PVector acceleration; boolean mouseClose = false; float maxForce; //max steering force (how fast it can turn around) float maxSpeed; // max speed Vehicle(float x, float y){ acceleration = new PVector(0,0); velocity = new PVector(0,-2); position = new PVector(x,y); maxSpeed = 4; maxForce = 0.1; } // Method to update position void update() { // Update velocity velocity.add(acceleration); // Limit speed velocity.limit(maxSpeed); position.add(velocity); // Reset accelerationelertion to 0 each cycle acceleration.mult(0); } void applyForce(PVector force) { // We could add mass here if we want A = F / M acceleration.add(force); } void arrive(PVector target){ checkMouse(); PVector desired = PVector.sub(target,position); // A vector pointing from the position to the target if(mouseClose){ PVector mouse = new PVector(mouseX,mouseY); desired = PVector.sub(mouse,position); // A vector pointing from the position to the cursor } float d = desired.mag(); // distance b/w position and target if (d < 100) { float m = map(d,0,100,0,maxSpeed); // if vehicle is close enough, slow down desired.setMag(m); } else { desired.setMag(maxSpeed); // or else set it to max speed } // Steering = Desired minus Velocity (could potential move backwards) PVector steer = PVector.sub(desired,velocity); steer.limit(maxForce); // Limit to maximum steering force applyForce(steer); } void display() { ellipse(position.x, position.y, 6, 6); } void checkMouse() { PVector mouse = new PVector(mouseX,mouseY); float d = PVector.sub(mouse,position).mag(); if (d<333 && mouseX!=pmouseX && mouseY!=pmouseY) { mouseClose = true; println(d); }else{ mouseClose = false; } } }