def sim_ln_dosc_complex_model_OLD(mu_ext, sigma_ext, L, mu_exp, sigma_exp,
                                  w_m_orig, dt, EW, taum, gL, tauw, a, b,
                                  mu_range, sig_range, f0_grid, tau_grid,
                                  tau_mu_f_grid, tau_sigma_f_grid, Vmean_grid,
                                  r_grid, rec, K, J, delay_type, n_d, taud):

    mu_f = np.zeros(L+1, dtype = numba.complex128) \
        if use_numba else np.zeros(L+1, dtype=np.complex128)
    mu_a = np.zeros(L + 1)
    r = np.zeros(L + 1)
    r_d = np.zeros(L + 1)
    wm = np.zeros(L + 1)
    sigma_f = np.zeros(L + 1)
    #initial_conditions
    mu_a[0] = mu_exp
    wm[0] = w_m_orig
    sigma_f[0] = sigma_exp
    weights_a = interpolate_xy(mu_a[0] - wm[0] / (taum * gL), sigma_f[0],
                               mu_range, sig_range)
    f0 = lookup_xy(f0_grid, weights_a)
    tau = lookup_xy(tau_grid, weights_a)
    mu_f[0] = (mu_exp * (1 + 1j * 2 * np.pi * f0 * tau))
    for i in xrange(L):
        #interpolates real numbers
        weights_a = interpolate_xy(mu_a[i] - wm[i] / (taum * gL), sigma_f[i],
                                   mu_range, sig_range)
        f0 = lookup_xy(f0_grid, weights_a)
        tau = lookup_xy(tau_grid, weights_a)
        tau_mu_f = lookup_xy(tau_mu_f_grid, weights_a)
        tau_sigma_f = lookup_xy(tau_sigma_f_grid, weights_a)

        weights_f = interpolate_xy(mu_f[i].real - wm[i] / (taum * gL),
                                   sigma_f[i], mu_range, sig_range)
        Vmean_dosc = lookup_xy(Vmean_grid, weights_f)
        r_dosc = lookup_xy(r_grid, weights_f)
        r[i] = r_dosc

        if rec:
            mu_syn = get_mu_syn(K, J, mu_ext, delay_type, i, r, r_d, n_d, taud,
                                dt)
            sigma_syn = get_sigma_syn(K, J, sigma_ext, delay_type, i, r, r_d,
                                      n_d, taud, dt)
        else:
            mu_syn = mu_ext[i]
            sigma_syn = sigma_ext[i]

        mu_f_rhs = ((2 * np.pi * f0)**2 * tau + 1. / tau) * mu_syn + (
            1j * 2 * np.pi * f0 - 1. / tau) * mu_f[i]
        sigma_f_rhs = (sigma_syn - sigma_f[i]) / tau_sigma_f
        w_rhs = (a[i] *
                 (Vmean_dosc - EW) - wm[i] + tauw * b[i] * r_dosc) / tauw
        mu_a_rhs = (mu_syn - mu_a[i]) / tau_mu_f

        #EULER STEP
        mu_f[i + 1] = mu_f[i] + dt * mu_f_rhs
        mu_a[i + 1] = mu_a[i] + dt * mu_a_rhs
        sigma_f[i + 1] = sigma_f[i] + dt * sigma_f_rhs
        wm[i + 1] = wm[i] + dt * w_rhs

    return (r * 1000., wm)
Exemplo n.º 2
0
def sim_spec1_without_HEUN_OLD(mu_ext, sigma_ext, map1_Vmean, map_r_inf, mu_range,
              sigma_range, map_lambda_1, tauw, dt, steps, C,a ,b, EW,
              s0, r0,w0, rec,K,J,delay_type,n_d,taud):

    # optimizations
    dt_tauw = dt/tauw
    b_tauw = b*tauw

    # initialize real arrays
    r   = np.zeros(steps+1)
    r_d = np.zeros(steps+1)
    s   = np.zeros(steps+1)
    wm  = np.zeros(steps+1)
    lambda_1_real = np.zeros(steps+1)

    # write initial condition into array
    r[0] = r0
    s[0] = s0
    wm[0] = w0

    for i in range(steps):
        #compute mu_syn/sigma_syn from
        if rec:
            mu_syn = get_mu_syn(K, J, mu_ext,delay_type,i,r,r_d,n_d,taud,dt)
            sigma_syn = get_sigma_syn(K, J, sigma_ext,delay_type,i,r,r_d,n_d,taud,dt)
        else:
            mu_syn = mu_ext[i]
            sigma_syn = sigma_ext[i]
        #effective mu
        mu_eff = mu_syn - wm[i] / C

        # interpolate
        weights = interpolate_xy(mu_eff, sigma_syn, mu_range, sigma_range)
        # lookup
        Vm_inf = lookup_xy(map1_Vmean, weights)
        r_inf =  lookup_xy(map_r_inf, weights)
        lambda_1 = lookup_xy(map_lambda_1, weights)
        lambda_1_real[i] = lambda_1.real # save real part of lambda(t)

        # split lambda in real and imaginary part
        Re = lambda_1.real
        Im = lambda_1.imag
        r_diff = r[i] - r_inf

        # integration step
#         r[i+1] = r[i] + dt * (Re * r_diff - Im * s[i])
        r_prelim = r[i] + dt * (Re * r_diff - Im * s[i])
        r[i+1] = r_prelim if r_prelim > 0. else 0.
        r[i+1] = r[i] + dt * (Re * r_diff - Im * s[i])
        # TODO: add rectify of r via toggle (def: on)
        s[i+1] = s[i] + dt * (Im * r_diff + Re * s[i])
        wm[i+1] = wm[i] + dt_tauw * (a[i] * (Vm_inf - EW) - wm[i] + b_tauw[i] * r[i])

    return (r*1000, wm, lambda_1_real)
def sim_ln_exp_without_HEUN_OLD(mu_ext, sigma_ext, mu_range, sigma_range,
               map_Vmean, map_r, map_tau_mu_f, map_tau_sigma_f,
               L, muf0, sigma_f0, w_m0, a, b, C, dt, tauW, Ew,
               rec, K, J, delay_type, const_delay, taud):

    b_tauW = b * tauW

    # initialize arrays
    r_d = np.zeros(L+1)
    mu_f = np.zeros(L+1)
    sigma_f = np.zeros(L+1)
    w_m = np.zeros(L+1)
    rates = np.zeros(L+1)
    tau_mu_f = np.zeros(L+1)
    tau_sigma_f = np.zeros(L+1)
    Vm = np.zeros(L+1)

    # set initial values
    w_m[0] = w_m0
    mu_f[0] = muf0
    sigma_f[0] = sigma_f0

    for i in xrange(L):

        # interpolate
        mu_f_eff = mu_f[i]-w_m[i]/C
        weights = interpolate_xy(mu_f_eff, sigma_f[i], mu_range, sigma_range)

        # lookup
        Vm[i] = lookup_xy(map_Vmean, weights)
        rates[i] = lookup_xy(map_r, weights)
        tau_mu_f[i] = lookup_xy(map_tau_mu_f, weights)
        tau_sigma_f[i] = lookup_xy(map_tau_sigma_f, weights)

        if rec:
            mu_syn = get_mu_syn(K,J,mu_ext,delay_type,i,rates,r_d,const_delay,taud,dt)
            sigma_syn = get_sigma_syn(K,J,sigma_ext,delay_type,i,rates,r_d,const_delay,taud,dt)
        else:
            mu_syn = mu_ext[i]
            sigma_syn = sigma_ext[i]

        # rhs of equations
        mu_f_rhs = (mu_syn - mu_f[i])/tau_mu_f[i]
        sigma_f_rhs = (sigma_syn - sigma_f[i])/tau_sigma_f[i]
        w_m_rhs = (a[i]*(Vm[i] - Ew) - w_m[i] + b_tauW[i] * (rates[i]))/tauW

        # euler step
        mu_f[i+1]= mu_f[i] + dt * mu_f_rhs
        sigma_f[i+1]= sigma_f[i] + dt * sigma_f_rhs
        w_m[i+1]=w_m[i]+ dt * w_m_rhs
    #order of return tuple should always be rates, w_m, Vm, etc...
    return (rates*1000., w_m, Vm, tau_mu_f, tau_sigma_f, mu_f, sigma_f)
def sim_ln_dosc_UPDATE_without_HEUN(
    mu_ext,
    sig_ext,
    dmu_ext_dt,
    t,
    dt,
    steps,
    mu_range,
    sig_range,
    omega_grid,
    tau_grid,
    tau_mu_f_grid,
    tau_sigma_f_grid,
    Vmean_grid,
    r_grid,
    a,
    b,
    C,
    wm0,
    EW,
    tauw,
    rec,
    K,
    J,
    delay_type,
    const_delay,
    taud,
):

    # initialize arrays
    r = np.zeros_like(t)
    r_d = np.zeros_like(t)
    mu_f = np.zeros_like(t)
    dmu_f = np.zeros_like(t)  # aux. var for integration
    mu_lookup = np.zeros_like(t)
    sig_f = np.zeros_like(t)
    wm = np.zeros_like(t)

    # set initial values
    wm[0] = wm0
    # mu_f[0]  = mu_f0
    # sig_f[0] = sig_f0

    for i in xrange(steps):

        # 1st interpolation and lookup with
        # exponentially filtered mu_ext for looking up omega,tau ..
        weights_1 = interpolate_xy(mu_lookup[i] - wm[i] / C, sig_f[i], mu_range, sig_range)
        omega = lookup_xy(omega_grid, weights_1)
        tau = lookup_xy(tau_grid, weights_1)
        tau_mu_f = lookup_xy(tau_mu_f_grid, weights_1)
        tau_sigma_f = lookup_xy(tau_sigma_f_grid, weights_1)
        # 2nd interpolation and lookup with
        # mu_ext filtered by damped oscillatory function for looking up Vm and r
        weights_2 = interpolate_xy(mu_f[i] - wm[i] / C, sig_f[i], mu_range, sig_range)
        Vm = lookup_xy(Vmean_grid, weights_2)
        r[i] = lookup_xy(r_grid, weights_2)

        if rec:
            mu_syn = get_mu_syn(K, J, mu_ext, delay_type, i, r, r_d, const_delay, taud, dt)
            sigma_syn = get_sigma_syn(K, J, sig_ext, delay_type, i, r, r_d, const_delay, taud, dt)
        else:
            mu_syn = mu_ext[i]
            sigma_syn = sig_ext[i]

        # rhs of the equations
        mu_lookup_rhs = (mu_syn - mu_lookup[i]) / tau_mu_f
        sig_f_rhs = (sigma_syn - sig_f[i]) / tau_sigma_f
        wm_rhs = (a[i] * (Vm - EW) - wm[i] + tauw * b[i] * r[i]) / tauw

        # euler step
        A = (tau ** 2 * omega ** 2 + 1) / tau
        mu_f[i + 1] = mu_f[i] + dt * dmu_f[i]
        dmu_f[i + 1] = dmu_f[i] + dt * (
            (-2.0 / tau) * dmu_f[i] - (1.0 / tau ** 2 + omega ** 2) * mu_f[i] + A * (mu_syn / tau + dmu_ext_dt[i])
        )
        # indentical to the old model
        mu_lookup[i + 1] = mu_lookup[i] + dt * mu_lookup_rhs
        sig_f[i + 1] = sig_f[i] + dt * sig_f_rhs
        wm[i + 1] = wm[i] + dt * wm_rhs

    return (r * 1000.0, wm)
