Crickets Chirping

mon qui si, mon qui d’où

Archive for the ‘Code’ Category

MapReduce with JavaScript, and My New Blog: dashdashverbose

without comments

I’ve started a new blog, dashdashverbose, where I will be putting my geekier code-related entries from now on.

I’m splitting the CS geekery off because I get one consistent piece of feedback from people who actually offer feedback on this blog: “It’s interesting except for the technical posts- I don’t get those so I just scroll past ‘em.”

The name “dashdashverbose” comes from a command line option used by unix-like applications: “- -verbose” usually tells the app to spit out as much information about what it’s doing as it can. The output is typically a firehose of technical details that only a few people care about.

Kinda like my geekier posts :)

The inaugural –verbose entry is about how to run MapReduce with JavaScript.

Written by banksean

January 8th, 2009 at 4:19 pm

Posted in Code,General

js.Processing with Rhino

with 4 comments

Processing.js: Processing in JavaScript

A few months ago JavaScript Ninja John Resig unleashed processing.js. Like many others I was shocked and amazed. I love to tinker with Processing, and I also do a fair amount of JavaScript work, so I was keenly interested.

There are some limitations to using the browser for the type of work people want to do with Processing though. Processing.js is even slower than Processing applets, and it’s not even a full implementation.

However, I am intrigued by the use of JavaScript to do Processing-like stuff.

js.Processing: JavaScript in Processing

The Processing language inherits some unfortunate (and personally annoying) features of Java since that’s what it compiles down to.

I actually prefer JavaScript to the Processing language because it’s loosely typed and has some other nifty features.

I’d like to be able to use all of Processing’s capabilities (not the crippled applet variety), AND program with JavaScript instead of Processing’s language.

cake.have().eat();

So today I created a .pde that loads Rhino, creates a JavaScript execution context, stuffs itself into that context, loads an external javascript file and runs it.

And js.Processing is born.

I added some functions to proxy the built-in Processing callbacks so you can write “draw(){}” and “mouseDragged(){}” in javascript and they do what you’d expect.

Here’s the main shell Processing sketch that runs the Javascript (listing below):


/**
 * Experiment to drive Processing with JavaScript.
 * Uses Rhino: https://developer.mozilla.org/en/Rhino_Overview
 * This does not currently work in an applet due to some Rhino issues
 * with class loading and optimization.
 *
 * This class itself isn't where you put the javascript.  .js files
 * should go in your processing project's code/ folder.  Load your .js
 * script explicitly in setup() below.  This example is hard-coded to
 * laod "guilloches.js", an example I ported from regular Processing
 * but you can set it to whatever file name you want.
 *
 * This class just forwards calls from Processing into your javascript code.
 *
 * To access Processing methods in javascript, prefix them with "p5." -
 * I'm looking at how to make those functions global, if that's possible.
 *
 * author: Sean McCullough banksean@gmail.com
 */
import org.mozilla.javascript.*;

Context cx;
Scriptable scope;
Function jsInit;
Function jsDraw;
Function jsMouseDragged;
Function jsMousePressed;
Function jsMouseReleased;
Function jsKeyPressed;
Function jsKeyReleased;

void setup() {
  cx = Context.enter();   

  // TODO: make this work so it can run in an applet.  Because optimization levels 0 and higher do classLoader voodoo,
  // the browser seems to object.  Setting it to -1, however, makes JavaAdapter no workie and that makes this exercise
  // even more useless.
  // cx.setOptimizationLevel(-1);

  scope = cx.initStandardObjects();
  size(400, 400);

  // String[] globalNames = {"log"};
  // TODO: make this work so global functions don't need to be prefixed with p5.whatever.
  // scope.defineFunctionProperties(globalNames, Class.forName("jstest.JSProcessing"), ScriptableObject.DONTENUM);

  Object wrappedThis = Context.javaToJS(this, scope);

  // p5 is the global "Processing" object available to your scripts.  Prefix any processing api calls with "p5." or they
  // won't work.
  ScriptableObject.putProperty(scope, "p5", wrappedThis);

  String srcStrings[] = loadStrings("guilloches.js");
  String src = "";
  for (int i=0; i<srcStrings.length; i++) {
    src += srcStrings[i] + "\n";
  }

  cx.evaluateString(scope, src, "<cmd>", 1, null);

  jsInit = getFunction("init");
  jsDraw = getFunction("draw");
  jsMouseDragged = getFunction("mouseDragged");
  jsMousePressed = getFunction("mousePressed");
  jsMouseReleased = getFunction("mouseReleased");

  jsKeyPressed = getFunction("keyPressed");
  jsKeyReleased = getFunction("keyReleased");

  jsInit.call(cx, scope, scope, null);
}

Function getFunction(String name) {
  Object o = scope.get(name, scope);
  if (o instanceof Function) { return (Function) o; }
  return null;
}

void draw() {
  callIfNotNull(jsDraw);
}

void mouseDragged() {
  callIfNotNull(jsMouseDragged);
}

void mousePressed() {
  callIfNotNull(jsMousePressed);
}

void mouseReleased() {
  callIfNotNull(jsMouseReleased);
}

void keyPressed() {
  callIfNotNull(jsKeyPressed);
}

void keyReleased() {
  callIfNotNull(jsKeyReleased);
}

void callIfNotNull(Function f) {
  if (f != null) {
    f.call(cx, scope, scope, null);
  }
}

public void log(String str) {
  System.out.println(str);
}

//////////////////// Begin overloaded global functions //////////////////////

public void stroke(String cr) {
  stroke((Integer)colors.get(cr));
}

public void fill(String s) {
  fill((Integer)colors.get(s));
}

HashMap colors = new HashMap();

/**
 * Rhino/Javascript don't support long types.  In processing, a color object is
 * represented by a long, so we have a problem.  This method proxies color() to
 * return a JS-safe reference to a processing color value.
 * See:
 * http://www.mozilla.org/rhino/apidocs/org/mozilla/javascript/FunctionObject.html
 * Also, it's called getColor() instead of color() because processing won't let
 * me override that method name.  Probably has something to do with it being a
 * reserved word as well as a method/class.  Should probably just replace this
 * with a hex string of the color values.
 */
public String getColor(int r, int g, int b, int a) {
  color c = color(r,g,b,a);
  colors.put("" + c, c);
  return "" + c;
}

Here’s what my Guilloches sketch looks like, re-implemented in js.Processing:


function init() {
  p5.smooth();
  p5.background(255);
  // NOTE: have to use getColor() instead of color()
  // because JavaScript is retarded about Longs, which color() returns.
  var c = p5.getColor(0, 0, 0, 64);
  p5.stroke(c);
  p5.frameRate(10);
  p5.strokeWeight(0.5);
  p5.strokeCap(p5.SQUARE);
}

var lastSet = false;
var lastX = 0;
var lastY = 0;

var dTheta = 0.0004 * p5.PI;
var theta = 0.0;

var R = 50.0;
var r = -0.25;
var p = 25.0;
var m = 1;
var n = 6.00;
var Q = 0; 

function mousePressed() {
  drawStuff();
}

function mouseDragged() {
  drawStuff();
}

function draw() {
  if (!lastSet) drawStuff();
}

