Example #1
0
def check_synapse_strengths(f, syn_list=(5, 100), target=5.,
                            num_runs=5, max_num_runs=10):
    """
    Find the number of synapses that yields the target (Hz)

    Assumptions:
    - Same number of synapses
    :param f: file handle to write results
    :type f: TextIO
    """

    h.tstop = 1000
    inh_freq, inh_noise = 5, 1
    exc_freq, exc_noise = 5, 1
    exc_weights = [1, 2, 5, 7, 10, 15, 20]
    inh_weights = [1, 2, 5, 7, 10, 15, 20]

    means = []
    stds = []
    weights = []

    h.inPy(1, inh_noise, 0)  # Frequency, Noise, Weight (# synapses)
    h.ex(1, exc_noise, 0)  # Frequency, Noise, Weight (uS)
    h.run()
    h.useCV()
    for syn in syn_list:
        # newSynapses from methods.hoc
        h.newSynapses(syn, syn)
        for inh_weight in inh_weights:
            above_max_f = False
            for exc_weight in exc_weights:
                f.write(
                        "exc_weight: {} ({})\t inh_weight: {} ({})\n".format(exc_weight, syn, inh_weight, syn))
                logger.info("exc_weight:{} ({})\t inh_weight: {} ({})\n".format(exc_weight, syn, inh_weight, syn))
                if above_max_f:
                    # skip values of excitation when firing rate is already above
                    # 11 Hz for lower values of excitation
                    f.write("\n{} +- {} (n={})\n".format(12, 0, 0))
                    logger.info("{} +- {} (n={})\n".format(12, 0, 0))
                else:

                    h.inPy(inh_freq, inh_noise, inh_weight)
                    h.ex(exc_freq, exc_noise, exc_weight)
                    x = []
                    f.write("spikes:\n")
                    num_zero = 0
                    run_list = list(range(num_runs))
                    for run in run_list:
                        h.run()
                        x.append(h.apc.n)
                        f.write("\t {}".format(h.apc.n))
                        logger.info("\t spikes {}".format(h.apc.n))
                        if not (0 < h.apc.n <= 11):
                            if h.apc.n == 0:
                                num_zero += 1
                                if num_zero >= num_runs/5:
                                    logger.info("break from too many 0's")
                                    f.write("break from too many 0's")
                                    break
                            else:
                                logger.info("break from above 11")
                                f.write("break from above 11")
                                above_max_f = True
                                break
                        elif (4 <= h.apc.n <= 6) and len(run_list) < max_num_runs:
                            # get more accurate results for values close to 5
                            run_list.append(len(run_list))
                    mean = np.mean(x)
                    std = np.std(x)
                    f.write("\n{} +- {} (n={})\n".format(mean, std, run + 1))
                    logger.info("{} +- {} (n={})\n".format(mean, std, run + 1))
                    means.append(mean)
                    stds.append(std)
                    weights.append((exc_weight, inh_weight))

    arr = np.abs(target - np.array(means))
    idx = np.argmin(arr)
    return weights[idx]
