1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
|
""" This sub-module contains functions to generate the Kramers-Kronig
transform of DC I-V data.
Used to find the real component of the response function from the DC I-V
curve.
"""
import numpy as np
from scipy.signal import hilbert
def kk_trans(v, i, n=50):
"""Calculate the Kramers-Kronig transform from DC I-V data.
Note:
Voltage spacing must be constant!
Args:
v (ndarray): normalized voltage (DC I-V curve)
i (ndarray): normalized current (DC I-V curve)
n (int): padding for Hilbert transform
Returns:
ndarray: kk transform
"""
npts = v.shape[0]
# Ensure v has (roughly) even spacing
assert np.abs((v[1] - v[0]) - (v[1:] - v[:-1])).max() < 1e-5
# Subtract v to make kk defined at v=infinity
ikk = -(hilbert(i - v, N=npts * n)).imag
ikk = ikk[:npts]
return ikk
def kk_trans_trapz(v, i):
"""Calculate the Kramers-Kronig transform using a simple trapezoidal
summation.
This function isn't used anymore, but it is nice to use it to
compare against qmix.mathfn.kktrans.kk_trans.
Note:
Voltage spacing must be constant!
This function is (much!) slower than the Hilbert transform version (i.e.,
qmix.mathfn.kktrans.kk_trans). It also has problems with how it is
calculated around the singularity.
Args:
v (ndarray): normalized voltage (DC I-V curve)
i (ndarray): normalized current (DC I-V curve)
Returns:
ndarray: kk transform
"""
# Ensure v has even spacing
assert ((v[1:] - v[:-1]) - (v[1] - v[0])).max() < 1e-5
# very crude integration
ikk = []
for a in range(len(v)):
v_prime, i_prime = np.delete(v, a), np.delete(i, a)
ikk.append(np.trapz((i_prime - v_prime) / (v_prime - v[a]), x=v_prime))
ikk = np.array(ikk) / np.pi
return ikk
|