version  0.0.1
Defines the C++ API for MsPASS
Public Member Functions | List of all members
mspass::utility::MetadataDefinitions Class Reference

Define properties of Metadata known to mspass. More...

#include <MetadataDefinitions.h>

Public Member Functions

 MetadataDefinitions ()
 
 MetadataDefinitions (const std::string mdname)
 Construct from a namespace title. More...
 
 MetadataDefinitions (const std::string mdname, const mspass::utility::MDDefFormat form)
 Construct from a file with variable formats. More...
 
 MetadataDefinitions (const MetadataDefinitions &parent)
 
bool is_defined (const std::string key) const noexcept
 
std::string concept (const std::string key) const
 
mspass::utility::MDtype type (const std::string key) const
 
std::list< std::string > keys () const
 
void add (const std::string key, const std::string concept_, const MDtype mdt)
 
bool has_alias (const std::string key) const
 Methods to handle aliases. More...
 
bool is_alias (const std::string key) const
 Ask if a key is a registered alias. More...
 
std::list< std::string > aliases (const std::string key) const
 
std::pair< std::string, mspass::utility::MDtype > unique_name (const std::string aliasname) const
 
void add_alias (const std::string key, const std::string aliasname)
 
bool writeable (const std::string key) const
 
bool readonly (const std::string key) const
 
void set_readonly (const std::string key)
 Lock a parameter to assure it will not be saved. More...
 
void set_writeable (const std::string key)
 Force a key:value pair to be writeable. More...
 
bool is_normalized (const std::string key) const
 Test if a key:value pair is set as normalized. More...
 
std::string unique_id_key (const std::string key) const
 Returns a unique identifier for a normalized attribute. More...
 
std::string collection (const std::string key) const
 
std::pair< std::string, std::string > normalize_data (const std::string key) const
 Special method for efficiency. More...
 
std::list< std::string > apply_aliases (mspass::utility::Metadata &d, const std::list< std::string > aliaslist)
 Apply a set of aliases to data. More...
 
void clear_aliases (mspass::utility::Metadata &d)
 Restore any aliases to unique names. More...
 
MetadataDefinitionsoperator= (const MetadataDefinitions &other)
 
MetadataDefinitionsoperator+= (const MetadataDefinitions &other)
 Accumulate additional definitions. More...
 

Detailed Description

Define properties of Metadata known to mspass.

The metadata system in mspass was designed to be infinitely flexible. However, to be maintainable and provide some stability we need a method to define the full properties of the keys that define attributes known to the system. This object does that through wwhat I hope is a simple interface. The expectation is the main use of this class is in python code that will read and write to mongo. Mongo is type sensitive but python tries hard to by loosy goosy about types. The main use is then expected that all gets and puts to Metadata will be preceded by calls to the type method here. Based on the return the right get or put method can be called.

The overhead of creating this thing is not small. It will likely be recommended as an initialization step for most mspass processing scripts. Ultimately it perhaps should have a database constructor, but initially we will build it only from data file.

Constructor & Destructor Documentation

◆ MetadataDefinitions() [1/4]

mspass::utility::MetadataDefinitions::MetadataDefinitions ( )

Default constructor. Loads default schema name of mspass.

47 {
48  try{
49  string datadir=mspass::utility::data_directory();
50  string path;
51  path=datadir+"/yaml/"+DefaultSchemaName+".yaml";
52  MetadataDefinitions tmp(path,MDDefFormat::YAML);
53  *this=tmp;
54  }catch(...){throw;};
55 }
Define properties of Metadata known to mspass.
Definition: MetadataDefinitions.h:31

◆ MetadataDefinitions() [2/4]

mspass::utility::MetadataDefinitions::MetadataDefinitions ( const std::string  mdname)

Construct from a namespace title.

How this is to be implemented is to be determined, but for many uses a simple one line description of the name space for attributes would be a helpful api. At this time it is not implemented and attempts to use this will throw an exception.

15 {
16  try{
17  /* silent try to recover if the user adds .yaml to mdname*/
18  std::size_t ipos; //size_t seems essential here for this to work -weird
19  string name_to_use;
20  ipos=mdname.find(".yaml");
21  if(ipos==std::string::npos)
22  {
23  name_to_use=mdname;
24  }
25  /* We throw an exception if the name is a path with / characters*/
26  else if(mdname.find("/")!=std::string::npos)
27  {
28  throw MsPASSError("MetadataDefinitions: name passed seems to be a full path name that is not allowed\nReceived this: "
29  +mdname,ErrorSeverity::Invalid);
30  }
31  else
32  {
33  name_to_use.assign(mdname,0,ipos);
34  }
35  string datadir=mspass::utility::data_directory();
36  string path;
37  path=datadir+"/yaml/"+name_to_use+".yaml";
38  MetadataDefinitions tmp(path,MDDefFormat::YAML);
39  *this=tmp;
40  }catch(...){throw;};
41 
42 }
Base class for error object thrown by MsPASS library routines.
Definition: MsPASSError.h:40

◆ MetadataDefinitions() [3/4]

mspass::utility::MetadataDefinitions::MetadataDefinitions ( const std::string  mdname,
const mspass::utility::MDDefFormat  form 
)

Construct from a file with variable formats.

This constructor reads from a file to build the object. The API allows multiple formats through the enum class.

Parameters
mdnameis the file to read
formdefines the format (limited by MDDefFormat definitions)

◆ MetadataDefinitions() [4/4]

mspass::utility::MetadataDefinitions::MetadataDefinitions ( const MetadataDefinitions parent)

Standard copy constructor.

74  : tmap(parent.tmap),cmap(parent.cmap),
75  aliasmap(parent.aliasmap),
76  alias_xref(parent.alias_xref),roset(parent.roset),
77  unique_id_data(parent.unique_id_data)
78 {}

Member Function Documentation

◆ add()

void mspass::utility::MetadataDefinitions::add ( const std::string  key,
const std::string  concept_,
const MDtype  mdt 
)

Basic putter.

Use to add a new entry to the definitions. Note that because this is implemented with C++ map containers if data for the defined key is already present it will be silently replaced.

Parameters
keyis the key for indexing this attribute
concept_is brief description saved as the concept for this key
typedefines the type to be defined for this key.
133 {
134  cmap[key]=concept_;
135  tmap[key]=mdt;
136 }

◆ add_alias()

void mspass::utility::MetadataDefinitions::add_alias ( const std::string  key,
const std::string  aliasname 
)

Add an alias for key.

Parameters
keyis the main key for which an alias is to be defined
aliasnameis the the alternative name to define.
163 {
164  /* We could use operator[] but this is more bombproof if not as clear */
165  aliasmap.insert(std::pair<string,string>(key,aliasname));
166  alias_xref.insert(std::pair<string,string>(aliasname,key));
167 }

◆ apply_aliases()

std::list< string > mspass::utility::MetadataDefinitions::apply_aliases ( mspass::utility::Metadata d,
const std::list< std::string >  aliaslist 
)

Apply a set of aliases to data.

This method should be called in processing workflows to apply a series of defined aliases to data. The method uses the is_alias method to verify if an alias name is valid. It will not change the key if the name is not defined as a valid alias. The keys that fail that test will be posted to the std::list that is returned. Callers should test the size of the return and if it is not empty take appropriate action.

Parameters
dis the data to alter (usually actually a TimeSeries of Seismogram)
aliaslistis a list of aliases names to apply.
Returns
std::list of srings of failed changes. Callers should test the size of this return and take action if needed.
521 {
522  list<string> failures;
523  list<string>::const_iterator aptr;
524  std::pair<string,MDtype> nmpair;
525  for(aptr=aliaslist.begin();aptr!=aliaslist.end();++aptr)
526  {
527  if(this->is_alias(*aptr))
528  {
529  nmpair=this->unique_name(*aptr);
530  string ukey=nmpair.first;
531  /* Silently skip any aliases not defined. That assures that if the
532  name had already been changed to this alias it will be prserved. */
533  if(d.is_defined(ukey))
534  {
535  d.change_key(ukey,*aptr);
536  }
537  }
538  else
539  {
540  failures.push_back(*aptr);
541  }
542  }
543  return failures;
544 }
bool is_alias(const std::string key) const
Ask if a key is a registered alias.
Definition: MetadataDefinitions.cc:168
std::pair< std::string, mspass::utility::MDtype > unique_name(const std::string aliasname) const
Definition: MetadataDefinitions.cc:179
bool is_defined(const std::string key) const noexcept
Definition: Metadata.cc:73
void change_key(const std::string oldkey, const std::string newkey)
Change the keyword to access an attribute.
Definition: Metadata.cc:324

References mspass::utility::Metadata::change_key(), is_alias(), mspass::utility::Metadata::is_defined(), and unique_name().

◆ clear_aliases()

void mspass::utility::MetadataDefinitions::clear_aliases ( mspass::utility::Metadata d)

Restore any aliases to unique names.

Aliases are needed to support legacy packages, but can cause downstream problem if left intact. This method clears any aliases and sets them to the unique_name defined by this object.

Parameters
dis data to be altered. Normally a Seismogram of TimeSeries but can be a raw Metadata object.
Returns
ErrorLogger containing any problems encountered. This function always returns and treats any problems as nonfatal errors and posts a log entry into this returned object. Caller should test the size of the return and handle or ignore errors as appropriate.
546 {
547  std::set<string> keys;
548  keys=d.keys();
549  std::set<string>::iterator kptr;
550  std::pair<string,MDtype> nmpair;
551  for (kptr=keys.begin();kptr!=keys.end();++kptr)
552  {
553  if(this->is_alias(*kptr))
554  {
555  nmpair=this->unique_name(*kptr);
556  string ukey=nmpair.first;
557  d.change_key(*kptr,ukey);
558  }
559  }
560 }
std::set< std::string > keys() const noexcept
Definition: Metadata.cc:140

References mspass::utility::Metadata::change_key(), is_alias(), mspass::utility::Metadata::keys(), and unique_name().

◆ collection()

string mspass::utility::MetadataDefinitions::collection ( const std::string  key) const

\Brief return the master collection (table) for a key used as a unique id.

Support for normalized Metadata requires static tables (collection in MongoDB) that contain the data using normalization. In seismic data type examples are receiver location tables, receiver response tables, and source location data. This method should nearly always be paired with a call to unique_id_key. The idea is to first ask for the unique_id_key and then ask what collection (table) contains the key returned by unique_id_key. This provides a fast and convenient lookup for normalized data.

Parameters
keyis the normally the return from unique_id_key
Returns
string defining the collection(table) the key can be used for locating the unique tuple/document required to access related Metadata. String will be empty if the search fails.
354 {
355  map<string,tuple<string,string>>::const_iterator uidptr;
356  uidptr=unique_id_data.find(key);
357  if(uidptr==unique_id_data.end())
358  {
359  return (string(""));
360  }
361  else
362  {
363  return(get<0>(uidptr->second));
364  }
365 }

◆ concept()

std::string mspass::utility::MetadataDefinitions::concept ( const std::string  key) const

Return a description of the concept this attribute defines.

Parameters
keyis the name that defines the attribute of interest
Returns
a string with a terse description of the concept this attribute defines.
103 {
104  const string base_error("MetadataDefinitions::concept: ");
105  map<string,string>::const_iterator cptr;
106  cptr=cmap.find(key);
107  if(cptr==cmap.end())
108  {
109  stringstream ss;
110  ss<<base_error<<"no match for key="<<key<<" found"<<endl;
111  throw MsPASSError(ss.str(),ErrorSeverity::Invalid);
112  }
113  return cptr->second;
114 }

◆ has_alias()

bool mspass::utility::MetadataDefinitions::has_alias ( const std::string  key) const

Methods to handle aliases.

Sometimes it is helpful to have alias keys to define a common concept. For instance, if an attribute is loaded from a ralational db one might want to use alias names of the form table.attribute as an alias to attribute. has_alias should be called first to establish if a name has an alias. To get a list of aliases call the aliases method.

138 {
139  multimap<string,string>::const_iterator aptr;
140  aptr=aliasmap.find(key);
141  if(aptr==aliasmap.end())
142  return false;
143  else
144  return true;
145 }

◆ is_alias()

bool mspass::utility::MetadataDefinitions::is_alias ( const std::string  key) const

Ask if a key is a registered alias.

This asks the inverse question to has_alias. That is, it yields true of the key is registered as a valid alias. It returns false if the key is not defined at all. Note it will yield false if the key is a registered unique name and not an alias.

