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.
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; };
size_t *
(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.
void
(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.
void
(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.*/
void
(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 ]
void
(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.
void
(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.
gal_data_t *
(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
.
size_t
(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.
void
(struct gal_tile_two_layer_params *tl
)
¶Free all the allocated arrays within tl
.
GNU Astronomy Utilities 0.23 manual, July 2024.