1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17   
 18   
 19   
 20   
 21   
 22   
 23   
 24  """The model-free analysis optimisation functions.""" 
 25   
 26   
 27  from math import pi 
 28  from minfx.generic import generic_minimise 
 29  from minfx.grid import grid, grid_point_array 
 30  from numpy import array, dot, float64 
 31  from re import match 
 32   
 33   
 34  import lib.arg_check 
 35  from lib.errors import RelaxError, RelaxInfError, RelaxMultiVectorError, RelaxNaNError 
 36  from lib.float import isNaN, isInf 
 37  from lib.optimisation import test_grid_ops 
 38  from lib.physical_constants import return_gyromagnetic_ratio 
 39  from multi import Memo, Result_command, Slave_command 
 40  from pipe_control import pipes 
 41  from pipe_control.interatomic import return_interatom_list 
 42  from pipe_control.mol_res_spin import return_spin, return_spin_from_index, spin_loop 
 43  from specific_analyses.model_free.model import determine_model_type 
 44  from specific_analyses.model_free.parameters import assemble_param_vector, disassemble_param_vector 
 45  from target_functions.mf import Mf 
 46   
 47   
 48 -def disassemble_result(param_vector=None, func=None, iter=None, fc=None, gc=None, hc=None, warning=None, spin=None, sim_index=None, model_type=None, scaling=None, scaling_matrix=None): 
  49      """Disassemble the optimisation results. 
 50   
 51      @keyword param_vector:      The model-free parameter vector. 
 52      @type param_vector:         numpy array 
 53      @keyword func:              The optimised chi-squared value. 
 54      @type func:                 float 
 55      @keyword iter:              The number of optimisation steps required to find the minimum. 
 56      @type iter:                 int 
 57      @keyword fc:                The function count. 
 58      @type fc:                   int 
 59      @keyword gc:                The gradient count. 
 60      @type gc:                   int 
 61      @keyword hc:                The Hessian count. 
 62      @type hc:                   int 
 63      @keyword warning:           Any optimisation warnings. 
 64      @type warning:              str or None 
 65      @keyword spin:              The spin container. 
 66      @type spin:                 SpinContainer instance or None 
 67      @keyword sim_index:         The Monte Carlo simulation index. 
 68      @type sim_index:            int or None 
 69      @keyword model_type:        The model-free model type, one of 'mf', 'local_tm', 'diff', or 
 70                                  'all'. 
 71      @type model_type:           str 
 72      @keyword scaling:           If True, diagonal scaling is enabled during optimisation to 
 73                                  allow the problem to be better conditioned. 
 74      @type scaling:              bool 
 75      @keyword scaling_matrix:    The diagonal, square scaling matrix. 
 76      @type scaling_matrix:       numpy diagonal matrix 
 77      """ 
 78   
 79       
 80      if param_vector == None: 
 81          return 
 82   
 83       
 84      cdp = pipes.get_pipe() 
 85   
 86       
 87      if isInf(func): 
 88          raise RelaxInfError('chi-squared') 
 89   
 90       
 91      if isNaN(func): 
 92          raise RelaxNaNError('chi-squared') 
 93   
 94       
 95      if scaling: 
 96          param_vector = dot(scaling_matrix, param_vector) 
 97   
 98       
 99      if sim_index == None: 
