Skip to content

Commit a63c5fb

Browse files
committed
Update to Brent and multi-param to put in bounds. Update to Brent and findSim to handle presettling.
1 parent bf7c721 commit a63c5fb

File tree

3 files changed

+73
-13
lines changed

3 files changed

+73
-13
lines changed

Brent_minimization.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,30 @@ def enumerateFindSimFiles( location ):
8585
quit()
8686

8787
class EvalFunc:
88-
def __init__( self, objField, expts, weights, pool, modelFile ):
88+
def __init__( self, objField, expts, weights, pool, modelFile, presettle = [] ):
8989
self.objField = objField
9090
self.expts = expts
9191
self.weights = weights
9292
self.pool = pool # pool of available CPUs
9393
self.modelFile = modelFile
94+
self.presettle = presettle
9495

9596
def doEval( self, x ):
9697
ret = []
9798
spl = self.objField.split( '.' )
9899
assert( len(spl) == 2 )
99100
obj, field = spl
101+
102+
settleDict = {}
103+
if len( self.presettle ) == 3:
104+
presettleTime = float( self.presettle[2] )
105+
if presettleTime > 0:
106+
#print("{}".format( self.presettle ) )
107+
settleDict = findSim.innerMain( self.presettle[0], modelFile = self.presettle[1], hidePlot=True, silent=True, scaleParam=[obj,field,str(x)], settleTime = presettleTime )
108+
#print( "Doing presettle, len = {}".format( len(settleDict) ) )
109+
100110
for k in self.expts:
101-
ret.append( self.pool.apply_async( findSim.innerMain, (k,), dict(modelFile = self.modelFile, hidePlot=True, silent=True, scaleParam=[obj,field,str(x)]), callback = reportReturn ) )
111+
ret.append( self.pool.apply_async( findSim.innerMain, (k,), dict(modelFile = self.modelFile, hidePlot=True, silent=True, scaleParam=[obj,field,str(x)], settleDict=settleDict ), callback = reportReturn ) )
102112
score = [ i.get() for i in ret ]
103113
sumScore = sum([ s*w for s,w in zip(score, self.weights) if s>=0.0])
104114
sumWts = sum( [ w for s,w in zip(score, self.weights) if s>=0.0 ] )
@@ -111,8 +121,10 @@ def main():
111121
parser.add_argument( 'location', type = str, help='Required: Directory in which the scripts (in tsv format) are all located. OR: File in which each line is the filename of a scripts.tsv file, followed by weight to assign for that file.')
112122
parser.add_argument( '-n', '--numProcesses', type = int, help='Optional: Number of processes to spawn', default = 2 )
113123
parser.add_argument( '-m', '--model', type = str, help='Optional: Composite model definition file. First searched in directory "location", then in current directory.', default = "FindSim_compositeModel_1.g" )
114-
parser.add_argument( '-p', '--parameter_sweep', nargs='*', default=[], help='Does a parameter sweep in range 0.5-2x of each object.field pair.' )
115-
parser.add_argument( '-f', '--file', type = str, help='Optional: File name for output of parameter sweep', default = "" )
124+
parser.add_argument( '-p', '--parameter_optimize', nargs='*', default=[], help='Does a parameter optimization for each specified object.field pair.' )
125+
parser.add_argument( '-ps', '--presettle', nargs=3, default=[], help='Arguments: tsv_file, model_file, settle_time. Obtains values of all concentrations after a specified settle-time, so that all calculations for the optimization runs can be initialized to this presettled value. The tsv_file is to specify which subset of the model_file to use. This option is most useful in costly multiscale models.' )
126+
parser.add_argument( '-f', '--file', type = str, help='Optional: File name for output of parameter optimization', default = ""
127+
)
116128
args = parser.parse_args()
117129
location = args.location
118130
if location[-1] != '/':
@@ -130,13 +142,14 @@ def main():
130142
pool = Pool( processes = args.numProcesses )
131143

