Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tutorial 10: Drizzle

Goal: make an image with twice the pixels in each direction from dithered frames, with crisper stars than a plain stack, instead of just a bigger copy of the stack. You finish with drizzled.fits (2160 by 3840 pixels from the 1080 by 1920 frames) and a map of how much data reached each pixel.

Data: the sixty IC 5070 Seestar lights in lights/, as raw mosaics, the same as tutorial 4. The Seestar's stars are only about 2.5 pixels wide (an undersampled image), it dithers between frames (the shifts in tutorial 3 run up to about 70 pixels) and its one-shot-colour sensor samples red and blue at every second pixel: the case drizzle is for. Give drizzle the frames themselves, not the stack and not the demosaiced registered/ copies: it drops each raw pixel into its own colour plane without interpolating them, and registers the frames by itself, the way stack does. If you calibrated, give it the calibrated frames of tutorial 2 written without --debayer. How it works, and what the resolution gain is, is in How drizzle works.

What happens. Each input pixel is shrunk to a "drop" --pixfrac of its side, laid onto an output grid --scale times finer (using the registration), and spread over the output pixels it overlaps in proportion to the overlap, weighted by the noise and star width of its frame. A second pass rejects input pixels more than --reject sigma from the first result (cosmic rays, hot pixels, satellite trails) and drizzles again.

Step 1: Drizzle

valerian drizzle lights/ -o drizzled.fits --scale 2 --pixfrac 0.6 \
    --report drizzle-report.txt --weight-map drizzle-weight.fits
read 60 frames in 308.4ms
registering through demosaiced copies of the mosaics
reference candidate frame 47: 59 of 59 other frames register
reference: frame 47 (FWHM 2.16 px)
drizzling 60 frames onto 2160 x 3840 (scale 2, pixfrac 0.6), raw Grbg mosaics dropped without interpolation
second pass: rejecting input pixels more than 4 sigma from the first result
   #  frame                         stars   FWHM  ellip      sky    noise   flux x rms px weight  reject  status
...
60 of 60 frames drizzled to 2160 x 3840 (scale 2, pixfrac 0.6), reference frame 47 (Light_IC 5070_10.0s_LP_20260728-224223.fit), 0.28 % of the input samples rejected, 0.015 % of the output without data, 6.8s
wrote drizzled.fits
wrote drizzle-weight.fits
wrote drizzle-report.txt

(The values of --scale 2 --pixfrac 0.6 are the defaults; they are written out to show the settings.) It took 6.8 s. Reading it:

  • registering through demosaiced copies of the mosaics. Registration needs to find stars, so the frames are demosaiced in memory for that; the drops themselves use the raw pixels. Registration is the same as in tutorials 3 and 4 (reference frame 47).
  • drizzling 60 frames onto 2160 x 3840 (scale 2, pixfrac 0.6), raw Grbg mosaics dropped without interpolation. The output grid is twice the size, and each raw pixel goes to its colour's plane. Grbg is the filter layout (green-red / blue-green) the header gives.
  • second pass: rejecting input pixels more than 4 sigma from the first result. The default --reject 4.
  • The table is the per-frame table of stack with the weights used.
  • 0.28 % of the input samples rejected. Cosmic rays, hot pixels and trails, as in stack.
  • 0.015 % of the output without data. The output pixels no drop reached: one in about 6,700. They are NaN in the file; the weight map shows where they are. 0.015 per cent is a good fill; see the troubleshooting for what to do when it is not.

drizzled.fits is 99.5 MB (2160 by 3840 by 3 planes of 32-bit floats), the weight map is a single plane of the same size, and the report is the table. The weight map's values, from info --stats: median 5.2 and maximum 11.4: the coverage is not uniform because the frames are dithered and weighted.

Step 2: Look at the result

valerian info drizzled.fits --stats:

drizzled.fits
  size: 2160 x 3840 pixels, 3 planes
  plane 0: min -107.7, sky 612.9, noise 31.11, max 69238.7 ADU
  stars: 605 (median FWHM 5.04 px, ellipticity 0.187)

The stars have a median FWHM of 5.04 drizzled pixels, or 2.52 original pixels, against 2.57 pixels in the stack (info stack.fits --stats): 2 per cent sharper at this setting. That is a small gain, because the 10-second frames are limited by the seeing and the optics (the stars are 2.5 pixels wide) more than by the pixels. Where it shows is in close stars: the pair at the top right of the crop below is better separated in the drizzled images than in the stack.

The picture is a 140 by 140 pixel crop of the stack (enlarged twice by repeating its pixels, left), the same patch of the drizzle with --pixfrac 0.6 (middle, 280 by 280 pixels) and with --pixfrac 1.0 (right). All three have the same screen stretch (black point at the sky minus 2.8 sigma, white point at the 99.9th percentile of the stack, the sky at 20 per cent grey). The drizzled image is not colour calibrated and not background corrected here, as the stack was not.

A crop of the stack at twice its size, and of the drizzle with a pixfrac of 0.6 and 1.0

The drizzle with --pixfrac 0.6 has the sharper stars and more grain; with --pixfrac 1.0 they are slightly softer and the picture smoother. That is the trade: a smaller drop is sharper and noisier, because each output pixel is made of fewer drops.

Step 3: What comes next