100           
101          chi2 = None 
102          if (model_type == 'mf' or model_type == 'local_tm') and hasattr(cdp, 'chi2'): 
103              chi2 = spin.chi2 
104          if (model_type == 'diff' or model_type == 'all') and hasattr(cdp, 'chi2'): 
105              chi2 = cdp.chi2 
106   
107           
108          spin_text = '' 
109          if spin != None and hasattr(spin, '_spin_ids') and len(spin._spin_ids): 
110              spin_text = " for the spin '%s'" % spin._spin_ids[0] 
111   
112           
113          if chi2 != None and func >= chi2: 
114              print("Discarding the optimisation results%s, the optimised chi-squared value is higher than the current value (%s >= %s)." % (spin_text, func, chi2)) 
115   
116               
117              return 
118   
119           
120          else: 
121              print("Storing the optimisation results%s, the optimised chi-squared value is lower than the current value (%s < %s)." % (spin_text, func, chi2)) 
122   
123       
124      disassemble_param_vector(model_type, param_vector=param_vector, spin=spin, sim_index=sim_index) 
125   
126       
127      if sim_index != None: 
128           
129          if model_type == 'mf' or model_type == 'local_tm': 
130   
131               
132              spin.chi2_sim[sim_index] = func 
133   
134               
135              spin.iter_sim[sim_index] = iter 
136   
137               
138              spin.f_count_sim[sim_index] = fc 
139   
140               
141              spin.g_count_sim[sim_index] = gc 
142   
143               
144              spin.h_count_sim[sim_index] = hc 
145   
146               
147              spin.warning_sim[sim_index] = warning 
148   
149           
150          elif model_type == 'diff' or model_type == 'all': 
151               
152              cdp.chi2_sim[sim_index] = func 
153   
154               
155              cdp.iter_sim[sim_index] = iter 
156   
157               
158              cdp.f_count_sim[sim_index] = fc 
159   
160               
161              cdp.g_count_sim[sim_index] = gc 
162   
163               
164              cdp.h_count_sim[sim_index] = hc 
165   
166               
167              cdp.warning_sim[sim_index] = warning 
168   
169       
170      else: 
171           
172          if model_type == 'mf' or model_type == 'local_tm': 
173               
174              spin.chi2 = func 
175   
176               
177              spin.iter = iter 
178   
179               
180              spin.f_count = fc 
181   
182               
183              spin.g_count = gc 
184   
185               
186              spin.h_count = hc 
187   
188               
189              spin.warning = warning 
190   
191           
192          elif model_type == 'diff' or model_type == 'all': 
193               
194              cdp.chi2 = func 
195   
196               
197              cdp.iter = iter 
198   
199               
200              cdp.f_count = fc 
201   
202               
203              cdp.g_count = gc 
204   
205               
206              cdp.h_count = hc 
207   
208               
209              cdp.warning = warning 
 210   
211   
212 -def grid_search_config(num_params, spin=None, spin_id=None, lower=None, upper=None, inc=None, scaling_matrix=None, verbosity=1): 
 213      """Configure the grid search. 
214   
215      @param num_params:          The number of parameters in the model. 
216      @type num_params:           int 
217      @keyword spin:              The spin data container. 
218      @type spin:                 SpinContainer instance 
219      @keyword spin_id:           The spin identification string. 
220      @type spin_id:              str 
221      @keyword lower:             The lower bounds of the grid search which must be equal to the 
222                                  number of parameters in the model. 
223      @type lower:                array of numbers 
224      @keyword upper:             The upper bounds of the grid search which must be equal to the 
225                                  number of parameters in the model. 
226      @type upper:                array of numbers 
227      @keyword inc:               The increments for each dimension of the space for the grid 
228                                  search.  The number of elements in the array must equal to the 
229                                  number of parameters in the model. 
230      @type inc:                  array of int 
231      @keyword scaling_matrix:    The diagonal, square scaling matrix. 
232      @type scaling_matrix:       numpy diagonal matrix 
233      @keyword verbosity:         A flag specifying the amount of information to print.  The 
234                                  higher the value, the greater the verbosity. 
235      @type verbosity:            int 
236      """ 
237   
238       
239      test_grid_ops(lower=lower, upper=upper, inc=inc, n=num_params) 
240   
241       
242      if isinstance(inc, int): 
243          inc = [inc]*num_params 
244   
245       
246      if not lower: 
247           
248          lower = [] 
249          upper = [] 
250   
251           
252          model_type = determine_model_type() 
253   
254           
255          if model_type == 'diff' or model_type == 'all': 
256               
257              grid_search_diff_bounds(lower, upper) 
258   
259           
260          if model_type != 'diff': 
261               
262              if spin: 
263                  loop = [spin] 
264              else: 
265                  loop = spin_loop(spin_id) 
266   
267               
268              for spin in loop: 
269                   
270                  if not spin.select: 
271                      continue 
272   
273                   
274                  grid_search_spin_bounds(spin, lower, upper) 
275   
276       
277      lower_new = [] 
278      upper_new = [] 
279      for i in range(num_params): 
280          lower_new.append(lower[i] / scaling_matrix[i, i]) 
281          upper_new.append(upper[i] / scaling_matrix[i, i]) 
282   
283       
284      return inc, lower_new, upper_new 
 285   
