Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
VisTags.cpp File Reference

Example demonstrating visualization of multi-level tags from climate data. More...

#include <iostream>
#include <vector>
#include <sstream>
#include <string>
#include "moab/Core.hpp"
#include "MBTagConventions.hpp"
#include "moab/FileOptions.hpp"
+ Include dependency graph for VisTags.cpp:

Go to the source code of this file.

Functions

int main (int argc, char **argv)
 

Detailed Description

Example demonstrating visualization of multi-level tags from climate data.

This example shows how to:

  • Load climate data files (NetCDF format) with multi-level tags
  • Extract specific tags and levels for visualization
  • Convert multi-level tags to individual dense tags
  • Handle time-indexed tags (e.g., T0, U0)
  • Write visualization-ready VTK files
  • Process tags on entities of specified dimension

This tool is particularly useful for climate data analysis where variables have multiple levels (e.g., atmospheric pressure levels).

Author
MOAB Development Team
Date
2024

tool for visualizing multi level tags
To run: VisTags inp_file outfile -O read_opts -t tags -l levels -d dim
In this example, it is shown how to create some simple tags for those tags that come from climate data, multiple levels. you can read directly nc data, or *.h5m file that will have the tag with multi levels output will be a vtk file with dense tags of form tag_name_<level> the tag name might contain a time index too, like T0 or U0 tag is a list of tags, separated by commas, no spaces levels is a list of levels, separated by commas, no spaces dimension of entities with the tags will be specified with -d (default 2)

an example of use

VisTags gcrm_r3.nc out.vtk -O VARIABLE=u -t u0,u1 -l 0,1,2 -d 2 (we knew that it had variable u in the file, that it had 256 levels, that there are 2 time steps, etc)

or VisTags gcrm_r3.nc out.vtk -t u0 -l 0,1,2 -d 2 (it will read all variables, but we need to know that u0 will be created as a tag)

the out.vtk file will contain u0_0, u0_1, as simple dense double tags

Parameters
argcNumber of command line arguments
argvCommand line arguments array
Returns
0 on success, 1 on failure

Definition in file VisTags.cpp.

Function Documentation

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 64 of file VisTags.cpp.

