Let me reinforce that again if you didn't quite get it yet ;) In the 'disp_speed' branch, there are a lot of cases where an array of 1e100 is returned when an array of R20 should be returned. Unit tests would instantly show these. If you put a catch at the start for all parameter values that result in no chemical exchange, then you will avoid most problems seen with the --numpy-raise flag, and the optimisation space you see with the dx.map user function might improve a lot. And these single value checks will be faster than the numpy array checks further into the functions, most of which will become redundant.
Regards, Edward On 21 May 2014 19:10, Edward d'Auvergne <[email protected]> wrote: > Hi Troels, > > You should really consider adding this check to absolutely all > lib.dispersion modules. And as close to the first line as possible > (for most it should be on line one, even if you have to replicate some > calculations just for the 'No Rex' case). It should magically make > most problems go away! Especially in the numeric dispersion models. > And then many checks will no longer be necessary > (https://gna.org/bugs/?22065 and most errors you see in the test suite > with --numpy-raise will disappear). > > Regards, > > Edward > > > On 21 May 2014 08:48, Edward d'Auvergne <[email protected]> wrote: >> Hi Troels, >> >> Actually, if you add that check to the start of all lib.dispersion modules: >> >> # Catch parameter values that will result in no exchange, returning >> flat R2eff = R20 lines. >> if dw == 0.0 or pA == 1.0 or kex == 0.0: >> return array([R20]*num_points) >> >> it would then be worth checking if the other tests are necessary. >> This one check might eliminate the need for most of the other checks >> and the less checks there are, the faster the code will be. >> >> Regards, >> >> Edward >> >> >> >> On 21 May 2014 08:37, Edward d'Auvergne <[email protected]> wrote: >>> Hi Troels, >>> >>> With some of these, you have to be very careful that the parameter >>> combination actually does produce infinite R2eff values. I think in >>> this combination, it might not be the case. What input parameter >>> value causes weff2 to be zero? To properly check, one needs to take >>> the original equation and remove the parameter that is zero, >>> collapsing the equations. What looks like a divide by zero in the >>> original equation might actually not be because of the equation >>> simplifications. For example in almost all cases of dw being zero, >>> the R2eff equations should collapse to R20. Or in this R1rho case, to >>> R1.cos^2(theta) + R1rho'.sin^2(theta). I.e. dw=0 means there is no >>> exchange. So you should never set R2eff to 1e100 in such a case, as >>> you will no longer be able to produce the flat exchange-free R2eff >>> lines. >>> >>> Note, you'll see that in some of my original checks in the >>> lib.dispersion modules, when I am looking for a numerator that is zero >>> before looking for a denominator that is zero. You can see that in >>> the original lib.dispersion.tp02 module. But check has been removed >>> from the disp_speed branch. Without such checks, the dispersion >>> models will incorrectly model no exchange as being almost infinite >>> exchange. It would be worth looking at all checks that I carefully >>> added (they are still in the trunk), because every last one was very >>> carefully thought out with the simplification it would make to the >>> equations. So every check should be in the disp_speed branch too. >>> The checks I have added are not complete though. >>> >>> Maybe there is a far better way to perform some of these checks. For >>> example, catching parameter values that will result in zero exchange: >>> >>> # Catch parameter values that will result in no exchange, returning >>> flat R2eff = R20 lines. >>> if dw == 0.0 or pA == 1.0 or kex == 0.0: >>> return array([R20]*num_points) >>> >>> This could happen at the very start of all of the lib.dispersion >>> modules. Such a check would eliminate many of the numpy warnings >>> where R2eff values end up being Inf, NaN or zero. Actually, I feel >>> rather stupid now for not having had thought of such a brilliant check >>> before :S >>> >>> Regards, >>> >>> Edward >>> >>> >>> >>> On 20 May 2014 22:29, <[email protected]> wrote: >>>> Author: tlinnet >>>> Date: Tue May 20 22:29:40 2014 >>>> New Revision: 23270 >>>> >>>> URL: http://svn.gna.org/viewcvs/relax?rev=23270&view=rev >>>> Log: >>>> Math-domain catching for model TP02. >>>> >>>> task #7793: (https://gna.org/task/?7793) Speed-up of dispersion models. >>>> >>>> This is to implement catching of math domain errors, before they occur. >>>> These can be found via the --numpy-raise function to the systemtests. >>>> >>>> To make the code look clean, the class object "back_calc" is no longer >>>> being updated per time point, but is updated in the relax_disp target >>>> function in >>>> one go. >>>> >>>> Modified: >>>> branches/disp_speed/lib/dispersion/tp02.py >>>> branches/disp_speed/target_functions/relax_disp.py >>>> >>>> Modified: branches/disp_speed/lib/dispersion/tp02.py >>>> URL: >>>> http://svn.gna.org/viewcvs/relax/branches/disp_speed/lib/dispersion/tp02.py?rev=23270&r1=23269&r2=23270&view=diff >>>> ============================================================================== >>>> --- branches/disp_speed/lib/dispersion/tp02.py (original) >>>> +++ branches/disp_speed/lib/dispersion/tp02.py Tue May 20 22:29:40 2014 >>>> @@ -60,10 +60,10 @@ >>>> """ >>>> >>>> # Python module imports. >>>> -from numpy import arctan2, array, isfinite, sin, sum >>>> +from numpy import abs, arctan2, array, isfinite, min, sin, sum >>>> >>>> >>>> -def r1rho_TP02(r1rho_prime=None, omega=None, offset=None, pA=None, >>>> pB=None, dw=None, kex=None, R1=0.0, spin_lock_fields=None, >>>> spin_lock_fields2=None, back_calc=None, num_points=None): >>>> +def r1rho_TP02(r1rho_prime=None, omega=None, offset=None, pA=None, >>>> pB=None, dw=None, kex=None, R1=0.0, spin_lock_fields=None, >>>> spin_lock_fields2=None, num_points=None): >>>> """Calculate the R1rho' values for the TP02 model. >>>> >>>> See the module docstring for details. This is the Trott and Palmer >>>> (2002) equation according to Korzhnev (J. Biomol. NMR (2003), 26, 39-48). >>>> @@ -89,9 +89,7 @@ >>>> @type spin_lock_fields: numpy rank-1 float array >>>> @keyword spin_lock_fields2: The R1rho spin-lock field strengths >>>> squared (in rad^2.s^-2). This is for speed. >>>> @type spin_lock_fields2: numpy rank-1 float array >>>> - @keyword back_calc: The array for holding the back calculated >>>> R1rho values. Each element corresponds to one of the spin-lock fields. >>>> - @type back_calc: numpy rank-1 float array >>>> - @keyword num_points: The number of points on the dispersion >>>> curve, equal to the length of the spin_lock_fields and back_calc arguments. >>>> + @keyword num_points: The number of points on the dispersion >>>> curve, equal to the length of the spin_lock_fields. >>>> @type num_points: int >>>> """ >>>> >>>> @@ -115,6 +113,13 @@ >>>> wbeff2 = spin_lock_fields2 + db2 # Effective field at B. >>>> weff2 = spin_lock_fields2 + d2 # Effective field at >>>> pop-average. >>>> >>>> + # Catch math domain error of dividing with 0. >>>> + # This is when weff2 = 0. >>>> + if min(abs(weff2)) == 0: >>>> + R2eff = array([1e100]*num_points) >>>> + >>>> + return R2eff >>>> + >>>> # The rotating frame flip angle. >>>> theta = arctan2(spin_lock_fields, d) >>>> >>>> @@ -127,6 +132,13 @@ >>>> denom = waeff2 * wbeff2 / weff2 + kex2 >>>> #denom_extended = waeff2*wbeff2/weff2+kex2-2*sin_theta2*pA*pB*dw**2 >>>> >>>> + # Catch math domain error of dividing with 0. >>>> + # This is when denom=0. >>>> + if min(abs(denom)) == 0: >>>> + R1rho = array([1e100]*num_points) >>>> + >>>> + return R1rho >>>> + >>>> # R1rho calculation. >>>> R1rho = R1_cos_theta2 + R1rho_prime_sin_theta2 + sin_theta2 * numer / >>>> denom >>>> >>>> @@ -135,6 +147,4 @@ >>>> if not isfinite(sum(R1rho)): >>>> R1rho = array([1e100]*num_points) >>>> >>>> - # Parse back the value to update the back_calc class object. >>>> - for i in range(num_points): >>>> - back_calc[i] = R1rho[i] >>>> + return R1rho >>>> >>>> Modified: branches/disp_speed/target_functions/relax_disp.py >>>> URL: >>>> http://svn.gna.org/viewcvs/relax/branches/disp_speed/target_functions/relax_disp.py?rev=23270&r1=23269&r2=23270&view=diff >>>> ============================================================================== >>>> --- branches/disp_speed/target_functions/relax_disp.py (original) >>>> +++ branches/disp_speed/target_functions/relax_disp.py Tue May 20 >>>> 22:29:40 2014 >>>> @@ -1875,7 +1875,7 @@ >>>> # Loop over the offsets. >>>> for oi in range(self.num_offsets[0][si][mi]): >>>> # Back calculate the R1rho values. >>>> - r1rho_TP02(r1rho_prime=R20[r20_index], >>>> omega=self.chemical_shifts[0][si][mi], offset=self.offset[0][si][mi][oi], >>>> pA=pA, pB=pB, dw=dw_frq, kex=kex, R1=self.r1[si, mi], >>>> spin_lock_fields=self.spin_lock_omega1[0][mi][oi], >>>> spin_lock_fields2=self.spin_lock_omega1_squared[0][mi][oi], >>>> back_calc=self.back_calc[0][si][mi][oi], >>>> num_points=self.num_disp_points[0][si][mi][oi]) >>>> + self.back_calc[0][si][mi][oi] = >>>> r1rho_TP02(r1rho_prime=R20[r20_index], >>>> omega=self.chemical_shifts[0][si][mi], offset=self.offset[0][si][mi][oi], >>>> pA=pA, pB=pB, dw=dw_frq, kex=kex, R1=self.r1[si, mi], >>>> spin_lock_fields=self.spin_lock_omega1[0][mi][oi], >>>> spin_lock_fields2=self.spin_lock_omega1_squared[0][mi][oi], >>>> num_points=self.num_disp_points[0][si][mi][oi]) >>>> >>>> # For all missing data points, set the >>>> back-calculated value to the measured values so that it has no effect on >>>> the chi-squared value. >>>> for di in range(self.num_disp_points[0][si][mi][oi]): >>>> >>>> >>>> _______________________________________________ >>>> relax (http://www.nmr-relax.com) >>>> >>>> This is the relax-commits mailing list >>>> [email protected] >>>> >>>> To unsubscribe from this list, get a password >>>> reminder, or change your subscription options, >>>> visit the list information page at >>>> https://mail.gna.org/listinfo/relax-commits _______________________________________________ relax (http://www.nmr-relax.com) This is the relax-devel mailing list [email protected] To unsubscribe from this list, get a password reminder, or change your subscription options, visit the list information page at https://mail.gna.org/listinfo/relax-devel