286   
288      """Set up the default grid search bounds the diffusion tensor. 
289   
290      This method appends the default bounds to the lower and upper lists. 
291   
292      @param lower:       The lower bound list to append to. 
293      @type lower:        list 
294      @param upper:       The upper bound list to append to. 
295      @type upper:        list 
296      """ 
297   
298       
299      if cdp.diff_tensor.type == 'sphere': 
300          lower.append(1.0 * 1e-9) 
301          upper.append(12.0 * 1e-9) 
302   
303       
304      if cdp.diff_tensor.type == 'spheroid': 
305           
306          lower.append(1.0 * 1e-9) 
307          upper.append(12.0 * 1e-9) 
308   
309           
310          if cdp.diff_tensor.spheroid_type == 'prolate': 
311              lower.append(0.0) 
312              upper.append(1e7) 
313          elif cdp.diff_tensor.spheroid_type == 'oblate': 
314              lower.append(-1e7) 
315              upper.append(0.0) 
316          else: 
317              lower.append(-1e7) 
318              upper.append(1e7) 
319   
320           
321          lower.append(0.0) 
322          upper.append(pi) 
323   
324           
325          lower.append(0.0) 
326          upper.append(pi) 
327   
328       
329      elif cdp.diff_tensor.type == 'ellipsoid': 
330           
331          lower.append(1.0 * 1e-9) 
332          upper.append(12.0 * 1e-9) 
333   
334           
335          lower.append(0.0) 
336          upper.append(1e7) 
337   
338           
339          lower.append(0.0) 
340          upper.append(1.0) 
341   
342           
343          lower.append(0.0) 
344          upper.append(pi) 
345   
346           
347          lower.append(0.0) 
348          upper.append(pi) 
349   
350           
351          lower.append(0.0) 
352          upper.append(pi) 
 353   
354   
356      """Set up the default grid search bounds for a single spin. 
357   
358      This method appends the default bounds to the lower and upper lists.  The ordering of the 
359      lists in min_options matches that of the params list in the spin container. 
360   
361      @param spin:        A SpinContainer object. 
362      @type spin:         class instance 
363      @param lower:       The lower bound list to append to. 
364      @type lower:        list 
365      @param upper:       The upper bound list to append to. 
366      @type upper:        list 
367      """ 
368   
369       
370      for i in range(len(spin.params)): 
371           
372          if spin.params[i] == 'local_tm': 
373              lower.append(1.0 * 1e-9) 
374              upper.append(12.0 * 1e-9) 
375   
376           
377          elif match('s2', spin.params[i]): 
378              lower.append(0.0) 
379              upper.append(1.0) 
380   
381           
382          elif match('t', spin.params[i]): 
383              lower.append(0.0) 
384              upper.append(500.0 * 1e-12) 
385   
386           
387          elif spin.params[i] == 'rex': 
388              lower.append(0.0) 
389              upper.append(5.0 / (2.0 * pi * cdp.spectrometer_frq[cdp.ri_ids[0]])**2) 
390   
391           
392          elif spin.params[i] == 'r': 
393              lower.append(1.0 * 1e-10) 
394              upper.append(1.05 * 1e-10) 
395   
396           
397          elif spin.params[i] == 'csa': 
398              lower.append(-120 * 1e-6) 
399              upper.append(-200 * 1e-6) 
400   
401           
402          else: 
403              raise RelaxError("Unknown model-free parameter.") 
 404   