function drawStuff() {
  var mx = 2.0*(p5.width/2.0-p5.mouseX)/p5.width;
  var my = 2.0*(p5.height/2.0-p5.mouseY)/p5.height;

  if (lastSet)
    Q = (50*Math.sqrt(mx*mx + my*my));

  var Rr = R + r;
  var rp = r + p;

  p5.background(255);

  var mTheta = m*theta;
  var mThetaRrr = m*theta*Rr/r;
  var nTheta = n*theta;
  var x;
  var y;
  var plotX;
  var plotY;

  for (var i=0; i<15000; i++) {
  theta += dTheta;

  mTheta = m*theta;
  mThetaRrr = m*theta*Rr/r;
  nTheta = n*theta;

  x = (Rr)*Math.cos(mTheta) +
	(rp)*Math.cos(mThetaRrr) +
	Q*Math.cos(nTheta);
  y = (Rr)*Math.sin(mTheta) +
	(rp)*Math.sin(mThetaRrr) +
	Q*Math.sin(nTheta);

  plotX = (p5.width/2 + (x/125)*p5.width/2);
  plotY = (p5.height/2 + (y/125)*p5.height/2);
  if (!lastSet) {
    lastSet = true;
    lastX = plotX;
    lastY = plotY;
  }

  p5.line(lastX, lastY, plotX, plotY);
  lastX = plotX;
  lastY = plotY;
  }
}

I’m not really taking advantage of JavaScript language features much here (besides not having to worry about variable types) but it proves the concept.

I haven’t done any formal performance tests, but this seems to run slower than the original.

Download the js.Processing Project .zip Here

The JavaScript source code is in the data/ folder (since it’s loaded as an external resource).

Of course I imagine there’s an easier way to go about this, especially if one were to actually modify the Processing source code itself to accommodate JavaScript/Rhino.

Written by banksean

December 7th, 2008 at 9:23 pm

Posted in Code,General,Processing

ep4js: Genetic/Evolutionary Programming in JavaScript

with 4 comments

From my pet project backlog: ep4js. You could say it’s from my “things you shouldn’t try to do in javascript” catalog as well.

Actually I was spurred to put this out there by this post from John Resig. This isn’t the exact same thing, but it got me thinking I might not be the only one interested in doing this.

ep4js aims to be an evolutionary programming framework for javascript. It’s very bare bones (very naive about most things, actually) but I managed to apply it to at least one useful real-world problem: symbolic regression. AKA “given a set of samples of an unknown function, try to approximate it with an equation”

I have some other examples in the works but they’re pretty rough: a bin packer (NP-Complete FTW), and Iterated Prisoners’ Dilemma strategies.

And of course there’s no end of GA/EP tweaks to apply to it. Right now the pairing for crossover is barely better than random, yadda yadda. Point is it works at all right now.

Here’s the demo, if you’re adventurous/patient:

Here’s the project page on code.google.com

Of course you may wonder what such a thing would be good for. I’m sure other people already have some ideas.

I may try to pair it up with processing.js for some experiments. That would be fun.

Written by banksean

December 2nd, 2008 at 3:10 am

Posted in Code,General

Guilloches

with 2 comments

I was inspired by this post on Guilloches to generate them in Processing (It’s been that kind of weekend. At least my unit tests are passing now :)

Click here to try out the applet

Or check out these stills:

This basically look like spirographs for now, but I’m sure there are ways to make them more interesting. Maybe have the extended cycloid follow some other curve besides a circle.

Written by banksean

November 24th, 2008 at 1:00 am

Posted in Code,General,Processing

Palin Speech Generator

with 2 comments

I found another use for my JavaScript Markov Chain thingie: train it on transcripts of Sarah Palin’s interviews and speeches. Viola.

