Branch data Line data Source code
1 : : #include "WriteNC.hpp"
2 : : #include "moab/CN.hpp"
3 : : #include "MBTagConventions.hpp"
4 : : #include "MBParallelConventions.h"
5 : : #include "moab/Interface.hpp"
6 : : #include "moab/Range.hpp"
7 : : #include "moab/WriteUtilIface.hpp"
8 : : #include "moab/FileOptions.hpp"
9 : : #include "NCWriteHelper.hpp"
10 : :
11 : : #include <fstream>
12 : : #include <map>
13 : : #include <set>
14 : :
15 : : #include <iostream>
16 : : #include <sstream>
17 : :
18 : : #ifdef WIN32
19 : : #ifdef size_t
20 : : #undef size_t
21 : : #endif
22 : : #endif
23 : :
24 : : namespace moab
25 : : {
26 : :
27 : 0 : WriterIface* WriteNC::factory( Interface* iface )
28 : : {
29 [ # # ]: 0 : return new WriteNC( iface );
30 : : }
31 : :
32 : 0 : WriteNC::WriteNC( Interface* impl )
33 : : : mbImpl( impl ), dbgOut( stderr ),
34 : : #ifdef MOAB_HAVE_MPI
35 : : myPcomm( NULL ),
36 : : #endif
37 [ # # ][ # # ]: 0 : noMesh( false ), noVars( false ), append( false ), mGlobalIdTag( 0 ), isParallel( false ), myHelper( NULL )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
38 : : {
39 [ # # ]: 0 : assert( impl != NULL );
40 [ # # ]: 0 : impl->query_interface( mWriteIface );
41 : 0 : }
42 : :
43 : 0 : WriteNC::~WriteNC()
44 : : {
45 : 0 : mbImpl->release_interface( mWriteIface );
46 [ # # ][ # # ]: 0 : if( myHelper != NULL ) delete myHelper;
47 [ # # ]: 0 : }
48 : :
49 : : //! Writes out a file
50 : 0 : ErrorCode WriteNC::write_file( const char* file_name, const bool overwrite, const FileOptions& options,
51 : : const EntityHandle* file_set, const int num_set, const std::vector< std::string >&,
52 : : const Tag*, int, int )
53 : : {
54 : : ErrorCode rval;
55 : : // See if opts has variable(s) specified
56 [ # # ]: 0 : std::vector< std::string > var_names;
57 [ # # ]: 0 : std::vector< std::string > desired_names;
58 [ # # ]: 0 : std::vector< int > tstep_nums;
59 [ # # ]: 0 : std::vector< double > tstep_vals;
60 : :
61 : : // Get and cache predefined tag handles
62 [ # # ]: 0 : mGlobalIdTag = mbImpl->globalId_tag();
63 : :
64 : : // num set has to be 1, we will write only one set, the original file set used to load
65 [ # # ][ # # ]: 0 : if( num_set != 1 ) MB_SET_ERR( MB_FAILURE, "We should write only one set (the file set used to read data into)" );
[ # # ][ # # ]
[ # # ][ # # ]
66 : :
67 [ # # ][ # # ]: 0 : rval = parse_options( options, var_names, desired_names, tstep_nums, tstep_vals );MB_CHK_SET_ERR( rval, "Trouble parsing option string" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
68 : :
69 : : // Important to create some data that will be used to write the file; dimensions, variables, etc
70 : : // new variables still need to have some way of defining their dimensions
71 : : // maybe it will be passed as write options
72 [ # # ][ # # ]: 0 : rval = process_conventional_tags( *file_set );MB_CHK_SET_ERR( rval, "Trouble processing conventional tags" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
73 : :
74 : : // Create or append the file
75 [ # # ]: 0 : if( append )
76 [ # # ]: 0 : dbgOut.tprintf( 1, "opening file %s for appending \n", file_name );
77 : : else
78 [ # # ]: 0 : dbgOut.tprintf( 1, "creating file %s\n", file_name );
79 : 0 : fileName = file_name;
80 : : int success;
81 : :
82 [ # # ]: 0 : if( append )
83 : : {
84 : 0 : int omode = NC_WRITE;
85 : : #ifdef MOAB_HAVE_PNETCDF
86 : : if( isParallel )
87 : : success = NCFUNC( open )( myPcomm->proc_config().proc_comm(), file_name, omode, MPI_INFO_NULL, &fileId );
88 : : else
89 : : success = NCFUNC( open )( MPI_COMM_SELF, file_name, omode, MPI_INFO_NULL, &fileId );
90 : : #else
91 : : // This is a regular netcdf file, open in write mode
92 [ # # ]: 0 : success = NCFUNC( open )( file_name, omode, &fileId );
93 : : #endif
94 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Trouble opening file " << file_name << " for appending" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
95 : : }
96 : : else
97 : : { // Case when the file is new, will be overwritten, most likely
98 [ # # ]: 0 : int cmode = overwrite ? NC_CLOBBER : NC_NOCLOBBER;
99 : : #ifdef MOAB_HAVE_PNETCDF
100 : : if( isParallel )
101 : : success = NCFUNC( create )( myPcomm->proc_config().proc_comm(), file_name, cmode, MPI_INFO_NULL, &fileId );
102 : : else
103 : : success = NCFUNC( create )( MPI_COMM_SELF, file_name, cmode, MPI_INFO_NULL, &fileId );
104 : : #else
105 : : // This is a regular netcdf file
106 [ # # ]: 0 : success = NCFUNC( create )( file_name, cmode, &fileId );
107 : : #endif
108 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Trouble creating file " << file_name << " for writing" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
109 : : }
110 : :
111 [ # # ][ # # ]: 0 : if( NULL != myHelper ) delete myHelper;
112 : :
113 : : // Get appropriate helper instance for WriteNC class based on some info in the file set
114 [ # # ]: 0 : myHelper = NCWriteHelper::get_nc_helper( this, fileId, options, *file_set );
115 [ # # ][ # # ]: 0 : if( NULL == myHelper ) { MB_SET_ERR( MB_FAILURE, "Failed to get NCWriteHelper class instance" ); }
[ # # ][ # # ]
[ # # ][ # # ]
116 : :
117 [ # # ][ # # ]: 0 : rval = myHelper->collect_mesh_info();MB_CHK_SET_ERR( rval, "Trouble collecting mesh information" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
118 : :
119 [ # # ][ # # ]: 0 : rval = myHelper->collect_variable_data( var_names, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble collecting variable data" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
120 : :
121 [ # # ][ # # ]: 0 : rval = myHelper->init_file( var_names, desired_names, append );MB_CHK_SET_ERR( rval, "Trouble initializing file" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
122 : :
123 [ # # ][ # # ]: 0 : rval = myHelper->write_values( var_names, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble writing values to file" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
124 : :
125 [ # # ]: 0 : success = NCFUNC( close )( fileId );
126 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Trouble closing file" );
[ # # ][ # # ]
[ # # ][ # # ]
127 : :
128 : 0 : return MB_SUCCESS;
129 : : }
130 : :
131 : 0 : ErrorCode WriteNC::parse_options( const FileOptions& opts, std::vector< std::string >& var_names,
132 : : std::vector< std::string >& desired_names, std::vector< int >& tstep_nums,
133 : : std::vector< double >& tstep_vals )
134 : : {
135 : : int tmpval;
136 [ # # ][ # # ]: 0 : if( MB_SUCCESS == opts.get_int_option( "DEBUG_IO", 1, tmpval ) )
137 : : {
138 [ # # ]: 0 : dbgOut.set_verbosity( tmpval );
139 [ # # ][ # # ]: 0 : dbgOut.set_prefix( "NCWrite" );
140 : : }
141 : :
142 [ # # ]: 0 : ErrorCode rval = opts.get_strs_option( "VARIABLE", var_names );
143 [ # # ]: 0 : if( MB_TYPE_OUT_OF_RANGE == rval )
144 : 0 : noVars = true;
145 : : else
146 : 0 : noVars = false;
147 : :
148 [ # # ]: 0 : rval = opts.get_strs_option( "RENAME", desired_names );
149 [ # # ]: 0 : if( MB_ENTITY_NOT_FOUND == rval )
150 : : {
151 [ # # ]: 0 : if( !noVars )
152 : : {
153 [ # # ]: 0 : desired_names.resize( var_names.size() );
154 [ # # ]: 0 : std::copy( var_names.begin(), var_names.end(), desired_names.begin() );
155 : : }
156 : : }
157 : : // Either way
158 [ # # ]: 0 : assert( desired_names.size() == var_names.size() );
159 : :
160 [ # # ]: 0 : opts.get_ints_option( "TIMESTEP", tstep_nums );
161 [ # # ]: 0 : opts.get_reals_option( "TIMEVAL", tstep_vals );
162 [ # # ]: 0 : rval = opts.get_null_option( "NOMESH" );
163 [ # # ]: 0 : if( MB_SUCCESS == rval ) noMesh = true;
164 : :
165 [ # # ]: 0 : rval = opts.get_null_option( "APPEND" );
166 [ # # ]: 0 : if( MB_SUCCESS == rval ) append = true;
167 : :
168 [ # # ][ # # ]: 0 : if( 2 <= dbgOut.get_verbosity() )
169 : : {
170 [ # # ]: 0 : if( !var_names.empty() )
171 : : {
172 [ # # ]: 0 : std::cerr << "Variables requested: ";
173 [ # # ]: 0 : for( unsigned int i = 0; i < var_names.size(); i++ )
174 [ # # ][ # # ]: 0 : std::cerr << var_names[i];
175 [ # # ]: 0 : std::cerr << std::endl;
176 : : }
177 [ # # ]: 0 : if( !tstep_nums.empty() )
178 : : {
179 [ # # ]: 0 : std::cerr << "Timesteps requested: ";
180 [ # # ]: 0 : for( unsigned int i = 0; i < tstep_nums.size(); i++ )
181 [ # # ][ # # ]: 0 : std::cerr << tstep_nums[i];
182 [ # # ]: 0 : std::cerr << std::endl;
183 : : }
184 [ # # ]: 0 : if( !tstep_vals.empty() )
185 : : {
186 [ # # ]: 0 : std::cerr << "Time vals requested: ";
187 [ # # ]: 0 : for( unsigned int i = 0; i < tstep_vals.size(); i++ )
188 [ # # ][ # # ]: 0 : std::cerr << tstep_vals[i];
189 [ # # ]: 0 : std::cerr << std::endl;
190 : : }
191 : : }
192 : :
193 : : // FIXME: copied from ReadNC, may need revise
194 : : #ifdef MOAB_HAVE_MPI
195 [ # # ]: 0 : isParallel = ( opts.match_option( "PARALLEL", "WRITE_PART" ) != MB_ENTITY_NOT_FOUND );
196 : :
197 [ # # ]: 0 : if( !isParallel )
198 : : // Return success here, since rval still has _NOT_FOUND from not finding option
199 : : // in this case, myPcomm will be NULL, so it can never be used; always check for isParallel
200 : : // before any use for myPcomm
201 : 0 : return MB_SUCCESS;
202 : :
203 : 0 : int pcomm_no = 0;
204 [ # # ]: 0 : rval = opts.get_int_option( "PARALLEL_COMM", pcomm_no );
205 [ # # ][ # # ]: 0 : if( MB_TYPE_OUT_OF_RANGE == rval ) { MB_SET_ERR( rval, "Invalid value for PARALLEL_COMM option" ); }
[ # # ][ # # ]
[ # # ][ # # ]
206 : :
207 [ # # ]: 0 : myPcomm = ParallelComm::get_pcomm( mbImpl, pcomm_no );
208 [ # # ][ # # ]: 0 : if( 0 == myPcomm ) { myPcomm = new ParallelComm( mbImpl, MPI_COMM_WORLD ); }
[ # # ]
209 : :
210 : : #ifndef MOAB_HAVE_PNETCDF
211 [ # # ][ # # ]: 0 : const int procs = myPcomm->proc_config().proc_size();
212 [ # # ]: 0 : if( procs > 1 )
213 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Attempt to launch NC writer in parallel without pnetcdf support" ); }
[ # # ][ # # ]
[ # # ]
214 : : #endif
215 : :
216 [ # # ][ # # ]: 0 : const int rank = myPcomm->proc_config().proc_rank();
217 [ # # ]: 0 : dbgOut.set_rank( rank );
218 : : #endif
219 : :
220 : 0 : return MB_SUCCESS;
221 : : }
222 : :
223 : : // This is the inverse process to create conventional tags
224 : : // Will look at <pargal_source>/src/core/fileinfo.cpp, init dim, vars, atts
225 : 0 : ErrorCode WriteNC::process_conventional_tags( EntityHandle fileSet )
226 : : {
227 : : ErrorCode rval;
228 : :
229 : : // Start copy
230 : 0 : Tag dimNamesTag = 0;
231 [ # # ]: 0 : std::string tag_name = "__DIM_NAMES";
232 : 0 : const void* data = NULL;
233 : 0 : int dimNamesSz = 0;
234 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, dimNamesTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
235 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_by_ptr( dimNamesTag, &fileSet, 1, &data, &dimNamesSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
236 : 0 : const char* p = static_cast< const char* >( data );
237 [ # # ]: 0 : dbgOut.tprintf( 1, "__DIM_NAMES tag has string length %d\n", dimNamesSz );
238 : :
239 : 0 : std::size_t start = 0;
240 : :
241 : 0 : Tag dimLensTag = 0;
242 [ # # ]: 0 : tag_name = "__DIM_LENS";
243 : 0 : data = NULL;
244 : 0 : int dimLensSz = 0;
245 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_INTEGER, dimLensTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
246 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_by_ptr( dimLensTag, &fileSet, 1, &data, &dimLensSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
247 : 0 : const int* int_p = static_cast< const int* >( data );
248 [ # # ]: 0 : dbgOut.tprintf( 1, "__DIM_LENS tag has %d values\n", dimLensSz );
249 : :
250 : 0 : int idxDim = 0;
251 : : // Dim names are separated by '\0' in the string of __DIM_NAMES tag
252 [ # # ]: 0 : for( std::size_t i = 0; i != static_cast< std::size_t >( dimNamesSz ); i++ )
253 : : {
254 [ # # ]: 0 : if( p[i] == '\0' )
255 : : {
256 [ # # ]: 0 : std::string dim_name( &p[start], i - start );
257 : 0 : int len = int_p[idxDim];
258 [ # # ]: 0 : dimNames.push_back( dim_name );
259 [ # # ]: 0 : dimLens.push_back( len );
260 [ # # ]: 0 : dbgOut.tprintf( 2, "Dimension %s has length %d\n", dim_name.c_str(), len );
261 : : // FIXME: Need info from moab to set unlimited dimension
262 : : // Currently assume each file has the same number of time dimensions
263 : : /*if ((dim_name == "time") || (dim_name == "Time"))
264 : : insert(dim_name, *(new pcdim(dim_name, len * m_file_names.size(), true)));
265 : : else
266 : : insert(dim_name, *(new pcdim(dim_name, len)));*/
267 : 0 : start = i + 1;
268 : 0 : idxDim++;
269 : : }
270 : : }
271 : :
272 : 0 : Tag meshTypeTag = 0;
273 [ # # ]: 0 : tag_name = "__MESH_TYPE";
274 : 0 : data = NULL;
275 : 0 : int meshTypeSz = 0;
276 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, meshTypeTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
277 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_by_ptr( meshTypeTag, &fileSet, 1, &data, &meshTypeSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
278 : 0 : p = static_cast< const char* >( data );
279 [ # # ][ # # ]: 0 : grid_type = std::string( &p[0], meshTypeSz );
280 [ # # ]: 0 : dbgOut.tprintf( 2, "Mesh type: %s\n", grid_type.c_str() );
281 : :
282 : : // Read <__VAR_NAMES_LOCATIONS> tag
283 : 0 : Tag varNamesLocsTag = 0;
284 [ # # ]: 0 : tag_name = "__VAR_NAMES_LOCATIONS";
285 : 0 : data = NULL;
286 : 0 : int varNamesLocsSz = 0;
287 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_INTEGER, varNamesLocsTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
288 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_by_ptr( varNamesLocsTag, &fileSet, 1, &data, &varNamesLocsSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
289 : 0 : int_p = static_cast< const int* >( data );
290 [ # # ]: 0 : std::vector< int > varNamesLocs( varNamesLocsSz );
291 [ # # ]: 0 : std::copy( int_p, int_p + varNamesLocsSz, varNamesLocs.begin() );
292 : :
293 : 0 : Tag varNamesTag = 0;
294 [ # # ]: 0 : tag_name = "__VAR_NAMES";
295 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, varNamesTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
296 : 0 : data = NULL;
297 : 0 : int varNamesSz = 0;
298 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_by_ptr( varNamesTag, &fileSet, 1, &data, &varNamesSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
299 [ # # ]: 0 : dbgOut.tprintf( 2, "__VAR_NAMES tag has string length %d\n", varNamesSz );
300 : 0 : p = static_cast< const char* >( data );
301 : :
302 : 0 : start = 0;
303 : 0 : int idxVar = 0;
304 : : int sz;
305 : : // Var names are separated by '\0' in the string of __VAR_NAMES tag
306 [ # # ]: 0 : for( std::size_t i = 0; i != static_cast< std::size_t >( varNamesSz ); i++ )
307 : : {
308 [ # # ]: 0 : if( p[i] == '\0' )
309 : : {
310 [ # # ]: 0 : std::string var_name( &p[start], i - start );
311 : :
312 [ # # ]: 0 : dbgOut.tprintf( 2, "var name: %s index %d \n", var_name.c_str(), idxVar );
313 : : // Process var name:
314 : : // This will create/initiate map; we will populate variableDataStruct with info about
315 : : // dims, tags, etc reference & is important; otherwise variableDataStruct will go out of
316 : : // scope, and deleted :(
317 [ # # ]: 0 : VarData& variableDataStruct = varInfo[var_name];
318 [ # # ]: 0 : variableDataStruct.varName = var_name;
319 [ # # ]: 0 : variableDataStruct.entLoc = varNamesLocs[idxVar];
320 : :
321 [ # # ]: 0 : dbgOut.tprintf( 2, "at var name %s varInfo size %d \n", var_name.c_str(), (int)varInfo.size() );
322 : :
323 : 0 : sz = 0;
324 : 0 : Tag dims_tag = 0;
325 [ # # ][ # # ]: 0 : std::string dim_names = "__" + var_name + "_DIMS";
[ # # # ]
326 [ # # ]: 0 : rval = mbImpl->tag_get_handle( dim_names.c_str(), 0, MB_TYPE_OPAQUE, dims_tag, MB_TAG_ANY );
327 [ # # ]: 0 : if( MB_SUCCESS != rval )
328 : : {
329 [ # # ]: 0 : if( MB_TAG_NOT_FOUND == rval )
330 : : {
331 [ # # ]: 0 : dbgOut.tprintf( 2, "tag : %s not found, continue \n", dim_names.c_str() );
332 : 0 : start = i + 1;
333 : 0 : idxVar++;
334 : 0 : continue;
335 : : }
336 [ # # ][ # # ]: 0 : MB_SET_ERR( rval, "Trouble getting conventional tag " << dim_names );
[ # # ][ # # ]
[ # # ][ # # ]
337 : : }
338 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_length( dims_tag, sz );MB_CHK_SET_ERR( rval, "Trouble getting size of dimensions for variable " << var_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
339 : 0 : sz /= sizeof( Tag ); // The type is MB_TYPE_OPAQUE, but it is a list of tags, so we
340 : : // need to divide by the size of Tag
341 : : // sz is used for number of dimension tags in this list
342 [ # # ]: 0 : dbgOut.tprintf( 2, "var name: %s has %d dimensions \n", var_name.c_str(), sz );
343 : :
344 [ # # ]: 0 : variableDataStruct.varDims.resize( sz );
345 : 0 : const void* ptr = NULL;
346 [ # # ]: 0 : rval = mbImpl->tag_get_by_ptr( dims_tag, &fileSet, 1, &ptr );
347 : :
348 : 0 : const Tag* ptags = static_cast< const moab::Tag* >( ptr );
349 [ # # ]: 0 : for( std::size_t j = 0; j != static_cast< std::size_t >( sz ); j++ )
350 : : {
351 [ # # ]: 0 : std::string dim_name;
352 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_name( ptags[j], dim_name );MB_CHK_SET_ERR( rval, "Trouble getting dimension of variable " << var_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
353 [ # # ]: 0 : dbgOut.tprintf( 2, "var name: %s has %s as dimension \n", var_name.c_str(), dim_name.c_str() );
354 [ # # ]: 0 : std::vector< std::string >::iterator vit = std::find( dimNames.begin(), dimNames.end(), dim_name );
355 [ # # ][ # # ]: 0 : if( vit == dimNames.end() )
356 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Dimension " << dim_name << " not found for variable " << var_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
357 [ # # ][ # # ]: 0 : variableDataStruct.varDims[j] = (int)( vit - dimNames.begin() ); // Will be used for writing
[ # # ]
358 : : // This will have to change to actual file dimension, for writing
359 : 0 : }
360 : :
361 : : // Attributes for this variable
362 [ # # ][ # # ]: 0 : std::stringstream ssTagName;
[ # # # ]
363 [ # # ][ # # ]: 0 : ssTagName << "__" << var_name << "_ATTRIBS";
[ # # ]
364 [ # # ][ # # ]: 0 : tag_name = ssTagName.str();
365 : 0 : Tag varAttTag = 0;
366 : : rval =
367 [ # # ][ # # ]: 0 : mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, varAttTag, MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
368 : 0 : const void* varAttPtr = NULL;
369 : 0 : int varAttSz = 0;
370 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_by_ptr( varAttTag, &fileSet, 1, &varAttPtr, &varAttSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
371 [ # # ][ # # ]: 0 : if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Tag retrieved for variable %s\n", tag_name.c_str() );
372 : :
373 [ # # ][ # # ]: 0 : std::string attribString( (char*)varAttPtr, (char*)varAttPtr + varAttSz );
374 [ # # ][ # # ]: 0 : if( attribString == "NO_ATTRIBS" )
375 : : {
376 : : // This variable has no attributes
377 : 0 : variableDataStruct.numAtts = 0;
378 : : }
379 [ # # ][ # # ]: 0 : else if( attribString == "DUMMY_VAR" )
380 : : {
381 : : // This variable is a dummy coordinate variable
382 : 0 : variableDataStruct.numAtts = 0;
383 [ # # ]: 0 : dummyVarNames.insert( variableDataStruct.varName );
384 : : }
385 : : else
386 : : {
387 [ # # ]: 0 : ssTagName << "_LEN";
388 [ # # ][ # # ]: 0 : tag_name = ssTagName.str();
389 : 0 : Tag varAttLenTag = 0;
390 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_INTEGER, varAttLenTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
391 : 0 : int varAttLenSz = 0;
392 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_length( varAttLenTag, varAttLenSz );MB_CHK_SET_ERR( rval, "Trouble getting length of conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
393 [ # # ]: 0 : std::vector< int > varAttLen( varAttLenSz );
394 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_data( varAttLenTag, &fileSet, 1, &varAttLen[0] );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
395 : :
396 [ # # ][ # # ]: 0 : rval = process_concatenated_attribute( varAttPtr, varAttSz, varAttLen, variableDataStruct.varAtts );MB_CHK_SET_ERR( rval, "Trouble processing attributes of variable " << var_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
397 : :
398 [ # # ][ # # ]: 0 : if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Tag metadata for variable %s\n", tag_name.c_str() );
[ # # ]
399 : : }
400 : : // End attribute
401 : :
402 : 0 : start = i + 1;
403 [ # # ]: 0 : idxVar++;
404 : : } // if (p[i] == '\0')
405 : : }
406 : :
407 : : // Global attributes
408 [ # # ]: 0 : tag_name = "__GLOBAL_ATTRIBS";
409 : 0 : Tag globalAttTag = 0;
410 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, globalAttTag, MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
411 [ # # ]: 0 : std::vector< int > gattLen;
412 : :
413 : 0 : const void* gattptr = NULL;
414 : 0 : int globalAttSz = 0;
415 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_by_ptr( globalAttTag, &fileSet, 1, &gattptr, &globalAttSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
416 : :
417 [ # # ][ # # ]: 0 : if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Tag value retrieved for %s size %d\n", tag_name.c_str(), globalAttSz );
418 : :
419 : : // <__GLOBAL_ATTRIBS_LEN>
420 [ # # ]: 0 : tag_name = "__GLOBAL_ATTRIBS_LEN";
421 : 0 : Tag globalAttLenTag = 0;
422 : :
423 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_INTEGER, globalAttLenTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
424 : 0 : int sizeGAtt = 0;
425 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_length( globalAttLenTag, sizeGAtt );MB_CHK_SET_ERR( rval, "Trouble getting length of conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
426 [ # # ]: 0 : gattLen.resize( sizeGAtt );
427 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_data( globalAttLenTag, &fileSet, 1, &gattLen[0] );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
428 [ # # ][ # # ]: 0 : if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Tag retrieved for variable %s\n", tag_name.c_str() );
429 : :
430 [ # # ][ # # ]: 0 : rval = process_concatenated_attribute( gattptr, globalAttSz, gattLen, globalAtts );MB_CHK_SET_ERR( rval, "Trouble processing global attributes" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
431 : :
432 : 0 : return MB_SUCCESS;
433 : : }
434 : :
435 : : // Reverse process from create_attrib_string
436 : 0 : ErrorCode WriteNC::process_concatenated_attribute( const void* attPtr, int attSz, std::vector< int >& attLen,
437 : : std::map< std::string, AttData >& attributes )
438 : : {
439 : 0 : std::size_t start = 0;
440 : 0 : std::size_t att_counter = 0;
441 [ # # ]: 0 : std::string concatString( (char*)attPtr, (char*)attPtr + attSz );
442 : :
443 [ # # ]: 0 : for( std::size_t i = 0; i != (size_t)attSz; i++ )
444 : : {
445 [ # # ][ # # ]: 0 : if( concatString[i] == '\0' )
446 : : {
447 [ # # ][ # # ]: 0 : std::string att_name( &concatString[start], i - start );
448 : 0 : start = i + 1;
449 [ # # ][ # # ]: 0 : while( concatString[i] != ';' )
450 : 0 : ++i;
451 [ # # ][ # # ]: 0 : std::string data_type( &concatString[start], i - start );
[ # # ]
452 : 0 : ++i;
453 : 0 : start = i;
454 [ # # ]: 0 : i = attLen[att_counter];
455 [ # # ][ # # ]: 0 : if( concatString[i] != ';' ) MB_SET_ERR( MB_FAILURE, "Error parsing attributes" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
456 : :
457 [ # # ][ # # ]: 0 : std::string data_val( &concatString[start], i - start );
[ # # ]
458 : 0 : start = i + 1;
459 : :
460 [ # # ]: 0 : AttData& attrib = attributes[att_name];
461 [ # # ]: 0 : attrib.attValue = data_val;
462 : 0 : attrib.attLen = data_val.size();
463 : :
464 [ # # ][ # # ]: 0 : if( data_type == "char" )
465 : 0 : attrib.attDataType = NC_CHAR;
466 [ # # ][ # # ]: 0 : else if( data_type == "double" )
467 : 0 : attrib.attDataType = NC_DOUBLE;
468 [ # # ][ # # ]: 0 : else if( data_type == "float" )
469 : 0 : attrib.attDataType = NC_FLOAT;
470 [ # # ][ # # ]: 0 : else if( data_type == "int" )
471 : 0 : attrib.attDataType = NC_INT;
472 [ # # ][ # # ]: 0 : else if( data_type == "short" )
473 : 0 : attrib.attDataType = NC_SHORT;
474 : :
475 : 0 : ++att_counter;
476 [ # # ]: 0 : dbgOut.tprintf( 2, " Process attribute %s with value %s \n", att_name.c_str(), data_val.c_str() );
477 : : }
478 : : }
479 : :
480 : 0 : return MB_SUCCESS;
481 : : }
482 : :
483 [ + - ][ + - ]: 228 : } // namespace moab
|