1""" 2PySCeS - Python Simulator for Cellular Systems (http://pysces.sourceforge.net) 3 4Copyright (C) 2004-2020 B.G. Olivier, J.M. Rohwer, J.-H.S Hofmeyr all rights reserved, 5 6Brett G. Olivier (bgoli@users.sourceforge.net) 7Triple-J Group for Molecular Cell Physiology 8Stellenbosch University, South Africa. 9 10Permission to use, modify, and distribute this software is given under the 11terms of the PySceS (BSD style) license. See LICENSE.txt that came with 12this distribution for specifics. 13 14NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 15Brett G. Olivier 16""" 17from __future__ import division, print_function 18from __future__ import absolute_import 19from __future__ import unicode_literals 20 21from .version import __version__ 22 23import os 24import math, operator 25import numpy 26 27CurrentDirectory = os.getcwd() # temporary thing 28 29# this is a PySCeS specific hack 30from pysces import output_dir as CurrentDirectory 31 32from .InfixParser import MyInfixParser 33InfixParser = MyInfixParser() 34InfixParser.buildlexer() 35InfixParser.buildparser(debug=0, debugfile='infix.dbg', 36 tabmodule='infix_tabmodule', outputdir=CurrentDirectory) 37InfixParser.setNameStr('self.', '()') 38 39#print 'CurrentDirectory', CurrentDirectory 40 41class MapList(list): 42 def __init__(self, *args): 43 list.__init__(self,*args) 44 45 def asSet(self): 46 return set(self.__getslice__(0, self.__len__())) 47 48 49class NewCoreBase(object): 50 __DEBUG__ = False 51 name = None 52 annotations = None 53 54 def getName(self): 55 return self.name 56 57 def setName(self,name): 58 self.name = name 59 60 def get(self, attr): 61 """Return an attribute whose name is str(attr)""" 62 return self.__getattribute__(attr) 63 64 def getAnnotation(self): 65 """Returns an annotation dictionary""" 66 if self.annotations == None: 67 self.annotations = {} 68 return self.annotations.copy() 69 70 def setAnnotation(self, key, value): 71 """Set an annotation as a key:value pair""" 72 if self.annotations == None: 73 self.annotations = {} 74 self.annotations.update({key : value}) 75 76 77class NumberBase(NewCoreBase): 78 value = None 79 value_initial = None 80 81 def __call__(self): 82 return self.value 83 84 def getValue(self): 85 return self.value 86 87 def setValue(self, v): 88 self.value = v 89 90 91class Compartment(NewCoreBase): 92 size = None 93 dimensions = None 94 Compartment = None 95 reactions = None 96 species = None 97 area = None 98 99 def __init__(self, name, compartment=None): 100 self.name = name 101 self.Compartment = compartment 102 self.reactions = [] 103 self.species = [] 104 105 def __call__(self): 106 return self.size 107 108 def setSize(self, size, dim): 109 self.size = size 110 assert dim in [0,1,2,3], '\nOkeee! %s dimensions?' % dim 111 self.dimensions = dim 112 113 def setArea(self, area=None): 114 if area == None and self.dimensions == 2: 115 self.area = self.size 116 if self.__DEBUG__: print('Setting reactive area to size for 2D compartment %s' % self.name) 117 elif area == None and self.dimensions == 3: 118 self.area = (113.09733552923255*self.size**2.0)**(0.33333333333333331) 119 if self.__DEBUG__: print('Setting reactive area to surface area for 3D compartment %s (assuming a sphere geometry)' % self.name) 120 self.area = area 121 122 def hasReactions(self): 123 return MapList([r.name for r in self.reactions]) 124 125 def hasSpecies(self): 126 return MapList([s.name for s in self.species]) 127 128 def addReaction(self, reaction): 129 if reaction.name not in self.hasReactions(): 130 self.reactions.append(reaction) 131 self.__setattr__(reaction.name, reaction) 132 if self.__DEBUG__: print('Adding reaction %s' % reaction.name) 133 134 def addSpecies(self, species): 135 if species.name not in self.hasSpecies(): 136 self.species.append(species) 137 self.__setattr__(species.name, species) 138 if self.__DEBUG__: print('Adding species %s' % species.name) 139 else: 140 if self.__DEBUG__: print('Species %s already added' % species.name) 141 142 def getDimensions(self): 143 return self.dimensions 144 145 def getCompartment(self): 146 return self.Compartment 147 148 def hasCompartment(self): 149 if self.Compartment != None: 150 return True 151 else: 152 return False 153 154 def isVolume(self): 155 if self.dimensions == 3: return True 156 else: return False 157 158 def isArea(self): 159 if self.dimensions == 2: return True 160 else: return False 161 162 def isLength(self): 163 if self.dimensions == 1: return True 164 else: return False 165 166 def isPoint(self): 167 if self.dimensions == 0: return True 168 else: return False 169 170 171class BaseUnit(NewCoreBase): 172 '''Base Unit can be of type: time, substance, volume''' 173 _types = ('time', 'substance', 'volume','area','length') 174 value = 1.0 175 type = None 176 177 def __init__(self, name, type): 178 self.name = name 179 assert type in self._types, '\nType must be one of: %s' % str(self._types) 180 self.type = type 181 182 def __call__(self): 183 return self.value 184 185 def getType(self): 186 return self.type 187 188 189class SimpleUnit(NewCoreBase): 190 exponent = 1.0 191 scale = 0.0 192 multiplier = 1.0 193 baseunit = None 194 type = None 195 196 def __init__(self, baseunit, name, exp=1.0, scale=0.0, mult=1.0): 197 self.baseunit = baseunit 198 self.exponent = exp 199 self.scale = scale 200 self.multiplier = mult 201 self.name = name 202 self.type = baseunit.type 203 204 def __call__(self): 205 return (self.multiplier*self.baseunit()*10**self.scale)**self.exponent 206 207 def getType(self): 208 return self.type 209 210 211class CompoundUnit(NewCoreBase): 212 units = None 213 _HAS_USERNAME = False 214 215 def __init__(self, name=None): 216 self.units = [] 217 if name != None: 218 self.name = name 219 self._HAS_USERNAME = True 220 else: 221 self.name = '' 222 223 def __call__(self): 224 U = 1.0 225 for u in self.units: 226 U *= u() 227 return U 228 229 def addUnit(self, unit): 230 self.units.append(unit) 231 if not self._HAS_USERNAME: 232 self.name = '%s%s' % (self.name, unit.getName()) 233 234 def getUnits(self): 235 return self.units 236 237 def hasUnits(self): 238 return MapList([u.getName() for u in self.units]) 239 240 241class Species(NumberBase): 242 subs = None 243 prods = None 244 mods = None 245 fixed = False 246 Compartment = None 247 __amount__ = False 248 249 def __init__(self, name, value): 250 self.setName(name) 251 self.value = value 252 self.value_initial = value 253 self.subs = [] 254 self.prods = [] 255 self.mods = [] 256 257 def getCompartment(self): 258 return self.Compartment 259 260 def setCompartment(self, c): 261 self.Compartment = c 262 263 def hasCompartment(self): 264 if self.Compartment != None: 265 return True 266 else: 267 return False 268 269 def setSubstrate(self, reaction): 270 self.__setattr__(reaction.name, reaction) 271 self.subs.append(reaction) 272 273 def setProduct(self, reaction): 274 self.__setattr__(reaction.name, reaction) 275 self.prods.append(reaction) 276 277 def setModifier(self, reaction): 278 self.__setattr__(reaction.name, reaction) 279 self.mods.append(reaction) 280 281 def isSubstrateOf(self): 282 return MapList([r.name for r in self.subs]) 283 284 def isProductOf(self): 285 return MapList([r.name for r in self.prods]) 286 287 def isModifierOf(self): 288 return MapList([r.name for r in self.mods]) 289 290 def isReagentOf(self): 291 return MapList(self.isSubstrateOf() + self.isProductOf()) 292 293 def setAmount(self, b): 294 self.__amount__ = bool(b) 295 296 def isAmount(self): 297 return self.__amount__ 298 299class SpeciesAssignmentRule(Species): 300 formula = None 301 code_string = None 302 _names = None 303 _functions = None 304 type = 'assignment' 305 _TIME_ = None 306 307 def __init__(self, name, value): 308 Species.__init__(self, name, value) 309 310 def __call__(self): 311 exec(self.xcode) 312 return self.value 313 314 def addFormula(self, formula): 315 formula = formula.replace('self.','') 316 self.formula = formula 317 InfixParser.setNameStr('self.', '()') 318 InfixParser.parse(formula) 319 self.code_string = 'self.value=%s' % InfixParser.output 320 self._names = InfixParser.names 321 self._functions = InfixParser.functions 322 self.xcode = compile(self.code_string, '<string>', 'exec') 323 324 def addModelAttr(self, obj): 325 self.__setattr__(obj.name, obj) 326 327class Function(NewCoreBase): 328 formula = None 329 code_string = None 330 xcode = None 331 value = None 332 _names = None 333 args = None 334 _TIME_ = None 335 336 def __init__(self, name): 337 self.setName(name) 338 self.args = [] 339 340 def __call__(self, *args): 341 for ar in range(len(args)): 342 self.__setattr__(self.args[ar], args[ar]) 343 exec(self.xcode) 344 return self.value 345 346 def setArg(self, var, value=None): 347 self.__setattr__(var, value) 348 self.args.append(var) 349 350 def addFormula(self, formula): 351 formula = formula.replace('self.','') 352 self.formula = formula 353 InfixParser.setNameStr('self.', '') 354 InfixParser.SymbolReplacements = {'_TIME_':'_TIME_()'} 355 InfixParser.parse(formula) 356 self._names = InfixParser.names 357 self.code_string = 'self.value=%s' % InfixParser.output 358 self.xcode = compile(self.code_string, '<string>', 'exec') 359 360class Reaction(NewCoreBase): 361 modifiers = None 362 substrates = None 363 products = None 364 stoichiometry = None 365 multistoich = None 366 multistoich_enabled = False 367 parameters = None 368 functions = None 369 reversible = True 370 formula = None 371 code_string = None 372 rate = None 373 xcode = None 374 _names = None 375 _functions = None 376 _TIME_ = None 377 Compartment = None 378 379 def __call__(self): 380 exec(self.xcode) 381 return self.rate 382 383 def __init__(self, name): 384 self.setName(name) 385 self.modifiers = [] 386 self.substrates = [] 387 self.products = [] 388 self.stoichiometry = {} 389 self.parameters = [] 390 self.functions = [] 391 self.multistoich = [] 392 393 def addSubstrate(self, species): 394 self.__setattr__(species.name, species) 395 self.substrates.append(species) 396 397 def addProduct(self, species): 398 self.__setattr__(species.name, species) 399 self.products.append(species) 400 401 def addModifier(self, species): 402 self.__setattr__(species.name, species) 403 self.modifiers.append(species) 404 405 def addFormula(self, formula): 406 formula = formula.replace('self.','') 407 self.formula = formula 408 InfixParser.setNameStr('self.', '()') 409 InfixParser.parse(formula) 410 self._names = InfixParser.names 411 self._functions = InfixParser.functions 412 self.code_string = 'self.rate=%s' % InfixParser.output 413 self.xcode = compile(self.code_string, '<string>', 'exec') 414 415 def addParameter(self, par): 416 self.__setattr__(par.name, par) 417 self.parameters.append(par) 418 419 def addFunction(self, func): 420 self.__setattr__(func.name, func) 421 self.functions.append(func) 422 423 def hasProducts(self, t=type): 424 return MapList([p.name for p in self.products]) 425 426 def hasSubstrates(self): 427 return MapList([s.name for s in self.substrates]) 428 429 def hasModifiers(self): 430 return MapList([m.name for m in self.modifiers]) 431 432 def hasParameters(self): 433 return MapList([p.name for p in self.parameters]) 434 435 def hasReagents(self): 436 return MapList(self.hasSubstrates() + self.hasProducts()) 437 438 def setCompartment(self, compartment): 439 self.Compartment = compartment 440 441 def getCompartment(self): 442 return self.Compartment 443 444 def hasCompartment(self): 445 if self.Compartment != None: 446 return True 447 else: 448 return False 449 450 451class Parameter(NumberBase): 452 association = None 453 454 def __init__(self, name, value): 455 self.name = name 456 self.value = value 457 self.value_initial = value 458 self.association = [] 459 460 def setAssociation(self, reac): 461 self.association.append(reac) 462 self.__setattr__(reac.name, reac) 463 464 def isParameterOf(self): 465 return MapList([a.name for a in self.association]) 466 467class AssignmentRule(Parameter): 468 formula = None 469 code_string = None 470 _names = None 471 _functions = None 472 type = 'assignment' 473 _TIME_ = None 474 fixed = False # added so that assignment rules can modify fixed species 475 476 def __init__(self, name, value): 477 Parameter.__init__(self, name, value) 478 479 def __call__(self): 480 exec(self.xcode) 481 return self.value 482 483 def addFormula(self, formula): 484 formula = formula.replace('self.','') 485 self.formula = formula 486 InfixParser.setNameStr('self.', '()') 487 InfixParser.parse(formula) 488 self.code_string = 'self.value=%s' % InfixParser.output 489 self._names = InfixParser.names 490 self._functions = InfixParser.functions 491 self.xcode = compile(self.code_string, '<string>', 'exec') 492 493 def addModelAttr(self, obj): 494 self.__setattr__(obj.name, obj) 495 496 497class RateRule(NewCoreBase): 498 formula = None 499 rate = None 500 xcode = None 501 code_string = None 502 _names = None 503 _functions = None 504 compartment = None 505 506 def __init__(self, name, formula): 507 self.name = name 508 self.addFormula(formula) 509 510 def __call__(self): 511 exec(self.xcode) 512 return self.rate 513 514 def addFormula(self, formula): 515 formula = formula.replace('self.','') 516 self.formula = formula.replace('()','') 517 InfixParser.setNameStr('self.', '()') 518 InfixParser.parse(self.formula) 519 self.code_string = 'self.rate=%s' % InfixParser.output 520 self._names = InfixParser.names 521 self._functions = InfixParser.functions 522 self.xcode = compile(self.code_string, 'RateRule: %s' % self.name, 'exec') 523 524 def getFormula(self): 525 return self.formula 526 527 def addModelAttr(self, obj): 528 self.__setattr__(obj.name, obj) 529 530 531class ODE(NewCoreBase): 532 sdot = None 533 value = None 534 coefficients = None 535 reactions = None 536 independent = None 537 ode_terms = None 538 formula = '' 539 formula_alt = '' 540 code_string = 'self.value=' 541 code_string_alt = 'sdot=' 542 543 def __init__(self, species, independent=True): 544 self.sdot = species 545 self.name = 'ODE_'+species.name 546 self.reactions = [] 547 self.coefficients = [] 548 self.ode_terms = [] 549 self.independent = independent 550 551 def __call__(self): 552 exec(self.code_string) 553 return self.value 554 555 def addReaction(self, reaction, coefficient): 556 self.reactions.append(reaction) 557 self.coefficients.append(coefficient) 558 if coefficient > 0.0: 559 if coefficient == 1.0: 560 term = '+self.%s() ' % (reaction.name) 561 aterm = '+(%s) ' % (reaction.code_string.replace('self.rate=','')) 562 fterm = '+%s' % (reaction.name) 563 afterm = '+ (%s) ' % (reaction.formula) 564 else: 565 term = '+%g*self.%s() ' % (abs(coefficient), reaction.name) 566 aterm = '+%g*(%s) ' % (abs(coefficient), reaction.code_string.replace('self.rate=','')) 567 fterm = '+%g*%s' % (abs(coefficient), reaction.name) 568 afterm = '+ %g*(%s) ' % (abs(coefficient), reaction.formula) 569 else: 570 if coefficient == -1.0: 571 term = '-self.%s() ' % (reaction.name) 572 aterm = '-(%s) ' % (reaction.code_string.replace('self.rate=','')) 573 fterm = '-%s' % (reaction.name) 574 afterm = '- (%s) ' % (reaction.formula) 575 else: 576 term = '-%g*self.%s() ' % (abs(coefficient), reaction.name) 577 aterm = '-%g*(%s) ' % (abs(coefficient), reaction.code_string.replace('self.rate=','')) 578 fterm = '-%g*%s' % (abs(coefficient), reaction.name) 579 afterm = '- %g*(%s) ' % (abs(coefficient), reaction.formula) 580 self.ode_terms.append(term) 581 self.code_string += term 582 self.code_string_alt += aterm 583 self.formula += fterm 584 self.formula_alt += afterm 585 self.__setattr__(reaction.name, reaction) 586 587 def hasReactions(self): 588 return MapList([r.name for r in self.reactions]) 589 590 def getFormula(self): 591 return self.code_string 592 593 def getGlobalFormula(self): 594 return self.code_string_alt 595 596 597class StructMatrix(NewCoreBase): 598 """ 599 This class is specifically designed to store structural matrix information 600 give it an array and row/col index permutations it can generate its own 601 row/col labels given the label src. 602 """ 603 604 array = None 605 ridx = None 606 cidx = None 607 row = None 608 col = None 609 610 def __init__(self, array, ridx, cidx, row=None, col=None): 611 """ 612 Instantiate with array and matching row/col index arrays, optional label arrays 613 """ 614 self.array = array 615 self.ridx = ridx 616 self.cidx = cidx 617 self.row = row 618 self.col = col 619 self.shape = array.shape 620 621 def __call__(self): 622 return self.array 623 624 def getRowsByIdx(self, *args): 625 """Return the rows referenced by index (1,3,5)""" 626 return self.array.take(args, axis=0) 627 628 def getColsByIdx(self, *args): 629 """Return the columns referenced by index (1,3,5)""" 630 return self.array.take(args, axis=1) 631 632 def setRow(self, src): 633 """ 634 Assuming that the row index array is a permutation (full/subset) 635 of a source label array by supplying that source to setRow it 636 maps the row labels to ridx and creates self.row (row label list) 637 """ 638 self.row = [src[r] for r in self.ridx] 639 640 def setCol(self, src): 641 """ 642 Assuming that the col index array is a permutation (full/subset) 643 of a source label array by supplying that src to setCol 644 maps the row labels to cidx and creates self.col (col label list) 645 """ 646 self.col = [src[c] for c in self.cidx] 647 648 def getRowsByName(self, *args): 649 """Return the rows referenced by label ('s','x','d')""" 650 assert self.row != None, "\nI need row labels" 651 try: 652 return self.array.take([self.row.index(l) for l in args], axis=0) 653 except Exception as ex: 654 print(ex) 655 print("\nValid row labels are: %s" % self.row) 656 return None 657 658 def getColsByName(self, *args): 659 """Return the columns referenced by label ('s','x','d')""" 660 assert self.col != None, "\nI need column labels" 661 try: 662 return self.array.take([self.col.index(l) for l in args], axis=1) 663 except Exception as ex: 664 print(ex) 665 print("Valid column labels are: %s" % self.col) 666 return None 667 668 def getLabels(self, axis='all'): 669 """Return the matrix labels ([rows],[cols]) where axis='row'/'col'/'all'""" 670 if axis == 'row': return self.row 671 elif axis == 'col': return self.col 672 else: return self.row, self.col 673 674 def getIndexes(self, axis='all'): 675 """Return the matrix indexes ([rows],[cols]) where axis='row'/'col'/'all'""" 676 if axis == 'row': return self.ridx 677 elif axis == 'col': return self.cidx 678 else: return self.ridx, self.cidx 679 680 def getByIdx(self, row, col): 681 assert row in self.ridx, '\n%s is an invalid index' % row 682 assert col in self.cidx, '\n%s is an invalid index' % col 683 return self.array[row, col] 684 685 def getByName(self, row, col): 686 assert row in self.row, '\n%s is an invalid name' % row 687 assert col in self.col, '\n%s is an invalid name' % col 688 return self.array[self.row.index(row), self.col.index(col)] 689 690 def setByIdx(self, row, col, val): 691 assert row in self.ridx, '\n%s is an invalid index' % row 692 assert col in self.cidx, '\n%s is an invalid index' % col 693 self.array[row, col] = val 694 695 def setByName(self, row, col, val): 696 assert row in self.row, '\n%s is an invalid name' % row 697 assert col in self.col, '\n%s is an invalid name' % col 698 self.array[self.row.index(row), self.col.index(col)] = val 699 700 def shape(self): 701 return self.array.shape 702 703class EventAssignment(NumberBase): 704 variable = None 705 _names = None 706 formula = None 707 code_string = None 708 xcode = None 709 710 def __call__(self): 711 self.variable.value = self.value 712 if self.__DEBUG__: print('\tAssigning %s = %s' % (self.variable.name, self.value)) 713 return True 714 715 def __init__(self, name='None'): 716 self.setName(name) 717 718 def setVariable(self, var): 719 self.variable = var 720 721 def setFormula(self, formula): 722 self.formula = formula 723 InfixParser.setNameStr('self.', '()') 724 ## InfixParser.SymbolReplacements = {'_TIME_':'_TIME_()'} 725 InfixParser.parse(formula) 726 self._names = InfixParser.names 727 self.code_string = 'self.value=%s' % InfixParser.output 728 self.xcode = compile(self.code_string, '<string>', 'exec') 729 if self.__DEBUG__: '\t', self.name, self.code_string 730 731 def evaluateAssignment(self): 732 exec(self.xcode) 733 734 735class Event(NewCoreBase): 736 trigger = None 737 delay = 0.0 738 739 formula = None 740 code_string = None 741 xcode = None 742 743 state0 = False 744 state = False 745 746 assignments = None 747 _TIME_ = None 748 _ASS_TIME_ = 0.0 749 _need_action = False 750 _names = None 751 _time_symbol = None 752 753 def __init__(self, name): 754 self.setName(name) 755 self.assignments = [] 756 757 def __call__(self, time): 758 self._TIME_.set(time) 759 exec(self.xcode) 760 if self.state0 and not self.state: 761 self.state0 = self.state 762 if not self.state0 and self.state: 763 for ass in self.assignments: 764 ass.evaluateAssignment() 765 self.state0 = self.state 766 self._need_action = True 767 self._ASS_TIME_ = self._TIME_() + self.delay 768 if self.__DEBUG__: print('event %s is evaluating at %s' % (self.name, time)) 769 if self._need_action and self._TIME_() >= self._ASS_TIME_: 770 for ass in self.assignments: 771 ass() 772 if self.__DEBUG__: print('event %s is assigning at %s (delay=%s)' % (self.name, time, self.delay)) 773 self._need_action = False 774 775 def setTrigger(self, formula, delay=0.0): 776 self.formula = formula 777 self.delay = delay 778 InfixParser.setNameStr('self.', '()') 779 ## print self._time_symbol 780 if self._time_symbol != None: 781 InfixParser.SymbolReplacements = {self._time_symbol : '_TIME_'} 782 ## self.formula = formula.replace(self._time_symbol, '_TIME_') 783 InfixParser.parse(formula) 784 self._names = InfixParser.names 785 self.code_string = 'self.state=%s' % InfixParser.output 786 if self._time_symbol != None: 787 InfixParser.setNameStr('', '') 788 InfixParser.SymbolReplacements = {self._time_symbol : '_TIME_'} 789 InfixParser.parse(formula) 790 self.formula = InfixParser.output 791 self.xcode = compile(self.code_string, '<string>', 'exec') 792 if self.__DEBUG__: self.name, self.code_string 793 794 def setTriggerAttributes(self, core): 795 # TODO: experimental 796 for n in self._names: 797 self.__setattr__(n, core.__getattribute__(n)) 798 799 def setAssignment(self, var, formula): 800 ass = EventAssignment(var.name) 801 ass.setVariable(var) 802 ass.setFormula(formula) 803 self.assignments.append(ass) 804 self.__setattr__('_'+var.name, ass) 805 806class PieceWise(NewCoreBase): 807 """ 808 Generic piecewise class written by me! 809 810 - *args* a dictionary of piecewise information generated by the InfixParser 811 """ 812 name = None 813 value = None 814 formula = None 815 code_string = None 816 xcode = None 817 _names = None 818 _TIME_ = None 819 820 def __init__(self, pwd): 821 pwd = pwd.copy() 822 if pwd['other'] != None: 823 other = 'self.value = %s' % pwd.pop('other') 824 else: 825 other = 'pass' 826 pwd.pop('other') 827 InfixParser.setNameStr('self.', '') 828 InfixParser.SymbolReplacements = {'_TIME_':'_TIME_()'} 829 self._names = [] 830 if len(list(pwd.keys())) == 1: 831 formula = pwd[0][0] 832 InfixParser.parse(formula) 833 for n in InfixParser.names: 834 if n not in self._names and n != '_TIME_()': 835 self._names.append(n) 836 formula = InfixParser.output 837 self.code_string = 'if %s:\n self.value = %s\nelse:\n %s' %\ 838 (formula, pwd[0][1], other) 839 self.formula = self.code_string.replace('self.','') 840 else: 841 formula = pwd[0][0] 842 InfixParser.parse(formula) 843 for n in InfixParser.names: 844 if n not in self._names and n != '_TIME_()': 845 self._names.append(n) 846 847 formula = InfixParser.output 848 self.code_string = 'if %s:\n self.value = %s\n' % (formula, pwd[0][1]) 849 pwd.pop(0) 850 for p in pwd: 851 formula = pwd[p][0] 852 InfixParser.SymbolReplacements = {'_TIME_':'_TIME_()'} 853 InfixParser.parse(formula) 854 for n in InfixParser.names: 855 if n not in self._names and n != '_TIME_()': 856 self._names.append(n) 857 formula = InfixParser.output 858 self.code_string += 'elif %s:\n self.value = %s\n' % (formula, pwd[p][1]) 859 self.code_string += 'else:\n %s' % other 860 self.formula = self.code_string.replace('self.','') 861 self.xcode = compile(self.code_string, 'PieceWise','exec') 862 863 864 def __call__(self): 865 exec(self.xcode) 866 return self.value 867 868 869class Time(object): 870 value = None 871 name = '__TIME__' 872 def __init__(self, t=0): 873 self.value = t 874 875 def __call__(self): 876 return self.value 877 878 def set(self, t): 879 self.value=t 880 881## def delay(*args): 882 ## print 'delay() ignored' 883 ## return 1.0 884 885class NewCore(NewCoreBase): 886 __nDict__ = None 887 reactions = None 888 species = None 889 species_variable = None 890 __model__ = None 891 __InitDict__ = None 892 __not_inited__ = None 893 global_parameters = None 894 __parameter_store__ = None 895 forcing_functions = None 896 __rules__ = None 897 __events__ = None 898 # new 899 __compartments__ = None 900 compartments = None 901 rate_rules = None 902 description = "Pysces Core2" 903 __uDict__ = None 904 stoichiometric_matrix = None 905 struct = None 906 ODEs = None 907 functions = None 908 _TIME_ = None 909 events = None 910 __sDict__ = None 911 __KeyWords__ = None 912 __piecewises__ = None 913 piecewise_functions = None 914 netStoich = None 915 916 def __init__(self, model, iValues=True, netStoich=True): 917 # setup core dictionaries 918 self.__nDict__ = model.__nDict__ 919 self.__sDict__ = model.__sDict__ 920 self.__KeyWords__ = model.__KeyWords__ 921 if self.__KeyWords__['Modelname'] != None: 922 self.setName(self.__KeyWords__['Modelname']) 923 else: 924 self.setName('PySCeSModel') 925 if self.__KeyWords__['Description'] != None: 926 self.setDescription(self.__KeyWords__['Description']) 927 else: 928 self.setDescription('PySCeSModel') 929 930 self.__model__ = model 931 self.__InitDict__ = model.__InitDict__ 932 if not iValues: 933 if self.__DEBUG__: print(self.__InitDict__) 934 for k in list(self.__InitDict__.keys()): 935 self.__InitDict__[k] = getattr(self.__model__, k) 936 for c in model.__compartments__: 937 model.__compartments__[c]['size'] = getattr(self.__model__, c) 938 self.netStoich = netStoich 939 940 self.global_parameters = [] 941 self.__parameter_store__ = [] 942 self.__not_inited__ = [] 943 self.forcing_functions = [] 944 self.__rules__ = model.__rules__ 945 self.__uDict__ = model.__uDict__ 946 self.__piecewises__ = model.__piecewises__ 947 InfixParser.__pwcntr__ = 0 948 949 # start building objects 950 self.__compartments__ = model.__compartments__ 951 self.addCompartments() 952 self._TIME_ = Time() 953 self.addPieceWiseFunctions() # this adds any piecewise functions 954 self.addSpecies() 955 956 # the order is important from here as eg functions can occur in rate equations 957 try: 958 self.__functions__ = model.__functions__ 959 except: 960 self.__functions__ = {} 961 if self.__DEBUG__: print('No functions') 962 self.functions = [] 963 self.addFunctions() 964 self.addReactions() 965 self.generateMappings() 966 self.setAssignmentRules() 967 self.setRateRules() 968 969 # add event support 970 self.__events__ = self.__model__.__eDict__ 971 self.events = [] 972 self.addEvents() 973 self.addPieceWiseFunctions(update=True) # this updates their attributes 974 975 ## # get rid of _TIME_ in not intited 976 ## if '_TIME_' in self.__not_inited__: 977 ## self.__not_inited__.pop(self.__not_inited__.index('_TIME_')) 978 if len(self.__not_inited__) > 0: 979 print("\nWARNING: Uninitialised parameters: %s (value set to zero)" % self.__not_inited__) 980 981 def __cleanString__(self,s): 982 s = s.lstrip() 983 s = s.rstrip() 984 return s 985 986 ## def parseForcingFunctions(self): 987 ## self.__rules__ = {} 988 ## try: 989 ## ff = self.__function_forced_str__.split('\n') 990 ## for f in ff: 991 ## if f != '': 992 ## f = f.split('=') 993 ## f[0] = f[0].replace('self.','') 994 ## f[1] = f[1].replace('self.','') 995 ## self.__rules__.setdefault(self.__cleanString__(f[0]), self.__cleanString__(f[1])) 996 ## except Exception, ex: 997 ## pass 998 # print 'No forcing functions (%s).' % ex 999 1000 def setDescription(self, txt): 1001 self.description = str(txt) 1002 1003 def getDescription(self): 1004 return str(self.description) 1005 1006 def setGlobalUnits(self, **kwargs): 1007 for un in list(kwargs.keys()): 1008 self.__uDict__[un] = (kwargs[un][0], kwargs[un][1]) 1009 if self.__DEBUG__: print("Modified \"%s\" to be %i*%s*10**%i" % (un, kwargs[un][0], un, kwargs[un][1])) 1010 1011 def getGlobalUnits(self): 1012 return self.__uDict__ 1013 1014 def addPieceWiseFunctions(self, update=False): 1015 if not update: 1016 self.piecewise_functions = [] 1017 for pw in list(self.__piecewises__.keys()): 1018 if self.__DEBUG__: print('Info: adding piecewise function:%s' % pw) 1019 P = PieceWise(self.__piecewises__[pw]) 1020 P.setName(pw) 1021 P.__setattr__('_TIME_', self.__getattribute__('_TIME_')) 1022 self.piecewise_functions.append(P) 1023 self.__setattr__(pw, P) 1024 else: 1025 for pw in self.piecewise_functions: 1026 for a in pw._names: 1027 pw.__setattr__(a, self.__getattribute__(a)) 1028 1029 1030 1031 def addOneCompartment(self, name, size, dimensions, compartment=None, area=None): 1032 C = Compartment(name, compartment) 1033 C.setSize(size, dimensions) 1034 ## C.setArea(area) 1035 self.compartments.append(C) 1036 self.__setattr__(name, C) 1037 1038 def addCompartments(self): 1039 self.compartments = [] 1040 for C in self.__compartments__: 1041 c2 = self.__compartments__[C] 1042 if self.__DEBUG__: print('Adding compartment %s' % c2['name']) 1043 self.addOneCompartment(c2['name'], c2['size'], c2['dimensions'], 1044 compartment=c2['compartment'], area=None) 1045 1046 def addOneSpecies(self, species, value, fix=False, comp=None, amount=False, fullName=None): 1047 s = Species(species, value) 1048 ## if comp != None: 1049 s.setCompartment(comp) 1050 s.setAmount(amount) 1051 s.setAnnotation('sbml_name', fullName) 1052 if fix: s.fixed = True 1053 self.__setattr__(species, s) 1054 self.species.append(s) 1055 if not fix: self.species_variable.append(s) 1056 if comp != None: 1057 comp.addSpecies(s) 1058 1059 def addSpecies(self): 1060 self.species = [] 1061 self.species_variable = [] 1062 for s in self.__sDict__: 1063 ## print s 1064 ## print self.__sDict__[s] 1065 name = self.__sDict__[s]['name'] 1066 if s in self.__InitDict__: 1067 val = self.__InitDict__[s] 1068 else: 1069 val = 0.0 1070 ## print val 1071 fix = self.__sDict__[s]['fixed'] 1072 if self.__sDict__[s]['compartment'] != None: 1073 comp = self.__getattribute__(self.__sDict__[s]['compartment']) 1074 else: 1075 comp = None 1076 amount = self.__sDict__[s]['isamount'] 1077 fullName = None 1078 if 'fullName' in self.__sDict__[s]: 1079 fullName = self.__sDict__[s]['fullName'] 1080 self.addOneSpecies(name, val, fix=fix, comp=comp, amount=amount, fullName=fullName) 1081 1082 def addOneFunction(self, name, args, formula): 1083 func = Function(name) 1084 # TODO: make better 1085 setattr(func, '_TIME_', self._TIME_) 1086 for a in args: 1087 func.setArg(a) 1088 func.addFormula(formula) 1089 self.functions.append(func) 1090 self.__setattr__(name, func) 1091 1092 1093 def addFunctions(self): 1094 for f in list(self.__functions__.keys()): 1095 self.addOneFunction(f,\ 1096 self.__functions__[f]['args'],\ 1097 self.__functions__[f]['formula']) 1098 1099 def addOneReaction(self, rDict): 1100 r = Reaction(rDict['name']) 1101 if rDict['compartment'] != None: 1102 C = self.__getattribute__(rDict['compartment']) 1103 r.setCompartment(C) 1104 C.addReaction(r) 1105 fullName = None 1106 if 'fullName' in rDict: 1107 r.setAnnotation('sbml_name', rDict['fullName']) 1108 1109 # add dummy reaction kinetic law 1110 # TODO: make better 1111 setattr(r, '_TIME_', self._TIME_) 1112 if rDict['RateEq'] != None: 1113 r.addFormula(rDict['RateEq'].replace('self.','')) 1114 else: 1115 r.addFormula('J') 1116 self.addParameter('J') 1117 if rDict['Type'] == 'Irrev': r.reversible = False 1118 # now we can add formulas that occured in the rate equation 1119 if len(r._functions) > 0: 1120 for func in r._functions: 1121 try: 1122 r.addFunction(self.__getattribute__(func)) 1123 except Exception as ex: 1124 print(ex) 1125 print('\nHave you added the function objects yet (addFunctions())') 1126 1127 #fxnames = self.hasFixedSpecies() 1128 processed_parameter = [] 1129 1130 # where parameters are defined `locally' per reaction 1131 for p in rDict['Params']: 1132 p = p.replace('self.','') 1133 if p not in self.hasGlobalParameters() and not (p in self.hasFixedSpecies() or p in self.__compartments__): 1134 if self.__DEBUG__: print("Adding parameter %s from networkdict" % p) 1135 self.addParameter(p) 1136 par = self.__getattribute__(p) 1137 par.setAssociation(r) 1138 r.addParameter(par) 1139 processed_parameter.append(p) 1140 elif not (p in self.hasFixedSpecies() or p in self.__compartments__): 1141 if self.__DEBUG__: print("Updating parameter %s from networkdict" % p) 1142 pidx = self.hasGlobalParameters().index(p) 1143 self.global_parameters[pidx].setAssociation(r) 1144 r.addParameter(self.global_parameters[pidx]) 1145 processed_parameter.append(p) 1146 1147 #print self.hasGlobalParameters() 1148 # where parameters are not `locally' defined and are extracted from Req (ie from SBML) 1149 for p in r._names: 1150 p = p.replace('self.','') 1151 if p == '_TIME_': 1152 pass 1153 elif p in [pw.name for pw in self.piecewise_functions]: 1154 pass 1155 elif p in self.hasCompartments() and p not in processed_parameter: 1156 C = self.__getattribute__(p) 1157 C.addReaction(r) 1158 # TODO: this will work until isParameterOf is called on a compartment object 1159 r.addParameter(C) 1160 # dirty alternative 1161 #setattr(r, C.name, C) 1162 processed_parameter.append(p) 1163 elif p not in processed_parameter and p not in self.hasGlobalParameters() and p not in self.hasSpecies(): 1164 if self.__DEBUG__: print("Adding parameter %s from global" % p) 1165 self.addParameter(p) 1166 par = self.__getattribute__(p) 1167 par.setAssociation(r) 1168 r.addParameter(par) 1169 processed_parameter.append(p) 1170 1171 elif p not in processed_parameter and p not in self.hasSpecies(): 1172 if self.__DEBUG__: print("Updating parameter %s from global" % p) 1173 pidx = self.hasGlobalParameters().index(p) 1174 self.global_parameters[pidx].setAssociation(r) 1175 r.addParameter(self.global_parameters[pidx]) 1176 processed_parameter.append(p) 1177 1178 self.__setattr__(rDict['name'], r) 1179 self.reactions.append(r) 1180 1181 def addParameter(self, name): 1182 if name not in self.__piecewises__: 1183 if name in self.__InitDict__: 1184 par = Parameter(name, self.__InitDict__[name]) 1185 else: 1186 par = Parameter(name, 0.0) 1187 if name not in self.__not_inited__: self.__not_inited__.append(name) 1188 self.global_parameters.append(par) 1189 self.__setattr__(name, par) 1190 1191 def addReactions(self): 1192 self.reactions = [] 1193 for r in self.__model__.reactions: 1194 self.addOneReaction(self.__nDict__[r]) 1195 non_parameters = self.hasGlobalParameters()+self.hasSpecies()+self.hasFixedSpecies() 1196 for k in list(self.__InitDict__.keys()): 1197 if k not in non_parameters: 1198 if self.__DEBUG__: print('Adding new parameter:', k) 1199 self.addParameter(k) 1200 1201 def replaceParameterWithRule(self, ar): 1202 par = self.__getattribute__(ar.name) 1203 for r in par.association: 1204 ar.setAssociation(r) 1205 setattr(r, ar.name, ar) 1206 r.parameters[r.hasParameters().index(ar.name)] = ar 1207 self.global_parameters[self.hasGlobalParameters().index(ar.name)] = ar 1208 self.__setattr__(ar.name, ar) 1209 1210 def replaceFixedSpeciesWithRule(self, ar): 1211 fs = self.__getattribute__(ar.name) 1212 ar.fixed = fs.fixed 1213 for r in fs.subs: 1214 ar.setSubstrate(r) 1215 setattr(r, ar.name, ar) 1216 r.substrates[r.hasSubstrates().index(ar.name)] = ar 1217 for r in fs.prods: 1218 ar.setProduct(r) 1219 setattr(r, ar.name, ar) 1220 r.products[r.hasProducts().index(ar.name)] = ar 1221 for r in fs.mods: 1222 ar.setModifier(r) 1223 setattr(r, ar.name, ar) 1224 r.modifiers[r.hasModifiers().index(ar.name)] = ar 1225 self.species[self.hasSpecies().index(ar.name)] = ar 1226 self.__setattr__(ar.name, ar) 1227 1228 def replaceSpeciesWithRule(self, ar): 1229 fs = self.__getattribute__(ar.name) 1230 for r in fs.subs: 1231 ar.setSubstrate(r) 1232 setattr(r, ar.name, ar) 1233 r.substrates[r.hasSubstrates().index(ar.name)] = ar 1234 for r in fs.prods: 1235 ar.setProduct(r) 1236 setattr(r, ar.name, ar) 1237 r.products[r.hasProducts().index(ar.name)] = ar 1238 for r in fs.mods: 1239 ar.setModifier(r) 1240 setattr(r, ar.name, ar) 1241 r.modifiers[r.hasModifiers().index(ar.name)] = ar 1242 self.species[self.hasSpecies().index(ar.name)] = ar 1243 self.species_variable[self.hasVariableSpecies().index(ar.name)] = ar 1244 self.__setattr__(ar.name, ar) 1245 1246 def setAssignmentRules(self): 1247 aps = [self.__rules__[ar]['name'] for ar in self.__rules__ if self.__rules__[ar]['type'] == 'assignment'] 1248 ## for p in self.global_parameters + [self.get(fs) for fs in self.hasFixedSpecies()]: 1249 for p in self.global_parameters + self.species: 1250 #print p.name 1251 if p.name in aps: 1252 if self.__DEBUG__: print('Assigning: %s = %s' % (p.name, self.__rules__[p.name]['formula'])) 1253 p2 = None 1254 # TODO: make better 1255 if p.name in self.hasGlobalParameters(): 1256 p2 = AssignmentRule(p.name, self.__InitDict__[p.name]) 1257 setattr(p2, '_TIME_', self._TIME_) 1258 self.replaceParameterWithRule(p2) 1259 elif p.name in self.hasFixedSpecies(): 1260 p2 = SpeciesAssignmentRule(p.name, self.__InitDict__[p.name]) 1261 p2.setCompartment(p.getCompartment()) 1262 setattr(p2, '_TIME_', self._TIME_) 1263 self.replaceFixedSpeciesWithRule(p2) 1264 elif p.name in self.hasVariableSpecies(): 1265 p2 = SpeciesAssignmentRule(p.name, self.__InitDict__[p.name]) 1266 p2.setCompartment(p.getCompartment()) 1267 setattr(p2, '_TIME_', self._TIME_) 1268 self.replaceSpeciesWithRule(p2) 1269 1270 assert isinstance(p2, AssignmentRule) or isinstance(p2, SpeciesAssignmentRule), "\nHappy assertion error" 1271 #print type(p2) 1272 p2.addFormula(self.__rules__[p.name]['formula']) 1273 ## print p2._names 1274 for n in p2._names+p2._functions: 1275 p2.addModelAttr(self.__getattribute__(n)) 1276 ## # setup initial values 1277 ## p2.value_initial = self.p2() 1278 if p2.name in self.__not_inited__: 1279 self.__not_inited__.pop(self.__not_inited__.index(p.name)) 1280 for p in self.global_parameters: 1281 if p.name in self.hasAssignmentRules(): 1282 # TODO assignment rules need a list of properties 1283 for ar in p._names: 1284 if ar in self.hasAssignmentRules(): 1285 setattr(p, ar, self.__getattribute__(ar)) 1286 #TODO this is where things will go wrong if fs --> ar contains nested ar's 1287 1288 def setRateRules(self): 1289 # TODO mayvbe split into two methods for now read from self.__rules__ 1290 # TODO add functions to rules 1291 ars = [self.__rules__[ar]['name'] for ar in self.__rules__ if self.__rules__[ar]['type'] == 'rate'] 1292 self.rate_rules = [] 1293 for rr in ars: 1294 rrobj = RateRule(self.__rules__[rr]['name'], self.__rules__[rr]['formula']) 1295 ## print 'RR:', rrobj.name, rrobj._names, rrobj._functions 1296 for symb in rrobj._names+rrobj._functions: 1297 rrobj.addModelAttr(self.__getattribute__(symb)) 1298 self.rate_rules.append(rrobj) 1299 # TODO investgiate this as it is problematic, the rate rule 1300 # is not a model property as such more an ODE property 1301 ## self.__setattr__(rrobj.name, rrobj) 1302 if self.__DEBUG__: print('Adding RateRule %s with formula: %s' % (rrobj.name, rrobj.formula)) 1303 1304 def addOneEvent(self, e): 1305 """Add a single event using an event dictionary """ 1306 # translate self.__events__[e] to e 1307 1308 ev = Event(e['name']) 1309 ev._time_symbol = e['tsymb'] 1310 ev.setTrigger(e['trigger'], e['delay']) 1311 # associate model attributes with event 1312 # TODO: check that this still works 1313 ev.setTriggerAttributes(self) 1314 ## for n in ev._names: 1315 ## setattr(ev, n, self.__getattribute__(n)) 1316 # for each assignment 1317 for ass in e['assignments']: 1318 ev.setAssignment(self.__getattribute__(ass), e['assignments'][ass]) 1319 assref = getattr(ev, '_'+ass) # don\t like this at all :-( 1320 # associate model attributes with assignment 1321 for n in assref._names: 1322 setattr(assref, n, self.__getattribute__(n)) 1323 self.events.append(ev) 1324 self.__setattr__(ev.name, ev) 1325 setattr(ev, '_TIME_', self._TIME_) 1326 1327 def addEvents(self): 1328 # TODO: check that you can change the trigger on the fly (might need a setAttr thing in event obj) 1329 self.events = [] 1330 # for each event 1331 for e in self.__events__: 1332 self.addOneEvent(self.__events__[e]) 1333 1334 def generateMappings(self): 1335 ## self.netStoich = False 1336 for reac in self.reactions: 1337 if self.netStoich: 1338 for reag in self.__nDict__[reac.name]['Reagents']: 1339 if self.__nDict__[reac.name]['Reagents'][reag] < 0.0: 1340 reac.addSubstrate(self.__getattribute__(reag.replace('self.',''))) 1341 self.__getattribute__(reag.replace('self.','')).setSubstrate(self.__getattribute__(reac.name)) 1342 else: 1343 reac.addProduct(self.__getattribute__(reag.replace('self.',''))) 1344 self.__getattribute__(reag.replace('self.','')).setProduct(self.__getattribute__(reac.name)) 1345 reac.stoichiometry.setdefault(reag.replace('self.',''), self.__nDict__[reac.name]['Reagents'][reag]) 1346 else: 1347 for reag in self.__nDict__[reac.name]['AllReagents']: 1348 if reag[1] < 0.0: 1349 reac.addSubstrate(self.__getattribute__(reag[0].replace('self.',''))) 1350 self.__getattribute__(reag[0].replace('self.','')).setSubstrate(self.__getattribute__(reac.name)) 1351 else: 1352 reac.addProduct(self.__getattribute__(reag[0].replace('self.',''))) 1353 self.__getattribute__(reag[0].replace('self.','')).setProduct(self.__getattribute__(reac.name)) 1354 reac.multistoich.append((reag[0].replace('self.',''), reag[1])) 1355 if reag[0].replace('self.','') in reac.stoichiometry: 1356 reac.multistoich_enabled = True 1357 reac.stoichiometry.setdefault(reag[0].replace('self.',''), reag[1]) 1358 for mod in self.__nDict__[reac.name]['Modifiers']: 1359 reac.addModifier(self.__getattribute__(mod.replace('self.',''))) 1360 self.__getattribute__(mod.replace('self.','')).setModifier(self.__getattribute__(reac.name)) 1361 ## print 'I AM LEGEND' 1362 ## print reac.stoichiometry 1363 ## print reac.multistoich 1364 ## print 'reac.multistoich_enabled', reac.multistoich_enabled 1365 ## print self.__nDict__[reac.name]['Reagents'] 1366 ## print self.__nDict__[reac.name]['AllReagents'] 1367 1368 def setStoichiometricMatrix(self): 1369 vspec = self.hasVariableSpecies() 1370 react = self.hasReactions() 1371 nm = numpy.zeros((len(vspec), len(react)),'d') 1372 for sp in vspec: 1373 for r in self.get(sp).isReagentOf(): 1374 nm[vspec.index(sp)][react.index(r)] = self.get(r).stoichiometry[sp] 1375 # this is if absolute stoichiometry value is used 1376 ## for r in self.get(sp).isSubstrateOf(): 1377 ## nm[vspec.index(sp)][react.index(r)] = abs(self.get(r).stoichiometry[sp]) 1378 ## for r in self.get(sp).isProductOf(): 1379 ## nm[vspec.index(sp)][react.index(r)] = -abs(self.get(r).stoichiometry[sp]) 1380 self.stoichiometric_matrix = StructMatrix(nm, list(range(len(vspec))), list(range(len(react)))) 1381 self.stoichiometric_matrix.setRow(vspec) 1382 self.stoichiometric_matrix.setCol(react) 1383 1384 def addODEs(self): 1385 self.ODEs = [] 1386 for varspec in self.stoichiometric_matrix.row: 1387 if self.struct != None: 1388 if varspec not in self.struct.Nr.row: 1389 if self.__DEBUG__: print('Creating dependent ODE_%s' % varspec) 1390 ode = ODE(self.get(varspec), independent=False) 1391 else: 1392 if self.__DEBUG__: print('Creating independent ODE_%s' % varspec) 1393 ode = ODE(self.get(varspec), independent=True) 1394 else: 1395 if self.__DEBUG__: print('Creating independent* ODE_%s (*assumed - no structural information available)' % varspec) 1396 ode = ODE(self.get(varspec), independent=True) 1397 mrow = self.stoichiometric_matrix.getRowsByName(varspec) 1398 for e in range(len(mrow[0])): 1399 if mrow[0,e] != 0.0: 1400 print('Adding term: %s*%s' % (mrow[0,e], self.stoichiometric_matrix.col[e])) 1401 ode.addReaction(self.get(self.stoichiometric_matrix.col[e]), mrow[0,e]) 1402 self.__setattr__(ode.name, ode) 1403 self.ODEs.append(ode) 1404 self.__setattr__('xcode_'+ode.name, compile(ode.getGlobalFormula(), '<string>', 'exec')) 1405 1406 def hasODEs(self): 1407 return MapList([o.name for o in self.ODEs]) 1408 1409 def evalODEs(self, odes): 1410 return [v() for v in odes] 1411 1412 def evalXcode(self, ode): 1413 exec(self.__getattribute__('xcode_'+ode.name)) 1414 return sdot 1415 1416 def hasFunctions(self): 1417 return MapList([f.name for f in self.functions]) 1418 1419 def hasReactions(self): 1420 return MapList([r.name for r in self.reactions]) 1421 1422 def hasSpecies(self): 1423 return MapList([s.name for s in self.species]) 1424 1425 def hasFixedSpecies(self): 1426 return MapList([s.name for s in self.species if s.fixed]) 1427 1428 def hasVariableSpecies(self): 1429 return MapList([s.name for s in self.species if not s.fixed]) 1430 1431 def findReactionsThatIncludeAllSpecifiedReagents(self, *args): 1432 assert len(args) > 1, '\nNeed two or more species for this one!' 1433 setlist = [self.__getattribute__(s).isReagentOf().asSet() for s in args] 1434 isect = setlist[0] 1435 for s in setlist: 1436 isect.intersection_update(s) 1437 return MapList(isect) 1438 1439 def hasGlobalParameters(self): 1440 return MapList(p.name for p in self.global_parameters) 1441 1442 def hasAssignmentRules(self): 1443 return MapList([ar.name for ar in self.global_parameters+self.species if hasattr(ar, 'type')=='assignemnt']) 1444 1445 def hasAssignmentRules(self): 1446 return MapList([ar.name for ar in self.global_parameters+self.species if hasattr(ar, 'type')=='rate']) 1447 1448 def hasEvents(self): 1449 return MapList(e.name for e in self.events) 1450 1451 def hasCompartments(self): 1452 return MapList(c.name for c in self.compartments) 1453 1454## if __psyco_active__: 1455 ## psyco.bind(NewCoreBase) 1456 ## psyco.bind(NumberBase) 1457 ## psyco.bind(Species) 1458 ## psyco.bind(Parameter) 1459 ## psyco.bind(AssignmentRule) 1460 ## psyco.bind(Reaction) 1461 ## psyco.bind(ODE) 1462 ## psyco.bind(NewCore) 1463 1464 1465 1466