GNU Astronomy Utilities



11.2 Makefile functions of Gnuastro

All Gnuastro Make functions start with the ast- prefix (similar to the programs on the command-line, but with a dash). After you have loaded Gnuastro’s shared library for Makefiles within your Makefile, you can call these functions just like any Make function. For instructions on how to load Gnuastro’s Make functions, see Loading the Gnuastro Make functions.

The Make functions in Gnuastro have been recently added (in August 2022), and will be gradually increasing, as we find the need for more specialized functions.

Difference between ‘=’ or ‘:=’ for variable definition When you define a variable with ‘=’, its value is expanded only when used, not when defined. However, when you use ‘:=’, it is immediately expanded when defined. Therefore the location of a ‘:=’ variable in the Makefile matters: if used before its definition, it will be empty! Those defined by ‘=’ can be used even before they are defined! On the other hand, if your variable invokes functions (like foreach or wildcard), it is better to use ‘:=’. Otherwise, each time the value is used, the function will be expanded (possibly may times) and this will reduce the speed of your pipeline. For more, see the The two flavors of variables in the GNU Make manual.

$(ast-version-is STRING)

Returns 1 if the version of the used Gnuastro is equal to STRING, and 0 otherwise. This is useful/critical for obtaining reproducible results on different systems. It can be used in combination with Conditionals in Make to ensure the required version of Gnuastro is going to be used in your workflow.

For example, in the minimal working Makefile below, we are using it to specify if the default (first) target (all) should have any prerequisites (and let the workflow start), or if it should simply print a message (that the required version of Gnuastro isn’t installed) and abort (without any prerequisites).

load /usr/local/lib/libgnuastro_make.so

gnuastro-version = 0.19
ifeq ($(ast-version-is $(gnuastro-version)),1)
all: paper.pdf
else
all:; @echo "Please use Gnuastro $(gnuastro-version)"
endif

result.fits: input.fits
        astnoisechisel $< --output=$@

paper.pdf: result.fits
        pdflatex --halt-on-error paper.tex
$(ast-text-contains STRING, TEXT)

Returns all white-space-separated words in TEXT that contain the STRING, removing any words that do not match. For example, the following minimal Makefile will only print the bAaz Aah word of the list.

load /usr/local/lib/libgnuastro_make.so

list = fooo baar bAaz uggh Aah
all:
     echo $(ast-text-contains Aa, $(list))

This can be thought of as Make’s own filter function, but if it would accept two patterns in a format like this $(filter %Aa%,$(list)) (for the example above). In fact, the first sentence describing this function is taken from the Make manual’s first sentence that describes the filter function! However, unfortunately Make’s filter function only accepts a single %, not two!

$(ast-text-not-contains STRING, TEXT)

Returns all white-space-separated words in TEXT that do not contain the STRING, removing any words that do not match. This is the inverse of the ast-text-contains function. For example, the following minimal Makefile will print fooo baar uggh word of the list.

load /usr/local/lib/libgnuastro_make.so

list = fooo baar bAaz uggh Aah
all:
     echo $(ast-text-not-contains Aa, $(list))
$(ast-fits-with-keyvalue KEYNAME, KEYVALUES, HDU, FITS_FILES)

Will select only the FITS files (from a list of many in FITS_FILES, non-FITS files are ignored), where the KEYNAME keyword has the value(s) given in KEYVALUES. Only the HDU given in the HDU argument will be checked. According to the FITS standard, the keyword name is not case sensitive, but the keyword value is.

For example, if you have many FITS files in the /datasets/images directory, the minimal Makefile below will put those with a value of BAR or BAZ for the FOO keyword in HDU number 1 in the selected Make variable. Notice how there is no comma between BAR and BAZ: you can specify any series of values.

load /usr/local/lib/libgnuastro_make.so

files := $(wildcard /datasets/images/*.fits)
selected := $(ast-fits-with-keyvalue FOO, BAR BAZ, 1, $(files))

all:
	echo "Full:     $(words $(files)) files";
	echo "Selected: $(words $(selected)) files"
$(ast-fits-unique-keyvalues KEYNAME, HDU, FITS_FILES)

Will return the unique values given to the given FITS keyword (KEYNAME) in the given HDU of all the input FITS files (non-FITS files are ignored). For example, after the commands below, the keyvalues variable will contain the unique values given to the FOO keyword in HDU number 1 of all the FITS files in /datasets/images/*.fits.

files := $(wildcard /datasets/images/*.fits)
keyvalues := $(ast-fits-unique-keyvalues FOO, 1, $(files))

This is useful when you do not know the full range of values a-priori. For example, let’s assume that you are looking at a night’s observations with a telescope and the purpose of the FITS image is written in the OBJECT keyword of the image (which we can assume is in HDU number 1). This keyword can have the name of the various science targets (for example, NGC123 and M31) and calibration targets (for example, BIAS and FLAT). The list of science targets is different from project to project, such that in one night, you can observe multiple projects. But the calibration frames have unique names. Knowing the calibration keyword values, you can extract the science keyword values of the night with the command below (feeding the output of this function to Make’s filter-out function).

calib = BIAS FLAT
files := $(wildcard /datasets/images/*.fits)
science := $(filter-out $(calib), \
             $(ast-fits-unique-keyvalues OBJECT, 1, $(files)))

The science variable will now contain the unique science targets that were observed in your selected FITS images. You can use it to group the various exposures together in the next stages to make separate stacks of deep images for each science target (you can select FITS files based on their keyword values using the ast-fits-with-keyvalue function, which is described separately in this section).