def do_sensitivity(exposure, workspace, protocol, statistic, par=None, seed=None, model=None, changeset=None, variant=None): """ Sensitivity analysis. Callback from R. >>> r("fun <- function(func, x) func(x)") RClosure with name <return value from eval>: <R function> >>> r.fun(r.sum, range(5)) array([10]) (R-style, sealed) >>> m = Model(workspace="beeler_reuter_1977", rename=dict( ... p=dict(IstimPeriod="stim_period", IstimAmplitude="stim_amplitude", ... IstimPulseDuration="stim_duration", IstimStart="stim_start")), ... reltol=1e-10, maxsteps=1e6, chunksize=100000) >>> m.pr.IstimStart = 0 >>> print "Result:", do_sensitivity("", "", "protocol", "apbase", ("C", "g_Na"), seed=1, model=m) Result:... Model runs: 6 mu mu.star sigma C 0.03672701 0.03672701 0.05130616 g_Na -0.41200934 0.41200934 0.04219007 TODO: Make optional arguments of exposure, lower, upper, etc. TODO: Accept json dict of model_kwargs, morris_kwargs """ if model is None: m = Model(workspace, exposure, changeset, variant, maxsteps=1e6, chunksize=1e5, reltol=1e-8) m.pr.stim_start = 0 else: m = model phenotypes(m) # initialize and cache default factors = [str(i) for i in par] # Numpy cannot handle Unicode names if not factors: # Default: sample within plus/minus 50% of all nonzero parameters factors = [k for k in m.dtype.p.names if m.pr[k] != 0] baseline = unstruct(m.pr[factors]).squeeze() lower = 0.5 * baseline upper = 1.5 * baseline if seed is not None: r.set_seed(seed) fun = scalar_pheno(statistic, m, factors) design = {"type": "oat", "levels": 10, "grid.jump": 5} return r.morris(fun, factors=factors, r=2, design=design, binf=lower, bsup=upper)
# This requires that an ipcluster is already started, see # http://ipython.org/ipython-doc/stable/parallel/parallel_task.html#parallel-function-decorator # rc = Client() # lview = rc.load_balanced_view() try: r.library("sensitivity") except RRuntimeError: r.install_packages("sensitivity", repos="http://cran.us.r-project.org") r.library("sensitivity") class Model(ex.Bond, AttractorMixin): pass logging.basicConfig() r.set_seed(20120221) m = Model(reltol=1e-10, maxsteps=1e6, chunksize=100000) mem = Memory("/tmp/sensitivity") factors = [k for k in m.dtype.p.names if m.pr[k] != 0] @mem.cache @failwithnanlikefirst def phenotypes(par=None): with m.autorestore(_p=par): m.eq(tmax=1e7, tol=1e-3) t, y, stats = m.ap() return ap_stats_array(stats) phenotypes() # initialize and cache default
"""Make a function to return a named field of the phenotype array.""" @ri.rternalize def fun(rmatrix): """Scalar function for use with R's sensitivity::morris().""" ph = np.concatenate([phenotypes(i) for i in mat2par(rmatrix)]) return py2ri(ph[field]) return fun if __name__ == "__main__": # Sensitivity analysis baseline = unstruct(m.pr[factors]) lower = 0.5 * baseline upper = 1.5 * baseline result = dict() for field in "appeak", "apd90", "ctpeak", "ctbase", "ctd90": r.set_seed(20120221) # repeatable random sampling result[field] = r.morris(scalar_pheno(field), factors=factors, r=2, design={"type": "oat", "levels": 10, "grid.jump": 5}, binf=lower, bsup=upper) # Print and visualize results r.png("sensitivity.png", width=1024, height=768, pointsize=24) r.par(mfrow=(2, 3)) # multiple figures in two rows, three columns for k, v in result.items(): print "====================================================" print k print v r.plot(v, log="y", main=k) r.dev_off() # close image file