Beispiel #1
0
 def allocfiles(self, **kwargs): # **kwargs override fname[k]
     """
     Save version info and preallocate empty memory-mapped arrays on disk.
     
     The arrays are taken from self.ftype, but may be overridden by 
     optional keyword arguments. For example, allocfiles(genotype=...) will 
     save the provided genotype as "genotype.npy" rather than allocate an 
     empty file of that name with dtype = ftype["genotype"].dtype.
     """
     genotype = kwargs.pop("genotype", self.genotype)
     shape = (len(genotype),) # must be tuple, or open_memmap creates broken file
     np.save("index.npy", np.arange(len(genotype)))
     for name, dtype in self.ftype.items():
         fname = "%s.npy" % name
         assert not os.path.exists(fname)
         if name in kwargs:
             np.save(fname, kwargs.pop(name))
         else:
             f = open_memmap(fname, mode="w+", dtype=dtype, shape=shape)
             if name == "timing":
                 f[:] = nans_like(np.empty(dtype=dtype, shape=shape))
                 f["waiting"] = time()
                 f["attempts"] = 0
             del f
     assert not kwargs, "Unrecognized keyword argument(s) %s" % kwargs.keys()
Beispiel #2
0
 def resume(self):
     """Prepare to rerun unfinished workpieces."""
     timing = open_memmap("timing.npy")
     indexbool = ~np.isfinite(timing["finished"])
     if self.resumeconv:
         c = np.load("convergence.npy").view(np.recarray)
         indexbool = indexbool | ((c.intervals > 0) & (c.period == 0))
     index = np.where(indexbool)[0]
     if len(index) == 0:
         raise Exception("No workpieces to resume")
     np.save("index.npy", index)
     timing[index]["waiting"] = time()
     timing[index]["attempts"] += 1
     del timing
Beispiel #3
0
    def task(self, real_i):
        """
        Map genotype i to parameter to steady state.
        
        Input and output uses memmaps. To allow load balancing, the memmaps 
        have only a single element (one genotype, one parameter set, etc.).
        
        In case of alternans, a list of (t, y, stats, integrals) is stored as e.g.
        alternans/123.list.npy
        To retrieve the list, use "L = np.load(filename).item()"
        """
        m = Dotdict()
        for name in self.ftype:
            m[name] = open_memmap("%s.npy" % name, offset=real_i, shape=1)
        i = 0
        alog.debug("Workpiece: real_i=%s, i=%s", real_i, i)
        m.timing[i]["attempts"] += 1
        m.timing[i]["started"] = time()
        try:
            m.genotype[i] = gt = self.genotype[real_i]
            m.parameter[i] = par = self.gt2par(gt)
            
            li = self.li
            
            with li.autorestore(_p=par):
                
                # Compute quiescent state
                with li.autorestore(stim_amplitude=0):
                    t, y, flag = li.integrate(t=[0, 1e6])
                m.quiescent[i] = yq = y[-1:] # yq now has shape (1,)
                
                # Run voltage stepping protocols
                bp = li.bond_protocols()
                p3, p5, p7 = [listify(bp[j].protocol) for j in 3, 5, 7]
                p3[1][1] = -40, -20, 0, 20, 40
                p5[1][1] = -40, -20, 0, 20, 40
                p7[2][0] = 2, 127, 252, 377, 502
                with li.autorestore(_y=yq):
                    L3 = li.vecvclamp(p3) # P1-P2 voltage stepping for i_Na
                    L5 = li.vecvclamp(p5) # P1-P2 voltage stepping for i_CaL
                    L7 = li.vecvclamp(p7) # Variable-gap protocol for i_CaL
                
                d = OrderedDict() # to hold voltage-clamp phenotype characteristics
                
                # Time constant of inactivation: -1/slope of ln(current) vs t after P1 peak
                for curr, L in ("i_Na", L3), ("i_CaL", L5):
                    for v, tau in zip(*decayfits(L, 1, curr)):
                        sv = str(v).replace("-", "m") # avoid minus sign in field name
                        k = "%s_tau_%s" % (curr, sv)
                        d[k] = tau
                
                # Michaelis-Menten half-saturation and asymptote of peak current vs gap duration
                gaps, voltages = p7[2]
                proto, traj = [np.array(j, dtype=object) for j in zip(*L7)]
                # Vectorized voltage clamping returns a 1-d array.
                # Dimensions should be (gap length, interpulse voltage, pulse index, last)
                # where the last dimension has length 2 for proto (duration, voltage) 
                # and 4 for traj (t, y, dy, a).
                for j in proto, traj:
                    j.shape = [len(gaps), len(voltages)] + list(j.shape[1:])
                for j, v in enumerate(voltages):
                    imax, thalf = mmfits(zip(proto[:,j,:,:], traj[:,j,:,:]), k="i_CaL")
                    sv = str(v).replace("-", "m")
                    d["i_CaL_vg_max_" + sv] = imax
                    d["i_CaL_vg_thalf_" + sv] = thalf
                # print " ".join(dict2rec(d).dtype.names) # for self.datatypes()
                m.clamppheno[i] = dict2rec(d).view(np.recarray)
                
                # Steady state under regular pacing
                (period, intervals), steady = li.par2steady(y0=yq, reltol=self.reltol, max_nap=1000)

                # # oldintervals will be nonzero if an earlier run failed to converge
                # oldperiod, oldintervals = m.convergence[i]
                # y0 = m.steady[i] if (self.resumeconv and oldintervals) else None
                # 
                # # Run to convergence; steady is a list of (t, y, stats, integrals).
                # # The cycle is aligned so that it starts with the highest Cai peak.
                # (period, intervals), steady = self.par2steady(par, y0)
                # intervals += oldintervals
                
                m.convergence[i] = period, intervals
                if period and (len(steady) > 1):
                    with write_if_not_exists("alternans/%s.list.npy" % real_i, 
                        raise_if_exists=True) as f:
                        L = []
                        for t, y, stats, int_ in steady:
                            ix = thin(len(t), self.raw_nthin)
                            L.append((t[ix], y[ix], stats, int_))
                        np.save(f, L)
                t, y, stats, _ = steady[-1]
                m.steady[i] = y[0]
                
                # Phenotypes for steady-state dynamics
                aps = [(t, y, stats) for t, y, stats, int_ in steady[-self.raw_nap:]]
                m.raw[i], m.ap_stats[i] = self.thin_aps(aps, self.raw_nthin, par)
                # Ion-current phenotypes, also applied to other state variables.
                # One table/ndarray per phenotype, one column per variable.
                raw = m.raw[i]
                currstats = np.concatenate([current_phenotypes_array(raw["t"], raw[k]) 
                    for k in raw.dtype.names if k != "t"])
                for k in currstats.dtype.names:
                    m[k][i] = np.ascontiguousarray(currstats[k])
                m.timing[i]["finished"] = time()
                m.timing[i]["seconds"] = m.timing[i]["finished"] - m.timing[i]["started"]
        except Exception, exc:
            m.timing[i]["error"] = time()
            alog.exception("Error processing item %s", i)