405   
406 -def minimise_data_setup(data_store, min_algor, num_data_sets, min_options, spin=None, sim_index=None): 
 407      """Set up all the data required for minimisation. 
408   
409      @param data_store:      A data storage container. 
410      @type data_store:       class instance 
411      @param min_algor:       The minimisation algorithm to use. 
412      @type min_algor:        str 
413      @param num_data_sets:   The number of data sets. 
414      @type num_data_sets:    int 
415      @param min_options:     The minimisation options array. 
416      @type min_options:      list 
417      @keyword spin:          The spin data container. 
418      @type spin:             SpinContainer instance 
419      @keyword sim_index:     The optional MC simulation index. 
420      @type sim_index:        int 
421      @return:                An insane tuple.  The full tuple is (ri_data, ri_data_err, equations, param_types, param_values, r, csa, num_frq, frq, num_ri, remap_table, noe_r1_table, ri_types, num_params, xh_unit_vectors, diff_type, diff_params) 
422      @rtype:                 tuple 
423      """ 
424   
425       
426      data_store.ri_data = [] 
427      data_store.ri_data_err = [] 
428      data_store.equations = [] 
429      data_store.param_types = [] 
430      data_store.param_values = None 
431      data_store.r = [] 
432      data_store.csa = [] 
433      data_store.num_frq = [] 
434      data_store.frq = [] 
435      data_store.num_ri = [] 
436      data_store.remap_table = [] 
437      data_store.noe_r1_table = [] 
438      data_store.ri_types = [] 
439      data_store.gx = [] 
440      data_store.gh = [] 
441      data_store.num_params = [] 
442      data_store.xh_unit_vectors = [] 
443      if data_store.model_type == 'local_tm': 
444          data_store.mf_params = [] 
445      elif data_store.model_type == 'diff': 
446          data_store.param_values = [] 
447   
448       
449      if min_algor == 'back_calc': 
450           
451          data_store.ri_data = [0.0] 
452          data_store.ri_data_err = [0.000001] 
453          data_store.equations = [spin.equation] 
454          data_store.param_types = [spin.params] 
455          data_store.csa = [spin.csa] 
456          data_store.num_frq = [1] 
457          data_store.frq = [[min_options[3]]] 
458          data_store.num_ri = [1] 
459          data_store.remap_table = [[0]] 
460          data_store.noe_r1_table = [[None]] 
461          data_store.ri_types = [[min_options[2]]] 
462          data_store.gx = [return_gyromagnetic_ratio(spin.isotope)] 
463   
464           
465          interatoms = return_interatom_list(data_store.spin_id) 
466          for i in range(len(interatoms)): 
467               
468              if not interatoms[i].dipole_pair: 
469                  continue 
470   
471               
472              if data_store.spin_id != interatoms[i].spin_id1: 
473                  spin_id2 = interatoms[i].spin_id1 
474              else: 
475                  spin_id2 = interatoms[i].spin_id2 
476              spin2 = return_spin(spin_id2) 
477   
478               
479              data_store.r = [interatoms[i].r] 
480              data_store.gh = [return_gyromagnetic_ratio(spin2.isotope)] 
481              if data_store.model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere': 
482                  data_store.xh_unit_vectors = [interatoms[i].vector] 
483              else: 
484                  data_store.xh_unit_vectors = [None] 
485   
486           
487          data_store.num_params = [len(spin.params)] 
488   
489       
490      for j in range(num_data_sets): 
491           
492          if data_store.model_type == 'diff' or data_store.model_type == 'all': 
493              spin_index = j 
494              spin, data_store.spin_id = return_spin_from_index(global_index=spin_index, return_spin_id=True) 
495   
496           
497          if not spin.select: 
498              continue 
499   
500           
501          if not hasattr(spin, 'ri_data') or not hasattr(spin, 'ri_data_err'): 
502              continue 
503   
504           
505          for ri_id in cdp.ri_ids: 
506               
507              if not ri_id in spin.ri_data_err: 
508                  continue 
509   
510               
511              err = spin.ri_data_err[ri_id] 
512   
513               
514              if err != None and err == 0.0: 
515                  raise RelaxError("Zero error for spin '%s' for the relaxation data ID '%s', minimisation not possible." % (data_store.spin_id, ri_id)) 
516              elif err != None and err < 0.0: 
517                  raise RelaxError("Negative error of %s for spin '%s' for the relaxation data ID '%s', minimisation not possible." % (err, data_store.spin_id, ri_id)) 
518   
519           
520          data = relax_data_opt_structs(spin, sim_index=sim_index) 
521   
522           
523          data_store.ri_data.append(data[0]) 
524          data_store.ri_data_err.append(data[1]) 
525          data_store.num_frq.append(data[2]) 
526          data_store.num_ri.append(data[3]) 
527          data_store.ri_types.append(data[4]) 
528          data_store.frq.append(data[5]) 
529          data_store.remap_table.append(data[6]) 
530          data_store.noe_r1_table.append(data[7]) 
531          if sim_index == None or data_store.model_type == 'diff': 
532              data_store.csa.append(spin.csa) 
533          else: 
534              data_store.csa.append(spin.csa_sim[sim_index]) 
535   
536           
537          data_store.equations.append(spin.equation) 
538          data_store.param_types.append(spin.params) 
539          data_store.gx.append(return_gyromagnetic_ratio(spin.isotope)) 
540   
541           
542          interatoms = return_interatom_list(data_store.spin_id) 
543          for i in range(len(interatoms)): 
544               
545              if not interatoms[i].dipole_pair: 
546                  continue 
547   
548               
549              if data_store.spin_id != interatoms[i].spin_id1: 
550                  spin_id2 = interatoms[i].spin_id1 
551              else: 
552                  spin_id2 = interatoms[i].spin_id2 
553              spin2 = return_spin(spin_id2) 
554   
555               
556              data_store.gh.append(return_gyromagnetic_ratio(spin2.isotope)) 
557              if sim_index == None or data_store.model_type == 'diff' or not hasattr(interatoms[i], 'r_sim'): 
558                  data_store.r.append(interatoms[i].r) 
559              else: 
560                  data_store.r.append(interatoms[i].r_sim[sim_index]) 
561   
562               
563              if data_store.model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere': 
564                   
565                  if lib.arg_check.is_num_list(interatoms[i].vector[0], raise_error=False): 
566                      raise RelaxMultiVectorError(data_store.spin_id) 
567   
568                   
569                  data_store.xh_unit_vectors.append(interatoms[i].vector) 
570   
571               
572              else: 
573                  data_store.xh_unit_vectors.append(None) 
574   
575               
576              break 
577   
578           
579          if data_store.model_type == 'local_tm': 
580              pass 
581   
582           
583          data_store.num_params.append(len(spin.params)) 
584   
585           
586          if data_store.model_type == 'diff': 
587              data_store.param_values.append(assemble_param_vector(model_type='mf')) 
588   
589       
590      for k in range(len(data_store.ri_data)): 
591          data_store.ri_data[k] = array(data_store.ri_data[k], float64) 
592          data_store.ri_data_err[k] = array(data_store.ri_data_err[k], float64) 
593   
594       
595      if data_store.model_type == 'local_tm': 
596          data_store.diff_type = 'sphere' 
597      else: 
598          data_store.diff_type = cdp.diff_tensor.type 
599   
600       
601      data_store.diff_params = None 
602      if data_store.model_type == 'mf': 
603           
604          if data_store.diff_type == 'sphere': 
605              data_store.diff_params = [cdp.diff_tensor.tm] 
606   
607           
608          elif data_store.diff_type == 'spheroid': 
609              data_store.diff_params = [cdp.diff_tensor.tm, cdp.diff_tensor.Da, cdp.diff_tensor.theta, cdp.diff_tensor.phi] 
610   
611           
612          elif data_store.diff_type == 'ellipsoid': 
613              data_store.diff_params = [cdp.diff_tensor.tm, cdp.diff_tensor.Da, cdp.diff_tensor.Dr, cdp.diff_tensor.alpha, cdp.diff_tensor.beta, cdp.diff_tensor.gamma] 
614      elif min_algor == 'back_calc' and data_store.model_type == 'local_tm': 
615           
616          data_store.diff_params = [spin.local_tm] 
 617   
