Hi Troels,

It's now done:

r25781:  http://article.gmane.org/gmane.science.nmr.relax.scm/23532
r25782:  http://article.gmane.org/gmane.science.nmr.relax.scm/23533
r25783:  http://article.gmane.org/gmane.science.nmr.relax.scm/23534
r25784:  http://article.gmane.org/gmane.science.nmr.relax.scm/23535
r25785:  http://article.gmane.org/gmane.science.nmr.relax.scm/23536
r25786:  http://article.gmane.org/gmane.science.nmr.relax.scm/23537
r25787:  http://article.gmane.org/gmane.science.nmr.relax.scm/23538
r25788:  http://article.gmane.org/gmane.science.nmr.relax.scm/23539
r25789:  http://article.gmane.org/gmane.science.nmr.relax.scm/23540

It took a little longer as there was a bug I had to sort out in the 1
new function (pipe_control.error_analysis.covariance_matrix()).  You
will see that these changes mainly involve rearranging your code.  I
have also deleted all of your error setting code as this now uses the
set_error() API method to avoid code duplication.  The covariance
matrix and error calculation code has shifted into the
pipe_control.error_analysis.covariance_matrix() function.  And your
backend in the specific_analysis.relax_fit.estimate_rx_err module is
now the API method covariance_matrix() in
specific_analyses.relax_fit.api.

If you run:

$ ./relax -s Relax_fit.test_curve_fitting_height_estimate_error

you will see that everything is functional, just as you had it.

Regards,

Edward

On 12 September 2014 13:46, Edward d'Auvergne <[email protected]> wrote:
> Hi,
>
> Ok, then I'll do it!  I cannot support multiple covariance matrix
> implementations for each analysis type.  The subsequent support work,
> which is always required especially when a code refactorisation occurs
> or when users find cases where the method doesn't work, is something
> I'll probably have to look after.  Therefore I will do this now before
> you get too far and make a lot more work for me in the future.
> Multiple implementations of the same thing are difficult to support.
> I'm guessing it'll take me all of about 15 min to rearrange the code
> and create the new pipe_control.error_analysis.covariance_matrix()
> function, so it is still not too late.  Fortunately most of the work
> happens in lib.statistics.multifit_covar() which does not require any
> changes.
>
> Regards,
>
> Edward
>
>
> On 12 September 2014 12:15, Troels Emtekær Linnet <[email protected]> 
> wrote:
>> Hi Edward.
>>
>> Thank you for the detailed description.
>>
>> I currently don't have time to look into api implementation.
>>
>> Best
>> Troels
>>
>> 2014-09-12 11:53 GMT+02:00 Edward d'Auvergne <[email protected]>:
>>> Hi Troels,
>>>
>>> For the backend function, instead of duplicating code and having one
>>> backend in the relaxation dispersion analysis and one backend in the
>>> relaxation curve-fitting analysis - now is the time to learn the
>>> specific analysis API!  I cannot emphasis how simple this is.  The
>>> steps would be:
>>>
>>> 1)  Create the error_analysis.covariance_matrix user function frontend
>>> in user_functions/.  This would be instead of creating a new relax_fit
>>> user function, and would be pretty much identical anyway.
>>>
>>> 2a)  I have renamed the pipe_control.monte_carlo module to
>>> pipe_control.error_analysis.  I have prepended the text 'monte_carlo_'
>>> to all of the current functions.  This module will be used for all
>>> error analysis techniques:  Monte Carlo simulations, covariance
>>> matrix, Jackknife simulations, Bootstrapping (which is currently via
>>> the Monte Carlo functions), etc.
>>>
>>> 2b)  Create a new function in pipe_control.error_analysis called
>>> covariance_matrix().
>>>
>>> 3)  Inside covariance_matrix(), call "api = return_api()", and then
>>> call "api.covariance_matrix()".  For the 'relax-fit' analysis, this
>>> will be the covariance_matrix() method in the
>>> specific_analyses.relax_fit.api module.
>>>
>>> 4)  Add a stub covariance_matrix() method to
>>> specific_analyses.api_base.  This defines how the method should be
>>> named and what arguments it takes.
>>>
>>> 5)  Add a new covariance_matrix() method to specific_analyses.relax_fit.api.
>>>
>>> That's all there is too it.  It is really time for this!  The entire
>>> point of the specific analysis API is to avoid what you are currently
>>> implementing in relax.  If the pattern of what you are doing is
>>> extended to all analysis types, which might happen in the future, then
>>> there will be huge amounts of code duplication required.  This is a
>>> bad design.  You need to dive into the specific API!  The steps above
>>> are all that are required for this.  Oh, a system test with a call to
>>> the error_analysis.covariance_matrix user function would be the best
>>> way to start this.
>>>
>>> Regards,
>>>
>>> Edward
>>>
>>> On 12 September 2014 11:25,  <[email protected]> wrote:
>>>> Author: tlinnet
>>>> Date: Fri Sep 12 11:25:50 2014
>>>> New Revision: 25775
>>>>
>>>> URL: http://svn.gna.org/viewcvs/relax?rev=25775&view=rev
>>>> Log:
>>>> Implemented back-end function to estimate Rx and I0 errors from Jacobian 
>>>> matrix.
>>>>
>>>> This is to prepare for user funcion in relax_fit, to estimate errors.
>>>>
>>>> Added:
>>>>     trunk/specific_analyses/relax_fit/estimate_rx_err.py
>>>> Modified:
>>>>     trunk/specific_analyses/relax_fit/__init__.py
>>>>
>>>> Modified: trunk/specific_analyses/relax_fit/__init__.py
>>>> URL: 
>>>> http://svn.gna.org/viewcvs/relax/trunk/specific_analyses/relax_fit/__init__.py?rev=25775&r1=25774&r2=25775&view=diff
>>>> ==============================================================================
>>>> --- trunk/specific_analyses/relax_fit/__init__.py       (original)
>>>> +++ trunk/specific_analyses/relax_fit/__init__.py       Fri Sep 12 
>>>> 11:25:50 2014
>>>> @@ -25,6 +25,7 @@
>>>>  # The available modules.
>>>>  __all__ = [
>>>>      'api',
>>>> +    'estimate_rx_err',
>>>>      'optimisation',
>>>>      'parameter_object',
>>>>      'parameters',
>>>>
>>>> Added: trunk/specific_analyses/relax_fit/estimate_rx_err.py
>>>> URL: 
>>>> http://svn.gna.org/viewcvs/relax/trunk/specific_analyses/relax_fit/estimate_rx_err.py?rev=25775&view=auto
>>>> ==============================================================================
>>>> --- trunk/specific_analyses/relax_fit/estimate_rx_err.py        (added)
>>>> +++ trunk/specific_analyses/relax_fit/estimate_rx_err.py        Fri Sep 12 
>>>> 11:25:50 2014
>>>> @@ -0,0 +1,157 @@
>>>> +###############################################################################
>>>> +#                                                                         
>>>>     #
>>>> +# Copyright (C) 2014 Troels E. Linnet                                     
>>>>     #
>>>> +#                                                                         
>>>>     #
>>>> +# This file is part of the program relax (http://www.nmr-relax.com).      
>>>>     #
>>>> +#                                                                         
>>>>     #
>>>> +# This program 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.                                     
>>>>     #
>>>> +#                                                                         
>>>>     #
>>>> +# This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.   
>>>>     #
>>>> +#                                                                         
>>>>     #
>>>> +###############################################################################
>>>> +
>>>> +# Module docstring.
>>>> +"""Estimation of rx error, from Co-variance matrix."""
>>>> +
>>>> +# Python module imports.
>>>> +from copy import deepcopy
>>>> +from numpy import asarray, diag, sqrt, transpose
>>>> +import sys
>>>> +from warnings import warn
>>>> +
>>>> +# relax module imports.
>>>> +from dep_check import C_module_exp_fn
>>>> +from lib.errors import RelaxError
>>>> +from lib.statistics import multifit_covar
>>>> +from lib.text.sectioning import subsection
>>>> +from lib.warnings import RelaxWarning
>>>> +from pipe_control.mol_res_spin import generate_spin_string, spin_loop
>>>> +
>>>> +# C modules.
>>>> +if C_module_exp_fn:
>>>> +    from target_functions.relax_fit import jacobian, jacobian_chi2, setup
>>>> +
>>>> +
>>>> +def estimate_rx_err(spin_id=None, epsrel=0.0, verbosity=2):
>>>> +    """This will estimate the rx and i0 errors from the covariance matrix 
>>>> Qxx.  Qxx is calculated from the Jacobian matrix and the optimised 
>>>> parameters.
>>>> +
>>>> +    @keyword spin_id:       The spin identification string.
>>>> +    @type spin_id:          str
>>>> +    @param epsrel:          Any columns of R which satisfy |R_{kk}| <= 
>>>> epsrel |R_{11}| are considered linearly-dependent and are excluded from 
>>>> the covariance matrix, where the corresponding rows and columns of the 
>>>> covariance matrix are set to zero.
>>>> +    @type epsrel:           float
>>>> +    @keyword verbosity:     The amount of information to print.  The 
>>>> higher the value, the greater the verbosity.
>>>> +    @type verbosity:        int
>>>> +    """
>>>> +
>>>> +    # Check that the C modules have been compiled.
>>>> +    if not C_module_exp_fn:
>>>> +        raise RelaxError("Relaxation curve fitting is not available.  Try 
>>>> compiling the C modules on your platform.")
>>>> +
>>>> +    # Perform checks.
>>>> +    if not cdp.curve_type == 'exp':
>>>> +        raise RelaxError("Only curve type of 'exp' is allowed for error 
>>>> estimation.  Set by: relax_fit.select_model('exp').")
>>>> +
>>>> +    # Loop over the spins.
>>>> +    for cur_spin, mol_name, resi, resn, cur_spin_id in 
>>>> spin_loop(selection=spin_id, full_info=True, return_id=True, 
>>>> skip_desel=True):
>>>> +        # Generate spin string.
>>>> +        spin_string = generate_spin_string(spin=cur_spin, 
>>>> mol_name=mol_name, res_num=resi, res_name=resn)
>>>> +
>>>> +        # Raise Error, if not optimised.
>>>> +        if not (hasattr(cur_spin, 'rx') and hasattr(cur_spin, 'i0')):
>>>> +            raise RelaxError("Spin '%s' does not contain optimised 'rx' 
>>>> and 'i0' values.  Try execute: minimise.execute(min_algor='Newton', 
>>>> constraints=False)"%(spin_string))
>>>> +
>>>> +        # Raise warning, if gradient count is 0.  This could point to a 
>>>> lack of minimisation first.
>>>> +        if hasattr(cur_spin, 'g_count'):
>>>> +            if getattr(cur_spin, 'g_count') == 0.0:
>>>> +                text = "Spin %s contains a gradient count of 0.0.  Is the 
>>>> rx parameter optimised?  Try execute: minimise.execute(min_algor='Newton', 
>>>> constraints=False)" %(spin_string)
>>>> +                warn(RelaxWarning("%s." % text))
>>>> +
>>>> +        # Print information.
>>>> +        if verbosity >= 1:
>>>> +            # Individual spin block section.
>>>> +            top = 2
>>>> +            if verbosity >= 2:
>>>> +                top += 2
>>>> +            subsection(file=sys.stdout, text="Estimating rx error for 
>>>> spin: %s"%spin_string, prespace=top)
>>>> +
>>>> +        # The keys.
>>>> +        keys = list(cur_spin.peak_intensity.keys())
>>>> +
>>>> +        # The peak intensities and times.
>>>> +        values = []
>>>> +        errors = []
>>>> +        times = []
>>>> +        for key in keys:
>>>> +            values.append(cur_spin.peak_intensity[key])
>>>> +            errors.append(cur_spin.peak_intensity_err[key])
>>>> +            times.append(cdp.relax_times[key])
>>>> +
>>>> +        # Convert to numpy array.
>>>> +        values = asarray(values)
>>>> +        errors = asarray(errors)
>>>> +        times = asarray(times)
>>>> +
>>>> +        # Extract values.
>>>> +        rx = getattr(cur_spin, 'rx')
>>>> +        i0 = getattr(cur_spin, 'i0')
>>>> +
>>>> +        # Pack data
>>>> +        param_vector = [rx, i0]
>>>> +
>>>> +        # Initialise data in C code.
>>>> +        scaling_list = [1.0, 1.0]
>>>> +        setup(num_params=len(param_vector), num_times=len(times), 
>>>> values=values, sd=errors, relax_times=times, scaling_matrix=scaling_list)
>>>> +
>>>> +        # Use the direct Jacobian from function.
>>>> +        jacobian_matrix_exp = transpose(asarray( jacobian(param_vector) ) 
>>>> )
>>>> +        weights = 1. / errors**2
>>>> +
>>>> +        # Get the co-variance
>>>> +        pcov = multifit_covar(J=jacobian_matrix_exp, weights=weights)
>>>> +
>>>> +        # To compute one standard deviation errors on the parameters, 
>>>> take the square root of the diagonal covariance.
>>>> +        param_vector_error = sqrt(diag(pcov))
>>>> +
>>>> +        # Extract values.
>>>> +        rx_err, i0_err = param_vector_error
>>>> +
>>>> +        # Copy rx, to rx_err, if not exists.
>>>> +        if not hasattr(cur_spin, 'rx_err'):
>>>> +            setattr(cur_spin, 'rx_err', deepcopy(getattr(cur_spin, 'rx')))
>>>> +        if not hasattr(cur_spin, 'i0_err'):
>>>> +            setattr(cur_spin, 'i0_err', deepcopy(getattr(cur_spin, 'i0')))
>>>> +
>>>> +        # Set error.
>>>> +        cur_spin.rx_err = rx_err
>>>> +        cur_spin.i0_err = i0_err
>>>> +
>>>> +        # Get other relevant information.
>>>> +        chi2 = getattr(cur_spin, 'chi2')
>>>> +
>>>> +        # Print information.
>>>> +        print_strings = []
>>>> +        if verbosity >= 1:
>>>> +            # Add print strings.
>>>> +            point_info = "Spin: '%s', with %i time points." % 
>>>> (spin_string, len(times))
>>>> +            print_strings.append(point_info)
>>>> +
>>>> +            par_info = "rx=%3.3f rx_err=%3.4f, i0=%6.1f, i0_err=%3.4f, 
>>>> chi2=%3.3f.\n" % ( rx, rx_err, i0, i0_err, chi2)
>>>> +            print_strings.append(par_info)
>>>> +
>>>> +            if verbosity >= 2:
>>>> +                time_info = ', '.join(map(str, times))
>>>> +                print_strings.append('For time array: '+time_info+'.\n\n')
>>>> +
>>>> +        # Print info
>>>> +        if len(print_strings) > 0:
>>>> +            for print_string in print_strings:
>>>> +                print(print_string),
>>>>
>>>>
>>>> _______________________________________________
>>>> 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

_______________________________________________
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

Reply via email to