Compare commits
15 Commits
refactor_l
...
feature/co
Author | SHA1 | Date | |
---|---|---|---|
|
6b7641f152 | ||
|
cd7097ad46 | ||
|
a0ca2d8657 | ||
|
9ff3badab1 | ||
|
0f47475f22 | ||
|
f6ff7606ad | ||
|
96c624efee | ||
|
492098fe01 | ||
|
accb43d7e6 | ||
|
07b14a6cd6 | ||
|
9f6af2af11 | ||
|
0ffce2f17a | ||
|
0eff84910b | ||
|
dae2d6ed95 | ||
|
ec4094cd92 |
@@ -166,8 +166,10 @@ def autosave_data(
|
|||||||
@functools.wraps(function)
|
@functools.wraps(function)
|
||||||
def autosave(*args, **kwargs):
|
def autosave(*args, **kwargs):
|
||||||
description = kwargs.pop("description", "")
|
description = kwargs.pop("description", "")
|
||||||
|
autosave_dir_overwrite = kwargs.pop("autosave_dir_overwrite", None)
|
||||||
|
autosave_dir = autosave_dir_overwrite if autosave_dir_overwrite is not None else autosave_directory
|
||||||
autoload = kwargs.pop("autoload", True) and load_autosave_data
|
autoload = kwargs.pop("autoload", True) and load_autosave_data
|
||||||
if autosave_directory is not None:
|
if autosave_dir is not None:
|
||||||
relevant_args = list(args[:nargs])
|
relevant_args = list(args[:nargs])
|
||||||
if kwargs_keys is not None:
|
if kwargs_keys is not None:
|
||||||
for key in [*posargs_keys, *kwargs_keys]:
|
for key in [*posargs_keys, *kwargs_keys]:
|
||||||
|
@@ -434,6 +434,34 @@ def center_of_masses(
|
|||||||
]
|
]
|
||||||
).T[mask]
|
).T[mask]
|
||||||
return np.array(positions)
|
return np.array(positions)
|
||||||
|
|
||||||
|
|
||||||
|
@map_coordinates
|
||||||
|
def center_of_atoms(
|
||||||
|
frame: CoordinateFrame, atom_indices=None, shear: bool = False
|
||||||
|
) -> NDArray:
|
||||||
|
if atom_indices is None:
|
||||||
|
atom_indices = list(range(len(frame)))
|
||||||
|
res_ids = frame.residue_ids[atom_indices]
|
||||||
|
if shear:
|
||||||
|
coords = frame[atom_indices]
|
||||||
|
box = frame.box
|
||||||
|
sort_ind = res_ids.argsort(kind="stable")
|
||||||
|
i = np.concatenate([[0], np.where(np.diff(res_ids[sort_ind]) > 0)[0] + 1])
|
||||||
|
coms = coords[sort_ind[i]][res_ids - min(res_ids)]
|
||||||
|
cor = pbc_diff(coords, coms, box)
|
||||||
|
coords = coms + cor
|
||||||
|
else:
|
||||||
|
coords = frame.whole[atom_indices]
|
||||||
|
mask = np.bincount(res_ids)[1:] != 0
|
||||||
|
positions = np.array(
|
||||||
|
[
|
||||||
|
np.bincount(res_ids, weights=c)[1:]
|
||||||
|
/ np.bincount(res_ids)[1:]
|
||||||
|
for c in coords.T
|
||||||
|
]
|
||||||
|
).T[mask]
|
||||||
|
return np.array(positions)
|
||||||
|
|
||||||
|
|
||||||
@map_coordinates
|
@map_coordinates
|
||||||
|
@@ -18,7 +18,7 @@ def log_indices(first: int, last: int, num: int = 100) -> np.ndarray:
|
|||||||
return np.unique(np.int_(ls) - 1 + first)
|
return np.unique(np.int_(ls) - 1 + first)
|
||||||
|
|
||||||
|
|
||||||
@autosave_data(2)
|
@autosave_data(nargs=2, kwargs_keys=('selector', 'segments', 'skip', 'window', 'average', 'points',), version=1.0)
|
||||||
def shifted_correlation(
|
def shifted_correlation(
|
||||||
function: Callable,
|
function: Callable,
|
||||||
frames: Coordinates,
|
frames: Coordinates,
|
||||||
@@ -147,7 +147,8 @@ def shifted_correlation(
|
|||||||
num_frames = int(len(frames) * window)
|
num_frames = int(len(frames) * window)
|
||||||
ls = np.logspace(0, np.log10(num_frames + 1), num=points)
|
ls = np.logspace(0, np.log10(num_frames + 1), num=points)
|
||||||
idx = np.unique(np.int_(ls) - 1)
|
idx = np.unique(np.int_(ls) - 1)
|
||||||
t = np.array([frames[i].time for i in idx]) - frames[0].time
|
dt = round(frames[1].time - frames[0].time, 6) # round to avoid bad floats
|
||||||
|
t = idx * dt
|
||||||
|
|
||||||
result = np.array(
|
result = np.array(
|
||||||
[
|
[
|
||||||
@@ -199,7 +200,7 @@ def msd(
|
|||||||
raise ValueError('Parameter axis has to be ether "all", "x", "y", or "z"!')
|
raise ValueError('Parameter axis has to be ether "all", "x", "y", or "z"!')
|
||||||
|
|
||||||
|
|
||||||
def isf(
|
def isf_raw(
|
||||||
start_frame: CoordinateFrame,
|
start_frame: CoordinateFrame,
|
||||||
end_frame: CoordinateFrame,
|
end_frame: CoordinateFrame,
|
||||||
q: float = 22.7,
|
q: float = 22.7,
|
||||||
@@ -216,29 +217,59 @@ def isf(
|
|||||||
displacements = displacements_without_drift(start_frame, end_frame, trajectory)
|
displacements = displacements_without_drift(start_frame, end_frame, trajectory)
|
||||||
if axis == "all":
|
if axis == "all":
|
||||||
distance = (displacements**2).sum(axis=1) ** 0.5
|
distance = (displacements**2).sum(axis=1) ** 0.5
|
||||||
return np.sinc(distance * q / np.pi).mean()
|
return np.sinc(distance * q / np.pi)
|
||||||
elif axis == "xy" or axis == "yx":
|
elif axis == "xy" or axis == "yx":
|
||||||
distance = (displacements[:, [0, 1]]**2).sum(axis=1) ** 0.5
|
distance = (displacements[:, [0, 1]]**2).sum(axis=1) ** 0.5
|
||||||
return np.real(jn(0, distance * q)).mean()
|
return np.real(jn(0, distance * q))
|
||||||
elif axis == "xz" or axis == "zx":
|
elif axis == "xz" or axis == "zx":
|
||||||
distance = (displacements[:, [0, 2]]**2).sum(axis=1) ** 0.5
|
distance = (displacements[:, [0, 2]]**2).sum(axis=1) ** 0.5
|
||||||
return np.real(jn(0, distance * q)).mean()
|
return np.real(jn(0, distance * q))
|
||||||
elif axis == "yz" or axis == "zy":
|
elif axis == "yz" or axis == "zy":
|
||||||
distance = (displacements[:, [1, 2]]**2).sum(axis=1) ** 0.5
|
distance = (displacements[:, [1, 2]]**2).sum(axis=1) ** 0.5
|
||||||
return np.real(jn(0, distance * q)).mean()
|
return np.real(jn(0, distance * q))
|
||||||
elif axis == "x":
|
elif axis == "x":
|
||||||
distance = np.abs(displacements[:, 0])
|
distance = np.abs(displacements[:, 0])
|
||||||
return np.mean(np.cos(np.abs(q * distance)))
|
return np.cos(np.abs(q * distance))
|
||||||
elif axis == "y":
|
elif axis == "y":
|
||||||
distance = np.abs(displacements[:, 1])
|
distance = np.abs(displacements[:, 1])
|
||||||
return np.mean(np.cos(np.abs(q * distance)))
|
return np.cos(np.abs(q * distance))
|
||||||
elif axis == "z":
|
elif axis == "z":
|
||||||
distance = np.abs(displacements[:, 2])
|
distance = np.abs(displacements[:, 2])
|
||||||
return np.mean(np.cos(np.abs(q * distance)))
|
return np.cos(np.abs(q * distance))
|
||||||
else:
|
else:
|
||||||
raise ValueError('Parameter axis has to be ether "all", "x", "y", or "z"!')
|
raise ValueError('Parameter axis has to be ether "all", "x", "y", or "z"!')
|
||||||
|
|
||||||
|
|
||||||
|
def isf(
|
||||||
|
start_frame: CoordinateFrame,
|
||||||
|
end_frame: CoordinateFrame,
|
||||||
|
q: float = 22.7,
|
||||||
|
trajectory: Coordinates = None,
|
||||||
|
axis: str = "all",
|
||||||
|
) -> float:
|
||||||
|
"""
|
||||||
|
Incoherent intermediate scattering function averaged over all particles.
|
||||||
|
See isf_raw for details.
|
||||||
|
"""
|
||||||
|
return isf_raw(start_frame, end_frame, q=q, trajectory=trajectory, axis=axis).mean()
|
||||||
|
|
||||||
|
|
||||||
|
def isf_mean_var(
|
||||||
|
start_frame: CoordinateFrame,
|
||||||
|
end_frame: CoordinateFrame,
|
||||||
|
q: float = 22.7,
|
||||||
|
trajectory: Coordinates = None,
|
||||||
|
axis: str = "all",
|
||||||
|
) -> float:
|
||||||
|
"""
|
||||||
|
Incoherent intermediate scattering function averaged over all particles and the
|
||||||
|
variance.
|
||||||
|
See isf_raw for details.
|
||||||
|
"""
|
||||||
|
values = isf_raw(start_frame, end_frame, q=q, trajectory=trajectory, axis=axis)
|
||||||
|
return values.mean(), values.var()
|
||||||
|
|
||||||
|
|
||||||
def rotational_autocorrelation(
|
def rotational_autocorrelation(
|
||||||
start_frame: CoordinateFrame, end_frame: CoordinateFrame, order: int = 2
|
start_frame: CoordinateFrame, end_frame: CoordinateFrame, order: int = 2
|
||||||
) -> float:
|
) -> float:
|
||||||
@@ -430,6 +461,7 @@ def non_gaussian_parameter(
|
|||||||
end_frame: CoordinateFrame,
|
end_frame: CoordinateFrame,
|
||||||
trajectory: Coordinates = None,
|
trajectory: Coordinates = None,
|
||||||
axis: str = "all",
|
axis: str = "all",
|
||||||
|
full_output = False,
|
||||||
) -> float:
|
) -> float:
|
||||||
r"""
|
r"""
|
||||||
Calculate the non-Gaussian parameter.
|
Calculate the non-Gaussian parameter.
|
||||||
@@ -442,27 +474,41 @@ def non_gaussian_parameter(
|
|||||||
else:
|
else:
|
||||||
vectors = displacements_without_drift(start_frame, end_frame, trajectory)
|
vectors = displacements_without_drift(start_frame, end_frame, trajectory)
|
||||||
if axis == "all":
|
if axis == "all":
|
||||||
r = (vectors**2).sum(axis=1)
|
r2 = (vectors**2).sum(axis=1)
|
||||||
dimensions = 3
|
dimensions = 3
|
||||||
elif axis == "xy" or axis == "yx":
|
elif axis == "xy" or axis == "yx":
|
||||||
r = (vectors[:, [0, 1]]**2).sum(axis=1)
|
r2 = (vectors[:, [0, 1]]**2).sum(axis=1)
|
||||||
dimensions = 2
|
dimensions = 2
|
||||||
elif axis == "xz" or axis == "zx":
|
elif axis == "xz" or axis == "zx":
|
||||||
r = (vectors[:, [0, 2]]**2).sum(axis=1)
|
r2 = (vectors[:, [0, 2]]**2).sum(axis=1)
|
||||||
dimensions = 2
|
dimensions = 2
|
||||||
elif axis == "yz" or axis == "zy":
|
elif axis == "yz" or axis == "zy":
|
||||||
r = (vectors[:, [1, 2]]**2).sum(axis=1)
|
r2 = (vectors[:, [1, 2]]**2).sum(axis=1)
|
||||||
dimensions = 2
|
dimensions = 2
|
||||||
elif axis == "x":
|
elif axis == "x":
|
||||||
r = vectors[:, 0] ** 2
|
r2 = vectors[:, 0] ** 2
|
||||||
dimensions = 1
|
dimensions = 1
|
||||||
elif axis == "y":
|
elif axis == "y":
|
||||||
r = vectors[:, 1] ** 2
|
r2 = vectors[:, 1] ** 2
|
||||||
dimensions = 1
|
dimensions = 1
|
||||||
elif axis == "z":
|
elif axis == "z":
|
||||||
r = vectors[:, 2] ** 2
|
r2 = vectors[:, 2] ** 2
|
||||||
dimensions = 1
|
dimensions = 1
|
||||||
else:
|
else:
|
||||||
raise ValueError('Parameter axis has to be ether "all", "x", "y", or "z"!')
|
raise ValueError('Parameter axis has to be ether "all", "x", "y", or "z"!')
|
||||||
|
|
||||||
|
m2 = np.mean(r2)
|
||||||
|
m4 = np.mean(r2**2)
|
||||||
|
if m2 == 0.0:
|
||||||
|
if full_output:
|
||||||
|
return 0.0, 0.0, 0.0
|
||||||
|
else:
|
||||||
|
return 0.0
|
||||||
|
|
||||||
|
alpha_2 = (m4 / ((1 + 2 / dimensions) * m2**2)) - 1
|
||||||
|
if full_output:
|
||||||
|
return alpha_2, m2, m4
|
||||||
|
else:
|
||||||
|
return alpha_2
|
||||||
|
|
||||||
|
|
||||||
return (np.mean(r**2) / ((1 + 2 / dimensions) * (np.mean(r) ** 2))) - 1
|
|
||||||
|
@@ -149,32 +149,21 @@ def nojump(frame: CoordinateFrame, usecache: bool = True) -> CoordinateFrame:
|
|||||||
i0 = 0
|
i0 = 0
|
||||||
delta = 0
|
delta = 0
|
||||||
|
|
||||||
delta = (
|
delta = (delta
|
||||||
delta
|
+ np.vstack(
|
||||||
+ np.array(
|
[m[i0 : abstep + 1].sum(axis=0) for m in reader.nojump_matrices]
|
||||||
np.vstack(
|
).T)
|
||||||
[m[i0 : abstep + 1].sum(axis=0) for m in reader.nojump_matrices]
|
|
||||||
).T
|
|
||||||
)
|
|
||||||
@ frame.box
|
|
||||||
)
|
|
||||||
|
|
||||||
reader._nojump_cache[abstep] = delta
|
reader._nojump_cache[abstep] = delta
|
||||||
while len(reader._nojump_cache) > NOJUMP_CACHESIZE:
|
while len(reader._nojump_cache) > NOJUMP_CACHESIZE:
|
||||||
reader._nojump_cache.popitem(last=False)
|
reader._nojump_cache.popitem(last=False)
|
||||||
delta = delta[selection, :]
|
|
||||||
else:
|
else:
|
||||||
delta = (
|
delta = np.vstack(
|
||||||
np.array(
|
[m[: frame.step + 1, selection].sum(axis=0) for m in reader.nojump_matrices]
|
||||||
np.vstack(
|
|
||||||
[
|
|
||||||
m[: frame.step + 1, selection].sum(axis=0)
|
|
||||||
for m in reader.nojump_matrices
|
|
||||||
]
|
|
||||||
).T
|
).T
|
||||||
)
|
|
||||||
@ frame.box
|
delta = delta[selection, :]
|
||||||
)
|
delta = np.array(delta @ frame.box)
|
||||||
return frame - delta
|
return frame - delta
|
||||||
|
|
||||||
|
|
||||||
|
@@ -357,6 +357,37 @@ def quick1etau(t: ArrayLike, C: ArrayLike, n: int = 7) -> float:
|
|||||||
return tau_est
|
return tau_est
|
||||||
|
|
||||||
|
|
||||||
|
def quicknongaussfit(t, C, width=2):
|
||||||
|
"""
|
||||||
|
Estimates the time and height of the peak in the non-Gaussian function.
|
||||||
|
C is C(t) the correlation function
|
||||||
|
"""
|
||||||
|
def ffunc(t,y0,A_main,log_tau_main,sig_main):
|
||||||
|
main_peak = A_main*np.exp(-(t - log_tau_main)**2 / (2 * sig_main**2))
|
||||||
|
return y0 + main_peak
|
||||||
|
|
||||||
|
# first rough estimate, the closest time. This is returned if the interpolation fails!
|
||||||
|
tau_est = t[np.argmax(C)]
|
||||||
|
nG_max = np.amax(C)
|
||||||
|
try:
|
||||||
|
with np.errstate(invalid='ignore'):
|
||||||
|
corr = C[t > 0]
|
||||||
|
time = np.log10(t[t > 0])
|
||||||
|
tau = time[np.argmax(corr)]
|
||||||
|
mask = (time>tau-width/2) & (time<tau+width/2)
|
||||||
|
time = time[mask] ; corr = corr[mask]
|
||||||
|
nG_min = C[t > 0].min()
|
||||||
|
guess = [nG_min, nG_max-nG_min, tau, 0.6]
|
||||||
|
popt = curve_fit(ffunc, time, corr, p0=guess, maxfev=10000)[0]
|
||||||
|
tau_est = 10**popt[-2]
|
||||||
|
nG_max = popt[0] + popt[1]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if np.isnan(tau_est):
|
||||||
|
tau_est = np.inf
|
||||||
|
return tau_est, nG_max
|
||||||
|
|
||||||
|
|
||||||
def susceptibility(
|
def susceptibility(
|
||||||
time: NDArray, correlation: NDArray, **kwargs
|
time: NDArray, correlation: NDArray, **kwargs
|
||||||
) -> tuple[NDArray, NDArray]:
|
) -> tuple[NDArray, NDArray]:
|
||||||
|
Reference in New Issue
Block a user