618   
620      """Package the relaxation data into the data structures used for optimisation. 
621   
622      @param spin:        The spin container to extract the data from. 
623      @type spin:         SpinContainer instance 
624      @keyword sim_index: The optional MC simulation index. 
625      @type sim_index:    int 
626      @return:            The structures ri_data, ri_data_err, num_frq, num_ri, ri_ids, frq, remap_table, noe_r1_table. 
627      @rtype:             tuple 
628      """ 
629   
630       
631      ri_data = [] 
632      ri_data_err = [] 
633      ri_labels = [] 
634      frq = [] 
635      remap_table = [] 
636      noe_r1_table = [] 
637   
638       
639      for ri_id in cdp.ri_ids: 
640           
641          if ri_id not in spin.ri_data: 
642              continue 
643   
644           
645          if sim_index == None: 
646              data = spin.ri_data[ri_id] 
647          else: 
648              data = spin.ri_data_sim[ri_id][sim_index] 
649   
650           
651          err = spin.ri_data_err[ri_id] 
652   
653           
654          if data == None or err == None: 
655              continue 
656   
657           
658          ri_data.append(data) 
659          ri_data_err.append(err) 
660   
661           
662          ri_labels.append(cdp.ri_type[ri_id]) 
663   
664           
665          if cdp.spectrometer_frq[ri_id] not in frq: 
666              frq.append(cdp.spectrometer_frq[ri_id]) 
667   
668           
669          remap_table.append(frq.index(cdp.spectrometer_frq[ri_id])) 
670   
671           
672          noe_r1_table.append(None) 
673   
674       
675      num_ri = len(ri_data) 
676   
677       
678      for i in range(num_ri): 
679           
680          if cdp.ri_type[cdp.ri_ids[i]] == 'NOE': 
681              for j in range(num_ri): 
682                  if cdp.ri_type[cdp.ri_ids[j]] == 'R1' and cdp.spectrometer_frq[cdp.ri_ids[i]] == cdp.spectrometer_frq[cdp.ri_ids[j]]: 
683                      noe_r1_table[i] = j 
684   
685       
686      return ri_data, ri_data_err, len(frq), num_ri, ri_labels, frq, remap_table, noe_r1_table 
 687   
