.. _lexicon-py:
##########
lexicon.py
##########
::
>>> from simo.builder.lexicon.lexicon import LexiconDef
>>> tdf = open('../../simulator/xml/schemas/Typedefs_SIMO.xsd')
>>> typedef = tdf.read()
>>> tdf.close()
>>> sf = open('../../simulator/xml/schemas/lexicon.xsd')
>>> schema = sf.read()
>>> sf.close()
>>> xml1 = '''
... simulation
...
...
... DIAM_CLASS_WIDTH
... Width of a single class...
...
...
...
...
...
... comp_unit
... static
...
...
... BA
... Basal area...
...
...
...
...
... SC
... Site class...
...
...
... 1
... Very good
...
...
...
...
...
...
... Stand label
... Id text for the stand
...
...
...
...
... stratum
... dynamic
...
...
... N
... Number of stems...
...
...
...
...
... SP
... Tree species...
...
...
... 1
... Pine
...
...
... 2
... Spruce
...
...
...
...
...
...
... tree
... dynamic
...
...
... d
... Diameter...
...
...
...
...
...
...
...
...
...
... sample_plot
... static
...
...
... BA
... Basal area...
...
...
...
...
...
... sample_tree
... dynamic
...
...
... h
... Height...
...
...
...
...
...
...
...
... '''
>>> ldef1 = LexiconDef(typedef)
>>> ldef1.schema = schema
>>> try:
... ldef1.xml = xml1
... except ValueError, e:
... print e
xml name and xml content must be passed
>>> ldef1.xml = ('Test lexicon', xml1)
>>> ldef1.xml['Test lexicon'][0:10]
'>> xml2 = '''
... simulation
...
...
... NUM_OF_CLASSES
... Number of size classes...
...
...
...
...
...
... comp_unit
... static
...
...
... D_gM
... Mean diameter...
...
...
...
...
... DEVEL_CLASS
... Development class...
...
...
... 1
... Seedling stand
...
...
...
...
...
...
... Stand label
... Id text for the stand
...
...
...
...
... stratum
... dynamic
...
...
... H_gM
... Mean height...
...
...
...
...
...
...
...
... sample_plot
... static
...
...
... RADIUS
... Plot radius...
...
...
...
...
...
... '''
>>> ldef2 = LexiconDef(typedef)
>>> ldef2.schema = schema
>>> try:
... ldef2.xml = xml2
... except ValueError, e:
... print e
xml name and xml content must be passed
>>> ldef2.xml = ('Additional lexicon', xml2)
>>> ldef2.xml['Additional lexicon'][0:10]
'>> xml3 = '''
... simulation
...
...
... NUM_OF_CLASSES
... Number of size classes...
...
...
...
...
...
... comp_unit
... static
...
...
... D_gM
... Mean diameter...
...
...
...
...
... DEVEL_CLASS
... Development class...
...
...
... 1
... Seedling stand
...
...
...
...
...
...
... Stand label
... Id text for the stand
...
...
...
...
... sample_tree
... dynamic
...
...
... h
... tree height...
...
...
...
...
...
...
...
... sample_plot
... static
...
...
... RADIUS
... Plot radius...
...
...
...
...
...
... '''
>>> ldef3 = LexiconDef(typedef)
>>> ldef3.schema = schema
>>> try:
... ldef3.xml = xml3
... except ValueError, e:
... print e
xml name and xml content must be passed
>>> ldef3.xml = ('Invalid lexicon', xml3)
>>> ldef3.xml['Invalid lexicon'][0:10]
'>> lex = ldef1.obj["Test lexicon"]
>>> for x, y in lex.level_ind.items(): print x, y # doctest: +ELLIPSIS
tree 3
simulation 0
sample_tree 5
sample_plot 4
stratum 2
comp_unit 1
>>> for x, y in lex.variable_ind.items():
... print x, y # doctest: +ELLIPSIS
tree {'d': None}
simulation {'DIAM_CLASS_WIDTH': None}
sample_tree {'h': None}
sample_plot {'BA': None}
stratum {'SP': None, 'N': None}
comp_unit {'SC': None, 'Stand label': None, 'BA': None}
>>> for x, y in lex.level_name.items():
... print x, y # doctest: +ELLIPSIS
0 simulation
1 comp_unit
2 stratum
3 tree
4 sample_plot
5 sample_tree
>>> for x, y in lex.variable_name.items():
... print x, y # doctest: +ELLIPSIS
0 {}
1 {}
2 {}
3 {}
4 {}
5 {}
>>> for x, y in lex.hierarchy.items():
... print x, y # doctest: +ELLIPSIS
0 {'ordinal': 0, 'lineage': set([0, 1]), 'children': [1, 4], 'parent': None}
1 {'ordinal': 1, 'lineage': set([0]), 'children': [2], 'parent': 0}
2 {'ordinal': 2, 'lineage': set([0]), 'children': [3], 'parent': 1}
3 {'ordinal': 3, 'lineage': set([0]), 'children': None, 'parent': 2}
4 {'ordinal': 1, 'lineage': set([1]), 'children': [5], 'parent': 0}
5 {'ordinal': 2, 'lineage': set([1]), 'children': None, 'parent': 4}
>>> for x, y in lex.active_variables.items():
... print x, y # doctest: +ELLIPSIS
tree {'d': False}
simulation {'DIAM_CLASS_WIDTH': False}
sample_tree {'h': False}
sample_plot {'BA': False}
stratum {'SP': False, 'N': False}
comp_unit {'SC': False, 'Stand label': False, 'BA': False}
>>> lex.get_variable_ind('tree', 'd')
(3, 0)
>>> lex.active_variables['tree']
{'d': True}
>>> lex.get_variable_ind('simulation', 'DIAM_CLASS_WIDTH')
(0, 0)
>>> lex.get_variable_ind('comp_unit', 'SC')
(1, 0)
>>> cd = lex.get_content_def()
>>> cd[('simulation', 0)]
[('DIAM_CLASS_WIDTH', 0)]
>>> cd[('comp_unit', 1)]
[('SC', 0)]
>>> lex.models
{}
>>> lex.add_model('prediction', 'testmodel')
>>> lex.add_model('aggregation', 'testmodel')
>>> lex.add_model('prediction', 'testmodel')
>>> lex.add_model('operation', 'testmodel1')
0
>>> lex.add_model('operation', 'testmodel2')
1
>>> lex.add_model('operation', 'testmodel2')
1
>>> lex.models['prediction']
set(['testmodel'])
>>> lex.models['aggregation']
set(['testmodel'])
>>> lex.models['operation']
set(['testmodel2', 'testmodel1'])
>>> l = lex.levels
>>> t = l['tree']
>>> var = t.variables['d']
>>> var.desc
'Diameter...'
>>> s = l['stratum']
>>> s.categorical
set(['SP'])
>>> s.numerical
set(['N'])
>>> sp = s.variables['SP']
>>> sp.name
'SP'
>>> sp.unit
>>> sp.maximum
>>> sp.minimum
>>> sp.desc
'Tree species...'
>>> sp.values
{1.0: 'Pine', 2.0: 'Spruce'}
>>> lex.reset_active_variables_and_models()
>>> lex.active_variables['tree']
{'d': False}
>>> lex.models
{}
>>> lex.operation_ind
{}
def _parse_level(self, elem, levelind, ordinal, line):
======================================================
Parse a single level and store level information into lexicon.
def _store_level(self, level, levelind, ordinal, lineage):
==========================================================
Store variable indices, level indices etc. from a single level. IMPORTANT: any variable longer than 30 characters will result in an error.
def get_level_ind(self, level):
===============================
Validate level against lexicon::
>>> lex.get_level_ind('comp_unit')
1
>>> lex.get_level_ind('compunit')
def get_variable_ind(self, level, variable):
============================================
Validate variable name and level against lexicon; create a new ind if one
doesn't already exist::
>>> lex.get_variable_ind('simulation', 'DIAM_CLASS_WIDTH')
(0, 0)
>>> lex.get_variable_ind('stratum', 'SP')
(2, 0)
>>> lex.get_variable_ind('stratum', 'N', True)
(None, None)
>>> lex.get_variable_ind('stratum', 'N')
(2, 1)
>>> lex.get_variable_ind('stratum', 'SP', True)
(2, 0)
>>> lex.get_variable_ind('no-level', 'SP')
(None, None)
>>> lex.get_variable_ind('stratum', 'no-variable')
(None, None)
def get_level_name(self, level):
================================
Get level name::
>>> lex.get_level_name(2)
'stratum'
>>> lex.get_level_name(10)
def get_variable_name(self, level, variable):
=============================================
Get variable name::
>>> lex.get_variable_name(1, 0)
'SC'
>>> lex.get_variable_name(10, 1)
>>> lex.get_variable_name(1, 10)
def is_parent(self, parentcandidate, childcandidate):
=====================================================
Check whether parentcandidate is a parent level of childcandidate level::
>>> lex.is_parent(0, 0)
False
>>> lex.is_parent(0, 1)
True
>>> lex.is_parent(0, 3)
True
>>> lex.is_parent(0, 5)
True
>>> lex.is_parent(1, 3)
True
>>> lex.is_parent(1, 5)
False
def is_child(self, childcandidate, parentcandidate):
====================================================
Check whether childcandidate is a child level of parentcandidate level::
>>> lex.is_child(0, 0)
False
>>> lex.is_child(1, 0)
True
>>> lex.is_child(3, 0)
True
>>> lex.is_child(5, 0)
True
>>> lex.is_child(3, 1)
True
>>> lex.is_child(5, 1)
False
Final checks:
=============
>>> for x, y in lex.variable_ind.items():
... print x, y # doctest: +ELLIPSIS
tree {'d': 0}
simulation {'DIAM_CLASS_WIDTH': 0}
sample_tree {'h': None}
sample_plot {'BA': None}
stratum {'SP': 0, 'N': 1}
comp_unit {'SC': 0, 'Stand label': None, 'BA': None}
>>> for x, y in lex.variable_name.items():
... print x, y # doctest: +ELLIPSIS
0 {0: 'DIAM_CLASS_WIDTH'}
1 {0: 'SC'}
2 {0: 'SP', 1: 'N'}
3 {0: 'd'}
4 {}
5 {}
def _match_hierarchy(self, lexicon, mylevel, lexlevel):
=======================================================
Make sure that self and another lexicon are compatible. This requires that the level names and the parent-child relations should match between the two lexicons.
Parameters ::
lexicon -- lexicon instance to be merged to self
mylevel -- current level indice for self
lexlevel -- current level indice for lexicon
Match two lexicons with compatible data hierarchies ::
>>> lex2 = ldef2.obj["Additional lexicon"]
>>> lex._match_hierarchy(lex2, 0, 0)
True
Match two lexicons with incompatible data hierarchies ::
>>> lex3 = ldef3.obj["Invalid lexicon"]
>>> lex._match_hierarchy(lex3, 0, 0)
False
def merge(self, lexicon):
=========================
Merge self with another lexicon. This way lexicons can be built from a master lexicon and a number of additional lexicons.
Parameters ::
lexicon -- Lexicon instance to be joined with self
>>> from minimock import Mock
>>> logger = Mock('Logger')
Merge an additional lexicon to the master lexicon ::
>>> lex.merge(lex2, logger)
Called Logger.log(
'warning',
"variable 'Stand label' defined in both master and extra lexicons; master lexicon definition will be overwritten.")
True
Make sure that the new variables were actually added to the master lexicon ::
>>> lex.get_variable_ind('simulation', 'NUM_OF_CLASSES')
(0, 1)
>>> lex.get_variable_ind('comp_unit', 'D_gM')
(1, 1)
>>> lex.get_variable_ind('comp_unit', 'DEVEL_CLASS')
(1, 2)
>>> lex.get_variable_ind('stratum', 'H_gM')
(2, 2)
>>> lex.get_variable_ind('sample_plot', 'RADIUS')
(4, 0)
Check that all level and variable information was also merged ::
>>> lex.levels['comp_unit'].variables['BA'].desc
'Basal area...'
>>> lex.levels['comp_unit'].variables['DEVEL_CLASS'].desc
'Development class...'
>>> lex.levels['comp_unit'].variables['DEVEL_CLASS'].values
{1.0: 'Seedling stand'}
Try to merge an incompatible lexicon to the master lexicon ::
>>> lex.merge(lex3, logger)
Called Logger.log(
'error',
'mismatching data hierarchies, cannot merge lexicons')
False