/* grid.h */ /* remap Copyright (C) 2006 Fabrice Ducos, fabrice.ducos@icare.univ-lille1.fr This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef GRID_H #define GRID_H #include #include "common.h" typedef enum grid_content_type_ { GRID_CONTENT_DEFAULT = 0, GRID_CONTENT_RADIANCES = 1 } grid_content_type; /** * Grids are the main data structures handled by the software. They should have been designed * as a class instead of a simple struct with functions to handle it, but by lack of time the software * had to be delivered as is. A rewritten code with a grid class instead of a struct should be much * clearer and easier to maintain, but will need a substantial amount of time to reimplement (and of course * redocument !), that is not available today. * * Grids are abstracts for reprojection. Their main purpose is to handle 2-dimensional buffers of geolocated data * (measures along with their latitudes, longitudes and times of acquisition). The reprojection algorithm * remaps a grid of data (from one instrument product) into another one. * For convenience, origin and target of the data (files and datasets) are also maintained in the structure * (although this is not a very clever design, I have to confess, I hope I'll have a chance to change this * if more time is given to this project) * */ typedef struct grid_type_ { char file[STRING_MAXLEN + 1]; ///< field used as the file source or target (for the grid contents) by functions ::load_grid and ::save_grid char input_dataset[STRING_MAXLEN + 1]; ///< input dataset of the grid, in the input file (relevant for source and target grids) char output_dataset[STRING_MAXLEN + 1]; ///< output dataset of the grid, in the output file (relevant for source and target grids), should be equal to input_dataset by default int ichannel; ///< only relevant for 3-dimensional input data (stacks of 2-dimensional planes), e.g. Modis. The first plane is numbered 1. Should be set to 0 when unused. int rank; ///< rank of the grid buffers (should always be 2 for the time being) int nrows; ///< number of rows of the grid buffers (common to all the buffers lat, lon, tim, data, distance_from_ref, time_from_ref) int ncols; ///< number of columns of the grid (common to all the buffers lat, lon tim, data, distance_from_ref, time_from_ref) coord_type *lat; ///< buffer for latitudes (nrows*ncols elements) coord_type *lon; ///< buffer for longitudes (nrows*ncols elements) time_type *tim; ///< buffer for times of acquisition (nrows*ncols elements) data_type *data; ///< buffer for measures, currently in 16-bit unsigned integer counts (nrows*ncols elements) distance_type *distance_from_ref; ///< buffer for distances between pixels in the target (reference) grid and their nearest neighbour in the source grid (nrows*ncols elements) time_type *time_from_ref; ///< buffer for time differences between pixels in the target (reference) grid and their nearest neighbour in the source grid (nrows*ncols elements) float64 slope; ///< calibration scale factor (slope) to apply to a measure count to convert it into a physical value: phys_val = slope*(count - offset) float64 offset; ///< calibration offset factor to apply to a measure count to convert it into a physical value: phys_val = slope*(count - offset) bool is_target; ///< specifies if a grid is a source (is_target == false) or a target (is_target == true) ///< currently not used (intended as a future optimization of the reprojection code, in order to reuse precomputed source rows and cols instead of recomputing them ///< again and again) int *src_irows; ///< buffer to store, for each pixel of the target grid, its nearest neighbour's row in the source grid (nrows*ncols elements); valid only if grid_type::is_target == true; ///< currently not used (intended as a future optimization of the reprojection code, in order to reuse precomputed source rows and cols instead of recomputing them ///< again and again) int *src_icols; ///< buffer to store, for each pixel of the target grid, its nearest neighbour's column in the source grid (nrows*ncols elements); valid only if grid_type::is_target == true; ///< currently not used (intended as a future optimization of the reprojection code, in order to reuse precomputed source rows and cols instead of recomputing them ///< again and again) coord_type first_lat; coord_type first_lon; coord_type last_lat; coord_type last_lon; grid_content_type content; double wavelength; ///< wavelength in microns (meaningful only if content == GRID_CONTENT_RADIANCE, should be 0. for other contents) int32 data_type_code; ///< HDF data type code for the type in the 'data' field (DFNT_CHAR8, DFNT_UCHAR8, ...) } grid_type; /** * the grid constructor * * @param grid the address of a grid structure to initialize. All fields will be allocated (for field pointers) and initialized with the values of the subsequent parameters. * @param nrows the number of rows of the grid (common number of rows of all the buffers in the grid) * @param ncols the number of columns of the grid (common number of columns of all the buffers in the grid) * @param slope the initialization value for the slope field of the grid * @param offset the initialization value for the offset field of the grid * * @see ::reset_grid(grid_type *) * * cautious: create_grid currently does not initialize the grid_type::is_target field (this one had to be added to meet some user's new requirements, * only after the interface of ::create_grid was designed. So for the time being, the grid_type::is_target field must be set directly before ::create_grid * is called, in order to allow ::create_grid to allocate and initialize correctly the grid_type::src_irows and grid_type::src_icols fields. This should be fixed in a * future release (this will imply to break the interface of ::create_grid, in order to pass the initialization value of grid_type::is_target as an argument). */ extern void create_grid(grid_type *grid, int nrows = 0, int ncols = 0, float64 slope = 1., float64 offset = 0.); /** * resets all the fields of a grid. It is essentially called by ::create_grid after allocations of pointers have been done. * * @param grid the pointer to the grid to reset * * @see ::create_grid */ extern void reset_grid(grid_type *grid); /** * the destructor of a grid * * it resets all the scalars fields and deallocates (and nullifies) all the pointer fields of a grid structure * * @param grid a pointer to the grid to destroy * * @see create_grid * @see load_grid */ extern void destroy_grid(grid_type *grid); /** * loads data from the dataset grid_type::input_dataset of the file grid_type::file into a grid. The function calls ::create_grid, so don't do it yourself. * Grids allocated and filled by load_grid must be destroyed by the caller with ::destroy_grid * * @param grid a pointer to the ::grid_type structure to allocate and fill with the file data * * @see create_grid (called by this one) * @see destroy_grid (to call when the grid is not used anymore) */ extern int load_grid(grid_type *grid); /** * saves grid_type::data buffer (with its slope and offset) into the grid_type::output_dataset of the file grid_type::file recorded in the grid structure. * * @param grid a pointer to the grid to save into a file * @param save_delta if true, saves grid_type::distance_from_ref and grid_type::time_from_ref (namely 'delta' buffers) along with the grid_type::data buffer * (this parameter may be controled by a user option, see ::main) */ extern int save_grid(grid_type *grid, bool save_delta); extern int save_latlontime(grid_type *grid); /** * intended to copy src_grid into target_grid (does correct allocation and copies) * this function is not used in the current implementation */ extern void copy_grid(grid_type *target_grid, grid_type *src_grid); /** * intended to copy the footprint of a grid (the footprint includes lightweight data, namely scalar fields, but not buffers) * this function is not used in the current implementation */ extern void copy_grid_footprint(grid_type *target_grid, grid_type *src_grid); /** * intended to compare two grids footprints (the footprint includes lightweight data, namely scalar fields, but not buffers) * this function is not used in the current implementation */ extern bool have_same_grid_footprint(grid_type *grid1, grid_type *grid2); /** * intended to compare two grids coordinates, for optimization purposes (if the geometry has not changed, it is useless * to redo computations to reproject) */ extern bool have_same_grid_coordinates(grid_type *grid1, grid_type *grid2); extern void grid_print(const grid_type *grid); #endif