28
28
netcdf::netcdf ()
29
29
{
30
30
_is_open = false ;
31
+ _datetime_field=" " ;
31
32
}
32
33
netcdf::~netcdf ()
33
34
{
@@ -100,55 +101,95 @@ void netcdf::open(const std::string &file)
100
101
{
101
102
_data.open (file.c_str (), netCDF::NcFile::read);
102
103
}
104
+
105
+ std::string netcdf::find_coord_by_standard_name (const std::string& standard_name) const
106
+ {
107
+ for (auto & itr : _data.getCoordVars ())
108
+ {
109
+ auto var = _data.getVar (itr.first );
110
+ auto standardNameAtt = var.getAtt (" standard_name" );
111
+ if (standardNameAtt.isNull ())
112
+ continue ;
113
+
114
+ std::string std_name;
115
+ standardNameAtt.getValues (std_name);
116
+ if (std_name == standard_name)
117
+ {
118
+ return itr.first ;
119
+ }
120
+ }
121
+
122
+ // if we get here, we didn't find what we were looking for
123
+ CHM_THROW_EXCEPTION (forcing_error, " Could not find coordinate variable for " + standard_name);
124
+
125
+ }
126
+
127
+ std::string netcdf::find_dim_by_standard_name (const std::string& standard_name) const
128
+ {
129
+ for (auto & itr : _data.getDims ())
130
+ {
131
+ auto var = _data.getVar (itr.first );
132
+ auto standardNameAtt = var.getAtt (" standard_name" );
133
+ if (standardNameAtt.isNull ())
134
+ continue ;
135
+
136
+ std::string std_name;
137
+ standardNameAtt.getValues (std_name);
138
+ if (std_name == standard_name)
139
+ {
140
+ return itr.first ;
141
+ }
142
+ }
143
+
144
+ // if we get here, we didn't find what we were looking for
145
+ CHM_THROW_EXCEPTION (forcing_error, " Could not find coordinate variable for " + standard_name);
146
+
147
+ }
148
+
103
149
void netcdf::open_GEM (const std::string &file)
104
150
{
105
151
_data.open (file.c_str (), netCDF::NcFile::read);
106
152
107
153
// gem netcdf files have 1 coordinate, datetime
108
154
109
- // for (auto& itr : _data.getVars())
110
- // {
111
- // LOG_DEBUG << itr.first;
112
- // }
113
- //
114
- // SPDLOG_DEBUG("-----");
115
- // for (auto& itr : _data.getCoordVars())
116
- // {
117
- // LOG_DEBUG << itr.first;
118
- // }
119
- // SPDLOG_DEBUG("-----");
120
- // for (auto& itr : _data.getDims())
121
- // {
122
- // LOG_DEBUG << itr.first;
123
- // }
155
+ SPDLOG_DEBUG (" NC getVars:" );
156
+ for (auto & itr : _data.getVars ())
157
+ {
158
+ SPDLOG_DEBUG (" \t " +itr.first );
159
+ }
160
+
161
+ SPDLOG_DEBUG (" NC getCoordVars" );
162
+ for (auto & itr : _data.getCoordVars ())
163
+ {
164
+ SPDLOG_DEBUG (" \t " +itr.first );
165
+ }
166
+ SPDLOG_DEBUG (" Nc getDims" );
167
+ for (auto & itr : _data.getDims ())
168
+ {
169
+ SPDLOG_DEBUG (" \t " +itr.first );
170
+ }
171
+
124
172
auto coord_vars = _data.getCoordVars ();
125
173
126
174
// a few NC have time as a variable and not a coordinate variable so look for time/datetime there
127
175
if (coord_vars.size () == 0 )
128
176
{
129
177
CHM_THROW_EXCEPTION (forcing_error," Netcdf file does not have a coordinate variable defined." );
130
178
}
131
- _datetime_field = " datetime" ;
179
+
180
+ _datetime_field = find_coord_by_standard_name (" time" );
181
+ SPDLOG_DEBUG (" Found time coordinate variable: " + _datetime_field);
132
182
133
183
try
134
184
{
135
185
_datetime_length = coord_vars[_datetime_field].getDim (_datetime_field).getSize ();
136
186
}
137
187
catch (netCDF::exceptions::NcNullGrp& e)
138
188
{
139
- _datetime_field = " time" ;
140
- try {
141
- _datetime_length = coord_vars[_datetime_field].getDim (_datetime_field).getSize ();
142
- }
143
- catch (netCDF::exceptions::NcNullGrp& e)
144
- {
145
- SPDLOG_ERROR (" Tried datetime and time, coord not found" );
146
- throw e;
147
- }
148
-
189
+ SPDLOG_ERROR (" Could not find datetime coordinate" );
190
+ throw ;
149
191
}
150
192
151
-
152
193
// if we don't have at least two timesteps, we can't figure out the model internal timestep length (dt)
153
194
if (_datetime_length == 1 )
154
195
{
@@ -168,22 +209,47 @@ void netcdf::open_GEM(const std::string &file)
168
209
169
210
netCDF::NcVar times = _data.getVar (_datetime_field);
170
211
171
- if (times.getType ().getName () != " int64" )
212
+ // load in the time offsets
213
+ auto * dt = new int64_t [_datetime_length];
214
+
215
+ if (times.getType ().getName () == " int64" )
172
216
{
173
- CHM_THROW_EXCEPTION (forcing_error, " Datetime dimension not in int64 format " );
217
+ times. getVar (dt );
174
218
}
219
+ else if (times.getType ().getName () == " double" )
220
+ {
221
+ auto * tmp_dt = new double [_datetime_length];
222
+ times.getVar (tmp_dt);
175
223
224
+ for (int i = 0 ; i < _datetime_length; i++)
225
+ {
226
+ dt[i] = static_cast <int64_t >(tmp_dt[i]);
227
+ }
176
228
177
- // load in the time offsets
178
- int64_t * dt = new int64_t [_datetime_length];
179
- times.getVar (dt);
229
+ delete[] tmp_dt;
230
+ }
231
+ else
232
+ {
233
+ CHM_THROW_EXCEPTION (forcing_error, " Datetime dimension not in int64 or double type. Type is: " + times.getType ().getName ());
234
+ }
180
235
181
236
// figure out what the epoch is
182
237
// we are expecting the units attribute data to look like
183
238
// hours since 2018-01-05 01:00:00
184
239
std::string epoch;
185
240
auto a = times.getAtt (" units" );
186
- a.getValues (epoch);
241
+
242
+ try
243
+ {
244
+ // SPDLOG_DEBUG(times.getAtt("units").getType().getName());
245
+ a.getValues (epoch);
246
+ }
247
+ catch (...)
248
+ {
249
+ SPDLOG_ERROR (" Datetime attributes are likely string attributes. Did you write this netcdf with xarray with engine=h5netcdf? Try engine=netcdf4" );
250
+ CHM_THROW_EXCEPTION (forcing_error, " Datetime string attributes not supported" );
251
+ }
252
+
187
253
188
254
189
255
if ( epoch.find (" hours" ) != std::string::npos )
@@ -206,15 +272,14 @@ void netcdf::open_GEM(const std::string &file)
206
272
207
273
} else
208
274
{
209
- CHM_THROW_EXCEPTION (forcing_error, " Unknown datetime epoch offset unit. " );
275
+ CHM_THROW_EXCEPTION (forcing_error, " Unknown datetime epoch offset unit: " + epoch );
210
276
}
211
277
212
278
std::vector<std::string> strs;
213
279
boost::split (strs, epoch, boost::is_any_of (" " ));
214
280
215
281
if (strs.size () != 4 )
216
282
{
217
-
218
283
// might be in iso format (2017-08-13T01:00:00)
219
284
if (strs.size () != 3 )
220
285
{
@@ -245,8 +310,6 @@ void netcdf::open_GEM(const std::string &file)
245
310
{
246
311
CHM_THROW_EXCEPTION (forcing_error, " Unable to parse netcdf epoch time " + s);
247
312
}
248
-
249
-
250
313
}
251
314
else
252
315
{
@@ -294,17 +357,13 @@ void netcdf::open_GEM(const std::string &file)
294
357
SPDLOG_DEBUG (" NetCDF end is {}" ,boost::posix_time::to_simple_string (_end));
295
358
SPDLOG_DEBUG (" NetCDF timestep is {}" , boost::posix_time::to_simple_string (_timestep));
296
359
297
- auto dims = _data.getDims ();
298
- for (auto itr : dims)
299
- {
300
- if (itr.first == " xgrid_0" )
301
- xgrid = itr.second .getSize ();
302
- else if (itr.first == " ygrid_0" )
303
- ygrid = itr.second .getSize ();
304
- }
360
+ _lat_field = find_dim_by_standard_name (" latitude" );
361
+ _lon_field = find_dim_by_standard_name (" longitude" );
305
362
306
- SPDLOG_DEBUG (" NetCDF grid is {} (x) by {} (y)" , xgrid, ygrid);
363
+ xgrid = _data.getDim (_lon_field).getSize ();
364
+ ygrid = _data.getDim (_lat_field).getSize ();
307
365
366
+ SPDLOG_DEBUG (" NetCDF grid is {} (x) by {} (y)" , xgrid, ygrid);
308
367
309
368
}
310
369
@@ -338,7 +397,7 @@ std::set<std::string> netcdf::get_variable_names()
338
397
{
339
398
auto vars = _data.getVars ();
340
399
341
- std::vector<std::string> exclude = {" datetime" ," leadtime" , " reftime" , " HGT_P0_L1_GST" , " gridlat_0 " , " gridlon_0 " , " xgrid_0" , " ygrid_0" };
400
+ std::vector<std::string> exclude = {" datetime" ," leadtime" , " reftime" , " HGT_P0_L1_GST" , _lat_field, _lon_field , " xgrid_0" , " ygrid_0" };
342
401
343
402
for (auto itr: vars)
344
403
{
@@ -464,11 +523,11 @@ double netcdf::get_var2D(std::string var, size_t x, size_t y)
464
523
465
524
netcdf::data netcdf::get_lat ()
466
525
{
467
- return get_var2D (" gridlat_0 " );
526
+ return get_var2D (_lat_field );
468
527
}
469
528
netcdf::data netcdf::get_lon ()
470
529
{
471
- return get_var2D (" gridlon_0 " );
530
+ return get_var2D (_lon_field );
472
531
}
473
532
474
533
size_t netcdf::get_xsize ()
@@ -482,11 +541,11 @@ size_t netcdf::get_ysize()
482
541
483
542
double netcdf::get_lat (size_t x, size_t y)
484
543
{
485
- return get_var2D (" gridlat_0 " ,x,y);
544
+ return get_var2D (_lat_field ,x,y);
486
545
}
487
546
double netcdf::get_lon (size_t x, size_t y)
488
547
{
489
- return get_var2D (" gridlon_0 " ,x,y);
548
+ return get_var2D (_lon_field ,x,y);
490
549
}
491
550
492
551
double netcdf::get_z (size_t x, size_t y)
0 commit comments