1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Target functions for relaxation exponential curve fitting with both minfx and scipy.optimize.leastsq."""
24
25
26 from copy import deepcopy
27 from numpy import array, asarray, diag, exp, log, ones, sqrt, sum, transpose, zeros
28 from minfx.generic import generic_minimise
29 import sys
30 from warnings import warn
31
32
33 from dep_check import C_module_exp_fn, scipy_module
34 from lib.dispersion.variables import MODEL_R2EFF
35 from lib.errors import RelaxError
36 from lib.statistics import multifit_covar
37 from lib.text.sectioning import subsection
38 from lib.warnings import RelaxWarning
39 from pipe_control.mol_res_spin import generate_spin_string, spin_loop
40 from specific_analyses.relax_disp.checks import check_model_type
41 from specific_analyses.relax_disp.data import average_intensity, loop_exp_frq_offset_point, loop_time, return_param_key_from_data
42 from specific_analyses.relax_disp.parameters import disassemble_param_vector
43 from target_functions.chi2 import chi2_rankN, dchi2
44 from target_functions.relax_fit_wrapper import Relax_fit_opt
45
46
47 if scipy_module:
48
49 from scipy.optimize import leastsq
50
51
53 """This will estimate the R2eff and i0 errors from the covariance matrix Qxx. Qxx is calculated from the Jacobian matrix and the optimised parameters.
54
55 @keyword spin_id: The spin identification string.
56 @type spin_id: str
57 @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.
58 @type epsrel: float
59 @keyword verbosity: The amount of information to print. The higher the value, the greater the verbosity.
60 @type verbosity: int
61 """
62
63
64 if not C_module_exp_fn:
65 raise RelaxError("Relaxation curve fitting is not available. Try compiling the C modules on your platform.")
66
67
68 check_model_type(model=MODEL_R2EFF)
69
70
71 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):
72
73 spin_string = generate_spin_string(spin=cur_spin, mol_name=mol_name, res_num=resi, res_name=resn)
74
75
76 if not (hasattr(cur_spin, 'r2eff') and hasattr(cur_spin, 'i0')):
77 raise RelaxError("Spin %s does not contain optimised 'r2eff' and 'i0' values. Try execute: minimise.execute(min_algor='Newton', constraints=False)"%(spin_string))
78
79
80 if hasattr(cur_spin, 'g_count'):
81 if getattr(cur_spin, 'g_count') == 0.0:
82 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)
83 warn(RelaxWarning("%s." % text))
84
85
86 if verbosity >= 1:
87
88 top = 2
89 if verbosity >= 2:
90 top += 2
91 subsection(file=sys.stdout, text="Estimating R2eff error for spin: %s"%spin_string, prespace=top)
92
93
94 for exp_type, frq, offset, point, ei, mi, oi, di in loop_exp_frq_offset_point(return_indices=True):
95
96 param_key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point)
97
98
99 r2eff = getattr(cur_spin, 'r2eff')[param_key]
100 i0 = getattr(cur_spin, 'i0')[param_key]
101
102
103 param_vector = [r2eff, i0]
104
105
106 values = []
107 errors = []
108 times = []
109 for time in loop_time(exp_type=exp_type, frq=frq, offset=offset, point=point):
110 values.append(average_intensity(spin=cur_spin, exp_type=exp_type, frq=frq, offset=offset, point=point, time=time))
111 errors.append(average_intensity(spin=cur_spin, exp_type=exp_type, frq=frq, offset=offset, point=point, time=time, error=True))
112 times.append(time)
113
114
115 values = asarray(values)
116 errors = asarray(errors)
117 times = asarray(times)
118
119
120 scaling_list = [1.0, 1.0]
121 model = Relax_fit_opt(model='exp', num_params=len(param_vector), values=values, errors=errors, relax_times=times, scaling_matrix=scaling_list)
122
123
124 jacobian_matrix_exp = transpose(asarray( model.jacobian(param_vector) ) )
125 weights = 1. / errors**2
126
127
128 pcov = multifit_covar(J=jacobian_matrix_exp, weights=weights)
129
130
131 param_vector_error = sqrt(diag(pcov))
132
133
134 r2eff_err, i0_err = param_vector_error
135
136
137 if not hasattr(cur_spin, 'r2eff_err'):
138 setattr(cur_spin, 'r2eff_err', deepcopy(getattr(cur_spin, 'r2eff')))
139 if not hasattr(cur_spin, 'i0_err'):
140 setattr(cur_spin, 'i0_err', deepcopy(getattr(cur_spin, 'i0')))
141
142
143 cur_spin.r2eff_err[param_key] = r2eff_err
144 cur_spin.i0_err[param_key] = i0_err
145
146
147 chi2 = getattr(cur_spin, 'chi2')
148
149
150 print_strings = []
151 if verbosity >= 1:
152
153 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))
154 print_strings.append(point_info)
155
156 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)
157 print_strings.append(par_info)
158
159 if verbosity >= 2:
160 time_info = ', '.join(map(str, times))
161 print_strings.append('For time array: '+time_info+'.\n\n')
162
163
164 if len(print_strings) > 0:
165 for print_string in print_strings:
166 print(print_string),
167
168
169
170
173 """Class for to set settings for minimisation and dispersion target functions for minimisation.
174
175 This class contains minimisation functions for both minfx and scipy.optimize.leastsq.
176
177 @keyword verbosity: The amount of information to print. The higher the value, the greater the verbosity.
178 @type verbosity: int
179 """
180
181
182 self.verbosity = verbosity
183
184
185 self.set_settings_leastsq()
186 self.set_settings_minfx()
187
188
189 - def setup_data(self, times=None, values=None, errors=None):
190 """Setup for minimisation with minfx.
191
192 @keyword times: The time points.
193 @type times: numpy array
194 @keyword values: The measured intensity values per time point.
195 @type values: numpy array
196 @keyword errors: The standard deviation of the measured intensity values per time point.
197 @type errors: numpy array
198 """
199
200
201 self.times = times
202 self.values = values
203 self.errors = errors
204
205
207 """Setup options to scipy.optimize.leastsq.
208
209 @keyword ftol: The function tolerance for the relative error desired in the sum of squares, parsed to leastsq.
210 @type ftol: float
211 @keyword xtol: The error tolerance for the relative error desired in the approximate solution, parsed to leastsq.
212 @type xtol: float
213 @keyword maxfev: The maximum number of function evaluations, parsed to leastsq. If zero, then 100*(N+1) is the maximum function calls. N is the number of elements in x0=[r2eff, i0].
214 @type maxfev: int
215 @keyword factor: The initial step bound, parsed to leastsq. It determines the initial step bound (''factor * || diag * x||''). Should be in the interval (0.1, 100).
216 @type factor: float
217 """
218
219
220 self.ftol = ftol
221 self.xtol = xtol
222 self.maxfev = maxfev
223 self.factor = factor
224
225
226 - def set_settings_minfx(self, scaling_matrix=None, min_algor='simplex', c_code=True, constraints=False, chi2_jacobian=False, func_tol=1e-25, grad_tol=None, max_iterations=10000000):
227 """Setup options to minfx.
228
229 @keyword scaling_matrix: The square and diagonal scaling matrix.
230 @type scaling_matrix: numpy rank-2 float array
231 @keyword min_algor: The minimisation algorithm
232 @type min_algor: string
233 @keyword c_code: If optimise with C code.
234 @type c_code: bool
235 @keyword constraints: If constraints should be used.
236 @type constraints: bool
237 @keyword chi2_jacobian: If the chi2 Jacobian should be used.
238 @type chi2_jacobian: bool
239 @keyword func_tol: The function tolerance which, when reached, terminates optimisation. Setting this to None turns of the check.
240 @type func_tol: None or float
241 @keyword grad_tol: The gradient tolerance which, when reached, terminates optimisation. Setting this to None turns of the check.
242 @type grad_tol: None or float
243 @keyword max_iterations: The maximum number of iterations for the algorithm.
244 @type max_iterations: int
245 """
246
247
248 self.scaling_matrix = scaling_matrix
249 self.c_code = c_code
250 self.chi2_jacobian = chi2_jacobian
251
252
253 self.scaling_flag = False
254 if self.scaling_matrix != None:
255 self.scaling_flag = True
256
257
258 self.min_algor = min_algor
259
260
261 self.constraints = constraints
262
263
264 self.func_tol = func_tol
265 self.grad_tol = grad_tol
266 self.max_iterations = max_iterations
267
268
269 if self.constraints:
270 self.min_options = ('%s'%(self.min_algor),)
271 self.min_algor = 'Log barrier'
272 self.A = array([ [ 1., 0.],
273 [-1., 0.],
274 [ 0., 1.]] )
275 self.b = array([ 0., -200., 0.])
276
277 else:
278 self.min_options = ()
279 self.A = None
280 self.b = None
281
282
284 """Estimate starting parameter x0 = [r2eff_est, i0_est], by converting the exponential curve to a linear problem. Then solving by linear least squares of: ln(Intensity[j]) = ln(i0) - time[j]* r2eff.
285
286 @keyword times: The time points.
287 @type times: numpy array
288 @keyword values: The measured intensity values per time point.
289 @type values: numpy array
290 @return: The list with estimated r2eff and i0 parameter for optimisation, [r2eff_est, i0_est]
291 @rtype: list
292 """
293
294
295 w = log(values)
296 x = - 1. * times
297 n = len(times)
298
299
300 b = (sum(x*w) - 1./n * sum(x) * sum(w) ) / ( sum(x**2) - 1./n * (sum(x))**2 )
301 a = 1./n * sum(w) - b * 1./n * sum(x)
302
303
304 r2eff_est = b
305 i0_est = exp(a)
306
307
308 return [r2eff_est, i0_est]
309
310
311 - def func_exp(self, params=None, times=None):
312 """Calculate the function values of exponential function.
313
314 @param params: The vector of parameter values.
315 @type params: numpy rank-1 float array
316 @keyword times: The time points.
317 @type times: numpy array
318 @return: The function values.
319 @rtype: numpy array
320 """
321
322
323 r2eff, i0 = params
324
325
326 return i0 * exp( -times * r2eff)
327
328
330 """Calculate the residual vector betwen measured values and the function values.
331
332 @param params: The vector of parameter values.
333 @type params: numpy rank-1 float array
334 @keyword times: The time points.
335 @type times: numpy array
336 @param values: The measured values.
337 @type values: numpy array
338 @return: The residuals.
339 @rtype: numpy array
340 """
341
342
343 K = values - self.func_exp(params=params, times=times)
344
345
346 return K
347
348
350 """Calculate the weighted residual vector betwen measured values and the function values.
351
352 @param params: The vector of parameter values.
353 @type params: numpy rank-1 float array
354 @keyword times: The time points.
355 @type times: numpy array
356 @param values: The measured values.
357 @type values: numpy array
358 @param errors: The standard deviation of the measured intensity values per time point.
359 @type errors: numpy array
360 @return: The weighted residuals.
361 @rtype: numpy array
362 """
363
364
365 Kw = 1. / errors * self.func_exp_residual(params=params, times=times, values=values)
366
367
368 return Kw
369
370
372 """The gradient (Jacobian matrix) of func_exp for Co-variance calculation.
373
374 @param params: The vector of parameter values.
375 @type params: numpy rank-1 float array
376 @keyword times: The time points.
377 @type times: numpy array
378 @return: The Jacobian matrix with 'm' rows of function derivatives per 'n' columns of parameters.
379 @rtype: numpy array
380 """
381
382
383 r2eff = params[0]
384 i0 = params[1]
385
386
387 d_exp_d_r2eff = -i0 * times * exp(-r2eff * times)
388
389
390 d_exp_d_i0 = exp(-r2eff * times)
391
392
393 jacobian_matrix_exp = transpose(array( [d_exp_d_r2eff, d_exp_d_i0] ) )
394
395
396 return jacobian_matrix_exp
397
398
399 - def func_exp_chi2(self, params=None, times=None, values=None, errors=None):
400 """Target function for minimising chi2 in minfx, for exponential fit.
401
402 @param params: The vector of parameter values.
403 @type params: numpy rank-1 float array
404 @keyword times: The time points.
405 @type times: numpy array
406 @param values: The measured values.
407 @type values: numpy array
408 @param errors: The standard deviation of the measured intensity values per time point.
409 @type errors: numpy array
410 @return: The chi2 value.
411 @rtype: float
412 """
413
414
415 back_calc = self.func_exp(params=params, times=times)
416
417
418 chi2 = chi2_rankN(data=values, back_calc_vals=back_calc, errors=errors)
419
420
421 return chi2
422
423
425 """Target function for the gradient (Jacobian matrix) to minfx, for exponential fit .
426
427 @param params: The vector of parameter values.
428 @type params: numpy rank-1 float array
429 @keyword times: The time points.
430 @type times: numpy array
431 @param values: The measured values.
432 @type values: numpy array
433 @param errors: The standard deviation of the measured intensity values per time point.
434 @type errors: numpy array
435 @return: The Jacobian matrix with 'm' rows of function derivatives per 'n' columns of parameters, which have been summed together.
436 @rtype: numpy array
437 """
438
439
440 back_calc = self.func_exp(params=params, times=times)
441
442
443 exp_grad = self.func_exp_grad(params=params, times=times)
444
445
446 exp_grad_t = transpose(exp_grad)
447
448
449 n = len(params)
450
451
452 jacobian_chi2_minfx = zeros([n])
453
454
455 dchi2(dchi2=jacobian_chi2_minfx, M=n, data=values, back_calc_vals=back_calc, back_calc_grad=exp_grad_t, errors=errors)
456
457
458 return jacobian_chi2_minfx
459
460
462 """Return the gradient (Jacobian matrix) of func_exp_chi2() for parameter co-variance error estimation. This needs return as array.
463
464 @param params: The vector of parameter values.
465 @type params: numpy rank-1 float array
466 @keyword times: The time points.
467 @type times: numpy array
468 @keyword values: The measured intensity values per time point.
469 @type values: numpy array
470 @keyword errors: The standard deviation of the measured intensity values per time point.
471 @type errors: numpy array
472 @return: The Jacobian matrix with 'm' rows of function derivatives per 'n' columns of parameters.
473 @rtype: numpy array
474 """
475
476
477 r2eff = params[0]
478 i0 = params[1]
479
480
481 d_chi2_d_r2eff = 2.0 * i0 * times * ( -i0 * exp( -r2eff * times) + values) * exp( -r2eff * times ) / errors**2
482
483
484 d_chi2_d_i0 = - 2.0 * ( -i0 * exp( -r2eff * times) + values) * exp( -r2eff * times) / errors**2
485
486
487 jacobian_matrix_exp_chi2 = transpose(array( [d_chi2_d_r2eff, d_chi2_d_i0] ) )
488
489 return jacobian_matrix_exp_chi2
490
491
492 -def estimate_r2eff(method='minfx', min_algor='simplex', c_code=True, constraints=False, chi2_jacobian=False, spin_id=None, ftol=1e-15, xtol=1e-15, maxfev=10000000, factor=100.0, verbosity=1):
493 """Estimate r2eff and errors by exponential curve fitting with scipy.optimize.leastsq or minfx.
494
495 THIS IS ONLY FOR TESTING.
496
497 scipy.optimize.leastsq is a wrapper around MINPACK's lmdif and lmder algorithms.
498
499 MINPACK is a FORTRAN90 library which solves systems of nonlinear equations, or carries out the least squares minimization of the residual of a set of linear or nonlinear equations.
500
501 Errors are calculated by taking the square root of the reported co-variance.
502
503 This can be an huge time saving step, when performing model fitting in R1rho.
504 Errors of R2eff values, are normally estimated by time-consuming Monte-Carlo simulations.
505
506 Initial guess for the starting parameter x0 = [r2eff_est, i0_est], is by converting the exponential curve to a linear problem.
507 Then solving initial guess by linear least squares of: ln(Intensity[j]) = ln(i0) - time[j]* r2eff.
508
509
510 @keyword method: The method to minimise and estimate errors. Options are: 'minfx' or 'scipy.optimize.leastsq'.
511 @type method: string
512 @keyword min_algor: The minimisation algorithm
513 @type min_algor: string
514 @keyword c_code: If optimise with C code.
515 @type c_code: bool
516 @keyword constraints: If constraints should be used.
517 @type constraints: bool
518 @keyword chi2_jacobian: If the chi2 Jacobian should be used.
519 @type chi2_jacobian: bool
520 @keyword spin_id: The spin identification string.
521 @type spin_id: str
522 @keyword ftol: The function tolerance for the relative error desired in the sum of squares, parsed to leastsq.
523 @type ftol: float
524 @keyword xtol: The error tolerance for the relative error desired in the approximate solution, parsed to leastsq.
525 @type xtol: float
526 @keyword maxfev: The maximum number of function evaluations, parsed to leastsq. If zero, then 100*(N+1) is the maximum function calls. N is the number of elements in x0=[r2eff, i0].
527 @type maxfev: int
528 @keyword factor: The initial step bound, parsed to leastsq. It determines the initial step bound (''factor * || diag * x||''). Should be in the interval (0.1, 100).
529 @type factor: float
530 @keyword verbosity: The amount of information to print. The higher the value, the greater the verbosity.
531 @type verbosity: int
532 """
533
534
535 check_model_type(model=MODEL_R2EFF)
536
537
538 if not C_module_exp_fn and method == 'minfx':
539 raise RelaxError("Relaxation curve fitting is not available. Try compiling the C modules on your platform.")
540
541
542 E = Exp(verbosity=verbosity)
543 E.set_settings_leastsq(ftol=ftol, xtol=xtol, maxfev=maxfev, factor=factor)
544
545
546 precalc = True
547 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):
548
549 if not hasattr(cur_spin, 'peak_intensity_err'):
550 precalc = False
551 break
552
553
554 for id in cdp.spectrum_ids:
555 if id not in cur_spin.peak_intensity_err:
556 precalc = False
557 break
558
559
560 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):
561
562 spin_string = generate_spin_string(spin=cur_spin, mol_name=mol_name, res_num=resi, res_name=resn)
563
564
565 if E.verbosity >= 1:
566
567 top = 2
568 if E.verbosity >= 2:
569 top += 2
570 subsection(file=sys.stdout, text="Fitting with %s to: %s"%(method, spin_string), prespace=top)
571 if method == 'minfx':
572 subsection(file=sys.stdout, text="min_algor='%s', c_code=%s, constraints=%s, chi2_jacobian?=%s"%(min_algor, c_code, constraints, chi2_jacobian), prespace=0)
573
574
575 for exp_type, frq, offset, point, ei, mi, oi, di in loop_exp_frq_offset_point(return_indices=True):
576
577 param_key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point)
578
579
580 values = []
581 errors = []
582 times = []
583 for time in loop_time(exp_type=exp_type, frq=frq, offset=offset, point=point):
584 values.append(average_intensity(spin=cur_spin, exp_type=exp_type, frq=frq, offset=offset, point=point, time=time))
585 errors.append(average_intensity(spin=cur_spin, exp_type=exp_type, frq=frq, offset=offset, point=point, time=time, error=True))
586 times.append(time)
587
588
589 values = asarray(values)
590 errors = asarray(errors)
591 times = asarray(times)
592
593
594 E.setup_data(values=values, errors=errors, times=times)
595
596
597 if method == 'scipy.optimize.leastsq':
598
599 results = minimise_leastsq(E=E)
600
601 elif method == 'minfx':
602
603 E.set_settings_minfx(min_algor=min_algor, c_code=c_code, chi2_jacobian=chi2_jacobian, constraints=constraints)
604
605
606 results = minimise_minfx(E=E)
607 else:
608 raise RelaxError("Method for minimisation not known. Try setting: method='scipy.optimize.leastsq'.")
609
610
611 param_vector, param_vector_error, chi2, iter_count, f_count, g_count, h_count, warning = results
612
613
614 r2eff = param_vector[0]
615 i0 = param_vector[1]
616 r2eff_err = param_vector_error[0]
617 i0_err = param_vector_error[1]
618
619
620 disassemble_param_vector(param_vector=param_vector, spins=[cur_spin], key=param_key)
621
622
623 if not hasattr(cur_spin, 'r2eff_err'):
624 setattr(cur_spin, 'r2eff_err', deepcopy(getattr(cur_spin, 'r2eff')))
625 if not hasattr(cur_spin, 'i0_err'):
626 setattr(cur_spin, 'i0_err', deepcopy(getattr(cur_spin, 'i0')))
627
628
629 cur_spin.r2eff_err[param_key] = r2eff_err
630 cur_spin.i0_err[param_key] = i0_err
631
632
633 cur_spin.chi2 = chi2
634
635
636 cur_spin.f_count = f_count
637
638
639 cur_spin.warning = warning
640
641
642 print_strings = []
643 if E.verbosity >= 1:
644
645 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))
646 print_strings.append(point_info)
647
648 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)
649 print_strings.append(par_info)
650
651 if E.verbosity >= 2:
652 time_info = ', '.join(map(str, times))
653 print_strings.append('For time array: '+time_info+'.\n\n')
654
655
656 if len(print_strings) > 0:
657 for print_string in print_strings:
658 print(print_string),
659
660
662 """Estimate r2eff and errors by exponential curve fitting with scipy.optimize.leastsq.
663
664 @keyword E: The Exponential function class, which contain data and functions.
665 @type E: class
666 @return: Packed list with optimised parameter, estimated parameter error, chi2, iter_count, f_count, g_count, h_count, warning
667 @rtype: list
668 """
669
670
671 if not scipy_module:
672 raise RelaxError("scipy module is not available.")
673
674
675 x0 = E.estimate_x0_exp(times=E.times, values=E.values)
676
677
678 use_weights = True
679
680 if use_weights:
681 func = E.func_exp_weighted_residual
682
683 absolute_sigma = True
684 else:
685 func = E.func_exp_residual
686 absolute_sigma = False
687
688
689 args=(E.times, E.values, E.errors)
690
691
692 popt, pcov, infodict, errmsg, ier = leastsq(func=func, x0=x0, args=args, full_output=True, ftol=E.ftol, xtol=E.xtol, maxfev=E.maxfev, factor=E.factor)
693
694
695 if ier in [1, 2, 3, 4]:
696 warning = None
697 elif ier in [9]:
698 warn(RelaxWarning("%s." % errmsg))
699 warning = errmsg
700 elif ier in [0, 5, 6, 7, 8]:
701 raise RelaxError("scipy.optimize.leastsq raises following error: '%s'." % errmsg)
702
703
704 f_count = infodict['nfev']
705
706
707 fvec = infodict['fvec']
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724 chi2 = sum( fvec**2 )
725
726
727 N = len(E.values)
728
729 p = len(x0)
730
731
732 n = N - p
733
734
735 chi2_red = chi2 / n
736
737
738
739
740
741
742 if pcov is None:
743
744 pcov = zeros((len(popt), len(popt)), dtype=float)
745 pcov.fill(inf)
746 elif not absolute_sigma:
747 if N > p:
748 pcov = pcov * chi2_red
749 else:
750 pcov.fill(inf)
751
752
753 perr = sqrt(diag(pcov))
754
755
756 param_vector = popt
757 param_vector_error = perr
758
759 iter_count = 0
760 g_count = 0
761 h_count = 0
762
763
764 results = [param_vector, param_vector_error, chi2, iter_count, f_count, g_count, h_count, warning]
765
766
767 return results
768
769
771 """Estimate r2eff and errors by minimising with minfx.
772
773 @keyword E: The Exponential function class, which contain data and functions.
774 @type E: class
775 @return: Packed list with optimised parameter, parameter error set to 'inf', chi2, iter_count, f_count, g_count, h_count, warning
776 @rtype: list
777 """
778
779
780 if not C_module_exp_fn:
781 raise RelaxError("Relaxation curve fitting is not available. Try compiling the C modules on your platform.")
782
783
784 x0 = asarray( E.estimate_x0_exp(times=E.times, values=E.values) )
785
786 if E.c_code:
787
788
789
790 scaling_list = [1.0, 1.0]
791 model = Relax_fit_opt(model='exp', num_params=len(x0), values=E.values, errors=E.errors, relax_times=E.times, scaling_matrix=scaling_list)
792
793
794 t_func = model.func
795 t_dfunc = model.dfunc
796 t_d2func = model.d2func
797 args=()
798
799 else:
800
801
802 t_func = E.func_exp_chi2
803 t_dfunc = E.func_exp_chi2_grad
804 t_d2func = None
805
806 args=(E.times, E.values, E.errors)
807
808
809 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)
810
811
812 param_vector, chi2, iter_count, f_count, g_count, h_count, warning = results_minfx
813
814
815 r2eff, i0 = param_vector
816
817
818 if E.c_code == True:
819 if E.chi2_jacobian:
820
821 jacobian_matrix_exp = transpose(asarray( model.jacobian_chi2(param_vector) ) )
822 weights = ones(E.errors.shape)
823
824 else:
825
826 jacobian_matrix_exp = transpose(asarray( model.jacobian(param_vector) ) )
827 weights = 1. / E.errors**2
828
829 elif E.c_code == False:
830 if E.chi2_jacobian:
831
832 jacobian_matrix_exp = E.func_exp_chi2_grad_array(params=param_vector, times=E.times, values=E.values, errors=E.errors)
833 weights = ones(E.errors.shape)
834
835 else:
836
837 jacobian_matrix_exp = E.func_exp_grad(params=param_vector, times=E.times)
838 weights = 1. / E.errors**2
839
840 pcov = multifit_covar(J=jacobian_matrix_exp, weights=weights)
841
842
843 param_vector_error = sqrt(diag(pcov))
844
845
846 results = [param_vector, param_vector_error, chi2, iter_count, f_count, g_count, h_count, warning]
847
848
849 return results
850