def covariance_matrix(epsrel=0.0, verbosity=2): """Estimate model parameter errors via the covariance matrix technique. Note that the covariance matrix error estimate is always of lower quality than Monte Carlo simulations. @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 """ # Test if the current data pipe exists. check_pipe() # The specific analysis API object. api = return_api() # Loop over the models. for model_info in api.model_loop(): # Get the Jacobian and weighting matrix. jacobian, weights = api.covariance_matrix(model_info=model_info, verbosity=verbosity) # Calculate the covariance matrix. pcov = statistics.multifit_covar(J=jacobian, weights=weights) # To compute one standard deviation errors on the parameters, take the square root of the diagonal covariance. sd = sqrt(diag(pcov)) # Loop over the parameters. index = 0 for name in api.get_param_names(model_info): # Set the parameter error. api.set_error(index, sd[index], model_info=model_info) # Increment the parameter index. index = index + 1
def minimise_minfx(E=None): """Estimate r2eff and errors by minimising with minfx. @keyword E: The Exponential function class, which contain data and functions. @type E: class @return: Packed list with optimised parameter, parameter error set to 'inf', chi2, iter_count, f_count, g_count, h_count, warning @rtype: list """ # 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." ) # Initial guess for minimisation. Solved by linear least squares. x0 = asarray(E.estimate_x0_exp(times=E.times, values=E.values)) if E.c_code: # Minimise with C code. # Initialise the function to minimise. scaling_list = [1.0, 1.0] model = Relax_fit_opt(model='exp', num_params=len(x0), values=E.values, errors=E.errors, relax_times=E.times, scaling_matrix=scaling_list) # Define function to minimise for minfx. t_func = model.func t_dfunc = model.dfunc t_d2func = model.d2func args = () else: # Minimise with minfx. # Define function to minimise for minfx. t_func = E.func_exp_chi2 t_dfunc = E.func_exp_chi2_grad t_d2func = None # All args to function. Params are packed out through function, then other parameters. args = (E.times, E.values, E.errors) # Minimise. results_minfx = generic_minimise(func=t_func, dfunc=t_dfunc, d2func=t_d2func, args=args, x0=x0, min_algor=E.min_algor, min_options=E.min_options, func_tol=E.func_tol, grad_tol=E.grad_tol, maxiter=E.max_iterations, A=E.A, b=E.b, full_output=True, print_flag=0) # Unpack param_vector, chi2, iter_count, f_count, g_count, h_count, warning = results_minfx # Extract. r2eff, i0 = param_vector # Get the Jacobian. if E.c_code == True: if E.chi2_jacobian: # Use the chi2 Jacobian from C. jacobian_matrix_exp = transpose( asarray(model.jacobian_chi2(param_vector))) weights = ones(E.errors.shape) else: # Use the direct Jacobian from C. jacobian_matrix_exp = transpose( asarray(model.jacobian(param_vector))) weights = 1. / E.errors**2 elif E.c_code == False: if E.chi2_jacobian: # Use the chi2 Jacobian from python. jacobian_matrix_exp = E.func_exp_chi2_grad_array( params=param_vector, times=E.times, values=E.values, errors=E.errors) weights = ones(E.errors.shape) else: # Use the direct Jacobian from python. jacobian_matrix_exp = E.func_exp_grad(params=param_vector, times=E.times) weights = 1. / E.errors**2 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)) # Pack to list. results = [ param_vector, param_vector_error, chi2, iter_count, f_count, g_count, h_count, warning ] # Return, including errors. return results
def minimise_minfx(E=None): """Estimate r2eff and errors by minimising with minfx. @keyword E: The Exponential function class, which contain data and functions. @type E: class @return: Packed list with optimised parameter, parameter error set to 'inf', chi2, iter_count, f_count, g_count, h_count, warning @rtype: list """ # 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.") # Initial guess for minimisation. Solved by linear least squares. x0 = asarray( E.estimate_x0_exp(times=E.times, values=E.values) ) if E.c_code: # Minimise with C code. # Initialise the function to minimise. scaling_list = [1.0, 1.0] model = Relax_fit_opt(model='exp', num_params=len(x0), values=E.values, errors=E.errors, relax_times=E.times, scaling_matrix=scaling_list) # Define function to minimise for minfx. t_func = model.func t_dfunc = model.dfunc t_d2func = model.d2func args=() else: # Minimise with minfx. # Define function to minimise for minfx. t_func = E.func_exp_chi2 t_dfunc = E.func_exp_chi2_grad t_d2func = None # All args to function. Params are packed out through function, then other parameters. args=(E.times, E.values, E.errors) # Minimise. results_minfx = generic_minimise(func=t_func, dfunc=t_dfunc, d2func=t_d2func, args=args, x0=x0, min_algor=E.min_algor, min_options=E.min_options, func_tol=E.func_tol, grad_tol=E.grad_tol, maxiter=E.max_iterations, A=E.A, b=E.b, full_output=True, print_flag=0) # Unpack param_vector, chi2, iter_count, f_count, g_count, h_count, warning = results_minfx # Extract. r2eff, i0 = param_vector # Get the Jacobian. if E.c_code == True: if E.chi2_jacobian: # Use the chi2 Jacobian from C. jacobian_matrix_exp = transpose(asarray( model.jacobian_chi2(param_vector) ) ) weights = ones(E.errors.shape) else: # Use the direct Jacobian from C. jacobian_matrix_exp = transpose(asarray( model.jacobian(param_vector) ) ) weights = 1. / E.errors**2 elif E.c_code == False: if E.chi2_jacobian: # Use the chi2 Jacobian from python. jacobian_matrix_exp = E.func_exp_chi2_grad_array(params=param_vector, times=E.times, values=E.values, errors=E.errors) weights = ones(E.errors.shape) else: # Use the direct Jacobian from python. jacobian_matrix_exp = E.func_exp_grad(params=param_vector, times=E.times) weights = 1. / E.errors**2 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)) # Pack to list. results = [param_vector, param_vector_error, chi2, iter_count, f_count, g_count, h_count, warning] # Return, including errors. return results
def estimate_r2eff_err(spin_id=None, epsrel=0.0, verbosity=1): """This will estimate the R2eff 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. check_model_type(model=MODEL_R2EFF) # 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, 'r2eff') and hasattr(cur_spin, 'i0')): raise RelaxError( "Spin %s does not contain optimised 'r2eff' 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 R2eff 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 R2eff error for spin: %s" % spin_string, prespace=top) # Loop over each spectrometer frequency and dispersion point. for exp_type, frq, offset, point, ei, mi, oi, di in loop_exp_frq_offset_point( return_indices=True): # The parameter key. param_key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point) # Extract values. r2eff = getattr(cur_spin, 'r2eff')[param_key] i0 = getattr(cur_spin, 'i0')[param_key] # Pack data param_vector = [r2eff, i0] # The peak intensities, errors and times. values = [] errors = [] times = [] for time in loop_time(exp_type=exp_type, frq=frq, offset=offset, point=point): values.append( average_intensity(spin=cur_spin, exp_type=exp_type, frq=frq, offset=offset, point=point, time=time)) errors.append( average_intensity(spin=cur_spin, exp_type=exp_type, frq=frq, offset=offset, point=point, time=time, error=True)) times.append(time) # Convert to numpy array. values = asarray(values) errors = asarray(errors) times = asarray(times) # Initialise data in C code. scaling_list = [1.0, 1.0] model = Relax_fit_opt(model='exp', num_params=len(param_vector), values=values, errors=errors, relax_times=times, scaling_matrix=scaling_list) # Use the direct Jacobian from function. jacobian_matrix_exp = transpose( asarray(model.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. r2eff_err, i0_err = param_vector_error # Copy r2eff dictionary, to r2eff_err dictionary. They have same keys to the dictionary, if not hasattr(cur_spin, 'r2eff_err'): setattr(cur_spin, 'r2eff_err', deepcopy(getattr(cur_spin, 'r2eff'))) if not hasattr(cur_spin, 'i0_err'): setattr(cur_spin, 'i0_err', deepcopy(getattr(cur_spin, 'i0'))) # Set error. cur_spin.r2eff_err[param_key] = r2eff_err cur_spin.i0_err[param_key] = i0_err # Get other relevant information. chi2 = getattr(cur_spin, 'chi2') # Print information. print_strings = [] if verbosity >= 1: # Add print strings. point_info = "%s at %3.1f MHz, for offset=%3.3f ppm and dispersion point %-5.1f, with %i time points." % ( exp_type, frq / 1E6, offset, point, len(times)) print_strings.append(point_info) par_info = "r2eff=%3.3f r2eff_err=%3.4f, i0=%6.1f, i0_err=%3.4f, chi2=%3.3f.\n" % ( r2eff, r2eff_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),
def estimate_r2eff_err(spin_id=None, epsrel=0.0, verbosity=1): """This will estimate the R2eff 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. check_model_type(model=MODEL_R2EFF) # 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, 'r2eff') and hasattr(cur_spin, 'i0')): raise RelaxError("Spin %s does not contain optimised 'r2eff' 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 R2eff 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 R2eff error for spin: %s"%spin_string, prespace=top) # Loop over each spectrometer frequency and dispersion point. for exp_type, frq, offset, point, ei, mi, oi, di in loop_exp_frq_offset_point(return_indices=True): # The parameter key. param_key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point) # Extract values. r2eff = getattr(cur_spin, 'r2eff')[param_key] i0 = getattr(cur_spin, 'i0')[param_key] # Pack data param_vector = [r2eff, i0] # The peak intensities, errors and times. values = [] errors = [] times = [] for time in loop_time(exp_type=exp_type, frq=frq, offset=offset, point=point): values.append(average_intensity(spin=cur_spin, exp_type=exp_type, frq=frq, offset=offset, point=point, time=time)) errors.append(average_intensity(spin=cur_spin, exp_type=exp_type, frq=frq, offset=offset, point=point, time=time, error=True)) times.append(time) # Convert to numpy array. values = asarray(values) errors = asarray(errors) times = asarray(times) # Initialise data in C code. scaling_list = [1.0, 1.0] model = Relax_fit_opt(model='exp', num_params=len(param_vector), values=values, errors=errors, relax_times=times, scaling_matrix=scaling_list) # Use the direct Jacobian from function. jacobian_matrix_exp = transpose(asarray( model.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. r2eff_err, i0_err = param_vector_error # Copy r2eff dictionary, to r2eff_err dictionary. They have same keys to the dictionary, if not hasattr(cur_spin, 'r2eff_err'): setattr(cur_spin, 'r2eff_err', deepcopy(getattr(cur_spin, 'r2eff'))) if not hasattr(cur_spin, 'i0_err'): setattr(cur_spin, 'i0_err', deepcopy(getattr(cur_spin, 'i0'))) # Set error. cur_spin.r2eff_err[param_key] = r2eff_err cur_spin.i0_err[param_key] = i0_err # Get other relevant information. chi2 = getattr(cur_spin, 'chi2') # Print information. print_strings = [] if verbosity >= 1: # Add print strings. point_info = "%s at %3.1f MHz, for offset=%3.3f ppm and dispersion point %-5.1f, with %i time points." % (exp_type, frq/1E6, offset, point, len(times)) print_strings.append(point_info) par_info = "r2eff=%3.3f r2eff_err=%3.4f, i0=%6.1f, i0_err=%3.4f, chi2=%3.3f.\n" % ( r2eff, r2eff_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),