def sim_ln_bexdos(mu_ext, sig_ext, mu_range, sigma_range, B_mu_grid,
                  tau_mu_1_grid, tau_mu_2_grid, f0_mu_grid, tau_mua_grid,
                  tau_sigma_grid, Vm_grid, r_grid, dmu_ext_dt, C, K, J,
                  const_delay, delay_type, rec, taud, a, b, tauw, EW, t, dt,
                  steps, uni_int_order):

    # todo: figure out how to deal with

    # initialize arrays
    x_mu = np.zeros_like(t)
    y_mu = np.zeros_like(t)
    z_mu = np.zeros_like(t)

    mu_f = np.zeros_like(t)
    mu_a = np.zeros_like(t)
    mu_syn = np.zeros_like(t)
    dmu_syn_dt = np.zeros_like(t)
    sigma_syn = np.zeros_like(t)
    sigma_f = np.zeros_like(t)
    wm = np.zeros_like(t)
    Vm = np.zeros_like(t)
    r = np.zeros_like(t)
    r_d = np.zeros_like(t)
    inv_tau1 = np.zeros_like(t)

    B_mu = np.zeros_like(t)
    tau_mu_1 = np.zeros_like(t)
    tau_mu_2 = np.zeros_like(t)
    f0_mu = np.zeros_like(t)
    tau_mua = np.zeros_like(t)
    tau_sigma = np.zeros_like(t)
    A_mu = np.zeros_like(t)

    for i in xrange(steps):
        for j in range(int(uni_int_order)):
            # mu_a lookup
            weights_1 = interpolate_xy(mu_a[i + j] - wm[i + j] / C,
                                       sigma_f[i + j], mu_range, sigma_range)
            B_mu[i + j] = lookup_xy(B_mu_grid, weights_1)
            tau_mu_1[i + j] = lookup_xy(tau_mu_1_grid, weights_1)
            inv_tau1[i + j] = tau_mu_1[i + j]
            tau_mu_2[i + j] = lookup_xy(tau_mu_2_grid, weights_1)
            # todo change this to omega
            f0_mu[i + j] = lookup_xy(f0_mu_grid, weights_1)
            # this is tau_mu_exp
            tau_mua[i + j] = lookup_xy(tau_mua_grid, weights_1)
            # this is tau_sigma_exp
            tau_sigma[i + j] = lookup_xy(tau_sigma_grid, weights_1)

            A_mu[i+j] = 1./tau_mu_1[i+j] - B_mu[i+j]*tau_mu_2[i+j]/\
                                           ((1.+(2.*np.pi*f0_mu[i+j]*tau_mu_2[i+j])**2)
                                            *tau_mu_1[i+j])

            # mu_f lookup
            weights_2 = interpolate_xy(mu_f[i + j] - wm[i + j] / C,
                                       sigma_f[i + j], mu_range, sigma_range)
            Vm[i + j] = lookup_xy(Vm_grid, weights_2)
            r[i + j] = lookup_xy(r_grid, weights_2)

            if rec:
                mu_syn[i + j] = get_mu_syn(K, J, mu_ext, delay_type, i + j, r,
                                           r_d, const_delay, taud, dt)
                sigma_syn[i + j] = get_sigma_syn(K, J, sig_ext, delay_type,
                                                 i + j, r, r_d, const_delay,
                                                 taud, dt)

                # also compute the derivatives of the synaptic input
                # in the case of exponentially distributed
                # delays; compute dmu_syn_dt analytically
                if delay_type == 2:
                    dmu_syn_dt[
                        i +
                        j] = dmu_ext_dt[i + j] + (r[i + j] - r_d[i + j]) / taud
                # else finite differences mu_syn
                else:
                    dmu_syn_dt[i +
                               j] = (mu_syn[i + j] - mu_syn[i + j - 1]) / dt

            # this case corresponds to an UNCOUPLED POPULATION of neurons, i.e. K=0.
            #todo: double check thist comutation
            else:
                mu_syn[i + j] = mu_ext[i + j]
                sigma_syn[i + j] = sig_ext[i + j]
                dmu_syn_dt[i + j] = dmu_ext_dt[i + j]

            #euler step
            if j == 0:
                x_mu[i + 1] = x_mu[i] + dt * (A_mu[i] * mu_syn[i] -
                                              x_mu[i] / tau_mu_1[i])
                y_mu[i + 1] = y_mu[i] + dt * z_mu[i]
                z_mu[i + 1] = z_mu[i] + dt * (
                    B_mu[i] * mu_syn[i] / tau_mu_2[i] +
                    B_mu[i] * dmu_ext_dt[i] - 2. * z_mu[i] / tau_mu_2[i] -
                    (1. / tau_mu_2[i]**2 +
                     (2. * np.pi * f0_mu[i])**2) * y_mu[i])
                mu_f[i + 1] = x_mu[i + 1] + y_mu[i + 1]
                mu_a[i + 1] = mu_a[i] + dt * (mu_syn[i] -
                                              mu_a[i]) / dt  #dt #tau_mua[i]
                sigma_f[i + 1] = sigma_f[i] + dt * (sigma_syn[i] -
                                                    sigma_f[i]) / tau_sigma[i]
                wm[i + 1] = wm[i] + dt * (a[i] * (Vm[i] - EW) - wm[i] +
                                          tauw * b[i] * r[i]) / tauw

            #additional heun step #TODO: adjust according to euler above
            if j == 1:
                x_mu[i + 1] = x_mu[i] + dt / 2. * (
                    (mu_syn[i] - x_mu[i] / tau_mu_1[i]) +
                    (mu_syn[i + 1] - x_mu[i + 1] / tau_mu_1[i + 1]))
                y_mu[i + 1] = y_mu[i] + dt / 2. * (z_mu[i] + z_mu[i + 1])
                z_mu[i + 1] = z_mu[i] + dt / 2. * (
                    (mu_syn[i] / tau_mu_2[i] + dmu_ext_dt[i] -
                     2. * z_mu[i] / tau_mu_2[i] -
                     (1. / tau_mu_2[i]**2 +
                      (2. * np.pi * f0_mu[i])**2) * y_mu[i]) +
                    (mu_syn[i + 1] / tau_mu_2[i + 1] + dmu_ext_dt[i + 1] -
                     2. * z_mu[i + 1] / tau_mu_2[i + 1] -
                     (1. / tau_mu_2[i + 1]**2 +
                      (2. * np.pi * f0_mu[i + 1])**2) * y_mu[i + 1]))

                # no heun scheme for that step
                mu_f[i + 1] = A_mu[i] * x_mu[i + 1] + B_mu[i] * y_mu[i + 1]
                mu_a[i + 1] = mu_a[i] + dt / 2. * (
                    (mu_syn[i] - mu_a[i]) / tau_mua[i] +
                    (mu_syn[i + 1] - mu_a[i + 1]) / tau_mua[i + 1])
                sigma_f[i + 1] = sigma_f[i] + dt / 2. * (
                    (sigma_syn[i] - sigma_f[i]) / tau_sigma[i] +
                    (sigma_syn[i + 1] - sigma_f[i + 1]) / tau_sigma[i + 1])
                wm[i + 1] = wm[i] + dt / 2. * (
                    (a[i] * (Vm[i] - EW) - wm[i] + tauw * b[i] * r[i]) / tauw +
                    (a[i + 1] * (Vm[i + 1] - EW) - wm[i + 1] +
                     tauw * b[i + 1] * r[i + 1]) / tauw)
    return (r * 1000., wm, Vm)
