示例#1
0
def threecycle_stimulus(tau):
    """
    Applies the 3-cycle stimulus protocol for a given tau

    Arguments
    ----------
    tau : float
        period of oscillation
    """

    # pre-pulse
    y0 = [0.99996874, 0.10023398, 0]
    param[3] = tau
    kron = lc.Oscillator(model(null_I), param, y0)
    kron.intoptions['constraints'] = None
    dsol_pre = kron.int_odes(10.4)
    dts_pre = kron.ts
    y0_pulse = dsol_pre[-1]

    dsol_pulses = [dsol_pre]
    dts_pulses = [dts_pre]
    for i in range(3):
        # during pulse
        kron = lc.Oscillator(model(I_pulse), param, y0_pulse)
        kron.intoptions['constraints'] = None
        dsol_dur = kron.int_odes(5)
        dts_dur = kron.ts

        # after pulse
        kron = lc.Oscillator(model(null_I), param, dsol_dur[-1])
        kron.intoptions['constraints'] = None
        dsol_post = kron.int_odes(19)
        dts_post = kron.ts

        y0_pulse = dsol_post[-1]
        dts_pulses.append(dts_dur + dts_pulses[-1][-1])
        dts_pulses.append(dts_post + dts_pulses[-1][-1])
        dsol_pulses.append(dsol_dur)
        dsol_pulses.append(dsol_post)

    final_dist = np.sqrt(np.sum(dsol_dur[-1][:2]**2))
    dsol_pulses = np.vstack(dsol_pulses)
    dts_pulses = np.hstack(dts_pulses)

    return dts_pulses, dsol_pulses, final_dist
示例#2
0
def mpc_problem(init_phi, ts, ref_phis, pred_horizon):
    """
    uses MPC to track the reference phis, using a stepsize and a predictive horizon.
    ts should be separated by stepsize.
    """
    # set up the system it gets applied to
    y0mpc = pmodel.lc(init_phi * pmodel.T / (2 * np.pi) + start_time)

    # get step size, current phase, etc
    stepsize = ts[1] - ts[0]
    u_input = []
    sys_state = y0mpc

    sys_phis = []
    for idx, inst_time in enumerate(ts):
        #get the ref phase at the time, compare to system phase at the time
        ref_phi = ref_phis[idx]
        # remember, phi0 is defined as when the 0-cross happens
        sys_phi = (pmodel.phase_of_point(sys_state) -
                   pmodel._t_to_phi(start_time)) % (2 * np.pi)
        sys_phis.append(sys_phi)

        # phase error
        phi_diff = np.angle(np.exp(1j * sys_phi)) - np.angle(
            np.exp(1j * ref_phi))
        delta_phi_f = -phi_diff % (
            2 * np.pi)  # the desired shift is to make up that angle

        if np.abs(phi_diff) > 0.1:  #this value may be changed as desired
            # calculate the optimal inputs
            us_opt = mpc_pred_horiz(sys_phi, delta_phi_f, stepsize,
                                    pred_horizon)
            u_apply = us_opt[0]

        else:
            u_apply = 0

        print delta_phi_f, u_apply
        # move forward a step
        u_input.append(u_apply)
        mpc_param = np.copy(param)
        mpc_param[15] = mpc_param[15] - u_apply
        mpc_sys = lco.Oscillator(model(), mpc_param, sys_state)
        sys_progress = mpc_sys.int_odes(stepsize)
        sys_state = sys_progress[-1]

    return ts, sys_phis, u_input
示例#3
0
def solutions_from_us(us, stepsize, init_phi):
    """ takes a set of us, a stepsize, and a phi0; returns the trajectories of the solutions """

    pred_horiz = len(us)
    phases = []
    ref_phases = []
    states = []
    times = []
    running_time = 0
    phi0 = init_phi

    y0mpc = pmodel.lc(phi0 * pmodel.T / (2 * np.pi) + start_time)
    sys_state = y0mpc

    for u_apply in us:
        mpc_param = np.copy(param)
        mpc_param[15] = mpc_param[15] - u_apply
        mpc_sys = lco.Oscillator(model(), mpc_param, sys_state)
        sys_progress = mpc_sys.int_odes(stepsize, numsteps=10)

        # append new times and phases
        times = times + list(mpc_sys.ts[:-1] + running_time)
        phases = phases + [
            pmodel.phase_of_point(state) for state in sys_progress[:-1]
        ]

        #update for next step
        sys_state = sys_progress[-1]
        running_time = running_time + mpc_sys.ts[-1]

    u0_phases = init_phi + np.asarray(times) * 2 * np.pi / pmodel.T

    return {
        'u0_phases': np.asarray(u0_phases),
        'times': np.asarray(times),
        'phases': np.asarray(phases),
        'us': np.asarray(us)
    }
