Package specific_analyses :: Package model_free :: Module optimisation
[hide private]
[frames] | no frames]

Source Code for Module specific_analyses.model_free.optimisation

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2003-2015 Edward d'Auvergne                                   # 
  4  # Copyright (C) 2007 Gary S Thompson (https://gna.org/users/varioustoxins)    # 
  5  #                                                                             # 
  6  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  7  #                                                                             # 
  8  # This program is free software: you can redistribute it and/or modify        # 
  9  # it under the terms of the GNU General Public License as published by        # 
 10  # the Free Software Foundation, either version 3 of the License, or           # 
 11  # (at your option) any later version.                                         # 
 12  #                                                                             # 
 13  # This program is distributed in the hope that it will be useful,             # 
 14  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 16  # GNU General Public License for more details.                                # 
 17  #                                                                             # 
 18  # You should have received a copy of the GNU General Public License           # 
 19  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 20  #                                                                             # 
 21  ############################################################################### 
 22   
 23  # Module docstring. 
 24  """The model-free analysis optimisation functions.""" 
 25   
 26  # Python module imports. 
 27  from minfx.generic import generic_minimise 
 28  from minfx.grid import grid, grid_point_array 
 29  from numpy import array, dot, float64 
 30  import sys 
 31   
 32  # relax module imports. 
 33  import lib.arg_check 
 34  from lib.errors import RelaxError, RelaxInfError, RelaxMultiVectorError, RelaxNaNError 
 35  from lib.float import isNaN, isInf 
 36  from lib.periodic_table import periodic_table 
 37  from lib.text.sectioning import subsection 
 38  from multi import Memo, Result_command, Slave_command 
 39  from pipe_control import pipes 
 40  from pipe_control.interatomic import return_interatom_list 
 41  from pipe_control.mol_res_spin import return_spin, return_spin_from_index 
 42  from specific_analyses.model_free.parameters import assemble_param_vector, disassemble_param_vector 
 43  from target_functions.mf import Mf 
 44   
 45   
