def planar_wave(self): ''' Finds the conduction velocity of a planar wave. First paces the 0D ode model for 50 cycles at a BCL of 1000, then initiates a single planar wave, measuring the conduction velocity half-way in the domain. ''' # Import function for pacing 0D cell model to find quasi steady-state import sys sys.path.append("../0D/") from steadystate import find_steadystate solver, ode_solver = self.solver, self.ode_solver # Pace 0D cell model and find quasi-steady state try: steadystate = np.load("../data/steadystate_%s_BCL%d.npy"%(ode,1000)) except: BCL = 1000 print "Pacing 0D model for BCL %g..." % BCL, steadystate = find_steadystate(BCL, 50, dt, ode, plot_results=False) print "done." # Get the solution fields (u, um) = solver.solution_fields() # Load steadystate into 2D model for i in range((N+1)*(N+1)): ode_solver.states(i)[:] = steadystate u.vector()[i] = steadystate[0] # Define the planar wave stimulus S = Expression(("near(x[0],0)*amp", "t"), amp=stim_amp, t=0) V = VectorFunctionSpace(self.domain, 'CG', 1) S = interpolate(S, V).vector().array() # Apply the stimulus ode_solver.set_field_parameters(S) xp = 0; yp = 0; for timestep, (u, vm) in solver.solve((0, tstop), dt): plot(u, **plot_args) print u.vector().max() x = u.vector()[N/2-d] y = u.vector()[N/2+d] if x > 0 and (x*xp) < 0: # X cell has activated t0 = timestep[0] if y > 0 and (y*yp) < 0 and t0 != 0: # Y cell has activated t1 = timestep[0] # Calculate conduction velocity print "CV: ", 2*d*h/(t1-t0)*1e3 break xp = x yp = y
def pacing_cv(ode, BCL_range, D, L, h, dt): """ Pace a 0D cell model for 50 cycles at given BCL, then simulate a wave in a 1D strand. 5 beats are initiated at the left hand side of the strand, after the fifth beat, the conduction velocity is measured. """ # Create domain N = int(L/h) # number of nodes - 1 domain = IntervalMesh(N, 0, L) # Define functions V = FunctionSpace(domain, 'Lagrange', 1) u = TrialFunction(V) up = Function(V) v = TestFunction(V) # Assemble the mass matrix and the stiffness matrix M = assemble(u*v*dx) K = assemble(Constant(dt)*inner(D*grad(u), grad(v))*dx) A = M + K pde_solver = LUSolver(A) pde_solver.parameters["reuse_factorization"] = True # Set up ODESolver ode = load_ode(ode) compiled_ode = dolfin_jit(ode, field_states=["V"], field_parameters = [ "stim_period"]) params = DOLFINODESystemSolver.default_parameters() params["scheme"] = "RL1" stim_field = interpolate(Expression("near(x[0],0)*sd", sd=1.), V) #compiled_ode.set_parameter("stim_duration", stim_field) BCL = 1000 #compiled_ode.set_parameter("stim_period", BCL) ode_solver = DOLFINODESystemSolver(domain, compiled_ode, params=params) solver = ode_solver._ode_system_solvers[0] try: states = np.load("../data/steadystate_%s_BCL%d.npy" % (ode, BCL)) except: states = find_steadystate(BCL, 50, dt, ode, plot_results=False) for i in range(N+1): solver.states(i)[:] = states up.vector()[i] = solver.states(i)[0] #params = np.zeros((N+1)*2) solver.set_field_parameters(np.array([BCL]+[0]*N, dtype=np.float_)) #stim_field = interpolate(Expression("0"), V) #compiled_ode.set_parameter("stim_duration", stim_field) t = 0. tstop = 1e6 while t < tstop: # Step ODE solver ode_solver.step((t, t+dt), up) # Assemble RHS and solve pde b = M*up.vector() pde_solver.solve(up.vector(), b) # Plot solution plot(up, range_min=-80.0, range_max=40.0) t += dt
def pacing_cv(ode, BCL_range, D, dt, threshold=0, stim_amp=0, plot_args=None): D = Constant(D) # Must be adjusted with temporal and spatial resolution L = 20 h = 0.5 dt_low = 0.1 # Create dolfin mesh N = int(L / h) domain = IntervalMesh(N, 0, L) # Load the cell model from file ode = load_ode(ode) cellmodel = dolfin_jit(ode, field_states=["V"], field_parameters=["stim_period", "stim_amplitude"]) # Create the CardiacModel for the given mesh and cell model heart = CardiacModel(domain, Constant(0.0), D, None, cellmodel) # Create the solver solver = GOSSplittingSolver(heart, GOSSparams()) # Get the solution fields and subsolvers dolfin_solver = solver.ode_solver ode_solver = dolfin_solver._ode_system_solvers[0] results = np.zeros((4, len(BCL_range))) for i, BCL in enumerate(BCL_range): # Set the stimulus parameter field stim_field = np.zeros(2 * (N + 1), dtype=np.float_) stim_field[0] = BCL stim_field[1] = stim_amp ode_solver.set_field_parameters(stim_field) # Pace 0D cell model and find quasi steady state sspath = "../data/steadystates/" try: states = np.load(sspath + "steadystate_%s_BCL%d.npy" % (ode, BCL)) except: print "Did not find steadystate for %s at BCL: %g, pacing 0D model" % ( ode, BCL) find_steadystate(ODE, BCL, 0.01) # Load quasi steady state into 1D model (u, um) = solver.solution_fields() for node in range(N + 1): ode_solver.states(node)[:] = states u.vector()[node] = states[0] # Used for measuring cell activation xp = 0 yp = 0 results[0][i] = BCL print "BCL: %g" % BCL # Do 3 pulses for pulsenr in range(1, 4): # Solve the pulse in higher temporal resolution for timestep, (u, vm) in solver.solve((i * BCL, i * BCL + 50), dt): if plot_args: plot(u, **plot_args) x = u.vector()[20] y = u.vector()[35] if x > threshold and (x - threshold) * (xp - threshold) < 0: t0 = (threshold - xp) / (x - xp) * dt + tp if y > threshold and (y - threshold) * (yp - threshold) < 0: t1 = (threshold - yp) / (y - yp) * dt + tp # Calculate conduction velocity Cv = 15 * h / (t1 - t0) * 1e3 print "\tCv: %g" % Cv results[pulsenr][i] = Cv t0 = 0 t1 = 0 xp = x yp = y tp = timestep[0] # Wait for next pulse for timestep, (u, vm) in solver.solve( (i * BCL + 50, (i + 1) * BCL), dt_low): if plot_args: plot(u, **plot_args) np.save("../data/results/cv_%s" % ode, results)
def pacing_cv(ode, BCL_range, D, dt, threshold=0, stim_amp=0, plot_args=None): D = Constant(D) # Must be adjusted with temporal and spatial resolution L = 20 h = 0.5 dt_low = 0.1 # Create dolfin mesh N = int(L/h) domain = IntervalMesh(N, 0, L) # Load the cell model from file ode = load_ode(ode) cellmodel = dolfin_jit(ode, field_states=["V"], field_parameters=["stim_period", "stim_amplitude"]) # Create the CardiacModel for the given mesh and cell model heart = CardiacModel(domain, Constant(0.0), D, None, cellmodel) # Create the solver solver = GOSSplittingSolver(heart, GOSSparams()) # Get the solution fields and subsolvers dolfin_solver = solver.ode_solver ode_solver = dolfin_solver._ode_system_solvers[0] results = np.zeros((4, len(BCL_range))) for i, BCL in enumerate(BCL_range): # Set the stimulus parameter field stim_field = np.zeros(2*(N+1), dtype=np.float_) stim_field[0] = BCL stim_field[1] = stim_amp ode_solver.set_field_parameters(stim_field) # Pace 0D cell model and find quasi steady state sspath = "../data/steadystates/" try: states = np.load(sspath+"steadystate_%s_BCL%d.npy" % (ode, BCL)) except: print "Did not find steadystate for %s at BCL: %g, pacing 0D model" % (ode, BCL) find_steadystate(ODE, BCL, 0.01) # Load quasi steady state into 1D model (u, um) = solver.solution_fields() for node in range(N+1): ode_solver.states(node)[:] = states u.vector()[node] = states[0] # Used for measuring cell activation xp = 0; yp=0 results[0][i] = BCL print "BCL: %g" % BCL # Do 3 pulses for pulsenr in range(1,4): # Solve the pulse in higher temporal resolution for timestep, (u, vm) in solver.solve((i*BCL, i*BCL+50), dt): if plot_args: plot(u, **plot_args) x = u.vector()[20] y = u.vector()[35] if x > threshold and (x-threshold)*(xp-threshold) < 0: t0 = (threshold - xp)/(x - xp)*dt + tp if y > threshold and (y-threshold)*(yp-threshold) < 0: t1 = (threshold - yp)/(y - yp)*dt + tp # Calculate conduction velocity Cv = 15*h/(t1-t0)*1e3 print "\tCv: %g" % Cv results[pulsenr][i] = Cv t0 = 0; t1 = 0 xp = x yp = y tp = timestep[0] # Wait for next pulse for timestep, (u, vm) in solver.solve((i*BCL+50, (i+1)*BCL), dt_low): if plot_args: plot(u, **plot_args) np.save("../data/results/cv_%s"%ode, results)
def spiral_wave(self): solver, ode_solver = self.solver, self.ode_solver # Define stimulus fields S1 = Expression(("near(x[0],0)*amp","t"), amp=stim_amp, t=0) S2 = Expression(("(x[1] < 0.5*L && x[0] < 0.5*L)*amp","t"), L=L, t=S2_time+1, amp=stim_amp) nostim = Expression(("0","0")) # Calculate parameter fields V = VectorFunctionSpace(self.domain, 'CG', 1) S1 = interpolate(S1, V).vector().array() S2 = interpolate(S2, V).vector().array() nostim = interpolate(nostim, V).vector().array() # Pace 0D cell model and find quasi-steady state try: steadystate = np.load("../data/steadystate_%s_BCL%d.npy"%(ode, BCL)) except: print "Pacing 0D model for BCL %g..." % BCL, steadystate = find_steadystate(BCL, 50, dt, ode, plot_results=False) print "done." # Get the solution fields (u, um) = solver.solution_fields() # Load steadystate into 2D model for i in range((N+1)*(N+1)): ode_solver.states(i)[:] = steadystate u.vector()[i] = steadystate[0] cnt = 0 plot(u, interactive=True, **plot_args) # Stimulate S1 pulse ode_solver.set_field_parameters(S1) for timestep, (u, vm) in solver.solve((0, S2_time), dt): fig = plot(u, interactive=False, **plot_args) if save_fig and cnt % 5 == 0: padded_index = '%08d' % cnt fig.write_png('../tmp/spiral_%s' % self.ode + padded_index) cnt += 1 ode_solver.set_field_parameters(S2) # Stimulate S2 pulse for timestep, (u, vm) in solver.solve((S2_time, S2_time+100), dt): fig = plot(u, interactive=False, **plot_args) if save_fig and cnt % 5 == 0: padded_index = '%08d' % cnt fig.write_png('../tmp/spiral_%s' % self.ode + padded_index) cnt += 1 # Turn of all stimulus and iterate until simulation stop ode_solver.set_field_parameters(nostim) for timestep, (u, vm) in solver.solve((S2_time+100, tstop), dt): fig = plot(u, interactive=False, **plot_args) if save_fig and cnt % 5 == 0: padded_index = '%08d' % cnt fig.write_png('../tmp/spiral_%s' % self.ode + padded_index) cnt += 1
def planar_wave(self): ''' Finds the conduction velocity of a planar wave. First paces the 0D ode model for 50 cycles at a BCL of 1000, then initiates a single planar wave, measuring the conduction velocity half-way in the domain. ''' # Import function for pacing 0D cell model to find quasi steady-state import sys sys.path.append("../0D/") from steadystate import find_steadystate solver, ode_solver = self.solver, self.ode_solver # Pace 0D cell model and find quasi-steady state try: steadystate = np.load("../data/steadystate_%s_BCL%d.npy" % (ode, 1000)) except: BCL = 1000 print "Pacing 0D model for BCL %g..." % BCL, steadystate = find_steadystate(BCL, 50, dt, ode, plot_results=False) print "done." # Get the solution fields (u, um) = solver.solution_fields() # Load steadystate into 2D model for i in range((N + 1) * (N + 1)): ode_solver.states(i)[:] = steadystate u.vector()[i] = steadystate[0] # Define the planar wave stimulus S = Expression(("near(x[0],0)*amp", "t"), amp=stim_amp, t=0) V = VectorFunctionSpace(self.domain, 'CG', 1) S = interpolate(S, V).vector().array() # Apply the stimulus ode_solver.set_field_parameters(S) xp = 0 yp = 0 for timestep, (u, vm) in solver.solve((0, tstop), dt): plot(u, **plot_args) print u.vector().max() x = u.vector()[N / 2 - d] y = u.vector()[N / 2 + d] if x > 0 and (x * xp) < 0: # X cell has activated t0 = timestep[0] if y > 0 and (y * yp) < 0 and t0 != 0: # Y cell has activated t1 = timestep[0] # Calculate conduction velocity print "CV: ", 2 * d * h / (t1 - t0) * 1e3 break xp = x yp = y
def spiral_wave(self): solver, ode_solver = self.solver, self.ode_solver # Define stimulus fields S1 = Expression(("near(x[0],0)*amp", "t"), amp=stim_amp, t=0) S2 = Expression(("(x[1] < 0.5*L && x[0] < 0.5*L)*amp", "t"), L=L, t=S2_time + 1, amp=stim_amp) nostim = Expression(("0", "0")) # Calculate parameter fields V = VectorFunctionSpace(self.domain, 'CG', 1) S1 = interpolate(S1, V).vector().array() S2 = interpolate(S2, V).vector().array() nostim = interpolate(nostim, V).vector().array() # Pace 0D cell model and find quasi-steady state try: steadystate = np.load("../data/steadystate_%s_BCL%d.npy" % (ode, BCL)) except: print "Pacing 0D model for BCL %g..." % BCL, steadystate = find_steadystate(BCL, 50, dt, ode, plot_results=False) print "done." # Get the solution fields (u, um) = solver.solution_fields() # Load steadystate into 2D model for i in range((N + 1) * (N + 1)): ode_solver.states(i)[:] = steadystate u.vector()[i] = steadystate[0] cnt = 0 plot(u, interactive=True, **plot_args) # Stimulate S1 pulse ode_solver.set_field_parameters(S1) for timestep, (u, vm) in solver.solve((0, S2_time), dt): fig = plot(u, interactive=False, **plot_args) if save_fig and cnt % 5 == 0: padded_index = '%08d' % cnt fig.write_png('../tmp/spiral_%s' % self.ode + padded_index) cnt += 1 ode_solver.set_field_parameters(S2) # Stimulate S2 pulse for timestep, (u, vm) in solver.solve((S2_time, S2_time + 100), dt): fig = plot(u, interactive=False, **plot_args) if save_fig and cnt % 5 == 0: padded_index = '%08d' % cnt fig.write_png('../tmp/spiral_%s' % self.ode + padded_index) cnt += 1 # Turn of all stimulus and iterate until simulation stop ode_solver.set_field_parameters(nostim) for timestep, (u, vm) in solver.solve((S2_time + 100, tstop), dt): fig = plot(u, interactive=False, **plot_args) if save_fig and cnt % 5 == 0: padded_index = '%08d' % cnt fig.write_png('../tmp/spiral_%s' % self.ode + padded_index) cnt += 1
def pacing_S1S2(ode, S1, S2_range, dt, threshold=-60): """ Calculate a restitution curve using S1-S2 pacing, take in the relevant ode model, the S1 length and the range of S2 values to calculate APD/DI. Note that the steady state of a BCL=S1 must be lying in /data/. If this does not exist for the given ODE file, you can make it using steadystate.py. """ module, forward = create_module(ode) model_params = module.init_parameter_values() # Pace 0D cell model and find quasi-steady state try: sspath = "../data/steadystates/" init_states = np.load(sspath+"steadystate_%s_BCL%d.npy" % (ode, S1)) except: print "Pacing 0D model for BCL %g..." % S1, init_states = find_steadystate(S1, 50, dt, ode, plot_results=False) print "done." # Find indices of various states/parameters V_index = module.state_indices("V") BCL_index = module.parameter_indices("stim_period") def pulse_S2(S2): """Pulse the steady state with a single S2 pulse and measure APD/DI.""" states = init_states model_params[BCL_index] = S2 t = 0.; tstop = 2*S2 while t <= S2: forward(states, t, dt, model_params) t += dt Vp = states[V_index] cross_threshold = [] while t <= tstop: forward(states, t, dt, model_params) V = states[V_index] if (Vp-threshold)*(V-threshold) < 0: cross_threshold.append(t) Vp = V t += dt try: APD = cross_threshold[-1] - cross_threshold[-2] DI = tstop - cross_threshold[-1] except: APD = 0 DI = 0 return APD, DI results = np.zeros((3, len(S2_range))) for S2 in S2_range: APD, DI = pulse_S2(S2) results[0][i] = S2 results[1][i] = APD results[2][i] = DI print "S2: %g, APD: %g, DI: %g" % (S2, APD, DI) np.save("../data/results/S1S2_%s" % ode, results)
def pacing_cv(ode, BCL_range, D, L, h, dt): """ Pace a 0D cell model for 50 cycles at given BCL, then simulate a wave in a 1D strand. 5 beats are initiated at the left hand side of the strand, after the fifth beat, the conduction velocity is measured. """ # Create domain N = int(L / h) # number of nodes - 1 domain = IntervalMesh(N, 0, L) # Define functions V = FunctionSpace(domain, 'Lagrange', 1) u = TrialFunction(V) up = Function(V) v = TestFunction(V) # Assemble the mass matrix and the stiffness matrix M = assemble(u * v * dx) K = assemble(Constant(dt) * inner(D * grad(u), grad(v)) * dx) A = M + K pde_solver = LUSolver(A) pde_solver.parameters["reuse_factorization"] = True # Set up ODESolver ode = load_ode(ode) compiled_ode = dolfin_jit(ode, field_states=["V"], field_parameters=["stim_period"]) params = DOLFINODESystemSolver.default_parameters() params["scheme"] = "RL1" stim_field = interpolate(Expression("near(x[0],0)*sd", sd=1.), V) #compiled_ode.set_parameter("stim_duration", stim_field) BCL = 1000 #compiled_ode.set_parameter("stim_period", BCL) ode_solver = DOLFINODESystemSolver(domain, compiled_ode, params=params) solver = ode_solver._ode_system_solvers[0] try: states = np.load("../data/steadystate_%s_BCL%d.npy" % (ode, BCL)) except: states = find_steadystate(BCL, 50, dt, ode, plot_results=False) for i in range(N + 1): solver.states(i)[:] = states up.vector()[i] = solver.states(i)[0] #params = np.zeros((N+1)*2) solver.set_field_parameters(np.array([BCL] + [0] * N, dtype=np.float_)) #stim_field = interpolate(Expression("0"), V) #compiled_ode.set_parameter("stim_duration", stim_field) t = 0. tstop = 1e6 while t < tstop: # Step ODE solver ode_solver.step((t, t + dt), up) # Assemble RHS and solve pde b = M * up.vector() pde_solver.solve(up.vector(), b) # Plot solution plot(up, range_min=-80.0, range_max=40.0) t += dt