ztv - an astronomical image viewer for Python

I made a thing that scratches an itch of mine for quick-look/analysis of images in Python. It's called ztv. Keep reading below, or check it out on github or pypi. If you've come to Python from IDL and used ATV previously, then you could have some similar itches that ztv can scratch.

ztv is an astronomical image viewer designed to be used from a python command line for display and analysis.

ztv is useful as-is for display and simple analysis of images already loaded in to numpy arrays, as well as FITS files. It can display the most recently acquired image by watching a directory for new FITS files to appear or watching a single FITS file for when it changes. It can also receive new images via an ActiveMQ message stream.

ztv is intended for real-time display and analysis. ztv is not intended to produce publication quality figures.

ztv comes with a number of built-in control panels, for: - selecting input source (FITS file, auto-reload from FITS file, etc) - selecting a frame to subtract (e.g. sky or dark) and a flat field frame to divide by - setting colormap, stretch, and lower/upper limits - doing basic slice plots, statistics, and aperture photometry. Additional panels can be written and added, for e.g. controlling a camera. (One example add-on panel is included that generates faked images in the FITS format.)

If proper FITS header keywords are available, ztv will display the ra/dec of the cursor point.

Examples of usage

To launch:

import ztv
z = ztv.ZTV()

To load an image in a numpy array:

import numpy as np
im = np.random.normal(size=[10, 256, 256])  # create a 3-d image stack

You can now look at your data, manipulate display parameters, etc all using the gui elements. All of these elements are accessible through the tabbed control panels. You can also switch amongst the control panel tabs by cmd-alt-# where # is the number of the panel, starting from 1. Or, by cmd-[ and cmd-] to move left/right amongst the tabs. You can even switch tabs from the command line api, e.g.:


To change cursor mode, press cmd-# where # is the number shown in the pop-up menu that's available by right-clicking in the primary image area:

To manipulate display parameters:

z.minmax(0., 4.)
z.xy_center(100, 100)

To set up a statistics box and see the GUI output (note that output is also returned to your command line as a dict):

z.stats_box(xrange=[80, 100], yrange=[100,120], show_overplot=True)

There's a lot more you can do from the command line if you play with ztv, especially in an exploration-friendly environment like ipython. And, anything you can do from the command line can be done from the GUI.

Download an iconic FITS image from the web and display it:

from urllib import urlopen
from zipfile import ZipFile
from StringIO import StringIO
remote_url = ''
local_filename = '/tmp/hst-eagle-nebula-656nmos.fits'
zip = ZipFile(StringIO(urlopen(remote_url).read()))
zip_filename = zip.filelist[0].filename
open(local_filename, 'w').write(
z.minmax(0, 500)

We can even do a little aperture photometry while we're here:

z.xy_center(624, 524)
z.minmax(0, 1000)
z.aperture_phot(xclick=614, yclick=516, show_overplot=True)

And, of course, you can adjust the window size to suit your needs, either smaller:

or larger:

Example of an Add-on Control Panel

One of the motivating use cases for ztv was real-time quick-look of incoming images and the ability to extend the basic installation, including instrumentat control. An example of this is that ztv will be used to both control and inspect the images from a slit viewing camera on a spectrograph of mine. To demonstrate this extensibility, there's a simple example in ztv_examples/fits_faker_panel/:

from ztv_examples.fits_faker_panel.launch_ztv import launch_ztv
z = launch_ztv()

Our fake example data looks a lot better when we subtract the sky and divide the flat field (someone needs to blow the dust off that fake dewar window...):


Installation and Dependencies

ztv uses several packages, including wxPython, astropy. These should be automatically installed if you install ztv with:

pip install ztv

You can also grab source code from github.


In graduate school in the late 1990's I learned IDL and used Aaron Barth's ATV extensively. I even contributed a little to a now-outdated version of ATV, adding 3-d image stack capability. ATV was and is incredibly useful for quick-looks at image data, analysis, and all the things you want when working with typical astronomical image data.

After graduate school I began migrating toward python and away from IDL. I've written about this choice elsewhere, but some of the basic reasons were to avoid IDL licensing issues and being beholden to one company. (To be fair, how much I pay every year to keep my IDL license current has always been reasonable. It helps that my license has some obscure history to it that makes the maintenance fees moderate. But, at any time they could raise the prices on me massively. And, I wanted to use a language that could effectively be on every machine I touch, from my main laptop to an embedded server.)

In python there are already a multitude of possible image viewers. Many of which are great and can do much of what I needed. (See next section for some links.) But, inevitably as I've played with them I've found they each doesn't scratch my itch in some way. I wanted something that worked exactly the way I wanted, with the right (for me) mix of complexity and simplicity. I need day-to-day image quicklook from the python command-line, e.g. while I'm developing some new image processing algorithm or to check on last night's data. But, I also need to be able to easily adapt my viewer to other situations, including real-time use on a slit-viewing camera, quick-reduction of incoming data, etc.. So, I wrote ztv.

The name ztv is an obvious play off of ATV. And, "z" is my daughter's middle initial.

Other Image Viewers You Should Check Out

(If your favorite isn't on this list, please email to get it added.)


Thank you to Aaron Barth for his original ATV. Thank you to all the numerous people who have put so much effort in to all the packages that make my work not only easier but possible. I especially thank the developers of astropy and its associated packages. e.g. It's an amazing thing to do correct FITS coordinate conversions in one line of code.


Sending iMessages from the command line

I have servers that send me emails when something is awry, but wanted to upgrade to more instantaneous iMessages in some cases. (I often only open my email a few times a day and wish I could reduce that to <=1.)

These servers use a different iCloud account than my personal account. I put the most basic contact info for myself into that iCloud account's contacts (just FirstName LastName and phone number +1-(###)-###-####).

Then the following command line will send me a message:

osascript -e 'tell application "Messages" to send "Howdy there" to buddy "1##########" of (1st service whose service type = iMessage)'

(replace the #'s with your ten digit phone number)

Be sure to use this only for good.


Update to: SSH/SSL & making security non-onerous

For years I've done the following to make ssh/scp straightforward between my computers:

ssh-keygen -t rsa    (on 'new' computer)
copy ~/.ssh/ to a tempfile on the 'old' computer
cat tempfile >> ~/.ssh/authorized_keys

I've implemented a TextExpander snippet to make the second part of this easier (appending from the 'new' computer to the end of authorized_keys on the 'old' computer):

cat ~/.ssh/ | ssh %filltext:name=user:default=hroe%@%filltext:name=hostname:width=40% "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

which I trigger with: scpsshkey and generates something looks like:

cat ~/.ssh/ | ssh username@hostname.blah "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Another little rough edge sanded down.


Dealing with winmail.dat attachments

If you're like me, every now and then you'll receive an email with an attached file named winmail.dat. This Apple support article suggests that these can be ignored. Well, that's sometimes true, but more often than not for me is absolutely not true. I get emails from admin-type people, presumably using Windows, where the body of their email comes through fine and any attached files don't show up. Just that dreaded winmail.dat attachment. Ugh.

Until today I've routed those emails to a gmail account and let google do its magical nuttiness. But, today I stumbled across TNEF's Enough. I installed it, used it once, and immediately went to donate $25 to Josh Jacob. If you've got winmail.dat problems like mine, you'd think it was worth that much (or more) too. (You should donate to him if you find this useful.)

Thank you Josh for making an aspect of my work easier. Seriously, thank you.


Saving email attachments with pre-pended YYYY-MM-DD_ - Take 2

Ok, scratch the solution in that earlier post. (AppleScript with is screwed up and unreliable, especially when dealing with attachments. My old solution had been working for me for a while and then just weirdly stopped working. When I started hunting around on the web, the mystery reversed and the question became "Wait, why had that been working as long as it had?".)

Anyhoot, I still need a way to save email attachments to a chosen folder, while pre-pending the YYYY-MM-DD the email was received.

So, I went ahead and wrote a quick Keyboard Maestro macro. You can set this to trigger any way you want. In my case I have an Alfred 2 keyword trigger that runs a short AppleScript to trigger the Keyboard Maestro macro. Yeah, that sounds a bit crazy, but it works for me and my muscle memory.

Download the Keyboard Maestro macro from github here

And, here it is graphically: