• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

/home/pascal/depot/filedata/src/modisfiledata.h

00001 /***************************************************************************
00002  *   Copyright (C) 2005 by Nicolas PASCAL                                  *
00003  *   nicolas.pascal@icare.univ-lille1.fr                                   *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 #ifndef MODISFILEDATA_H
00021 #define MODISFILEDATA_H
00022 
00023 #include "hdffiledata.h"
00024 #include "satellitefiledata.h"
00025 #include "pixel.h"
00026 #include "geometry.h"
00027 
00032 typedef struct ModisCloudMask_1{
00033         unsigned int cloud_mask  : 1;
00034         unsigned int FOV_quality : 2;
00035         unsigned int day_night   : 1;
00036         unsigned int sunlight    : 1;
00037         unsigned int snow_ice    : 1;
00038         unsigned int land_water  : 2;
00039     } ModisCloudMask_1;
00045 class MODISFileData : public SatelliteFileData, public HDFFileData {
00046   protected:
00047     typedef vector<double>                    GRingPoint;
00048     typedef vector<GRingPoint>                GRingPolygon;
00049     typedef vector<GRingPolygon>              GRing;
00050 //     typedef P_Pixel_base< float,vector<int> > PixelType;
00051 //     typedef vector<PixelType>::iterator       I_Pixel;
00052 
00054     static const string latitude_sds_name;
00056     static const string longitude_sds_name;
00058     static const int fast_srch_frame_x;
00060     static const int fast_srch_frame_y;
00062     float colocation_tolerance;
00066     enum PlatformType {
00067         UNDEFINED_PLATFORM_TYPE = 0,
00068         TERRA,
00069         AQUA,
00070     };
00072     PlatformType platform;
00073 
00077     enum Product_ID {
00078         UNDEFINED_PRODUCT_ID = 0,
00079         MYD02QKM,
00080         MYD02HKM,
00081         MYD021KM,
00082         MYD03,
00083         MYD02SSH,
00084         MYD04_L2,
00085         MYD05_L2,
00086         MYD06_L2,
00087         MOD06_L2,
00088     };
00090     Product_ID product_id;
00092     string product;
00094     float resolution;
00095 
00097     float lat_min;
00099     float lat_max;
00101     float lon_min;
00103     float lon_max;
00105     vector <int> lat_lon_index_max;
00107     GRing gring;
00109     vector<PixelType> v_pixel;
00111     vector < float32 > lat_gran_corner;
00113     vector < float32 > lon_gran_corner;
00117     void init();
00121     void set_time_coverage();
00126     void parse_filename(const string & file_basename);
00132     bool check_filename(const string & file_basename) const;
00136     void set_lat_lon_index_max();
00141     void set_gring();
00149     const bool is_inside_gring( const float & lat, const float & lon ) const;
00155     virtual string get_gring_latitude_name(const string &product="") {
00156         return "GRINGPOINTLATITUDE";
00157     };
00163     virtual string get_gring_longitude_name(const string &product="") {
00164         return "GRINGPOINTLONGITUDE";
00165     };
00169     virtual void load_v_pixel() ;
00170 
00174     void init_colocation_tolerance ();
00175 
00176 public:
00178     static const int NB_MAX_X_10KM;
00180     static const int NB_MAX_Y_10KM;
00182     static const int NB_MAX_X_5KM;
00184     static const int NB_MAX_Y_5KM;
00186     static const int NB_MAX_X_1KM;
00188     static const int NB_MAX_Y_1KM;
00190     static const int NB_MAX_X_250M;
00192     static const int NB_MAX_Y_250M;
00193 
00198     const int get_x_size_10km() {
00199         switch ( product_id ) {
00200             case ( MYD04_L2 ) :
00201                 return ( lat_lon_index_max[1] + 1 );
00202                 break;
00203             default : // TODO set it for all products
00204                 string msg ( "Unimplemented method for product "  + product ) ;
00205                 g_exception e( __FILE__ , __LINE__ , msg );
00206                 throw e;
00207                 break;
00208         }
00209         return - 1;
00210     }
00215     const int get_y_size_10km() {
00216         switch ( product_id ) {
00217             case ( MYD04_L2 ) :
00218                 return ( lat_lon_index_max[0] + 1 );
00219                 break;
00220             default : // TODO set it for all products
00221                 string msg ( "Unimplemented method for product "  + product ) ;
00222                 g_exception e( __FILE__ , __LINE__ , msg );
00223                 throw e;
00224                 break;
00225         }
00226         return - 1;
00227     }
00228 
00233     const int get_x_size_5km() {
00234         switch ( product_id ) {
00235             case ( MYD06_L2 ) :
00236             case ( MOD06_L2 ) :
00237             case ( MYD05_L2 ) :
00238             case ( MYD021KM ) :
00239                 return ( lat_lon_index_max[1] + 1 );
00240                 break;
00241             default : // TODO set it for all products
00242                 string msg ( "Unimplemented method for product "  + product ) ;
00243                 g_exception e( __FILE__ , __LINE__ , msg );
00244                 throw e;
00245                 break;
00246         }
00247         return - 1;
00248     }
00253     const int get_y_size_5km() {
00254         switch ( product_id ) {
00255             case ( MYD06_L2 ) :
00256             case ( MOD06_L2 ) :
00257             case ( MYD05_L2 ) :
00258             case ( MYD021KM ) :
00259                 return ( lat_lon_index_max[0] + 1 );
00260                 break;
00261             default : // TODO set it for all products
00262                 string msg ( "Unimplemented method for product "  + product ) ;
00263                 g_exception e( __FILE__ , __LINE__ , msg );
00264                 throw e;
00265                 break;
00266         }
00267         return - 1;
00268     }
00273     const int get_x_size_1km() {
00274         switch ( product_id ) {
00275             case ( MYD06_L2 ) :
00276             case ( MOD06_L2 ) :
00277             case ( MYD05_L2 ) :
00278                 // 270 5km pixels
00279                 return ( get_x_size_5km () * 5 ) + 4;
00280             case ( MYD021KM ) :
00281                 // 271 5km pixels
00282                 return ( get_x_size_5km () * 5 ) - 1;
00283             case ( MYD02QKM ) :
00284             case ( MYD03    ) :
00285                 return ( lat_lon_index_max[1] + 1 );
00286                 break;
00287             default : // TODO set it for all products
00288                 string msg ( "Unimplemented method for product "  + product ) ;
00289                 g_exception e( __FILE__ , __LINE__ , msg );
00290                 throw e;
00291                 break;
00292         }
00293         return - 1;
00294     }
00295 
00300     const int get_y_size_1km() {
00301         switch ( product_id ) {
00302             case ( MYD06_L2 ) :
00303             case ( MOD06_L2 ) :
00304             case ( MYD05_L2 ) :
00305             case ( MYD021KM ) :
00306                 return ( get_y_size_5km () * 5 );
00307             case ( MYD02QKM ) :
00308             case ( MYD03    ) :
00309                 return ( lat_lon_index_max[0] + 1 );
00310                 break;
00311             default : // TODO set it for all products
00312                 string msg ( "Unimplemented method for product "  + product ) ;
00313                 g_exception e( __FILE__ , __LINE__ , msg );
00314                 throw e;
00315                 break;
00316         }
00317         return - 1;
00318     }
00319 
00325     const int get_x_size_250m() {
00326         switch ( product_id ) {
00327             case ( MYD02QKM ) :
00328                 return 4 * get_x_size_1km();
00329                 break;
00330             default : // TODO set it for all products
00331                 string msg ( "Unimplemented method for product "  + product ) ;
00332                 g_exception e( __FILE__ , __LINE__ , msg );
00333                 throw e;
00334                 return - 1;
00335                 break;
00336         }
00337         return -1;
00338     };
00339 
00345     const int get_y_size_250m() {
00346         switch ( product_id ) {
00347             case ( MYD02QKM ) :
00348                 return 4 * get_y_size_1km();
00349                 break;
00350             default : // TODO set it for all products
00351                 string msg ( "At this time, this method is only supported for MYD02QKM products" ) ;
00352                 g_exception e( __FILE__ , __LINE__ , msg );
00353                 throw e;
00354                 break;
00355         }
00356         return -1;
00357     };
00358 
00364     MODISFileData(const string &_name, const string &mode="r");
00368     ~MODISFileData();
00372     void print_gring() const;
00373 
00380     const string get_radix();
00389     const bool get_5_to_1km_index(const float &lat, const float &lon, int * one_km_indexes, const int * five_km_indexes=NULL);
00399     const bool get_1km_to_250m_pixel( const float32 lat, const float32 lon, const int i_pix_1km[2],
00400                                       int i_pix_250m[2]);
00410     const bool get_5km_to_1km_pixel( const float32 lat, const float32 lon, const int i_pix_5km[2],
00411                                       int i_pix_1km[2]);
00420     void get_5_to_1km_area(const int * five_km_idx, int * one_km_min_idx, int * one_km_max_idx);
00427     const int convert_5_to_1km_index(const int &five_km_index, const bool is_x_axis = false) const;
00428 
00434     void convert_1km_to_250m_index( const int  i_pix_1km  [2],
00435                                           float i_pix_250m [2] ) const;
00443     const bool contain_data(const float &lat,const float &lon, const double &time, const double &tolerance=0.1);
00452     const bool contain_location(const float &lat,const float &lon, const double &tolerance=0.1) ;
00458     const vector<int> get_lat_lon_index_max_5km() const {
00459         return lat_lon_index_max;
00460     }
00461 
00467     const vector<int> get_lat_lon_index_max_1km() const {
00468         vector<int> vect;
00469         vect.push_back(convert_5_to_1km_index(lat_lon_index_max[0],false)+2);
00470         vect.push_back(convert_5_to_1km_index(lat_lon_index_max[1],true)+1);
00471         return vect;
00472     }
00473 
00478     string get_product() const {
00479         return product;
00480     }
00485     float get_resolution() const {
00486         return resolution;
00487     }
00492     void load_geolocation_data();
00496     void free_geolocation_data();
00500     virtual void close_data_file() {
00501         free_hdf_file();
00502     };
00506     virtual void open_data_file() {
00507         load_hdf_file();
00508     };
00512     const bool is_geolocation_data_loaded() const;
00523     void get_sds_calibration(const string &sds_name, double & scale, double & offset, const string &scale_name="scale_factor", const string &offset_name="add_offset", const int channel_nb=-1);
00545     template<class Value_T,class Count_T>
00546     Value_T* read_calibrated_data(Value_T* data,const char* sds_name = "Height", int start[]=NULL, int stride[]=NULL, int edges[]=NULL, int rank=-1, Value_T fill_value =Value_T(0), const string &scale_name="scale_factor", const string &offset_name="add_offset", const int channel_nb=-1);
00557     const bool get_index(const float &lat, const float& lon, const double time, int * near_point_idx, float coloc_tolerance=-1.);
00558 
00569     const bool get_index(const float &lat, const float& lon, int & nearest_pix_idx, float coloc_tolerance=-1.);
00578      virtual void get_vindex(vector < vector < int > > &v_index, const float &lat, const float& lon,
00579                                             const float colocation_tolerance ) {
00580         UnimplementedMethod e(__FILE__,__LINE__,__PRETTY_FUNCTION__);
00581         throw e;
00582      };
00591     const float get_nearest_point_distance(const float &lat,const float &lon, float coloc_tolerance=-1.);
00599     virtual void get_pixel_coord ( const vector < int > & ipix, float &lat, float &lon, double &time ) {
00600         UnimplementedMethod e(__FILE__,__LINE__,__PRETTY_FUNCTION__);
00601         throw e;
00602     };
00607     vector< float32 > get_lat_gran_corner() const
00608     {
00609             return lat_gran_corner;
00610     }
00615     vector< float32 > get_lon_gran_corner() const
00616     {
00617             return lon_gran_corner;
00618     }
00619 
00624     vector< int > get_geolocation_dim() const
00625     {
00626         vector < int > v_dim (2);
00627         v_dim [0] = lat_lon_index_max [0] + 1;
00628         v_dim [1] = lat_lon_index_max [1] + 1;
00629         return v_dim;
00630     }
00631 
00640     inline void get_250m_pix_pos (  const int itk_250m, const int isc_250m,
00641                                     float32 & lat, float32 & lon );
00642 
00651     inline void get_1km_pix_pos (  const int itk_1km, const int isc_1km,
00652                                    float & lat, float & lon );
00653 
00666     inline void get_bounds_1km_to_250m ( const int itk_1km, const int isc_1km,
00667                                          int & itk_250m_min, int & itk_250m_max,
00668                                          int & isc_250m_min, int & isc_250m_max
00669                                         );
00670 
00683     inline void get_bounds_5km_to_1km ( const int itk_5km, const int isc_5km,
00684                                          int & itk_1km_min, int & itk_1km_max,
00685                                          int & isc_1km_min, int & isc_1km_max
00686                                         );
00687 
00688 protected:
00689 
00694     void set_lat_lon_min_max();
00695 
00706     inline void get_y_pos_1km_to_250m ( const int isc_1km,
00707                                         const int itk_p1_1km, const int itk_p2_1km,
00708                                         const int itk_250m,
00709                                         double & lat, double & lon );
00710 
00722     inline void get_x_pos_1km_to_250m ( const double lat_left_250m,  const double lon_left_250m,
00723                                         const int isc_left_1km,
00724                                         const double lat_right_250m, const double lon_right_250m,
00725                                         const int isc_right_1km,
00726                                         const int isc_250m,
00727                                         double & lat, double & lon );
00728 
00739     inline void get_y_pos_5km_to_1km (  const int isc_5km,
00740                                         const int itk_p1_5km, const int itk_p2_5km,
00741                                         const int itk_1km,
00742                                         double & lat, double & lon );
00743 
00755     inline void get_x_pos_5km_to_1km (  const double lat_left_1km,  const double lon_left_1km,
00756                                         const int isc_left_5km,
00757                                         const double lat_right_1km, const double lon_right_1km,
00758                                         const int isc_right_5km,
00759                                         const int isc_1km,
00760                                         double & lat, double & lon );
00761 
00762 };
00763 
00764 template<class Value_T,class Count_T>
00765 Value_T * MODISFileData::read_calibrated_data( Value_T * data, const char * sds_name, int start[], int stride[], int edges[], int rank, Value_T fill_value, const string & scale_name, const string & offset_name, const int channel_nb )
00766 {
00767     bool are_limits_initialized[3]; // check if start, stride or edges had been initialized in this method
00768     bool hdf_file_already_loaded = is_hdf_file_loaded();
00769     try {
00770         if (!hdf_file_already_loaded)
00771             load_hdf_file();
00772         // --- initialize NULL input parametres ---
00773         init_read_write_null_input_param(sds_name, start, stride, edges,rank, are_limits_initialized);
00774         // check the selection limits
00775         check_read_write_limits(sds_name, start,stride,edges,rank); // throw bad_index in case of problem
00776         int nb_data = 1;
00777         int i=0;
00778         for (i = 0 ; i<rank ; ++i)
00779             nb_data*=edges[i];
00780         // read the uncalibrated dataS
00781         Count_T* count_data=NULL;
00782         count_data=static_cast<Count_T*>(read_data(count_data,sds_name,start,stride,edges,rank));
00783         // eventually allocate the calibrated data
00784         if (data==NULL) {
00785             // read the size of the sds data
00786             size_t data_type_size = hdf_file->get_sds_sizeof(sds_name);
00787             data = static_cast<Value_T*>(malloc(data_type_size*nb_data));
00788         }
00789         // read the calibration
00790         double cal,offset;
00791         get_sds_calibration(sds_name,cal,offset,scale_name,offset_name,channel_nb);
00792         // read the fill value
00793         Count_T count_fill_value;
00794         get_dataset_fill_value(sds_name,static_cast<void*>(&count_fill_value));
00795         // apply the calibration
00796         for (i=0;i<nb_data;++i) {
00797             if (count_data[i]!=count_fill_value)
00798                 // a valid value
00799                 data[i]=static_cast<Value_T>(cal)*(static_cast<Value_T>(count_data[i])-static_cast<Value_T>(offset));
00800             else
00801                 // set a fill value
00802                 data[i]=fill_value;
00803         }
00804 
00805        // free the ressources allocated by this method
00806         free_read_write_allocations(are_limits_initialized, start, stride, edges);
00807         delete[] count_data;
00808         if (!hdf_file_already_loaded)
00809             free_hdf_file();
00810         return data;
00811 
00812     } catch(exception &e) {
00813         // free the ressources allocated in this method
00814         //             free_read_write_allocations(are_limits_initialized , start, stride,edges);
00815         if (!hdf_file_already_loaded)
00816             free_hdf_file();
00817         cerr<<e.what()<<endl;
00818         throw;
00819     } catch(...) {
00820         // free the ressources allocated in this method
00821         //             free_read_write_allocations(are_limits_initialized , start, stride,edges);
00822         cout<< "Unknown exception in "<<__FILE__<<" line : "<<__LINE__<<endl;
00823         throw;
00824     }
00825 
00826 }
00827 
00828 void MODISFileData::get_y_pos_1km_to_250m ( const int isc_1km,
00829                                             const int itk_p1_1km, const int itk_p2_1km,
00830                                             const int itk_250m,
00831                                             double & lat, double & lon )
00832 {
00833     // make sure P1 and P1 are 2 successive pixels along-track
00834     if ( fabs ( itk_p1_1km - itk_p2_1km ) != 1. )
00835     {
00836         string msg ( "P1 and P2 are on the same cross-track line and must be successive" ) ;
00837         g_exception e( __FILE__ , __LINE__ , msg );
00838         throw e;
00839     }
00840 
00841     // lat, lon of the 1km bounding pixels
00842     int sz_sc_1km = get_x_size_1km();
00843     int i_buf = itk_p1_1km * sz_sc_1km + isc_1km;
00844     float32 p1_1km_lat = lat_data [ i_buf ];
00845     float32 p1_1km_lon = lon_data [ i_buf ];
00846     i_buf = itk_p2_1km * sz_sc_1km + isc_1km;
00847     float32 p2_1km_lat = lat_data [ i_buf ];
00848     float32 p2_1km_lon = lon_data [ i_buf ];
00849 
00850     // check for change date meridian particular case
00851 
00852     // change date meridian case sentinel
00853 //     bool is_crossing_change_date = false;
00854     if ( fabs ( p1_1km_lon - p2_1km_lon ) > 180. )
00855     {
00856         if ( p1_1km_lon < 0. )
00857             p1_1km_lon += 360.;
00858         else if ( p2_1km_lon < 0. )
00859             p2_1km_lon += 360.;
00860 //         is_crossing_change_date = true;
00861     }
00862 
00863     // coordinates of p1, p2 in the 250m grid
00864     double itk_p1_250m = 1.5 + 4. * itk_p1_1km;
00865     double itk_p2_250m = 1.5 + 4. * itk_p2_1km;
00866 
00867 //     printf ( "itk_p1_250m=%f itk_p2_250m=%f\n", itk_p1_250m, itk_p2_250m );
00868 
00869     // linear interpolation on the position
00870     double div = 1. / ( itk_p2_250m - itk_p1_250m ); // for speed
00871     double dtk = ( itk_250m - itk_p1_250m );
00872     double alpha_lon = ( p2_1km_lon - p1_1km_lon ) * div;
00873     double alpha_lat = ( p2_1km_lat - p1_1km_lat ) * div;
00874     lon = p1_1km_lon + alpha_lon * dtk;
00875     lat = p1_1km_lat + alpha_lat * dtk;
00876 
00877     // in case of change date crossing, turn values > 180. to negative
00878 //     if ( is_crossing_change_date and lon > 180. )
00879 //         lon -= 360.;
00880 }
00881 
00882 void MODISFileData::get_x_pos_1km_to_250m ( const double lat_left_250m,  const double lon_left_250m,
00883                                             const int isc_left_1km,
00884                                             const double lat_right_250m, const double lon_right_250m,
00885                                             const int isc_right_1km,
00886                                             const int isc_250m,
00887                                             double & lat, double & lon )
00888 {
00889     // make sure P1 and P1 are 2 successive pixels along-track
00890     if ( fabs ( isc_left_1km - isc_right_1km ) != 1. )
00891     {
00892         string msg ( "The 2 borders are on the same along-track line and must be successive" ) ;
00893         g_exception e( __FILE__ , __LINE__ , msg );
00894         throw e;
00895     }
00896 
00897     // coordinates of left and right border in the 250m grid
00898     int isc_left_250m  = 4 * isc_left_1km;
00899     int isc_right_250m = 4 * isc_right_1km;
00900 
00901     //print "isc_left_1km=%d isc_right_1km=%d"%(isc_left_1km, isc_right_1km)
00902     //print "isc_left_250m=%d isc_right_250m=%d"%(isc_left_250m, isc_right_250m)
00903     //print "isc_250m_min=%d isc_250m_max=%d"%(isc_250m_min,isc_250m_max)
00904 
00905     // linear interpolation on the position
00906     double div = 1. / double ( isc_right_250m - isc_left_250m );
00907     double dsc = isc_250m - isc_left_250m;
00908     double alpha_lon = ( lon_right_250m - lon_left_250m ) * div;
00909     double alpha_lat = ( lat_right_250m - lat_left_250m ) * div;
00910 
00911     lat = lat_left_250m + alpha_lat * dsc;
00912     lon = lon_left_250m + alpha_lon * dsc;
00913 }
00914 
00915 void MODISFileData::get_250m_pix_pos (  const int itk_250m, const int isc_250m,
00916                                         float32 & lat, float32 & lon )
00917 {
00918     if ( product_id != MYD02QKM )
00919     {
00920         string msg ( "At this time, this method is only supported for MYD02QKM products" ) ;
00921         g_exception e( __FILE__ , __LINE__ , msg );
00922         throw e;
00923     }
00924 
00925     // change date meridian case sentinel
00926 //     bool is_crossing_change_date = false;
00927 
00928     // check 250m indexes validity
00929     int sz_tk_250m = get_y_size_250m ();
00930     int sz_sc_250m = get_x_size_250m ();
00931     if ( ( isc_250m < 0 ) or ( isc_250m > ( sz_sc_250m - 1 ) ) )
00932     {
00933         string msg ( "Invalid cross-track index " + MyTools::to_string ( isc_250m ) +
00934                      ". Must in range [0," + MyTools::to_string ( sz_sc_250m - 1 ) ) ;
00935         g_exception e( __FILE__ , __LINE__ , msg );
00936         throw e;
00937     }
00938     if ( ( itk_250m < 0 ) or ( itk_250m > ( sz_tk_250m - 1 ) ) )
00939     {
00940         string msg ( "Invalid along-track index " + MyTools::to_string ( itk_250m ) +
00941                      ". Must in range [0," + MyTools::to_string ( sz_tk_250m - 1 ) ) ;
00942         g_exception e( __FILE__ , __LINE__ , msg );
00943         throw e;
00944     }
00945 
00946     // --- set the bounding 1km pixels to take for interpolation
00947     // set the (track,scan) indexes of the 1km pixel in the 250m grid ( can be a float grid index )
00948     double itk_1km = ( itk_250m - 1.5 ) / 4.;
00949     double isc_1km = isc_250m / 4.;
00950 
00951 //     printf ( "i_250m=[%ld, %ld] -> i_1km=[%.2f, %.2f]", itk_250m, isc_250m, itk_1km, isc_1km );
00952 
00953     // the width of one scan, in number of pixels, at 250m resolution
00954     int w_scan_250m = 40;
00955     // - extra/interpolation 1km pixels along track
00956     double itk_top_1km    = -1.;
00957     double itk_bottom_1km = -1.;
00958     if (   ( itk_250m % w_scan_250m ) <= 1 ) { // extrapolate start of scan
00959         itk_top_1km    = ceil ( itk_1km );
00960         itk_bottom_1km = itk_top_1km + 1.;
00961     } else if ( ( itk_250m % w_scan_250m ) >= 38 ) { // extrapolate end of scan
00962         itk_top_1km    = floor ( itk_1km );
00963         itk_bottom_1km = itk_top_1km - 1.;
00964     } else { // general case : middle of scan
00965         itk_top_1km    = floor ( itk_1km );
00966         itk_bottom_1km = itk_top_1km + 1.;
00967     }
00968 
00969     // - extra/interpolation 1km pixels cross track
00970     double isc_left_1km  = -1.;
00971     double isc_right_1km = -1.;
00972     if ( isc_1km >= 1353. ) { // extrapolate end of scan line
00973         isc_left_1km  = floor ( isc_1km ) - 1.;
00974         isc_right_1km = floor ( isc_1km );
00975     } else { // general case : interpolation
00976         isc_left_1km  = floor ( isc_1km );
00977         isc_right_1km = isc_left_1km + 1.;
00978     }
00979 
00980 //     printf ( "itk_top_1km=%f itk_bottom_1km=%f isc_left_1km=%f isc_right_1km=%f\n", itk_top_1km, itk_bottom_1km, isc_left_1km, isc_right_1km );
00981 
00982     // --- set the 1km track lines position ; left border ---
00983     double lat_left_250m, lon_left_250m;
00984     get_y_pos_1km_to_250m (
00985                 ( int ) ( isc_left_1km ), ( int ) ( itk_top_1km ), ( int ) ( itk_bottom_1km ),
00986                 ( int ) ( itk_250m ),
00987                 lat_left_250m, lon_left_250m );
00988     // --- set the 1km track lines position ; right border ---
00989     double lat_right_250m, lon_right_250m;
00990     get_y_pos_1km_to_250m (
00991                 ( int ) ( isc_right_1km ), ( int ) ( itk_top_1km ), ( int ) ( itk_bottom_1km ),
00992                 ( int ) ( itk_250m ),
00993                 lat_right_250m, lon_right_250m );
00994 
00995 //     printf ( "left_250m=[%f,%f] right_250m=[%f,%f]\n",lat_left_250m, lon_left_250m, lat_right_250m, lon_right_250m);
00996 
00997     // check for change date meridian case
00998     if  ( fabs ( lon_right_250m  - lon_left_250m  ) > 180. ) {
00999 //         is_crossing_change_date = true;
01000         // all negative longitudes will be incremented of 360 before interpolation
01001         if ( lon_left_250m < 0. )
01002             lon_left_250m += 360.;
01003         if ( lon_right_250m < 0. )
01004             lon_right_250m += 360.;
01005     }
01006 
01007     // for each track line position, interpolate along scan to retrieve the 250m geolocation
01008     double dbl_lat, dbl_lon;
01009     get_x_pos_1km_to_250m ( lat_left_250m,  lon_left_250m,  ( int ) ( isc_left_1km ),
01010                             lat_right_250m, lon_right_250m, ( int ) ( isc_right_1km ),
01011                             isc_250m,
01012                             dbl_lat, dbl_lon );
01013 
01014     // in case of change date crossing, turn values > 180. to negative
01015     if ( dbl_lon > 180. )
01016         dbl_lon -= 360.;
01017     if ( dbl_lon < -180. )
01018         dbl_lon += 360.;
01019 
01020     lat = ( float32 ) ( dbl_lat );
01021     lon = ( float32 ) ( dbl_lon );
01022 //     printf ( "geolocation = [%f, %f]\n",lat,lon);
01023 
01024 }
01025 
01026 void MODISFileData::get_bounds_1km_to_250m( const int itk_1km, const int isc_1km,
01027                                             int & itk_250m_min, int & itk_250m_max,
01028                                             int & isc_250m_min, int & isc_250m_max )
01029 {
01030     // set the (track,scan) indexes of the 1km pixel in the 250m grid
01031     float itk_250m = 1.5 + 4 * itk_1km;
01032     int  isc_250m =       4 * isc_1km;
01033 
01034     // the width of one scan, at 1km resolution
01035     int sz_sc_1km = get_x_size_1km();
01036     // set the interpolation quarters characteristics
01037     itk_250m_min    = ( int ) ( itk_250m - 1.5 );
01038     itk_250m_max    = ( int ) ( itk_250m + 1.5 );
01039     if ( isc_1km == 0 ) {
01040         isc_250m_min  = 0;
01041         isc_250m_max  = isc_250m + 2;
01042     } else if ( isc_1km == sz_sc_1km - 1 ) { // end of scan -> extrapolation along scan
01043         isc_250m_min  = isc_250m - 2;
01044         isc_250m_max  = isc_250m + 3;
01045     } else { // general case : 2 interpolations done along scan : [isc-1, isc] then [isc, isc+1]
01046         isc_250m_min  = isc_250m - 2;
01047         isc_250m_max  = isc_250m + 2;
01048     }
01049 }
01050 
01051 void MODISFileData::get_1km_pix_pos (  const int itk_1km, const int isc_1km,
01052                                        float & lat, float & lon )
01053 {
01054     if ( product_id != MYD06_L2 && product_id != MOD06_L2 &&
01055          product_id != MYD05_L2 && product_id != MYD021KM )
01056     {
01057         string msg ( "Method not implemented for products " + product ) ;
01058         g_exception e( __FILE__ , __LINE__ , msg );
01059         throw e;
01060     }
01061 
01062     // check 1km indexes validity
01063     int sz_tk_1km = get_y_size_1km ();
01064     int sz_sc_1km = get_x_size_1km ();
01065     if ( ( isc_1km < 0 ) || ( isc_1km > ( sz_sc_1km - 1 ) ) )
01066     {
01067         string msg ( "Invalid cross-track index " + MyTools::to_string ( isc_1km ) +
01068                      ". Must in range [0," + MyTools::to_string ( sz_sc_1km - 1 ) ) ;
01069         g_exception e( __FILE__ , __LINE__ , msg );
01070         throw e;
01071     }
01072     if ( ( itk_1km < 0 ) || ( itk_1km > ( sz_tk_1km - 1 ) ) )
01073     {
01074         string msg ( "Invalid along-track index " + MyTools::to_string ( itk_1km ) +
01075                      ". Must in range [0," + MyTools::to_string ( sz_tk_1km - 1 ) ) ;
01076         g_exception e( __FILE__ , __LINE__ , msg );
01077         throw e;
01078     }
01079 
01080     // --- set the bounding 5km pixels to take for interpolation
01081     // set the (track,scan) indexes of the 5km pixel in the 1km grid ( can be a float grid index )
01082     double itk_5km = ( itk_1km - 2. ) / 5.;
01083     double isc_5km = ( isc_1km - 2. ) / 5.;
01084 
01085 //     printf ( "i_1km=[%ld, %ld] -> i_5km=[%.2f, %.2f]", itk_1km, isc_1km, itk_5km, isc_5km );
01086 
01087     // the width of one scan, in number of pixels, at 1km resolution
01088     int w_scan_1km = 10;
01089     // - extra/interpolation 5km pixels along track
01090     double itk_top_5km    = -1.;
01091     double itk_bottom_5km = -1.;
01092 
01093     if ( ( itk_1km % w_scan_1km ) <= 2 ) { // extrapolate start of scan
01094         itk_top_5km    = ceil ( itk_5km );
01095         itk_bottom_5km = itk_top_5km + 1;
01096     } else if ( ( itk_1km % w_scan_1km ) >= 7 ) { // extrapolate end of scan
01097         itk_top_5km    = floor ( itk_5km );
01098         itk_bottom_5km = itk_top_5km - 1;
01099     } else { // general case { middle of scan
01100         itk_top_5km    = floor ( itk_5km );
01101         itk_bottom_5km = itk_top_5km + 1;
01102     }
01103     // - extra/interpolation 5km pixels cross track
01104     double isc_left_5km  = -1.;
01105     double isc_right_5km = -1.;
01106     int sz_sc_5km = get_x_size_5km();
01107     if ( isc_1km <= 2 ) { // extrapolate start of scan line
01108         isc_left_5km  = 0;
01109         isc_right_5km = 1;
01110     } else if ( isc_5km >= ( sz_sc_5km - 1 )  ) { // extrapolate end of scan line
01111         isc_left_5km  = sz_sc_5km - 2;
01112         isc_right_5km = sz_sc_5km - 1;
01113     } else { // general case { interpolation
01114         isc_left_5km  = floor ( isc_5km );
01115         isc_right_5km = isc_left_5km + 1;
01116     }
01117 
01118 //     printf ( "itk_top_5km=%f itk_bottom_5km=%f isc_left_5km=%f isc_right_5km=%f\n", itk_top_5km, itk_bottom_5km, isc_left_5km, isc_right_5km );
01119 
01120     // --- set the 5km track lines position ; left border ---
01121     double lat_left_1km, lon_left_1km;
01122     get_y_pos_5km_to_1km (
01123                 ( int ) ( isc_left_5km ), ( int ) ( itk_top_5km ), ( int ) ( itk_bottom_5km ),
01124                 ( int ) ( itk_1km ),
01125                 lat_left_1km, lon_left_1km );
01126     // --- set the 5km track lines position ; right border ---
01127     double lat_right_1km, lon_right_1km;
01128     get_y_pos_5km_to_1km (
01129                 ( int ) ( isc_right_5km ), ( int ) ( itk_top_5km ), ( int ) ( itk_bottom_5km ),
01130                 ( int ) ( itk_1km ),
01131                 lat_right_1km, lon_right_1km );
01132 
01133 //     printf ( "left_1km=[%f,%f] right_1km=[%f,%f]\n",lat_left_1km, lon_left_1km, lat_right_1km, lon_right_1km);
01134 
01135     // check for change date meridian case
01136     if  ( fabs ( lon_right_1km  - lon_left_1km  ) > 180. ) {
01137         // all negative longitudes will be incremented of 360 before interpolation
01138         if ( lon_left_1km < 0. )
01139             lon_left_1km += 360.;
01140         if ( lon_right_1km < 0. )
01141             lon_right_1km += 360.;
01142     }
01143 
01144     // for each track line position, interpolate along scan to retrieve the 1km geolocation
01145     double dbl_lat, dbl_lon;
01146     get_x_pos_5km_to_1km ( lat_left_1km,  lon_left_1km,  ( int ) ( isc_left_5km ),
01147                             lat_right_1km, lon_right_1km, ( int ) ( isc_right_5km ),
01148                             isc_1km,
01149                             dbl_lat, dbl_lon );
01150     lat = ( float ) ( dbl_lat );
01151     lon = ( float ) ( dbl_lon );
01152 
01153     // in case of change date crossing, turn values > 180. to negative
01154     if ( lon > 180. )
01155         lon = lon - 360.;
01156     else if ( lon < -180. )
01157         lon += 360.;
01158 }
01159 
01160 void MODISFileData::get_y_pos_5km_to_1km (  const int isc_5km,
01161                                             const int itk_p1_5km, const int itk_p2_5km,
01162                                             const int itk_1km,
01163                                             double & lat, double & lon )
01164 {
01165     // make sure P1 and P1 are 2 successive pixels along-track
01166     if ( fabs ( itk_p1_5km - itk_p2_5km ) != 1. )
01167     {
01168         string msg ( "P1 and P2 are on the same cross-track line and must be successive" ) ;
01169         g_exception e( __FILE__ , __LINE__ , msg );
01170         throw e;
01171     }
01172 
01173     // lat, lon of the 5km bounding pixels
01174     int sz_sc_5km = get_x_size_5km();
01175     int i_buf = itk_p1_5km * sz_sc_5km + isc_5km;
01176     float32 p1_5km_lat = lat_data [ i_buf ];
01177     float32 p1_5km_lon = lon_data [ i_buf ];
01178     i_buf = itk_p2_5km * sz_sc_5km + isc_5km;
01179     float32 p2_5km_lat = lat_data [ i_buf ];
01180     float32 p2_5km_lon = lon_data [ i_buf ];
01181 
01182     // check for change date meridian particular case
01183 
01184     // change date meridian case sentinel
01185     if ( fabs ( p1_5km_lon - p2_5km_lon ) > 180. )
01186     {
01187         if ( p1_5km_lon < 0. )
01188             p1_5km_lon += 360.;
01189         if ( p2_5km_lon < 0. )
01190             p2_5km_lon += 360.;
01191     }
01192 
01193     // coordinates of p1, p2 in the 1km grid
01194     double itk_p1_1km = 2. + 5. * itk_p1_5km;
01195     double itk_p2_1km = 2. + 5. * itk_p2_5km;
01196 
01197 //     printf ( "itk_p1_1km=%f itk_p2_1km=%f\n", itk_p1_1km, itk_p2_1km );
01198 
01199     // linear interpolation on the position
01200     double div = 1. / ( itk_p2_1km - itk_p1_1km ); // for speed
01201     double dtk = ( itk_1km - itk_p1_1km );
01202     double alpha_lon = ( p2_5km_lon - p1_5km_lon ) * div;
01203     double alpha_lat = ( p2_5km_lat - p1_5km_lat ) * div;
01204     lon = p1_5km_lon + alpha_lon * dtk;
01205     lat = p1_5km_lat + alpha_lat * dtk;
01206 
01207     // in case of change date crossing, turn values > 180. to negative and < 180. to positive
01208     if ( lon > 180. )
01209         lon -= 360.;
01210     else if ( lon < -180. )
01211         lon += 360.;
01212 }
01213 
01214 void MODISFileData::get_x_pos_5km_to_1km (  const double lat_left_1km,  const double lon_left_1km,
01215                                             const int isc_left_5km,
01216                                             const double lat_right_1km, const double lon_right_1km,
01217                                             const int isc_right_5km,
01218                                             const int isc_1km,
01219                                             double & lat, double & lon )
01220 {
01221     // make sure P1 and P1 are 2 successive pixels along-track
01222     if ( fabs ( isc_left_5km - isc_right_5km ) != 1. )
01223     {
01224         string msg ( "The 2 borders are on the same along-track line and must be successive" ) ;
01225         g_exception e( __FILE__ , __LINE__ , msg );
01226         throw e;
01227     }
01228 
01229     // coordinates of left and right border in the 1km grid
01230     int isc_left_1km  = 2 + 5 * isc_left_5km;
01231     int isc_right_1km = 2 + 5 * isc_right_5km;
01232 
01233     //print "isc_left_5km=%d isc_right_5km=%d"%(isc_left_5km, isc_right_5km)
01234     //print "isc_left_1km=%d isc_right_1km=%d"%(isc_left_1km, isc_right_1km)
01235     //print "isc_1km_min=%d isc_1km_max=%d"%(isc_1km_min,isc_1km_max)
01236 
01237     // linear interpolation on the position
01238     double div = 1. / double ( isc_right_1km - isc_left_1km );
01239     double dsc = isc_1km - isc_left_1km;
01240     double alpha_lon = ( lon_right_1km - lon_left_1km ) * div;
01241     double alpha_lat = ( lat_right_1km - lat_left_1km ) * div;
01242 
01243     lat = lat_left_1km + alpha_lat * dsc;
01244     lon = lon_left_1km + alpha_lon * dsc;
01245 }
01246 
01247 void MODISFileData::get_bounds_5km_to_1km(  const int itk_5km, const int isc_5km,
01248                                             int & itk_1km_min, int & itk_1km_max,
01249                                             int & isc_1km_min, int & isc_1km_max )
01250 {
01251     // set the (track,scan) indexes of the 5km pixel in the 1km grid
01252     int itk_1km = 2 + 5 * itk_5km;
01253     int isc_1km = 2 + 5 * isc_5km;
01254 
01255     // the width of one scan, at 5km resolution
01256     int sz_sc_5km = get_x_size_5km();
01257     // set the interpolation quarters characteristics
01258     itk_1km_min    = itk_1km - 2;
01259     itk_1km_max    = itk_1km + 2;
01260 
01261     // general case : 2 interpolations done along scan : [isc-1, isc] then [isc, isc+1]
01262     isc_1km_min  = isc_1km - 2;
01263     isc_1km_max  = isc_1km + 2;
01264     // treat scan borders cases
01265     if ( isc_5km == 0 ) {  // start of scan -> extrapolation along scan
01266         isc_1km_min  = 0;
01267         isc_1km_max  = isc_1km + 2;
01268     } else if ( isc_5km == sz_sc_5km - 1 ) { // end of scan -> extrapolation along scan
01269         if ( product_id == MYD021KM )
01270             // This product have 271 5km pixels along scan, and so the last along scan pixel is composed of 4 1km pixels
01271             isc_1km_max  = isc_1km + 1;
01272         else
01273             // The others products are supposed by default to have 270 5km pixels along scan, and so the last along scan pixel is composed of 9 1km pixels to interpolate. This is the case for MYD06 and MYD05 products
01274             isc_1km_max  = isc_1km + 6;
01275     }
01276 }
01277 
01278 #endif

Generated on Thu Feb 14 2013 17:59:03 for filedata.kdevelop by  doxygen 1.7.1