Example #2
0
def check_num_synapses(f, synapse_type, exc_weight, inh_weight,
                       exc_syn_list=None, inh_syn_list=None,
                       exc_freq=5, inh_freq=5,
                       exc_noise=1, inh_noise=1,
                       num_runs=5, max_num_runs=15,
                       upper_bound=15):
    """

    A target of 5 Hz is used, with simulations with 4, 5, and 6 spikes taking extra trials. This target and the
    range to expand the number of trials can be implemented relatively easily in the future.

    Assumptions
    - GABAa gmax per synapse = 350 pS
    - AMPA+NMDA gmax per synapse = 1000 pS [AMPA:NMDA ratio = 1]

    :param f: file handle to write results
    :type f: TextIO
    """
    step = 10
    if inh_syn_list is None:
        inh_syn_list = range(0, 800 + step, step)
    if exc_syn_list is None:
        exc_syn_list = range(0, 800 + step, step)
    if upper_bound is not None:
        assert upper_bound > 0
    else:
        upper_bound = 10000

    prev_run = f.read()

    load_file(synapse_type)

    h.tstop = 1000
    h.useCV()

    # without a 2nd load NEURON seems to complain about synapseFile being a non-variable...
    load_file(synapse_type)

    for inh_syn in inh_syn_list:
        above_bound = False
        for exc_syn in exc_syn_list:
            line = "exc_syn: {} ({})\t inh_syn: {} ({})\n".format(exc_syn, exc_weight, inh_syn, inh_weight)
            if line in prev_run:
                continue
            f.write(line)
            logger.info(line)
            if above_bound:
                # skip values of excitation when firing rate is already above
                # 15 Hz for lower values of excitation
                f.write("\n{} +- {} (n={})\n".format(16, 0, 0))
                logger.info("{} +- {} (n={})\n".format(16, 0, 0))
            else:
                # newSynapses from methods.hoc
                h.newSynapses(exc_syn, inh_syn)
                # Frequency, Noise, Weight (# synapses)
                h.inPy(inh_freq, inh_noise, inh_weight)
                h.ex(exc_freq, exc_noise, exc_weight)
                x = []
                f.write("spikes:\n")
                num_zero = 0
                run_list = list(range(num_runs))
                for run in run_list:
                    h.run()
                    x.append(h.apc.n)
                    f.write("\t {}".format(h.apc.n))
                    logger.info("\t spikes {}".format(h.apc.n))
                    if h.apc.n == 0:
                        num_zero += 1
                        if num_zero >= num_runs/2:
                            logger.info("break from too many 0's")
                            f.write("break from too many 0's")
                            break
                    elif (4 <= h.apc.n <= 6) and len(run_list) < max_num_runs:
                        # get more accurate results for values close to 5
                        run_list.append(len(run_list))
                    elif h.apc.n > upper_bound:
                        logger.info("break from above {}".format(upper_bound))
                        f.write("break from above {}".format(upper_bound))
                        above_bound = True
                        break
                mean = np.mean(x)
                std = np.std(x)
                f.write("\n{} +- {} (n={})\n".format(mean, std, run + 1))
                logger.info("{} +- {} (n={})\n".format(mean, std, run + 1))
def get_trace(file_name,
              synapse_type=0,
              synapse_numbers=(10, 10),
              hz=None,
              space_plot=False,
              vm=-65.0,
              cli=5.0,
              ldend_diam=0.5):
    """
    Get the voltage trace and cli trace from running a hoc file.

    Optionally, specify space_plot to get the cli along the entire neuron (nseg dependent).

    `vm` and `cli` should be specified by running `get_base_vm_cli` beforehand and passing in those values.

    :param file_name: hoc-specified neuron to load (from hoc_files/cells)
    :type file_name: str
    :param synapse_type: 0 if 'f-in' NETSTIM synapses. 1 if 'persistetnt' fluctuating conductance synapses.
    :type synapse_type: int
    :param synapse_numbers: Number of (E,I) synapses.
    :type synapse_numbers: tuple of int
    :param hz: Input to the synapses. Keys used are 'in' and 'ex'.
        Either frequency-based (`synapse_type` is `0`) or relative conductance (`synapse_type` is `1`).
    :type hz: dict of str
    :param space_plot: Compute cli at every location.
    :type space_plot: bool
    :param vm: Initial membrane potential
    :type vm: float
    :param cli: Initial chloride ion concentration
    :type cli: float
    :param ldend_diam: Diameter of distal dendrite.
    :type ldend_diam: float
    :return: Time array, voltage array, chloride array,
        space plot dict data of form `{distance from soma: chloride array}`
    :rtype: tuple[h.Vector, h.Vector, h.Vector, dict of float:h.Vector]
    """
    if hz is None:
        hz = {'in': 5, 'ex': 5}
    load_file(file_name)

    h.changeSynapseType(synapse_type)
    h.newSynapses(synapse_numbers[0], synapse_numbers[1])
    if synapse_type == 0:
        h.inPy(hz['in'], 1, 1)
        h.ex(hz['ex'], 1, 1)
    else:
        h.inPy(hz['in'])
        h.ex(hz['ex'])
    if "distal" in file_name:
        compartment = h.ldend
    elif "proximal" in file_name:
        compartment = h.bdend
    else:
        compartment = h.soma

    h("forall {" + "cli={} ".format(cli) + "cli0_KCC2={}".format(cli) + "}")
    for sec in h.allsec:
        for seg in sec:
            seg.cli = cli
    h.cli0_cl_ion = cli
    h.ldend.diam = ldend_diam
    # sort on key
    data = {}
    if space_plot:
        h.distance(0, 1, sec=h.soma)
        for sec in h.allsec:
            for seg in sec:
                # label = f"{sec.name()}({seg.x:.5f})"
                label = h.distance(seg.x, sec=sec)
                if 'dend' in sec.name():
                    label *= -1
                data[label] = h.Vector()
                data[label].record(sec(seg.x)._ref_cli)

    h.tstop = 1000.0
    time_past = current_time('ms')
    logger.info("running {}...".format(file_name))
    h.v_init = vm
    h.finitialize(vm)
    t_vec = h.Vector()
    t_vec.record(h._ref_t)
    v_vec = h.Vector()
    v_vec.record(h.axon(0.5)._ref_v)
    cli_vec = h.Vector()
    cli_vec.record(compartment(0.5)._ref_cli)

    h.run()

    logger.info("time taken: {}ms".format(current_time('ms') - time_past))
    logger.info("no. spikes = {}".format(h.apc.n))

    return t_vec, v_vec, cli_vec, data
