.. _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