169 {
170  map<string,string>::const_iterator mptr;
171  mptr=alias_xref.find(key);
172  if(mptr==alias_xref.end())
173  return false;
174  else
175  return true;
176 }

◆ is_defined()

bool mspass::utility::MetadataDefinitions::is_defined ( const std::string  key) const
noexcept

Test if a key is defined either as a unique key or an alias

80 {
81  /* test type map because concept can be empty for a key */
82  map<string,MDtype>::const_iterator tptr;
83  tptr=tmap.find(key);
84  if(tptr!=tmap.end())
85  {
86  return true;
87  }
88  else
89  {
90  pair<string,MDtype> unr;
91  /* A bit weird to catch an exception as a way to test for a false, but
92  the way the api currently is defined requires this. */
93  try{
94  unr=this->unique_name(key);
95  return true;
96  }catch(MsPASSError& mderr)
97  {
98  return false;
99  }
100  }
101 }

◆ is_normalized()

bool mspass::utility::MetadataDefinitions::is_normalized ( const std::string  key) const

Test if a key:value pair is set as normalized.

In MongoDB a normalized attribute is one that has a master copy in one and only one place. This method returns true if an attribute is marked normalized and false otherwise (It will also return false for any key that is undefined.).

331 {
332  if(unique_id_data.find(key)!=unique_id_data.end())
333  return true;
334  else
335  return false;
336 }

◆ normalize_data()

std::pair< std::string, std::string > mspass::utility::MetadataDefinitions::normalize_data ( const std::string  key) const

Special method for efficiency.

For mspass using mongodb normalization for all currently supported Metadata can be reduced to a collection(table)-attribute name pair. The unique_id_key and collection methods can be called to obtained this information, but doing so requires a purely duplicate (internal map container) search. This convenience method is best used with MongoDB for efficiency.

Parameters
keyis the flat namespace key for which normalizing data is needed
Returns
an std::pair with of strings with first=collection and second=attribute name.
367 {
368  map<string,tuple<string,string>>::const_iterator uidptr;
369  uidptr=unique_id_data.find(key);
370  if(uidptr==unique_id_data.end())
371  {
372  throw MsPASSError("MetadataDefinitions::normalize_data: key="
373  + key + " has no normalization data");
374  }
375  else
376  {
377  pair<string,string> result;
378  result.first=get<0>(uidptr->second);
379  result.second=get<1>(uidptr->second);
380  return result;
381  }
382 }

◆ operator+=()

MetadataDefinitions & mspass::utility::MetadataDefinitions::operator+= ( const MetadataDefinitions other)

Accumulate additional definitions.

Appends data in other to current. The behavior or this operator is not really a pure + operation as one would think of it as with arithmetic. Because the model is that we are defining the properties of unique keys handling the case where other has a duplicate key to the instance of the left hand side is ambiguous. We choose the more intuitive case where the right hand side overrides the left. i.e. if other has duplicate data for a key the right hand side version replaces the left. There are two exceptions. Aliases are multivalued so they accumulate. i.e. this mechanism can be used to do little more than add an alias if the others data are the same. The second case is more trivial and rarely of importance. That is, other can have empty concept data for a key and it will be silently set empty. The reason is concept is purely for human readers and is not expected to ever be used by processors.

228 {
229  if(this==&other) return *this;
230  list<string> kvals=other.keys();
231  list<string>::iterator kptr;
232  for(kptr=kvals.begin();kptr!=kvals.end();++kptr)
233  {
234  MDtype mdt=other.type(*kptr);
235  /* Note this will silently overwrite previous if the key was already present*/
236  this->tmap[*kptr]=mdt;
237  try{
238  string cother=other.concept(*kptr);
239  this->cmap[*kptr]=cother;
240  }catch(MsPASSError& merr)
241  {
242  //Assume the only error here comes from concept methode failing
243  cerr << "MetadataDefinitions operator+= (Warning): concept description is missing for key="
244  <<*kptr<<endl<<"Error will be ignored"<<endl;
245  }
246  /* The alias_xref is a multimap so we just append other data - no such thing as duplicates*/
247  map<string,string>::const_iterator aptr;
248  for(aptr=other.alias_xref.begin();aptr!=other.alias_xref.end();++aptr)
249  {
250  this->alias_xref.insert(*aptr);
251  }
252  /* These behave like the type map above - we silently replace any entry
253  that was present before. i.e. other overrides */
254  set<string>::const_iterator sptr;
255  for(sptr=other.roset.begin();sptr!=roset.end();++sptr)
256  {
257  this->roset.insert(*sptr);
258  }
259  map<string,tuple<string,string>>::const_iterator uptr;
260  for(uptr=other.unique_id_data.begin();uptr!=other.unique_id_data.end();++uptr)
261  {
262  this->unique_id_data.insert(*uptr);
263  }
264  }
265  return *this;
266 }
std::string concept(const std::string key) const
Definition: MetadataDefinitions.cc:102
mspass::utility::MDtype type(const std::string key) const
Definition: MetadataDefinitions.cc:116

