So everyone and their uncle has already written a post about the JWST images from last week. I'm not going to do the "look how amazing these are" thing, because you've seen the Carina Nebula shot by now, you've seen the deep field, you know what SMACS 0723 is even if you can't pronounce it right. What I want to write about instead is what happened when I actually went and grabbed the raw data myself and tried to make my own version of the Cosmic Cliffs picture, because it was a way weirder weekend project than I expected.
Short version: NASA and STScI didn't just release the pretty finished PNGs on July 12th. They also dumped the actual calibrated exposures onto the MAST archive (that's the Mikulski Archive for Space Telescopes, in case you didn't know either), free for anyone to download. So Saturday afternoon, instead of mowing the lawn like I'd told my wife I would, I went digging.
Getting the files
The Carina Nebula NIRCam data is a set of FITS files, one per filter. FITS has been the standard format for this stuff since forever, and if you've never opened one, it's basically a big table of pixel intensity values with a text header bolted on describing the instrument, exposure time, filter name, all that. Not an image file in the JPEG sense at all. There's no color in a FITS file. That was the first thing that tripped me up, honestly, because I sort of assumed I'd download something and it would just look like a picture already. It does not. It looks like static.
Each filter (F090W, F187N, F200W, F335M, F444W, and a couple more) is its own grayscale file, and you build the color image by stacking them, assigning shorter wavelengths to blue-ish channels and longer ones to red-ish channels, then stretching the brightness curve so the faint stuff doesn't disappear. I used Python with astropy to load the FITS data and numpy to do the channel math, then just exported to PNG with matplotlib once I had something that didn't look completely blown out.
The part nobody tells you
Here's my actual opinion on this, and it's a little bit of a downer take: the "color" in these images is a choice, not a fact. Nobody is cheating exactly, the wavelengths really are shorter and longer in the way that gets mapped to blue and red, but the specific stretch, the specific saturation, how much you crank the contrast on those wispy cliff edges — that's a person (or a team at STScI) making an aesthetic decision, the same way you'd pick a filter in Lightroom. My first attempt at stacking the three main filters came out looking like a sunburned orange mess, nothing like the official version, and it took maybe six or seven tries at adjusting the stretch function before I got something I'd actually want to look at. I'm not saying the official images are fake or misleading, I just think it's a little funny how much "raw scientific data straight from space" actually depends on somebody's eye for color grading.
Total download for the six filters I used was a little over 600MB, which surprised me since I was picturing something bigger given how much noise there's been about the size of these exposures. Processing time on my aging desktop (a five year old Ryzen 5, nothing special) was maybe four minutes per attempt once I had the script working, most of which was just matplotlib being matplotlib.
My version isn't as good as NASA's. Obviously. The dust lanes are muddier, the star colors are less distinct, and I definitely have some banding artifacts in the darker regions that a real image processor would know how to fix and I don't. But it's mine, I made it on a Saturday with a cup of coffee going cold next to the keyboard, and there's something genuinely satisfying about turning a folder of grayscale static into a picture of a nebula 7,600 light years away using nothing but a laptop and some free astropy documentation.
If you want to try this yourself, the MAST portal search is clunky but workable, search for the Carina Nebula proposal data, filter by NIRCam, and grab the calibrated (_i2d.fits) files rather than the uncalibrated ones unless you enjoy pain. I'll probably post the actual script sometime this week once I clean it up enough that I'm not embarrassed by it.