This file is indexed.

/usr/share/cain/state/ParameterEvaluation.py is in cain 1.9-8.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
"""Implements functions for parameter evaluation."""

# If we are running the unit tests.
if __name__ == '__main__':
    import sys
    sys.path.insert(1, '..')

from fio.MathematicaWriter import mathematicaForm

import re
import string
import math
# Import the math functions for use in evaluating expressions.
from math import *

def getParameters(expression, identifiers):
    parameters = []
    while True:
        matchObject = re.search('([a-zA-z]|_)[a-zA-Z0-9_]*', expression)
        if not matchObject:
            break
        id = matchObject.group()
        if id in identifiers:
            parameters.append(id)
        expression = expression[matchObject.end():]
    return list(set(parameters))
        
def getIdentifiers(expression):
    identifiers = []
    while True:
        matchObject = re.search('([a-zA-z]|_)[a-zA-Z0-9_]*', expression)
        if not matchObject:
            break
        identifiers.append(matchObject.group())
        expression = expression[matchObject.end():]
    return identifiers
        
# CONTINUE REMOVE
def checkIdentifiers(identifiers):
    """Check the identifiers. If they are valid return None, otherwise return
    an error message. The identifiers may not be objects defined in math:
    ['pow', 'cosh', 'ldexp', 'hypot', 'tan', 'asin', 'log', 'fabs', 'floor', 'sqrt', 'frexp', 'degrees', 'pi', 'log10', '__doc__', 'fmod', 'atan', '__file__', 'ceil', 'sinh', '__name__', 'cos', 'e', 'tanh', 'radians', 'sin', 'atan2', 'modf', 'exp', 'acos']
    Parameters:
    - identifiers is a list of the identifiers."""
    # Check that each is a valid SBML identifier.
    reserved = math.__dict__.keys()
    for id in identifiers:
        matchObject = re.match('([a-zA-z]|_)[a-zA-Z0-9_]*', id)
        if not (matchObject and matchObject.group(0) == id):
            return '"%s" is not a valid identifier.' % id
        if id in reserved:
            return '"%s" is a reserved word. You cannot use it as an identifier.' % id
    # Indicate that there were no errors.
    return None

class Mangler:
    def __init__(self, prefix, identifiers):
        self.prefix = prefix
        self.identifiers = identifiers

    def __call__(self, matchObject):
        m = matchObject.group()
        if m in self.identifiers:
            return self.prefix + m
        else:
            return m

def mangle(expression, prefix, identifiers):
    """Mangle the identifiers in the expression. Return the mangled
    expression."""
    mangler = Mangler(prefix, identifiers)
    return re.sub('([a-zA-z]|_)[a-zA-Z0-9_]*', mangler, expression)

class KineticLawDecorator:
    """Mangle each parameter identifier by adding a prefix. Change species
    identifiers to array elements."""
    def __init__(self, parameterPrefix, parameterIdentifiers, speciesArrayName,
                 speciesIdentifiers):
        self.parameterPrefix = parameterPrefix
        self.parameterIdentifiers = parameterIdentifiers
        self.speciesArrayName = speciesArrayName
        self.speciesIdentifiers = speciesIdentifiers

    def __call__(self, expression):
        return re.sub('([a-zA-z]|_)[a-zA-Z0-9_]*', self.decorateIdentifier,
                      expression)

    def decorateIdentifier(self, matchObject):
        m = matchObject.group()
        # Special case: the e in 1e-5 is not a parameter.
        n = matchObject.start()
        if m == 'e' and n != 0 and matchObject.string[n-1] in\
               ['.'] + list(string.digits):
            return m
        if m in self.parameterIdentifiers:
            return self.parameterPrefix + m
        elif m in self.speciesIdentifiers:
            return self.speciesArrayName + '[' +\
                str(self.speciesIdentifiers.index(m)) + ']'
        else:
            return m

class KineticLawDecoratorMathematica:
    """Change species identifiers to function evaluations."""
    def __init__(self, speciesIdentifiers):
        self.speciesIdentifiers = speciesIdentifiers

    def __call__(self, expression):
        # Change species identifiers to function evaluations.
        expression = re.sub('([a-zA-z]|_)[a-zA-Z0-9_]*',
                            self.decorateIdentifier, expression)
        # Fix the floating-point numbers.
        return re.sub(r'[0-9]+\.?[0-9]*(e|E)(\+|-)?[0-9]+',
                      self.decorateNumber, expression)

    def decorateIdentifier(self, matchObject):
        m = matchObject.group()
        if m in self.speciesIdentifiers:
            return m + '[t]'
        else:
            return m

    def decorateNumber(self, matchObject):
        return mathematicaForm(float(matchObject.group()))