46 -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_matrix=None):
47 """Disassemble the optimisation results. 48 49 @keyword param_vector: The model-free parameter vector. 50 @type param_vector: numpy array 51 @keyword func: The optimised chi-squared value. 52 @type func: float 53 @keyword iter: The number of optimisation steps required to find the minimum. 54 @type iter: int 55 @keyword fc: The function count. 56 @type fc: int 57 @keyword gc: The gradient count. 58 @type gc: int 59 @keyword hc: The Hessian count. 60 @type hc: int 61 @keyword warning: Any optimisation warnings. 62 @type warning: str or None 63 @keyword spin: The spin container. 64 @type spin: SpinContainer instance or None 65 @keyword sim_index: The Monte Carlo simulation index. 66 @type sim_index: int or None 67 @keyword model_type: The model-free model type, one of 'mf', 'local_tm', 'diff', or 68 'all'. 69 @type model_type: str 70 @keyword scaling_matrix: The diagonal, square scaling matrix. 71 @type scaling_matrix: numpy diagonal matrix 72 """ 73 74 # No result. 75 if param_vector is None: 76 return 77 78 # Alias the current data pipe. 79 cdp = pipes.get_pipe() 80 81 # Catch infinite chi-squared values. 82 if isInf(func): 83 raise RelaxInfError('chi-squared') 84 85 # Catch chi-squared values of NaN. 86 if isNaN(func): 87 raise RelaxNaNError('chi-squared') 88 89 # Scaling. 90 if scaling_matrix is not None: 91 param_vector = dot(scaling_matrix, param_vector) 92 93 # Check if the chi-squared value is lower. This allows for a parallelised grid search! 94 if sim_index == None: 95 # Get the correct value. 96 chi2 = None 97 if (model_type == 'mf' or model_type == 'local_tm') and hasattr(cdp, 'chi2'): 98 chi2 = spin.chi2 99 if (model_type == 'diff' or model_type == 'all') and hasattr(cdp, 'chi2'): 100 chi2 = cdp.chi2 101 102 # Spin text. 103 spin_text = '' 104 if spin != None and hasattr(spin, '_spin_ids') and len(spin._spin_ids): 105 spin_text = " for the spin '%s'" % spin._spin_ids[0] 106 107 # No improvement. 108 if chi2 != None and func >= chi2: 109 print("Discarding the optimisation results%s, the optimised chi-squared value is higher than the current value (%s >= %s)." % (spin_text, func, chi2)) 110 111 # Exit! 112 return 113 114 # New minimum. 115 else: 116 print("Storing the optimisation results%s, the optimised chi-squared value is lower than the current value (%s < %s)." % (spin_text, func, chi2)) 117 118 # Disassemble the parameter vector. 119 disassemble_param_vector(model_type, param_vector=param_vector, spin=spin, sim_index=sim_index) 120 121 # Monte Carlo minimisation statistics. 122 if sim_index != None: 123 # Sequence specific minimisation statistics. 124 if model_type == 'mf' or model_type == 'local_tm': 125 126 # Chi-squared statistic. 127 spin.chi2_sim[sim_index] = func 128 129 # Iterations. 130 spin.iter_sim[sim_index] = iter 131 132 # Function evaluations. 133 spin.f_count_sim[sim_index] = fc 134 135 # Gradient evaluations. 136 spin.g_count_sim[sim_index] = gc 137 138 # Hessian evaluations. 139 spin.h_count_sim[sim_index] = hc 140 141 # Warning. 142 spin.warning_sim[sim_index] = warning 143 144 # Global minimisation statistics. 145 elif model_type == 'diff' or model_type == 'all': 146 # Chi-squared statistic. 147 cdp.chi2_sim[sim_index] = func 148 149 # Iterations. 150 cdp.iter_sim[sim_index] = iter 151 152 # Function evaluations. 153 cdp.f_count_sim[sim_index] = fc 154 155 # Gradient evaluations. 156 cdp.g_count_sim[sim_index] = gc 157 158 # Hessian evaluations. 159 cdp.h_count_sim[sim_index] = hc 160 161 # Warning. 162 cdp.warning_sim[sim_index] = warning 163 164 # Normal statistics. 165 else: 166 # Sequence specific minimisation statistics. 167 if model_type == 'mf' or model_type == 'local_tm': 168 # Chi-squared statistic. 169 spin.chi2 = func 170 171 # Iterations. 172 spin.iter = iter 173 174 # Function evaluations. 175 spin.f_count = fc 176 177 # Gradient evaluations. 178 spin.g_count = gc 179 180 # Hessian evaluations. 181 spin.h_count = hc 182 183 # Warning. 184 spin.warning = warning 185 186 # Global minimisation statistics. 187 elif model_type == 'diff' or model_type == 'all': 188 # Chi-squared statistic. 189 cdp.chi2 = func 190 191 # Iterations. 192 cdp.iter = iter 193 194 # Function evaluations. 195 cdp.f_count = fc 196 197 # Gradient evaluations. 198 cdp.g_count = gc 199 200 # Hessian evaluations. 201 cdp.h_count = hc 202 203 # Warning. 204 cdp.warning = warning
205 206
207 -def minimise_data_setup(data_store, min_algor, num_data_sets, min_options, spin=None, sim_index=None):
208 """Set up all the data required for minimisation. 209 210 @param data_store: A data storage container. 211 @type data_store: class instance 212 @param min_algor: The minimisation algorithm to use. 213 @type min_algor: str 214 @param num_data_sets: The number of data sets. 215 @type num_data_sets: int 216 @param min_options: The minimisation options array. 217 @type min_options: list 218 @keyword spin: The spin data container. 219 @type spin: SpinContainer instance 220 @keyword sim_index: The optional MC simulation index. 221 @type sim_index: int 222 @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) 223 @rtype: tuple 224 """ 225 226 # Initialise the data structures for the model-free function. 227 data_store.ri_data = [] 228 data_store.ri_data_err = [] 229 data_store.equations = [] 230 data_store.param_types = [] 231 data_store.param_values = None 232 data_store.r = [] 233 data_store.csa = [] 234 data_store.num_frq = [] 235 data_store.frq = [] 236 data_store.num_ri = [] 237 data_store.remap_table = [] 238 data_store.noe_r1_table = [] 239 data_store.ri_types = [] 240 data_store.gx = [] 241 data_store.gh = [] 242 data_store.num_params = [] 243 data_store.xh_unit_vectors = [] 244 if data_store.model_type == 'local_tm': 245 data_store.mf_params = [] 246 elif data_store.model_type == 'diff': 247 data_store.param_values = [] 248 249 # Set up the data for the back_calc function. 250 if min_algor == 'back_calc': 251 # The spin data. 252 data_store.ri_data = [0.0] 253 data_store.ri_data_err = [0.000001] 254 data_store.equations = [spin.equation] 255 data_store.param_types = [spin.params] 256 data_store.csa = [spin.csa] 257 data_store.num_frq = [1] 258 data_store.frq = [[min_options[3]]] 259 data_store.num_ri = [1] 260 data_store.remap_table = [[0]] 261 data_store.noe_r1_table = [[None]] 262 data_store.ri_types = [[min_options[2]]] 263 data_store.gx = [periodic_table.gyromagnetic_ratio(spin.isotope)] 264 265 # The interatomic data. 266 interatoms = return_interatom_list(data_store.spin_id) 267 for i in range(len(interatoms)): 268 # No relaxation mechanism. 269 if not interatoms[i].dipole_pair: 270 continue 271 272 # The surrounding spins. 273 if data_store.spin_id != interatoms[i].spin_id1: 274 spin_id2 = interatoms[i].spin_id1 275 else: 276 spin_id2 = interatoms[i].spin_id2 277 spin2 = return_spin(spin_id2) 278 279 # The data. 280 data_store.r = [interatoms[i].r] 281 data_store.gh = [periodic_table.gyromagnetic_ratio(spin2.isotope)] 282 if data_store.model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere': 283 data_store.xh_unit_vectors = [interatoms[i].vector] 284 else: 285 data_store.xh_unit_vectors = [None] 286 287 # Count the number of model-free parameters for the spin index. 288 data_store.num_params = [len(spin.params)] 289 290 # Loop over the number of data sets. 291 for j in range(num_data_sets): 292 # Set the spin index and get the spin, if not already set. 293 if data_store.model_type == 'diff' or data_store.model_type == 'all': 294 spin_index = j 295 spin, data_store.spin_id = return_spin_from_index(global_index=spin_index, return_spin_id=True) 296 297 # Skip deselected spins. 298 if not spin.select: 299 continue 300 301 # Skip spins where there is no data or errors. 302 if not hasattr(spin, 'ri_data') or not hasattr(spin, 'ri_data_err'): 303 continue 304 305 # Make sure that the errors are strictly positive numbers. 306 for ri_id in cdp.ri_ids: 307 # Skip missing data. 308 if not ri_id in spin.ri_data_err: 309 continue 310 311 # Alias. 312 err = spin.ri_data_err[ri_id] 313 314 # Checks. 315 if err != None and err == 0.0: 316 raise RelaxError("Zero error for spin '%s' for the relaxation data ID '%s', minimisation not possible." % (data_store.spin_id, ri_id)) 317 elif err != None and err < 0.0: 318 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)) 319 320 # The relaxation data optimisation structures. 321 data = relax_data_opt_structs(spin, sim_index=sim_index) 322 323 # Append the data. 324 data_store.ri_data.append(data[0]) 325 data_store.ri_data_err.append(data[1]) 326 data_store.num_frq.append(data[2]) 327 data_store.num_ri.append(data[3]) 328 data_store.ri_types.append(data[4]) 329 data_store.frq.append(data[5]) 330 data_store.remap_table.append(data[6]) 331 data_store.noe_r1_table.append(data[7]) 332 if sim_index == None or data_store.model_type == 'diff': 333 data_store.csa.append(spin.csa) 334 else: 335 data_store.csa.append(spin.csa_sim[sim_index]) 336 337 # Repackage the spin data. 338 data_store.equations.append(spin.equation) 339 data_store.param_types.append(spin.params) 340 data_store.gx.append(periodic_table.gyromagnetic_ratio(spin.isotope)) 341 342 # Repackage the interatomic data. 343 interatoms = return_interatom_list(data_store.spin_id) 344 for i in range(len(interatoms)): 345 # No relaxation mechanism. 346 if not interatoms[i].dipole_pair: 347 continue 348 349 # The surrounding spins. 350 if data_store.spin_id != interatoms[i].spin_id1: 351 spin_id2 = interatoms[i].spin_id1 352 else: 353 spin_id2 = interatoms[i].spin_id2 354 spin2 = return_spin(spin_id2) 355 356 # The data. 357 data_store.gh.append(periodic_table.gyromagnetic_ratio(spin2.isotope)) 358 if sim_index == None or data_store.model_type == 'diff' or not hasattr(interatoms[i], 'r_sim'): 359 data_store.r.append(interatoms[i].r) 360 else: 361 data_store.r.append(interatoms[i].r_sim[sim_index]) 362 363 # Vectors. 364 if data_store.model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere': 365 # Check that this is a single vector! 366 if lib.arg_check.is_num_list(interatoms[i].vector[0], raise_error=False): 367 raise RelaxMultiVectorError(data_store.spin_id) 368 369 # Store the vector. 370 data_store.xh_unit_vectors.append(interatoms[i].vector) 371 372 # No vector. 373 else: 374 data_store.xh_unit_vectors.append(None) 375 376 # Stop - only one mechanism is current supported. 377 break 378 379 # Model-free parameter values. 380 if data_store.model_type == 'local_tm': 381 pass 382 383 # Count the number of model-free parameters for the spin index. 384 data_store.num_params.append(len(spin.params)) 385 386 # Repackage the parameter values for minimising just the diffusion tensor parameters. 387 if data_store.model_type == 'diff': 388 data_store.param_values.append(assemble_param_vector(model_type='mf')) 389 390 # Convert to numpy arrays. 391 for k in range(len(data_store.ri_data)): 392 data_store.ri_data[k] = array(data_store.ri_data[k], float64) 393 data_store.ri_data_err[k] = array(data_store.ri_data_err[k], float64) 394 395 # Diffusion tensor type. 396 if data_store.model_type == 'local_tm': 397 data_store.diff_type = 'sphere' 398 else: 399 data_store.diff_type = cdp.diff_tensor.type 400 401 # Package the diffusion tensor parameters. 402 data_store.diff_params = None 403 if data_store.model_type == 'mf': 404 # Spherical diffusion. 405 if data_store.diff_type == 'sphere': 406 data_store.diff_params = [cdp.diff_tensor.tm] 407 408 # Spheroidal diffusion. 409 elif data_store.diff_type == 'spheroid': 410 data_store.diff_params = [cdp.diff_tensor.tm, cdp.diff_tensor.Da, cdp.diff_tensor.theta, cdp.diff_tensor.phi] 411 412 # Ellipsoidal diffusion. 413 elif data_store.diff_type == 'ellipsoid': 414 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] 415 elif min_algor == 'back_calc' and data_store.model_type == 'local_tm': 416 # Spherical diffusion. 417 data_store.diff_params = [spin.local_tm]
418 419
420 -def relax_data_opt_structs(spin, sim_index=None):
421 """Package the relaxation data into the data structures used for optimisation. 422 423 @param spin: The spin container to extract the data from. 424 @type spin: SpinContainer instance 425 @keyword sim_index: The optional MC simulation index. 426 @type sim_index: int 427 @return: The structures ri_data, ri_data_err, num_frq, num_ri, ri_ids, frq, remap_table, noe_r1_table. 428 @rtype: tuple 429 """ 430 431 # Initialise the data. 432 ri_data = [] 433 ri_data_err = [] 434 ri_labels = [] 435 frq = [] 436 remap_table = [] 437 noe_r1_table = [] 438 439 # Loop over the relaxation data. 440 for ri_id in cdp.ri_ids: 441 # Skip missing data. 442 if ri_id not in spin.ri_data: 443 continue 444 445 # The Rx data. 446 if sim_index == None: 447 data = spin.ri_data[ri_id] 448 else: 449 data = spin.ri_data_sim[ri_id][sim_index] 450 451 # The errors. 452 err = spin.ri_data_err[ri_id] 453 454 # Missing data, so don't add it. 455 if data == None or err == None: 456 continue 457 458 # Append the data and error. 459 ri_data.append(data) 460 ri_data_err.append(err) 461 462 # The labels. 463 ri_labels.append(cdp.ri_type[ri_id]) 464 465 # The frequencies. 466 if cdp.spectrometer_frq[ri_id] not in frq: 467 frq.append(cdp.spectrometer_frq[ri_id]) 468 469 # The remap table. 470 remap_table.append(frq.index(cdp.spectrometer_frq[ri_id])) 471 472 # The NOE to R1 mapping table. 473 noe_r1_table.append(None) 474 475 # The number of data sets. 476 num_ri = len(ri_data) 477 478 # Fill the NOE to R1 mapping table. 479 for i in range(num_ri): 480 # If the data corresponds to 'NOE', try to find if the corresponding R1 data. 481 if cdp.ri_type[cdp.ri_ids[i]] == 'NOE': 482 for j in range(num_ri): 483 if cdp.ri_type[cdp.ri_ids[j]] == 'R1' and cdp.spectrometer_frq[cdp.ri_ids[i]] == cdp.spectrometer_frq[cdp.ri_ids[j]]: 484 noe_r1_table[i] = j 485 486 # Return the structures. 487 return ri_data, ri_data_err, len(frq), num_ri, ri_labels, frq, remap_table, noe_r1_table
488 489 490
491 -class MF_memo(Memo):
492 """The model-free memo class. 493 494 Not quite a momento so a memo. 495 """ 496
497 - def __init__(self, model_free=None, model_type=None, spin=None, sim_index=None, scaling_matrix=None):
498 """Initialise the model-free memo class. 499 500 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. 501 502 @keyword model_free: The model-free class instance. 503 @type model_free: specific_analyses.model_free.Model_free instance 504 @keyword spin: The spin data container. If this argument is supplied, then the spin_id argument will be ignored. 505 @type spin: SpinContainer instance 506 @keyword sim_index: The optional MC simulation index. 507 @type sim_index: int 508 @keyword scaling_matrix: The diagonal, square scaling matrix. 509 @type scaling_matrix: numpy diagonal matrix 510 """ 511 512 # Execute the base class __init__() method. 513 super(MF_memo, self).__init__() 514 515 # Store the arguments. 516 self.model_free = model_free 517 self.model_type = model_type 518 self.spin = spin 519 self.sim_index = sim_index 520 self.scaling_matrix = scaling_matrix
521 522 523
524 -class MF_minimise_command(Slave_command):
525 """Command class for standard model-free minimisation.""" 526
527 - def __init__(self):
528 """Initialise the base class.""" 529 530 # Execute the base class __init__() method. 531 super(MF_minimise_command, self).__init__()
532 533
534 - def optimise(self):
535 """Model-free optimisation. 536 537 @return: The optimisation results consisting of the parameter vector, function value, iteration count, function count, gradient count, Hessian count, and warnings. 538 @rtype: tuple of numpy array, float, int, int, int, int, str 539 """ 540 541 # Minimisation. 542 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) 543 544 # Return the minfx results unmodified. 545 return results
546 547
548 - def run(self, processor, completed):
549 """Setup and perform the model-free optimisation.""" 550 551 # Initialise the function to minimise. 552 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) 553 554 # Printout. 555 if self.opt_params.verbosity >= 1 and (self.data.model_type == 'mf' or self.data.model_type == 'local_tm'): 556 subsection(file=sys.stdout, text="Optimisation: Spin '%s'" % self.data.spin_id, prespace=2, postspace=0) 557 558 # Preform optimisation. 559 results = self.optimise() 560 561 # Disassemble the results list. 562 param_vector, func, iter, fc, gc, hc, warning = results 563 564 processor.return_object(MF_result_command(processor, self.memo_id, param_vector, func, iter, fc, gc, hc, warning, completed=False))
565 566
567 - def store_data(self, data, opt_params):
568 """Store all the data required for model-free optimisation. 569 570 @param data: The data used to initialise the model-free target function class. 571 @type data: class instance 572 @param opt_params: The parameters and data required for optimisation using minfx. 573 @type opt_params: class instance 574 """ 575 576 # Store the data. 577 self.data = data 578 self.opt_params = opt_params
579 580 581
582 -class MF_grid_command(MF_minimise_command):
583 """Command class for the model-free grid search.""" 584
585 - def __init__(self):
586 """Initialise all the data.""" 587 588 # Execute the base class __init__() method. 589 super(MF_grid_command, self).__init__()
590 591
592 - def optimise(self):
593 """Model-free grid search. 594 595 @return: The optimisation results consisting of the parameter vector, function value, iteration count, function count, gradient count, Hessian count, and warnings. 596 @rtype: tuple of numpy array, float, int, int, int, int, str 597 """ 598 599 # Normal grid search. 600 if not hasattr(self.opt_params, 'subdivision'): 601 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) 602 603 # Subdivided grid. 604 else: 605 results = grid_point_array(func=self.mf.func, args=(), points=self.opt_params.subdivision, verbosity=self.opt_params.verbosity) 606 607 # Unpack the results. 608 param_vector, func, iter, warning = results 609 fc = iter 610 gc = 0.0 611 hc = 0.0 612 613 # Return everything. 614 return param_vector, func, iter, fc, gc, hc, warning
615 616 617
618 -class MF_result_command(Result_command):
619 """Class for processing the model-free results.""" 620
621 - def __init__(self, processor, memo_id, param_vector, func, iter, fc, gc, hc, warning, completed):
622 """Set up the class, placing the minimisation results here.""" 623 624 # Execute the base class __init__() method. 625 super(MF_result_command, self).__init__(processor=processor, completed=completed) 626 627 # Store the arguments. 628 self.memo_id = memo_id 629 self.param_vector = param_vector 630 self.func = func 631 self.iter = iter 632 self.fc = fc 633 self.gc = gc 634 self.hc = hc 635 self.warning = warning
636 637
638 - def run(self, processor, memo):
639 """Disassemble the model-free optimisation results. 640 641 @param processor: Unused! 642 @type processor: None 643 @param memo: The model-free memo. 644 @type memo: memo 645 """ 646 647 # Disassemble the results. 648 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_matrix=memo.scaling_matrix)
649