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

Reply via email to