132144
results = {}
133-
for i in args.parameter_sweep:
145+
for i in args.parameter_optimize:
134146
print( "{}".format( i ) )
135147
spl = i.split( '.' )
136148
assert( len(spl) == 2 )
137149
obj, field = spl
138-
ev = EvalFunc( i, fnames, weights, pool, modelFile )
139-
results[i] = optimize.minimize_scalar( ev.doEval )
150+
ev = EvalFunc( i, fnames, weights, pool, modelFile, args.presettle )
151+
# Bounded method uses Bounded Brent method.
152+
results[i] = optimize.minimize_scalar( ev.doEval, method = 'bounded', bounds = (0.0, 100.0) )
140153
print( "\n Finished optimizing for " + i)
141154
print( "\n---------------- Completed ----------------- " )
142155
dumpData = False

findSim.py

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
**********************************************************************/
3434
3535
'''
36-
36+
from __future__ import print_function
3737
import heapq
3838
import pylab
3939
import numpy as np
@@ -545,7 +545,10 @@ def _scaleOneParam( self, params ):
545545

546546
obj = self.findObj( '/model', params[0] )
547547
scale = float( params[2] )
548-
assert( scale >= 0.0 and scale <= 100.0 )
548+
if not ( scale >= 0.0 and scale <= 100.0 ):
549+
print( "Error: Scale {} out of range".format( scale ) )
550+
assert( False )
551+
#assert( scale >= 0.0 and scale <= 100.0 )
549552
if params[1] == 'Kd':
550553
if not obj.isA[ "ReacBase" ]:
551554
raise SimError( "scaleParam: can only assign Kd to a Reac, was: '{}'".format( obj.className ) )
@@ -1435,11 +1438,19 @@ def main():
14351438
parser.add_argument( '-hs', '--hide_subplots', action="store_true", help='Hide subplot output of simulation. By default the graphs include dotted lines to indicate individual quantities (e.g., states of a molecule) that are being summed to give a total response. This flag turns off just those dotted lines, while leaving the main plot intact.' )
14361439
parser.add_argument( '-o', '--optimize_elec', action="store_true", help='Optimize electrical computation. By default the electrical computation runs for the entire duration of the simulation. With this flag the system turns off the electrical engine except during the times when electrical stimuli are being given. This can be *much* faster.' )
14371440
parser.add_argument( '-s', '--scale_param', nargs=3, default=[], help='Scale specified object.field by ratio.' )
1441+
parser.add_argument( '-settle_time', '--settle_time', type=float, default=0, help='Run model for specified settle time and return dict of {path,conc}.' )
14381442
args = parser.parse_args()
1439-
innerMain( args.script, modelFile = args.model, dumpFname = args.dump_subset, paramFname = args.param_file, hidePlot = args.hide_plot, hideSubplots = args.hide_subplots, optimizeElec = args.optimize_elec, scaleParam = args.scale_param )
1443+
innerMain( args.script, modelFile = args.model, dumpFname = args.dump_subset, paramFname = args.param_file, hidePlot = args.hide_plot, hideSubplots = args.hide_subplots, optimizeElec = args.optimize_elec, scaleParam = args.scale_param, settleTime = args.settle_time )
1444+
14401445

1446+
def innerMain( script, modelFile = "model/synSynth7.g", dumpFname = "", paramFname = "", hidePlot = True, hideSubplots = False, optimizeElec=True, silent = False, scaleParam=[], settleTime = 0, settleDict = {} ):
1447+
''' If *settleTime* > 0, then we need to return a dict of concs of
1448+
all variable pools in the chem model obtained after loading in model,
1449+
applying all modifications, and running for specified settle time.\n
1450+
If the *settleDict* is not empty, then the system goes through and
1451+
matches up pools to assign initial concentrations.
1452+
'''
14411453

1442-
def innerMain( script, modelFile = "model/synSynth7.g", dumpFname = "", paramFname = "", hidePlot = True, hideSubplots = False, optimizeElec=True, silent = False, scaleParam=[] ):
14431454
global pause
14441455
solver = "gsl" # Pick any of gsl, gssa, ee..
14451456
modelWarning = ""
@@ -1511,6 +1522,33 @@ def innerMain( script, modelFile = "model/synSynth7.g", dumpFname = "", paramFna
15111522
for i in range( 10, 20 ):
15121523
moose.setClock( i, 0.1 )
15131524

1525+
##############################################################
1526+
# Here we handle presettling. First to generate, then to apply
1527+
# the dict of settled values.
1528+
if settleTime > 0:
1529+
t0 = time.time()
1530+
moose.reinit()
1531+
#print settleTime
1532+
moose.start( settleTime )
1533+
w = moose.wildcardFind( modelId.path + "/##[ISA=PoolBase]" )
1534+
ret = {}
1535+
for i in w:
1536+
if not i.isBuffered:
1537+
ret[i.path] = i.n
1538+
#print( "{}.nInit = {:.3f}".format( i.path, i.n ))
1539+
#print "-------------------- settle done -------------------"
1540+
moose.delete( modelId )
1541+
if moose.exists( '/library' ):
1542+
moose.delete( '/library' )
1543+
#print( "Done settling in {:.2f} seconds".format( time.time()-t0))
1544+
print( "s", end = '' )
1545+
sys.stdout.flush()
1546+
return ret
1547+
1548+
for key, value in settleDict.items():
1549+
moose.element( key ).nInit = value
1550+
##############################################################
1551+
15141552
t0 = time.time()
15151553
score = runit( expt, model,stims, readouts, modelId )
15161554
elapsedTime = time.time() - t0
@@ -1522,13 +1560,17 @@ def innerMain( script, modelFile = "model/synSynth7.g", dumpFname = "", paramFna
15221560

15231561
pylab.show()
15241562
moose.delete( modelId )
1563+
if moose.exists( '/library' ):
1564+
moose.delete( '/library' )
15251565
return score
15261566

15271567
except SimError as msg:
15281568
if not silent:
15291569
print( "Error: findSim failed for script {}: {}".format(script, msg ))
15301570
if modelId:
15311571
moose.delete( modelId )
1572+
if moose.exists( '/library' ):
1573+
moose.delete( '/library' )
15321574
return -1.0
15331575
# Run the 'main' if this script is executed standalone.
15341576
if __name__ == '__main__':

multi_param_minimization.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454

5555
resultCount = 0
5656
numIterations = 0
57-
TOLERANCE = 0.001 # Don't want to go too tight on tolarance.
57+
TOLERANCE = 0.0001 # Don't want to go too tight on tolarance.
5858

5959
def reportReturn( result ):
6060
global resultCount
@@ -146,13 +146,18 @@ def main():
146146
pool = Pool( processes = args.numProcesses )
147147

148148
params = []
149+
bounds = []
149150
for i in args.parameters:
150151
print( "{}".format( i ) )
151152
spl = i.split( '.' )
152153
assert( len(spl) == 2 )
153154
params.append( i )
155+
if spl[1] == 'Kd' or spl[1] == 'tau' or spl[1] == 'Km':
156+
bounds.append( (0.03,30) )
157+
else:
158+
bounds.append( (0.0, 30 ) ) # Concs, Kfs and Kbs can be zero.
154159
ev = EvalFunc( params, fnames, weights, pool, modelFile )
155-
results = optimize.minimize( ev.doEval, np.ones( len(params) ), tol = TOLERANCE, callback = optCallback )
160+
results = optimize.minimize( ev.doEval, np.ones( len(params) ), method='L-BFGS-B', tol = TOLERANCE, callback = optCallback, bounds = bounds )
156161
print( "\n----------- Completed in {:.3f} sec ---------- ".format(time.time() - t0 ) )
157162
print( "\n----- Score= {:.4f} ------ ".format(results.fun ) )
158163
dumpData = False

0 commit comments

Comments
 (0)