Esempio n. 1
0
File: ast.py Progetto: bcmd/BCMD
def process_chemterm(term, work, multiplier):
    logger.detail("Processing chemterm")
    terms = []
    idx = 1
    while idx < len(term):
        logger.detail('iterating term: ' + str(term[idx]) + ', ' + str(term[idx+1]))
        i_expr, expr, deps = process_mathterm(term[idx][1], work)
        unmod = expr
        i_unmod = i_expr
        mathterm = term[idx][1]
        
        # # this is a thoroughly dodgy bit of hackery
        # # may change in line with better expr handling
        if ( multiplier != 1 ):
            expr = '(' + str(multiplier) + '*' + expr + ')'
            i_expr = (('literal','(' + str(multiplier) + '*'),) + i_expr + (('literal',')'),)
            mathterm = ('arithmetic', '*', ('mathterm', decimal.Decimal('-1')), term[idx])
        
        chem = process_chemical(term[idx+1], work)
        terms.append({'stoich': expr, 'chem':chem, 'unmod':unmod,
                      'i_stoich': i_expr, 'i_unmod':i_unmod,
                      'mathterm_unmod':term[idx][1], 'mathterm':mathterm,
                     'depends': deps|work['symbols'][chem]['depends']})
        idx = idx + 2
    return terms
Esempio n. 2
0
File: ast.py Progetto: bcmd/BCMD
def process_explicit_rate(term, work, lhs):
    logger.detail("Processing explicit rateterm")
    if len(term[2]) > 2:
        logger.warn("More than 1 rate term supplied, ignoring excess")
    
    i_expr, expr, deps = process_mathterm(term[2][1][1], work)
    return { 'i_expr':i_expr, 'expr':expr, 'depends':deps, 'mathterm':term[2][1][1] }
Esempio n. 3
0
File: ast.py Progetto: bcmd/BCMD
def process_flux(term, work):
    tag = term[1]    
    logger.detail('Processing ' + tag + ' reaction')
    label = term[2][1]
    if label == '': label = default_label(tag + '__')
    while label in work['reactions'].keys():
        newlabel = default_label(tag + '__')
        logger.warn("Duplicate reaction label '" + label
                     + "', substituting '" + newlabel + "'")
        label = newlabel
    
    # I have no idea whether this is reasonable, but:
    # outflux reactions have an LHS and can (if necessary)
    # be given MA rates; influx reactions don't and can't
    if tag == 'outflux':
        terms = process_chemterm(term[3], work, -1)
        rate = process_rateterm(term[4], work, terms)
        lhs = terms
        rhs = []
    else:
        terms = process_chemterm(term[3], work, 1)
        rate = process_rateterm(term[4], work, None)
        lhs = []
        rhs = terms

    work['reactions'][label] = { 'type' : tag,
                                 'terms' : terms,
                                 'rate' : rate,
                                 'lhs' : lhs,
                                 'rhs': rhs,
                                 'ratespec': term[4] }
    consolidate_chems(work['reactions'][label])
Esempio n. 4
0
def process_flux(term, work):
    tag = term[1]
    logger.detail('Processing ' + tag + ' reaction')
    label = term[2][1]
    if label == '': label = default_label(tag + '__')
    while label in work['reactions'].keys():
        newlabel = default_label(tag + '__')
        logger.warn("Duplicate reaction label '" + label +
                    "', substituting '" + newlabel + "'")
        label = newlabel

    # I have no idea whether this is reasonable, but:
    # outflux reactions have an LHS and can (if necessary)
    # be given MA rates; influx reactions don't and can't
    if tag == 'outflux':
        terms = process_chemterm(term[3], work, -1)
        rate = process_rateterm(term[4], work, terms)
        lhs = terms
        rhs = []
    else:
        terms = process_chemterm(term[3], work, 1)
        rate = process_rateterm(term[4], work, None)
        lhs = []
        rhs = terms

    work['reactions'][label] = {
        'type': tag,
        'terms': terms,
        'rate': rate,
        'lhs': lhs,
        'rhs': rhs,
        'ratespec': term[4]
    }
    consolidate_chems(work['reactions'][label])
Esempio n. 5
0
def process_chemterm(term, work, multiplier):
    logger.detail("Processing chemterm")
    terms = []
    idx = 1
    while idx < len(term):
        logger.detail('iterating term: ' + str(term[idx]) + ', ' +
                      str(term[idx + 1]))
        i_expr, expr, deps = process_mathterm(term[idx][1], work)
        unmod = expr
        i_unmod = i_expr
        mathterm = term[idx][1]

        # # this is a thoroughly dodgy bit of hackery
        # # may change in line with better expr handling
        if (multiplier != 1):
            expr = '(' + str(multiplier) + '*' + expr + ')'
            i_expr = (('literal', '(' + str(multiplier) + '*'), ) + i_expr + (
                ('literal', ')'), )
            mathterm = ('arithmetic', '*', ('mathterm', decimal.Decimal('-1')),
                        term[idx])

        chem = process_chemical(term[idx + 1], work)
        terms.append({
            'stoich': expr,
            'chem': chem,
            'unmod': unmod,
            'i_stoich': i_expr,
            'i_unmod': i_unmod,
            'mathterm_unmod': term[idx][1],
            'mathterm': mathterm,
            'depends': deps | work['symbols'][chem]['depends']
        })
        idx = idx + 2
    return terms
