Some programs might need lots of source files and if there is no fixed convention, navigating them can become very hard for a new inquirer into the code. The following source files exist in every program’s source directory (which is located in bin/progname). For small programs, these files are enough. Larger programs will need more files and developers are encouraged to define any number of new files. It is just important that the following list of files exist and do what is described here. When creating other source files, please choose filenames that are a complete single word: do not abbreviate (abbreviations are cryptic). For a minimal program containing all these files, see The TEMPLATE program.
Each executable has a main
function, which is located in main.c.
Therefore this file is the starting point when reading any program’s source code.
No actual processing functions must be defined in this file, the function(s) in this file are only meant to connect the most high level steps of each program.
Generally, main
will first call the top user interface function to read user input and make all the preparations.
Then it will pass control to the top processing function for that program.
The functions to do both these jobs must be defined in other source files.
All the major parameters which will be used in the program must be stored in a structure which is defined in main.h.
The name of this structure is usually prognameparams
, for example, cropparams
or noisechiselparams
.
So #include "main.h"
will be a staple in all the source codes of the program.
It is also regularly the first (and only) argument of many of the program’s functions which greatly helps in readability.
Keeping all the major parameters of a program in this structure has the major benefit that most functions will only need one argument: a pointer to this structure. This will significantly facilitate the job of the programmer, the inquirer and the computer. All the programs in Gnuastro are designed to be low-level, small and independent parts, so this structure should not get too large.
The main root structure of all programs contains at least one instance of the gal_options_common_params
structure.
This structure will keep the values to all common options in Gnuastro’s programs (see Common options).
This top root structure is conveniently called p
(short for parameters) by all the functions in the programs and the common options parameters within it are called cp
.
With this convention any reader can immediately understand where to look for the definition of one parameter.
For example, you know that p->cp->output
is in the common parameters while p->threshold
is in the program’s parameters.
With this basic root structure, the source code of functions can potentially become full of structure de-reference operators (->
) which can make the code very unreadable.
In order to avoid this, whenever a structure element is used more than a couple of times in a function, a variable of the same type and with the same name (so it can be searched) as the desired structure element should be defined with the value of the root structure inside of it in definition time.
Here is an example:
char *hdu=p->cp.hdu; float threshold=p->threshold;
The options particular to each program are defined in this file.
Each option is defined by a block of parameters in program_options
.
These blocks are all you should modify in this file, leave the bottom group of definitions untouched.
These are fed directly into the GNU C library’s Argp facilities and it is recommended to have a look at that for better understand what is going on, although this is not required here.
Each element of the block defining an option is described under argp_option
in bootstrapped/lib/argp.h
(from Gnuastro’s top source file).
Note that the last few elements of this structure are Gnuastro additions (not documented in the standard Argp manual).
The values to these last elements are defined in lib/gnuastro/type.h
and lib/gnuastro-internal/options.h
(from Gnuastro’s top source directory).
Besides declaring the exported functions of ui.c
, this header also keeps the “key”s to every program-specific option.
The first class of keys for the options that have a short-option version (single letter, see Options).
The character that is defined here is the option’s short option name.
The list of available alphabet characters can be seen in the comments.
Recall that some common options also take some characters, for those, see lib/gnuastro-internal/options.h.
The second group of options are those that do not have a short option alternative.
Only the first in this group needs a value (1000
), the rest will be given a value by C’s enum
definition, so the actual value is irrelevant and must never be used, always use the name.
Everything related to reading the user input arguments and options, checking the configuration files and checking the consistency of the input parameters before the actual processing is run should be done in this file.
Since most functions are the same, with only the internal checks and structure parameters differing.
We recommend going through the ui.c
of The TEMPLATE program, or several other programs for a better understanding.
The most high-level function in ui.c is named ui_read_check_inputs_setup
.
It accepts the raw command-line inputs and a pointer to the root structure for that program (see the explanation for main.h).
This is the function that main
calls.
The basic idea of the functions in this file is that the processing functions should need a minimum number of such checks.
With this convention an inquirer who only wants to understand only one part (mostly the processing part and not user input details and sanity checks) of the code can easily do so in the later files.
It also makes all the errors related to input appear before the processing begins which is more convenient for the user.
The high-level processing functions in each program are in a file named progname.c, for example, crop.c or noisechisel.c.
The function within these files which main
calls is also named after the program, for example:
void crop(struct cropparams *p)
or
void noisechisel(struct noisechiselparams *p)
In this manner, if an inquirer is interested in the processing steps, they can immediately come and check this file for the first processing step without having to go through main.c and ui.c first.
In most situations, any failure in any step of the programs will result in an informative error message and an immediate abort in the program.
So there is usually no need for return values.
Under more complicated situations where a return value might be necessary, void
will be replaced with an int
in the examples above.
This value must be directly returned by main
, so it has to be an int
.
This header file keeps the global variable for the program authors and its BibTeX record for citation. They are used in the outputs of the common options --version and --cite, see Operating mode options.
This shell script is used for implementing auto-completion features when running Gnuastro’s programs within GNU Bash. For more on the concept of shell auto-completion and how it is managed in Gnuastro, see Bash programmable completion.
These files assume a set of common shell functions that have the prefix _gnuastro_autocomplete_
in their name and are defined in bin/complete.bash.in (of the source directory, and under version control) and bin/complete.bash.built (built during the building of Gnuastro in the build directory).
During Gnuastro’s build, all these Bash completion files are merged into one file that is installed and the user can source
them into their Bash startup file, for example, see Quick start.
GNU Astronomy Utilities 0.23 manual, July 2024.