Exemplo n.º 6
0
def sim_spec1(mu_ext,
              sigma_ext,
              map1_Vmean,
              map_r_inf,
              mu_range,
              sigma_range,
              map_lambda_1,
              tauw,
              dt,
              steps,
              C,
              a,
              b,
              EW,
              s0,
              r0,
              w0,
              rec,
              K,
              J,
              delay_type,
              n_d,
              taud,
              uni_int_order,
              rectify,
              grid_warn=True):

    # small optimization(s)
    dt_tauw = dt / tauw
    b_tauw = b * tauw

    # initialize arrays
    r = np.zeros(steps + 1)
    r_d = np.zeros(steps + 1)
    s = np.zeros(steps + 1)
    wm = np.zeros(steps + 1)
    Re = np.zeros(steps + 1)
    Im = np.zeros(steps + 1)
    Vm_inf = np.zeros(steps + 1)
    r_inf = np.zeros(steps + 1)
    r_diff = np.zeros(steps + 1)
    lambda_1_real = np.zeros(steps + 1)
    mu_total = np.zeros(steps + 1)

    # write initial condition into array
    r[0] = r0
    s[0] = s0
    wm[0] = w0

    for i in range(steps):
        for j in xrange(int(uni_int_order)):

            if rec:
                mu_syn = get_mu_syn(K, J, mu_ext, delay_type, i + j, r, r_d,
                                    n_d, taud, dt)
                sigma_syn = get_sigma_syn(K, J, sigma_ext, delay_type, i + j,
                                          r, r_d, n_d, taud, dt)

            # this case corresponds to an UNCOUPLED POPULATION of neurons, i.e. K=0.
            else:
                mu_syn = mu_ext[i + j]
                sigma_syn = sigma_ext[i + j]

            #effective mu
            mu_eff = mu_syn - wm[i + j] / C

            # grid warning
            if grid_warn and j == 0:
                outside_grid_warning(mu_eff, sigma_syn, mu_range, sigma_range,
                                     dt * i)

            # interpolate
            weights = interpolate_xy(mu_eff, sigma_syn, mu_range, sigma_range)
            # lookup
            Vm_inf[i + j] = lookup_xy(map1_Vmean, weights)
            r_inf[i + j] = lookup_xy(map_r_inf, weights)
            lambda_1 = lookup_xy(map_lambda_1, weights)
            lambda_1_real[i + j] = lambda_1.real  # save real part of lambda(t)

            # split lambda in real and imaginary part
            Re[i + j] = lambda_1.real
            Im[i + j] = lambda_1.imag
            r_diff[i + j] = r[i + j] - r_inf[i + j]
            mu_total[i + j] = mu_eff

            # j == 0: corresponds to a simple Euler method.
            # If j reaches 1 (-> j!=0) the ELSE block is executed
            # which updates using the HEUN scheme.
            if j == 0:
                r[i + 1] = r[i] + dt * (Re[i] * r_diff[i] - Im[i] * s[i])
                s[i + 1] = s[i] + dt * (Im[i] * r_diff[i] + Re[i] * s[i])

                wm[i+1] = wm[i] + dt_tauw * \
                                  (a[i] * (Vm_inf[i] - EW) - wm[i] + b_tauw[i] * r[i])

            # only perform Heun integration step if 'uni_int_order' == 2
            else:
                r[i + 1] = r[i] + dt / 2 * (
                    (Re[i] * r_diff[i] - Im[i] * s[i]) +
                    (Re[i + 1] * r_diff[i + 1] - Im[i + 1] * s[i + 1]))
                s[i + 1] = s[i] + dt / 2 * (
                    (Im[i] * r_diff[i] + Re[i] * s[i]) +
                    (Im[i + 1] * r_diff[i + 1] + Re[i + 1] * s[i + 1]))

                wm[i + 1] = wm[i] + dt_tauw / 2 * (
                    (a[i] * (Vm_inf[i] - EW) - wm[i] + b_tauw[i] * r[i]) +
                    (a[i + 1] * (Vm_inf[i + 1] - EW) - wm[i + 1] +
                     b_tauw[i + 1] * r[i + 1]))

        # set variables to zero if they would be integrated below 0
        if rectify and r[i + 1] < 0.:
            r[i + 1] = 0.
            s[i + 1] = 0.

    return (r * 1000, wm, lambda_1_real, mu_total, Vm_inf)
def sim_spec2m_simple_HEUN(mu_ext, sigma_ext,steps,dt,EW, a,b,C, tauw,
                      map_Vmean, map_rss, mu_range2, sigma_range2,
                      map_eig1, map_eig_mattia, rec,K,J,delay_type,n_d,
                      taud, r0, s0, w0, uni_int_order):

    # optimazations
    dt_tauw = dt/tauw
    b_tauw = b*tauw

    # initialize arrays
    r = np.zeros(steps+1)
    dr = np.zeros(steps+1)
    r_d = np.zeros(steps+1)
    s = np.zeros(steps+1)
    wm = np.zeros(steps+1)
    # more arrays for HEUN method
    Vm_inf = np.zeros(steps+1)
    r_inf = np.zeros(steps+1)
    lambda1_plus_lambda2 = np.zeros(steps+1)
    lambda1_times_lambda2 = np.zeros(steps+1)



    # write initial condition into array
    r[0] = r0
    s[0] = s0
    wm[0] = w0

    for i in xrange(steps):
        for j in xrange(int(uni_int_order)): # i --> i + j = i + 1 (for second round)

            if rec:
                mu_syn = get_mu_syn(K,J,mu_ext,delay_type,i+j,r,r_d,n_d,taud,dt)
                sigma_syn = get_sigma_syn(K,J,sigma_ext,delay_type,i+j,r,r_d,n_d,taud,dt)
            else:
                mu_syn = mu_ext[i+j]
                sigma_syn = sigma_ext[i+j]

            # compute effective mu
            mu_tot = mu_syn  - wm[i+j] / C

            # interpolate
            # weights_quant = interpolate_xy(mu_tot, sigma_syn, mu_range1, sigma_range1)
            weights_eig = interpolate_xy(mu_tot, sigma_syn, mu_range2, sigma_range2)

            # lookup
            Vm_inf[i+j]  = lookup_xy(map_Vmean, weights_eig)
            r_inf[i+j]  = lookup_xy(map_rss, weights_eig)
            lambda1  = lookup_xy(map_eig1, weights_eig)
            lambda2  = lookup_xy(map_eig_mattia, weights_eig)
            # results of lambda1+lambda2 and lambda1*lambda2
            # are always real --> eliminate imaginary parts
            lambda1_plus_lambda2[i+j] = (lambda1+lambda2).real
            lambda1_times_lambda2[i+j] = (lambda1*lambda2).real

            # TODO: add rectify of r via toggle (def: on)

            if j == 0:
                dr[i+1] = dr[i] + dt * (lambda1_times_lambda2[i] * (r_inf[i]-r[i])
                                        + lambda1_plus_lambda2[i] * dr[i])

                r[i+1]  = r[i]  + dt * dr[i]

                wm[i+1] = wm[i] + dt_tauw * (a[i] * (Vm_inf[i] - EW)
                                             - wm[i] + b_tauw[i] * r[i])

            # only perform Heun integration step if 'uni_int_order' == 2
            # to compute the updates state variables with the trapezian rule
            elif j == 1:
                dr[i+1] = dr[i] + dt/2. * ( (lambda1_times_lambda2[i] * (r_inf[i]-r[i])
                                               + lambda1_plus_lambda2[i] * dr[i])
                                        + (lambda1_times_lambda2[i+1] * (r_inf[i+1]-r[i+1])
                                            + lambda1_plus_lambda2[i+1] * dr[i+1]))

                r[i+1]  = r[i]  + dt/2. * (dr[i]+dr[i+1])

                wm[i+1] = wm[i] + dt_tauw/2.  * ( (a[i] * (Vm_inf[i] - EW)
                                                   - wm[i] + b_tauw[i] * r[i])
                                                  +(a[i+1] * (Vm_inf[i+1] - EW)
                                                    - wm[i+1] + b_tauw[i+1] * r[i+1]))
    # re
    return (r*1000., wm)
def sim_spec2m_simple(mu_ext, sigma_ext,steps,dt,EW, a,b,C, tauw,
                      map_Vmean, map_rss, mu_range2, sigma_range2,
                      map_eig1, map_eig_mattia, rec,K,J,delay_type,n_d,
                      taud, r0, s0, w0):

    # optimazations
    dt_tauw = dt/tauw
    b_tauw = b*tauw

    # initialize arrays
    r = np.zeros(steps+1)
    dr = np.zeros(steps+1)
    r_d = np.zeros(steps+1)
    s = np.zeros(steps+1)
    wm = np.zeros(steps+1)

    # write initial condition into array
    r[0] = r0
    s[0] = s0
    wm[0] = w0

    for i in xrange(steps):
        if rec:
            mu_syn = get_mu_syn(K,J,mu_ext,delay_type,i,r,r_d,n_d,taud,dt)
            sigma_syn = get_sigma_syn(K,J,sigma_ext,delay_type,i,r,r_d,n_d,taud,dt)
        else:
            mu_syn = mu_ext[i]
            sigma_syn = sigma_ext[i]

        # compute effective mu
        mu_tot = mu_syn  - wm[i] / C

        # interpolate
        # weights_quant = interpolate_xy(mu_tot, sigma_syn, mu_range1, sigma_range1)
        weights_eig = interpolate_xy(mu_tot, sigma_syn, mu_range2, sigma_range2)

        # lookup
        Vm_inf  = lookup_xy(map_Vmean, weights_eig)
        r_inf  = lookup_xy(map_rss, weights_eig)
        lambda1  = lookup_xy(map_eig1, weights_eig)
        lambda2  = lookup_xy(map_eig_mattia, weights_eig)
        # results of lambda1+lambda2 and lambda1*lambda2
        # are always real --> eliminate imaginary parts
        lambda1_plus_lambda2 = (lambda1+lambda2).real
        lambda1_times_lambda2 = (lambda1*lambda2).real

        # euler step
        # the model equations below are equal to the ones of
        # the spectral2m model for a feedforward setting without coupling and without adaptation
        dr[i+1] = dr[i] + dt * (lambda1_times_lambda2 * (r_inf-r[i]) + lambda1_plus_lambda2 * dr[i])
#         r_prelim = r[i] + dt * dr[i]
        # assert that r[i+1] is leq than 0
        # r[i+1]  = r[i]  + dt * dr[i]
#         r[i+1] = r_prelim if r_prelim > 0. else 0.
        r[i+1]  = r[i]  + dt * dr[i]
        # TODO: add rectify of r via toggle (def: on)
        # adaptation
        wm[i+1] = wm[i] + dt_tauw * (a[i] * (Vm_inf - EW) - wm[i] + b_tauw[i] * r[i])


    # rates computed in [kHz] or [1/ms] therefore change to [Hz]
    # return (r*1000., wm)
    return (r*1000., wm)