class KineticLawDecoratorSbml:
    """Change parameter identifiers to parameter values.
    - parameters is the dictionary of parameters"""
    def __init__(self, parameters):
        self.parameters = parameters

    def __call__(self, expression):
        # Change species identifiers to function evaluations.
        return re.sub('([a-zA-z]|_)[a-zA-Z0-9_]*', self.decorateIdentifier,
                      expression)

    def decorateIdentifier(self, matchObject):
        m = matchObject.group()
        if m in self.parameters:
            return self.parameters[m].expression
        else:
            return m

def evaluateValues(parameters):
    """Evaluate the expressions in the dictionary of parameters and
    compartments. Return True if the evaluation is successful. Store
    the parameter values in the 'value' member data field."""
    # Check the identifiers.
    for id in parameters:
        matchObject = re.match('([a-zA-z]|_)[a-zA-Z0-9_]*', id)
        if not (matchObject and matchObject.group() == id):
            return id + ' is not a valid identifier.'
    # Start with null values.
    for id in parameters:
        parameters[id].value = None
    # The prefix for mangling parameters.
    prefix = '__p_'
    # Make a list of identifiers and mangled expressions.
    remaining = [(id, mangle(parameters[id].expression, prefix, 
                             parameters.keys())) for id in parameters]
    passes = 0
    while remaining:
        passes += 1
        if passes > len(parameters):
            remainingIds = [x[0] for x in remaining]
            return 'Could not evaluate the expressions for: ' +\
                ', '.join(remainingIds) + '.'
        for id, expression in remaining:
            # Try to evaluate the expression.
            try:
                value = eval(expression)
            except:
                continue
            # Try to convert it to a floating point number.
            try:
                value = float(value)
            except:
                return 'Could not convert the expression for "%s" to a floating point number.' % id
            # Record the value.
            parameters[id].value = value
            exec(prefix + id + ' = value')
            remaining.remove((id, expression))
    # Indicate that there were no errors.
    return None

def evaluateParametersOld(__parameters):
    """Evaluate the expressions in the dictionary of parameters. Return True
    if the evaluation is successful. Store the parameter values in the 
    'value' member data field."""
    # I hide the variables in a class to avoid collision with the parameter
    # identifiers.
    class __Namespace:
        pass
    __names = __Namespace()
    __names.parameters = __parameters
    # Check the identifiers.
    __names.error = checkIdentifiers(__names.parameters)
    if __names.error:
        return __names.error
    # Start with null values.
    for id in __names.parameters:
        __names.parameters[id].value = None
    # Evaluate the expressions.
    __names.remaining = __names.parameters.keys()
    __names.passes = 0
    while __names.remaining:
        __names.passes += 1
        if __names.passes > len(__names.parameters):
            return 'Could not evaluate the expressions for ' +\
                ', '.join(__names.remaining) + '.'
        for id in __names.remaining:
            # Try to evaluate the expression.
            try:
                __names.value = eval(__names.parameters[id].expression)
            except:
                continue
            # Try to convert it to a floating point number.
            try:
                __names.value = float(__names.value)
            except:
                return 'Could not convert the expression for "%s" to a floating point number.' % id
            # Record the value.
            __names.parameters[id].value = __names.value
            exec(id + ' = __names.value')
            __names.remaining.remove(id)
    # Indicate that there were no errors.
    return None

