One very useful application of tiles is to completely cover an input dataset with tiles. Such that you know every pixel/data-element of the input image is covered by only one tile. The constructs in this section allow easy definition of such a tile structure. They will create lists of tiles that are also usable by the general tools discussed in Independent tiles.

As discussed in Tessellation, (mainly raw) astronomical images will mostly require two layers of tessellation, one for amplifier channels which all have the same size and another (smaller tile-size) tessellation over each channel. Hence, in this section we define a general structure to keep the main parameters of this two-layer tessellation and help in benefiting from it.

- Type (C
`struct`

):**gal_tile_two_layer_params**¶ The general structure to keep all the necessary parameters for a two-layer tessellation.

struct gal_tile_two_layer_params { /* Inputs */ size_t *tilesize; /*******************************/ size_t *numchannels; /* These parameters have to be */ float remainderfrac; /* filled manually before */ uint8_t workoverch; /* calling the functions in */ uint8_t checktiles; /* this section. */ uint8_t oneelempertile; /*******************************/ /* Internal parameters. */ size_t ndim; size_t tottiles; size_t tottilesinch; size_t totchannels; size_t *channelsize; size_t *numtiles; size_t *numtilesinch; char *tilecheckname; size_t *permutation; size_t *firsttsize; /* Tile and channel arrays (which are also lists). */ gal_data_t *tiles; gal_data_t *channels; };

- Function:

`size_t *`

**gal_tile_full**`(gal_data_t`

¶`*input`

, size_t`*regular`

, float`remainderfrac`

, gal_data_t`**out`

, size_t`multiple`

, size_t`**firsttsize`

) Cover the full dataset with (mostly) identical tiles and return the number of tiles created along each dimension. The regular tile size (along each dimension) is determined from the

`regular`

array. If`input`

’s size is not an exact multiple of`regular`

for each dimension, then the tiles touching the edges in that dimension will have a different size to fully cover every element of the input (depending on`remainderfrac`

).The output is an array with the same dimensions as

`input`

which contains the number of tiles along each dimension. See Tessellation for a description of its application in Gnuastro’s programs and`remainderfrac`

, just note that this function defines only one layer of tiles.This is a low-level function (independent of the

`gal_tile_two_layer_params`

structure defined above). If you want a two-layer tessellation, directly call`gal_tile_full_two_layers`

that is described below. The input arguments to this function are:`input`

The main dataset (allocated block) which you want to create a tessellation over (only used for its sizes). So

`input`

may be a tile also.`regular`

The size of the regular tiles along each of the input’s dimensions. So it must have the same number of elements as the dimensions of

`input`

(or`input->ndim`

).`remainderfrac`

The significant fraction of the remainder space to see if it should be split into two and put on both sides of a dimension or not. This is thus only relevant

`input`

length along a dimension is not an exact multiple of the regular tile size along that dimension. See Tessellation for a more thorough discussion.`out`

Pointer to the array of data structures that will keep all the tiles (see Arrays of datasets). If

`*out==NULL`

, then the necessary space to keep all the tiles will be allocated. If not, then all the tile information will be filled from the dataset that`*out`

points to, see`multiple`

for more.`multiple`

When

`*out==NULL`

(and thus will be allocated by this function), allocate space for`multiple`

times the number of tiles needed. This can be very useful when you have several more identically sized`inputs`

, and you want all their tiles to be allocated (and thus indexed) together, even though they have different`block`

datasets (that then link to one allocated space). See the definition of channels in Tessellation and`gal_tile_full_two_layers`

below.`firsttsize`

The size of the first tile along every dimension. This is only different from the regular tile size when

`regular`

is not an exact multiple of`input`

’s length along every dimension. This array is allocated internally by this function.

- Function:

`void`

**gal_tile_full_sanity_check**`(char`

¶`*filename`

, char`*hdu`

, gal_data_t`*input`

, struct gal_tile_two_layer_params`*tl`

) Make sure that the input parameters (in

`tl`

, short for two-layer) correspond to the input dataset.`filename`

and`hdu`

are only required for error messages. Also, allocate and fill the`tl->channelsize`

array.

- Function:

`void`

**gal_tile_full_two_layers**`(gal_data_t`

¶`*input`

, struct gal_tile_two_layer_params`*tl`

) Create the two layered tessellation in

`tl`

