def piecewise_pulse_fast(step_func, t_off, t_currents, currents, T, n=20, n_pulse=2): """ Computes response from double pulses (negative then positive) T: Period (e.g. 25 Hz base frequency, 0.04 s period) """ # Use early out scheme for speed. Can turn assertions off with "python -O" assert (n_pulse == 1 or n_pulse == 2), NotImplementedError("n_pulse must be either 1 or 2") # Get gauss-legendre points and weights early since n never changes inside here x, w = _cached_roots_legendre(n) if n_pulse == 1: response = piecewise_ramp_fast(step_func, t_off, t_currents, currents, x, w) elif n_pulse == 2: response = piecewise_ramp_fast_diff(step_func, t_off, t_off + 0.5 * T, t_currents, currents, x, w) return response
def piecewise_pulse_fast( step_func, t_off, t_currents, currents, T, n=20, n_pulse=2 ): """ Computes response from double pulses (negative then positive) T: Period (e.g. 25 Hz base frequency, 0.04 s period) """ # Use early out scheme for speed. Can turn assertions off with "python -O" assert (n_pulse == 1 or n_pulse == 2), NotImplementedError("n_pulse must be either 1 or 2") # Get gauss-legendre points and weights early since n never changes inside here x, w = _cached_roots_legendre(n) if n_pulse == 1: response = piecewise_ramp_fast( step_func, t_off, t_currents, currents, x, w ) elif n_pulse == 2: response = piecewise_ramp_fast_diff( step_func, t_off, t_off+0.5*T, t_currents, currents, x, w ) return response
def waveform(times, resp, times_wanted, wave_time, wave_amp, nquad=3): """Apply a source waveform to the signal. Parameters ---------- times : ndarray Times of calculated input response; should start before and end after `times_wanted`. resp : ndarray EM-response corresponding to `times`. times_wanted : ndarray Wanted times. wave_time : ndarray Time steps of the wave. wave_amp : ndarray Amplitudes of the wave corresponding to `wave_time`, usually in the range of [0, 1]. nquad : int Number of Gauss-Legendre points for the integration. Default is 3. Returns ------- resp_wanted : ndarray EM field for `times_wanted`. """ # Interpolate on log. PP = iuSpline(np.log10(times), resp) # Wave time steps. dt = np.diff(wave_time) dI = np.diff(wave_amp) dIdt = dI / dt # Gauss-Legendre Quadrature; 3 is generally good enough. g_x, g_w = _cached_roots_legendre(nquad) # Pre-allocate output. resp_wanted = np.zeros_like(times_wanted) # Loop over wave segments. for i, cdIdt in enumerate(dIdt): # We only have to consider segments with a change of current. if cdIdt == 0.0: continue # If wanted time is before a wave element, ignore it. ind_a = wave_time[i] < times_wanted if ind_a.sum() == 0: continue # If wanted time is within a wave element, we cut the element. ind_b = wave_time[i + 1] > times_wanted[ind_a] # Start and end for this wave-segment for all times. ta = times_wanted[ind_a] - wave_time[i] tb = times_wanted[ind_a] - wave_time[i + 1] tb[ind_b] = 0.0 # Cut elements # Gauss-Legendre for this wave segment. See # https://en.wikipedia.org/wiki/Gaussian_quadrature#Change_of_interval # for the change of interval, which makes this a bit more complex. logt = np.log10(np.outer((tb - ta) / 2, g_x) + (ta + tb)[:, None] / 2) fact = (tb - ta) / 2 * cdIdt resp_wanted[ind_a] += fact * np.sum(np.array(PP(logt) * g_w), axis=1) return resp_wanted