References concept(), and type().

◆ operator=()

MetadataDefinitions & mspass::utility::MetadataDefinitions::operator= ( const MetadataDefinitions other)

Standard assignment operator.

215 {
216  if(this!=&parent)
217  {
218  tmap=parent.tmap;
219  cmap=parent.cmap;
220  aliasmap=parent.aliasmap;
221  alias_xref=parent.alias_xref;
222  roset=parent.roset;
223  unique_id_data=parent.unique_id_data;
224  }
225  return *this;
226 }

◆ readonly()

bool mspass::utility::MetadataDefinitions::readonly ( const std::string  key) const

Check if a key:value pair is marked readonly. Inverted logic of similar writeable method.

Parameters
keyis key used to access the parameter to be tested.
Returns
true of the data linked to this keys IS marked readonly. (if the key is undefined this method silently returns true)
309 {
310  return( ! (this->writeable(key)));
311 }
bool writeable(const std::string key) const
Definition: MetadataDefinitions.cc:271

References writeable().

◆ set_readonly()

void mspass::utility::MetadataDefinitions::set_readonly ( const std::string  key)

Lock a parameter to assure it will not be saved.

Parameters can be defined readonly. That is a standard feature of this class, but is normally expected to be set on construction of the object. There are sometimes reason to lock out a parameter to keep it from being saved in output. This method allows this. On the other hand, use this feature only if you fully understand the downstream implications or you may experience unintended consequences.

Parameters
keyis the key for the attribute with properties to be redefined.
313 {
314  /* Silently return if key is already set as readonly */
315  if(roset.find(key)==roset.end())
316  {
317  roset.insert(key);
318  }
319 }

◆ set_writeable()

void mspass::utility::MetadataDefinitions::set_writeable ( const std::string  key)

Force a key:value pair to be writeable.

Normally some parameters are marked readonly on construction to avoid corrupting the database with inconsistent data defined with a common key. (e.g. sta) This method overrides such definitions for any key so marked. It does nothing except a pointles search if the key hasn't been marked readonly previously. This method should be used with caution as it could have unintended side effects.

Parameters
keyis key for the attribute to be redefined.
321 {
322  set<string>::const_iterator roptr;
323  roptr=roset.find(key);
324  /* Here we silently do nothing if the key is not in roset */
325  if(roptr!=roset.end())
326  {
327  roset.erase(roptr);
328  }
329 }

◆ type()

mspass::utility::MDtype mspass::utility::MetadataDefinitions::type ( const std::string  key) const

Get the type of an attribute.

Parameters
keyis the name that defines the attribute of interest
Returns
MDtype enum that can be used to establish the proper type.
117 {
118  const string base_error("MetadataDefinitions::type: ");
119  map<std::string,mspass::utility::MDtype>::const_iterator tptr;
120  if(this->is_alias(key))
121  return this->unique_name(key).second;
122  tptr=tmap.find(key);
123  if(tptr==tmap.end())
124  {
125  stringstream ss;
126  ss<<base_error<<"no match for key="<<key<<" found"<<endl;
127  throw MsPASSError(ss.str(),ErrorSeverity::Invalid);
128  }
129  return tptr->second;
130 }

References is_alias(), and unique_name().

◆ unique_id_key()

string mspass::utility::MetadataDefinitions::unique_id_key ( const std::string  key) const

Returns a unique identifier for a normalized attribute.