def evaluateInitialAmounts(species, parameters):
    """Evaluate the propensity factors for the mass action kinetic laws.
    The parameter values must be evaluated before using this in this function.
    If the evaluation is successful return None. Otherwise return an error 
    message.
    Parameters:
    - species: A dictionary of species.
    - parameters: The dictionary of parameters."""
    # The prefix for mangling parameters.
    prefix = '__p_'
    # Evaluate the parameters.
    for id in parameters:
        assert parameters[id].value is not None
        exec(prefix + id + " = parameters['" + id + "'].value")
    parameterIdentifiers = parameters.keys()
    # Evaluate the initial amounts for the species.
    for id in species:
        # Start with a null value.
        species[id].initialAmountValue = None
        try:
            species[id].initialAmountValue =\
                eval(mangle(species[id].initialAmount, prefix, 
                            parameterIdentifiers))
        except:
            return 'Could not evaluate the initial amount for species '\
                + id + '.'
        # This form of the conditional checks for nan and other wierdness.
        if not species[id].initialAmountValue >= 0:
            return 'Species ' + id + ' does not have a non-negative initial amount.'
    # Indicate that there were no errors.
    return None

def evaluatePropensityFactors(reactions, parameters):
    """Evaluate the propensity factors for the mass action kinetic laws.
    The parameter values must be evaluated before using this in this function.
    If the evaluation is successful return None. Otherwise return an error 
    message.
    Parameters:
    - reactions: A list of reactions.
    - parameters: The dictionary of parameters."""
    # The prefix for mangling parameters.
    prefix = '__p_'
    # Evaluate the parameters.
    for id in parameters:
        assert parameters[id].value is not None
        exec(prefix + id + " = parameters['" + id + "'].value")
    parameterIdentifiers = parameters.keys()
    # Evaluate the propensity factors for the mass action kinetic laws.
    for r in reactions:
        # Start with a null value.
        r.propensityFactor = None
        if r.massAction:
            try:
                r.propensityFactor = eval(mangle(r.propensity, prefix, 
                                                 parameterIdentifiers))
            except:
                return 'Could not evaluate the propensity factor for reaction '\
                    + r.id + '.'
            # This form of the conditional checks for nan and other wierdness.
            if not r.propensityFactor >= 0:
                return 'Reaction ' + r.id + ' has a negative propensity factor.'
    # Indicate that there were no errors.
    return None

def makeValuesDictionary(model):
    values = {}
    for k, v in model.parameters.iteritems():
        values[k] = v
    for k, v in model.compartments.iteritems():
        values[k] = v
    return values

def evaluateModel(model):
    """Evaluate the parameters, the species initial amounts, and the
    reaction propensities for the mass action kinetic laws. Return
    None if successful. Otherwise return an error message."""
    values = makeValuesDictionary(model)
    return evaluateValues(values) or\
        evaluateInitialAmounts(model.species, values) or\
        evaluatePropensityFactors(model.reactions, values)

def evaluateModelInhomogeneous(model):
    """Evaluate the parameters and the species initial amounts. Return
    None if successful. Otherwise return an error message."""
    values = makeValuesDictionary(model)
    return evaluateValues(values) or\
        evaluateInitialAmounts(model.species, model.parameters)


def main():
    from Value import Value

    # The unit tests are in Species.py, Reaction.py, and Model.py.
    print mangle('a b c x y z', '__', ['a', 'b', 'c'])
    print mangle('a b c aa x y z', '__', ['a', 'b', 'c'])
    print mangle('(a+b-c)*aa**x(y)/z', '__', ['a', 'b', 'c'])

    print '\nKineticLawDecorator: s1 and s2 are species.'
    decorator = KineticLawDecorator('__p_', ['a', 'b', 'e'], 'x', ['s1', 's2'])

    expression = '6.42e-5'
    print expression
    print decorator(expression)

    print '\nKineticLawDecoratorMathematica: s1 and s2 are species.'
    decorator = KineticLawDecoratorMathematica(['s1', 's2'])

    expression = '0.5*s1'
    print expression
    print decorator(expression)

    expression = '1e-10*s1*s2'
    print expression
    print decorator(expression)

    expression = '1.23e-10'
    print expression
    print decorator(expression)

    expression = '1.23e10'
    print expression
    print decorator(expression)

    # CONTINUE: Make this work.
    expression = 'sqrt(s1)'
    print expression
    print decorator(expression)

    print '\nKineticLawDecoratorSbml: c1 and c2 are parameters.'
    decorator = KineticLawDecoratorSbml({'c1': Value('', '1'),
                                         'c2': Value('', '2')})

    expression = 'c1*s1'
    print expression
    print decorator(expression)

    expression = 'c1/c2*sqrt(c3)*s1'
    print expression
    print decorator(expression)


if __name__ == '__main__':
    main()