/*************************************************************************** * Copyright (C) 2005 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. * ***************************************************************************/ /************************************************************************** * History : * * 1/08/05 : start * **************************************************************************/ #ifndef CALIOPFILEDATA_H #define CALIOPFILEDATA_H #include "hdffiledata.h" // #include "tools.h" #include "file_tools.h" #include #include #include "satellitefiledata.h" /** facility for Feature_CLassification_Flags sds reading. Equivalent to a uint16 type */ struct FeatureClassFlag{ unsigned int type : 3; unsigned int typeQA : 2; unsigned int phase : 2; unsigned int phaseQA : 2; unsigned int subtype : 3; unsigned int subtypeQA : 1; unsigned int horizontal_avg_detection : 3; }; /** Manages the opening, reading and accessing to data of a CALIOP file ( CALIPSO LIDAR ) To see a more detailed documentation about this class, please refer to the HDFFileData class for all inherited methods. You will find some examples on how to do some useful actions (loading an sds array...), in the HDFFileData class documentation. @author Nicolas PASCAL */ class CALIOPFileData : public SatelliteFileData, public HDFFileData { public: /** number of lidar layers of cloud products */ static const int nb_cloud_layer=10; /** number surface elevation data for one profile */ static const int nb_lidar_surface_elevation=8; /** number of lidar layers of aerosol products */ static const int nb_aerosol_layer=8; /** number of vertical bins for L1 products (583) */ static const int nb_vbins=583; /** number of vertical feature masks for L2 VFM products */ static const int nb_vfm_bins=5515; /** number of vsamples per profile for L2 VFM products */ static const int nb_vfm_samples_per_profile=545; /** number of meteo levels (pressure and temperature) in L1 files */ static const int nb_meteo_level=33; /** number of bins in cloud profile products ( CPro ) */ static const int nb_05kmcpro_bins=345; /** Altitudes of each level in the meteo profiles data. To be rigourous, those levels shall be loaded while reading the data (they are available in the VD named "Met_Data_Altitudes" ) but, at the time this comment is written, they are constant */ static const float32 meteo_level_altitude[]; /** altitudes of the bins of the CALIOP L2 VFM profiles in km, from down to up. Each value is the mean altitude of the bin ( ie: ( top_bin_alt - base_bin_alt ) / 2 ) */ static const float32 cal_lid_l2_vfm_altitude[]; /** altitudes of the bins of the CALIOP L2 VFM profiles in km, from up to down */ static const float32 cal_lid_l2_vfm_altitude_ud[]; /** altitudes of the bins in the CAL_LID L2 05kmCPro products */ static const float32 cal_lid_l2_05kmCPro_altitude[]; static const float colocation_tolerance; /** defines the possible types of CALIOP products */ enum ProductType{ CAL_LID_UNDEFINED, CAL_LID_L1, CAL_LID_L2_333mCLay, CAL_LID_L2_01kmCLay, CAL_LID_L2_05kmCLay, CAL_LID_L2_05kmALay, CAL_LID_L2_40kmAPro, CAL_LID_L2_05kmCPro, CAL_LID_L2_VFM }; /** * @brief check if 2 CALIOP files contain data of the same half-orbit. * It compares the end of the files' names. The purpose of this method is to be used as a binary predicate for the STL search algorithms * @param fd1 first CALIOP file * @param fd2 first CALIOP file * @return true if they have the same timestamp */ static inline bool is_same_orbit(const CALIOPFileData* fd1, const CALIOPFileData* fd2) { string fd1_timestamp=(fd1->get_name()).substr((fd1->get_name()).size()-25,21); string fd2_timestamp=(fd2->get_name()).substr((fd2->get_name()).size()-25,21); return fd1_timestamp==fd2_timestamp; } /** * @brief build the pixels viewing directions, as a segment from satellite position to viewed pixel center. All positions are stored in Earth Center Rotating carthesian coordinates. * For directionnal products (L1), a pixel is identified by the 3 indices : [irow, icolum, idirection]. For non directionnal ones, only [irow, icolum] is used */ // virtual void load_viewing_directions (); /** * @brief test if the data requested for computing the viewing directions has been loaded */ virtual bool is_viewing_directions_data_loaded(); /** * @brief load the data requested for computing the viewing directions */ virtual void load_viewing_directions_data (); /** * @brief free the data requested for computing the viewing directions */ virtual void free_viewing_directions_data (); /** * @brief constucts the viewing directions observations for the given profile * @param ipix 1D profile indice * @param v_obs vector of observation(s) */ virtual void get_viewing_directions (const vector & ipix, vector & v_obs); private: /** the level of the product */ int level; /** the type of the product */ ProductType product_type; /** the resolution of the product, in km */ float resolution; /** wether the data in this file have been taken during day (true) or night(false) */ bool day_mode; /** number of LIDAR echos layers of the product data. Different for cloud products(10) and aerosol ones (8) */ int nb_layer; /** the product name */ string product; int lat_lon_index_max[2]; float lat_min,lat_max,lon_min,lon_max; /** [X, Y, Z] position of the satellite data buffer (km) */ float64 * v_pos_data; /** earth pixe l altitude data buffer (km) */ float32 * v_alt_data; // some constant specific to CALIOP string latitude_sds_name; string longitude_sds_name; string time_sds_name; void init(); public: /** Constructor @param _name the name of the file to open @param mode the opening mode. Only 'r' (reading) is supported at this time */ CALIOPFileData(const string &_name = string(""), const string & mode = string("r")); /** Destructor */ ~CALIOPFileData(); /** read the level of the file @return the level */ const int get_level() const { return level; }; void set_lat_lon_index_max(); /** access to the higher usable indexes of the "Latitude" and "Longitude" sds. In other words, it returns the size of those sds arrays, diminuted of 1. Ex : if the sds "Latitude" has a size of (287,3), it will return [286,2] @return an array containing the maximal usable indexes for the geolocation sds */ const int * get_lat_lon_index_max() const { return lat_lon_index_max; } /** wether the file contains day or night data @return true if it is day data */ const bool is_day() const; /** access the number of different shot times of the file. @return the number of shot times */ const int get_nb_geo_points() const ; /** * access to the accessible number of LIDAR echos layers. * @return the accessible number of LIDAR echos layers. */ int get_nb_layer() const { return nb_layer; }; /** * return the fill value defined for the different data type as defined in the CALIPSO specification * @param typecode "float", "int8" ... * @return the fill value for sds having this data type */ template static const T get_calipso_fill_value(const string &typecode); /** * @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 nearest_pix_idx the 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. * @return true if the coincidence has been found */ const bool get_index(const float &lat, const float& lon, int &nearest_pix_idx, const float colocation_tolerance=CALIOPFileData::colocation_tolerance); /** * @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 = CALIOPFileData::colocation_tolerance ) ; /** * @brief compute the distance to (lat,lon) of the nearest point in the data * If @a coloc_tolerance is given, it will compute only the distance of the points that have a distance to ( @a lat, @a lon ) inferior to @a coloc_tolerance * @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=CALIOPFileData::colocation_tolerance); /** * @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=CALIOPFileData::colocation_tolerance); /** * @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=CALIOPFileData::colocation_tolerance) ; /** * @brief read the geolocations data and put it in memory * 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 */ void free_geolocation_data(); /** * @brief check if the geolocation data have been already loaded */ const bool is_geolocation_data_loaded() const; /** * @brief build the lines of sight for all pixels, from satellite position to viewed pixel center. All positions arez gieven in Earth Center Rotating carthesian coordinates */ // virtual void load_lines_of_sight (); /** * @brief free the pixels lines of sight, if set */ // virtual void free_lines_of_sight (); /** * @brief load the list data pixels */ 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 * @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 */ virtual void get_pixel_coord ( const vector < int > & ipix, float &lat, float &lon, double &time ) { if (!is_geolocation_data_loaded()) load_geolocation_data(); lat = lat_data [ ipix[0] ]; lon = lon_data [ ipix[0] ]; time = time_data [ ipix[0] ]; }; /** * @brief accessor to the product horizontal resolution * @return the horizontal resolution */ const float get_resolution() const { return resolution; } virtual string get_product(){ return product; }; /** * @brief accessor to the altitude vector in CALIOP L2 VFM product * @return the CALIOP L2 VFM altitudes abscissa */ static const float32* get_cal_lid_l2_vfm_altitude() { return cal_lid_l2_vfm_altitude; } /** * @brief accessor to the altitude vector in CALIOP L2 05km CPro product * @return the CALIOP L2 05km CPro altitudes abscissa */ static const float32* get_cal_lid_l2_05kmcpro_altitude() { return cal_lid_l2_05kmCPro_altitude; } private: /** @brief Check is a the file is a valid caliop data file ( the analysis is done with a filename parsing, not on the data ) @throw invalid_filename if the filename does not match the file pattern @param short_filename string : the filename without its path */ void check_filename( const string& short_filename ) const; /** Once the filename has been checked (that's a precondition : no verification on it are done in this method), some informations can be extracted of it. @param short_filename string : the filename without its path */ void parse_filename( const string& short_filename ); /** * @brief read the time covered by the data, in secs * compute the difference of the last and first LIDAR profile timestamp */ void set_time_coverage(); protected: /** set the mininimal and maximal values of latitude and longitude */ void set_lat_lon_min_max(); }; template const T CALIOPFileData::get_calipso_fill_value(const string &typecode) { if (typecode=="float64" || typecode=="double" || typecode=="float32" || typecode=="float" || typecode=="int32" || typecode=="long" || typecode=="int16" || typecode=="short" ) return static_cast(-9999); else if (typecode=="int8" ) return static_cast(-99); else { cerr<<"In "<<__FILE__<<" at "<<__LINE__<<" : case of typecode "<