Esempio n. 6
0
def process_explicit_rate(term, work, lhs):
    logger.detail("Processing explicit rateterm")
    if len(term[2]) > 2:
        logger.warn("More than 1 rate term supplied, ignoring excess")

    i_expr, expr, deps = process_mathterm(term[2][1][1], work)
    return {
        'i_expr': i_expr,
        'expr': expr,
        'depends': deps,
        'mathterm': term[2][1][1]
    }
Esempio n. 7
0
def process_twoway(term, work):
    label = term[2][1]
    logger.detail("Processing twoway reaction '" + label + "'")
    if label == '': label = default_label('twoway__')

    forward = ('reaction', 'oneway', ('label', label + '_forward'), term[3],
               term[4], term[5])
    reverse = ('reaction', 'oneway', ('label', label + '_reverse'), term[4],
               term[3], term[6])

    process_oneway(forward, work)
    process_oneway(reverse, work)
Esempio n. 8
0
File: ast.py Progetto: bcmd/BCMD
def process_assign(item, work):
    target = item[1]
    logger.detail("Processing assignment to variable: " + target)
    symbol = declare_symbol(target, work)
    if work['docstack']:
        symbol['docs'].extend(work['docstack'])
        work['docstack'] = []
    work['assigned'].add(target)
    
    i_expr, expr, depends = process_mathterm(item[2][1], work)
    symbol['assigns'].append({'expr':expr, 'i_expr':i_expr, 'depends':depends, 'init':item[4], 'mathterm':item[2][1]})
    symbol['depends'] |= depends
Esempio n. 9
0
def load_sources(config):
    sources = config['sources']
    srcIndex = 0
    parsedSources = []
    failedSources = []
    merged = []

    while srcIndex < len(sources):
        logger.message("Searching for source file: " + sources[srcIndex])
        src = search_file(sources[srcIndex], config['modelpath'])
        if (src is None) and (not sources[srcIndex].endswith(MODELDEF_EXT)):
            logger.message("Not found, trying with added extension: " +
                           sources[srcIndex] + MODELDEF_EXT)
            src = search_file(sources[srcIndex] + MODELDEF_EXT,
                              config['modelpath'])

        if src is None:
            logger.warn("File not found: " + sources[srcIndex])
            failedSources.append(sources[srcIndex])
        else:
            nErrs, ast = parse_file(src)
            if nErrs > 0 or ast is None:
                failedSources.append(src)
            else:
                ast = list(ast)

                # add imports that are not already in the source list to it
                for imp in list(
                        sum([x[1:] for x in ast if x[0] == 'import'], ())):
                    if imp not in sources and imp + MODELDEF_EXT not in sources:
                        sources.append(imp)

                logger.detail(ast, prettify=True)
                parsedSources.append((sources[srcIndex], src))

                merged = merged + ast

        srcIndex = srcIndex + 1

    logger.message("Total number of attempted source files: %d" % srcIndex)
    logger.message("%d parsed, %d failed" %
                   (len(parsedSources), len(failedSources)))
    for failed in failedSources:
        logger.message("  ->  %s" % failed)

    return {
        'sources': sources,
        'parsed': parsedSources,
        'failed': failedSources,
        'merged': merged
    }
Esempio n. 10
0
def process_mathterm(term, work):
    logger.detail("Processing mathterm: " + str(term))
    if isinstance(term, decimal.Decimal):
        return (('literal', str(float(term))), ), str(term), set()
    if isinstance(term, str):
        declare_symbol(term, work)
        return (('symbol', term), ), term, set([term])

    if not isinstance(term, tuple):
        return (('error', 'ERROR'), ), 'ERROR', set()

    return {
        'function': process_function,
        'conditional': process_conditional,
        'arithmetic': process_binop
    }.get(term[0], unknown_mathterm)(term, work)
Esempio n. 11
0
File: ast.py Progetto: bcmd/BCMD
def process_mathterm(term, work):
    logger.detail("Processing mathterm: " + str(term))
    if isinstance(term, decimal.Decimal):
        return (('literal', str(float(term))),), str(term), set()
    if isinstance(term, str):
        declare_symbol(term,work)
        return (('symbol', term),), term, set([term])
    
    if not isinstance(term, tuple):
        return (('error','ERROR'),), 'ERROR', set()
    
    return {
            'function' : process_function,
            'conditional' : process_conditional,
            'arithmetic' : process_binop
           }.get(term[0], unknown_mathterm)(term, work)
Esempio n. 12
0
File: ast.py Progetto: bcmd/BCMD
def recurse_dependencies(name, parents, done, symbols):
    if name in parents:
       if not symbols[name]['circular']:
           logger.detail('Circular dependency found for ' + name)
           symbols[name]['circular'] = True
    elif symbols[name]['circular']:
       logger.detail('Previous circularity noted for ' + name)
    else:
       for dep in symbols[name]['depends']:
           if dep in done:
               symbols[name]['depends'] = symbols[name]['depends'] | symbols[dep]['depends']
           else:
               symbols[name]['depends'] = (symbols[name]['depends']
                   | recurse_dependencies(dep, parents | set([name]), done, symbols))
        
    done = done | set([name])
    return symbols[name]['depends']
Esempio n. 13
0
File: ast.py Progetto: bcmd/BCMD
def process_chemical(term, work):
    logger.detail("Processing chemical: " + str(term))
    if len(term) == 2:
        chem = term[1]
        work['chemicals'][chem] = None
        symbol = declare_symbol(chem, work)
    else:
        chem = term[1] + '_' + term[2]
        work['chemicals'][chem] = term[2]
        declare_symbol(term[2], work)
        symbol = declare_symbol(chem, work)
        symbol['depends'] = symbol['depends'] | set([term[2]])
    
    # automatic non-negativity constraint on chemicals
    if NON_NEGATIVE not in symbol['constraints']:
        symbol['constraints'].append(NON_NEGATIVE)
    
    return chem
Esempio n. 14
0
def process_assign(item, work):
    target = item[1]
    logger.detail("Processing assignment to variable: " + target)
    symbol = declare_symbol(target, work)
    if work['docstack']:
        symbol['docs'].extend(work['docstack'])
        work['docstack'] = []
    work['assigned'].add(target)

    i_expr, expr, depends = process_mathterm(item[2][1], work)
    symbol['assigns'].append({
        'expr': expr,
        'i_expr': i_expr,
        'depends': depends,
        'init': item[4],
        'mathterm': item[2][1]
    })
    symbol['depends'] |= depends
Esempio n. 15
0
def process_chemical(term, work):
    logger.detail("Processing chemical: " + str(term))
    if len(term) == 2:
        chem = term[1]
        work['chemicals'][chem] = None
        symbol = declare_symbol(chem, work)
    else:
        chem = term[1] + '_' + term[2]
        work['chemicals'][chem] = term[2]
        declare_symbol(term[2], work)
        symbol = declare_symbol(chem, work)
        symbol['depends'] = symbol['depends'] | set([term[2]])

    # automatic non-negativity constraint on chemicals
    if NON_NEGATIVE not in symbol['constraints']:
        symbol['constraints'].append(NON_NEGATIVE)

    return chem
Esempio n. 16
0
File: ast.py Progetto: bcmd/BCMD
def declare_symbol(name, work):
    if name in work['symbols']:
        symbol = work['symbols'][name]
    else:
        symbol = { 'id' : name,
                   'depends' : set(),
                   'conflicts':0,
                   'assigns':[],
                   'diffs':[],
                   'algs':[],
                   'constraints':[],
                   'circular': False,
                   'index':len(work['symbols']),
                   'docs':[],
                   'tags':[] }
        work['symbols'][name] = symbol
        work['symlist'].append(name)
        logger.detail("Created symbol '" + name + "' at index %d" % work['symbols'][name]['index'])
    return symbol
Esempio n. 17
0
File: bcmd.py Progetto: bcmd/BCMD
def load_sources(config):
    sources = config['sources']
    srcIndex = 0
    parsedSources = []
    failedSources = []
    merged = []
    
    while srcIndex < len(sources):
        logger.message("Searching for source file: " + sources[srcIndex])
        src = search_file(sources[srcIndex], config['modelpath'])
        if ( src is None ) and ( not sources[srcIndex].endswith(MODELDEF_EXT) ):
            logger.message("Not found, trying with added extension: " + sources[srcIndex] + MODELDEF_EXT)
            src = search_file(sources[srcIndex] + MODELDEF_EXT, config['modelpath'])
        
        if src is None:
            logger.warn("File not found: " + sources[srcIndex])
            failedSources.append(sources[srcIndex])
        else:
            nErrs, ast = parse_file(src)
            if nErrs > 0 or ast is None:
                failedSources.append(src)
            else:
                ast = list(ast)
            
                # add imports that are not already in the source list to it
                for imp in list(sum([x[1:] for x in ast if x[0]=='import'], ())):
                    if imp not in sources and imp + MODELDEF_EXT not in sources:
                        sources.append(imp)
            
                logger.detail(ast, prettify=True)
            	parsedSources.append((sources[srcIndex],src))
            
                merged = merged + ast
        
        srcIndex = srcIndex + 1
    
    logger.message("Total number of attempted source files: %d" % srcIndex)
    logger.message("%d parsed, %d failed" % (len(parsedSources), len(failedSources)))
    for failed in failedSources:
        logger.message("  ->  %s" % failed)
    
    return {'sources':sources, 'parsed':parsedSources, 'failed':failedSources, 'merged':merged}
Esempio n. 18
0
def recurse_dependencies(name, parents, done, symbols):
    if name in parents:
        if not symbols[name]['circular']:
            logger.detail('Circular dependency found for ' + name)
            symbols[name]['circular'] = True
    elif symbols[name]['circular']:
        logger.detail('Previous circularity noted for ' + name)
    else:
        for dep in symbols[name]['depends']:
            if dep in done:
                symbols[name]['depends'] = symbols[name]['depends'] | symbols[
                    dep]['depends']
            else:
                symbols[name]['depends'] = (symbols[name]['depends']
                                            | recurse_dependencies(
                                                dep, parents | set([name]),
                                                done, symbols))

    done = done | set([name])
    return symbols[name]['depends']
Esempio n. 19
0
File: ast.py Progetto: bcmd/BCMD
def process_twoway(term, work):
    label = term[2][1]
    logger.detail("Processing twoway reaction '" + label + "'")
    if label == '': label = default_label('twoway__')
    
    forward = ('reaction',
               'oneway',
               ('label', label + '_forward'),
               term[3],
               term[4],
               term[5])
    reverse = ('reaction',
               'oneway',
               ('label', label + '_reverse'),
               term[4],
               term[3],
               term[6])
    
    process_oneway(forward, work)
    process_oneway(reverse, work)
Esempio n. 20
0
File: ast.py Progetto: bcmd/BCMD
def process_oneway(term, work):
    label = term[2][1]
    logger.detail("Processing oneway reaction '" + label + "'")
    if label == '': label = default_label('oneway__')
    while label in work['reactions'].keys():
        newlabel = default_label('oneway__')
        logger.warn("Duplicate reaction label '" + label
                     + "', substituting '" + newlabel + "'")
        label = newlabel
    
    lhs = process_chemterm(term[3], work, -1)
    rhs = process_chemterm(term[4], work, 1)
    
    rate = process_rateterm(term[5], work, lhs)
    
    work['reactions'][label] = { 'type' : 'oneway',
                                 'terms' : lhs + rhs,
                                 'rate' : rate,
                                 'lhs' : lhs,
                                 'rhs' : rhs,
                                 'ratespec': term[5] }
    consolidate_chems(work['reactions'][label])
Esempio n. 21
0
def declare_symbol(name, work):
    if name in work['symbols']:
        symbol = work['symbols'][name]
    else:
        symbol = {
            'id': name,
            'depends': set(),
            'conflicts': 0,
            'assigns': [],
            'diffs': [],
            'algs': [],
            'constraints': [],
            'circular': False,
            'index': len(work['symbols']),
            'docs': [],
            'tags': []
        }
        work['symbols'][name] = symbol
        work['symlist'].append(name)
        logger.detail("Created symbol '" + name +
                      "' at index %d" % work['symbols'][name]['index'])
    return symbol
Esempio n. 22
0
def process_oneway(term, work):
    label = term[2][1]
    logger.detail("Processing oneway reaction '" + label + "'")
    if label == '': label = default_label('oneway__')
    while label in work['reactions'].keys():
        newlabel = default_label('oneway__')
        logger.warn("Duplicate reaction label '" + label +
                    "', substituting '" + newlabel + "'")
        label = newlabel

    lhs = process_chemterm(term[3], work, -1)
    rhs = process_chemterm(term[4], work, 1)

    rate = process_rateterm(term[5], work, lhs)

    work['reactions'][label] = {
        'type': 'oneway',
        'terms': lhs + rhs,
        'rate': rate,
        'lhs': lhs,
        'rhs': rhs,
        'ratespec': term[5]
    }
    consolidate_chems(work['reactions'][label])
Esempio n. 23
0
File: ast.py Progetto: bcmd/BCMD
def process_extern(item, work):
    logger.detail('Appending extern fields:' + str(item[1:]))
    # only include each field once
    work['extern'].extend([x for x in item[1:] if x not in work['extern']])
Esempio n. 24
0
def process_extern(item, work):
    logger.detail('Appending extern fields:' + str(item[1:]))
    # only include each field once
    work['extern'].extend([x for x in item[1:] if x not in work['extern']])
Esempio n. 25
0
def process_input(item, work):
    logger.detail('Appending input fields:' + str(item[1:]))
    # only include each field once
    work['inputs'].extend([x for x in item[1:] if x not in work['inputs']])
Esempio n. 26
0
def process_output(item, work):
    logger.detail('Appending default output fields:' + str(item[1:]))
    # only include each field once
    for id in item[1:]:
        if id not in work['outputs']:
            work['outputs'].append(id)
Esempio n. 27
0
def ignore_item(item, work):
    logger.detail("Ignoring item: " + item[0])
Esempio n. 28
0
def process_embedded(item, work):
    logger.detail("Processing embedded code fragment")
    work['embeds'].append(item[1])
Esempio n. 29
0
File: ast.py Progetto: bcmd/BCMD
def process_input(item, work):
    logger.detail('Appending input fields:' + str(item[1:]))
    # only include each field once
    work['inputs'].extend([x for x in item[1:] if x not in work['inputs']])
Esempio n. 30
0
File: ast.py Progetto: bcmd/BCMD
def ignore_item(item, work):
    logger.detail("Ignoring item: " + item[0])
Esempio n. 31
0
def process_MA_rate(term, work, lhs):
    logger.detail("Processing mass action rateterm")
    if len(term[2]) > 2:
        logger.detail(
            "More than 1 rate term supplied, extras will be taken as concentration exponents"
        )

    i_expr, expr, deps = process_mathterm(term[2][1][1], work)
    mathterm = term[2][1][1]

    if lhs is None:
        logger.detail("Reaction has no LHS, omitting concentration dependence")
    else:
        num = []
        denom = []
        i_num = []
        i_denom = []

        m_num = ()
        m_denom = ()

        offset_exp_idx = 2
        for chem in lhs:
            name = chem['chem']

            if len(term[2]) > offset_exp_idx:
                i_exponent, exponent, exp_deps = process_mathterm(
                    term[2][offset_exp_idx][1], work)
                m_exponent = term[2][offset_exp_idx][1]

                num.append('pow(' + name + ',' + exponent + ')')
                i_num.append((('literal', 'pow('), ) + (('symbol', name), ) +
                             (('literal', ','), ) + i_exponent +
                             (('literal', ')'), ))
                deps = deps | exp_deps

                m_sub = ('arithmetic', '^', ('mathterm', name), ('mathterm',
                                                                 m_exponent))

                if m_num:
                    m_num = ('arithmetic', '*', ('mathterm', m_num),
                             ('mathterm', m_sub))
                else:
                    m_num = m_sub
            else:
                num.append(name)
                i_num.append((('symbol', name), ))

                if m_num:
                    m_num = ('arithmetic', '*', ('mathterm', m_num),
                             ('mathterm', name))
                else:
                    m_num = name

            if work['chemicals'][name] is not None:
                compartment = work['chemicals'][name]
                denom.append(compartment)
                i_denom.append((('symbol', compartment), ))

                if m_denom:
                    m_denom = ('arithmetic', '*', ('mathterm', m_denom),
                               ('mathterm', compartment))
                else:
                    m_denom = compartment

            deps = deps | set([name]) | work['symbols'][name]['depends']

            offset_exp_idx += 1

        factor = '(' + '*'.join(num) + ')'

        i_factor = i_num[0]
        for ifx in i_num[1:]:
            i_factor = i_factor + (('literal', '*'), ) + ifx

        i_factor = (('literal', '('), ) + i_factor + (('literal', ')'), )

        m_factor = m_num

        if len(denom) > 0:
            factor = factor + '/(' + '*'.join(denom) + ')'

            i_divisor = i_denom[0]
            for idn in i_denom[1:]:
                i_divisor = i_divisor + (('literal', '*'), ) + idn
            i_factor = i_factor + (('literal', '/('), ) + i_divisor + (
                ('literal', ')'), )

            m_factor = ('arithmetic', '/', ('mathterm', m_factor), ('mathterm',
                                                                    m_denom))

        expr = '(' + expr + '*' + factor + ')'
        i_expr = (('literal','('),) + i_expr + (('literal','*'),) \
                 + i_factor + (('literal',')'),)

        mathterm = ('arithmetic', '+', ('mathterm', mathterm), ('mathterm',
                                                                m_factor))

    return {
        'i_expr': i_expr,
        'expr': expr,
        'depends': deps,
        'mathterm': mathterm
    }
Esempio n. 32
0
File: ast.py Progetto: bcmd/BCMD
def process_MA_rate(term, work, lhs):
    logger.detail("Processing mass action rateterm")
    if len(term[2]) > 2:
        logger.detail("More than 1 rate term supplied, extras will be taken as concentration exponents")
    
    i_expr, expr, deps = process_mathterm(term[2][1][1], work)
    mathterm = term[2][1][1]
    
    if lhs is None:
        logger.detail("Reaction has no LHS, omitting concentration dependence")
    else:
        num = []
        denom = []
        i_num = []
        i_denom = []
        
        m_num = ()
        m_denom = ()
        
        offset_exp_idx = 2
        for chem in lhs:
            name = chem['chem']
            
            if len(term[2]) > offset_exp_idx:
                i_exponent, exponent, exp_deps = process_mathterm(term[2][offset_exp_idx][1], work)
                m_exponent = term[2][offset_exp_idx][1]
                
                num.append('pow(' + name + ',' + exponent + ')')
                i_num.append( (('literal','pow('),) + (('symbol', name),) + (('literal',','),) + i_exponent + (('literal',')'),) )
                deps = deps | exp_deps
                
                m_sub = ('arithmetic',
                         '^',
                         ('mathterm', name),
                         ('mathterm', m_exponent))
                
                if m_num:
                    m_num = ('arithmetic',
                             '*',
                             ('mathterm', m_num),
                             ('mathterm', m_sub))
                else:
                    m_num = m_sub
            else:
                num.append(name)
                i_num.append((('symbol',name),))
                
                if m_num:
                    m_num = ('arithmetic',
                             '*',
                             ('mathterm', m_num),
                             ('mathterm', name))
                else:
                    m_num = name
            
            if work['chemicals'][name] is not None:
                compartment = work['chemicals'][name]
                denom.append(compartment)
                i_denom.append((('symbol',compartment),))
                
                if m_denom:
                    m_denom = ('arithmetic',
                               '*',
                               ('mathterm', m_denom),
                               ('mathterm', compartment))
                else:
                    m_denom = compartment
            
            deps = deps | set([name]) | work['symbols'][name]['depends']
            
            offset_exp_idx += 1
        
        factor = '(' + '*'.join(num) + ')'
        
        i_factor = i_num[0]
        for ifx in i_num[1:]:
            i_factor = i_factor + (('literal','*'),) + ifx
        
        i_factor = (('literal','('),) + i_factor + (('literal',')'),)
        
        m_factor = m_num
        
        if len(denom) > 0:
            factor = factor + '/(' + '*'.join(denom) + ')'
            
            i_divisor = i_denom[0]
            for idn in i_denom[1:]:
                i_divisor = i_divisor + (('literal','*'),) + idn
            i_factor = i_factor + (('literal','/('),) + i_divisor + (('literal', ')'),)
            
            m_factor = ('arithmetic',
                        '/',
                        ('mathterm', m_factor),
                        ('mathterm', m_denom))
        
        expr = '(' + expr + '*' + factor + ')'
        i_expr = (('literal','('),) + i_expr + (('literal','*'),) \
                 + i_factor + (('literal',')'),)
                 
        mathterm = ('arithmetic',
                    '+',
                    ('mathterm', mathterm),
                    ('mathterm', m_factor))
    
    return { 'i_expr':i_expr, 'expr':expr, 'depends':deps, 'mathterm':mathterm }
Esempio n. 33
0
File: ast.py Progetto: bcmd/BCMD
def process_output(item, work):
    logger.detail('Appending default output fields:' + str(item[1:]))    
    # only include each field once
    for id in item[1:]:
        if id not in work['outputs']:
            work['outputs'].append(id)
Esempio n. 34
0
File: ast.py Progetto: bcmd/BCMD
def process_MM_rate(term, work, lhs):
    logger.detail("Processing Michaelis-Menten rateterm")
    arglist = term[2]
    if len(arglist) != len(lhs) + 2: # one for 'arglist' + one for Vmax
        logger.warn("Incorrect parameters for Michaelis-Menten rate term, skipping!")
        return { 'i_expr':('error','FAILED'), 'expr':'FAILED', 'depends':set() }
    
    i_num = []
    i_denom = []
    num = []
    denom = []
    
    i_expr, expr, deps = process_mathterm(arglist[1][1], work)
    num.append(expr)
    i_num.append(i_expr)
    
    m_num = arglist[1][1]
    m_denom = ()
    
    for idx in range(len(lhs)):
        logger.detail(idx)
        i_Km_expr, Km_expr, km_deps = process_mathterm(arglist[idx+2][1], work)
        deps = deps | km_deps | lhs[idx]['depends']
        
        m_Km = arglist[idx+2][1]
        
        # explicitly add Km to dependencies if it is a symbol in its own right
        # since otherwise the dependency won't get registered
        if Km_expr in work['symbols'].keys():
            deps = deps | set([Km_expr])
        
        chem = lhs[idx]['chem']
        i_chem = (('symbol',chem),)
        stoich = lhs[idx]['unmod']   # we only want the original value without the -1 multiplier
        i_stoich = lhs[idx]['i_unmod']
        
        m_stoich = lhs[idx]['mathterm_unmod']
        
        # x^1 is obviously just x...
        if stoich == '1':
            conc_pwr = chem
            Km_pwr = Km_expr
            i_conc_pwr = i_chem
            i_Km_pwr = i_Km_expr
            
            m_conc_pwr = chem
            m_Km_pwr = m_Km
        else:
            conc_pwr = 'pow(' + chem + ',' + stoich + ')'
            Km_pwr = 'pow(' + Km_expr + ',' + stoich + ')'
            i_conc_pwr = (('literal','pow('),) + i_chem + (('literal',','),) + i_stoich + (('literal',')'),)
            i_Km_pwr = (('literal','pow('),) + i_Km_expr + (('literal',','),) + i_stoich + (('literal',')'),)
            
            m_conc_pwr = ('arithmetic',
                          '^',
                          ('mathterm', chem),
                          ('mathterm', m_stoich))
            m_Km_pwr = ('arithmetic',
                        '^',
                        ('mathterm', m_Km),
                        ('mathterm', m_stoich))
        
        num.append(conc_pwr)
        denom.append('(' + Km_pwr + '+' + conc_pwr + ')')
        i_num.append(i_conc_pwr)
        i_denom.append((('literal', '('),) + i_Km_pwr + (('literal','+'),) + i_conc_pwr + (('literal',')'),))
        
        m_num = ('arithmetic',
                 '*',
                 ('mathterm', m_num),
                 ('mathterm', m_conc_pwr))
        
        m_sub = ('arithmetic',
                 '+',
                 ('mathterm', m_Km_pwr),
                 ('mathterm', m_conc_pwr))
        
        if m_denom:
            m_denom = ('arithmetic',
                       '*',
                       ('mathterm', m_denom),
                       ('mathterm', m_sub))
        else:
            m_denom = m_sub
    
    num_expr = '*'.join(num)
    denom_expr = '*'.join(denom)
    expr = '((' + num_expr + ')/(' + denom_expr + '))'
    
    i_num_expr = i_num[0]
    for iex in i_num[1:]:
        i_num_expr = i_num_expr + (('literal','*'),) + iex
    i_denom_expr = i_denom[0]
    for iex in i_denom[1:]:
        i_denom_expr = i_denom_expr + (('literal','*'),) + iex

    i_expr = (('literal','(('),) + i_num_expr + (('literal',')/('),) \
             + i_denom_expr + (('literal','))'),)
    
    mathterm = ('arithmetic',
                '/',
                ('mathterm', m_num),
                ('mathterm', m_denom))
    
    return { 'i_expr':i_expr, 'expr':expr, 'depends':deps, 'mathterm': mathterm }
Esempio n. 35
0
File: ast.py Progetto: bcmd/BCMD
def process_embedded(item, work):
    logger.detail("Processing embedded code fragment")
    work['embeds'].append(item[1])
Esempio n. 36
0
def process_MM_rate(term, work, lhs):
    logger.detail("Processing Michaelis-Menten rateterm")
    arglist = term[2]
    if len(arglist) != len(lhs) + 2:  # one for 'arglist' + one for Vmax
        logger.warn(
            "Incorrect parameters for Michaelis-Menten rate term, skipping!")
        return {
            'i_expr': ('error', 'FAILED'),
            'expr': 'FAILED',
            'depends': set()
        }

    i_num = []
    i_denom = []
    num = []
    denom = []

    i_expr, expr, deps = process_mathterm(arglist[1][1], work)
    num.append(expr)
    i_num.append(i_expr)

    m_num = arglist[1][1]
    m_denom = ()

    for idx in range(len(lhs)):
        logger.detail(idx)
        i_Km_expr, Km_expr, km_deps = process_mathterm(arglist[idx + 2][1],
                                                       work)
        deps = deps | km_deps | lhs[idx]['depends']

        m_Km = arglist[idx + 2][1]

        # explicitly add Km to dependencies if it is a symbol in its own right
        # since otherwise the dependency won't get registered
        if Km_expr in work['symbols'].keys():
            deps = deps | set([Km_expr])

        chem = lhs[idx]['chem']
        i_chem = (('symbol', chem), )
        stoich = lhs[idx][
            'unmod']  # we only want the original value without the -1 multiplier
        i_stoich = lhs[idx]['i_unmod']

        m_stoich = lhs[idx]['mathterm_unmod']

        # x^1 is obviously just x...
        if stoich == '1':
            conc_pwr = chem
            Km_pwr = Km_expr
            i_conc_pwr = i_chem
            i_Km_pwr = i_Km_expr

            m_conc_pwr = chem
            m_Km_pwr = m_Km
        else:
            conc_pwr = 'pow(' + chem + ',' + stoich + ')'
            Km_pwr = 'pow(' + Km_expr + ',' + stoich + ')'
            i_conc_pwr = (('literal', 'pow('), ) + i_chem + (
                ('literal', ','), ) + i_stoich + (('literal', ')'), )
            i_Km_pwr = (('literal', 'pow('), ) + i_Km_expr + (
                ('literal', ','), ) + i_stoich + (('literal', ')'), )

            m_conc_pwr = ('arithmetic', '^', ('mathterm', chem), ('mathterm',
                                                                  m_stoich))
            m_Km_pwr = ('arithmetic', '^', ('mathterm', m_Km), ('mathterm',
                                                                m_stoich))

        num.append(conc_pwr)
        denom.append('(' + Km_pwr + '+' + conc_pwr + ')')
        i_num.append(i_conc_pwr)
        i_denom.append((('literal', '('), ) + i_Km_pwr + (('literal', '+'), ) +
                       i_conc_pwr + (('literal', ')'), ))

        m_num = ('arithmetic', '*', ('mathterm', m_num), ('mathterm',
                                                          m_conc_pwr))

        m_sub = ('arithmetic', '+', ('mathterm', m_Km_pwr), ('mathterm',
                                                             m_conc_pwr))

        if m_denom:
            m_denom = ('arithmetic', '*', ('mathterm', m_denom), ('mathterm',
                                                                  m_sub))
        else:
            m_denom = m_sub

    num_expr = '*'.join(num)
    denom_expr = '*'.join(denom)
    expr = '((' + num_expr + ')/(' + denom_expr + '))'

    i_num_expr = i_num[0]
    for iex in i_num[1:]:
        i_num_expr = i_num_expr + (('literal', '*'), ) + iex
    i_denom_expr = i_denom[0]
    for iex in i_denom[1:]:
        i_denom_expr = i_denom_expr + (('literal', '*'), ) + iex

    i_expr = (('literal','(('),) + i_num_expr + (('literal',')/('),) \
             + i_denom_expr + (('literal','))'),)

    mathterm = ('arithmetic', '/', ('mathterm', m_num), ('mathterm', m_denom))

    return {
        'i_expr': i_expr,
        'expr': expr,
        'depends': deps,
        'mathterm': mathterm
    }