Drizzle removes the world coordinate system (the grid is different). To colour calibrate the drizzled image, solve it and run photocal, as in tutorials 8 and 9:

valerian solve drizzled.fits -o drizzled-solved.fits
valerian photocal drizzled-solved.fits -o drizzled-calibrated.fits

Background extraction and stretching work on drizzled.fits as on a stack. Open drizzled.fits at full size next to stack.fits to compare: any picture on a web page is reduced.

Options used

All options are in the command line reference.

OptionWhat it doesRange or valuesDefault
<FRAMES>...frames: files or folders (calibrated; raw mosaics are fine)one or morerequired
-o, --output <FILE>the drizzled FITS filea filerequired
--scale <FACTOR>output pixels per input pixel, linear0.25 to 82
--pixfrac <FRACTION>side of a drop as a fraction of an input pixelabove 0, at most 10.6
--reject <SIGMA>reject input pixels this many sigma from the first-pass resultsigmas4
--no-rejectdrizzle every pixel, with no rejection passon or offoff
--weight-map <FILE>also write the weight map (coverage)a filenot written
--report <FILE>also write the per-frame tablea filenot written
--weightsframe weightsequal, noise, fwhm, noise-fwhmnoise-fwhm
--normalisationlevel matchingnone, additive, additive-scalingadditive-scaling
--reference <N>the reference frame (from 0, sorted)frame numberthe sharpest
--modelthe transform to fitsimilarity, affine, homographysimilarity
--threshold <SIGMA>detection threshold in sigmas of the smoothed noisesigmas5
--min-stars <N>leave out frames with fewer starscount20
--max-fwhm-ratio <RATIO>leave out frames whose FWHM is more than this multiple of the reference'srationo limit

(drizzle has no --backend: it runs on the processor. The star-finding options are those of register.)

Measured on the same sixty frames (the times are for the whole command on the shared server):

Command differs byOutputWithout dataRejectedStar FWHM (original pixels)Noise (red)Time
nothing (--scale 2 --pixfrac 0.6)2160 x 38400.015 %0.28 %2.5231.17.1 s
--pixfrac 1.02160 x 38400.000 %0.32 %2.6322.88.9 s
--scale 33240 x 57600.024 %0.23 %2.4535.49.0 s
--no-reject2160 x 38400.015 %0.00 %2.4631.74.3 s

The noise is per output pixel; neighbouring output pixels share drops, so it falls less than in a stack when the pixels are averaged down. The rows show the trade-offs: --pixfrac 1.0 fills every pixel and is smoother (22.8 against 31.1) but 4 per cent softer; --scale 3 is the sharpest and the noisiest, and makes an image of 224 MB; with --no-reject the second pass is skipped, which is faster (4.3 s against 7.1 s) but leaves in the 0.28 per cent of samples that were cosmic rays, hot pixels or trails.

How to tell it worked

  • The summary line says 60 of 60 frames drizzled to 2160 x 3840.
  • of the output without data is small: under 1 per cent, and ideally near 0.
  • of the input samples rejected is under a few per cent.
  • The stars are at least as sharp as in the stack (here 2.52 against 2.57 pixels) and a close pair is split.
  • The weight map is smooth, with no large empty areas inside the field.

Troubleshooting

Large holes: 9.263 % of the output without data. There are too few frames, or too little dither, for a 2x grid. The same command on the first 8 of these frames (valerian drizzle of a folder of 8) gave 8 of 8 frames drizzled to 2160 x 3840 (scale 2, pixfrac 0.6), ... 9.263 % of the output without data and a noise of 51.9 against 31.1. The documentation says: a dither of a pixel or more between frames and a dozen or more of them to fill a 2x grid. With fewer frames use a larger --pixfrac or a smaller --scale: with --scale 1 --pixfrac 1, the 8 frames left 0.233 % without data. Otherwise take more frames, dithered.

valerian: drizzling failed: pixfrac must be above 0 and at most 1 (the drop is that fraction of a pixel). --pixfrac 1.5 was given. Use a value from just above 0 to 1.

valerian: drizzling failed: the drizzle scale must be 0.25 to 8. --scale 0 was given; the range is 0.25 to 8.

valerian: drizzling failed: registration failed: fewer than two frames registered; nothing to stack. One frame, or frames that do not register. Drizzle needs a series of frames of one field.

The result looks noisier than the stack. It has four times as many pixels from the same photons: each output pixel has less signal. Compare the stars, not the noise; or smooth: --pixfrac 1.0 reduces it, a stretch or a gentle denoise after drizzle does the rest. If you only want a clean picture, the plain stack is the better product; use the drizzle when you want resolution.

The colour is soft. Drizzle drops raw mosaics pixel by pixel into their own colour plane. Frames that were demosaiced first (for example the registered/ copies) have the interpolation already in them, which defeats the point. The command's help says to give the calibrated frames from valerian calibrate without --debayer, or the raw frames.

It uses a lot of memory and disk. The output is scale squared times the frame: --scale 3 is nine times the pixels (3240 by 5760 by 3 floats, 224 MB). Use --scale 2 unless you have a reason.

The desktop app

In the desktop app this is the Drizzle chip of step 3, Stack: see the reference.

Where next

You have drizzled the frames. Tutorial 11 is about the graphics card: which of these steps use it, how to check it, and what it gains.