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  r"""The Luz and Meiboom (1963) 3-site fast exchange U{LM63 3-site<http://wiki.nmr-relax.com/LM63_3-site>} model. 
 26   
 27  Description 
 28  =========== 
 29   
 30  This module is for the function, gradient and Hessian of the U{LM63 3-site<http://wiki.nmr-relax.com/LM63_3-site>} model. 
 31   
 32   
 33  References 
 34  ========== 
 35   
 36  The model is named after the reference: 
 37   
 38      - Luz, S. and Meiboom S., (1963)  Nuclear Magnetic Resonance study of protolysis of trimethylammonium ion in aqueous solution - order of reaction with respect to solvent, I{J. Chem. Phys}. B{39}, 366-370 (U{DOI: 10.1063/1.1734254<http://dx.doi.org/10.1063/1.1734254>}). 
 39   
 40   
 41  Equations 
 42  ========= 
 43   
 44  The equation used is:: 
 45   
 46                     _3_ 
 47                     \    phi_ex_i   /     4 * nu_cpmg         /     ki      \ \  
 48      R2eff = R20 +   >   -------- * | 1 - -----------  * tanh | ----------- | | . 
 49                     /__     ki      \         ki              \ 4 * nu_cpmg / / 
 50                     i=2 
 51   
 52  For deconvoluting the parameters, see the relax user manual or the reference: 
 53   
 54      - O'Connell, N. E., Grey, M. J., Tang, Y., Kosuri, P., Miloushev, V. Z., Raleigh, D. P., and Palmer, 3rd, A. G. (2009). Partially folded equilibrium intermediate of the villin headpiece HP67 defined by 13C relaxation dispersion. I{J. Biomol. NMR}, B{45}(1-2), 85-98. (U{DOI: 10.1007/s10858-009-9340-0<http://dx.doi.org/10.1007/s10858-009-9340-0>}). 
 55   
 56   
 57  Links 
 58  ===== 
 59   
 60  More information on the LM63 3-site model can be found in the: 
 61   
 62      - U{relax wiki<http://wiki.nmr-relax.com/LM63_3-site>}, 
 63      - U{relax manual<http://www.nmr-relax.com/manual/The_LM63_3_site_fast_exchange_CPMG_model.html>}, 
 64      - U{relaxation dispersion page of the relax website<http://www.nmr-relax.com/analyses/relaxation_dispersion.html#LM63_3-site>}. 
 65  """ 
 66   
 67   
 68  from numpy import fabs, min, tanh, isfinite, sum 
 69  from numpy.ma import fix_invalid, masked_where 
 70   
 71   
 72 -def r2eff_LM63_3site(r20=None, phi_ex_B=None, phi_ex_C=None, kB=None, kC=None, cpmg_frqs=None, back_calc=None): 
  73      """Calculate the R2eff values for the LM63 3-site model. 
 74   
 75      See the module docstring for details. 
 76   
 77   
 78      @keyword r20:           The R20 parameter value (R2 with no exchange). 
 79      @type r20:              numpy float array of rank [NS][NM][NO][ND] 
 80      @keyword phi_ex_B:      The fast exchange factor between sites A and B (ppm^2) 
 81      @type phi_ex_B:         numpy float array of rank [NS][NM][NO][ND] 
 82      @keyword phi_ex_C:      The fast exchange factor between sites A and C (ppm^2) 
 83      @type phi_ex_C:         numpy float array of rank [NE][NS][NM][NO][ND] 
 84      @keyword kB:            Approximate chemical exchange rate constant between sites A and B (the exchange rate in rad/s). 
 85      @type kB:               float 
 86      @keyword kC:            Approximate chemical exchange rate constant between sites A and C (the exchange rate in rad/s). 
 87      @type kC:               float 
 88      @keyword cpmg_frqs:     The CPMG nu1 frequencies. 
 89      @type cpmg_frqs:        numpy float array of rank [NE][NS][NM][NO][ND] 
 90      @keyword back_calc:     The array for holding the back calculated R2eff values.  Each element corresponds to one of the CPMG nu1 frequencies. 
 91      @type back_calc:        numpy float array of rank [NE][NS][NM][NO][ND] 
 92      """ 
 93   
 94       
 95       
 96      rex_B = phi_ex_B / kB 
 97   
 98       
 99      rex_C = phi_ex_C / kC 
100   
101       
102      quart_kB = kB / 4.0 
103   
104       
105      quart_kC = kC / 4.0 
106   
107       
108      t_rex_zero = False 
109      t_quart_kB_zero = False 
110      t_quart_kC_zero = False 
111      t_quart_kB_kC_zero = False 
112   
113       
114      if quart_kB == 0.0: 
115          t_quart_kB_zero = True 
116   
117      if quart_kC == 0.0: 
118          t_quart_kC_zero = True 
119   
120       
121      if t_quart_kB_zero and t_quart_kC_zero: 
122          t_quart_kB_kC_zero = True 
123   
124       
125      if min(fabs(rex_B)) == 0.0 and min(fabs(rex_C)) == 0.0: 
126          t_rex_zero = True 
127          mask_rex_B_zero = masked_where(rex_B == 0.0, rex_B) 
128          mask_rex_C_zero = masked_where(rex_C == 0.0, rex_C) 
129   
130       
131       
132      if t_quart_kB_kC_zero: 
133          back_calc[:] = r20 
134      elif t_quart_kB_zero: 
135          back_calc[:] = r20 + rex_C * (1.0 - cpmg_frqs * tanh(quart_kC / cpmg_frqs) / quart_kC) 
136      elif t_quart_kC_zero: 
137          back_calc[:] = r20 + rex_B * (1.0 - cpmg_frqs * tanh(quart_kB / cpmg_frqs) / quart_kB) 
138      else: 
139           
140          back_calc[:] = r20 + rex_B * (1.0 - cpmg_frqs * tanh(quart_kB / cpmg_frqs) / quart_kB) + rex_C * (1.0 - cpmg_frqs * tanh(quart_kC / cpmg_frqs) / quart_kC) 
141   
142       
143      if t_rex_zero: 
144          back_calc[mask_rex_B_zero.mask] = r20[mask_rex_B_zero.mask] 
145          back_calc[mask_rex_C_zero.mask] = r20[mask_rex_C_zero.mask] 
146   
147       
148       
149      if not isfinite(sum(back_calc)): 
150           
151          fix_invalid(back_calc, copy=False, fill_value=1e100) 
 152