Esempio n. 37
0
def logModelInfo(model, config):
    logger.detail('\n\n** work **\n', False)
    logger.detail(model)
    
    # log the main actual equation system
    logger.message("\n\n** equations **")
    for name in model['diffs']:
        sym = model['symbols'][name]
        if sym['conflicts'] > 0: tag = '[CONFLICT-?] '
        else: tag = ''
        
        lhs = name + "'"
        for aux in model['auxiliaries'][name]:
            mass = aux[0]
            if mass < 0:
               mass = mass * -1
               op = ' - '
            else:
               op = ' + '
            lhs = lhs + op + str(mass) + ' ' + aux[1] + "'"
        
        for diff in sym['diffs']:
            logger.message(tag + lhs + ' = ' + diff['expr'])
    
    for name in model['algs']:
        sym = model['symbols'][name]
        if sym['conflicts'] > 0: tag = '[CONFLICT-?] '
        else: tag = ''
        for alg in sym['algs']:
            logger.message(tag + 'f(' + name + ') : 0 = ' + alg['expr'])

    # log dependency info
    logger.message("\n\n** dependency analysis **")
    logger.message("\nThe following solver variables are used in the model:")
    for name in sorted(model['diffs'], key=str.lower): logger.message(name)
    for name in sorted(model['algs'], key=str.lower): logger.message(name)
    
    logger.detail("\nThe following intermediate variables or parameters are used by the model:", False)
    for name in sorted(model['required'], key=str.lower):
        if name in model['assigned']:
            logger.detail(name + ' (assigned)')
        else:
            logger.detail(name + ' (unassigned)')
    
    if model['inputs']:
        logger.message('\nThe following symbols are declared as inputs:')
        for name in sorted(model['inputs'], key=str.lower):
            logger.message(name)
    
    if model['params']:
        logger.message('\nThe following symbols are parameters, independent of the solver variables:')
        for name in sorted(model['params'], key=str.lower):
            logger.message(name)
        
        logger.message('\nThe following parameters have no dependencies at all:')
        for name in sorted(model['params'], key=str.lower):
            if len(model['symbols'][name]['depends']) == 0:
                logger.message(name)
    
    if model['intermeds']:
        logger.message('\nThe following symbols are intermediates, with solver variable dependencies:')
        for name in sorted(model['intermeds'], key=str.lower):
            logger.message(name)
    
    if model['unused']:
        logger.message('\nThe following intermediate variables or parameters are declared but unused:')
        for name in sorted(model['unused'], key=str.lower): logger.message(name)
        if config['unused']:
            logger.message('(NB: unused variables will still be calculated)')
        else:
            logger.message('(NB: unused variables will NOT be calculated)')
            
    undoc = [ x for x in model['symbols'] if not [y for y in model['symbols'][x]['docs'] if not y.startswith('+')] ]
    if undoc:
        logger.message('\nThe following symbols are not documented:')
        for name in sorted(undoc, key=str.lower): logger.message(name)

    unassigned = set(model['symlist']) - model['assigned']
    if unassigned:
        logger.warn('\nThe following symbols are never explicitly assigned (will default to 0):')
        for name in sorted(unassigned, key=str.lower):
            logger.warn(name)

    if model['extern']:
        logger.warn('\nThe following external dependencies are declared but unsatisfied:\n')
        for name in sorted(model['extern'], key=str.lower): logger.warn(name)

    if model['unknown']:
        logger.warn("\nThe model makes use of the following non-standard functions:")
        for name in model['unknown']: logger.warn(name)
    
    # examine circular dependencies
    logger.detail("\nCircular dependencies:")
    for name in model['symbols'].keys():
        if model['symbols'][name]['circular']:
            if name in model['roots']:
                logger.detail(name + " (is a solver var)")
            elif name in model['unused']:
                logger.detail(name + ' (unused)')
            else:
                LHS = model['symbols'][name]['depends'] & set(model['roots'])
                if len(LHS) == 0:
                    logger.detail(name + " (no LHS dependencies)")
                else:
                    logger.detail(name + ' ' + str(LHS))
    
    logger.message('')

    logger.message('** summary for model %s **' % config['name'])
    logger.message('%d model variables (%d differential, %d algebraic)' % (len(model['roots']), len(model['diffs']), len(model['algs'])))
    logger.message('%d intermediate variables (%d unused)' % (len(model['intermeds']), len([x for x in model['intermeds'] if x in model['unused']])))
    logger.message('%d parameters (%d unused)' % (len(model['params']), len([x for x in model['params'] if x in model['unused']])))
    logger.message('%d unsatisfied external dependencies\n' % len(model['extern']))

    logger.message('')