00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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)
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
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
00210 int n_msg;
00212
00214 typedef map < string, t_grib_var_desc > t_var_table;
00215 t_var_table var_table;
00216 public:
00217
00218
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
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
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
00430
00431
00432
00433
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
00497
00498
00499 bool is_int = ((data_flag & 0x4) >> 3) == 1;
00500 if (is_int)
00501 type_id = "int";
00502 else
00503 type_id = "float";
00504
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
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
00521
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
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
00536 GRIB_CHECK(grib_get_double_array(handle, GribFileData::data_id.c_str(), inner_buf, &sz_buf), 0);
00537
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
00547 if (typeid (T) == typeid(double)) {
00548
00549 return inner_buf;
00550 } else {
00551
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