12 fret_efficiency: float,
13 n_samples: int = 10000,
23 Second rank order parameter S2 of the donor dye. This can correspond
24 to the fraction of trapped donor dye.
26 Second rank order parameter S2 of the acceptor dye. This can correspond
27 to the fraction of trapped acceptor dye.
28 fret_efficiency : float
31 The number of bins in the kappa2 distribution that is
34 Upper kappa2 bound in the generated histogram
36 Lower kappa2 bound in the generate histogram
38 The number random vector pairs that are drawn (default: 10000)
45 k2_step = (k2_max - k2_min) / (n_bins - 1)
46 k2_scale = np.arange(k2_min, k2_max + 1e-14, k2_step, dtype=np.float64)
49 donor_vec = np.random.randn(n_samples, 3)
50 acceptor_vec = np.random.randn(n_samples, 3)
53 x = 1 / fret_efficiency - 1
55 k2s = np.zeros(n_samples, dtype=np.float64)
56 for i
in range(n_samples):
58 acceptor = acceptor_vec[i]
60 delta = np.arccos(np.dot(donor, acceptor) / (np.linalg.norm(donor) * np.linalg.norm(acceptor)))
61 beta1 = np.arccos(donor[0] / np.linalg.norm(donor))
62 beta2 = np.arccos(acceptor[0] / np.linalg.norm(acceptor))
64 k2_trapped_free = kappasq(
71 k2_free_trapped = kappasq(
78 k2_trapped_trapped = kappasq(
86 Ek2 = (1 - sD2) * (1 - sA2) / (1 + x) + sD2 * sA2 / (1 + 2 / 3. / k2_trapped_trapped * x) + sD2 * (1 - sA2) / (
87 1 + 2 / 3. / k2_trapped_free * x) + (1 - sD2) * sA2 / (1 + 2 / 3. / k2_free_trapped * x)
88 k2 = 2 / 3. * x / (1 / Ek2 - 1)
92 k2hist, bins = np.histogram(k2s, k2_scale)
93 return k2_scale, k2hist, k2s
96 def kappasq_all_delta_new(
104 ) -> typing.Tuple[np.ndarray, np.ndarray, np.ndarray]:
107 for beta1
in np.arange(0, np.pi/2, step=step / 180. * np.pi):
108 weight_beta1 = np.sin(beta1)
109 for beta2
in np.arange(
110 start=abs(delta - beta1),
111 stop=min(delta + beta1, np.pi / 2.),
112 step=step / 180. * np.pi
114 weight_beta2 = np.sin(beta1)
116 weight_beta1 * weight_beta2
130 k2_step = (k2_max - k2_min) / (n_bins - 1)
131 k2scale = np.arange(k2_min, k2_max + 1e-14, k2_step, dtype=np.float64)
133 k2hist, x = np.histogram(ks, bins=k2scale, weights=weights)
134 return k2scale, k2hist, ks
138 @nb.jit(nopython=
True)
139 def kappasq_all_delta(
147 ) -> typing.Tuple[np.ndarray, np.ndarray, np.ndarray]:
148 """Computes a orientation factor distribution for a wobbling in a cone model
149 using parameters that can be estimated by experimental anisotropies.
151 The function used second rank order parameter of the donor and acceptor
152 and the angle delta between the symmetry axes of the dyes as input. These
153 parameters can be estimated by the residual anisotropy the the dyes. The
154 second rank order parameter of the donor and acceptor are estimated by the
155 dye's residual anisotropies. The angle between the symmetry axes is estimated
156 by the residual anisotropy of the FRET sensitized emission (see:
157 `chisurf.fluorescence.anisotropy.kappa2.s2delta`).
159 This function computes a orientation factor distribution, :math:`p(/kappa^2)`,
160 for a wobbling in a cone model (WIC) for second rank structure factors of
161 the donor and acceptor, and an angle :math:`delta`. The angle
162 :math:`delta` is the angle between the symmetry axes of the dyes and can be
163 estimated using experimental residual anisotropies [1]_.
168 The angle delta (in rad) for which the WIC orientation factor
169 distribution is calculated.
171 Second rank order parameter S2 of the donor dye. This can correspond
172 to the fraction of trapped donor dye.
174 Second rank order parameter S2 of the acceptor dye. This can correspond
175 to the fraction of trapped acceptor dye.
177 The step size in degrees that is used to sample the
180 The number of bins in the kappa2 distribution that is
183 Upper kappa2 bound in the generated histogram
185 Lower kappa2 bound in the generate histogram
189 k2scale : numpy-array
190 A linear scale in the range of [0, 4] with *n_bins* elements
192 The histogram of kappa2 values
194 A numpy-array containing all computed kappa2 values. The histogram
195 corresponds to a histogram over all returned kappa2 values.
199 >>> from scikit_fluorescence.modeling.kappa2 import kappasq_all_delta
200 >>> k2s, k2h, k2v = kappasq_all_delta(
207 >>> np.allclose(k2h, np.array([ 0. , 0. , 0. , 0. ,
208 ... 3205.72877776, 1001.19048825, 611.44917432, 252.97166906,
209 ... 0. , 0. , 0. , 0. ,
210 ... 0. , 0. , 0. , 0. ,
211 ... 0. , 0. , 0. , 0. ,
212 ... 0. , 0. , 0. , 0. ,
213 ... 0. , 0. , 0. , 0. ,
214 ... 0. , 0. ]), rtol=0.3, atol=2.0)
219 The angle :math:`/beta_1` is varied in the range (0,pi/2)
220 The angle :math:`/phi` is varied in the range (0, 2 pi)
224 .. [1] Simon Sindbert, Stanislav Kalinin, Hien Nguyen, Andrea Kienzler,
225 Lilia Clima, Willi Bannwarth, Bettina Appel, Sabine Mueller, Claus A. M.
226 Seidel, "Accurate Distance Determination of Nucleic Acids via Foerster
227 Resonance Energy Transfer: Implications of Dye Linker Length and Rigidity"
228 vol. 133, pp. 2463-2480, J. Am. Chem. Soc., 2011
232 beta1 = np.arange(0.001, np.pi / 2.0, step * np.pi / 180.0, dtype=np.float64)
233 phi = np.arange(0.001, 2.0 * np.pi, step * np.pi / 180.0, dtype=np.float64)
236 rda_vec = np.array([1, 0, 0], dtype=np.float64)
239 k2 = np.zeros((n, m), dtype=np.float64)
240 k2hist = np.zeros(n_bins - 1, dtype=np.float64)
243 k2_step = (k2_max - k2_min) / (n_bins - 1)
244 k2scale = np.arange(k2_min, k2_max + 1e-14, k2_step, dtype=np.float64)
246 d1 = np.array([np.cos(beta1[i]), 0, np.sin(beta1[i])])
247 n1 = np.array([-np.sin(beta1[i]), 0, np.cos(beta1[i])])
248 n2 = np.array([0, 1, 0])
250 d2 = (n1*np.cos(phi[j])+n2*np.sin(phi[j]))*np.sin(delta)+d1*np.cos(delta)
251 beta2 = np.arccos(np.abs(d2.dot(rda_vec)))
259 y, x = np.histogram(k2[i, :], bins=k2scale)
260 k2hist += y*np.sin(beta1[i])
261 return k2scale, k2hist, k2
264 @nb.jit(nopython=
True)
271 n_samples: int = 10000
272 ) -> typing.Tuple[np.array, np.array, np.array]:
273 """Computes a orientation factor distribution for a wobbling in a cone model
274 using specific second rank structure factors of the donor and acceptor.
276 This function computes a orientation factor distribution, :math:`p(/kappa^2)`,
277 for a wobbling in a cone model (WIC) for second rank structure factors of
278 the donor and acceptor estimated using experimental residual anisotropies [1]_.
283 Second rank order parameter S2 of the donor dye
285 Second rank order parameter S2 of the acceptor dye
287 The number of bins in the kappa2 histogram that is
290 Upper kappa2 bound in the generated histogram
292 Lower kappa2 bound in the generate histogram
294 The number random vector pairs that are drawn (default: 10000)
298 k2scale : numpy-array
299 A linear scale in the range of [0, 4] with *n_bins* elements
301 The histogram of kappa2 values
303 A numpy-array containing all computed kappa2 values. The histogram
304 corresponds to a histogram over all returned kappa2 values.
308 >>> from scikit_fluorescence.modeling.kappa2 import kappasq_all_delta
309 >>> k2_scale, k2_hist, k2 = kappasq_all(
316 array([0. , 0.13333333, 0.26666667, 0.4 , 0.53333333,
317 0.66666667, 0.8 , 0.93333333, 1.06666667, 1.2 ,
318 1.33333333, 1.46666667, 1.6 , 1.73333333, 1.86666667,
319 2. , 2.13333333, 2.26666667, 2.4 , 2.53333333,
320 2.66666667, 2.8 , 2.93333333, 3.06666667, 3.2 ,
321 3.33333333, 3.46666667, 3.6 , 3.73333333, 3.86666667,
323 >>> reference = np.array([0.0000e+00, 0.0000e+00, 0.0000e+00, 3.1920e+04, 4.3248e+04,
324 ... 1.4842e+04, 5.8930e+03, 2.5190e+03, 1.0840e+03, 3.9700e+02,
325 ... 9.4000e+01, 3.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00,
326 ... 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00,
327 ... 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00,
328 ... 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00])
329 >>> np.allclose(reference, k2_hist, rtol=0.3, atol=2.0)
334 .. [1] Simon Sindbert, Stanislav Kalinin, Hien Nguyen, Andrea Kienzler,
335 Lilia Clima, Willi Bannwarth, Bettina Appel, Sabine Mueller, Claus A. M.
336 Seidel, "Accurate Distance Determination of Nucleic Acids via Foerster
337 Resonance Energy Transfer: Implications of Dye Linker Length and Rigidity"
338 vol. 133, pp. 2463-2480, J. Am. Chem. Soc., 2011
341 k2 = np.zeros(n_samples, dtype=np.float64)
342 step = (k2_max - k2_min) / (n_bins - 1)
343 k2scale = np.arange(k2_min, k2_max + 1e-14, step, dtype=np.float64)
344 k2hist = np.zeros(k2scale.shape[0] - 1, dtype=np.float64)
345 for i
in range(n_samples):
346 d1 = np.random.random(3)
347 d2 = np.random.random(3)
348 n1 = np.linalg.norm(d1)
349 n2 = np.linalg.norm(d2)
351 delta = np.arccos(np.dot(d1, d2) / (n1 * n2))
352 beta1 = np.arccos(d1[0] / n1)
353 beta2 = np.arccos(d2[0] / n2)
361 y, x = np.histogram(k2, bins=k2scale)
363 return k2scale, k2hist, k2
366 @nb.jit(nopython=
True)
372 ) -> typing.Tuple[float, float]:
373 r"""Calculates the distance between the center of two dipoles and the
374 orientation-factor kappa of the dipoles
376 Calculates for the vectors d1 and d2 pointing to the donors and the vectors
377 a1 and a2 pointing to the ends of the acceptor dipole the orientation
383 Vector pointing to the first point of the dipole D
385 Vector pointing to the second point of the dipole D
387 Vector pointing to the first point of the dipole A
389 Vector pointing to the second point of the dipole A
394 distance between the center of the dipoles and the orientation factor
395 for the two dipoles kappa
399 The four vectors defining the dipole of the donor :math:`\vec{r}_{D1}` and
400 :math:`\vec{r}_{D2}` specified by the parameters `d1` and `d2` and
401 :math:`\vec{r}_{A1}` and :math:`\vec{r}_{A2}` specified by the parameters
402 `a1` and `a1` are used to compute orientation factor :math:`kappa^2`
403 and the distance between the center of the two dipoles :math:`R_{DA}`.
405 The distance :math:`R_{DA}` between the dipole centers and :math:`kappa`
406 is calculated as follows:
410 R_{D,21}=|\vec{r}_{D2} - \vec{r}_{D1}| \
411 R_{A,21}=|\vec{r}_{A2} - \vec{r}_{A1}| \
412 \hat{\mu}_{D}=1/R_{D,21} \cdot (\vec{r}_{D2}-\vec{r}_{D1}) \
413 \hat{\mu}_{A}=1/R_{A,21} \cdot (\vec{r}_{A2}-\vec{r}_{A1}) \
414 \vec{m}_{D}=\vec{r}_{D1}+1/2 \cdot \hat{\mu}_{D} \
415 \vec{m}_{A}=\vec{r}_{A1}+1/2 \cdot \hat{\mu}_{A} \
416 \vec{r}_{DA}=\vec{m}_{D}-\vec{m}_{A} \
417 R_{DA}=|\vec{m}_{D}-\vec{m}_{A}| \
418 \hat{\mu}_{DA}=\vec{r}_{DA} / R_{DA} \
419 \kappa=\langle\mu_A,\mu_D\rangle-3\cdot\langle\mu_D,\mu_{DA}\rangle \cdot \langle\mu_A,\mu_{DA}\rangle
423 >>> import scikit_fluorescence.modeling.kappa2
424 >>> donor_dipole = np.array(
428 ... ], dtype=np.float64
430 >>> acceptor_dipole = np.array(
434 ... ], dtype=np.float64
436 >>> scikit_fluorescence.modeling.kappa2.kappa(
440 (0.8660254037844386, 1.0000000000000002)
454 (d11 - d21) * (d11 - d21) +
455 (d12 - d22) * (d12 - d22) +
456 (d13 - d23) * (d13 - d23)
460 muD1 = (d21 - d11) / dD21
461 muD2 = (d22 - d12) / dD21
462 muD3 = (d23 - d13) / dD21
465 dM1 = d11 + dD21 * muD1 / 2.0
466 dM2 = d12 + dD21 * muD2 / 2.0
467 dM3 = d13 + dD21 * muD3 / 2.0
481 (a11 - a21) * (a11 - a21) +
482 (a12 - a22) * (a12 - a22) +
483 (a13 - a23) * (a13 - a23)
487 muA1 = (a21 - a11) / dA21
488 muA2 = (a22 - a12) / dA21
489 muA3 = (a23 - a13) / dA21
492 aM1 = a11 + dA21 * muA1 / 2.0
493 aM2 = a12 + dA21 * muA2 / 2.0
494 aM3 = a13 + dA21 * muA3 / 2.0
502 dRDA = np.sqrt(RDA1 * RDA1 + RDA2 * RDA2 + RDA3 * RDA3)
510 kappa = muA1 * muD1 + \
513 3.0 * (muD1 * nRDA1 + muD2 * nRDA2 + muD3 * nRDA3) * \
514 (muA1 * nRDA1 + muA2 * nRDA2 + muA3 * nRDA3)
519 donor_dipole: np.ndarray,
520 acceptor_dipole: np.ndarray
521 ) -> typing.Tuple[float, float]:
522 """Calculates the orientation-factor kappa
524 :param donor_dipole: 2x3 vector of the donor-dipole
525 :param acceptor_dipole: 2x3 vector of the acceptor-dipole
526 :return: distance, kappa
531 >>> import numpy as np
532 >>> donor_dipole = np.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0]], dtype=np.float64)
533 >>> acceptor_dipole = np.array([[0.0, 0.5, 0.0], [0.0, 0.5, 1.0]], dtype=np.float64)
534 >>> kappa(donor_dipole, acceptor_dipole)
535 (0.8660254037844386, 1.0000000000000002)
537 return kappa_distance(
538 donor_dipole[0], donor_dipole[1],
539 acceptor_dipole[0], acceptor_dipole[1]
548 ) -> typing.Tuple[float, float]:
549 """Calculate s2delta from the residual anisotropies of the donor and acceptor
554 Fundamental anisotropy, the anisotropy of the dyes at time zero (
557 The second rank oder parameter of the donor dye. The second rank oder
558 parameter can be computed using the dye's residual anisotropy (see
561 The second rank oder parameter of the direct excited acceptor dye.
563 The residual anisotropy on the acceptor excited by the donor dye.
568 A second rank order parameter of the angle [1]_ eq. 10
570 The angle between the two symmetry axes of the dipols in units of rad.
574 >>> from scikit_fluorescence.modeling.kappa2 import s2delta
581 ... s2_donor=s2donor,
582 ... s2_acceptor=s2acceptor,
583 ... r_inf_AD=r_inf_AD
585 (0.4385964912280701, 0.6583029208008411)
589 The parameters `s2_donor` and `s2_acceptor`, which correspond to :math:`S^{(2)}_D`
590 and :math:`S^{(2)}_A` are calculated using the dye's residual anisotropy [1]_
594 S^{(2)}_D = - /sqrt{/frac{r_{D,inf}}{r_{0,D}}} \
595 S^{(2)}_D = /sqrt{/frac{r_{A,inf}}{r_{0,A}}} \
600 .. [1] Simon Sindbert, Stanislav Kalinin, Hien Nguyen, Andrea Kienzler,
601 Lilia Clima, Willi Bannwarth, Bettina Appel, Sabine Mueller, Claus A. M.
602 Seidel, "Accurate Distance Determination of Nucleic Acids via Foerster
603 Resonance Energy Transfer: Implications of Dye Linker Length and Rigidity"
604 vol. 133, pp. 2463-2480, J. Am. Chem. Soc., 2011
607 s2_delta = r_inf_AD/(r_0 * s2_donor * s2_acceptor)
608 delta = np.arccos(np.sqrt((2.0 * s2_delta + 1.0) / 3.0))
609 return s2_delta, delta
612 def calculate_kappa_distance(
618 ) -> typing.Tuple[np.ndarray, np.ndarray]:
619 """Calculates the orientation factor kappa2 and the distance of a
620 trajectory given the atom-indices of the donor and the acceptor.
622 :param xyz: numpy-array (frame, atom, xyz)
623 :param aid1: int, atom-index of d-dipole 1
624 :param aid2: int, atom-index of d-dipole 2
625 :param aia1: int, atom-index of a-dipole 1
626 :param aia2: int, atom-index of a-dipole 2
628 :return: distances, kappa2
630 n_frames = xyz.shape[0]
631 ks = np.empty(n_frames, dtype=np.float32)
632 ds = np.empty(n_frames, dtype=np.float32)
634 for i_frame
in range(n_frames):
636 d, k = kappa_distance(
637 xyz[i_frame, aid1], xyz[i_frame, aid2],
638 xyz[i_frame, aia1], xyz[i_frame, aia2]
643 print(
"Frame ", i_frame,
"skipped, calculation error")
648 @nb.jit(nopython=
True)
656 """Calculates kappa2 given a set of oder parameters and angles
661 The angle between the symmetry axis of rotation of the dyes in units
664 The second rank oder parameter of the donor
666 The second rank oder parameter of the acceptor
668 The angle between the symmetry axes of the rotation of the dye and
669 the distance vector RDA between the two dipoles
671 The angle between the symmetry axes of the rotation of the dye and
672 the distance vector RDA between the two dipoles
677 The orientation factor that corresponds to the provided angles.
682 This function corresponds to eq. 9 in [1]_.
686 .. [1] Simon Sindbert, Stanislav Kalinin, Hien Nguyen, Andrea Kienzler,
687 Lilia Clima, Willi Bannwarth, Bettina Appel, Sabine Mueller, Claus A. M.
688 Seidel, "Accurate Distance Determination of Nucleic Acids via Foerster
689 Resonance Energy Transfer: Implications of Dye Linker Length and Rigidity"
690 vol. 133, pp. 2463-2480, J. Am. Chem. Soc., 2011
693 s2delta = (3.0 * np.cos(delta) * np.cos(delta) - 1.0) / 2.0
694 s2beta1 = (3.0 * np.cos(beta1) * np.cos(beta1) - 1.0) / 2.0
695 s2beta2 = (3.0 * np.cos(beta2) * np.cos(beta2) - 1.0) / 2.0
702 6 * s2beta1 * s2beta2 +
706 9 * np.cos(beta1) * np.cos(beta2) * np.cos(delta)
712 def p_isotropic_orientation_factor(
714 normalize: bool =
True
716 """Calculates an the probability of a given kappa2 according to
717 an isotropic orientation factor distribution
722 An array containing kappa squared values.
724 If this parameter is set to True (default) the returned distribution is
730 The probability distribution of kappa2 for isotropic oriented dipoles
735 >>> import scikit_fluorescence.modeling.kappa2
736 >>> k2 = np.linspace(0.1, 4, 32)
737 >>> p_k2 = scikit_fluorescence.modeling.kappa2.p_isotropic_orientation_factor(k2=k2)
739 array([0.17922824, 0.11927194, 0.09558154, 0.08202693, 0.07297372,
740 0.06637936, 0.06130055, 0.05723353, 0.04075886, 0.03302977,
741 0.0276794 , 0.02359627, 0.02032998, 0.01763876, 0.01537433,
742 0.01343829, 0.01176177, 0.01029467, 0.00899941, 0.00784718,
743 0.00681541, 0.00588615, 0.00504489, 0.0042798 , 0.0035811 ,
744 0.00294063, 0.00235153, 0.001808 , 0.00130506, 0.00083845,
749 http://www.fretresearch.org/kappasquaredchapter.pdf
754 r = np.zeros_like(k2)
755 for i, k
in enumerate(ks):
757 r[i] = 0.5 / (s3 * k) * np.log(2 + s3)
759 r[i] = 0.5 / (s3 * k) * np.log((2 + s3) / (k + np.sqrt(k**2 - 1.0)))
761 r /= max(1.0, r.sum())