QCgravlens is a gravitational lens simulation based on Apple's Quartz Composer environment. The software warps the image from your Mac's webcam in real time, in an analogous way as the lens RXJ1131-1231, discovered by Sluse et al. (2003). In this particular lens system, a galaxy deflects the light of a background quasar and its host galaxy. This leads to the formation of 4 separate images of the quasar, and a spectacular Einstein ring.

QCgravlens has 3 display modes :

  • What you would see without the presence of the lensing galaxy (i.e., the source plane, caustics and QSO position are drawn as well)
  • The warped image that we see due to the space-time distortion by the lensing galaxy (i.e., the image plane)
  • The Hubble Space Telescope image of RXJ1131-1231 (data from CASTLES)


Simple Standalone App

The latest (and probably last) version, v1.2, released in September 2018, fixes a compatibility issue with macOS High Sierra, and the problem of a displaced lens model whenever the aspect ratio in full-screen-mode was not 4:3. Also, the support for the discontinued Apple Remote was removed.

The requirements for this v1.2 are macOS 10.6 or above (I've only tested it with High Sierra 10.13.6, but in theory it should work with older versions down to 10.6), and the internal iSight or an external webcam.

  1. Download QCgravlens.app.zip (1.6 MB), and decompress it.
  2. Run the app. You might have to allow this from within your Security & Privacy preference pane.
  3. Click the green button or use the Window menu to go full screen.
  4. Switch between the 3 modes using either the keyboard (right or left arrow keys) or the mouse (right or left button).
  5. Press esc to quit.

If an external iSight or webcam is connected, it gets automatically selected as video source. For public outreach events I'm using a Unibrain firewire camera resting on a table, so to clearly make the distinction between observer, deflector, and source.


The idea of such a webcam simulation is not mine ! Thanks to a team from the University of Tübingen (I think... they wrote an article about a very similar black hole simulation maybe around 2000 in Sterne und Weltraum or Astronomie Heute but to my shame I didn't manage to find it again !), Matthew Turk (author of the similar and better packaged GLOYD, that uses simply parametrized lenses directly in QC), and Ute Kraus & Corvin Zahn from Uni Hildesheim, authors of spacetimetravel.org.
Special thanks to Dominique Sluse for providing me the lens model of RXJ1131, and to Chuck Keeton et al. for releasing gravlens, the software used to calculate the deflection map. The above standalone app is built using QuartzBuilder (I first thought I would build something custom, but let's face it, no time for this ...)

How it works

Here is the "source" : QCgravlens_source.tgz (1.5 MB). To play with the QC part, simply open QCgravlens.qtz (you'll need to have the developer tools installed).

The deflection map is precalculated, using gravlens. The plotgrid command saves the mapping between the source and image planes, on a specific polar grid, into a text file. This can of course be done with lens models of arbitrary complexity. Sample input file for gravlens : startup_RXJ1131.in .

Next step is to interpolate this mapping so to generate a pixel to pixel correspondance (cartesian grid) from the image plane to the source plane. This is done in python (see interpdef.py) with matplotlib's griddata (natural neighbor interpolation). The script writes the deflection maps into two png files, xdef.png and ydef.png, as image files are suited to be handled in Quartz Composer. For each pixel location in the image plane, the pixel values in xdef.png and ydef.png give the x and y location of the source pixel to use. As a png channel can contain only 255 different values, the red and green channels are used : x = G*100 + R.

Finally, in Quartz Composer, we load those png deflection maps and read the pixels of the webcam stream accordingly.

Version with time delays

Turns out that this is rather easy to implement ! There are Quartz Composer modules to store the incoming video flux into a buffer, for instance the Video Delay plugin.
Unfortunately this takes a lot more memory... You can nevertheless try it by running QCgravlens_delays.qtz provided in the source tar (install the Video Delay plugin first).

Like for the deflections, a python script generates a map of the delay for each image position in the form of a png file. This is not just the typical "virtual photon" arrival time surface for one given source position, but the superposition of all arrival time surfaces evaluated only at the positions of the actual (and not virtual) image pixels. The calculation is done with many calls of findimg3 in gravlens. Here is how such an unusual map of time delays looks like, for RXJ1131 (red == image close to the center of the lens == high delay, same orientation as all the images shown by QCgravlens) :