In MongoDB a normalized attribute is one that has a master copy in one and only one place. This method returns a unique identifier, which defines a key that can be used to access the attribute used as an index to identify a unique location for an otherwise potentially ambiguous identifier (e.g. sta can be used in may contexts). The type of attribute to which the returned key is linked is expected to normally be acquired by am immediate call to the type method of this class using the return key. It is the callers responsibility to handle errors if the request for the type information fails. Note for MongoDB the most common (and recommended) type for the unique id is an Object_ID. The design of the API, however, should not preclude some other index or an index oriented toward a relational database. (e.g. chanid is an integer key with a one-to-one relation for channel data in the CSS3.0 schema.)

Some unique id specifications require a table/collection qualifier. See related collection method that is designed to handle that.

This method should normally be used only on read operations to select the correct entry for what could otherwise be a potentially ambiguous key.

Parameters
keyis the flat namespace key for which normalizing data is needed
Returns
name for unique id for requested key. Returns an empty string if the key is not defined as normalized. In multiple calls it is more efficient to test for a null return and handle such entries inline instead of a double search required if preceded by is_normalized.
340 {
341  map<string,tuple<string,string>>::const_iterator uidptr;
342  uidptr=unique_id_data.find(key);
343 
344  if(uidptr!=unique_id_data.end())
345  {
346  return(get<1>(uidptr->second));
347  }
348  else
349  {
350  return (string(""));
351  }
352 }

◆ unique_name()

std::pair< std::string, mspass::utility::MDtype > mspass::utility::MetadataDefinitions::unique_name ( const std::string  aliasname) const

Get definitive name for an alias.

This method is used to ask the opposite question as aliases. The aliases method returns all acceptable alternatives to a definitive name defined as the key to get said list. This method asks what definitive key should be used to fetch an attribute and what it's type is. It does this by returning an std::pair with first being the key and second the type.

Parameters
aliasnameis the name of the alias for which we want the definitive key
Returns
std::pair with the definitive key as the first of the pair and the type in the second field.
180 {
181  const string base_error("MetadataDefinitions::unique_name: ");
182  map<std::string,std::string>::const_iterator aptr;
183  aptr=alias_xref.find(aliasname);
184  if(aptr==alias_xref.end())
185  {
186  throw MsPASSError(base_error+"alias name="
187  + aliasname + " is not defined",ErrorSeverity::Invalid);
188  }
189  else
190  {
191  /* We do not assume the key returned from alias_xref resolves. Small
192  cost for a stability gain*/
193  string kname=aptr->second;
194  map<std::string,MDtype>::const_iterator tptr;
195  tptr=tmap.find(kname);
196  if(tptr==tmap.end()) throw MsPASSError(base_error+"alias name="+aliasname
197  + " has no matching entry in alias tables\n"
198  + "SETUP ERROR - FIX CONFIGURATION FILES",
199  ErrorSeverity::Fatal);
200  return(pair<std::string,mspass::utility::MDtype>(kname,tptr->second));
201  }
202 }

◆ writeable()

bool mspass::utility::MetadataDefinitions::writeable ( const std::string  key) const

Check if a key:value pair is mutable(writeable). Inverted logic from similar readonly method.

Parameters
keyis key used to access the parameter to be tested.
Returns
true if the data linked to this not not marked readonly. (if the key is undefined a false is silently returned)
272 {
273  set<string>::const_iterator roptr;
274  roptr=roset.find(key);
275  if(roptr==roset.end())
276  return true;
277  else if(this->is_alias(key))
278  {
279  /* roset only contains unique key entries. This checks any possible
280  aliases. */
281  pair<string,MDtype> kp;
282  /* unique_name method returns an exception if the key is not defined.
283  We avoid that and silently return false if that happens, although
284  that situation will likely create downstream problems. */
285  try{
286  kp=this->unique_name(key);
287  }catch(MsPASSError &mderr)
288  {
289  cerr << "MetadataDefinitions::writeable method (WARNING): Requested key "
290  << key<<" is undefined and is not a registered alias"<<endl
291  <<"This may cause downstream problems"<<endl;
292  return false;
293  }
294  roptr=roset.find(kp.first);
295  if(roptr==roset.end())
296  return true;
297  else
298  return false;
299  }
300  else
301  {
302  /* A bit confusing layout here. We land here if the
303  * key was marked read only and was not an alias. */
304  return false;
305  }
306 }

References is_alias(), and unique_name().


The documentation for this class was generated from the following files: