-
Notifications
You must be signed in to change notification settings - Fork 0
/
DistProd.py
74 lines (55 loc) · 2.62 KB
/
DistProd.py
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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2021 Albert Smith-Penzel
This file is part of POPC frames archive (PFA).
PFA is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PFA is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PFA. If not, see <https://www.gnu.org/licenses/>.
Questions, contact me at:
Created on Tue May 11 12:51:59 2021
@author: albertsmith
"""
import numpy as np
def dist_prod(z,*dist):
"""
If we have two or more distributions describing individual motions, which
together make up the total motion, then it is the correlation functions
that are multiplied together, NOT the distributions themselves. Then, we
need to perform a special operation to get the distribution of correlation
times resulting from a product of motions. This may be done by calculating
the effective correlation time resulting from every possible pair of
correlation times of two distributions. The result may be re-binned into
a new distribution.
"""
dist=list(dist)
if len(dist)==2:
"Just two elements– then we simply get the product of these"
dist1,dist2=dist
dz=z[1]-z[0] #Axis spacing
S21=1-dist1.sum()*dz #Order parameters are just 1-integral_over_distribution
S22=1-dist2.sum()*dz
"All possible combinations of z for the two distributions"
z1,z2=[x.reshape(z.size**2) for x in np.meshgrid(z,z)]
zeff=z1+z2-np.log10(10**z1+10**z2) #Log-effective correlation time
"A0 is the amplitude corresponding to all the elements in zeff"
A0=np.array([x.reshape(z.size**2) for x in np.meshgrid(dist1,dist2)]).prod(0)*dz
i=np.digitize(zeff,z) #Index mapping all zeff back into the original z index
"Sum up all A for which zeff matches a given bin in z"
out=np.array([A0[i==i0].sum() for i0 in range(z.size)])
out+=S21*dist2+S22*dist1 #Include contributions from S2 *
return out
else:
"Run the program recursively over all elements"
out=dist.pop()
for d in dist:
out=dist_prod(z,out,d)
return out