示例#4
0
def threecycle_targeted_stimulus(tau, phase_target):
    """
    Applies the 3-cycle stimulus protocol for a given tau

    Arguments
    ----------
    tau : float
        period of oscillation
    phase_target : float
        phase at which we want to apply the pulse
    """

    # set up parameters for first time
    y0 = [0.99996874, 0.10023398, 0]
    param[3] = tau

    dsol_total = [[y0]]
    dts_total = [[0]]
    for pulsecount in range(3):

        # set up oscillator
        kron = lc.Oscillator(model(null_I), param, y0)
        kron.intoptions['constraints'] = None
        phase = skron.phase_of_point(y0[:-1])

        # move forward when it's before the pulse time, or after the pulse
        while np.logical_or(phase < phase_target,
                            phase > phase_target + 3 / tau * 2 * np.pi):
            # perform the integration
            dsol_pre = kron.int_odes(0.5, numsteps=100)
            dts_pre = kron.ts
            yend = dsol_pre[-1]
            phase = skron.phase_of_point(yend[:-1])
            kron.y0 = yend

            # append the integration
            dsol_total.append(dsol_pre)
            dts_total.append(dts_pre + dts_total[-1][-1])

        # when it's time, apply the pulse
        kron = lc.Oscillator(model(I_pulse), param, yend)
        kron.intoptions['constraints'] = None
        dsol_dur = kron.int_odes(5)
        dts_dur = kron.ts

        y0 = dsol_dur[-1]
        dts_total.append(dts_dur + dts_total[-1][-1])
        dsol_total.append(dsol_dur)

    # residual 15h period after pulse - no need to try to target here
    kron = lc.Oscillator(model(null_I), param, dsol_dur[-1])
    kron.intoptions['constraints'] = None
    dsol_post = kron.int_odes(15)
    dts_post = kron.ts

    dts_total.append(dts_post + dts_total[-1][-1])
    dsol_total.append(dsol_post)

    final_dist = np.sqrt(np.sum(dsol_dur[-1][:2]**2))
    dsol_total = np.vstack(dsol_total)
    dts_total = np.hstack(dts_total)

    return dts_total, dsol_total, final_dist