. The general set of steps you need to take to define the two-layered tessellation over an image can be seen in the example code below.gal_data_t *input; struct gal_tile_two_layer_params tl; char *filename="input.fits", *hdu="1"; /* Set all the inputs shown in the structure definition. */ ... /* Read the input dataset. */ input=gal_fits_img_read(filename, hdu, -1, 1, NULL); /* Do a sanity check and preparations. */ gal_tile_full_sanity_check(filename, hdu, input, &tl); /* Build the two-layer tessellation*/ gal_tile_full_two_layers(input, &tl); /* `tl.tiles' and `tl.channels' are now a lists of tiles.*/

- Function:

`void`

**gal_tile_full_permutation**`(struct gal_tile_two_layer_params`

¶`*tl`

) Make a permutation to allow the conversion of tile location in memory to its location in the full input dataset and put it in

`tl->permutation`

. If a permutation has already been defined for the tessellation, this function will not do anything. If permutation will not be necessary (there is only one channel or one dimension), then this function will not do anything (`tl->permutation`

must have been initialized to`NULL`

).When there is only one channel OR one dimension, the tiles are allocated in memory in the same order that they represent the input data. However, to make channel-independent processing possible in a generic way, the tiles of each channel are allocated contiguously. So, when there is more than one channel AND more than one dimension, the index of the tile does not correspond to its position in the grid covering the input dataset.

The example below may help clarify: assume you have a 6x6 tessellation with two channels in the horizontal and one in the vertical. On the left you can see how the tile IDs correspond to the input dataset. NOTE how ‘03’ is on the second row, not on the first after ‘02’. On the right, you can see how the tiles are stored in memory (and shown if you simply write the array into a FITS file for example).

Corresponding to input In memory ---------------------- -------------- 15 16 17 33 34 35 30 31 32 33 34 35 12 13 14 30 31 32 24 25 26 27 28 29 09 10 11 27 28 29 18 19 20 21 22 23 06 07 08 24 25 26 <-- 12 13 14 15 16 17 03 04 05 21 22 23 06 07 08 09 10 11 00 01 02 18 19 20 00 01 02 03 04 05

As a result, if your values are stored in same order as the tiles, and you want them in over-all memory (for example, to save as a FITS file), you need to permute the values:

gal_permutation_apply(values, tl->permutation);

If you have values over-all and you want them in tile-order, you can apply the inverse permutation:

gal_permutation_apply_inverse(values, tl->permutation);

Recall that this is the definition of permutation in this context:

permute: IN_ALL[ i ] = IN_MEMORY[ perm[i] ] inverse: IN_ALL[ perm[i] ] = IN_MEMORY[ i ]

- Function:

`void`

**gal_permutation_apply_onlydim0**`(gal_data_t`

¶`*input`

, size_t`*permutation`

) Similar to

`gal_permutation_apply`

, but when the dataset is 2-dimensional, permute each row (dimension 1 in C) as one element. In other words, only permute along dimension 0. The`permutation`

array should therefore only have`input->dsize[0]`

elements.

- Function:

`void`

**gal_tile_full_values_write**`(gal_data_t`

¶`*tilevalues`

, struct gal_tile_two_layer_params`*tl`

, int`withblank`

, char`*filename`

, gal_fits_list_key_t`*keys`

, int`freekeys`

) Write one value for each tile into a file. It is important to note that the values in

`tilevalues`

must be ordered in the same manner as the tiles, so`tilevalues->array[i]`

is the value that should be given to`tl->tiles[i]`

. The`tl->permutation`

array must have been initialized before calling this function with`gal_tile_full_permutation`

.If

`withblank`

is non-zero, then block structure of the tiles will be checked and all blank pixels in the block will be blank in the final output file also.

- Function:

`gal_data_t *`

**gal_tile_full_values_smooth**`(gal_data_t`

¶`*tilevalues`

, struct gal_tile_two_layer_params`*tl`

, size_t`width`

, size_t`numthreads`

) Smooth the given values with a flat kernel of the given

`width`

. This cannot be done manually because if`tl->workoverch==0`

, tiles in different channels must not be mixed/smoothed. Also the tiles are contiguous within the channel, not within the image, see the description under`gal_tile_full_permutation`

.

- Function:

`size_t`

**gal_tile_full_id_from_coord**`(struct gal_tile_two_layer_params`

¶`*tl`

, size_t`*coord`

) Return the ID of the tile that corresponds to the coordinates

`coord`

. Having this ID, you can use the`tl->tiles`

array to get to the proper tile or read/write a value into an array that has one value per tile.

- Function:

`void`

**gal_tile_full_free_contents**`(struct gal_tile_two_layer_params`

¶`*tl`

) Free all the allocated arrays within

`tl`

.

GNU Astronomy Utilities 0.22 manual, February 2024.