def sim_spec2m_simple(mu_ext, sigma_ext, steps, dt, EW, a, b, C, tauw,
                      map_Vmean, map_rss, mu_range2, sigma_range2, map_eig1,
                      map_eig_mattia, rec, K, J, delay_type, n_d, taud, r0, s0,
                      w0):

    # optimazations
    dt_tauw = dt / tauw
    b_tauw = b * tauw

    # initialize arrays
    r = np.zeros(steps + 1)
    dr = np.zeros(steps + 1)
    r_d = np.zeros(steps + 1)
    s = np.zeros(steps + 1)
    wm = np.zeros(steps + 1)

    # write initial condition into array
    r[0] = r0
    s[0] = s0
    wm[0] = w0

    for i in xrange(steps):
        if rec:
            mu_syn = get_mu_syn(K, J, mu_ext, delay_type, i, r, r_d, n_d, taud,
                                dt)
            sigma_syn = get_sigma_syn(K, J, sigma_ext, delay_type, i, r, r_d,
                                      n_d, taud, dt)
        else:
            mu_syn = mu_ext[i]
            sigma_syn = sigma_ext[i]

        # compute effective mu
        mu_tot = mu_syn - wm[i] / C

        # interpolate
        # weights_quant = interpolate_xy(mu_tot, sigma_syn, mu_range1, sigma_range1)
        weights_eig = interpolate_xy(mu_tot, sigma_syn, mu_range2,
                                     sigma_range2)

        # lookup
        Vm_inf = lookup_xy(map_Vmean, weights_eig)
        r_inf = lookup_xy(map_rss, weights_eig)
        lambda1 = lookup_xy(map_eig1, weights_eig)
        lambda2 = lookup_xy(map_eig_mattia, weights_eig)
        # results of lambda1+lambda2 and lambda1*lambda2
        # are always real --> eliminate imaginary parts
        lambda1_plus_lambda2 = (lambda1 + lambda2).real
        lambda1_times_lambda2 = (lambda1 * lambda2).real

        # euler step
        # the model equations below are equal to the ones of
        # the spectral2m model for a feedforward setting without coupling and without adaptation
        dr[i +
           1] = dr[i] + dt * (lambda1_times_lambda2 *
                              (r_inf - r[i]) + lambda1_plus_lambda2 * dr[i])
        #         r_prelim = r[i] + dt * dr[i]
        # assert that r[i+1] is leq than 0
        # r[i+1]  = r[i]  + dt * dr[i]
        #         r[i+1] = r_prelim if r_prelim > 0. else 0.
        r[i + 1] = r[i] + dt * dr[i]
        # TODO: add rectify of r via toggle (def: on)
        # adaptation
        wm[i +
           1] = wm[i] + dt_tauw * (a[i] *
                                   (Vm_inf - EW) - wm[i] + b_tauw[i] * r[i])

    # rates computed in [kHz] or [1/ms] therefore change to [Hz]
    # return (r*1000., wm)
    return (r * 1000., wm)
Exemplo n.º 10
0
def sim_spec1(mu_ext, sigma_ext, map1_Vmean, map_r_inf, mu_range,
              sigma_range, map_lambda_1, tauw, dt, steps, C,a ,b, EW,
              s0, r0,w0, rec,K,J,delay_type,n_d,taud, uni_int_order,
              rectify):

    # optimizations
    dt_tauw = dt/tauw
    b_tauw = b*tauw

    # initialize real arrays
    r   = np.zeros(steps+1)
    r_d = np.zeros(steps+1)
    s   = np.zeros(steps+1)
    wm  = np.zeros(steps+1)
    Re = np.zeros(steps+1)
    Im = np.zeros(steps+1)
    Vm_inf = np.zeros(steps+1)
    r_inf = np.zeros(steps+1)
    r_diff = np.zeros(steps+1)
    lambda_1_real = np.zeros(steps+1)
    mu_total = np.zeros(steps+1)

    # write initial condition into array
    r[0] = r0
    s[0] = s0
    wm[0] = w0

    for i in range(steps):
        # break loop after 1 iteration for Euler
        # two for Heun

        for j in xrange(int(uni_int_order)): # i --> i + j = i + 1 (for second round)

            if rec:
                mu_syn = get_mu_syn(K, J, mu_ext,delay_type,i+j,r,r_d,n_d,taud,dt)
                sigma_syn = get_sigma_syn(K, J, sigma_ext,delay_type,i+j,r,r_d,n_d,taud,dt)

            # this case corresponds to an UNCOUPLED POPULATION of neurons, i.e. K=0.
            else:
                mu_syn = mu_ext[i+j]
                sigma_syn = sigma_ext[i+j]

            #effective mu
            mu_eff = mu_syn - wm[i+j] / C

            # interpolate
            weights = interpolate_xy(mu_eff, sigma_syn, mu_range, sigma_range)
            # lookup
            Vm_inf[i+j] = lookup_xy(map1_Vmean, weights)
            r_inf[i+j] =  lookup_xy(map_r_inf, weights)
            lambda_1 = lookup_xy(map_lambda_1, weights)
            lambda_1_real[i+j] = lambda_1.real # save real part of lambda(t)

            # split lambda in real and imaginary part
            Re[i+j] = lambda_1.real
            Im[i+j] = lambda_1.imag
            r_diff[i+j] = r[i+j] - r_inf[i+j]
            mu_total[i+j] = mu_eff


            # TODO: add rectify of r via toggle (def: on)
            # integration step Euler
            if j == 0:
                r[i+1] = r[i] + dt * (Re[i] * r_diff[i] - Im[i] * s[i])
                s[i+1] = s[i] + dt * (Im[i] * r_diff[i] + Re[i] * s[i])

                wm[i+1] = wm[i] + dt_tauw * \
                                  (a[i] * (Vm_inf[i] - EW) - wm[i] + b_tauw[i] * r[i])

            # only perform Heun integration step if 'uni_int_order' == 2
            elif j == 1:
                    r[i+1] = r[i] + dt/2 * ( (Re[i] * r_diff[i] - Im[i] * s[i])
                                        + (Re[i+1]  * r_diff[i+1] - Im[i+1] * s[i+1]))
                    s[i+1] = s[i] + dt/2 * ( (Im[i] * r_diff[i] + Re[i] * s[i])
                                        + (Im[i+1]  * r_diff[i+1] + Re[i+1] * s[i+1]))

                    wm[i+1] = wm[i] + dt_tauw/2  * ( (a[i] * (Vm_inf[i] - EW) -
                                                wm[i] + b_tauw[i] * r[i])
                                                +(a[i+1] * (Vm_inf[i+1] - EW) -
                                               wm[i+1] + b_tauw[i+1] * r[i+1]))

        # set variables to zero if they would be integrated below 0
        if rectify and r[i+1] < 0.:
            r[i+1] = 0.
            s[i+1] = 0.

    return (r*1000, wm, lambda_1_real, mu_total, Vm_inf)
Exemplo n.º 11
0
def sim_ln_dos(mu_ext, sig_ext, dmu_ext_dt, t, dt, steps,
               mu_range, sig_range, omega_grid,tau_grid,
               tau_mu_f_grid, tau_sigma_f_grid, Vmean_grid,
               r_grid,a,b,C,wm0, EW, tauw, rec, K, J, delay_type,
               const_delay,taud,uni_int_order, grid_warn = True):
    
    # small optimization(s)
    b_tauW = b * tauw
    
    # initialize arrays
    r     = np.zeros_like(t)
    r_d   = np.zeros_like(t)
    mu_f  = np.zeros_like(t)
    mu_total = np.zeros_like(t)
    dmu_f = np.zeros_like(t)      #aux. var for integration
    dmu_syn_dt = np.zeros_like(t)
    sig_f     = np.zeros_like(t)
    wm  = np.zeros_like(t)
    Vm = np.zeros_like(t)
    mu_syn = np.zeros_like(t)
    sigma_syn = np.zeros_like(t)
    omega = np.zeros_like(t)
    tau = np.zeros_like(t)
    tau_mu_f = np.zeros_like(t)
    tau_sigma_f = np.zeros_like(t)
    A = np.zeros_like(t)

    # set initial value of wm
    wm[0] = wm0

    for i in xrange(steps):
        for j in range(int(uni_int_order)):



            # outside grid warning
            if grid_warn and j == 0:
                outside_grid_warning(mu_f[i+j]-wm[i+j]/C, sig_f[i+j],
                                     mu_range, sig_range, dt*i)



            # weights for looking up mean membrane voltage (Vm) 
            # and the firing rate (r)
            weights_2 = interpolate_xy(mu_f[i+j]-wm[i+j]/C, sig_f[i+j],
                                       mu_range, sig_range)
            Vm[i+j] = lookup_xy(Vmean_grid,weights_2)
            r[i+j] = lookup_xy(r_grid,weights_2)
            
            # with recurrency compute the synaptic mean and sigma
            # by generative functions 
            if rec:
                mu_syn[i+j] = get_mu_syn(K,J,mu_ext,delay_type,i+j,
                                    r,r_d,const_delay,taud,dt)
                sigma_syn[i+j] = get_sigma_syn(K,J,sig_ext,delay_type,i+j,
                                          r,r_d,const_delay,taud,dt)

                # exponentially distributed delays -> compute dmu_syn_dt analytically
                if delay_type == 2:
                    dmu_syn_dt[i+j] = dmu_ext_dt[i+j] + (r[i+j]-r_d[i+j])/taud
                # in all other rec cases compute dmu_syn by finite differences
                else:
                    dmu_syn_dt[i+j] = (mu_syn[i+j]-mu_syn[i+j-1])/dt

            # w/o recurrency (i.e. in the case of an upcoupled populatoin of neurons, K=0)
            # -> mu_syn, sigma_syn and dmu_syn_dt equal the external quantities
            else:
                mu_syn[i+j] = mu_ext[i+j]
                sigma_syn[i+j] = sig_ext[i+j]
                dmu_syn_dt[i+j] = dmu_ext_dt[i+j]

            # save total mu
            mu_total[i+j] = mu_syn[i+j]-wm[i+j]/C

            # weights for looking up omega, tau, tau_mu_f, tau_sigma_f                    
            weights_1 = interpolate_xy(mu_total[i+j],sigma_syn[i+j],
                                       mu_range, sig_range)   
                                       
            omega[i+j]  =      lookup_xy(omega_grid, weights_1)
            tau[i+j] =         lookup_xy(tau_grid, weights_1)
            tau_mu_f[i+j] =    lookup_xy(tau_mu_f_grid, weights_1)
            tau_sigma_f[i+j] = lookup_xy(tau_sigma_f_grid, weights_1)

            A[i+j] = (tau[i+j]**2*omega[i+j]**2+1)/tau[i+j]

            # j == 0: corresponds to a simple Euler method. 
            # If j reaches 1 (-> j!=0) the ELSE block is executed 
            # which updates using the HEUN scheme.
            if j == 0:
                mu_f[i+1] = mu_f[i] + dt*dmu_f[i]
                dmu_f[i+1] = dmu_f[i] + dt*( (-2./tau[i])*dmu_f[i]
                                        -(1./tau[i]**2 + omega[i]**2)*mu_f[i]
                                        +A[i]*(mu_syn[i]/tau[i]+dmu_syn_dt[i]))
                
                sig_f[i+1] = sig_f[i] + dt*(sigma_syn[i]-sig_f[i])/tau_sigma_f[i]
                wm[i+1] = wm[i] + dt*(a[i]*(Vm[i] - EW) - wm[i] + b_tauW[i] * r[i])/tauw
            # only perform Heun integration step if 'uni_int_order' == 2
            else:
                mu_f[i+1] = mu_f[i] + dt/2.*(dmu_f[i]+dmu_f[i+1])
                dmu_f[i+1] = dmu_f[i] + dt/2. * (( (-2./tau[i])*dmu_f[i]
                                        -(1./tau[i]**2 + omega[i]**2)*mu_f[i]
                                        +A[i]*(mu_syn[i]/tau[i]+dmu_syn_dt[i]))
                                        +( (-2./tau[i+1])*dmu_f[i+1]
                                        -(1./tau[i+1]**2 + omega[i+1]**2)*mu_f[i+1]
                                        +A[i+1]*(mu_syn[i+1]/tau[i+1]+dmu_syn_dt[i+1])))

                sig_f[i+1] = sig_f[i] + dt/2.*((sigma_syn[i]-sig_f[i])/tau_sigma_f[i]
                                            +(sigma_syn[i+1]-sig_f[i+1])/tau_sigma_f[i+1])
                
                wm[i+1] = wm[i] + dt/2.*((a[i]*(Vm[i] - EW) - wm[i] + b_tauW[i] * r[i])/tauw
                                      +(a[i+1]*(Vm[i+1] - EW) - wm[i+1] + b_tauW[i+1] * r[i+1])/tauw)

    # return results tuple
    return (r*1000., wm, mu_total, Vm)
