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

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

00001 /***************************************************************************
00002  *   Copyright (C) 2011 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 
00021 #ifndef GRIBFILEDATA_H
00022 #define GRIBFILEDATA_H
00023 
00024 #include <cstdio>
00025 #include <string>
00026 #include <map>
00027 #include "grib_api.h"
00028 
00029 #include "filedatareader.h"
00030 using namespace std;
00031 
00032 #define MAX_KEY_LEN  255
00033 #define MAX_VAL_LEN  1024
00034 
00039 class t_grib_var_desc {
00040 public:
00042     string name;
00044     string long_name;
00046     int param_id;
00048     string type_id;
00050     int sz_x;
00052     int sz_y;
00054     string z_level_type;
00056     double fill_value;
00058     double scale;
00060     double offset;
00062     vector <int> v_msg;
00064     vector <int> v_lvl;
00065 
00079     t_grib_var_desc (const string & name = "", const string & long_name = "", const int param_id = -1, const string & type_id = "",
00080         const int sz_x = -1, const int sz_y = -1, const string & z_level_type = "",
00081         const double fill_value = -DBL_MAX, const double scale = -DBL_MAX, const double offset = -DBL_MAX) :
00082         name (name),
00083         long_name (long_name),
00084         param_id (param_id),
00085         type_id (type_id),
00086         sz_x (sz_x),
00087         sz_y (sz_y),
00088         z_level_type (z_level_type),
00089         fill_value (fill_value),
00090         scale (scale),
00091         offset (offset) {
00092         // check pressure level validity
00093         if (!z_level_type.empty() &&
00094             z_level_type != string("surface") &&
00095             z_level_type != string("isobaricInhPa") &&
00096             z_level_type != string("hybrid") ) {
00097             string msg ( "Invalid Pressure level type " + z_level_type ) ;
00098             g_exception e( __FILE__ , __LINE__ , msg );
00099             throw e;
00100         }
00101         v_msg = vector <int> (0);
00102         v_lvl = vector <int> (0);
00103     };
00107     ~t_grib_var_desc () {
00108         v_msg.clear();
00109         v_lvl.clear();
00110     };
00114     friend std::ostream &operator<< (std::ostream &stream, const t_grib_var_desc &grib_var_desc) {
00115         stream << grib_var_desc.to_string();
00116         return stream;
00117     }
00121     const string to_string (void) const {
00122         string desc ("");
00123         desc += "var name     : " + name + "\n";
00124         desc += "long name    : " + long_name + "\n";
00125         desc += "param ID     : " + MyTools::to_string (param_id) + "\n";
00126         desc += "Data Type    : " + MyTools::to_string (type_id) + "\n";
00127         desc += "grid size    : " + MyTools::to_string (sz_y) + "x" + MyTools::to_string (sz_x) + "\n";
00128         desc += "Z level type : " + z_level_type + "\n";
00129         desc += "Fill value   : " + MyTools::to_string (fill_value) + "\n";
00130         desc += "Scale factor : " + MyTools::to_string (scale) + "\n";
00131         desc += "Scale offset : " + MyTools::to_string (offset) + "\n";
00132         desc += "Msg indices  : ";
00133         for (vector <int>::const_iterator it_msg = v_msg.begin(); it_msg != v_msg.end() ; ++it_msg )
00134             desc += MyTools::to_string (*it_msg) + " ";
00135         desc += "\n";
00136         desc += "Msg levels   : ";
00137         for (vector <int>::const_iterator it_lvl = v_lvl.begin(); it_lvl != v_lvl.end() ; ++it_lvl )
00138             desc += MyTools::to_string (*it_lvl) + " ";
00139         desc += "\n";
00140         return desc;
00141     };
00147     void add_msg (const int i_msg, const int z_lvl) {
00148         v_msg.push_back(i_msg);
00149         v_lvl.push_back(z_lvl);
00150     }
00155     vector <int> get_sz_dims (void) {
00156         vector <int> sz_dims (0);
00157         sz_dims.reserve (3);
00158 
00159         int sz_z = v_lvl.size();
00160         if (sz_z > 1) // 3D var
00161             sz_dims.push_back(sz_z);
00162         sz_dims.push_back(sz_y);
00163         sz_dims.push_back(sz_x);
00164         return sz_dims;
00165     }
00166 };
00167 
00175 class GribFileData : virtual public FileData {
00176 protected:
00177     // --- parameters attributes IDs --- //
00179     static const string var_name_id;
00181     static const string parameter_code_id;
00183     static const string parameter_name_id;
00185     static const string fill_value_id;
00187     static const string scale_factor_id;
00189     static const string add_offset_id;
00191     static const string x_dim_id;
00193     static const string y_dim_id;
00195     static const string level_type_id;
00197     static const string level_id;
00199     static const string data_flag_id;
00201     static const string data_width_id;
00203     static const string data_id;
00204 
00206     FILE * fd;
00208 //     grib_handle * handle;
00210     int n_msg;
00212 //     int icur_msg;
00214     typedef map < string, t_grib_var_desc > t_var_table;
00215     t_var_table var_table;
00216 public:
00217     /*********************
00218     **   CONSTRUCTORS   **
00219     *********************/
00226     GribFileData(const string &name = "", const string &mode = "r", const bool open_file = false);
00231     GribFileData(const GribFileData &fdata);
00235     virtual ~GribFileData();
00240     GribFileData &operator= (const GribFileData &fdata);
00244     void open_data_file();
00248     void close_data_file();
00252     const bool is_file_loaded();
00258     const bool is_existing_dataset (const string & ds_name) {
00259         return (var_table.find(ds_name) != var_table.end());
00260     };
00266     const t_grib_var_desc & get_dataset_desc (const string & ds_name) {
00267         return var_table [ds_name];
00268     };
00276     string get_msg_key (int i_msg, const string & key);
00282     virtual void get_dataset_fill_value(const string &dataset_name, void* fill_value);
00288     vector<int> get_dataset_dimension (const string &dataset_name);
00293     int get_n_dataset() {
00294         return var_table.size();
00295     };
00301     string get_dataset_name (int i_dataset) {
00302         return get_msg_key (i_dataset, GribFileData::var_name_id);
00303     };
00309     string get_dataset_long_name (int i_dataset) {
00310         return get_msg_key (i_dataset, GribFileData::parameter_name_id);
00311     };
00317     string get_dataset_level (int i_dataset) {
00318         return get_msg_key (i_dataset, GribFileData::level_id);
00319     };
00326     void print_msg_keys (int i_msg, unsigned int keys_filter = GRIB_KEYS_ITERATOR_ALL_KEYS);
00334     void get_msg_keys (int i_msg, vector < pair < string, string > > & v_keys,
00335         unsigned int keys_filter = GRIB_KEYS_ITERATOR_ALL_KEYS);
00341     void print_keys(unsigned int keys_filter = GRIB_KEYS_ITERATOR_ALL_KEYS);
00347     int get_dataset_data_type(string dataset_name);
00351     void print_param_table (void);
00352 //     {return this->get_hdf_file()->get_dataset_data_type(dataset_name.c_str());};
00353 
00354 // string get_values_attr_dataset(string dataset_name,string attr_name);
00355 
00356 //     bool has_attr_dataset(string dataset_name,string attr_name);
00357 /*
00358     string get_values_attr(string attr_name);
00359 
00360     string get_file_attr(string attr_name);
00361 
00362     bool has_attr(string attr_name);
00363 
00364     bool has_file_attr(string attr_name);*/
00365     /************************
00366     ** DATA ACCESS METHODS **
00367     ************************/
00368 
00380     void * read_data (void * data, const char * dataset_name, int * start = NULL, int * stride = NULL, int * edges = NULL, int rank = -1);
00381 
00391     template <typename T>
00392     T * get_msg_data (const int i_msg, vector <int> & sz_dim, T * outdata = NULL);
00397     const void print_msg_data (const int i_msg);
00407     void init_selector (const char* ds_name, int *&start, int *&stride, int *&edges, int &rank, bool is_selector_allocated[3]);
00408 
00416     void free_selector(const bool *is_selector_allocated, int *start, int *stride, int *edges);
00427     void check_selector(const char* ds_name, int *start, int *stride, int *edges, const int rank);
00428 
00429 //     void get_fillValue(const string &dataset_name, void *fillValue);
00430 
00431 //     void get_scaling(const string &dataset_name, float64 &scale, float64 &offset) {
00432 //         string key ("parameterName");
00433 //         return get_msg_key (i_dataset, key);
00434 //     };
00435 
00442     void get_scaling(int i_msg, double &scale, double &offset) {
00443         string s_scale = get_msg_key (i_msg, GribFileData::scale_factor_id);
00444         string s_offset = get_msg_key (i_msg, GribFileData::add_offset_id);
00445         scale = MyTools::to_num <double> (s_scale);
00446         offset = MyTools::to_num <double> (s_offset);
00447     };
00452     const int get_n_msg() const {
00453         return n_msg;
00454     };
00455 
00456 private :
00460     void init_n_msg ();
00467     grib_handle * get_handle (int i_msg);
00472     void release_handle (grib_handle *handle);
00476     void init_param_table (void);
00481     static void print_var_desc ( const pair<string, t_grib_var_desc> & var_table_elt) {
00482         cout << "---" << var_table_elt.first << "---" << endl;
00483         cout << var_table_elt.second << endl;
00484     };
00485 
00494     static string parse_type_id (const unsigned int data_flag, const int data_width) {
00495         string type_id ("");
00496         // check if data is stored as float or integers : 3rd bit from right
00497 //         printf ( "flag = %lx width = %ld\n", data_flag, data_width );
00498 //         cout << (data_flag & 0x4) << " " << ((data_flag & 0x4) >> 3) << endl;
00499         bool is_int = ((data_flag & 0x4) >> 3) == 1;
00500         if (is_int)
00501             type_id = "int";
00502         else
00503             type_id = "float";
00504         // add data width
00505         type_id += MyTools::to_string(data_width);
00506         return type_id;
00507     };
00508 
00509 };
00510 
00511 template <typename T>
00512 T * GribFileData::get_msg_data(const int i_msg, vector <int> & sz_dim, T * outdata) {
00513     // --- seek message number i_msg
00514     grib_handle * handle = get_handle (i_msg);
00515     if (handle == NULL) {
00516         string msg = "Fail to seek GRIB message number " + MyTools::to_string<int>(i_msg);
00517         g_exception e( __FILE__ , __LINE__ , msg );
00518         throw e;
00519     }
00520 //     cout << get_dataset_name (i_msg) << " " << get_msg_key (i_msg, "level") << endl;
00521     // --- allocate inner buffer
00522     size_t sz_buf;
00523     GRIB_CHECK (grib_get_size (handle, GribFileData::data_id.c_str(), &sz_buf), 0);
00524     double * inner_buf = NULL;
00525     // if the output data are requested in double and outdata already allocated, a unique buffer can be used for read and returned data. Else a temporary double buffer is needed.
00526     if (outdata != NULL && typeid (T) == typeid(double)) {
00527         inner_buf = outdata;
00528     } else {
00529         inner_buf = new double [sz_buf];
00530         if (inner_buf == NULL) {
00531             g_exception e(__FILE__ , __LINE__ , "Unable to allocate buffer\n");
00532             throw e;
00533         }
00534     }
00535     // --- read data
00536     GRIB_CHECK(grib_get_double_array(handle, GribFileData::data_id.c_str(), inner_buf, &sz_buf), 0);
00537     // --- read output dimensions size
00538     sz_dim.resize (2);
00539     long long_int;
00540     GRIB_CHECK(grib_get_long(handle, GribFileData::x_dim_id.c_str(), &long_int),0);
00541     sz_dim[1] = long_int;
00542     GRIB_CHECK(grib_get_long(handle, GribFileData::y_dim_id.c_str(), &long_int),0);
00543     sz_dim[0] = long_int;
00544     release_handle(handle);
00545 
00546     // --- format returned output buffer
00547     if (typeid (T) == typeid(double)) {
00548         // double typed output is requested : just return the inner buffer
00549         return inner_buf;
00550     } else {
00551         // innner and returned buffer does not have the same type -> allocate returned one and cast data
00552         outdata = new T [sz_buf];
00553         if (outdata == NULL) {
00554             g_exception e(__FILE__ , __LINE__ , "Unable to allocate buffer\n");
00555             throw e;
00556         }
00557         copy (inner_buf, inner_buf + sz_buf, outdata);
00558         free (inner_buf);
00559     }
00560     return outdata;
00561 }
00562 
00563 #endif

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