def sim_slopes_debug(Cc_cells, cc_env, Dm_array, z_array, ion_i, gj_connects, GP): sim.cc_cells = Cc_cells Vm = sim.compute_Vm(Cc_cells, GP) # General note: our units of flux are moles/(m2*s). The question: m2 of # what area? You might think that for, e.g., ion channels, it should be per # m2 of ion-channel area -- but it's not. All fluxes are per m2 of cell- # membrane area. Thus, the (e.g.,) diffusion rate through ion channels must # be scaled down by the fraction of membrane area occupied by channels. # The same goes for ion pumps and GJs. # Run the Na/K-ATPase ion pump in each cell. # Returns two 1D arrays[N_CELLS] of fluxes; units are moles/(m2*s) pump_Na, pump_K, _ = stb.pumpNaKATP(Cc_cells[ion_i['Na']], cc_env[ion_i['Na']], Cc_cells[ion_i['K']], cc_env[ion_i['K']], Vm, GP.T, GP, 1.0) # Kill the pumps on worm-interior cells (based on Dm=0 for all ions) keep_pumps = np.any(Dm_array > 0, 0) # array[n_cells] pump_Na *= keep_pumps pump_K *= keep_pumps # for each ion: (sorted to be in order 0,1,2,... rather than random) GHK_fluxes = np.empty(Cc_cells.shape) for ion_name, ion_index in sorted(ion_i.items(), key=operator.itemgetter(1)): # GHK flux across membranes into the cell # It returns array[N_CELLS] of moles/(m2*s) f_ED = sim.GHK(ion_index, Vm) f_ED *= sim.eval_magic(sim.ion_magic[ion_index, :]) GHK_fluxes[ion_index] = f_ED # Gap-junction computations. deltaV_GJ = (Vm[gj_connects['to']] - Vm[gj_connects['from']]) # [n_GJs] # Get the gap-junction Norton-equivalent circuits for all ions at once. # Units of Ith are mol/(m2*s); units of Gth are mol/(m2*s) per Volt. (GJ_Ith, GJ_Gth) = sim.GJ_norton(GP) # Both are [n_ions,n_GJs]. # As opposed so sim.slew_cc(), our callers just want GJ diffusion and # drift. # [n_ions,n_GJs] * [n_GJs] GJ_diff = GJ_Ith.copy() * sim.eval_magic(sim.GJ_magic) # [n_ions,n_GJs] * [n_GJs] * [n_GJs] GJ_drif = GJ_Gth * sim.eval_magic(sim.GJ_magic) * deltaV_GJ # Next, do generation and decay. gen = sim.gen_cells.copy() # [n_ions, n_cells] decay = Cc_cells.copy() # [n_ions, n_cells] for ion_name, ion_index in sorted(ion_i.items(), key=operator.itemgetter(1)): gen[ion_index] = sim.gen_cells[ion_index,:] \ * sim.eval_magic(sim.gen_magic[ion_index,:]) decay[ion_index, :] *= sim.decay_rates[ion_index] # All returned values are in moles/(m2*s), where the m2 is m2 of # cell-membrane area. return (pump_Na, pump_K, GHK_fluxes, GJ_diff, GJ_drif, gen, decay)
def dump(t, cc_cells, units, long): print('\nt={}: dumping {}-format...'.format(t, 'long' if long else 'short')) # Print cc_cells[]. sim.cc_cells = cc_cells np.set_printoptions(formatter={'float': '{:4.0f}'.format}) print('cc_cells=') for ion_name, idx in sorted(sim.ion_i.items(), key=operator.itemgetter(1)): if (cc_cells[idx, :].sum() > 0): print(' {} {}'.format(cc_cells[idx], ion_name)) # Print Vm. np.set_printoptions(formatter={'float': '{:4.2f}'.format}) print('Vm = {}mV'.format(sim.compute_Vm(cc_cells, sim.GP) * 1000.0)) if (not long): return (pump_Na, pump_K, GHK_fluxes, GJ_diff, GJ_drif, gen, decay) \ =sim_slopes_debug (cc_cells,sim.cc_env,sim.Dm_array,sim.z_array, \ sim.ion_i,sim.gj_connects,sim.GP) (scl, tag) = scale([pump_Na, pump_K, GHK_fluxes, GJ_diff, GJ_drif, gen, decay], units, sim.GP) # Get the GJ contributions to the flux in each cell. GJ_diff_by_cell = np.zeros(cc_cells.shape) GJ_drif_by_cell = np.zeros(cc_cells.shape) for ion in range(cc_cells.shape[0]): np.add.at(GJ_drif_by_cell[ion, :], sim.gj_connects['from'], -GJ_drif[ion]) np.add.at(GJ_drif_by_cell[ion, :], sim.gj_connects['to'], GJ_drif[ion]) np.add.at(GJ_diff_by_cell[ion, :], sim.gj_connects['from'], -GJ_diff[ion]) np.add.at(GJ_diff_by_cell[ion, :], sim.gj_connects['to'], GJ_diff[ion]) # For each ion, sum all the various contributions per cell. ion_totals = GHK_fluxes + GJ_diff_by_cell + GJ_drif_by_cell ion_totals[sim.ion_i['Na']] += pump_Na ion_totals[sim.ion_i['K']] += pump_K # And also get the grand total flux (all ions together, for QSS) per cell grand_totals = (ion_totals.T * sim.z_array).T.sum(0) # Now the summing & distributing is done; round to integers for printing. pump_Na = np.round(pump_Na * scl) pump_K = np.round(pump_K * scl) GHK_fluxes = np.round(GHK_fluxes * scl) GJ_diff = np.round(GJ_diff * scl) GJ_drif = np.round(GJ_drif * scl) GJ_diff_by_cell = np.round(GJ_diff_by_cell * scl) GJ_drif_by_cell = np.round(GJ_drif_by_cell * scl) gen = np.round(gen * scl) decay = np.round(decay * scl) ion_totals = np.round(ion_totals * scl) grand_totals = np.round(grand_totals * scl) # First, ion channels and pumps np.set_printoptions(formatter={'float': '{:4.0f}'.format}) for ion_name, ion_idx in sorted(sim.ion_i.items(), key=operator.itemgetter(1)): if ((GHK_fluxes[ion_idx, :] != 0).any()): print('{:2s} ionCh: {} {}'.format(ion_name, GHK_fluxes[ion_idx], tag)) if (ion_name == 'Na'): print('Na pump: {} {}'.format(pump_Na, tag)) if (ion_name == 'K'): print('K pump: {} {}'.format(pump_K, tag)) if ((GJ_diff_by_cell[ion_idx, :] != 0).any()): print('{:2s} GJdiff:{} {}'.format(ion_name, GJ_diff_by_cell[ion_idx], tag)) if ((GJ_drif_by_cell[ion_idx, :] != 0).any()): print('{:2s} GJdrif:{} {}'.format(ion_name, GJ_drif_by_cell[ion_idx], tag)) # Per-ion totals print('\nTotals by ion from all sources:') for ion_name, ion_idx in sorted(sim.ion_i.items(), key=operator.itemgetter(1)): if ((ion_totals[ion_idx, :] != 0).any()): print('{:2s} total: {} {}'.format(ion_name, ion_totals[ion_idx], tag)) # Grand totals print('\nGrand valence-weighted totals from all sources across all ions:') print(' {} {}'.format(grand_totals, tag)) # Now, GJs. We did them above by cell; this time, by GJ print('\nnow the GJs by GJ (if any have non-zero flux):') for ion_name, ion_idx in sorted(sim.ion_i.items(), key=operator.itemgetter(1)): if ((GJ_diff[ion_idx, :] != 0).any()): print('{:2s} GJ diff: {} {}'.format(ion_name, GJ_diff[ion_idx], tag)) if ((GJ_drif[ion_idx, :] != 0).any()): print('{:2s} GJ drif: {} {}'.format(ion_name, GJ_drif[ion_idx], tag)) # Generation and decay if ((gen != 0).any() or (decay != 0).any()): print('\nnow generation and decay:') for ion_name, ion_idx in sorted(sim.ion_i.items(), key=operator.itemgetter(1)): if ((gen[ion_idx, :] != 0).any()): print('{:2s} generation: {} {}'.format(ion_name, gen[ion_idx], tag)) if ((decay[ion_idx, :] != 0).any()): print('{:2s} decay: {} {}'.format(ion_name, decay[ion_idx], tag))
def setup_and_sim(worm, time_to_run): import sys """ # If no command-line arguments are given, prompt for them. if (len (sys.argv) <= 1): args = 'main.py ' + input('Arguments: ') sys.argv = re.split (' ', args) regress_mode = (len(sys.argv) == 4) and (sys.argv[3]=="--regress") if (regress_mode): sys.argv = sys.argv[0:3] if (len(sys.argv) != 3): raise SyntaxError('Usage: python3 main.py test-name-to-run sim-end-time') """ end_time = time_to_run # Run whatever test got chosen on the command line. GP = sim.Params() setup_lab_worm(GP, worm) #eval ('setup_'+sys.argv[1]+'(GP)') #if (regress_mode): # Works even if setup_...() overrules these params! # GP.adaptive_timestep = False # Force regression # GP.sim_dump_interval = 1 # GP.sim_long_dump_interval = 10 # Initialize Vmem -- typically 0, or close to that. Vm = sim.compute_Vm (sim.cc_cells, GP) assert (Vm<.5).all() # I.e.,roughly charge neutral np.set_printoptions (formatter={'float': '{: 6.3g}'.format}, linewidth=90) #print ('Initial Vm ={}mV\n'.format(1000*Vm)) #print ('Starting main simulation loop') t_shots, cc_shots = sim.sim (end_time, GP) #print ('Simulation is finished.') # Now, the simulation is over. Do any end-of-sim analysis. #edb.analyze_equiv_network (GP) # If your network contains cells that are interconnected by GJs, then # pretty_plot() can make a nice picture of the interconnections and each # cell's Vm. Vm = sim.compute_Vm (sim.cc_cells, GP) # print("Worm Fitness = " + str(worm.fitness)) # print("Km = " + str(worm.Km)) # print("N = " + str(worm.N)) # print("Gj_scale = " + str(worm.Gj_scale)) # print("num_cells = " + str(worm.num_cells)) # print("G_k = " + str(worm.G_k)) # print("G_k = " + str(worm.G_na)) # print("G_cl = " + str(worm.G_cl)) # print("Gj_diff_m = " + str(worm.Gj_diff_m)) #print("Vmem?: {}".format(Vm)) Vgrad = abs(Vm[0] - Vm[worm.num_cells -1]) worm.grad_stren = Vgrad #eplt.pretty_plot (Vm*1e3) # We often want a printed dump of the final simulation results. np.set_printoptions (formatter={'float': '{:.6g}'.format}, linewidth=90) #edb.dump (end_time, sim.cc_cells, edb.Units.mV_per_s, True) #edb.dump (end_time, sim.cc_cells, edb.Units.mol_per_m2s, True) # We often want graphs of various quantities vs. time. # If so, then comment out the quit() here, and then modify the code below # as desired. # quit() Na = sim.ion_i['Na']; K = sim.ion_i['K']; Cl=sim.ion_i['Cl'] # P=sim.ion_i['P']; M=sim.ion_i['M'] Vm_shots = [sim.compute_Vm (c,GP)*1000 for c in cc_shots] n_cells = sim.cc_cells.shape[1] # eplt.plot_Vmem_graph(t_shots,Vm_shots, np.arange(n_cells),'Vmem(mV)') # eplt.plot_Vmem_graph(t_shots,[s[Na] for s in cc_shots],np.arange(n_cells),'[Na] (mol/m3') # eplt.plot_Vmem_graph(t_shots,[s[K] for s in cc_shots],np.arange(n_cells),'[K] (mol/m3') # eplt.plot_Vmem_graph(t_shots,[s[Cl] for s in cc_shots],np.arange(n_cells),'[Cl] (mol/m3') #eplt.plot_Vmem_graph(t_shots,[s[M] for s in cc_shots],np.arange(n_cells),'[M] (mol/m3')
def analyze_equiv_network(GP): print('Analyze_equiv_network() info...') # First, the ion-channel equivalents. And x1000 to use mV and not V. Vn = Vnernst(GP) * 1000 # 3 rows(for Na,K,Cl) x num_cells Gthev = IC_Gthev(GP) / 1000 # 3 rows x num_cells (Vthev_net, Gthev_net) = merge_Thev(Vn, Gthev, sim.z_array) # merge across ions # Actual fluxes at current Vm Vm = sim.compute_Vm(sim.cc_cells, sim.GP) * 1000 IC_net = (Vm - Vn) * Gthev # 3 rows x num_cells allIC_net = (Vm - Vthev_net) * Gthev_net # summed across all ions-> [num_cells] # Make the ion-channel equivalents pretty for printout. units = Units.mol_per_m2s (scl, tag) = scale([Gthev, Gthev_net], units, GP) Gthev = np.round(Gthev * scl) Gthev_net = np.round(Gthev_net * scl) IC_net = np.round(IC_net * scl) # 3 rows x num_cells allIC_net = np.round(allIC_net * scl) # [num_cells] # Print out Vn, Gth for each ion channel. for ion_index, ion in enumerate(['Na', 'K', 'Cl']): np.set_printoptions(formatter={'float': '{:4.2g}'.format}) print(' {:2s} IC Vn ={}mV'.format(ion, Vn[ion_index])) np.set_printoptions(formatter={'float': '{:4.0f}'.format}) print(' {:2s} IC Gth={}{}'.format(ion, Gthev[ion_index], tag + '/mV')) print(' {:2s} IC net={}{}{}'.format(ion, IC_net[ion_index], tag, ' of ions through ICs')) # Print out Vn, Gth for the merged-across-all-ion-channels version. np.set_printoptions(formatter={'float': '{:4.2g}'.format}) print('IC Vthev_net ={}mV'.format(Vthev_net)) np.set_printoptions(formatter={'float': '{:4.0f}'.format}) print('IC Gth_net ={}{}'.format(Gthev_net, tag + '/mV')) print('IC net_net ={}{}{}'.format(allIC_net, tag, ' of charge through ICs')) # Compute the QSS Vmem using this model, but taking the pumps into account, # and disregarding GJs. # We have (Vmem-Vthev_net)*Gthev_net + pump_Na + pump_K = 0, or # Vmem*Gthev_net - Vthev_net*Gthev_net + pump_Na + pump_K = 0, or # Vmem = (Vthev_net*Gthev_net + pump_Na + pump_K) / Gthev_net (pump_Na, pump_K, GHK_fluxes, GJ_diff, GJ_drif, gen, decay) \ =sim_slopes_debug (sim.cc_cells,sim.cc_env,sim.Dm_array,sim.z_array, \ sim.ion_i,sim.gj_connects,sim.GP) Vmem = (Vthev_net * Gthev_net + pump_Na + pump_K) / Gthev_net print('Open-circuit Vmem including pumps = ', Vmem) # Next, equivalents for GJs (if there are any). (GJ_Ith, GJ_Gth) = sim.GJ_norton(GP) if (GJ_Gth.size == 0): return # Scale the GJ models for printing. units = Units.mol_per_m2s units = Units.mV_per_s (scl, tag) = scale([GJ_Gth, GJ_Ith], units, GP) GJ_Gth = np.round(GJ_Gth * scl) GJ_Ith = np.round(GJ_Ith * scl) # Print the per-ion GJ models. for ion, ion_index in sorted(sim.ion_i.items(), key=operator.itemgetter(1)): if ((GJ_Ith[ion_index, :] != 0).any()): print(' {:2} GJ Ith = {}{}'.format(ion, GJ_Ith[ion_index], tag)) if ((GJ_Gth[ion_index, :] != 0).any()): print(' {:2} GJ Gth = {}{}'.format(ion, GJ_Gth[ion_index], tag + '/V'))
def plot_Vmem(t_shots, cc_shots, cells=None): Vm_shots = [sim.compute_Vm(c, sim.GP) * 1000 for c in cc_shots] n_cells = cc_shots[0].shape[1] cells = (np.arange(n_cells) if cells == None else np.array((cells))) plot_Vmem_graph(t_shots, Vm_shots, cells, 'Vmem(mV)')