示例#5
0
"""
from __future__ import division

import numpy as np
import casadi as cs
import matplotlib.pyplot as plt
from matplotlib import Grid

from LocalImports import LimitCycle as lc
from LocalImports import PlotOptions as plo

from LocalModels.kronauer_model import model, param, EqCount, y0in, null_I
import LocalModels.simplified_kronauer_model as skm

# set-up way to get the phase of a point using the simpler model
skron = lc.Oscillator(skm.model(), skm.param, skm.y0in)
skron.intoptions['constraints'] = None
skron.calc_y0()
skron.limit_cycle()

# figure out phase at which the pulse occurs for the 24.6h case, since that
# one is the most effective
y0 = [0.99996874, 0.10023398, 0]
param[3] = 24.6
kron = lc.Oscillator(model(null_I), param, y0)
kron.intoptions['constraints'] = None
dsol_pre = kron.int_odes(10.4)
dts_pre = kron.ts
y0_pulse = dsol_pre[-1]
pulse_phase = skron.phase_of_point(y0_pulse[:-1])  # should give ~2.66
import numpy as np
from scipy import integrate, optimize, stats
import matplotlib.pyplot as plt
from matplotlib import gridspec
import casadi as cs
from pyswarm import pso
import brewer2mpl as colorbrewer

#local imports
from LocalModels.hirota2012 import model, param, y0in
from LocalImports import LimitCycle as lco
from LocalImports import PlotOptions as plo
from LocalImports import Utilities as ut

pmodel = lco.Oscillator(model(), param, y0in)
pmodel.calc_y0()
pmodel.corestationary()
pmodel.limit_cycle()
pmodel.find_prc()

# start at negative prc region
times = np.linspace(0, pmodel.T, 10001)
roots = pmodel.pPRC_interp.splines[15].root_offset()
neg_start_root = roots[0]  # for when region becomes positive
pos_start_root = roots[1]  # for when region becomes negative
umax = 0.06

# define a periodic spline for the
start_time = pos_start_root
prc_pos = stats.threshold(-pmodel.pPRC_interp(times + start_time)[:, 15],
def mpc_problem_fig2(shift_value):
    """
    function for parallelization. returns the max time at which there is an
    error in phase greater than 0.1rad
    """
    print str(shift_value) + ' started'
    shift_val = shift_value * pmodel.T / 24.
    prediction_window = 2
    # set up times, and phases
    days = 7
    shift_day = 1.75
    times = np.linspace(0, days * 23.7, days * 1200 + 1)

    def phase_of_time(times):
        return (times * 2 * np.pi / pmodel.T) % (2 * np.pi)

    def shift_time(ts, shift_t=shift_day * pmodel.T, shift_val=shift_val):
        if np.size(ts) is 1:
            if ts >= shift_t:
                return ts + shift_val
            else:
                return ts
        elif np.size(ts) > 1:
            ts = np.copy(ts)
            ts[np.where(ts >= shift_t)] += shift_val
            return np.asarray(ts)
        else:
            print "unknown type supplied"

    # create the ref and uncontrolled traj
    unpert_p = pmodel.lc(times)[:, 0]
    pert_p = pmodel.lc(pmodel._phi_to_t(phase_of_time(shift_time(times))))[:,
                                                                           0]

    # control inputs
    control_vectors = [pmodel.pdict['vdCn']]
    prcs = pmodel.pPRC_interp

    # set up the discretization
    control_dur = 23.7 / 12  # 2hr
    time_steps = np.arange(0, days * 23.7, 2 * 23.7 / 24)
    tstep_len = time_steps[1]
    control_inputs = np.zeros(
        [len(time_steps) - prediction_window,
         len(control_vectors) + 1])
    single_step_ts = np.linspace(0, tstep_len, 100)

    # initialize the problem
    segment_ystart = y0in
    mpc_ts = []
    mpc_ps = []
    mpc_phis = []
    mpc_pts = []
    pred_phis = [0.]
    errors = []
    continuous_phases = []
    tphases = []

    for idx, time in enumerate(time_steps[:-prediction_window]):
        #calculate current phase of oscillator
        mpc_phi = None
        while mpc_phi is None:
            # this sometimes fails to converge and I do not know why
            try:
                mpc_phi = pmodel.phase_of_point(segment_ystart)
            except:
                mpc_phi = 0
                print segment_ystart

        mpc_phis.append(mpc_phi)
        mpc_pts.append(segment_ystart)
        mpc_time_start = pmodel._phi_to_t(
            mpc_phi)  # used for calculating steps
        control_inputs[idx, 0] = time

        # get the absolute times, external times, external phases, and predicted
        # phases. predicted phases are what's used for the mpc
        abs_times = time_steps[idx:idx + prediction_window + 1]
        abs_phases = phase_of_time(abs_times)
        ext_times = shift_time(abs_times)
        ext_phases = phase_of_time(ext_times)
        # the next predicted phases do not anticipate the shift
        pred_ext_times = ext_times[0] + time_steps[1:prediction_window + 1]
        pred_ext_phases = pmodel._t_to_phi(pred_ext_times) % (2 * np.pi)

        # calculate the error in phase at the current step
        p1 = mpc_phi
        p2 = ext_phases[0]
        diff = np.min([(p1 - p2) % (2 * np.pi), (p2 - p1) % (2 * np.pi)])

        errors.append(diff**2)
        print idx, diff**2

        # only calculate if the error matters
        if diff**2 > 0.01:
            # define the objective fcn
            def err(parameter_shifts, future_ext_phases, mpc_time):
                # assert that args are good
                assert len(parameter_shifts)==len(future_ext_phases), \
                            "length mismatch between u, phi_ext"
                osc_phases = np.zeros(len(parameter_shifts) + 1)
                osc_phases[0] = mpc_phi

                for i, pshift in enumerate(parameter_shifts):
                    # next oscilltor phase = curr phase + norm prog +integr pPRC
                    def dphidt(phi, t0):
                        return 2 * np.pi / (pmodel.T) + pshift * prcs(
                            pmodel._phi_to_t(phi))[:, control_vectors[0]]

                    osc_phases[i + 1] = integrate.odeint(
                        dphidt, osc_phases[i], single_step_ts)[-1]

                #calc difference
                p1 = osc_phases[1:]
                p2 = future_ext_phases
                differences = np.asarray([(p1 - p2) % (2 * np.pi),
                                          (p2 - p1) % (2 * np.pi)]).min(0)
                differences = stats.threshold(differences, threshmin=0.1)
                #quadratic cost in time
                weights = (np.arange(len(differences)) + 1)
                return np.sum(weights * differences**2) + 0.001 * np.sum(
                    parameter_shifts**2)

            # the sys functions here stop the swarm from printing its results
            xopt, fopt = pso(err, [-0.1] * prediction_window,
                             [0.0] * prediction_window,
                             args=(pred_ext_phases, mpc_time_start),
                             maxiter=300,
                             swarmsize=100,
                             minstep=1e-4,
                             minfunc=1e-4)
            opt_shifts = xopt
            opt_first_step = opt_shifts[0]

        else:
            # no action necessary
            opt_shifts = np.zeros(prediction_window)
            opt_first_step = opt_shifts[0]

        # simulate everything forward for one step
        control_inputs[idx, 1] = opt_first_step
        mpc_opt_param = np.copy(param)
        mpc_opt_param[pmodel.pdict['vdCn']] += opt_first_step
        mpc_model = lco.Oscillator(model(), mpc_opt_param, segment_ystart)
        sol = mpc_model.int_odes(tstep_len, numsteps=500)
        tsol = mpc_model.ts

        # add the step results to the overall results
        segment_ystart = sol[-1]
        mpc_ts += list(tsol + time)
        mpc_ps += list(sol[:, 0])
        phases = [pmodel.phase_of_point(pt) for pt in sol[::60]]
        tphases += list(tsol[::60] + time)
        continuous_phases += list(phases)

    abs_err = np.sqrt(errors)
    ext_phis_output = phase_of_time(shift_time(time_steps))
    simulation_results = [
        control_inputs, errors, time_steps, mpc_phis, ext_phis_output, mpc_ps,
        mpc_ts, tphases, continuous_phases
    ]
    print str(shift_value) + ' completed'
    return simulation_results
@author: abel

This file plots the ARC of the Kronauer model toward driving it to 0.
"""
from __future__ import division

import numpy as np
import casadi as cs
import matplotlib.pyplot as plt

from LocalImports import LimitCycle as lc
from LocalImports import PlotOptions as plo

from LocalModels.simplified_kronauer_model import model, param, EqCount, y0in

kron = lc.Oscillator(model(), param, y0in)
kron.intoptions['constraints'] = None

# get the PRC and ARC for this model
kron.calc_y0()
kron.limit_cycle()
kron.find_prc()
kron.findARC_whole()

# plot PRC, ARC

plt.figure()
plt.plot(kron.arc_ts, kron.pPRC_interp(kron.arc_ts)[:, 4])
plt.vlines(12.9, -0.4, 0.3, 'k')
plt.xlabel('time (h), CBTmin = 12.9')
plt.ylabel('pPRC $\hat B$')
        dts_pulses.append(dts_post)
        dsol_pulses.append(dsol_dur)
        dsol_pulses.append(dsol_post)

    final_dist = np.sqrt(np.sum(dsol_dur[-1][:2]**2))
    dsol_pulses = np.vstack(dsol_pulses)
    dts_pulses = np.hstack(dts_pulses)

    return dts_pulses, dsol_pulses, final_dist


dts_pulses, dsol_pulses, final_dist = threecycle_stimulus(24.2)

# comparison lc
y0 = [0.99996874, 0.10023398, 0]
kron = lc.Oscillator(model(null_I), param, y0)
kron.intoptions['constraints'] = None
dsol_lc = kron.int_odes(25)
dts_lc = kron.ts

plt.figure()

# limit cycle plot
plt.plot(dsol_lc[:, 0], dsol_lc[:, 1], 'k', label='LC')
plt.plot(dsol_pre[:, 0], dsol_pre[:, 1], 'r--', label='Pre-Stim')
plt.plot(dsol_pulses[:, 0], dsol_pulses[:, 1], 'b--', label='During')
plt.plot(dsol_post[:, 0], dsol_post[:, 1], 'g', label='Post')

plt.xlabel('$x$')
plt.ylabel('$x_c$')
plt.ylim([-1.4, 1.1])
示例#10
0
get, full pulse form 10-15h.
"""
from __future__ import division

import numpy as np
import casadi as cs
import matplotlib.pyplot as plt

from LocalImports import LimitCycle as lc
from LocalImports import PlotOptions as plo

from LocalModels.kronauer_model import model, param, EqCount, y0in, null_I

# pre-pulse
y0 = [0.99996874, 0.10023398, 0]
kron = lc.Oscillator(model(null_I), param, y0)
kron.intoptions['constraints'] = None
dsol_pre = kron.int_odes(3)
dts_pre = kron.ts


# during pulse
def I_pulse(t):
    """ returns just max """
    return 9500


kron = lc.Oscillator(model(I_pulse), param, dsol_pre[-1])
kron.intoptions['constraints'] = None
dsol_dur = kron.int_odes(5)
dts_dur = kron.ts