def pyrun(file_name,
          synapse_type=1,
          synapse_numbers=(100, 100),
          syn_input=None,
          diam=None,
          pa_kcc2=None,
          location='axon',
          trials=1,
          save=True,
          tstop=TSTOP,
          **kwargs):
    """
    Run a NEURON simulation for a neuron specified in ``file_name`` with input specified by other parameters provided.

    :param file_name: Neuron definition (excluding '.hoc').
    :type file_name: str
    :param synapse_type: Type of synapses to use (0 for frequency-based 'f-in', 1 for persistent conductance, 'gclamp').
    :type synapse_type: int
    :param synapse_numbers: Number of (E, I) on the neuron.
    :type synapse_numbers: (int, int)
    :param syn_input: Mapping of excitatory/inhibitory type to input strength. {'ex', E, 'in: I}
    :type syn_input: dict[str, int]
    :param diam: Re-specify diam for specific regions of the neuron. Valid: 'ldend', 'bdend', 'soma', 'axon'.
    :type diam: dict[str: float]
    :param pa_kcc2: Strength of KCC2.
    :type pa_kcc2: float
    :param location: Location to recording firing rate.
    :type location: str
    :param trials: Number of repeated simulations to run.
    :type trials: int
    :param save: Whether to load/save the results from/to file.
    :type save: bool
    :param tstop: Length of simulation (ms).
    :type tstop: float
    :param kwargs: Other keywords are ignored.

    :return: Pair of DataFrame with results and name of save file (even if not saved, the name is generated).
    :rtype: (pd.DataFrame, str)
    """
    if syn_input is None:
        syn_input = {'in': 5, 'ex': 5}
    save_name = "{}_{}_{}_{}".format(file_name, synapse_type, synapse_numbers,
                                     syn_input)
    save_name += "_{}".format(diam) if diam is not None else ''
    save_name += "_{}".format(pa_kcc2) if pa_kcc2 is not None else ''
    save_name += "_{}_{}".format(location, trials)
    save_name = save_name.replace(" ", "").replace("'", "").replace(
        ":", "=").replace("{", "(").replace("}", ")")
    logger.info(save_name)
    if save:
        loaded = load_from_file(save_name)
        if loaded is not None:
            return loaded, save_name

    load_file(file_name)
    load_file(file_name)
    if diam is not None:
        for seg in diam.keys():
            nrn_seg = get_compartment(seg)
            nrn_seg.diam = diam[seg]
    if pa_kcc2 is not None:
        hoc_cmd = "forall {" + """
            Pa_KCC2 = {pa_kcc2}e-5""".format(pa_kcc2=pa_kcc2) +\
                  " }"
        h(hoc_cmd)
    compartment = get_compartment(location)
    if file_name.find('distal') > -1:
        cli_rec_loc = get_compartment('ldend')
    elif file_name.find('proximal') > -1 or file_name.find('proximal') > -1:
        cli_rec_loc = get_compartment('bdend')
    else:
        cli_rec_loc = get_compartment('soma')

    logger.info("recording cli from {}".format(cli_rec_loc.hname()))

    h("access {}".format(location))
    h.changeSynapseType(synapse_type)
    h.newSynapses(synapse_numbers[0], synapse_numbers[1])
    h.inPy(0)
    h.ex(0)
    vm_init, cli = get_base_vm_cli(file_name, compartment=compartment)
    h.v_init = vm_init
    h_str = """
        forall{""" + """
            cli = {0}
            cli0_cl_ion = {0}
            """.format(cli)
    if file_name.find("KCC2") > 0:
        h_str += """cli0_KCC2 = {0}
        """.format(cli)
    h_str += "}"
    h(h_str)

    h.tstop = tstop

    if synapse_type == 0:
        # Hz, duration (s), start (ms), noise, weight/channels
        h.inPy(syn_input['in'], h.tstop / 1000, 0, 1, 1)
        h.ex(syn_input['ex'], h.tstop / 1000, 0, 1, 1)
    else:
        h.inPy(syn_input['in'])
        h.ex(syn_input['ex'])

    # create recording vector objects
    t_rec = h.Vector()
    v_rec = h.Vector()
    cli_rec = h.Vector()
    spike_rec = h.Vector()

    t_rec.record(h._ref_t)
    v_rec.record(compartment(0.5)._ref_v)
    cli_rec.record(cli_rec_loc(0.5)._ref_cli)
    spike_rec.record(h.apc._ref_n)

    time_past = current_time('ms')
    logger.info("using {}...".format(file_name))
    assert trials > 0
    logger.info(save_name)
    logger.info("trial # | # spikes")
    df = pd.DataFrame()
    for i in range(trials):
        trial_num = i + 1
        h.run()
        logger.info("{:7} | {:8}".format(trial_num, h.apc.n))

        temp_dict = {
            (trial_num, 'v'): v_rec.as_numpy(),
            (trial_num, 'cli'): cli_rec.as_numpy(),
            (trial_num, 'spikes'): spike_rec.as_numpy()
        }
        recording = pd.DataFrame(temp_dict, index=t_rec.to_python())

        df = pd.concat([df, recording], axis=1)

    logger.info("time taken: {}ms".format(current_time('ms') - time_past))

    if save:
        save_to_file(save_name, df)
    return df, save_name