def sim_ln_exp(mu_ext,
               sigma_ext,
               mu_range,
               sigma_range,
               map_Vmean,
               map_r,
               map_tau_mu_f,
               map_tau_sigma_f,
               L,
               muf0,
               sigma_f0,
               w_m0,
               a,
               b,
               C,
               dt,
               tauW,
               Ew,
               rec,
               K,
               J,
               delay_type,
               const_delay,
               taud,
               uni_int_order,
               grid_warn=True):

    # small optimization(s)
    b_tauW = b * tauW

    # initialize arrays
    r_d = np.zeros(L + 1)
    mu_f = np.zeros(L + 1)
    sigma_f = np.zeros(L + 1)
    mu_syn = np.zeros(L + 1)
    mu_total = np.zeros(L + 1)
    sigma_syn = np.zeros(L + 1)
    w_m = np.zeros(L + 1)
    rates = np.zeros(L + 1)
    tau_mu_f = np.zeros(L + 1)
    tau_sigma_f = np.zeros(L + 1)
    Vm = np.zeros(L + 1)

    # set initial values
    w_m[0] = w_m0
    mu_f[0] = muf0
    sigma_f[0] = sigma_f0

    for i in xrange(L):
        for j in xrange(int(uni_int_order)):
            # interpolate
            mu_f_eff = mu_f[i + j] - w_m[i + j] / C
            # save for param exploration
            # todo remove this again
            mu_total[i + j] = mu_f_eff

            # grid warning
            if grid_warn and j == 0:
                outside_grid_warning(mu_f_eff, sigma_f[i + j], mu_range,
                                     sigma_range, dt * i)
            # interpolate
            weights = interpolate_xy(mu_f_eff, sigma_f[i + j], mu_range,
                                     sigma_range)

            # lookup
            Vm[i + j] = lookup_xy(map_Vmean, weights)
            rates[i + j] = lookup_xy(map_r, weights)
            tau_mu_f[i + j] = lookup_xy(map_tau_mu_f, weights)
            tau_sigma_f[i + j] = lookup_xy(map_tau_sigma_f, weights)

            if rec:
                mu_syn[i + j] = get_mu_syn(K, J, mu_ext, delay_type, i + j,
                                           rates, r_d, const_delay, taud, dt)
                sigma_syn[i + j] = get_sigma_syn(K, J, sigma_ext, delay_type,
                                                 i + j, rates, r_d,
                                                 const_delay, taud, dt)

            # this case corresponds to an UNCOUPLED POPULATION of neurons, i.e. K=0.
            else:
                mu_syn[i + j] = mu_ext[i + j]
                sigma_syn[i + j] = sigma_ext[i + j]

            # j == 0: corresponds to a simple Euler method.
            # If j reaches 1 (-> j!=0) the ELSE block is executed
            # which updates using the HEUN scheme.
            if j == 0:
                mu_f[i+1] = mu_f[i] \
                           + dt * (mu_syn[i] - mu_f[i])/tau_mu_f[i]
                sigma_f[i+1] = sigma_f[i] \
                              + dt * (sigma_syn[i] - sigma_f[i])/tau_sigma_f[i]
                w_m[i+1] = w_m[i] + dt \
                                  * (a[i]*(Vm[i] - Ew) - w_m[i]
                                     + b_tauW[i] * (rates[i]))/tauW
            # only perform Heun integration step if 'uni_int_order' == 2
            else:
                mu_f[i+1] = mu_f[i] \
                            + dt/2. * ((mu_syn[i] - mu_f[i])/tau_mu_f[i]
                                       +(mu_syn[i+1] - mu_f[i+1])/tau_mu_f[i+1])

                sigma_f[i+1] = sigma_f[i] \
                               + dt/2. * ((sigma_syn[i] - sigma_f[i])/tau_sigma_f[i]
                                          +(sigma_syn[i+1] - sigma_f[i+1])/tau_sigma_f[i+1])
                w_m[i+1] = w_m[i] \
                           + dt/2. * (((a[i]*(Vm[i] - Ew) - w_m[i]
                                       + b_tauW[i] * (rates[i]))/tauW)
                                      +((a[i+1]*(Vm[i+1] - Ew) - w_m[i+1]
                                     + b_tauW[i+1] * (rates[i+1]))/tauW))

    #order of return tuple should always be rates, w_m, Vm, etc...
    return (rates * 1000., w_m, Vm, tau_mu_f, tau_sigma_f, mu_f, sigma_f,
            mu_total)
def sim_ln_bexdos(mu_ext, sig_ext, mu_range, sigma_range,
                  B_mu_grid, tau_mu_1_grid, tau_mu_2_grid,
                  f0_mu_grid, tau_mua_grid, tau_sigma_grid,
                  Vm_grid, r_grid, dmu_ext_dt,
                  C, K, J, const_delay, delay_type,
                  rec, taud,
                  a,b,tauw, EW,
                  t, dt, steps, uni_int_order):

    # todo: figure out how to deal with


    # initialize arrays
    x_mu = np.zeros_like(t)
    y_mu = np.zeros_like(t)
    z_mu = np.zeros_like(t)

    mu_f = np.zeros_like(t)
    mu_a = np.zeros_like(t)
    mu_syn = np.zeros_like(t)
    dmu_syn_dt = np.zeros_like(t)
    sigma_syn = np.zeros_like(t)
    sigma_f = np.zeros_like(t)
    wm = np.zeros_like(t)
    Vm = np.zeros_like(t)
    r = np.zeros_like(t)
    r_d = np.zeros_like(t)
    inv_tau1 = np.zeros_like(t)


    B_mu = np.zeros_like(t)
    tau_mu_1 = np.zeros_like(t)
    tau_mu_2 = np.zeros_like(t)
    f0_mu = np.zeros_like(t)
    tau_mua = np.zeros_like(t)
    tau_sigma = np.zeros_like(t)
    A_mu = np.zeros_like(t)





    for i in xrange(steps):
        for j in range(int(uni_int_order)):
            # mu_a lookup
            weights_1 = interpolate_xy(mu_a[i+j]-wm[i+j]/C, sigma_f[i+j], mu_range, sigma_range)
            B_mu[i+j] = lookup_xy(B_mu_grid, weights_1)
            tau_mu_1[i+j] = lookup_xy(tau_mu_1_grid,weights_1)
            inv_tau1[i+j] = tau_mu_1[i+j]
            tau_mu_2[i+j] = lookup_xy(tau_mu_2_grid,weights_1)
            # todo change this to omega
            f0_mu[i+j] = lookup_xy(f0_mu_grid, weights_1)
            # this is tau_mu_exp
            tau_mua[i+j] = lookup_xy(tau_mua_grid, weights_1)
            # this is tau_sigma_exp
            tau_sigma[i+j] = lookup_xy(tau_sigma_grid, weights_1)

            A_mu[i+j] = 1./tau_mu_1[i+j] - B_mu[i+j]*tau_mu_2[i+j]/\
                                           ((1.+(2.*np.pi*f0_mu[i+j]*tau_mu_2[i+j])**2)
                                            *tau_mu_1[i+j])



            # mu_f lookup
            weights_2 = interpolate_xy(mu_f[i+j]-wm[i+j]/C, sigma_f[i+j], mu_range, sigma_range)
            Vm[i+j] = lookup_xy(Vm_grid, weights_2)
            r[i+j] = lookup_xy(r_grid, weights_2)

            if rec:
                mu_syn[i+j] = get_mu_syn(K,J,mu_ext,delay_type,i+j,
                                    r,r_d,const_delay,taud,dt)
                sigma_syn[i+j] = get_sigma_syn(K,J,sig_ext,delay_type,i+j,
                                          r,r_d,const_delay,taud,dt)

                # also compute the derivatives of the synaptic input
                # in the case of exponentially distributed
                # delays; compute dmu_syn_dt analytically
                if delay_type == 2:
                    dmu_syn_dt[i+j] = dmu_ext_dt[i+j] + (r[i+j]-r_d[i+j])/taud
                # else finite differences mu_syn
                else:
                    dmu_syn_dt[i+j] = (mu_syn[i+j]-mu_syn[i+j-1])/dt




            # this case corresponds to an UNCOUPLED POPULATION of neurons, i.e. K=0.
            #todo: double check thist comutation
            else:
                mu_syn[i+j] = mu_ext[i+j]
                sigma_syn[i+j] = sig_ext[i+j]
                dmu_syn_dt[i+j] = dmu_ext_dt[i+j]


            #euler step
            if j == 0:
                x_mu[i+1] = x_mu[i] + dt*(A_mu[i]*mu_syn[i] - x_mu[i]/tau_mu_1[i])
                y_mu[i+1] = y_mu[i] + dt*z_mu[i]
                z_mu[i+1] = z_mu[i] + dt*(B_mu[i]*mu_syn[i]/tau_mu_2[i] + B_mu[i]*dmu_ext_dt[i]-2.*z_mu[i]/tau_mu_2[i]
                                          -(1./tau_mu_2[i]**2 + (2.*np.pi*f0_mu[i])**2)*y_mu[i])
                mu_f[i+1] = x_mu[i+1] + y_mu[i+1]
                mu_a[i+1] = mu_a[i] + dt*(mu_syn[i]-mu_a[i])/dt #dt #tau_mua[i]
                sigma_f[i+1] = sigma_f[i] + dt*(sigma_syn[i]-sigma_f[i])/tau_sigma[i]
                wm[i+1] = wm[i] + dt*(a[i]*(Vm[i] - EW) - wm[i] + tauw * b[i] * r[i])/tauw




            #additional heun step #TODO: adjust according to euler above
            if j == 1:
                x_mu[i+1] = x_mu[i] + dt/2.*((mu_syn[i] - x_mu[i]/tau_mu_1[i])
                                             +(mu_syn[i+1] - x_mu[i+1]/tau_mu_1[i+1]))
                y_mu[i+1] = y_mu[i] + dt/2.*(z_mu[i]+z_mu[i+1])
                z_mu[i+1] = z_mu[i] + dt/2.*((mu_syn[i]/tau_mu_2[i] + dmu_ext_dt[i]-2.*z_mu[i]/tau_mu_2[i]
                                              -(1./tau_mu_2[i]**2 + (2.*np.pi*f0_mu[i])**2)*y_mu[i])
                                            +(mu_syn[i+1]/tau_mu_2[i+1] + dmu_ext_dt[i+1]-2.*z_mu[i+1]/tau_mu_2[i+1]
                                              -(1./tau_mu_2[i+1]**2 + (2.*np.pi*f0_mu[i+1])**2)*y_mu[i+1]))

                # no heun scheme for that step
                mu_f[i+1] = A_mu[i]*x_mu[i+1] + B_mu[i]*y_mu[i+1]
                mu_a[i+1] = mu_a[i] + dt/2.*((mu_syn[i]-mu_a[i])/tau_mua[i]
                                             +(mu_syn[i+1]-mu_a[i+1])/tau_mua[i+1])
                sigma_f[i+1] = sigma_f[i] + dt/2.*((sigma_syn[i]-sigma_f[i])/tau_sigma[i]
                                                   +(sigma_syn[i+1]-sigma_f[i+1])/tau_sigma[i+1])
                wm[i+1] = wm[i] + dt/2.*((a[i]*(Vm[i] - EW) - wm[i] + tauw * b[i] * r[i])/tauw
                                         +(a[i+1]*(Vm[i+1] - EW) - wm[i+1] + tauw * b[i+1] * r[i+1])/tauw)
    return (r*1000., wm, Vm)
def sim_ln_dosc_UPDATE_without_HEUN(mu_ext, sig_ext, dmu_ext_dt, t, dt, steps,
                                    mu_range, sig_range, omega_grid, tau_grid,
                                    tau_mu_f_grid, tau_sigma_f_grid,
                                    Vmean_grid, r_grid, a, b, C, wm0, EW, tauw,
                                    rec, K, J, delay_type, const_delay, taud):

    # initialize arrays
    r = np.zeros_like(t)
    r_d = np.zeros_like(t)
    mu_f = np.zeros_like(t)
    dmu_f = np.zeros_like(t)  #aux. var for integration
    mu_lookup = np.zeros_like(t)
    sig_f = np.zeros_like(t)
    wm = np.zeros_like(t)

    # set initial values
    wm[0] = wm0
    # mu_f[0]  = mu_f0
    # sig_f[0] = sig_f0

    for i in xrange(steps):

        # 1st interpolation and lookup with
        # exponentially filtered mu_ext for looking up omega,tau ..
        weights_1 = interpolate_xy(mu_lookup[i] - wm[i] / C, sig_f[i],
                                   mu_range, sig_range)
        omega = lookup_xy(omega_grid, weights_1)
        tau = lookup_xy(tau_grid, weights_1)
        tau_mu_f = lookup_xy(tau_mu_f_grid, weights_1)
        tau_sigma_f = lookup_xy(tau_sigma_f_grid, weights_1)
        # 2nd interpolation and lookup with
        # mu_ext filtered by damped oscillatory function for looking up Vm and r
        weights_2 = interpolate_xy(mu_f[i] - wm[i] / C, sig_f[i], mu_range,
                                   sig_range)
        Vm = lookup_xy(Vmean_grid, weights_2)
        r[i] = lookup_xy(r_grid, weights_2)

        if rec:
            mu_syn = get_mu_syn(K, J, mu_ext, delay_type, i, r, r_d,
                                const_delay, taud, dt)
            sigma_syn = get_sigma_syn(K, J, sig_ext, delay_type, i, r, r_d,
                                      const_delay, taud, dt)
        else:
            mu_syn = mu_ext[i]
            sigma_syn = sig_ext[i]

        # rhs of the equations
        mu_lookup_rhs = (mu_syn - mu_lookup[i]) / tau_mu_f
        sig_f_rhs = (sigma_syn - sig_f[i]) / tau_sigma_f
        wm_rhs = (a[i] * (Vm - EW) - wm[i] + tauw * b[i] * r[i]) / tauw

        # euler step
        A = (tau**2 * omega**2 + 1) / tau
        mu_f[i + 1] = mu_f[i] + dt * dmu_f[i]
        dmu_f[i +
              1] = dmu_f[i] + dt * ((-2. / tau) * dmu_f[i] -
                                    (1. / tau**2 + omega**2) * mu_f[i] + A *
                                    (mu_syn / tau + dmu_ext_dt[i]))
        # indentical to the old model
        mu_lookup[i + 1] = mu_lookup[i] + dt * mu_lookup_rhs
        sig_f[i + 1] = sig_f[i] + dt * sig_f_rhs
        wm[i + 1] = wm[i] + dt * wm_rhs

    return (r * 1000., wm)
def sim_ln_dosc(
    mu_ext,
    sig_ext,
    dmu_ext_dt,
    t,
    dt,
    steps,
    mu_range,
    sig_range,
    omega_grid,
    tau_grid,
    tau_mu_f_grid,
    tau_sigma_f_grid,
    Vmean_grid,
    r_grid,
    a,
    b,
    C,
    wm0,
    EW,
    tauw,
    rec,
    K,
    J,
    delay_type,
    const_delay,
    taud,
    uni_int_order,
):

    # initialize arrays
    r = np.zeros_like(t)
    r_d = np.zeros_like(t)
    mu_f = np.zeros_like(t)
    mu_total = np.zeros_like(t)
    dmu_f = np.zeros_like(t)  # aux. var for integration
    dmu_syn_dt = np.zeros_like(t)
    sig_f = np.zeros_like(t)
    wm = np.zeros_like(t)
    # new arrays for HEUN method
    Vm = np.zeros_like(t)
    mu_syn = np.zeros_like(t)
    sigma_syn = np.zeros_like(t)
    omega = np.zeros_like(t)
    tau = np.zeros_like(t)
    tau_mu_f = np.zeros_like(t)
    tau_sigma_f = np.zeros_like(t)
    A = np.zeros_like(t)

    # set initial values
    wm[0] = wm0
    # mu_f[0]  = mu_f0
    # sig_f[0] = sig_f0

    for i in xrange(steps):
        for j in range(int(uni_int_order)):

            # mu_ext filtered by damped oscillatory function for looking up Vm and r
            weights_2 = interpolate_xy(mu_f[i + j] - wm[i + j] / C, sig_f[i + j], mu_range, sig_range)
            Vm[i + j] = lookup_xy(Vmean_grid, weights_2)
            r[i + j] = lookup_xy(r_grid, weights_2)

            if rec:
                mu_syn[i + j] = get_mu_syn(K, J, mu_ext, delay_type, i + j, r, r_d, const_delay, taud, dt)
                sigma_syn[i + j] = get_sigma_syn(K, J, sig_ext, delay_type, i + j, r, r_d, const_delay, taud, dt)

                # in the case of exponentially distributed
                # delays; compute dmu_syn_dt analytically
                if delay_type == 2:
                    dmu_syn_dt[i + j] = dmu_ext_dt[i + j] + K * J * (r[i + j] - r_d[i + j]) / taud
                # else finite differences mu_syn
                else:
                    dmu_syn_dt[i + j] = (mu_syn[i + j] - mu_syn[i + j - 1]) / dt

            # this case corresponds to an UNCOUPLED POPULATION of neurons, i.e. K=0.
            else:
                mu_syn[i + j] = mu_ext[i + j]
                sigma_syn[i + j] = sig_ext[i + j]
                dmu_syn_dt[i + j] = dmu_ext_dt[i + j]

            # save mu_total for param exploration
            # todo: remove this again
            mu_total[i + j] = mu_syn[i + j] - wm[i + j] / C

            # todo
            weights_1 = interpolate_xy(mu_total[i + j], sig_f[i + j], mu_range, sig_range)
            omega[i + j] = lookup_xy(omega_grid, weights_1)
            tau[i + j] = lookup_xy(tau_grid, weights_1)
            tau_mu_f[i + j] = lookup_xy(tau_mu_f_grid, weights_1)
            tau_sigma_f[i + j] = lookup_xy(tau_sigma_f_grid, weights_1)
            # 2nd interpolation and lookup with

            # euler step
            A[i + j] = (tau[i + j] ** 2 * omega[i + j] ** 2 + 1) / tau[i + j]

            if j == 0:
                mu_f[i + 1] = mu_f[i] + dt * dmu_f[i]
                dmu_f[i + 1] = dmu_f[i] + dt * (
                    (-2.0 / tau[i]) * dmu_f[i]
                    - (1.0 / tau[i] ** 2 + omega[i] ** 2) * mu_f[i]
                    + A[i] * (mu_syn[i] / tau[i] + dmu_syn_dt[i])
                )

                # indentical to the old model
                # mu_lookup[i+1] = mu_lookup[i] + dt*(mu_syn[i]-mu_lookup[i])/tau_mu_f[i]
                sig_f[i + 1] = sig_f[i] + dt * (sigma_syn[i] - sig_f[i]) / tau_sigma_f[i]
                wm[i + 1] = wm[i] + dt * (a[i] * (Vm[i] - EW) - wm[i] + tauw * b[i] * r[i]) / tauw
            if j == 1:
                mu_f[i + 1] = mu_f[i] + dt / 2.0 * (dmu_f[i] + dmu_f[i + 1])
                dmu_f[i + 1] = dmu_f[i] + dt / 2.0 * (
                    (
                        (-2.0 / tau[i]) * dmu_f[i]
                        - (1.0 / tau[i] ** 2 + omega[i] ** 2) * mu_f[i]
                        + A[i] * (mu_syn[i] / tau[i] + dmu_syn_dt[i])
                    )
                    + (
                        (-2.0 / tau[i + 1]) * dmu_f[i + 1]
                        - (1.0 / tau[i + 1] ** 2 + omega[i + 1] ** 2) * mu_f[i + 1]
                        + A[i + 1] * (mu_syn[i + 1] / tau[i + 1] + dmu_syn_dt[i + 1])
                    )
                )

                # indentical to the old model
                # mu_lookup[i+1] = mu_lookup[i] + dt/2.*((mu_syn[i]-mu_lookup[i])/tau_mu_f[i]
                #                                       +(mu_syn[i+1]-mu_lookup[i+1])/tau_mu_f[i+1])

                sig_f[i + 1] = sig_f[i] + dt / 2.0 * (
                    (sigma_syn[i] - sig_f[i]) / tau_sigma_f[i] + (sigma_syn[i + 1] - sig_f[i + 1]) / tau_sigma_f[i + 1]
                )
                wm[i + 1] = wm[i] + dt / 2.0 * (
                    (a[i] * (Vm[i] - EW) - wm[i] + tauw * b[i] * r[i]) / tauw
                    + (a[i + 1] * (Vm[i + 1] - EW) - wm[i + 1] + tauw * b[i + 1] * r[i + 1]) / tauw
                )
    return (r * 1000.0, wm, mu_total, Vm)
def sim_ln_dosc_complex_model_OLD(
    mu_ext,
    sigma_ext,
    L,
    mu_exp,
    sigma_exp,
    w_m_orig,
    dt,
    EW,
    taum,
    gL,
    tauw,
    a,
    b,
    mu_range,
    sig_range,
    f0_grid,
    tau_grid,
    tau_mu_f_grid,
    tau_sigma_f_grid,
    Vmean_grid,
    r_grid,
    rec,
    K,
    J,
    delay_type,
    n_d,
    taud,
):

    mu_f = np.zeros(L + 1, dtype=numba.complex128) if use_numba else np.zeros(L + 1, dtype=np.complex128)
    mu_a = np.zeros(L + 1)
    r = np.zeros(L + 1)
    r_d = np.zeros(L + 1)
    wm = np.zeros(L + 1)
    sigma_f = np.zeros(L + 1)
    # initial_conditions
    mu_a[0] = mu_exp
    wm[0] = w_m_orig
    sigma_f[0] = sigma_exp
    weights_a = interpolate_xy(mu_a[0] - wm[0] / (taum * gL), sigma_f[0], mu_range, sig_range)
    f0 = lookup_xy(f0_grid, weights_a)
    tau = lookup_xy(tau_grid, weights_a)
    mu_f[0] = mu_exp * (1 + 1j * 2 * np.pi * f0 * tau)
    for i in xrange(L):
        # interpolates real numbers
        weights_a = interpolate_xy(mu_a[i] - wm[i] / (taum * gL), sigma_f[i], mu_range, sig_range)
        f0 = lookup_xy(f0_grid, weights_a)
        tau = lookup_xy(tau_grid, weights_a)
        tau_mu_f = lookup_xy(tau_mu_f_grid, weights_a)
        tau_sigma_f = lookup_xy(tau_sigma_f_grid, weights_a)

        weights_f = interpolate_xy(mu_f[i].real - wm[i] / (taum * gL), sigma_f[i], mu_range, sig_range)
        Vmean_dosc = lookup_xy(Vmean_grid, weights_f)
        r_dosc = lookup_xy(r_grid, weights_f)
        r[i] = r_dosc

        if rec:
            mu_syn = get_mu_syn(K, J, mu_ext, delay_type, i, r, r_d, n_d, taud, dt)
            sigma_syn = get_sigma_syn(K, J, sigma_ext, delay_type, i, r, r_d, n_d, taud, dt)
        else:
            mu_syn = mu_ext[i]
            sigma_syn = sigma_ext[i]

        mu_f_rhs = ((2 * np.pi * f0) ** 2 * tau + 1.0 / tau) * mu_syn + (1j * 2 * np.pi * f0 - 1.0 / tau) * mu_f[i]
        sigma_f_rhs = (sigma_syn - sigma_f[i]) / tau_sigma_f
        w_rhs = (a[i] * (Vmean_dosc - EW) - wm[i] + tauw * b[i] * r_dosc) / tauw
        mu_a_rhs = (mu_syn - mu_a[i]) / tau_mu_f

        # EULER STEP
        mu_f[i + 1] = mu_f[i] + dt * mu_f_rhs
        mu_a[i + 1] = mu_a[i] + dt * mu_a_rhs
        sigma_f[i + 1] = sigma_f[i] + dt * sigma_f_rhs
        wm[i + 1] = wm[i] + dt * w_rhs

    return (r * 1000.0, wm)
def sim_ln_exp(mu_ext, sigma_ext, mu_range, sigma_range,
               map_Vmean, map_r, map_tau_mu_f, map_tau_sigma_f,
               L, muf0, sigma_f0, w_m0, a, b, C, dt, tauW, Ew,
               rec, K, J, delay_type, const_delay, taud, uni_int_order):

    b_tauW = b * tauW

    # initialize arrays
    r_d = np.zeros(L+1)
    mu_f = np.zeros(L+1)
    sigma_f = np.zeros(L+1)
    mu_syn = np.zeros(L+1)
    mu_total = np.zeros(L+1)
    sigma_syn = np.zeros(L+1)
    w_m = np.zeros(L+1)
    rates = np.zeros(L+1)
    tau_mu_f = np.zeros(L+1)
    tau_sigma_f = np.zeros(L+1)
    Vm = np.zeros(L+1)

    # set initial values
    w_m[0] = w_m0
    mu_f[0] = muf0
    sigma_f[0] = sigma_f0

    for i in xrange(L):
        for j in xrange(int(uni_int_order)):
            # interpolate
            mu_f_eff = mu_f[i+j]-w_m[i+j]/C
            # save for param exploration
            # todo remove this again
            mu_total[i+j] = mu_f_eff
            weights = interpolate_xy(mu_f_eff, sigma_f[i+j], mu_range, sigma_range)

            # lookup
            Vm[i+j] = lookup_xy(map_Vmean, weights)
            rates[i+j] = lookup_xy(map_r, weights)
            tau_mu_f[i+j] = lookup_xy(map_tau_mu_f, weights)
            tau_sigma_f[i+j] = lookup_xy(map_tau_sigma_f, weights)

            if rec:
                mu_syn[i+j] = get_mu_syn(K,J,mu_ext,delay_type,i+j,
                                         rates,r_d,const_delay,taud,dt)
                sigma_syn[i+j] = get_sigma_syn(K,J,sigma_ext,delay_type,i+j,
                                               rates,r_d,const_delay,taud,dt)

            # this case corresponds to an UNCOUPLED POPULATION of neurons, i.e. K=0.
            else:
                mu_syn[i+j] = mu_ext[i+j]
                sigma_syn[i+j] = sigma_ext[i+j]


            # euler step
            if j == 0:
                mu_f[i+1] = mu_f[i] \
                           + dt * (mu_syn[i] - mu_f[i])/tau_mu_f[i]
                sigma_f[i+1] = sigma_f[i] \
                              + dt * (sigma_syn[i] - sigma_f[i])/tau_sigma_f[i]
                w_m[i+1] = w_m[i] + dt \
                                  * (a[i]*(Vm[i] - Ew) - w_m[i]
                                     + b_tauW[i] * (rates[i]))/tauW
            if j == 1:
                mu_f[i+1] = mu_f[i] \
                            + dt/2. * ((mu_syn[i] - mu_f[i])/tau_mu_f[i]
                                       +(mu_syn[i+1] - mu_f[i+1])/tau_mu_f[i+1])

                sigma_f[i+1] = sigma_f[i] \
                               + dt/2. * ((sigma_syn[i] - sigma_f[i])/tau_sigma_f[i]
                                          +(sigma_syn[i+1] - sigma_f[i+1])/tau_sigma_f[i+1])
                w_m[i+1] = w_m[i] \
                           + dt/2. * (((a[i]*(Vm[i] - Ew) - w_m[i]
                                       + b_tauW[i] * (rates[i]))/tauW)
                                      +((a[i+1]*(Vm[i+1] - Ew) - w_m[i+1]
                                     + b_tauW[i+1] * (rates[i+1]))/tauW))
    #order of return tuple should always be rates, w_m, Vm, etc...
    return (rates*1000., w_m, Vm, tau_mu_f, tau_sigma_f, mu_f, sigma_f, mu_total)