[Yes, I've seen interviewpalin.com.]

Written by banksean

October 6th, 2008 at 7:52 pm

Posted in Code,General

Protocol Buffers

without comments

Newly open-sourced goodies from teh goog: Thrift, meet Protocol Buffers. I believe you two have a lot in common. Mark Slee (one of authors of the Thrift paper) apparently interned at google.

Written by banksean

July 7th, 2008 at 5:52 pm

Posted in Code,General

Random Sampling in JavaScript

with one comment

I’m working on a personal project that requires me to take random samples from arrays in JavaScript. I’ll write about the bigger project in detail later, but for now here’s a piece that may be of use all by itself.

Context:

If you were to randomly increment integers in a JavaScript Array using plain ol’ Math.random() you might end up with something like this (blue=10000, green=1000, red=100 samples, respectively):



But what if you want to sample from a Normal distribution?



Then you might want to use some code I wrote.

Enjoy, send me bug reports, do whatever.

Written by banksean

December 25th, 2007 at 4:14 pm

Posted in Code,General

Comments Now OpenID-Enabled

with 7 comments

I jumped on the OpenID bandwagon and installed this WordPress OpenID Plugin. It allows you to post comments here using an OpenID URL. In technical terms, my blog is now an OpenID Consumer. This means I can accept logins using OpenID but I don’t provide the actual accounts. If you want an OpenID URL of your own to play around with, here’s a site just for that purpose.

Now when you post a comment you can either use the old tried and true anonymous fields and enter your name, email address and homepage URL every time, or you can just paste your OpenID URL into the top field and be done with it. Your choice.

So go there and get an account then come back and try commenting on this post with it.

I mean, if you’re really bored.

Josh and I had some interesting off-line discussions about OpenID and Facebook (more like OpenID vs. Facebook) a while back. I would try to summarize my thoughts here in this post, but his are more interesting.

Written by banksean

September 16th, 2007 at 4:52 pm

Posted in Code,General

Funny Blog Comment

with 4 comments

Check out this post. Scroll down to the comment by “Lester Bangs.” I don’t know if it’s a joke or not but either way it resonated with me. It’s programmery/Ruby related, but still might be funny to you even if you don’t write code. you know sometimes I think I should write less about code since most of my friends don’t write code, but then I think I should write what I know, and I know code. And bacon. I was talking to Craig at lunch the other day about the adage, “you are what you repeatedly do” – that means that if you don’t have something that you repeatedly do, then you are essentially nothing. That got me thinking about consistency, and how what I do on this blog lacks it. They say it takes a while to “find your voice” but shit, I’ve been doing this since 2002 so maybe I just don’t have one. Is this nothing? Is my existence in the minds of others dictated by the consistency of my words and actions? That sounds like a prison walled with mirrors. Consistency is often foolish, as I’m discovering in my reading of Persuasion by Chialdini (highly recommended, btw. one of my many books in progress :). Why can’t people value variety over consistency? I think I do. Consistent = boring. There’s nothing to take away from something after you’ve experienced it a hundred times. Like kids watching teletubbies saying “again!” do we expect to repeat our grown up experiences and interactions with others over and over? Like Ground Hog Day? That’s my birthday so maybe the filmmakers were trying to tell me something. The one thing that I consistently blog about is bacon, and that’s not really what I’d like to be known for. That’s what people remember about my blog, but it’s not the best stuff I put up here. Like when I ego surf del.icio.us for people who’ve bookmarked my site, bacon shows up. I was reading my friends’ bookmarks on delicious and one of them tagged an amusingly titled blog post as Ruby, and since I’ve been using ruby a lot lately I clicked on it to check it out. Bookmark sharing sites are like a freehand sketch of the collective consciousness (or a geeky corner of it) They’re primarily a way to organize your own external long-term memory, but the secondary function of sharing lets us learn from others when and how we structure that memory with tags. I often see people reading the same things I read even though we might not even know each other I know we both had similar experiences reading something. It might seem pathetically fanboyish to subscribe to a famous person’s delicious bookmarks just because you think they’re smart but I think it’s a good thing. I’m glad people think it’s funny but I don’t really want to be known for bacon. Maybe I should blog more consistently about something else. I have to clarify that what I got out of that ruby-related blog post wasn’t necessarily the same thing that my friend got. See, I would have tagged it “funny” because I think it’s funny. Since that comment was posted 8 days ago, and dave didn’t bookmark it until yesterday, he most likely saw the comment but didn’t find it remarkable. So that’s an example of one of the gaps in the retraced lines of the aforementioned freehand sketch of the collective consciousness.

Written by banksean

August 14th, 2007 at 4:08 pm

Posted in Code,General