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 """The Trott and Palmer (2002) 2-site exchange R1rho U{TP02<http://wiki.nmr-relax.com/TP02>} model.
27
28 Description
29 ===========
30
31 This module is for the function, gradient and Hessian of the U{TP02<http://wiki.nmr-relax.com/TP02>} model.
32
33
34 References
35 ==========
36
37 The model is named after the reference:
38
39 - Trott, O. and Palmer, 3rd, A. G. (2002). R1rho relaxation outside of the fast-exchange limit. I{J. Magn. Reson.}, B{154}(1), 157-160. (U{DOI: 10.1006/jmre.2001.2466<http://dx.doi.org/10.1006/jmre.2001.2466>}).
40
41
42 Code origin
43 ===========
44
45 The code originates as the funTrottPalmer.m Matlab file from the sim_all.tar file attached to task #7712 (U{https://web.archive.org/web/https://gna.org/task/?7712}). This is code from Nikolai Skrynnikov and Martin Tollinger.
46
47 Links to the copyright licensing agreements from all authors are:
48
49 - Nikolai Skrynnikov, U{http://article.gmane.org/gmane.science.nmr.relax.devel/4279},
50 - Martin Tollinger, U{http://article.gmane.org/gmane.science.nmr.relax.devel/4276}.
51
52
53 Links
54 =====
55
56 More information on the TP02 model can be found in the:
57
58 - U{relax wiki<http://wiki.nmr-relax.com/TP02>},
59 - U{relax manual<http://www.nmr-relax.com/manual/The_TP02_2_site_exchange_R1_rho_model.html>},
60 - U{relaxation dispersion page of the relax website<http://www.nmr-relax.com/analyses/relaxation_dispersion.html#TP02>}.
61 """
62
63
64 from numpy import arctan2, isfinite, min, sin, sum
65 from numpy.ma import fix_invalid, masked_where
66
67
68 -def r1rho_TP02(r1rho_prime=None, omega=None, offset=None, pA=None, dw=None, kex=None, R1=0.0, spin_lock_fields=None, spin_lock_fields2=None, back_calc=None):
69 """Calculate the R1rho' values for the TP02 model.
70
71 See the module docstring for details. This is the Trott and Palmer (2002) equation according to Korzhnev (J. Biomol. NMR (2003), 26, 39-48).
72
73
74 @keyword r1rho_prime: The R1rho_prime parameter value (R1rho with no exchange).
75 @type r1rho_prime: numpy float array of rank [NE][NS][NM][NO][ND]
76 @keyword omega: The chemical shift for the spin in rad/s.
77 @type omega: numpy float array of rank [NE][NS][NM][NO][ND]
78 @keyword offset: The spin-lock offsets for the data.
79 @type offset: numpy float array of rank [NE][NS][NM][NO][ND]
80 @keyword pA: The population of state A.
81 @type pA: float
82 @keyword dw: The chemical exchange difference between states A and B in rad/s.
83 @type dw: numpy float array of rank [NE][NS][NM][NO][ND]
84 @keyword kex: The kex parameter value (the exchange rate in rad/s).
85 @type kex: float
86 @keyword R1: The R1 relaxation rate.
87 @type R1: numpy float array of rank [NE][NS][NM][NO][ND]
88 @keyword spin_lock_fields: The R1rho spin-lock field strengths (in rad.s^-1).
89 @type spin_lock_fields: numpy float array of rank [NE][NS][NM][NO][ND]
90 @keyword spin_lock_fields2: The R1rho spin-lock field strengths squared (in rad^2.s^-2). This is for speed.
91 @type spin_lock_fields2: numpy float array of rank [NE][NS][NM][NO][ND]
92 @keyword back_calc: The array for holding the back calculated R1rho values. Each element corresponds to the combination of offset and spin lock field.
93 @type back_calc: numpy float array of rank [NE][NS][NM][NO][ND]
94 """
95
96
97 t_numer_zero = False
98
99
100 pB = 1.0 - pA
101
102
103 kex2 = kex**2
104
105
106 Wa = omega
107 Wb = omega + dw
108
109
110 W = pA*Wa + pB*Wb
111
112
113 da = Wa - offset
114
115
116 db = Wb - offset
117
118
119 d = W - offset
120 da2 = da**2
121 db2 = db**2
122 d2 = d**2
123
124
125 numer = pA * pB * dw**2 * kex
126
127
128
129 waeff2 = spin_lock_fields2 + da2
130
131
132 wbeff2 = spin_lock_fields2 + db2
133
134
135 weff2 = spin_lock_fields2 + d2
136
137
138 theta = arctan2(spin_lock_fields, d)
139
140
141 sin_theta2 = sin(theta)**2
142 R1_cos_theta2 = R1 * (1.0 - sin_theta2)
143 R1rho_prime_sin_theta2 = r1rho_prime * sin_theta2
144
145
146
147 if min(numer) == 0.0:
148 t_numer_zero = True
149 mask_numer_zero = masked_where(numer == 0.0, numer)
150
151
152 denom = waeff2 * wbeff2 / weff2 + kex2
153
154
155
156 back_calc[:] = R1_cos_theta2 + R1rho_prime_sin_theta2 + sin_theta2 * numer / denom
157
158
159 if t_numer_zero:
160 replace = R1_cos_theta2 + R1rho_prime_sin_theta2
161 back_calc[mask_numer_zero.mask] = replace[mask_numer_zero.mask]
162
163
164
165 if not isfinite(sum(back_calc)):
166
167 fix_invalid(back_calc, copy=False, fill_value=1e100)
168