/*************************************************************************** * Copyright (C) 2010 by Nicolas PASCAL * * nicolas.pascal@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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef PMFILEDATA_H #define PMFILEDATA_H #include "hdffiledata.h" #include "pixel.h" #include "satellitefiledata.h" /** @author Nicolas PASCAL @class PMFileData manage the reading of PM ( PARASOL/POLDER-MODIS ) files */ class PMFileData : public SatelliteFileData, public HDFFileData { static const float colocation_tolerance; /***** constants *****/ /** The name of the latitude data field */ static const string latitude_name; /** The name of the longitude data field */ static const string longitude_name; /** number of pixels of the data grid along y */ static const int16 sz_grid_y; /** number of pixels of the data grid along x */ static const int16 sz_grid_x; /***** Product characteristics *****/ /** The name of the CLOUDSAT product */ string product; /** The version of the product : concatenation of the reprocessing and the epoch number (format R**_V** where * is a digit number) */ string version; /** The geolocation data array size */ int lat_lon_index_max [2]; /** The number of the orbit */ int orbit_nb; /** The column shift in POLDER sinusoidal reference grid for each row */ int16 * irow_shift_data; /** ascending node longitude */ float32 node_lon; /** * @brief initialize the attributes during the first read of the file */ void init(); /** * @brief compute the time range covered by this file, depending of the product */ void set_time_coverage(); /** * @brief extract sone informations using the filename * @param short_filename the filename without its path */ void parse_filename ( const string & short_filename ); /** * @brief test if the filename seems to be a valid CLOUDSAT file * @param short_filename the filename without its path */ static bool check_filename(const string & short_filename); /** * @brief read the geolocation data array size (latitude, and longitude) */ void set_lat_lon_index_max(); public: /** * @brief constructor * @param name the filename * @param mode opening mode. only "r" at this time */ PMFileData(const string &name, const string &mode="r"); /** * @brief destructor */ ~PMFileData(); /** * @brief read the geolocation data (latitude, longitude and time) * This method is used to make the search of the indexes of a (lat,lon,time) point faster. */ void load_geolocation_data(); /** * @brief free eventually loaded geolocation data * If the geolocation data are not loaded, doesn't do anything */ void free_geolocation_data(); /** * @brief check if this file has eventually data coincident with (lat,lon) * Actually, it only tests if (lat,lon) is contained in the data's bounding rectangle. * @param lat the latitude of the event * @param lon the longitude of the event * @param tolerance acceptable bias between the nearest point in the data and the given (lat,lon) point * @return true if a point in the data has been found in the colocation frame */ const bool contain_location(const float &lat,const float &lon, const double &tolerance=0.01); /** * @brief check if the file has possible (lat,lon) coincidence * @warning it's an EVENTUAL coincidence. That is not a proof !!! * @param lat latitude * @param lon longitude * @param time time * @param colocation_tolerance the acceptable bias (in km or degrees. Supposed to be in, a plane approximation) between [lat,lon] and the nearest data point. * @return true if can eventually contain a coincidence with the point. * @warning at this time always true. I don't have a good way to do it */ const bool contain_data(const float &lat, const float &lon, const double &time, const double &colocation_tolerance=0.01) ; /** * @brief compute the distance to (lat,lon) of the nearest point in the data * @warning this method does not make sense for a gridded product. This code is here only to implement the interface * @param lat the latitude * @param lon the longitude * @param coloc_tolerance the -/+ maximal tolerance for 2 points considered as colocated * @return the distance to the nearest point, or -1 if no point in the colocalisation frame has been found. */ const float get_nearest_point_distance ( const float &lat, const float &lon, const float coloc_tolerance = PMFileData::colocation_tolerance ) { UnimplementedMethod e(__FILE__,__LINE__,__PRETTY_FUNCTION__); throw e; }; /** * @brief access to the product name * @return the product name */ string get_product () const { return product; } /** * @brief access to the version of the product * @return the version of the product */ string get_version () const { return version; } /** * @brief find the index of the nearest point to (lat,lon) in the data. * If (lat,lon) is not found or out of the colocalisation_frame, returned indexes are [-1,-1] * @param lat the latitude * @param lon the longitude * @param igrid the indexes of the grid cell that contains the measure. {-1,-1} if no coincidence found. * @param colocation_tolerance the acceptable bias (in km or degrees. Supposed to be in, a plane approximation) between [lat,lon] and the nearest data point. Unused here because data are gridded * @return true if the coincidence has been found */ const bool get_index(const float &lat, const float& lon, int igrid [2], const float colocation_tolerance=0.01); /** * @brief find the index of the nearest point to (lat,lon) in the data. The resulting index is linearized : if the dataset has 2 dimensions, this index will be "i_x + sz_x * i_y" * If (lat,lon) is not found or out of the colocalisation_frame, returned indexes are [-1,-1] * @param lat the latitude * @param lon the longitude * @param idata the linearized index of the nearest measure. -1 if no coincidence found. * @param colocation_tolerance the acceptable bias (in km or degrees. Supposed to be in, a plane approximation) between [lat,lon] and the nearest data point. Unused here because data are gridded * @return true if the coincidence has been found */ const bool get_index(const float &lat, const float& lon, int &idata, const float colocation_tolerance=0.01); /** * @brief build the list of indices of pixels that are in colocation tolerance, sorted by increasing distance to (lat,lon) * If (lat,lon) is not found or out of the colocalisation_frame, returns an empty vector * @param lat the latitude * @param lon the longitude * @param colocation_tolerance the acceptable bias (in km or degrees. Supposed to be in, a plane approximation) between [lat,lon] and the nearest data point. * @return the list of indices of pixels */ virtual void get_vindex(vector < vector < int > > &v_index, const float &lat, const float& lon, const float colocation_tolerance=0.01 ) { UnimplementedMethod e(__FILE__,__LINE__,__PRETTY_FUNCTION__); throw e; }; /** * @brief retrieve the number of (lat,lon) pixels in the file * @return the number of (lat,lon) pixels */ const int get_nb_geo_points() { return ( PMFileData::sz_grid_y * PMFileData::sz_grid_x ) ; } /** * @brief load the list data pixels * Unused for this type of product */ virtual void load_v_pixel() {;}; /** * @brief closes the file. */ virtual void close_data_file() { free_hdf_file(); }; /** * @brief opens the file. */ virtual void open_data_file() { load_hdf_file(); }; /** * @brief retrieve the coordinates of a pixel using its index. Actuallty, the data are gridded, so the ( lat, lon ) position returned is the center of the grid cell * @param ipix [IN] index of the pixel * @param lat [OUT] latitude of the pixel * @param lon [OUT] longitude of the pixel * @param time [OUT] timestamp of the pixel. Unused for this product */ virtual void get_pixel_coord ( const vector < int > & ipix, float &lat, float &lon, double &time ) { float lat_minmax [2]; float lon_minmax [2]; int igrid [2]; copy ( ipix.begin(), ipix.end(), igrid ); grid_to_geolocation ( igrid, lat_minmax, lon_minmax ); lat = -9999.; if ( lat_minmax [0] != -9999. && lat_minmax [1] != -9999. ) lat = ( lat_minmax [0] + lat_minmax [1] ) / 2.; lon = -9999.; if ( lon_minmax [0] != -9999. && lon_minmax [1] != -9999. ) lon = ( lon_minmax [0] + lon_minmax [1] ) / 2.; time = -9999.; }; /** * @brief orbit number getter * @return the orbit number */ int get_orbit_nb() const { return orbit_nb; } /** * @brief get the full resolution polder grid indexes corresponding to a point given by its (lat,lon) coordinates * @param lat_lon the geolocation coordinates * @param igrid the indexes in the reference POLDER full resolution grid, in the format [line,col] and starting from 1 */ void geolocation_to_grid ( const float * lat_lon, int * igrid ); /** * @brief get the full resolution polder grid indexes corresponding to a point given by its (lat,lon) coordinates * @param lat latitude * @param lon longitude * @param igrid the indexes in the reference POLDER full resolution grid, in the format [line,col] and starting from 1 */ inline void geolocation_to_grid ( const float &lat, const float &lon, int * igrid ) { float lat_lon [] = { lat, lon }; geolocation_to_grid ( lat_lon, igrid ); }; /** * @brief get the lat,lon extrema for a grid point * if the indexes are out of the grid or not valid, lat_minmax and lon_minmax are set to -1. * @param lat_minmax 2 elements array containing the latitude extrema. Mustn't be NULL * @param lon_minmax 2 elements array containing the longitude extrema. Can be NULL. In this case, only lat_minmax will be computed * @param igrid the indexes in the reference POLDER grid (line,col) and so starts from 1 */ void grid_to_geolocation ( const int* igrid, float* lat_minmax, float* lon_minmax = NULL ); /** * @brief getter of the column shift for each row data * @return the column shift data buffer */ const int16* get_irow_shift_data() const { return irow_shift_data; } /** * @brief getter of the ascending node longitude * @return the ascending node longitude */ float32 get_node_lon() const { return node_lon; } /** * @brief read the ascending node longitude in the file attributes and set it */ void read_node_lon (); /** * @brief check if the geolocation data have been already loaded */ const bool is_geolocation_data_loaded() const { return ( lat_data != NULL && lon_data != NULL ); }; /** * @brief accessor to the height, in pixels, of the data grid * @return the height of the data grid */ static const int16 get_sz_grid_y() { return sz_grid_y; } /** * @brief accessor to the width, in pixels, of the data grid * @return the width of the data grid */ static const int16 get_sz_grid_x() { return sz_grid_x; } }; #endif