65 {
66 #ifdef MOAB_HAVE_NETCDF
67 
68 #ifdef MOAB_HAVE_MPI
69  MPI_Init( &argc, &argv );
70 #endif
71 
72  ErrorCode rval;
73  string file_input, file_output;
74  string read_opts, tags; // Tags to write, separated by commas; it is the name of the tag
75  if( argc < 2 )
76  {
77  file_input = string( MESH_DIR ) + string( "/io/gcrm_r3.nc" );
78  file_output = "VisTagsOut.vtk";
79  }
80  else
81  {
82  file_input = argv[1];
83  file_output = argv[2];
84  }
85  read_opts = "";
86  tags = "";
87 
88  // Instantiate
89  Interface* mb = new( std::nothrow ) Core;
90  if( NULL == mb ) return 1;
91 
92  int dimension = 2;
93  // In MOAB, it may have index after reading (T0, T1, etc)
94  char* levels = NULL; // Levels, separated by commas, no spaces (like 0, 1, 19)
95  if( argc > 3 )
96  {
97  int index = 3;
98  while( index < argc )
99  {
100  if( !strcmp( argv[index], "-O" ) ) // This is for reading options, optional
101  read_opts = argv[++index];
102  if( !strcmp( argv[index], "-t" ) ) tags = argv[++index];
103  if( !strcmp( argv[index], "-l" ) ) levels = argv[++index];
104  if( !strcmp( argv[index], "-d" ) ) dimension = atoi( argv[++index] );
105  index++;
106  }
107  }
108 
109  ostringstream opts;
110  opts << ";;TAGS=" << tags << ";LEVELS=" << levels << "\0";
111  FileOptions fo( opts.str().c_str() );
112 
113  vector< string > tagsNames;
114  vector< int > levelsArray;
115  fo.get_strs_option( "TAGS", tagsNames );
116  fo.get_ints_option( "LEVELS", levelsArray );
117 
118  // Load the input file with the specified options
119  MB_CHK_SET_ERR( mb->load_file( file_input.c_str(), 0, read_opts.c_str() ), "not loading file" );
120 
121  Range ents;
122  MB_CHK_SET_ERR( mb->get_entities_by_dimension( 0, dimension, ents ), "not getting ents" );
123 
124  // Now create double tags for entities of dimension
125  for( size_t i = 0; i < tagsNames.size(); i++ )
126  {
127  string tagName = tagsNames[i];
128  Tag tagh;
129  rval = mb->tag_get_handle( tagName.c_str(), tagh );
130  if( MB_SUCCESS != rval )
131  {
132  cout << "not getting tag " << tagName.c_str() << "\n";
133  continue;
134  }
135 
136  int len = 0;
137  rval = mb->tag_get_length( tagh, len );
138  if( MB_SUCCESS != rval )
139  {
140  cout << "not getting tag len " << tagName.c_str() << "\n";
141  continue;
142  }
143 
144  DataType type;
145  rval = mb->tag_get_data_type( tagh, type );
146  if( MB_SUCCESS != rval )
147  {
148  cout << "not getting tag type " << tagName.c_str() << "\n";
149  continue;
150  }
151 
152  int count;
153  void* dataptr; // Assume double tags, for simplicity
154  rval = mb->tag_iterate( tagh, ents.begin(), ents.end(), count, dataptr );
155  if( MB_SUCCESS != rval || count != (int)ents.size() )
156  {
157  cout << "not getting tag iterate right " << tagName.c_str() << "\n";
158  continue;
159  }
160 
161  // Now create a new tag, with a new name, concatenated, and copy data there , for each level
162  for( size_t j = 0; j < levelsArray.size(); j++ )
163  {
164  int level = levelsArray[j];
165  if( level >= len )
166  {
167  cout << "level too big at " << level << "\n";
168  continue;
169  }
170 
171  ostringstream newTagName;
172  newTagName << tagName << "_" << level;
173  Tag newTagh;
174  rval = mb->tag_get_handle( newTagName.str().c_str(), 1, type, newTagh, MB_TAG_DENSE | MB_TAG_CREAT );
175  if( MB_SUCCESS != rval )
176  {
177  cout << "not getting new tag " << newTagName.str() << "\n";
178  continue;
179  }
180 
181  void* newDataPtr;
182  rval = mb->tag_iterate( newTagh, ents.begin(), ents.end(), count, newDataPtr );
183  if( MB_SUCCESS != rval || count != (int)ents.size() )
184  {
185  cout << "not getting new tag iterate " << newTagName.str() << "\n";
186  continue;
187  }
188 
189  if( MB_TYPE_DOUBLE == type )
190  {
191  double* ptrD = (double*)newDataPtr;
192  double* oldData = (double*)dataptr;
193  for( int k = 0; k < count; k++, ptrD++ )
194  *ptrD = oldData[level + count * k];
195  }
196  } // for (size_t j = 0; j < levelsArray.size(); j++)
197 
198  mb->tag_delete( tagh ); // No need for the tag anymore, write it to the new file
199  } // for (size_t i = 0; i < tagsNames.size(); i++)
200 
201  MB_CHK_SET_ERR( mb->write_file( file_output.c_str() ), "Can't write file " << file_output );
202  cout << "Successfully wrote file " << file_output << "\n";
203 
204  delete mb;
205 
206 #ifdef MOAB_HAVE_MPI
207  MPI_Finalize();
208 #endif
209 #else
210  std::cout << " configure with netcdf for this example to work\n";
211 #endif
212  return 0;
213 }

References moab::Range::begin(), moab::Range::end(), ErrorCode, moab::Core::get_entities_by_dimension(), moab::FileOptions::get_ints_option(), moab::FileOptions::get_strs_option(), moab::index, moab::Core::load_file(), mb, MB_CHK_SET_ERR, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_DENSE, MB_TYPE_DOUBLE, MESH_DIR, moab::Range::size(), moab::Core::tag_delete(), moab::Core::tag_get_data_type(), moab::Core::tag_get_handle(), moab::Core::tag_get_length(), moab::Core::tag_iterate(), and moab::Core::write_file().