diff --git a/docs/Users_Guide/appendixA.rst b/docs/Users_Guide/appendixA.rst index 9b47a535bd..6fe28f380f 100644 --- a/docs/Users_Guide/appendixA.rst +++ b/docs/Users_Guide/appendixA.rst @@ -147,9 +147,10 @@ Q. How do I choose a time slice in a NetCDF file? A. When processing NetCDF files, the level information needs to be -specified to tell MET which 2D slice of data to use. There is -currently no way to explicitly define which time slice to use -other than selecting the time index. +specified to tell MET which 2D slice of data to use. The index is selected from +a value when it starts with "@" for vertical level (pressure or height) +and time. The actual time, @YYYYMMDD_HHMM, is allowed instead of selecting +the time index. Let's use plot_data_plane as an example: @@ -160,6 +161,11 @@ Let's use plot_data_plane as an example: obs.ps \ 'name="APCP"; level="(5,*,*)";' + plot_data_plane \ + gtg_obs_forecast.20130730.i00.f00.nc \ + altitude_20000.ps \ + 'name = "edr"; level = "(@20130730_0000,@20000,*,*)";' + Assuming that the first array is the time, this will select the 6-th time slice of the APCP data and plot it since these indices are 0-based. diff --git a/docs/Users_Guide/config_options.rst b/docs/Users_Guide/config_options.rst index e0f573ed9f..5e4ae8fdbe 100644 --- a/docs/Users_Guide/config_options.rst +++ b/docs/Users_Guide/config_options.rst @@ -991,7 +991,8 @@ File-format specific settings for the "field" entry: * (i,...,j,*,*) for a single field, where i,...,j specifies fixed dimension values and *,* specifies the two dimensions for the - gridded field. For example: + gridded field. @ specifies the vertical level value or time value + instead of offset, (i,...,@NNN,*,*). For example: .. code-block:: none @@ -1006,6 +1007,17 @@ File-format specific settings for the "field" entry: } ]; + field = [ + { + name = "QVAPOR"; + level = "(@20220601_1200,@850,*,*)"; + }, + { + name = "TMP_P850_ENS_MEAN"; + level = [ "(*,*)" ]; + } + ]; + * Python (using PYTHON_NUMPY or PYTHON_XARRAY): * The Python interface for MET is described in Appendix F of the MET diff --git a/internal/test_unit/xml/unit_plot_data_plane.xml b/internal/test_unit/xml/unit_plot_data_plane.xml index 02f85765bc..f581160b33 100644 --- a/internal/test_unit/xml/unit_plot_data_plane.xml +++ b/internal/test_unit/xml/unit_plot_data_plane.xml @@ -273,6 +273,20 @@ + + &MET_BIN;/plot_data_plane + \ + &DATA_DIR_MODEL;/nccf/gtg/latlon/gtg_obs_forecast.20130730.i00.f00.nc \ + &OUTPUT_DIR;/plot_data_plane/gtg_obs_forecast.20130730.i00.f00.NCCF_latlon_20000.ps \ + 'name = "edr"; level = "(0,@20000,*,*)";' \ + -title "NCCF Latitude/Longitude Level 0" \ + -v 1 + + + &OUTPUT_DIR;/plot_data_plane/gtg_obs_forecast.20130730.i00.f00.NCCF_latlon_20000.ps + + + &MET_BIN;/plot_data_plane \ @@ -403,7 +417,7 @@ \ &DATA_DIR_MODEL;/easm/pr_day_MPI-ESM-MR_rcp85_r1i1p1_20060101-20091231.nc \ &OUTPUT_DIR;/plot_data_plane/EaSM_CMIP5_pr_day_MPI-ESM-MR_rcp85_r1i1p1_20060101_12_time.ps \ - 'name="pr"; level="(20060102_000000,*,*)";' \ + 'name="pr"; level="(@20060102_000000,*,*)";' \ -v 4 diff --git a/src/basic/vx_util/util_constants.h b/src/basic/vx_util/util_constants.h index d8920d0f9b..2200bded36 100644 --- a/src/basic/vx_util/util_constants.h +++ b/src/basic/vx_util/util_constants.h @@ -119,6 +119,7 @@ static const double const_gop = 9.80616; // from The Ceaseless Wind static const double const_rd = 287.0; // kg/k dry gas constant static const int vx_data2d_star = -12345; +static const int vx_data2d_dim_by_value = -123456; // apply the value instead of offset for slicing //////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_data2d/level_info.cc b/src/libcode/vx_data2d/level_info.cc index 2323475e93..92df64e9db 100644 --- a/src/libcode/vx_data2d/level_info.cc +++ b/src/libcode/vx_data2d/level_info.cc @@ -70,7 +70,6 @@ void LevelInfo::init_from_scratch() { clear(); - return; } /////////////////////////////////////////////////////////////////////////////// @@ -88,9 +87,8 @@ void LevelInfo::assign(const LevelInfo &l) { Upper = l.upper(); Lower = l.lower(); Increment = l.increment(); - time_as_offset = l.is_time_as_offset(); + Is_offset = l.is_offset(); - return; } /////////////////////////////////////////////////////////////////////////////// @@ -106,9 +104,8 @@ void LevelInfo::clear() { Upper = 0.0; Lower = 0.0; Increment = 0.0; - time_as_offset = true; + Is_offset = true; - return; } /////////////////////////////////////////////////////////////////////////////// @@ -125,56 +122,48 @@ void LevelInfo::dump(ostream &out) const { << " Upper = " << Upper << "\n" << " Increment = " << Increment << "\n"; - return; } /////////////////////////////////////////////////////////////////////////////// void LevelInfo::set_type(LevelType lt) { Type = lt; - return; } /////////////////////////////////////////////////////////////////////////////// void LevelInfo::set_type_num(int i) { TypeNum = i; - return; } /////////////////////////////////////////////////////////////////////////////// void LevelInfo::set_req_name(const char *str) { ReqName = str; - return; } /////////////////////////////////////////////////////////////////////////////// void LevelInfo::set_name(const char *str) { Name = str; - return; } /////////////////////////////////////////////////////////////////////////////// void LevelInfo::set_units(const char *str) { Units = str; - return; } /////////////////////////////////////////////////////////////////////////////// void LevelInfo::set_upper(double u) { Upper = u; - return; } /////////////////////////////////////////////////////////////////////////////// void LevelInfo::set_lower(double l) { Lower = l; - return; } /////////////////////////////////////////////////////////////////////////////// @@ -182,21 +171,18 @@ void LevelInfo::set_lower(double l) { void LevelInfo::set_range(double l, double u) { Lower = l; Upper = u; - return; } /////////////////////////////////////////////////////////////////////////////// void LevelInfo::set_increment(double i) { Increment = i; - return; } /////////////////////////////////////////////////////////////////////////////// -void LevelInfo::set_time_as_offset(bool b) { - time_as_offset = b; - return; +void LevelInfo::set_is_offset(bool b) { + Is_offset = b; } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_data2d/level_info.h b/src/libcode/vx_data2d/level_info.h index a9becc61e6..445528017a 100644 --- a/src/libcode/vx_data2d/level_info.h +++ b/src/libcode/vx_data2d/level_info.h @@ -48,7 +48,7 @@ class LevelInfo double Upper; // Upper level limit double Lower; // Lower level limit double Increment; // Increment (time: seconds, 0 for no increment) - bool time_as_offset;// default: true, false: the (time) value instead + bool Is_offset; // default: true, false: the value instead // of the offset at Lower and Upper void init_from_scratch(); @@ -77,7 +77,7 @@ class LevelInfo double upper() const; double lower() const; double increment() const; - bool is_time_as_offset()const; + bool is_offset() const; // // set stuff @@ -92,7 +92,7 @@ class LevelInfo void set_lower(double l); void set_range(double l, double u); void set_increment(double i); - void set_time_as_offset(bool b); + void set_is_offset(bool b); }; @@ -106,7 +106,7 @@ inline ConcatString LevelInfo::units() const { return(Units); } inline double LevelInfo::upper() const { return(Upper); } inline double LevelInfo::lower() const { return(Lower); } inline double LevelInfo::increment()const { return(Increment);} -inline bool LevelInfo::is_time_as_offset()const { return(time_as_offset);} +inline bool LevelInfo::is_offset()const { return(Is_offset);} /////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_data2d_nc_met/met_file.cc b/src/libcode/vx_data2d_nc_met/met_file.cc index 90b9ed48ef..4aab77db9d 100644 --- a/src/libcode/vx_data2d_nc_met/met_file.cc +++ b/src/libcode/vx_data2d_nc_met/met_file.cc @@ -35,12 +35,6 @@ using namespace std; static const char x_dim_name [] = "lon"; static const char y_dim_name [] = "lat"; -static const string valid_time_att_name = "valid_time"; -static const string init_time_att_name = "init_time"; -static const string valid_time_ut_att_name = "valid_time_ut"; -static const string init_time_ut_att_name = "init_time_ut"; -static const string accum_time_att_name = "accum_time_sec"; - static const int max_met_args = 30; //////////////////////////////////////////////////////////////////////// @@ -254,11 +248,11 @@ for (j=0; jget_nc_var_info(vinfo_nc->req_name().c_str(), info); + LongArray dimension = vinfo_nc->dimension(); + int dim_count = dimension.n_elements(); + for (int k=0; kvar, k)); + NcVarInfo *var_info = find_var_info_by_dim_name(PinterpNc->Var, dim_name, + PinterpNc->Nvars); + if (var_info) { + long new_offset = get_index_at_nc_data(var_info->var, + vinfo_nc->dim_value(k), + dim_name, (k == info->t_slot)); + if (new_offset != bad_data_int) dimension[k] = new_offset; + } + } + } + status = PinterpNc->data(vinfo_nc->req_name().c_str(), - vinfo_nc->dimension(), - plane, pressure, info); + dimension, plane, pressure, info); // Check that the times match those requested if(status) { diff --git a/src/libcode/vx_data2d_nc_pinterp/pinterp_file.cc b/src/libcode/vx_data2d_nc_pinterp/pinterp_file.cc index d31e692e1a..c5dbe62a7b 100644 --- a/src/libcode/vx_data2d_nc_pinterp/pinterp_file.cc +++ b/src/libcode/vx_data2d_nc_pinterp/pinterp_file.cc @@ -52,7 +52,7 @@ static const char pressure_var_wrf_interp_name [] = "LEV"; static const char pa_units_str [] = "Pa"; static const char hpa_units_str [] = "hPa"; -static const string init_time_att_name = "START_DATE"; +static const string start_time_att_name = "START_DATE"; static const int max_pinterp_args = 30; @@ -73,7 +73,6 @@ static bool is_bad_data_pinterp(double); static bool is_accumulation(const char *); - //////////////////////////////////////////////////////////////////////// @@ -281,7 +280,7 @@ else { } ConcatString att_value; -get_global_att(Nc, init_time_att_name, att_value); +get_global_att(Nc, start_time_att_name, att_value); InitTime = parse_init_time(att_value.c_str()); @@ -796,61 +795,72 @@ return ( true ); bool PinterpFile::data(const char * var_name, const LongArray & a, DataPlane & plane, - double & pressure, NcVarInfo *&info) const - -{ - -int j, time_index; -bool found = false; - -for (j=0; jvar, a, plane, pressure); // // store the times // -time_index = a[Var[j].t_slot]; + time_index = a[info->t_slot]; -plane.set_init ( InitTime ); -plane.set_valid ( valid_time(time_index) ); -plane.set_lead ( lead_time(time_index) ); + plane.set_init ( InitTime ); + plane.set_valid ( valid_time(time_index) ); + plane.set_lead ( lead_time(time_index) ); // // since Pinterp files only contain WRF-ARW output, it is always a // a runtime accumulation // -if ( is_accumulation(var_name) ) { + if ( is_accumulation(var_name) ) { - plane.set_accum ( lead_time(time_index) ); + plane.set_accum ( lead_time(time_index) ); -} else { + } else { - plane.set_accum ( 0 ); + plane.set_accum ( 0 ); -} + } // // done // -return ( found ); + return ( found ); } +//////////////////////////////////////////////////////////////////////// + +bool PinterpFile::get_nc_var_info(const char *var_name, NcVarInfo *&info) const { + bool found = false; + + if (NULL == info) { + for (int j=0; j " + mlog << Error << "\n" << method_name << "only one dimension can have a range for NetCDF variable \"" << MagicStr << "\".\n\n"; exit(1); } // Store the dimension of the range and limits else { - Dimension.add(range_flag); + add_dimension(range_flag); Level.set_lower(atoi(ptr2)); Level.set_upper(atoi(++ptr3)); @@ -202,7 +218,29 @@ void VarInfoNcPinterp::set_magic(const ConcatString &nstr, const ConcatString &l } // Single level else { - Dimension.add(atoi(ptr2)); + int level = 0; + double level_value = bad_data_double; + if (is_number(ptr2)) { + if (as_offset) level = atoi(ptr2); + else { + level = vx_data2d_dim_by_value; + level_value = atof(ptr2); + } + } + else if (is_datestring(ptr2)) { + unixtime unix_time = timestring_to_unix(ptr2); + level = vx_data2d_dim_by_value; + level_value = unix_time; + as_offset = false; + } + else { + mlog << Error << "\n" << method_name + << "trouble parsing NetCDF dimension value \"" + << ptr2 << "\"!\n\n"; + exit(1); + } + if (as_offset) add_dimension(level, as_offset); + else add_dimension(level, as_offset, level_value); } } diff --git a/src/libcode/vx_data2d_nc_pinterp/var_info_nc_pinterp.h b/src/libcode/vx_data2d_nc_pinterp/var_info_nc_pinterp.h index e169437291..bff8f90389 100644 --- a/src/libcode/vx_data2d_nc_pinterp/var_info_nc_pinterp.h +++ b/src/libcode/vx_data2d_nc_pinterp/var_info_nc_pinterp.h @@ -23,6 +23,10 @@ /////////////////////////////////////////////////////////////////////////////// +typedef CRC_Array BoolArray; + +/////////////////////////////////////////////////////////////////////////////// + // // List of Pinterp precipitation variable names // Taken from the WRF version 3.2 Registry.EM file @@ -184,9 +188,12 @@ class VarInfoNcPinterp : public VarInfo // LongArray Dimension; // Dimension values for extracting 2D field + BoolArray Is_offset; // boolean for Dimension value (true: offset, false: value to be an offset (false for value) + NumArray Dim_value; // Dimension values as float for extracting 2D field void init_from_scratch(); void assign(const VarInfoNcPinterp &); + void clear_dimension(); public: VarInfoNcPinterp(); @@ -202,8 +209,12 @@ class VarInfoNcPinterp : public VarInfo // GrdFileType file_type() const; - const LongArray & dimension() const; - int dimension(int i) const; + const LongArray & dimension() const; + int dimension(int i) const; + const NumArray & dim_value() const; + double dim_value(int i) const; + const BoolArray & is_offset() const; + bool is_offset(int i) const; int n_dimension() const; // @@ -213,7 +224,7 @@ class VarInfoNcPinterp : public VarInfo void set_magic(const ConcatString &, const ConcatString &); void set_dict(Dictionary &); - void add_dimension(int dim); + void add_dimension(int dim, bool as_index=true, double dim_value=bad_data_double); void set_dimension(int i_dim, int dim); // @@ -235,6 +246,10 @@ inline GrdFileType VarInfoNcPinterp::file_type() const { return(FileT inline const LongArray & VarInfoNcPinterp::dimension() const { return(Dimension); } inline int VarInfoNcPinterp::dimension(int i) const { return(Dimension[i]); } inline int VarInfoNcPinterp::n_dimension() const { return(Dimension.n_elements()); } +inline const NumArray & VarInfoNcPinterp::dim_value() const { return(Dim_value); } +inline double VarInfoNcPinterp::dim_value(int i) const { return(Dim_value[i]); } +inline const BoolArray & VarInfoNcPinterp::is_offset() const { return(Is_offset); } +inline bool VarInfoNcPinterp::is_offset(int i) const { return(Is_offset[i]); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_data2d_nccf/data2d_nccf.cc b/src/libcode/vx_data2d_nccf/data2d_nccf.cc index 8a8b2008c3..2a078bf4ed 100644 --- a/src/libcode/vx_data2d_nccf/data2d_nccf.cc +++ b/src/libcode/vx_data2d_nccf/data2d_nccf.cc @@ -76,8 +76,8 @@ MetNcCFDataFile & MetNcCFDataFile::operator=(const MetNcCFDataFile &) { void MetNcCFDataFile::nccf_init_from_scratch() { - _file = (NcCfFile *) 0; - _time_dim_offset = -1; + _file = (NcCfFile *) 0; + _cur_time_index = -1; close(); @@ -175,51 +175,89 @@ bool MetNcCFDataFile::data_plane(VarInfo &vinfo, DataPlane &plane) if (NULL != data_var) vinfo_nc->set_req_name(data_var->name.c_str()); } + int zdim_slot = bad_data_int; int time_dim_slot = bad_data_int; long org_time_offset = bad_data_int; + long org_z_offset = bad_data_int; + NumArray dim_value = vinfo_nc->dim_value(); LongArray dimension = vinfo_nc->dimension(); - long time_cnt = (long)_file->ValidTime.n_elements(); - long time_threshold_cnt = (time_cnt + 1000) * 1000; - + BoolArray is_offset = vinfo_nc->is_offset(); + data_var = _file->find_var_name(vinfo_nc->req_name().c_str()); if (NULL != data_var) { time_dim_slot = data_var->t_slot; - if (0 <= time_dim_slot) { - org_time_offset = dimension[time_dim_slot]; - long time_offset = org_time_offset; - bool time_as_value = !vinfo_nc->level().is_time_as_offset(); - if (time_as_value || (time_offset == range_flag) || (time_offset == vx_data2d_star)) { - if (0 <= _time_dim_offset) time_offset = _time_dim_offset; - if (time_as_value && time_offset > time_threshold_cnt) // convert the unixtime to offset + for (int idx=0; idxValidTime.n(); + long time_threshold_cnt = 10000000; + org_time_offset = dim_offset; + long time_offset = org_time_offset; + if (time_offset == range_flag) time_offset = _cur_time_index; // from data_plane_array() + else if (!is_offset[idx]) { + long time_value = dim_value[idx]; + time_offset = convert_time_to_offset(time_value); + if ((0 > time_offset) || (time_offset >= time_cnt)) { + if (time_value > time_threshold_cnt) // from time string (yyyymmdd_hh) + mlog << Warning << "\n" << method_name << "the requested time " + << unix_to_yyyymmdd_hhmmss(time_value) << " for \"" + << vinfo.req_name() << "\" variable does not exist (" + << unix_to_yyyymmdd_hhmmss(_file->ValidTime[0]) << " and " + << unix_to_yyyymmdd_hhmmss(_file->ValidTime[time_cnt-1]) << ").\n\n"; + else + mlog << Warning << "\n" << method_name << "the requested time value " + << time_value << " for \"" << vinfo.req_name() << "\" variable " + << "is out of range (between 0 and " << (time_cnt-1) << ").\n\n"; + + return false; + } + } + else if ((0 > time_offset) || (time_offset >= time_cnt)) { time_offset = convert_time_to_offset(time_offset); - } - - if ((0 <= time_offset) && (time_offset < time_cnt)) + } + if ((0 > time_offset) || (time_offset >= time_cnt)) { + mlog << Error << "\n" << method_name << "the requested time offset " + << time_offset << " for \"" << vinfo.req_name() << "\" variable " + << "is out of range (between 0 and " << (time_cnt-1) << ").\n\n"; + return false; + } dimension[time_dim_slot] = time_offset; + } else { - bool do_stop = true; - if (time_offset > time_threshold_cnt) // is from time string (yyyymmdd_hh) - mlog << Warning << "\n" << method_name << "the requested time " - << unix_to_yyyymmdd_hhmmss(time_offset) << " for \"" - << vinfo.req_name() << "\" variable does not exist (" - << unix_to_yyyymmdd_hhmmss(_file->ValidTime[0]) << " and " - << unix_to_yyyymmdd_hhmmss(_file->ValidTime[time_cnt-1]) << ").\n\n"; - else if (org_time_offset == bad_data_int) - mlog << Warning << "\n" << method_name << "the requested offset for \"" - << vinfo.req_name() << "\" variable " - << "is out of range (between 0 and " << (time_cnt-1) << ").\n\n"; - else if (org_time_offset == vx_data2d_star) { - do_stop = false; - dimension[time_dim_slot] = 0; - mlog << Warning << "\n" << method_name << "returns the first available time for \"" - << vinfo.req_name() << "\" variable.\n\n"; + long z_cnt = (long)_file->vlevels.n(); + if (z_cnt > 0) { + + zdim_slot = idx; + org_z_offset = dim_offset; + long z_offset = dim_offset; + string z_dim_name; + if (0 <= data_var->z_slot) { + NcDim z_dim = get_nc_dim(data_var->var, data_var->z_slot); + if (IS_VALID_NC(z_dim)) z_dim_name = GET_NC_NAME(z_dim); + } + if (!is_offset[idx]) { + // convert the value to index for slicing + z_offset = convert_value_to_offset(dim_value[idx], z_dim_name); + } + else if ((dim_offset < 0 || dim_offset >= z_cnt)) { + // convert the value to index for slicing + z_offset = convert_value_to_offset(dim_offset, z_dim_name); + } + if ((z_offset >= 0) && (z_offset < z_cnt)) + dimension[idx] = long(z_offset); + else { + if (is_offset[idx]) + mlog << Error << "\n" << method_name << "the requested vertical offset " + << dim_offset << " for \"" << vinfo.req_name() << "\" variable " + << "is out of range (between 0 and " << (z_cnt-1) << ").\n\n"; + else + mlog << Error << "\n" << method_name << "the requested vertical value " + << dim_value[idx] << " for \"" << vinfo.req_name() << "\" variable " + << "does not exist (data size = " << z_cnt << ").\n\n"; + return false; + } } - else - mlog << Warning << "\n" << method_name << "the requested offset " - << org_time_offset << " for \"" << vinfo.req_name() << "\" variable " - << "is out of range (between 0 and " << (time_cnt-1) << ").\n\n"; - - if (do_stop) return false; } } } @@ -233,6 +271,8 @@ bool MetNcCFDataFile::data_plane(VarInfo &vinfo, DataPlane &plane) if (org_time_offset != bad_data_int && 0 <= time_dim_slot) dimension[time_dim_slot] = org_time_offset; + if (org_z_offset != bad_data_int && 0 <= zdim_slot) + dimension[zdim_slot] = org_z_offset; // Check that the times match those requested @@ -311,28 +351,27 @@ int MetNcCFDataFile::data_plane_array(VarInfo &vinfo, NcVarInfo *data_var = find_first_data_var(); if (NULL != data_var) vinfo_nc->set_req_name(data_var->name.c_str()); } - - LongArray time_offsets = collect_time_offsets(vinfo); + + LongArray time_offsets = collect_time_offsets(vinfo); if (0 < time_offsets.n_elements()) { LevelInfo level = vinfo.level(); VarInfoNcCF *vinfo_nc = (VarInfoNcCF *)&vinfo; - LongArray dimension = vinfo_nc->dimension(); long time_lower = bad_data_int; long time_upper = bad_data_int; if (level.type() == LevelType_Time) { time_lower = level.lower(); time_upper = level.upper(); } - - int debug_level = 7; + for (int idx=0; idx= debug_level) { for (int idx=0; idx< time_offsets.n_elements(); idx++ ) { mlog << Debug(debug_level) << method_name << "time: " @@ -368,10 +407,10 @@ LongArray MetNcCFDataFile::collect_time_offsets(VarInfo &vinfo) { int time_dim_slot = info->t_slot; int time_dim_size = _file->ValidTime.n_elements(); if (0 < time_dim_size && time_dim_slot < 0) { - // The time dimension does not exist at the variable and the time - // variable exists. Stop time slicing and set the time offset to 0. - time_offsets.add(0); - return(time_offsets); + // The time dimension does not exist at the variable and the time + // variable exists. Stop time slicing and set the time offset to 0. + time_offsets.add(0); + return(time_offsets); } double time_lower = bad_data_double; @@ -380,7 +419,7 @@ LongArray MetNcCFDataFile::collect_time_offsets(VarInfo &vinfo) { LevelInfo level = vinfo.level(); LongArray dimension = vinfo_nc->dimension(); bool is_time_range = (level.type() == LevelType_Time); - bool time_as_value = !level.is_time_as_offset(); + bool time_as_value = !level.is_offset(); long dim_offset = (time_dim_slot >= 0) ? dimension[time_dim_slot] : -1; bool include_all_times = (dim_offset == vx_data2d_star); @@ -444,8 +483,7 @@ LongArray MetNcCFDataFile::collect_time_offsets(VarInfo &vinfo) { if (_file->ValidTime[idx] == next_time) { time_offsets.add(idx); mlog << Debug(9) << method_name << " found the time " - << (is_time_range ? - unix_to_yyyymmdd_hhmmss(_file->ValidTime[idx]) : idx) << "\n"; + << unix_to_yyyymmdd_hhmmss(_file->ValidTime[idx]) << "\n"; next_time += time_inc; } } @@ -571,18 +609,72 @@ int MetNcCFDataFile::index(VarInfo &vinfo){ //////////////////////////////////////////////////////////////////////// long MetNcCFDataFile::convert_time_to_offset(long time_value) { + bool found = false; + bool found_value = false; long time_offset = time_value; - int dim_size = _file->ValidTime.n_elements(); - long time_threshold_cnt = (dim_size + 1000) * 1000; - if (time_value >= time_threshold_cnt) { + int dim_size = _file->ValidTime.n(); + static const string method_name + = "MetNcCFDataFile::convert_time_to_offset() -> "; + + for (int idx=0; idxValidTime[idx] == time_value) { + time_offset = idx; + found = true; + break; + } + } + + if (!found) { + dim_size = _file->raw_times.n(); for (int idx=0; idxValidTime[idx] == time_value) { + if (_file->raw_times[idx] == time_value) { time_offset = idx; + found_value = true; break; } } } + + if (found) + mlog << Debug(7) << method_name << " Found " + << unix_to_yyyymmdd_hhmmss(time_value) + << " at index " << time_offset << " from time value\n"; + else if (found_value) + mlog << Debug(7) << method_name << " Found " << time_value + << " at index " << time_offset << " from time value\n"; + else + mlog << Warning << "\n" << method_name << time_value + << " does not exist at time variable\n\n"; + return time_offset; } //////////////////////////////////////////////////////////////////////// + +long MetNcCFDataFile::convert_value_to_offset(double z_value, string z_dim_name) { + bool found = false; + long z_offset = (long)z_value; + int dim_size = _file->vlevels.n(); + static const string method_name + = "MetNcCFDataFile::convert_value_to_offset() -> "; + + for (int idx=0; idxvlevels[idx], z_value)) { + found = true; + z_offset = idx; + break; + } + } + + if (!found && 0 < z_dim_name.length()) { + NcVarInfo *var_info = find_var_info_by_dim_name(_file->Var, z_dim_name, _file->Nvars); + if (var_info) { + long new_offset = get_index_at_nc_data(var_info->var, z_value, z_dim_name); + if (new_offset != bad_data_int) z_offset = new_offset; + } + } + + return z_offset; +} + +//////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_data2d_nccf/data2d_nccf.h b/src/libcode/vx_data2d_nccf/data2d_nccf.h index dbe5ed8073..4abc64d934 100644 --- a/src/libcode/vx_data2d_nccf/data2d_nccf.h +++ b/src/libcode/vx_data2d_nccf/data2d_nccf.h @@ -36,7 +36,8 @@ class MetNcCFDataFile : public Met2dDataFile { void nccf_init_from_scratch(); NcVarInfo *find_first_data_var(); - long convert_time_to_offset(long time_dim_value); + long convert_time_to_offset(long time_value); + long convert_value_to_offset(double z_value, string z_dim_name); LongArray collect_time_offsets(VarInfo &vinfo); MetNcCFDataFile(const MetNcCFDataFile &); @@ -47,7 +48,7 @@ class MetNcCFDataFile : public Met2dDataFile { // NcCfFile * _file; // allocated - long _time_dim_offset; // current time offset to get the data plane + long _cur_time_index; // current time index to get the data plane (for array of data_plane) public: diff --git a/src/libcode/vx_data2d_nccf/nccf_file.cc b/src/libcode/vx_data2d_nccf/nccf_file.cc index 20ac4be91e..5235b1639d 100644 --- a/src/libcode/vx_data2d_nccf/nccf_file.cc +++ b/src/libcode/vx_data2d_nccf/nccf_file.cc @@ -150,6 +150,8 @@ void NcCfFile::close() // Reset the time values ValidTime.clear(); + raw_times.clear(); + vlevels.clear(); InitTime = (unixtime)0; AccumTime = (unixtime)0; @@ -183,7 +185,6 @@ bool NcCfFile::open(const char * filepath) // NcError err(NcError::silent_nonfatal); // Open the file - _ncFile = open_ncfile(filepath); if (IS_INVALID_NC_P(_ncFile)) @@ -206,15 +207,16 @@ bool NcCfFile::open(const char * filepath) // Pull out the variables + int max_dim_count = 0; + NcVar *z_var = (NcVar *)0; NcVar *valid_time_var = (NcVar *)0; ConcatString att_value; - StringArray varNames; Nvars = get_var_names(_ncFile, &varNames); Var = new NcVarInfo [Nvars]; - //get_vars_info(Nc, &Var); + NcDim dim; for (int j=0; j max_dim_count) max_dim_count = dim_count; Var[j].Dims = new NcDim * [dim_count]; // parse the variable attributes - get_att_str( Var[j], (string)"long_name", Var[j].long_name_att ); - get_att_str( Var[j], (string)"units", Var[j].units_att ); + get_att_str( Var[j], long_name_att_name, Var[j].long_name_att ); + get_att_str( Var[j], units_att_name, Var[j].units_att ); - if (get_nc_att_value(Var[j].var, (string)"axis", att_value)) { + if (get_var_axis(Var[j].var, att_value)) { if ( "T" == att_value || "time" == att_value ) { valid_time_var = Var[j].var; _time_var_info = &Var[j]; } + else if ( "Z" == att_value || "z" == att_value ) { + z_var = Var[j].var; + } } - if (get_nc_att_value(Var[j].var, (string)"standard_name", att_value)) { + + if (get_var_standard_name(Var[j].var, att_value)) { if ( "time" == att_value ) { valid_time_var = Var[j].var; _time_var_info = &Var[j]; } else if( "latitude" == att_value ) _latVar = Var[j].var; else if( "longitude" == att_value ) _lonVar = Var[j].var; + else if( ("air_pressure" == att_value || "height" == att_value) + && (0 == z_var) ) z_var = Var[j].var; } if ( Var[j].name == "time" && (valid_time_var == 0)) { valid_time_var = Var[j].var; @@ -297,30 +306,25 @@ bool NcCfFile::open(const char * filepath) // Parse the units for the time variable. ut = sec_per_unit = 0; - NcVarAtt *units_att = get_nc_att(valid_time_var, (string)"units", false); - if (IS_VALID_NC_P(units_att)) - { - if (!get_att_value_chars(units_att, units) || units.length() == 0) - { + if (get_var_units(valid_time_var, units)) { + if (units.length() == 0) { mlog << Warning << "\n" << method_name << "the \"time\" variable must contain a \"units\" attribute. " << "Using valid time of 0\n\n"; } - else - { + else { mlog << Debug(4) << method_name << "parsing units for the time variable \"" << units << "\"\n"; parse_cf_time_string(units.c_str(), ut, sec_per_unit); } } - if (units_att) delete units_att; NcVar bounds_time_var; NcVar *nc_time_var = (NcVar *)0; bool use_bounds_var = false; ConcatString bounds_var_name; nc_time_var = valid_time_var; - NcVarAtt *bounds_att = get_nc_att(valid_time_var, (string)"bounds", false); + NcVarAtt *bounds_att = get_nc_att(valid_time_var, bounds_att_name, false); if (get_att_value_chars(bounds_att, bounds_var_name)) { bounds_time_var = get_nc_var(_ncFile, bounds_var_name.c_str()); use_bounds_var = IS_VALID_NC(bounds_time_var); @@ -346,6 +350,7 @@ bool NcCfFile::open(const char * filepath) if( latest_time < time_values[i] ) latest_time = time_values[i]; } ValidTime.add(add_to_unixtime(ut, sec_per_unit, latest_time, no_leap_year)); + raw_times.add(latest_time); } else { if (use_bounds_var) { @@ -353,6 +358,7 @@ bool NcCfFile::open(const char * filepath) double time_fraction; for(int i=0; iunits_att.c_str())) { + Var[j].t_slot = k; + t_dims.add(dim_name); + } + else if (is_nc_unit_latitude(info->units_att.c_str())) { + Var[j].y_slot = k; + } + else if (is_nc_unit_longitude(info->units_att.c_str())) { + Var[j].x_slot = k; + } + else { + Var[j].z_slot = k; + z_dims.add(dim_name); + if (0 == z_dim_name.length()) z_dim_name = dim_name; + } + } + } } } // for j + // Find the vertical level variable from dimension name if not found + if (IS_INVALID_NC_P(z_var) && (0 < z_dim_name.length())) { + NcVarInfo *info = find_var_by_dim_name(z_dim_name.c_str()); + if (info) z_var = info->var; + } + + // Pull out the vertical levels + if (IS_VALID_NC_P(z_var)) { + + int z_count = (int) get_data_size(z_var); + double *z_values = new double[z_count]; + + if( get_nc_data(z_var, z_values) ) { + for(int i=0; igetSize(), _xDim->getSize()); status = true; } @@ -1289,7 +1351,7 @@ void NcCfFile::get_grid_from_grid_mapping(const NcVarAtt *grid_mapping_att) } } /* endfor - i */ - if (grid_mapping_var == 0 || IS_INVALID_NC_P(grid_mapping_var)) + if ((grid_mapping_var == 0) || (IS_INVALID_NC_P(grid_mapping_var))) { mlog << Error << "\n" << method_name << " -> " << "Cannot extract grid mapping variable (" << mapping_name @@ -1299,7 +1361,7 @@ void NcCfFile::get_grid_from_grid_mapping(const NcVarAtt *grid_mapping_att) // Get the name of the grid mapping - NcVarAtt *grid_mapping_name_att = get_nc_att(grid_mapping_var, (string)"grid_mapping_name"); + NcVarAtt *grid_mapping_name_att = get_nc_att(grid_mapping_var, grid_mapping_name_att_name); if (IS_INVALID_NC_P(grid_mapping_name_att)) { @@ -1568,18 +1630,14 @@ void NcCfFile::get_grid_mapping_lambert_conformal_conic(const NcVar *grid_mappin // files that are in other units, we'll have to update the code to do the // units conversions. - const NcVarAtt *x_coord_units_att = get_nc_att(_xCoordVar, (string)"units"); - if (IS_INVALID_NC_P(x_coord_units_att)) - { + ConcatString x_coord_units_name; + if (!get_var_units(_xCoordVar, x_coord_units_name)) { mlog << Warning << "\n" << method_name << " -> " << "Units not given for X coordinate variable -- assuming meters.\n\n"; } - else - { + else { //const char *x_coord_units_name = x_coord_units_att->getValues(att->as_string(0); - ConcatString x_coord_units_name; - if (!get_att_value_chars(x_coord_units_att, x_coord_units_name)) - { + if (0 == x_coord_units_name.length()) { mlog << Warning << "\n" << method_name << " -> " << "Cannot extract X coordinate units from netCDF file -- " << "assuming meters.\n\n"; @@ -1595,20 +1653,14 @@ void NcCfFile::get_grid_mapping_lambert_conformal_conic(const NcVar *grid_mappin } } - if (x_coord_units_att) delete x_coord_units_att; - - const NcVarAtt *y_coord_units_att = get_nc_att(_yCoordVar, (string)"units"); - if (IS_INVALID_NC_P(y_coord_units_att)) - { + ConcatString y_coord_units_name; + if (!get_var_units(_yCoordVar, y_coord_units_name)) { mlog << Warning << "\n" << method_name << " -> " << "Units not given for Y coordinate variable -- assuming meters.\n\n"; } - else - { + else { //const char *y_coord_units_name = y_coord_units_att->getValues(att->as_string(0); - ConcatString y_coord_units_name; - if (!get_att_value_chars(y_coord_units_att, y_coord_units_name)) - { + if (0 == y_coord_units_name.length()) { mlog << Warning << "\n" << method_name << " -> " << "Cannot extract Y coordinate units from netCDF file -- " << "assuming meters.\n\n"; @@ -1624,8 +1676,6 @@ void NcCfFile::get_grid_mapping_lambert_conformal_conic(const NcVar *grid_mappin } } - if (y_coord_units_att) delete y_coord_units_att; - // Figure out the dx/dy and x/y pin values from the dimension variables long x_counts = GET_NC_SIZE_P(_xDim); @@ -1634,7 +1684,6 @@ void NcCfFile::get_grid_mapping_lambert_conformal_conic(const NcVar *grid_mappin //_xCoordVar->get(x_values, &x_counts); get_nc_data(_xCoordVar, x_values); - long y_counts = GET_NC_SIZE_P(_yDim); double y_values[y_counts]; @@ -1752,22 +1801,10 @@ void NcCfFile::get_grid_mapping_latitude_longitude(const NcVar *grid_mapping_var // The lat/lon dimensions are identified by their units const NcVar coord_var = get_var(_ncFile, _dims[dim_num]->getName().c_str()); - if (IS_INVALID_NC(coord_var)) - continue; - - const NcVarAtt *units_att = get_nc_att(&coord_var, (string)"units"); - if (IS_INVALID_NC_P(units_att)) { - if (units_att) delete units_att; - continue; - } + if (IS_INVALID_NC(coord_var)) continue; ConcatString dim_units; - if (!get_att_value_chars(units_att, dim_units)) { - if (units_att) delete units_att; - continue; - } - - if (units_att) delete units_att; + if (!get_var_units(&coord_var, dim_units)) continue; // See if this is a lat or lon dimension @@ -1958,17 +1995,11 @@ void NcCfFile::get_grid_mapping_polar_stereographic(const NcVar *grid_mapping_va if (IS_INVALID_NC(coord_var)) continue; - const NcVarAtt *std_name_att = get_nc_att(&coord_var, (string)"standard_name"); - if (IS_INVALID_NC_P(std_name_att)) { - if (std_name_att) delete std_name_att; - continue; - } ConcatString dim_std_name; - if (!get_att_value_chars(std_name_att, dim_std_name)) { - if (std_name_att) delete std_name_att; + const NcVarAtt *std_name_att = get_nc_att(&coord_var, standard_name_att_name); + if (!get_var_standard_name(&coord_var, dim_std_name)) { continue; } - if (std_name_att) delete std_name_att; // See if this is an X or Y dimension @@ -2046,17 +2077,14 @@ void NcCfFile::get_grid_mapping_polar_stereographic(const NcVar *grid_mapping_va // files that are in other units, we'll have to update the code to do the // units conversions. - const NcVarAtt *x_coord_units_att = get_nc_att(_xCoordVar, (string)"units"); - if (IS_INVALID_NC_P(x_coord_units_att)) - { + ConcatString x_coord_units_name; + const NcVarAtt *x_coord_units_att = get_nc_att(_xCoordVar, units_att_name); + if (!get_var_units(_xCoordVar, x_coord_units_name)) { mlog << Warning << "\n" << method_name << " -> " << "Units not given for X coordinate variable -- assuming meters.\n\n"; } - else - { - ConcatString x_coord_units_name; - if (!get_att_value_chars(x_coord_units_att, x_coord_units_name)) - { + else { + if (0 == x_coord_units_name.length()) { mlog << Warning << "\n" << method_name << " -> " << "Cannot extract X coordinate units from netCDF file -- " << "assuming meters.\n\n"; @@ -2072,19 +2100,14 @@ void NcCfFile::get_grid_mapping_polar_stereographic(const NcVar *grid_mapping_va } } - if(x_coord_units_att) delete x_coord_units_att; - - const NcVarAtt *y_coord_units_att = get_nc_att(_yCoordVar, (string)"units"); - if (IS_INVALID_NC_P(y_coord_units_att)) - { + ConcatString y_coord_units_name; + const NcVarAtt *y_coord_units_att = get_nc_att(_yCoordVar, units_att_name); + if (!get_var_units(_yCoordVar, y_coord_units_name)) { mlog << Warning << "\n" << method_name << " -> " << "Units not given for Y coordinate variable -- assuming meters.\n\n"; } - else - { - ConcatString y_coord_units_name; - if (!get_att_value_chars(y_coord_units_att, y_coord_units_name)) - { + else { + if (0 == y_coord_units_name.length()) { mlog << Warning << "\n" << method_name << " -> " << "Cannot extract Y coordinate units from netCDF file -- " << "assuming meters.\n\n"; @@ -2100,8 +2123,6 @@ void NcCfFile::get_grid_mapping_polar_stereographic(const NcVar *grid_mapping_va } } - if(y_coord_units_att) delete y_coord_units_att; - // Figure out the dx/dy and x/y pin values from the dimension variables long x_counts = GET_NC_SIZE_P(_xDim); @@ -2203,20 +2224,15 @@ void NcCfFile::get_grid_mapping_rotated_latitude_longitude(const NcVar *grid_map if (IS_INVALID_NC(coord_var)) continue; - const NcVarAtt *std_name_att = get_nc_att(&coord_var, (string)"standard_name"); - if (IS_INVALID_NC_P(std_name_att)) { - if (std_name_att) delete std_name_att; + ConcatString dim_standard_name; + if (!get_var_standard_name(&coord_var, dim_standard_name)) { continue; } - ConcatString dim_standard_name; - if (!get_att_value_chars(std_name_att, dim_standard_name)) { - if (std_name_att) delete std_name_att; + if (0 == dim_standard_name.length()) { continue; } - if (std_name_att) delete std_name_att; - // See if this is a grid_latitude or grid_longitude dimension if (dim_standard_name == "grid_latitude") @@ -2480,7 +2496,7 @@ void NcCfFile::get_grid_mapping_geostationary( if (IS_INVALID_NC(coord_var)) continue; - const NcVarAtt *std_name_att = get_nc_att(&coord_var, (string)"standard_name"); + const NcVarAtt *std_name_att = get_nc_att(&coord_var, standard_name_att_name); if (IS_INVALID_NC_P(std_name_att)) { if (std_name_att) delete std_name_att; continue; @@ -2675,11 +2691,10 @@ bool NcCfFile::get_grid_from_coordinates(const NcVar *data_var) { mlog << Debug(6) << "\n" << method_name << " -> " << "collect GRID info from \"" << GET_NC_NAME_P(data_var) << "\".\n\n"; - NcVarAtt *coordinates_att = get_nc_att(data_var, (string)"coordinates"); + NcVarAtt *coordinates_att = get_nc_att(data_var, coordinates_att_name); if (IS_VALID_NC_P(coordinates_att)) { ConcatString coordinates_value, units_value, axis_value; - NcVarAtt *missing_value_att = (NcVarAtt*) 0; get_att_value_chars(coordinates_att, coordinates_value); StringArray sa = coordinates_value.split(" "); int count = sa.n_elements(); @@ -2695,7 +2710,7 @@ bool NcCfFile::get_grid_from_coordinates(const NcVar *data_var) { is_x_dim_var = is_y_dim_var = false; for (int cIdx = 0; cIdx " << "unknown units [" << units_value << "] for the coordinate variable [" @@ -2722,21 +2737,11 @@ bool NcCfFile::get_grid_from_coordinates(const NcVar *data_var) { } if (is_y_dim_var || Var[var_num].name == y_dim_var_name) { _yCoordVar = Var[var_num].var; - missing_value_att = get_nc_att(_yCoordVar, (string)"_FillValue"); - if (IS_VALID_NC_P(missing_value_att)) { - lat_missing_value = get_att_value_double(missing_value_att); - } + get_var_fill_value(_yCoordVar, lat_missing_value); } else if (is_x_dim_var || Var[var_num].name == x_dim_var_name) { _xCoordVar = Var[var_num].var; - missing_value_att = get_nc_att(_xCoordVar, (string)"_FillValue"); - if (IS_VALID_NC_P(missing_value_att)) { - lon_missing_value = get_att_value_double(missing_value_att); - } - } - if(missing_value_att) { - delete missing_value_att; - missing_value_att = (NcVarAtt *)0; + get_var_fill_value(_xCoordVar, lon_missing_value); } } diff --git a/src/libcode/vx_data2d_nccf/nccf_file.h b/src/libcode/vx_data2d_nccf/nccf_file.h index e2acf3ee64..9aa9308f16 100644 --- a/src/libcode/vx_data2d_nccf/nccf_file.h +++ b/src/libcode/vx_data2d_nccf/nccf_file.h @@ -80,6 +80,8 @@ class NcCfFile { // TimeArray ValidTime; + NumArray raw_times; + NumArray vlevels; unixtime InitTime; unixtime AccumTime; @@ -112,6 +114,7 @@ class NcCfFile { bool getData(const char *, const LongArray &, DataPlane &, NcVarInfo *&) const; NcVarInfo* find_var_name(const char * var_name) const; + NcVarInfo* find_var_by_dim_name(const char *dim_name) const; private: diff --git a/src/libcode/vx_data2d_nccf/var_info_nccf.cc b/src/libcode/vx_data2d_nccf/var_info_nccf.cc index 25495392f0..ee3880971c 100644 --- a/src/libcode/vx_data2d_nccf/var_info_nccf.cc +++ b/src/libcode/vx_data2d_nccf/var_info_nccf.cc @@ -95,8 +95,10 @@ void VarInfoNcCF::assign(const VarInfoNcCF &v) { VarInfo::assign(v); // Copy - Dimension.clear(); - for(i=0; i " + if (Dimension.has(range_flag)) { + mlog << Error << "\n" << method_name << "only one dimension can have a range for NetCDF variable \"" << MagicStr << "\".\n\n"; exit(1); } - else - { - int increment = 0; + else { + int increment = 1; // Store the dimension of the range and limits *ptr3++ = 0; char *ptr_inc = strchr(ptr3, ':'); @@ -228,50 +242,66 @@ void VarInfoNcCF::set_magic(const ConcatString &nstr, const ConcatString &lstr) bool datestring_start = is_datestring(ptr2); bool datestring_end = is_datestring(ptr3); + if (datestring_start != datestring_end) { + mlog << Error << "\n" << method_name + << "the time value and an index/offset can not be mixed for NetCDF variable \"" + << MagicStr << "\".\n\n"; + exit(1); + } + if (datestring_start && datestring_end) as_offset = false; + unixtime time_lower = datestring_start - ? timestring_to_unix(ptr2) : atoi(ptr2); + ? timestring_to_unix(ptr2) + : (as_offset ? atoi(ptr2) : atof(ptr2)); unixtime time_upper = datestring_end - ? timestring_to_unix(ptr3) : atoi(ptr3); + ? timestring_to_unix(ptr3) + : (as_offset ? atoi(ptr3) : atof(ptr3)); if (ptr_inc != NULL) { - if (datestring_end && datestring_start) { - increment = timestring_to_sec(ptr_inc); - mlog << Debug(7) << method_name - << " increment: \"" << ptr_inc << "\" to " - << increment << " seconds.\n"; - } - else increment = atoi(ptr_inc); + if (as_offset) increment = atoi(ptr_inc); + else { + increment = is_float(ptr_inc) + ? atof(ptr_inc) : timestring_to_sec(ptr_inc); + mlog << Debug(7) << method_name + << " increment: \"" << ptr_inc << "\" to " + << increment << " seconds.\n"; + } } - Dimension.add(range_flag); + add_dimension(range_flag, as_offset); Level.set_lower(time_lower); Level.set_upper(time_upper); Level.set_increment(increment); // Assume time level type for a range of levels Level.set_type(LevelType_Time); - if (datestring_end && datestring_start) - as_offset = false; + Level.set_is_offset(as_offset); } } - else - { + else { // Single level int level = 0; - if (is_datestring(ptr2)) { + double level_value = bad_data_double; + if (is_number(ptr2)) { + if (as_offset) level = atoi(ptr2); + else { + level = vx_data2d_dim_by_value; + level_value = atof(ptr2); + } + } + else if (is_datestring(ptr2)) { unixtime unix_time = timestring_to_unix(ptr2); - level = unix_time; + level = vx_data2d_dim_by_value; + level_value = unix_time; as_offset = false; } - else if (is_number(ptr2)) { - level = atoi(ptr2); - } else { mlog << Error << "\n" << method_name << "trouble parsing NetCDF dimension value \"" << ptr2 << "\"!\n\n"; exit(1); } - Dimension.add(level); + if (as_offset) add_dimension(level, as_offset); + else add_dimension(level, as_offset, level_value); } } @@ -279,7 +309,6 @@ void VarInfoNcCF::set_magic(const ConcatString &nstr, const ConcatString &lstr) ptr = NULL; } // end while - Level.set_time_as_offset(as_offset); } // end else diff --git a/src/libcode/vx_data2d_nccf/var_info_nccf.h b/src/libcode/vx_data2d_nccf/var_info_nccf.h index f49326d80a..f740539e0d 100644 --- a/src/libcode/vx_data2d_nccf/var_info_nccf.h +++ b/src/libcode/vx_data2d_nccf/var_info_nccf.h @@ -23,6 +23,10 @@ /////////////////////////////////////////////////////////////////////////////// +typedef CRC_Array BoolArray; + +/////////////////////////////////////////////////////////////////////////////// + class VarInfoNcCF : public VarInfo { private: @@ -32,9 +36,12 @@ class VarInfoNcCF : public VarInfo // LongArray Dimension; // Dimension values for extracting 2D field + BoolArray Is_offset; // boolean for Dimension value (true: offset, false: value to be an offset (false for value) + NumArray Dim_value; // Dimension values as float for extracting 2D field void init_from_scratch(); void assign(const VarInfoNcCF &); + void clear_dimension(); public: VarInfoNcCF(); @@ -49,10 +56,14 @@ class VarInfoNcCF : public VarInfo // get stuff // - GrdFileType file_type() const; - const LongArray & dimension() const; - int dimension(int i) const; - int n_dimension() const; + GrdFileType file_type() const; + const LongArray & dimension() const; + int dimension(int i) const; + const NumArray & dim_value() const; + double dim_value(int i) const; + const BoolArray & is_offset() const; + bool is_offset(int i) const; + int n_dimension() const; // // set stuff @@ -61,7 +72,7 @@ class VarInfoNcCF : public VarInfo void set_magic(const ConcatString &, const ConcatString &); void set_dict(Dictionary &s); - void add_dimension(int dim); + void add_dimension(int dim, bool as_offset=true, double dim_value=bad_data_double); // // do stuff @@ -78,9 +89,13 @@ class VarInfoNcCF : public VarInfo /////////////////////////////////////////////////////////////////////////////// inline GrdFileType VarInfoNcCF::file_type() const { return(FileType_NcCF); } -inline const LongArray & VarInfoNcCF::dimension() const { return(Dimension); } -inline int VarInfoNcCF::dimension(int i) const { return(Dimension[i]); } -inline int VarInfoNcCF::n_dimension() const { return(Dimension.n_elements()); } +inline const LongArray & VarInfoNcCF::dimension() const { return(Dimension); } +inline int VarInfoNcCF::dimension(int i) const { return(Dimension[i]); } +inline int VarInfoNcCF::n_dimension() const { return(Dimension.n_elements());} +inline const NumArray & VarInfoNcCF::dim_value() const { return(Dim_value); } +inline double VarInfoNcCF::dim_value(int i) const { return(Dim_value[i]); } +inline const BoolArray & VarInfoNcCF::is_offset() const { return(Is_offset); } +inline bool VarInfoNcCF::is_offset(int i) const { return(Is_offset[i]); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_nc_util/nc_utils.cc b/src/libcode/vx_nc_util/nc_utils.cc index 4186970649..f439407c1f 100644 --- a/src/libcode/vx_nc_util/nc_utils.cc +++ b/src/libcode/vx_nc_util/nc_utils.cc @@ -57,7 +57,7 @@ bool get_att_value(const NcAtt *att, ConcatString &value) { //////////////////////////////////////////////////////////////////////// template -bool get_att_num_value_T(const NcAtt *att, T &att_val, int matching_type) { +bool get_att_num_value_(const NcAtt *att, T &att_val, int matching_type) { bool status = false; if (IS_VALID_NC_P(att)) { int nc_type_id = GET_NC_TYPE_ID_P(att); @@ -83,42 +83,42 @@ bool get_att_num_value_T(const NcAtt *att, T &att_val, int matching_type) { //////////////////////////////////////////////////////////////////////// bool get_att_value(const NcAtt *att, ncbyte &att_val) { - bool status = get_att_num_value_T(att, att_val, NC_BYTE); + bool status = get_att_num_value_(att, att_val, NC_BYTE); return(status); } //////////////////////////////////////////////////////////////////////// bool get_att_value(const NcAtt *att, short &att_val) { - bool status = get_att_num_value_T(att, att_val, NC_SHORT); + bool status = get_att_num_value_(att, att_val, NC_SHORT); return(status); } //////////////////////////////////////////////////////////////////////// bool get_att_value(const NcAtt *att, int &att_val) { - bool status = get_att_num_value_T(att, att_val, NC_INT); + bool status = get_att_num_value_(att, att_val, NC_INT); return(status); } //////////////////////////////////////////////////////////////////////// bool get_att_value(const NcAtt *att, unsigned int &att_val) { - bool status = get_att_num_value_T(att, att_val, NC_UINT); + bool status = get_att_num_value_(att, att_val, NC_UINT); return(status); } //////////////////////////////////////////////////////////////////////// bool get_att_value(const NcAtt *att, float &att_val) { - bool status = get_att_num_value_T(att, att_val, NC_FLOAT); + bool status = get_att_num_value_(att, att_val, NC_FLOAT); return(status); } //////////////////////////////////////////////////////////////////////// bool get_att_value(const NcAtt *att, double &att_val) { - bool status = get_att_num_value_T(att, att_val, NC_DOUBLE); + bool status = get_att_num_value_(att, att_val, NC_DOUBLE); return(status); } @@ -490,9 +490,9 @@ bool get_nc_att_value(const NcVar *var, const ConcatString &att_name, //////////////////////////////////////////////////////////////////////// template -bool get_nc_att_value_T(const NcVar *var, const ConcatString &att_name, - T &att_val, bool exit_on_error, - T bad_data, const char *caller_name) { +bool get_nc_att_value_(const NcVar *var, const ConcatString &att_name, + T &att_val, bool exit_on_error, + T bad_data, const char *caller_name) { bool status = false; // Initialize @@ -521,8 +521,18 @@ bool get_nc_att_value_T(const NcVar *var, const ConcatString &att_name, bool get_nc_att_value(const NcVar *var, const ConcatString &att_name, int &att_val, bool exit_on_error) { static const char *method_name = "get_nc_att_value(NcVar,int) -> "; - bool status = get_nc_att_value_T(var, att_name, att_val, exit_on_error, - bad_data_int, method_name); + bool status = get_nc_att_value_(var, att_name, att_val, exit_on_error, + bad_data_int, method_name); + return(status); +} + +//////////////////////////////////////////////////////////////////////// + +bool get_nc_att_value(const NcVar *var, const ConcatString &att_name, + double &att_val, bool exit_on_error) { + static const char *method_name = "get_nc_att_value(NcVar,double) -> "; + bool status = get_nc_att_value_(var, att_name, att_val, exit_on_error, + bad_data_double, method_name); return(status); } @@ -531,8 +541,8 @@ bool get_nc_att_value(const NcVar *var, const ConcatString &att_name, bool get_nc_att_value(const NcVar *var, const ConcatString &att_name, float &att_val, bool exit_on_error) { static const char *method_name = "get_nc_att_value(NcVar,float) -> "; - bool status = get_nc_att_value_T(var, att_name, att_val, exit_on_error, - bad_data_float, method_name); + bool status = get_nc_att_value_(var, att_name, att_val, exit_on_error, + bad_data_float, method_name); return(status); } @@ -558,8 +568,8 @@ bool get_nc_att_value(const NcVarAtt *att, ConcatString &att_val) { //////////////////////////////////////////////////////////////////////// template -bool get_nc_att_value_T(const NcVarAtt *att, T &att_val, bool exit_on_error, - T bad_data, const char *caller_name) { +bool get_nc_att_value_(const NcVarAtt *att, T &att_val, bool exit_on_error, + T bad_data, const char *caller_name) { bool status = true; // Initialize @@ -582,7 +592,7 @@ bool get_nc_att_value_T(const NcVarAtt *att, T &att_val, bool exit_on_error, bool get_nc_att_value(const NcVarAtt *att, int &att_val, bool exit_on_error) { static const char *method_name = "get_nc_att_value(NcVarAtt,int) -> "; - bool status = get_nc_att_value_T(att, att_val, exit_on_error, bad_data_int, method_name); + bool status = get_nc_att_value_(att, att_val, exit_on_error, bad_data_int, method_name); return(status); } @@ -590,7 +600,7 @@ bool get_nc_att_value(const NcVarAtt *att, int &att_val, bool exit_on_error) { bool get_nc_att_value(const NcVarAtt *att, float &att_val, bool exit_on_error) { static const char *method_name = "get_nc_att_value(NcVarAtt,float) -> "; - bool status = get_nc_att_value_T(att, att_val, exit_on_error, bad_data_float, method_name); + bool status = get_nc_att_value_(att, att_val, exit_on_error, bad_data_float, method_name); return(status); } @@ -598,7 +608,7 @@ bool get_nc_att_value(const NcVarAtt *att, float &att_val, bool exit_on_error) { bool get_nc_att_value(const NcVarAtt *att, double &att_val, bool exit_on_error) { static const char *method_name = "get_nc_att_value(NcVarAtt,double) -> "; - bool status = get_nc_att_value_T(att, att_val, exit_on_error, bad_data_double, method_name); + bool status = get_nc_att_value_(att, att_val, exit_on_error, bad_data_double, method_name); return(status); } @@ -758,8 +768,8 @@ bool get_global_att(const NcFile *nc, const ConcatString &att_name, //////////////////////////////////////////////////////////////////////// template -bool get_global_att_value_T(const NcFile *nc, const ConcatString& att_name, - T &att_val, T bad_data, bool error_out, const char *caller_name) { +bool get_global_att_value_(const NcFile *nc, const ConcatString& att_name, + T &att_val, T bad_data, bool error_out, const char *caller_name) { bool status = false; // Initialize att_val = bad_data; @@ -792,17 +802,17 @@ bool get_global_att_value_T(const NcFile *nc, const ConcatString& att_name, bool get_global_att(const NcFile *nc, const ConcatString& att_name, int &att_val, bool error_out) { static const char *method_name = "\nget_global_att(int) -> "; - bool status = get_global_att_value_T(nc, att_name, att_val, bad_data_int, - false, method_name); + bool status = get_global_att_value_(nc, att_name, att_val, bad_data_int, + false, method_name); if (!status) { short tmp_att_val; - status = get_global_att_value_T(nc, att_name, tmp_att_val, (short)bad_data_int, - false, method_name); + status = get_global_att_value_(nc, att_name, tmp_att_val, (short)bad_data_int, + false, method_name); if (status) att_val = tmp_att_val; else { ncbyte tmp_val2; - status = get_global_att_value_T(nc, att_name, tmp_val2, (ncbyte)bad_data_int, - error_out, method_name); + status = get_global_att_value_(nc, att_name, tmp_val2, (ncbyte)bad_data_int, + error_out, method_name); if (status) att_val = tmp_val2; } } @@ -840,8 +850,8 @@ bool get_global_att(const NcFile *nc, const ConcatString& att_name, bool get_global_att(const NcFile *nc, const ConcatString& att_name, float &att_val, bool error_out) { static const char *method_name = "\nget_global_att(float) -> "; - bool status = get_global_att_value_T(nc, att_name, att_val, bad_data_float, - error_out, method_name); + bool status = get_global_att_value_(nc, att_name, att_val, bad_data_float, + error_out, method_name); return(status); } @@ -852,12 +862,12 @@ bool get_global_att(const NcFile *nc, const ConcatString& att_name, double &att_val, bool error_out) { static const char *method_name = "\nget_global_att(double) -> "; bool status; - status = get_global_att_value_T(nc, att_name, att_val, bad_data_double, - false, method_name); + status = get_global_att_value_(nc, att_name, att_val, bad_data_double, + false, method_name); if (!status) { float tmp_att_val; - status = get_global_att_value_T(nc, att_name, tmp_att_val, bad_data_float, - error_out, method_name); + status = get_global_att_value_(nc, att_name, tmp_att_val, bad_data_float, + error_out, method_name); if (status) att_val = tmp_att_val; } @@ -959,8 +969,8 @@ int get_var_names(NcFile *nc, StringArray *varNames) { //////////////////////////////////////////////////////////////////////// template -bool get_var_att_num_T(const NcVar *var, const ConcatString &att_name, - T &att_val, T bad_data) { +bool get_var_att_num_(const NcVar *var, const ConcatString &att_name, + T &att_val, T bad_data) { bool status = false; // Initialize @@ -981,7 +991,7 @@ bool get_var_att_num_T(const NcVar *var, const ConcatString &att_name, bool get_var_att_double(const NcVar *var, const ConcatString &att_name, double &att_val) { - bool status = get_var_att_num_T(var, att_name, att_val, bad_data_double); + bool status = get_var_att_num_(var, att_name, att_val, bad_data_double); return(status); } @@ -990,29 +1000,33 @@ bool get_var_att_double(const NcVar *var, const ConcatString &att_name, bool get_var_att_float(const NcVar *var, const ConcatString &att_name, float &att_val) { - bool status = get_var_att_num_T(var, att_name, att_val, bad_data_float); + bool status = get_var_att_num_(var, att_name, att_val, bad_data_float); return(status); } //////////////////////////////////////////////////////////////////////// -bool get_var_units(const NcVar *var, ConcatString &att_val) { +double get_var_add_offset(const NcVar *var) { + double v; - return(get_nc_att_value(var, units_att_name, att_val)); + if(!get_var_att_double(var, add_offset_att_name, v)) { + v = 0.f; + } + + return(v); } //////////////////////////////////////////////////////////////////////// -bool get_var_level(const NcVar *var, ConcatString &att_val) { - - return(get_nc_att_value(var, level_att_name, att_val)); +bool get_var_axis(const NcVar *var, ConcatString &att_val) { + return(get_nc_att_value(var, axis_att_name, att_val)); } //////////////////////////////////////////////////////////////////////// template -bool get_var_fill_value_T(const NcVar *var, T &att_val) { +bool get_var_fill_value(const NcVar *var, T &att_val) { bool found = false; NcVarAtt *att = get_nc_att(var, fill_value_att_name); @@ -1032,10 +1046,10 @@ bool get_var_fill_value_T(const NcVar *var, T &att_val) { //////////////////////////////////////////////////////////////////////// -double get_var_missing_value(const NcVar *var) { +double get_var_fill_value(const NcVar *var) { double v; - if(!get_var_att_double(var, missing_value_att_name, v)) { + if(!get_var_att_double(var, fill_value_att_name, v)) { v = bad_data_double; } @@ -1044,23 +1058,29 @@ double get_var_missing_value(const NcVar *var) { //////////////////////////////////////////////////////////////////////// -double get_var_fill_value(const NcVar *var) { - double v; +bool get_var_grid_mapping(const NcVar *var, ConcatString &att_val) { + return(get_nc_att_value(var, grid_mapping_att_name, att_val)); +} - if(!get_var_att_double(var, fill_value_att_name, v)) { - v = bad_data_double; - } +//////////////////////////////////////////////////////////////////////// - return(v); +bool get_var_grid_mapping_name(const NcVar *var, ConcatString &att_val) { + return(get_nc_att_value(var, grid_mapping_name_att_name, att_val)); +} + +//////////////////////////////////////////////////////////////////////// + +bool get_var_long_name(const NcVar *var, ConcatString &att_val) { + return(get_nc_att_value(var, long_name_att_name, att_val)); } //////////////////////////////////////////////////////////////////////// -double get_var_add_offset_value(const NcVar *var) { +double get_var_missing_value(const NcVar *var) { double v; - if(!get_var_att_double(var, add_offset_att_name, v)) { - v = 0.f; + if(!get_var_att_double(var, missing_value_att_name, v)) { + v = bad_data_double; } return(v); @@ -1068,7 +1088,7 @@ double get_var_add_offset_value(const NcVar *var) { //////////////////////////////////////////////////////////////////////// -double get_var_scale_factor_value(const NcVar *var) { +double get_var_scale_factor(const NcVar *var) { double v; if(!get_var_att_double(var, scale_factor_att_name, v)) { @@ -1080,6 +1100,19 @@ double get_var_scale_factor_value(const NcVar *var) { //////////////////////////////////////////////////////////////////////// +bool get_var_standard_name(const NcVar *var, ConcatString &att_val) { + return(get_nc_att_value(var, standard_name_att_name, att_val)); +} + +//////////////////////////////////////////////////////////////////////// + +bool get_var_units(const NcVar *var, ConcatString &att_val) { + + return(get_nc_att_value(var, units_att_name, att_val)); +} + +//////////////////////////////////////////////////////////////////////// + char get_char_val(NcFile * nc, const char * var_name, const int index) { NcVar var = get_var(nc, var_name); return (get_char_val(&var, index)); @@ -1327,11 +1360,11 @@ float get_float_var(NcVar * var, const int index) { //////////////////////////////////////////////////////////////////////// template -void apply_scale_factor_T(T *data, const int cell_count, - double add_offset, double scale_factor, - const T nc_fill_value, const T met_fill_value, - bool has_fill_value, - const char *data_type, const char *var_name) { +void apply_scale_factor_(T *data, const int cell_count, + double add_offset, double scale_factor, + const T nc_fill_value, const T met_fill_value, + bool has_fill_value, + const char *data_type, const char *var_name) { const int debug_level = 7; clock_t start_clock = clock(); const char *method_name = "apply_scale_factor(T) "; @@ -1372,9 +1405,10 @@ void apply_scale_factor_T(T *data, const int cell_count, << unpacked_count << " out of " << cell_count << ", scale_factor=" << scale_factor<< " add_offset=" << add_offset << ". FillValue(" << data_type << ")=" << nc_fill_value << "\n"; - mlog << Debug(debug_level) << method_name << " data range [" << min_value << " - " << max_value - << "] raw data: [" << raw_min_val << " - " << raw_max_val << "] Positive count: " - << positive_cnt << "\n"; + mlog << Debug(debug_level) << method_name + << " data range [" << min_value << " - " << max_value + << "] raw data: [" << raw_min_val << " - " << raw_max_val + << "] Positive count: " << positive_cnt << "\n"; } mlog << Debug(debug_level) << method_name << " took " << (clock()-start_clock)/double(CLOCKS_PER_SEC) << " seconds\n"; @@ -1383,8 +1417,8 @@ void apply_scale_factor_T(T *data, const int cell_count, //////////////////////////////////////////////////////////////////////// // Note: -// - template _t reads data as is (do not apply no scale_factor and add_offset) -// - template _T reads data and applies scale_factor and add_offset. +// - template _t reads data as is (do not apply no scale_factor and add_offset) +// - template _ reads data and applies scale_factor and add_offset. template bool get_nc_data_t(NcVar *var, T *data) { @@ -1399,81 +1433,10 @@ bool get_nc_data_t(NcVar *var, T *data) { } //////////////////////////////////////////////////////////////////////// -// Note: template _t reads data as is (do not apply no scale_factor and add_offset) -/* -template -bool get_nc_data_t(NcVar *var, T *data, const long *dims, const long *curs) { - bool return_status = false; - const char *method_name = "get_nc_data_t(*dims, *curs) "; - - if (IS_VALID_NC_P(var)) { - std::vector start; - std::vector count; - - int dimC = get_dim_count(var); - int data_size = 1; - for (int idx = 0; idx < dimC; idx++) { - int dim_size = get_dim_size(var, idx); - if ((curs[idx]+dims[idx]) > dim_size) { - NcDim nc_dim = get_nc_dim(var, idx); - mlog << Error << "\n" << method_name << "The start offset and count (" - << curs[idx] << ", " << dims[idx] << ") exceeds the dimension[" - << idx << "] " << dim_size << " " - << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") - << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; - exit(1); - } - - start.push_back((size_t)curs[idx]); - count.push_back((size_t)dims[idx]); - data_size *= (dims[idx] - curs[idx]); - } - - //for (int idx1=0; idx1getVar(start, count, data); - return_status = true; - } - return(return_status); -} - -//////////////////////////////////////////////////////////////////////// -// Note: template _t reads data as is (do not apply no scale_factor and add_offset) -// Read a single data template -bool get_nc_data_t(NcVar *var, T *data, const long *curs) { - bool return_status = false; - const char *method_name = "get_nc_data_t(*curs) "; - - if (IS_VALID_NC_P(var)) { - - int dimC = get_dim_count(var); - long dims[dimC]; - for (int idx = 0; idx < dimC; idx++) { - dims[idx] = 1; - } - - return_status = get_nc_data_t(var, data, dims, curs); - } - return(return_status); -} -*/ - -//////////////////////////////////////////////////////////////////////// -// Note: -// - template _t reads data as is (do not apply no scale_factor and add_offset) -// - template _T reads data and applies scale_factor and add_offset. - -template -bool get_nc_data_T(NcVar *var, T *data, const T met_missing) { - //const char *method_name = "get_nc_data_T() "; +bool get_nc_data_(NcVar *var, T *data, const T met_missing) { + //const char *method_name = "get_nc_data_() "; int data_size = get_data_size(var); for (int idx1=0; idx1", GET_NC_NAME_P(var).c_str()); + apply_scale_factor_(data, cell_count, add_offset, scale_factor, + nc_missing, met_missing, has_missing_attr, + "", GET_NC_NAME_P(var).c_str()); } } return(return_status); } //////////////////////////////////////////////////////////////////////// -// Note: template _T reads data and applies scale_factor and add_offset. template -bool get_nc_data_T(NcVar *var, T *data, T bad_data, const long *dims, const long *curs) { +bool get_nc_data_(NcVar *var, T *data, T bad_data, const long *dims, const long *curs) { bool return_status = false; - const char *method_name = "get_nc_data_T(*dims, *curs) "; + const char *method_name = "get_nc_data_(T, *dims, *curs) "; if (IS_VALID_NC_P(var)) { std::vector start; @@ -1544,25 +1506,24 @@ bool get_nc_data_T(NcVar *var, T *data, T bad_data, const long *dims, const long //scale_factor and add_offset if (has_add_offset_attr(var) || has_scale_factor_attr(var)) { T nc_missing; - double add_offset = get_var_add_offset_value(var); - double scale_factor = get_var_scale_factor_value(var); - bool has_missing_attr = get_var_fill_value_T(var, nc_missing); + double add_offset = get_var_add_offset(var); + double scale_factor = get_var_scale_factor(var); + bool has_missing_attr = get_var_fill_value(var, nc_missing); if (!has_missing_attr) nc_missing = bad_data; - apply_scale_factor_T(data, data_size, add_offset, scale_factor, - nc_missing, bad_data, has_missing_attr, - "", GET_NC_NAME_P(var).c_str()); + apply_scale_factor_(data, data_size, add_offset, scale_factor, + nc_missing, bad_data, has_missing_attr, + "", GET_NC_NAME_P(var).c_str()); } } return(return_status); } //////////////////////////////////////////////////////////////////////// -// Note: template _T reads data and applies scale_factor and add_offset. template -bool get_nc_data_T(NcVar *var, T *data, T met_missing, const long dim, const long cur) { +bool get_nc_data_(NcVar *var, T *data, T met_missing, const long dim, const long cur) { bool return_status = false; - const char *method_name = "get_nc_data_T(dim, cur) "; + const char *method_name = "get_nc_data_(T, dim, cur) "; for (int idx=0; idx", GET_NC_NAME_P(var).c_str()); + apply_scale_factor_(data, dim, add_offset, scale_factor, + nc_missing, met_missing, has_missing_attr, + "", GET_NC_NAME_P(var).c_str()); } } return(return_status); } //////////////////////////////////////////////////////////////////////// -// Note: template _T reads data and applies scale_factor and add_offset. // read a single data template -bool get_nc_data_T(NcVar *var, T *data, T bad_data, const long *curs) { +bool get_nc_data_(NcVar *var, T *data, T bad_data, const long *curs) { bool return_status = false; - const char *method_name = "get_nc_data_T(*curs) "; + const char *method_name = "get_nc_data_(*curs) "; if (IS_VALID_NC_P(var)) { @@ -1631,7 +1591,7 @@ bool get_nc_data_T(NcVar *var, T *data, T bad_data, const long *curs) { } // Retrieve the NetCDF value from the NetCDF variable. - return_status = get_nc_data_T(var, data, bad_data, dims, curs); + return_status = get_nc_data_(var, data, bad_data, dims, curs); } return(return_status); } @@ -1639,7 +1599,7 @@ bool get_nc_data_T(NcVar *var, T *data, T bad_data, const long *curs) { //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, int *data, const long *curs) { - bool return_status = get_nc_data_T(var, data, bad_data_int, curs); + bool return_status = get_nc_data_(var, data, bad_data_int, curs); return(return_status); } @@ -1647,7 +1607,7 @@ bool get_nc_data(NcVar *var, int *data, const long *curs) { //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, time_t *data) { - bool return_status = get_nc_data_T(var, data, (time_t)bad_data_int); + bool return_status = get_nc_data_(var, data, (time_t)bad_data_int); return(return_status); } @@ -1655,20 +1615,20 @@ bool get_nc_data(NcVar *var, time_t *data) { //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, int *data) { - bool return_status = get_nc_data_T(var, data, bad_data_int); + bool return_status = get_nc_data_(var, data, bad_data_int); return(return_status); } //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, int *data, const long dim, const long cur) { - return(get_nc_data_T(var, data, bad_data_int, dim, cur)); + return(get_nc_data_(var, data, bad_data_int, dim, cur)); } //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, int *data, const long *dims, const long *curs) { - bool return_status = get_nc_data_T(var, data, bad_data_int, dims, curs); + bool return_status = get_nc_data_(var, data, bad_data_int, dims, curs); return(return_status); } @@ -1676,7 +1636,7 @@ bool get_nc_data(NcVar *var, int *data, const long *dims, const long *curs) { //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, short *data, const long *curs) { - bool return_status = get_nc_data_T(var, data, (short)bad_data_int, curs); + bool return_status = get_nc_data_(var, data, (short)bad_data_int, curs); return(return_status); } @@ -1684,7 +1644,7 @@ bool get_nc_data(NcVar *var, short *data, const long *curs) { //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, short *data, const long *dims, const long *curs) { - bool return_status = get_nc_data_T(var, data, (short)bad_data_int, dims, curs); + bool return_status = get_nc_data_(var, data, (short)bad_data_int, dims, curs); return(return_status); } @@ -1692,9 +1652,9 @@ bool get_nc_data(NcVar *var, short *data, const long *dims, const long *curs) { //////////////////////////////////////////////////////////////////////// template -void copy_nc_data_t1(NcVar *var, float *data, const T *packed_data, - const int cell_count, const char *data_type, - double add_offset, double scale_factor, bool has_missing, T missing_value) { +void copy_nc_data_t(NcVar *var, float *data, const T *packed_data, + const int cell_count, const char *data_type, + double add_offset, double scale_factor, bool has_missing, T missing_value) { clock_t start_clock = clock(); const char *method_name = "copy_nc_data_t(float) "; @@ -1732,9 +1692,10 @@ void copy_nc_data_t1(NcVar *var, float *data, const T *packed_data, << " apply_scale_factor unpacked data: count=" << unpacked_count << " out of " << cell_count << ". FillValue(" << data_type << ")=" << missing_value << "\n"; - mlog << Debug(7) << method_name << "data range [" << min_value << " - " << max_value - << "] raw data: [" << raw_min_val << " - " << raw_max_val << "] Positive count: " - << positive_cnt << "\n"; + mlog << Debug(7) << method_name + << "data range [" << min_value << " - " << max_value + << "] raw data: [" << raw_min_val << " - " << raw_max_val + << "] Positive count: " << positive_cnt << "\n"; } else { idx = 0; @@ -1767,13 +1728,13 @@ void copy_nc_data_t1(NcVar *var, float *data, const T *packed_data, //////////////////////////////////////////////////////////////////////// template -void copy_nc_data_t(NcVar *var, float *data, const T *packed_data, - const int cell_count, const char *data_type, - double add_offset, double scale_factor) { +void copy_nc_data_(NcVar *var, float *data, const T *packed_data, + const int cell_count, const char *data_type, + double add_offset, double scale_factor) { T missing_value; - bool has_missing = get_var_fill_value_T(var, missing_value); - copy_nc_data_t1(var, data, packed_data, cell_count, data_type, - add_offset, scale_factor, has_missing, missing_value); + bool has_missing = get_var_fill_value(var, missing_value); + copy_nc_data_t(var, data, packed_data, cell_count, data_type, + add_offset, scale_factor, has_missing, missing_value); return; } @@ -1798,7 +1759,7 @@ bool get_nc_data(NcVar *var, float *data) { get_nc_data_t(var, data); float fill_value; - bool has_fill_value = get_var_fill_value_T(var, fill_value); + bool has_fill_value = get_var_fill_value(var, fill_value); if (has_fill_value) { for (int idx=0; idxgetVar(packed_data); - copy_nc_data_t(var, data, packed_data, cell_count, - "int64", add_offset, scale_factor); + copy_nc_data_(var, data, packed_data, cell_count, + "int64", add_offset, scale_factor); delete [] packed_data; } break; @@ -1852,15 +1813,15 @@ bool get_nc_data(NcVar *var, float *data) { int *packed_data = new int[cell_count]; var->getVar(packed_data); - copy_nc_data_t(var, data, packed_data, cell_count, - "int", add_offset, scale_factor); + copy_nc_data_(var, data, packed_data, cell_count, + "int", add_offset, scale_factor); delete [] packed_data; } break; case NcType::nc_SHORT: { short missing_value; - bool has_missing = get_var_fill_value_T(var, missing_value); + bool has_missing = get_var_fill_value(var, missing_value); short *packed_data = new short[cell_count]; var->getVar(packed_data); @@ -1869,15 +1830,15 @@ bool get_nc_data(NcVar *var, float *data) { for (int idx=0; idxgetVar(packed_data); - copy_nc_data_t(var, data, packed_data, cell_count, - "unsigned short", add_offset, scale_factor); + copy_nc_data_(var, data, packed_data, cell_count, + "unsigned short", add_offset, scale_factor); delete [] packed_data; } break; case NcType::nc_BYTE: { ncbyte missing_value; - bool has_missing = get_var_fill_value_T(var, missing_value); + bool has_missing = get_var_fill_value(var, missing_value); ncbyte *packed_data = new ncbyte[cell_count]; var->getVar(packed_data); @@ -1904,15 +1865,15 @@ bool get_nc_data(NcVar *var, float *data) { for (int idx=0; idxgetVar(packed_data); - copy_nc_data_t(var, data, packed_data, cell_count, - "unsigned char", add_offset, scale_factor); + copy_nc_data_(var, data, packed_data, cell_count, + "unsigned char", add_offset, scale_factor); delete [] packed_data; } break; @@ -1945,7 +1906,7 @@ bool get_nc_data(NcVar *var, float *data) { //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, float *data, const long *curs) { - bool return_status = get_nc_data_T(var, data, bad_data_float, curs); + bool return_status = get_nc_data_(var, data, bad_data_float, curs); return(return_status); } @@ -1953,7 +1914,7 @@ bool get_nc_data(NcVar *var, float *data, const long *curs) { //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, float *data, const long *dims, const long *curs) { - bool return_status = get_nc_data_T(var, data, bad_data_float, dims, curs); + bool return_status = get_nc_data_(var, data, bad_data_float, dims, curs); return(return_status); } @@ -1961,7 +1922,7 @@ bool get_nc_data(NcVar *var, float *data, const long *dims, const long *curs) { //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, float *data, const long dim, const long cur) { - bool return_status = get_nc_data_T(var, data, bad_data_float, dim, cur); + bool return_status = get_nc_data_(var, data, bad_data_float, dim, cur); return(return_status); } @@ -1981,10 +1942,10 @@ bool get_nc_data(NcFile *nc, const char *var_name, double *data, //////////////////////////////////////////////////////////////////////// template -void copy_nc_data_t1(NcVar *var, double *data, const T *packed_data, - const int cell_count, const char *data_type, - double add_offset, double scale_factor, - bool has_missing, T missing_value) { +void copy_nc_data_t(NcVar *var, double *data, const T *packed_data, + const int cell_count, const char *data_type, + double add_offset, double scale_factor, + bool has_missing, T missing_value) { int unpacked_count = 0; const char *method_name = "copy_nc_data_t(double) "; @@ -2023,8 +1984,8 @@ void copy_nc_data_t1(NcVar *var, double *data, const T *packed_data, << unpacked_count << " out of " << cell_count << ". FillValue(" << data_type << ")=" << missing_value << " data range [" << min_value << " - " << max_value - << "] raw data: [" << raw_min_val << " - " << raw_max_val << "] Positive count: " - << positive_cnt << "\n"; + << "] raw data: [" << raw_min_val << " - " << raw_max_val + << "] Positive count: " << positive_cnt << "\n"; } else { idx = 0; @@ -2054,13 +2015,13 @@ void copy_nc_data_t1(NcVar *var, double *data, const T *packed_data, //////////////////////////////////////////////////////////////////////// template -void copy_nc_data_t(NcVar *var, double *data, const T *packed_data, - const int cell_count, const char *data_type, - double add_offset, double scale_factor) { +void copy_nc_data_(NcVar *var, double *data, const T *packed_data, + const int cell_count, const char *data_type, + double add_offset, double scale_factor) { T missing_value; - bool has_missing = get_var_fill_value_T(var, missing_value); - copy_nc_data_t1(var, data, packed_data, cell_count, data_type, - add_offset, scale_factor, has_missing, missing_value); + bool has_missing = get_var_fill_value(var, missing_value); + copy_nc_data_t(var, data, packed_data, cell_count, data_type, + add_offset, scale_factor, has_missing, missing_value); return; } @@ -2085,7 +2046,7 @@ bool get_nc_data(NcVar *var, double *data) { var->getVar(data); double fill_value; - bool has_fill_value = get_var_fill_value_T(var, fill_value); + bool has_fill_value = get_var_fill_value(var, fill_value); if (has_fill_value) { for (int idx=0; idxgetVar(packed_data); float fill_value; - bool has_fill_value = get_var_fill_value_T(var, fill_value); + bool has_fill_value = get_var_fill_value(var, fill_value); for (int idx=0; idxgetVar(packed_data); - copy_nc_data_t(var, data, packed_data, cell_count, - "int64", add_offset, scale_factor); + copy_nc_data_(var, data, packed_data, cell_count, + "int64", add_offset, scale_factor); delete [] packed_data; } break; @@ -2138,15 +2099,15 @@ bool get_nc_data(NcVar *var, double *data) { int *packed_data = new int[cell_count]; var->getVar(packed_data); - copy_nc_data_t(var, data, packed_data, cell_count, - "int", add_offset, scale_factor); + copy_nc_data_(var, data, packed_data, cell_count, + "int", add_offset, scale_factor); delete [] packed_data; } break; case NcType::nc_SHORT: { short missing_value; - bool has_missing = get_var_fill_value_T(var, missing_value); + bool has_missing = get_var_fill_value(var, missing_value); short *packed_data = new short[cell_count]; var->getVar(packed_data); if (unsigned_value) { @@ -2154,15 +2115,15 @@ bool get_nc_data(NcVar *var, double *data) { for (int idx=0; idxgetVar(packed_data); - copy_nc_data_t(var, data, packed_data, cell_count, - "ushort", add_offset, scale_factor); + copy_nc_data_(var, data, packed_data, cell_count, + "ushort", add_offset, scale_factor); delete [] packed_data; } break; case NcType::nc_BYTE: { ncbyte missing_value; - bool has_missing = get_var_fill_value_T(var, missing_value); + bool has_missing = get_var_fill_value(var, missing_value); ncbyte *packed_data = new ncbyte[cell_count]; var->getVar(packed_data); @@ -2189,15 +2150,15 @@ bool get_nc_data(NcVar *var, double *data) { for (int idx=0; idxgetVar(packed_data); - copy_nc_data_t(var, data, packed_data, cell_count, - "ncubyte", add_offset, scale_factor); + copy_nc_data_(var, data, packed_data, cell_count, + "ncubyte", add_offset, scale_factor); delete [] packed_data; } break; @@ -2227,14 +2188,14 @@ bool get_nc_data(NcVar *var, double *data) { //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, double *data, const long *curs) { - bool return_status = get_nc_data_T(var, data, bad_data_double, curs); + bool return_status = get_nc_data_(var, data, bad_data_double, curs); return(return_status); } //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, double *data, const long dim, const long cur) { - bool return_status = get_nc_data_T(var, data, bad_data_double, dim, cur);; + bool return_status = get_nc_data_(var, data, bad_data_double, dim, cur);; return(return_status); } @@ -2242,7 +2203,7 @@ bool get_nc_data(NcVar *var, double *data, const long dim, const long cur) { //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, double *data, const long *dims, const long *curs) { - bool return_status = get_nc_data_T(var, data, bad_data_double, dims, curs); + bool return_status = get_nc_data_(var, data, bad_data_double, dims, curs); return(return_status); } @@ -2333,7 +2294,7 @@ bool get_nc_data(NcFile *nc, const char *var_name, char *data, //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, char *data, const long dim, const long cur) { - bool return_status = get_nc_data_T(var, data, bad_data_char, dim, cur); + bool return_status = get_nc_data_(var, data, bad_data_char, dim, cur); return(return_status); } @@ -2341,7 +2302,7 @@ bool get_nc_data(NcVar *var, char *data, const long dim, const long cur) { //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, char *data, const long *dims, const long *curs) { - bool return_status = get_nc_data_T(var, data, bad_data_char, dims, curs); + bool return_status = get_nc_data_(var, data, bad_data_char, dims, curs); return(return_status); } @@ -2371,7 +2332,7 @@ bool get_nc_data(NcFile *nc, const char *var_name, ncbyte *data, //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, ncbyte *data, const long dim, const long cur) { - bool return_status = get_nc_data_T(var, data, (ncbyte)bad_data_char, dim, cur); + bool return_status = get_nc_data_(var, data, (ncbyte)bad_data_char, dim, cur); return(return_status); } @@ -2379,11 +2340,72 @@ bool get_nc_data(NcVar *var, ncbyte *data, const long dim, const long cur) { //////////////////////////////////////////////////////////////////////// bool get_nc_data(NcVar *var, ncbyte *data, const long *dims, const long *curs) { - bool return_status = get_nc_data_T(var, data, (ncbyte)bad_data_char, dims, curs); + bool return_status = get_nc_data_(var, data, (ncbyte)bad_data_char, dims, curs); return(return_status); } +//////////////////////////////////////////////////////////////////////// +// returns matching offset or bad_data_int if not found + +int get_index_at_nc_data(NcVar *var, double value, const string dim_name, bool is_time) { + int offset = bad_data_int; + static const char *method_name = "get_index_at_nc_data() -> "; + if (IS_VALID_NC_P(var)) { + int data_size = get_data_size(var); + double *values = new double[data_size]; + + if (get_nc_data(var, values)) { + unixtime ut; + int sec_per_unit; + bool no_leap_year = get_att_no_leap_year(var); + ut = sec_per_unit = 0; + if (is_time) { + ConcatString units; + bool has_attr = get_var_units(var, units); + if (has_attr && (0 < units.length())) + parse_cf_time_string(units.c_str(), ut, sec_per_unit); + else { + mlog << Warning << "\n" << method_name + << "the time variable \"" << GET_NC_NAME_P(var) + << "\" must contain a \"" + << units_att_name << "\" attribute.\n\n"; + } + } + for (int idx=0; idx 10000000.)) value_str << unix_to_yyyymmdd_hhmmss(value); + else value_str << value; + if (offset == bad_data_int) + mlog << Debug(7) << method_name << "Not found value " << value_str + << " at " << GET_NC_NAME_P(var) + << " by dimension name \"" << dim_name << "\"\n"; + else + mlog << Debug(7) << method_name << "Found value " << value_str + << " (index=" << offset << ") at " << GET_NC_NAME_P(var) + << " by dimension name \"" << dim_name << "\"\n"; + } + else { + mlog << Debug(7) << method_name << "Not found a dimension variable for \"" + << dim_name << "\"\n"; + } + return(offset); +} + //////////////////////////////////////////////////////////////////////// bool get_nc_data_to_array(NcVar *var, StringArray *array_buf) { @@ -2474,7 +2496,7 @@ int get_nc_string_length(NcFile *nc_file, NcVar var, const char *var_name) { //////////////////////////////////////////////////////////////////////// template -bool _put_nc_data(NcVar *var, const T data, long offset0, long offset1, long offset2) { +bool put_nc_data_T(NcVar *var, const T data, long offset0, long offset1, long offset2) { vector offsets; offsets.push_back((size_t)offset0); if (0 <= offset1) { @@ -2490,31 +2512,31 @@ bool _put_nc_data(NcVar *var, const T data, long offset0, long offset1, long off //////////////////////////////////////////////////////////////////////// bool put_nc_data(NcVar *var, const int data, long offset0, long offset1, long offset2) { - return _put_nc_data(var, data, offset0, offset1, offset2); + return put_nc_data_T(var, data, offset0, offset1, offset2); } //////////////////////////////////////////////////////////////////////// bool put_nc_data(NcVar *var, const char data, long offset0, long offset1, long offset2) { - return _put_nc_data(var, data, offset0, offset1, offset2); + return put_nc_data_T(var, data, offset0, offset1, offset2); } //////////////////////////////////////////////////////////////////////// bool put_nc_data(NcVar *var, const float data , long offset0, long offset1, long offset2) { - return _put_nc_data(var, data, offset0, offset1, offset2); + return put_nc_data_T(var, data, offset0, offset1, offset2); } //////////////////////////////////////////////////////////////////////// bool put_nc_data(NcVar *var, const double data, long offset0, long offset1, long offset2) { - return _put_nc_data(var, data, offset0, offset1, offset2); + return put_nc_data_T(var, data, offset0, offset1, offset2); } //////////////////////////////////////////////////////////////////////// bool put_nc_data(NcVar *var, const ncbyte data, long offset0, long offset1, long offset2) { - return _put_nc_data(var, data, offset0, offset1, offset2); + return put_nc_data_T(var, data, offset0, offset1, offset2); } //////////////////////////////////////////////////////////////////////// @@ -2555,7 +2577,7 @@ bool put_nc_data(NcVar *var, const ncbyte *data ) { //////////////////////////////////////////////////////////////////////// template -bool _put_nc_data(NcVar *var, const T *data, const long length, const long offset) { +bool put_nc_data_T(NcVar *var, const T *data, const long length, const long offset) { vector offsets, counts; int dim_count = get_dim_count(var); offsets.push_back(offset); @@ -2571,42 +2593,42 @@ bool _put_nc_data(NcVar *var, const T *data, const long length, const long of //////////////////////////////////////////////////////////////////////// bool put_nc_data(NcVar *var, const int *data, const long length, const long offset) { - _put_nc_data(var, data, length, offset); + put_nc_data_T(var, data, length, offset); return true; } //////////////////////////////////////////////////////////////////////// bool put_nc_data(NcVar *var, const char *data, const long length, const long offset) { - _put_nc_data(var, data, length, offset); + put_nc_data_T(var, data, length, offset); return true; } //////////////////////////////////////////////////////////////////////// bool put_nc_data(NcVar *var, const float *data , const long length, const long offset) { - _put_nc_data(var, data, length, offset); + put_nc_data_T(var, data, length, offset); return true; } //////////////////////////////////////////////////////////////////////// bool put_nc_data(NcVar *var, const double *data, const long length, const long offset) { - _put_nc_data(var, data, length, offset); + put_nc_data_T(var, data, length, offset); return true; } //////////////////////////////////////////////////////////////////////// bool put_nc_data(NcVar *var, const ncbyte *data, const long length, const long offset) { - _put_nc_data(var, data, length, offset); + put_nc_data_T(var, data, length, offset); return true; } //////////////////////////////////////////////////////////////////////// template -bool _put_nc_data(NcVar *var, const T *data , const long *lengths, const long *offsets) { +bool put_nc_data_T(NcVar *var, const T *data , const long *lengths, const long *offsets) { int dim = get_dim_count(var); vector nc_offsets, counts; for (int idx = 0 ; idx < dim; idx++) { @@ -2622,29 +2644,29 @@ bool _put_nc_data(NcVar *var, const T *data , const long *lengths, const long *o //////////////////////////////////////////////////////////////////////// bool put_nc_data(NcVar *var, const float *data , const long *lengths, const long *offsets) { - _put_nc_data(var, data , lengths, offsets); + put_nc_data_T(var, data , lengths, offsets); return true; } //////////////////////////////////////////////////////////////////////// bool put_nc_data(NcVar *var, const char *data , const long *lengths, const long *offsets) { - _put_nc_data(var, data , lengths, offsets); + put_nc_data_T(var, data , lengths, offsets); return true; } //////////////////////////////////////////////////////////////////////// bool put_nc_data(NcVar *var, const int *data , const long *lengths, const long *offsets) { - _put_nc_data(var, data , lengths, offsets); + put_nc_data_T(var, data , lengths, offsets); return true; } //////////////////////////////////////////////////////////////////////// template -bool _put_nc_data_with_dims(NcVar *var, const T *data, - const long len0, const long len1, const long len2) { +bool put_nc_data_T_with_dims(NcVar *var, const T *data, + const long len0, const long len1, const long len2) { vector offsets, counts; if (0 < len0) { offsets.push_back(0); @@ -2673,7 +2695,7 @@ bool put_nc_data_with_dims(NcVar *var, const int *data, bool put_nc_data_with_dims(NcVar *var, const int *data, const long len0, const long len1, const long len2) { - _put_nc_data_with_dims(var, data, len0, len1, len2); + put_nc_data_T_with_dims(var, data, len0, len1, len2); return true; } @@ -2688,7 +2710,7 @@ bool put_nc_data_with_dims(NcVar *var, const float *data, bool put_nc_data_with_dims(NcVar *var, const float *data, const long len0, const long len1, const long len2) { - _put_nc_data_with_dims(var, data, len0, len1, len2); + put_nc_data_T_with_dims(var, data, len0, len1, len2); return true; } @@ -2703,7 +2725,7 @@ bool put_nc_data_with_dims(NcVar *var, const double *data, bool put_nc_data_with_dims(NcVar *var, const double *data, const long len0, const long len1, const long len2) { - _put_nc_data_with_dims(var, data, len0, len1, len2); + put_nc_data_T_with_dims(var, data, len0, len1, len2); return true; } @@ -3674,15 +3696,16 @@ NcVar get_nc_var_lat(const NcFile *nc) { itVar != mapVar.end(); ++itVar) { ConcatString name = (*itVar).first; //if (is_nc_name_lat(name)) found = true; - if (get_nc_att_value(&(*itVar).second, "standard_name", name)) { + if (get_var_standard_name(&(*itVar).second, name)) { if (is_nc_name_lat(name)) found = true; } - if (!found && get_nc_att_value(&(*itVar).second, "units", name)) { + if (!found && get_var_units(&(*itVar).second, name)) { if (is_nc_unit_latitude(name.c_str())) { - if (get_nc_att_value(&(*itVar).second, "axis", name)) { + if (get_nc_att_value(&(*itVar).second, axis_att_name, name)) { if (is_nc_attr_lat(name)) found = true; } - else if (get_nc_att_value(&(*itVar).second, "_CoordinateAxisType", name)) { + else if (get_nc_att_value(&(*itVar).second, + coordinate_axis_type_att_name, name)) { if (is_nc_attr_lat(name)) found = true; } } @@ -3715,15 +3738,16 @@ NcVar get_nc_var_lon(const NcFile *nc) { itVar != mapVar.end(); ++itVar) { ConcatString name = (*itVar).first; //if (is_nc_name_lon(name)) found = true; - if (get_nc_att_value(&(*itVar).second, "standard_name", name)) { + if (get_var_standard_name(&(*itVar).second, name)) { if (is_nc_name_lon(name)) found = true; } - if (!found && get_nc_att_value(&(*itVar).second, "units", name)) { + if (!found && get_var_units(&(*itVar).second, name)) { if (is_nc_unit_longitude(name.c_str())) { - if (get_nc_att_value(&(*itVar).second, "axis", name)) { + if (get_nc_att_value(&(*itVar).second, axis_att_name, name)) { if (is_nc_attr_lon(name)) found = true; } - else if (get_nc_att_value(&(*itVar).second, "_CoordinateAxisType", name)) { + else if (get_nc_att_value(&(*itVar).second, + coordinate_axis_type_att_name, name)) { if (is_nc_attr_lon(name)) found = true; } } @@ -3756,17 +3780,18 @@ NcVar get_nc_var_time(const NcFile *nc) { itVar != mapVar.end(); ++itVar) { ConcatString name = (*itVar).first; //if (is_nc_name_time(name)) found = true; - if (get_nc_att_value(&(*itVar).second, "standard_name", name)) { + if (get_var_standard_name(&(*itVar).second, name)) { if (is_nc_name_time(name)) found = true; mlog << Debug(7) << method_name << "checked variable \"" << name << "\" is_time: " << found << "\n"; } - if (!found && get_nc_att_value(&(*itVar).second, "units", name)) { + if (!found && get_var_units(&(*itVar).second, name)) { if (is_nc_unit_time(name.c_str())) { - if (get_nc_att_value(&(*itVar).second, "axis", name)) { + if (get_nc_att_value(&(*itVar).second, axis_att_name, name)) { if (is_nc_attr_time(name)) found = true; } - else if (get_nc_att_value(&(*itVar).second, "_CoordinateAxisType", name)) { + else if (get_nc_att_value(&(*itVar).second, + coordinate_axis_type_att_name, name)) { if (is_nc_attr_time(name)) found = true; } } @@ -3787,7 +3812,6 @@ NcVar get_nc_var_time(const NcFile *nc) { return var; } - //////////////////////////////////////////////////////////////////////// NcFile *open_ncfile(const char * nc_name, bool write) { @@ -3831,7 +3855,7 @@ unixtime get_reference_unixtime(NcVar *time_var, int &sec_per_unit, ConcatString time_unit_str; static const char *method_name = "get_reference_unixtime() -> "; - if (get_nc_att_value(time_var, (string)"units", time_unit_str)) { + if (get_var_units(time_var, time_unit_str)) { parse_cf_time_string(time_unit_str.c_str(), ref_ut, sec_per_unit); no_leap_year = (86400 == sec_per_unit) ? get_att_no_leap_year(time_var) : false; } diff --git a/src/libcode/vx_nc_util/nc_utils.h b/src/libcode/vx_nc_util/nc_utils.h index 007f17dcea..9db75b08ea 100644 --- a/src/libcode/vx_nc_util/nc_utils.h +++ b/src/libcode/vx_nc_util/nc_utils.h @@ -31,6 +31,7 @@ typedef unsigned char uchar; #include "int_array.h" #include "long_array.h" #include "num_array.h" +#include "nc_var_info.h" //////////////////////////////////////////////////////////////////////// @@ -130,16 +131,21 @@ static const char nc_att_obs_version[] = "MET_Obs_version"; static const char nc_att_met_point_nccf[] = "MET_point_NCCF"; static const string add_offset_att_name = "add_offset"; +static const string axis_att_name = "axis"; +static const string bounds_att_name = "bounds"; +static const string coordinates_att_name = "coordinates"; +static const string coordinate_axis_type_att_name = "_CoordinateAxisType"; static const string description_att_name = "description"; static const string fill_value_att_name = "_FillValue"; -static const string level_att_name = "level"; +static const string grid_mapping_att_name = "grid_mapping"; +static const string grid_mapping_name_att_name = "grid_mapping_name"; static const string long_name_att_name = "long_name"; static const string missing_value_att_name = "missing_value"; -static const string name_att_name = "name"; +static const string projection_att_name = "Projection"; static const string scale_factor_att_name = "scale_factor"; +static const string standard_name_att_name = "standard_name"; static const string units_att_name = "units"; - static const char nc_time_unit_exp[] = "^[a-z|A-Z]* since [0-9]\\{1,4\\}-[0-9]\\{1,2\\}-[0-9]\\{1,2\\}"; static const char MET_NC_Obs_ver_1_2[] = "1.02"; @@ -185,6 +191,7 @@ extern bool get_nc_att_value(const NcVarAtt *, double &, bool exit_on_erro extern bool get_nc_att_value(const NcVar *, const ConcatString &, ConcatString &, bool exit_on_error = false); extern bool get_nc_att_value(const NcVar *, const ConcatString &, int &, bool exit_on_error = false); extern bool get_nc_att_value(const NcVar *, const ConcatString &, float &, bool exit_on_error = false); +extern bool get_nc_att_value(const NcVar *, const ConcatString &, double &, bool exit_on_error = false); extern bool has_att(NcFile *, const ConcatString name, bool exit_on_error=false); extern bool has_att(NcVar *, const ConcatString name, bool do_log=false); @@ -216,10 +223,16 @@ extern int get_var_names(NcFile *, StringArray *varNames); extern bool get_var_att_float (const NcVar *, const ConcatString &, float &); extern bool get_var_att_double(const NcVar *, const ConcatString &, double &); -extern bool get_var_units(const NcVar *, ConcatString &); -extern bool get_var_level(const NcVar *, ConcatString &); -extern double get_var_missing_value(const NcVar *); +template +extern bool get_var_fill_value(const NcVar *var, T &att_val); +extern bool get_var_axis(const NcVar *var, ConcatString &att_val); extern double get_var_fill_value(const NcVar *); +extern bool get_var_grid_mapping(const NcVar *var, ConcatString &att_val); +extern bool get_var_grid_mapping_name(const NcVar *var, ConcatString &att_val); +extern bool get_var_long_name(const NcVar *, ConcatString &); +extern double get_var_missing_value(const NcVar *); +extern bool get_var_standard_name(const NcVar *, ConcatString &); +extern bool get_var_units(const NcVar *, ConcatString &); extern bool args_ok(const LongArray &); @@ -266,12 +279,6 @@ extern bool get_nc_data(NcVar *, float *data, const long *dims, const long *cur extern bool get_nc_data(NcVar *, double *data, const long *dims, const long *curs); extern bool get_nc_data(NcVar *, ncbyte *data, const long *dims, const long *curs); -extern bool get_nc_data(NcFile *, const char *var_name, int *data, const long *dims, const long *curs); -extern bool get_nc_data(NcFile *, const char *var_name, char *data, const long *dims, const long *curs); -extern bool get_nc_data(NcFile *, const char *var_name, float *data, const long *dims, const long *curs); -extern bool get_nc_data(NcFile *, const char *var_name, double *data, const long *dims, const long *curs); -extern bool get_nc_data(NcFile *, const char *var_name, ncbyte *data, const long *dims, const long *curs); - extern bool get_nc_data_to_array(NcVar *, StringArray *); extern bool get_nc_data_to_array(NcFile *, const char *, StringArray *); extern int get_nc_string_length(NcVar *); @@ -313,6 +320,7 @@ extern bool put_nc_data_with_dims(NcVar *, const double *data, const long len0, extern NcVar get_var(NcFile *, const char * var_name); // exit if not exists extern NcVar get_nc_var(NcFile *, const char * var_name, bool log_as_error=false); // continue even though not exists + extern NcVar *copy_nc_var(NcFile *, NcVar *, const int deflate_level=DEF_DEFLATE_LEVEL, const bool all_attrs=true); extern void copy_nc_att(NcFile *, NcVar *, const ConcatString attr_name); extern void copy_nc_att( NcVar *, NcVar *, const ConcatString attr_name); @@ -347,7 +355,7 @@ extern bool get_dim_names(const NcFile *nc, StringArray *dimNames); extern NcVar get_nc_var_lat(const NcFile *nc); extern NcVar get_nc_var_lon(const NcFile *nc); extern NcVar get_nc_var_time(const NcFile *nc); - +extern int get_index_at_nc_data(NcVar *var, double value, const string dim_name, bool is_time=false); extern NcFile* open_ncfile(const char * nc_name, bool write = false); extern int get_data_size(NcVar *); diff --git a/src/libcode/vx_nc_util/nc_var_info.cc b/src/libcode/vx_nc_util/nc_var_info.cc index d41d7c8762..1d3b278103 100644 --- a/src/libcode/vx_nc_util/nc_var_info.cc +++ b/src/libcode/vx_nc_util/nc_var_info.cc @@ -1,5 +1,3 @@ - - // *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* // ** Copyright UCAR (c) 1992 - 2022 // ** University Corporation for Atmospheric Research (UCAR) @@ -9,8 +7,6 @@ // *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* - - //////////////////////////////////////////////////////////////////////// @@ -27,6 +23,8 @@ using namespace std; #include "vx_log.h" #include "vx_cal.h" +//////////////////////////////////////////////////////////////////////// + unixtime get_att_value_unixtime(const NcAtt *att) { ConcatString s; unixtime time_value = -1; @@ -53,7 +51,6 @@ unixtime get_att_value_unixtime(const NcAtt *att) { return time_value; } - //////////////////////////////////////////////////////////////////////// @@ -65,9 +62,7 @@ unixtime get_att_value_unixtime(const NcAtt *att) { //////////////////////////////////////////////////////////////////////// -NcVarInfo::NcVarInfo() - -{ +NcVarInfo::NcVarInfo() { init_from_scratch(); @@ -77,9 +72,7 @@ init_from_scratch(); //////////////////////////////////////////////////////////////////////// -NcVarInfo::~NcVarInfo() - -{ +NcVarInfo::~NcVarInfo() { clear(); @@ -89,9 +82,7 @@ clear(); //////////////////////////////////////////////////////////////////////// -NcVarInfo::NcVarInfo(const NcVarInfo & i) - -{ +NcVarInfo::NcVarInfo(const NcVarInfo & i) { init_from_scratch(); @@ -103,9 +94,7 @@ assign(i); //////////////////////////////////////////////////////////////////////// -NcVarInfo & NcVarInfo::operator=(const NcVarInfo & i) - -{ +NcVarInfo & NcVarInfo::operator=(const NcVarInfo & i) { if ( this == &i ) return ( * this ); @@ -119,9 +108,7 @@ return ( * this ); //////////////////////////////////////////////////////////////////////// -void NcVarInfo::init_from_scratch() - -{ +void NcVarInfo::init_from_scratch() { Dims = (NcDim **) 0; @@ -135,9 +122,7 @@ return; //////////////////////////////////////////////////////////////////////// -void NcVarInfo::clear() - -{ +void NcVarInfo::clear() { var = (NcVar *) 0; // don't delete @@ -175,9 +160,7 @@ return; //////////////////////////////////////////////////////////////////////// -void NcVarInfo::dump(ostream & out, int depth) const - -{ +void NcVarInfo::dump(ostream & out, int depth) const { Indent prefix(depth); @@ -245,9 +228,7 @@ return; //////////////////////////////////////////////////////////////////////// -int NcVarInfo::lead_time() const - -{ +int NcVarInfo::lead_time() const { return ( (int) (ValidTime - InitTime) ); @@ -257,9 +238,7 @@ return ( (int) (ValidTime - InitTime) ); //////////////////////////////////////////////////////////////////////// -void NcVarInfo::assign(const NcVarInfo & i) - -{ +void NcVarInfo::assign(const NcVarInfo & i) { clear(); @@ -316,9 +295,39 @@ return; //////////////////////////////////////////////////////////////////////// -bool get_att_str(const NcVarInfo &info, const ConcatString att_name, ConcatString &att_value) +NcVarInfo *find_var_info_by_dim_name(NcVarInfo *vars, const string dim_name, + const int nvars) { + // Find the variable with the same dimension name + NcVarInfo *var = (NcVarInfo *)NULL; + for (int i = 0; i < nvars; i++) { + if (vars[i].name == dim_name) { + var = &vars[i]; + break; + } + } + + if (!var) { + //StringArray dim_names; + for (int i=0; iputAtt("accum_time_sec", ncInt, accum_sec); + add_att(var, accum_time_att_name, time_str.text()); + var->putAtt(accum_time_sec_att_name, ncInt, accum_sec); } return; diff --git a/src/tools/other/madis2nc/madis2nc.cc b/src/tools/other/madis2nc/madis2nc.cc index f6ba8a6696..ecb537b8a4 100644 --- a/src/tools/other/madis2nc/madis2nc.cc +++ b/src/tools/other/madis2nc/madis2nc.cc @@ -418,19 +418,20 @@ static bool get_filtered_nc_data(NcVar var, float *data, const char *var_name, bool required) { bool status = false; - float in_fill_value; const char *method_name = "get_filtered_nc_data(float) "; if (IS_VALID_NC(var)) { if(status = get_nc_data(&var, data, dim, cur)) { - get_nc_att_value(&var, (string)in_fillValue_str, in_fill_value); - mlog << Debug(5) << " " << method_name << GET_NC_NAME(var) << " " - << in_fillValue_str << "=" << in_fill_value << "\n"; - for (int idx=0; idx init time should be an integer or a string!\n\n"; exit ( 1 ); } - if (att) delete att; - att = get_nc_att(FcstRaw, (string)"valid_time_ut"); - ValidTime = get_att_value_unixtime(att); - if (ValidTime < 0) { + if (!get_att_unixtime(FcstRaw, valid_time_ut_att_name, ValidTime) || ValidTime < 0) { mlog << Error << "ModeNcOutputFile::open(const char *) -> valid time should be an integer or a string!\n\n"; exit ( 1 ); } - if (att) delete att; // att = FcstRaw->get_att("accum_time_sec"); // @@ -1006,6 +1000,3 @@ return ( s ); //////////////////////////////////////////////////////////////////////// - - - diff --git a/src/tools/other/plot_data_plane/plot_data_plane.cc b/src/tools/other/plot_data_plane/plot_data_plane.cc index 1d266bfc40..d5eb23e571 100644 --- a/src/tools/other/plot_data_plane/plot_data_plane.cc +++ b/src/tools/other/plot_data_plane/plot_data_plane.cc @@ -94,7 +94,6 @@ int main(int argc, char * argv[]) { VarInfo * var_ptr = (VarInfo * ) 0; VarInfoFactory v_factory; DataPlane data_plane; - DataPlaneArray data_plane_array; Grid grid; GrdFileType ftype; ColorTable color_table; diff --git a/src/tools/other/plot_point_obs/plot_point_obs.cc b/src/tools/other/plot_point_obs/plot_point_obs.cc index 888b521758..5990a33769 100644 --- a/src/tools/other/plot_point_obs/plot_point_obs.cc +++ b/src/tools/other/plot_point_obs/plot_point_obs.cc @@ -250,7 +250,6 @@ void process_point_obs(const char *point_obs_filename) { obs_qty_block, (char *)0); if (!status) exit(1); - int typ_idx, sid_idx, vld_idx; for(int i_offset=0; i_offset