688   
690      """Reset all the minimisation statistics. 
691   
692      All global and spin specific values will be set to None. 
693      """ 
694   
695       
696      if hasattr(cdp, 'chi2'): 
697          cdp.chi2 = None 
698          cdp.iter = None 
699          cdp.f_count = None 
700          cdp.g_count = None 
701          cdp.h_count = None 
702          cdp.warning = None 
703   
704       
705      for spin in spin_loop(): 
706          if hasattr(spin, 'chi2'): 
707              spin.chi2 = None 
708              spin.iter = None 
709              spin.f_count = None 
710              spin.g_count = None 
711              spin.h_count = None 
712              spin.warning = None 
 713   
714   
716      """Print out some header text for the spin. 
717   
718      @param spin_id:     The spin ID string. 
719      @type spin_id:      str 
720      @param verbosity:   The amount of information to print.  The higher the value, the greater the verbosity. 
721      @type verbosity:    int 
722      """ 
723   
724       
725      if verbosity >= 2: 
726          print("\n\n") 
727   
728       
729      string = "Fitting to spin " + repr(spin_id) 
730      print("\n\n" + string) 
731      print(len(string) * '~') 
 732   
733   
734   
736      """The model-free memo class. 
737   
738      Not quite a momento so a memo. 
739      """ 
740   
741 -    def __init__(self, model_free=None, model_type=None, spin=None, sim_index=None, scaling=None, scaling_matrix=None): 
 742          """Initialise the model-free memo class. 
743   
744          This memo stores the model-free class instance so that the disassemble_result() method can be called to store the optimisation results.  The other args are those required by this method but not generated through optimisation. 
745   
746          @keyword model_free:        The model-free class instance. 
747          @type model_free:           specific_analyses.model_free.Model_free instance 
748          @keyword spin:              The spin data container.  If this argument is supplied, then the spin_id argument will be ignored. 
749          @type spin:                 SpinContainer instance 
750          @keyword sim_index:         The optional MC simulation index. 
751          @type sim_index:            int 
752          @keyword scaling:           If True, diagonal scaling is enabled. 
753          @type scaling:              bool 
754          @keyword scaling_matrix:    The diagonal, square scaling matrix. 
755          @type scaling_matrix:       numpy diagonal matrix 
756          """ 
757   
758           
759          super(MF_memo, self).__init__() 
760   
761           
762          self.model_free = model_free 
763          self.model_type = model_type 
764          self.spin = spin 
765          self.sim_index = sim_index 
766          self.scaling = scaling 
767          self.scaling_matrix = scaling_matrix 
  768   