Example #5
0
def get_base_vm_cli(file_name, load=False, compartment=None):
    """
    Determine steady-state internal chloride concentration by
    1) instantiating a class that extends BaseNeuron (NOTE: class should not have spiking at default values)
    2) adding KCC2 using the add_kcc2() method
    3) setting [Cl]_i to an arbitrary value (can be set in method invocation)
    running a fast simulation for a long time
    checking if chloride is at steady state (repeat 4 until it is)
    return steady state Vm and [Cl]_i

    :return: steady state Vm and [Cl]_i
    """
    logger.debug(f"finding steady-state vm and cli for {file_name}")
    if load:
        load_file(file_name, set_file_name=False)
    if compartment is None:
        compartment = h.soma
    h.inPy(0)
    h.ex(0)
    if file_name.find("KCC2") > 0:
        kcc2_already = True
    else:
        kcc2_already = False
        h.load_file(1, "insert_KCC2.hoc")
        logger.info("KCC2 temporarily inserted")

    h.tstop = 50000
    h.useCV()
    h.finitialize(-65)

    h.run()

    def at_steady_state(compartment, continue_dt):
        """
        check if [Cl]_i is at steady state
        :param continue_dt: amount of time to run
        :return: [Cl]_i if at steady state, False otherwise
        """
        v_start = compartment(.5).v
        cli_start = compartment(.5).cli
        h.continuerun(h.tstop + continue_dt)
        h.tstop += continue_dt
        v_after = compartment(.5).v
        cli_after = compartment(.5).cli
        if v_after - v_start < 1e-8 and cli_after - cli_start < 1e-8:
            return cli_after
        else:
            return False

    num_steady_state_checks = 0
    while not at_steady_state(compartment, 1):
        h.continuerun(h.tstop + 10000)
        h.tstop += 10000
        num_steady_state_checks += 1
        if num_steady_state_checks > 10:
            logger.info("not at steady state even after {} ms".format(
                50000 + num_steady_state_checks * 10000))
            exit(-1)

    h.disableCV()
    vm, cli = compartment(.5).v, compartment(.5).cli
    logger.info("steady state [Cl]_i {}".format(cli))
    logger.info("steady state Vm {}".format(vm))
    logger.info(
        "took {} ms (simulation time)".format(50000 +
                                              num_steady_state_checks * 10000))
    if not kcc2_already:
        h("""
            forall{
                uninsert KCC2
            }
        """)
        logger.info("temporary KCC2 removed")
    return vm, cli