def sim_spec2m_simple_HEUN(mu_ext, sigma_ext, steps, dt, EW, a, b, C, tauw,
                           map_Vmean, map_rss, mu_range2, sigma_range2,
                           map_eig1, map_eig_mattia, rec, K, J, delay_type,
                           n_d, taud, r0, s0, w0, uni_int_order):

    # optimazations
    dt_tauw = dt / tauw
    b_tauw = b * tauw

    # initialize arrays
    r = np.zeros(steps + 1)
    dr = np.zeros(steps + 1)
    r_d = np.zeros(steps + 1)
    s = np.zeros(steps + 1)
    wm = np.zeros(steps + 1)
    # more arrays for HEUN method
    Vm_inf = np.zeros(steps + 1)
    r_inf = np.zeros(steps + 1)
    lambda1_plus_lambda2 = np.zeros(steps + 1)
    lambda1_times_lambda2 = np.zeros(steps + 1)

    # write initial condition into array
    r[0] = r0
    s[0] = s0
    wm[0] = w0

    for i in xrange(steps):
        for j in xrange(
                int(uni_int_order)):  # i --> i + j = i + 1 (for second round)

            if rec:
                mu_syn = get_mu_syn(K, J, mu_ext, delay_type, i + j, r, r_d,
                                    n_d, taud, dt)
                sigma_syn = get_sigma_syn(K, J, sigma_ext, delay_type, i + j,
                                          r, r_d, n_d, taud, dt)
            else:
                mu_syn = mu_ext[i + j]
                sigma_syn = sigma_ext[i + j]

            # compute effective mu
            mu_tot = mu_syn - wm[i + j] / C

            # interpolate
            # weights_quant = interpolate_xy(mu_tot, sigma_syn, mu_range1, sigma_range1)
            weights_eig = interpolate_xy(mu_tot, sigma_syn, mu_range2,
                                         sigma_range2)

            # lookup
            Vm_inf[i + j] = lookup_xy(map_Vmean, weights_eig)
            r_inf[i + j] = lookup_xy(map_rss, weights_eig)
            lambda1 = lookup_xy(map_eig1, weights_eig)
            lambda2 = lookup_xy(map_eig_mattia, weights_eig)
            # results of lambda1+lambda2 and lambda1*lambda2
            # are always real --> eliminate imaginary parts
            lambda1_plus_lambda2[i + j] = (lambda1 + lambda2).real
            lambda1_times_lambda2[i + j] = (lambda1 * lambda2).real

            # TODO: add rectify of r via toggle (def: on)

            if j == 0:
                dr[i + 1] = dr[i] + dt * (lambda1_times_lambda2[i] *
                                          (r_inf[i] - r[i]) +
                                          lambda1_plus_lambda2[i] * dr[i])

                r[i + 1] = r[i] + dt * dr[i]

                wm[i + 1] = wm[i] + dt_tauw * (a[i] * (Vm_inf[i] - EW) -
                                               wm[i] + b_tauw[i] * r[i])

            # only perform Heun integration step if 'uni_int_order' == 2
            # to compute the updates state variables with the trapezian rule
            elif j == 1:
                dr[i + 1] = dr[i] + dt / 2. * (
                    (lambda1_times_lambda2[i] *
                     (r_inf[i] - r[i]) + lambda1_plus_lambda2[i] * dr[i]) +
                    (lambda1_times_lambda2[i + 1] * (r_inf[i + 1] - r[i + 1]) +
                     lambda1_plus_lambda2[i + 1] * dr[i + 1]))

                r[i + 1] = r[i] + dt / 2. * (dr[i] + dr[i + 1])

                wm[i + 1] = wm[i] + dt_tauw / 2. * (
                    (a[i] * (Vm_inf[i] - EW) - wm[i] + b_tauw[i] * r[i]) +
                    (a[i + 1] * (Vm_inf[i + 1] - EW) - wm[i + 1] +
                     b_tauw[i + 1] * r[i + 1]))
    # re
    return (r * 1000., wm)
def sim_ln_dosc(mu_ext, sig_ext, dmu_ext_dt, t, dt, steps, mu_range, sig_range,
                omega_grid, tau_grid, tau_mu_f_grid, tau_sigma_f_grid,
                Vmean_grid, r_grid, a, b, C, wm0, EW, tauw, rec, K, J,
                delay_type, const_delay, taud, uni_int_order):

    # initialize arrays
    r = np.zeros_like(t)
    r_d = np.zeros_like(t)
    mu_f = np.zeros_like(t)
    mu_total = np.zeros_like(t)
    dmu_f = np.zeros_like(t)  #aux. var for integration
    dmu_syn_dt = np.zeros_like(t)
    sig_f = np.zeros_like(t)
    wm = np.zeros_like(t)
    # new arrays for HEUN method
    Vm = np.zeros_like(t)
    mu_syn = np.zeros_like(t)
    sigma_syn = np.zeros_like(t)
    omega = np.zeros_like(t)
    tau = np.zeros_like(t)
    tau_mu_f = np.zeros_like(t)
    tau_sigma_f = np.zeros_like(t)
    A = np.zeros_like(t)

    # set initial values
    wm[0] = wm0
    # mu_f[0]  = mu_f0
    # sig_f[0] = sig_f0

    for i in xrange(steps):
        for j in range(int(uni_int_order)):

            # mu_ext filtered by damped oscillatory function for looking up Vm and r
            weights_2 = interpolate_xy(mu_f[i + j] - wm[i + j] / C,
                                       sig_f[i + j], mu_range, sig_range)
            Vm[i + j] = lookup_xy(Vmean_grid, weights_2)
            r[i + j] = lookup_xy(r_grid, weights_2)

            if rec:
                mu_syn[i + j] = get_mu_syn(K, J, mu_ext, delay_type, i + j, r,
                                           r_d, const_delay, taud, dt)
                sigma_syn[i + j] = get_sigma_syn(K, J, sig_ext, delay_type,
                                                 i + j, r, r_d, const_delay,
                                                 taud, dt)

                # in the case of exponentially distributed
                # delays; compute dmu_syn_dt analytically
                if delay_type == 2:
                    dmu_syn_dt[i + j] = dmu_ext_dt[
                        i + j] + K * J * (r[i + j] - r_d[i + j]) / taud
                # else finite differences mu_syn
                else:
                    dmu_syn_dt[i +
                               j] = (mu_syn[i + j] - mu_syn[i + j - 1]) / dt

            # this case corresponds to an UNCOUPLED POPULATION of neurons, i.e. K=0.
            else:
                mu_syn[i + j] = mu_ext[i + j]
                sigma_syn[i + j] = sig_ext[i + j]
                dmu_syn_dt[i + j] = dmu_ext_dt[i + j]

            # save mu_total for param exploration
            # todo: remove this again
            mu_total[i + j] = mu_syn[i + j] - wm[i + j] / C

            # todo
            weights_1 = interpolate_xy(mu_total[i + j], sig_f[i + j], mu_range,
                                       sig_range)
            omega[i + j] = lookup_xy(omega_grid, weights_1)
            tau[i + j] = lookup_xy(tau_grid, weights_1)
            tau_mu_f[i + j] = lookup_xy(tau_mu_f_grid, weights_1)
            tau_sigma_f[i + j] = lookup_xy(tau_sigma_f_grid, weights_1)
            # 2nd interpolation and lookup with

            # euler step
            A[i + j] = (tau[i + j]**2 * omega[i + j]**2 + 1) / tau[i + j]

            if j == 0:
                mu_f[i + 1] = mu_f[i] + dt * dmu_f[i]
                dmu_f[i + 1] = dmu_f[i] + dt * (
                    (-2. / tau[i]) * dmu_f[i] -
                    (1. / tau[i]**2 + omega[i]**2) * mu_f[i] + A[i] *
                    (mu_syn[i] / tau[i] + dmu_syn_dt[i]))

                # indentical to the old model
                # mu_lookup[i+1] = mu_lookup[i] + dt*(mu_syn[i]-mu_lookup[i])/tau_mu_f[i]
                sig_f[i + 1] = sig_f[i] + dt * (sigma_syn[i] -
                                                sig_f[i]) / tau_sigma_f[i]
                wm[i + 1] = wm[i] + dt * (a[i] * (Vm[i] - EW) - wm[i] +
                                          tauw * b[i] * r[i]) / tauw
            if j == 1:
                mu_f[i + 1] = mu_f[i] + dt / 2. * (dmu_f[i] + dmu_f[i + 1])
                dmu_f[i + 1] = dmu_f[i] + dt / 2. * (
                    ((-2. / tau[i]) * dmu_f[i] -
                     (1. / tau[i]**2 + omega[i]**2) * mu_f[i] + A[i] *
                     (mu_syn[i] / tau[i] + dmu_syn_dt[i])) +
                    ((-2. / tau[i + 1]) * dmu_f[i + 1] -
                     (1. / tau[i + 1]**2 + omega[i + 1]**2) * mu_f[i + 1] +
                     A[i + 1] *
                     (mu_syn[i + 1] / tau[i + 1] + dmu_syn_dt[i + 1])))

                # indentical to the old model
                # mu_lookup[i+1] = mu_lookup[i] + dt/2.*((mu_syn[i]-mu_lookup[i])/tau_mu_f[i]
                #                                       +(mu_syn[i+1]-mu_lookup[i+1])/tau_mu_f[i+1])

                sig_f[i + 1] = sig_f[i] + dt / 2. * (
                    (sigma_syn[i] - sig_f[i]) / tau_sigma_f[i] +
                    (sigma_syn[i + 1] - sig_f[i + 1]) / tau_sigma_f[i + 1])
                wm[i + 1] = wm[i] + dt / 2. * (
                    (a[i] * (Vm[i] - EW) - wm[i] + tauw * b[i] * r[i]) / tauw +
                    (a[i + 1] * (Vm[i + 1] - EW) - wm[i + 1] +
                     tauw * b[i + 1] * r[i + 1]) / tauw)
    return (r * 1000., wm, mu_total, Vm)