769   
770   
772      """Command class for standard model-free minimisation.""" 
773   
779   
780   
782          """Model-free optimisation. 
783   
784          @return:    The optimisation results consisting of the parameter vector, function value, iteration count, function count, gradient count, Hessian count, and warnings. 
785          @rtype:     tuple of numpy array, float, int, int, int, int, str 
786          """ 
787   
788           
789          results = generic_minimise(func=self.mf.func, dfunc=self.mf.dfunc, d2func=self.mf.d2func, args=(), x0=self.opt_params.param_vector, min_algor=self.opt_params.min_algor, min_options=self.opt_params.min_options, func_tol=self.opt_params.func_tol, grad_tol=self.opt_params.grad_tol, maxiter=self.opt_params.max_iterations, A=self.opt_params.A, b=self.opt_params.b, full_output=True, print_flag=self.opt_params.verbosity) 
790   
791           
792          return results 
 793   
794   
795 -    def run(self, processor, completed): 
 796          """Setup and perform the model-free optimisation.""" 
797   
798           
799          self.mf = Mf(init_params=self.opt_params.param_vector, model_type=self.data.model_type, diff_type=self.data.diff_type, diff_params=self.data.diff_params, scaling_matrix=self.data.scaling_matrix, num_spins=self.data.num_spins, equations=self.data.equations, param_types=self.data.param_types, param_values=self.data.param_values, relax_data=self.data.ri_data, errors=self.data.ri_data_err, bond_length=self.data.r, csa=self.data.csa, num_frq=self.data.num_frq, frq=self.data.frq, num_ri=self.data.num_ri, remap_table=self.data.remap_table, noe_r1_table=self.data.noe_r1_table, ri_labels=self.data.ri_types, gx=self.data.gx, gh=self.data.gh, h_bar=self.data.h_bar, mu0=self.data.mu0, num_params=self.data.num_params, vectors=self.data.xh_unit_vectors) 
800   
801           
802          if self.opt_params.verbosity >= 1 and (self.data.model_type == 'mf' or self.data.model_type == 'local_tm'): 
803              spin_print(self.data.spin_id, self.opt_params.verbosity) 
804   
805           
806          results = self.optimise() 
807   
808           
809          param_vector, func, iter, fc, gc, hc, warning = results 
810   
811          processor.return_object(MF_result_command(processor, self.memo_id, param_vector, func, iter, fc, gc, hc, warning, completed=False)) 
 812   
813   
815          """Store all the data required for model-free optimisation. 
816   
817          @param data:        The data used to initialise the model-free target function class. 
818          @type data:         class instance 
819          @param opt_params:  The parameters and data required for optimisation using minfx. 
820          @type opt_params:   class instance 
821          """ 
822   
823           
824          self.data = data 
825          self.opt_params = opt_params 
  826   
827   
828   
830      """Command class for the model-free grid search.""" 
831   
837   
838   
840          """Model-free grid search. 
841   
842          @return:    The optimisation results consisting of the parameter vector, function value, iteration count, function count, gradient count, Hessian count, and warnings. 
843          @rtype:     tuple of numpy array, float, int, int, int, int, str 
844          """ 
845   
846           
847          if not hasattr(self.opt_params, 'subdivision'): 
848              results = grid(func=self.mf.func, args=(), num_incs=self.opt_params.inc, lower=self.opt_params.lower, upper=self.opt_params.upper, A=self.opt_params.A, b=self.opt_params.b, verbosity=self.opt_params.verbosity) 
849   
850           
851          else: 
852              results = grid_point_array(func=self.mf.func, args=(), points=self.opt_params.subdivision, verbosity=self.opt_params.verbosity) 
853   
854           
855          param_vector, func, iter, warning = results 
856          fc = iter 
857          gc = 0.0 
858          hc = 0.0 
859   
860           
861          return param_vector, func, iter, fc, gc, hc, warning 
  862   
863   
864   
866      """Class for processing the model-free results.""" 
867   
868 -    def __init__(self, processor, memo_id, param_vector, func, iter, fc, gc, hc, warning, completed): 
 883   
884   
885 -    def run(self, processor, memo): 
 886          """Disassemble the model-free optimisation results. 
887   
888          @param processor:   Unused! 
889          @type processor:    None 
890          @param memo:        The model-free memo. 
891          @type memo:         memo 
892          """ 
893   
894           
895          disassemble_result(param_vector=self.param_vector, func=self.func, iter=self.iter, fc=self.fc, gc=self.gc, hc=self.hc, warning=self.warning, spin=memo.spin, sim_index=memo.sim_index, model_type=memo.model_type, scaling=memo.scaling, scaling_matrix=memo.scaling_matrix) 
  896