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 Lipari-Szabo model-free analysis API object."""
25
26
27
28 import dep_check
29 if dep_check.bmrblib_module:
30 import bmrblib
31 from copy import deepcopy
32 from math import pi
33 from minfx.grid import grid_split
34 from numpy import array, dot, float64, int32, zeros
35 from numpy.linalg import inv
36 from re import match, search
37 import string
38 import sys
39 from types import MethodType
40 from warnings import warn
41
42
43 from lib.arg_check import is_num_list, is_str_list
44 from lib.errors import RelaxError, RelaxFault, RelaxNoModelError, RelaxNoSequenceError, RelaxNoTensorError
45 from lib.float import isInf
46 from lib.periodic_table import periodic_table
47 from lib.physical_constants import h_bar, mu0
48 from lib.text.sectioning import subsection
49 from lib.warnings import RelaxDeselectWarning, RelaxWarning
50 from multi import Processor_box
51 from pipe_control import diffusion_tensor, interatomic, mol_res_spin, pipes, relax_data, sequence
52 from pipe_control.bmrb import list_sample_conditions
53 from pipe_control.exp_info import bmrb_write_citations, bmrb_write_methods, bmrb_write_software
54 from pipe_control.interatomic import return_interatom_list
55 from pipe_control.mol_res_spin import count_spins, exists_mol_res_spin_data, find_index, get_molecule_names, return_spin, return_spin_from_index, return_spin_indices, spin_loop
56 from pipe_control.spectrometer import check_spectrometer_setup
57 from specific_analyses.api_base import API_base
58 from specific_analyses.api_common import API_common
59 from specific_analyses.model_free.bmrb import sf_csa_read, sf_model_free_read, to_bmrb_model
60 from specific_analyses.model_free.data import compare_objects
61 from specific_analyses.model_free.molmol import Molmol
62 from specific_analyses.model_free.model import determine_model_type
63 from specific_analyses.model_free.parameters import are_mf_params_set, assemble_param_names, assemble_param_vector, linear_constraints
64 from specific_analyses.model_free.optimisation import MF_grid_command, MF_memo, MF_minimise_command, minimise_data_setup, relax_data_opt_structs
65 from specific_analyses.model_free.parameter_object import Model_free_params
66 from specific_analyses.model_free.pymol import Pymol
67 from target_functions.mf import Mf
68
69
71 """Parent class containing all the model-free specific functions."""
72
73
74 instance = None
75
95
96
97 - def back_calc_ri(self, spin_index=None, ri_id=None, ri_type=None, frq=None):
98 """Back-calculation of relaxation data from the model-free parameter values.
99
100 @keyword spin_index: The global spin index.
101 @type spin_index: int
102 @keyword ri_id: The relaxation data ID string.
103 @type ri_id: str
104 @keyword ri_type: The relaxation data type.
105 @type ri_type: str
106 @keyword frq: The field strength.
107 @type frq: float
108 @return: The back calculated relaxation data value corresponding to the index.
109 @rtype: float
110 """
111
112
113 spin, spin_id = return_spin_from_index(global_index=spin_index, return_spin_id=True)
114
115
116 if hasattr(cdp, 'diff_tensor') and (cdp.diff_tensor.type == 'spheroid' or cdp.diff_tensor.type == 'ellipsoid'):
117 interatoms = interatomic.return_interatom_list(spin_hash=spin._hash)
118 for i in range(len(interatoms)):
119
120 if not interatoms[i].dipole_pair:
121 continue
122
123
124 if not hasattr(interatoms[i], 'vector') or interatoms[i].vector is None:
125 warn(RelaxDeselectWarning(spin_id, 'missing structural data'))
126 return
127
128
129 self.overfit_deselect(data_check=False, verbose=False)
130
131
132 value = self.minimise(min_algor='back_calc', min_options=(spin_index, ri_id, ri_type, frq))
133
134
135 return value
136
137
138 - def bmrb_read(self, file_path, version=None, sample_conditions=None):
176
177
179 """Write the model-free results to a BMRB NMR-STAR v3.1 formatted file.
180
181 @param file_path: The full file path.
182 @type file_path: str
183 @keyword version: The BMRB NMR-STAR dictionary format to output to.
184 @type version: str
185 """
186
187
188 check_spectrometer_setup(escalate=2)
189
190
191 cdp = pipes.get_pipe()
192
193
194 star = bmrblib.create_nmr_star('relax_model_free_results', file_path, version)
195
196
197 global_chi2 = None
198 if hasattr(cdp, 'chi2'):
199 global_chi2 = cdp.chi2
200
201
202 rex_frq = cdp.spectrometer_frq[cdp.ri_ids[0]]
203
204
205 mol_name_list = []
206 res_num_list = []
207 res_name_list = []
208 atom_name_list = []
209
210 csa_list = []
211 r_list = []
212 isotope_list = []
213 element_list = []
214
215 local_tm_list = []
216 s2_list = []
217 s2f_list = []
218 s2s_list = []
219 te_list = []
220 tf_list = []
221 ts_list = []
222 rex_list = []
223
224 local_tm_err_list = []
225 s2_err_list = []
226 s2f_err_list = []
227 s2s_err_list = []
228 te_err_list = []
229 tf_err_list = []
230 ts_err_list = []
231 rex_err_list = []
232
233 chi2_list = []
234 model_list = []
235
236
237 for spin, mol_name, res_num, res_name, spin_id in spin_loop(full_info=True, skip_desel=True, return_id=True):
238
239 if spin.name == 'H' or (hasattr(spin, 'element') and spin.element == 'H'):
240 warn(RelaxWarning("Skipping the proton spin '%s'." % spin_id))
241 continue
242
243
244 if not hasattr(spin, 'model'):
245 warn(RelaxWarning("Skipping the spin '%s' as no model-free model has been set up." % spin_id))
246 continue
247
248
249 if res_num == None:
250 raise RelaxError("For the BMRB, the residue of spin '%s' must be numbered." % spin_id)
251 if res_name == None:
252 raise RelaxError("For the BMRB, the residue of spin '%s' must be named." % spin_id)
253 if spin.name == None:
254 raise RelaxError("For the BMRB, the spin '%s' must be named." % spin_id)
255 if not hasattr(spin, 'isotope') or spin.isotope == None:
256 raise RelaxError("For the BMRB, the spin isotope type of '%s' must be specified." % spin_id)
257 if not hasattr(spin, 'element') or spin.element == None:
258 raise RelaxError("For the BMRB, the spin element type of '%s' must be specified. Please use the spin user function for setting the element type." % spin_id)
259
260
261 mol_name_list.append(mol_name)
262 res_num_list.append(res_num)
263 res_name_list.append(res_name)
264 atom_name_list.append(spin.name)
265
266
267 if hasattr(spin, 'csa'):
268 csa_list.append(spin.csa * 1e6)
269 else:
270 csa_list.append(None)
271
272
273 interatoms = return_interatom_list(spin_hash=spin._hash)
274 for i in range(len(interatoms)):
275
276 if not interatoms[i].dipole_pair:
277 continue
278
279
280 if hasattr(interatoms[i], 'r'):
281 r_list.append(interatoms[i].r)
282 else:
283 r_list.append(None)
284
285
286 break
287
288
289 if hasattr(spin, 'isotope'):
290 isotope_list.append(int(spin.isotope.strip(string.ascii_letters)))
291 else:
292 isotope_list.append(None)
293
294
295 if hasattr(spin, 'element'):
296 element_list.append(spin.element)
297 else:
298 element_list.append(None)
299
300
301 if hasattr(spin, 'local_tm'):
302 local_tm_list.append(spin.local_tm)
303 else:
304 local_tm_list.append(None)
305 if hasattr(spin, 'local_tm_err'):
306 local_tm_err_list.append(spin.local_tm_err)
307 else:
308 local_tm_err_list.append(None)
309
310
311 s2_list.append(spin.s2)
312 s2f_list.append(spin.s2f)
313 s2s_list.append(spin.s2s)
314 te_list.append(spin.te)
315 tf_list.append(spin.tf)
316 ts_list.append(spin.ts)
317 if spin.rex == None:
318 rex_list.append(None)
319 else:
320 rex_list.append(spin.rex / (2.0*pi*rex_frq**2))
321
322
323 params = ['s2', 's2f', 's2s', 'te', 'tf', 'ts', 'rex']
324 for param in params:
325
326 err_list = locals()[param+'_err_list']
327
328
329 if hasattr(spin, param+'_err'):
330
331 val = getattr(spin, param+'_err')
332
333
334 if param == 'rex' and val != None:
335 val = val / (2.0*pi*rex_frq**2)
336
337
338 err_list.append(val)
339
340
341 else:
342 err_list.append(None)
343
344
345
346 chi2_list.append(spin.chi2)
347
348
349 model_list.append(to_bmrb_model(spin.model))
350
351
352 if not len(model_list):
353 raise RelaxError("No model-free data could be found for any of the currently selected spins.")
354
355
356 entity_ids = zeros(len(mol_name_list), int32)
357 mol_names = get_molecule_names()
358 for i in range(len(mol_name_list)):
359 for j in range(len(mol_names)):
360 if mol_name_list[i] == mol_names[j]:
361 entity_ids[i] = j+1
362
363
364
365
366
367
368 bmrb_write_citations(star)
369
370
371
372
373
374
375 mol_res_spin.bmrb_write_entity(star)
376
377
378
379
380
381
382 bmrb_write_methods(star)
383
384
385 software_ids, software_labels = bmrb_write_software(star)
386
387
388
389
390
391
392 star.chem_shift_anisotropy.add(entity_ids=entity_ids, res_nums=res_num_list, res_names=res_name_list, atom_names=atom_name_list, atom_types=element_list, isotope=isotope_list, csa=csa_list)
393
394
395
396
397
398
399 relax_data.bmrb_write(star)
400
401
402
403
404
405
406 for i in range(len(software_ids)):
407 if software_labels[i] == 'relax':
408 software_id = software_ids[i]
409
410
411 star.model_free.add(global_chi2=global_chi2, software_ids=[software_id], software_labels=['relax'], entity_ids=entity_ids, res_nums=res_num_list, res_names=res_name_list, atom_names=atom_name_list, atom_types=element_list, isotope=isotope_list, bond_length=r_list, local_tc=local_tm_list, s2=s2_list, s2f=s2f_list, s2s=s2s_list, te=te_list, tf=tf_list, ts=ts_list, rex=rex_list, local_tc_err=local_tm_err_list, s2_err=s2_err_list, s2f_err=s2f_err_list, s2s_err=s2s_err_list, te_err=te_err_list, tf_err=tf_err_list, ts_err=ts_err_list, rex_err=rex_err_list, rex_frq=rex_frq, chi2=chi2_list, model_fit=model_list)
412
413
414
415
416
417
418 diffusion_tensor.bmrb_write(star)
419
420
421
422 star.write()
423
424
425 - def calculate(self, spin_id=None, scaling_matrix=None, verbosity=1, sim_index=None):
426 """Calculation of the model-free chi-squared value.
427
428 @keyword spin_id: The spin identification string.
429 @type spin_id: str
430 @keyword scaling_matrix: The per-model list of diagonal and square scaling matrices.
431 @type scaling_matrix: list of numpy rank-2, float64 array or list of None
432 @keyword verbosity: The amount of information to print. The higher the value, the greater the verbosity.
433 @type verbosity: int
434 @keyword sim_index: The optional MC simulation index.
435 @type sim_index: int
436 """
437
438
439 if not exists_mol_res_spin_data():
440 raise RelaxNoSequenceError
441
442
443 model_type = determine_model_type()
444
445
446 if model_type != 'local_tm' and not diffusion_tensor.diff_data_exists():
447 raise RelaxNoTensorError('diffusion')
448
449
450 if model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere' and not hasattr(cdp, 'structure'):
451 raise RelaxNoPdbError
452
453
454 for spin, id in spin_loop(spin_id, return_id=True):
455
456 if not spin.select:
457 continue
458
459
460 if not spin.model:
461 raise RelaxNoModelError
462
463
464 if not hasattr(spin, 'isotope'):
465 raise RelaxSpinTypeError
466
467
468 unset_param = are_mf_params_set(spin)
469 if unset_param != None:
470 raise RelaxNoValueError(unset_param)
471
472
473 if not hasattr(spin, 'csa') or spin.csa == None:
474 raise RelaxNoValueError("CSA")
475
476
477 interatoms = return_interatom_list(spin_hash=spin._hash)
478 for interatom in interatoms:
479
480 if not interatom.dipole_pair:
481 continue
482
483
484 if model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere' and not hasattr(interatom, 'vector'):
485 raise RelaxNoVectorsError
486
487
488 if model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere' and hasattr(interatom, 'vector') and is_num_list(interatom.vector[0], raise_error=False):
489 raise RelaxMultiVectorError
490
491
492 if spin_id != interatom.spin_id1:
493 spin_id2 = interatom.spin_id1
494 else:
495 spin_id2 = interatom.spin_id2
496 spin2 = return_spin(spin_id=spin_id2)
497
498
499 if not hasattr(spin2, 'isotope'):
500 raise RelaxSpinTypeError
501
502
503 if not hasattr(interatom, 'r') or interatom.r == None:
504 raise RelaxNoValueError("interatomic distance", spin_id=spin_id, spin_id2=spin_id2)
505
506
507 if not hasattr(spin, 'ri_data') or not hasattr(spin, 'ri_data_err'):
508 continue
509
510
511 for ri_id in cdp.ri_ids:
512
513 err = spin.ri_data_err[ri_id]
514
515
516 if err != None and err == 0.0:
517 raise RelaxError("Zero error for spin '%s' for the relaxation data ID '%s', minimisation not possible." % (id, ri_id))
518 elif err != None and err < 0.0:
519 raise RelaxError("Negative error of %s for spin '%s' for the relaxation data ID '%s', minimisation not possible." % (err, id, ri_id))
520
521
522 param_vector = assemble_param_vector(spin=spin, sim_index=sim_index)
523
524
525 data = relax_data_opt_structs(spin, sim_index=sim_index)
526
527
528 ri_data = [array(data[0])]
529 ri_data_err = [array(data[1])]
530 num_frq = [data[2]]
531 num_ri = [data[3]]
532 ri_labels = [data[4]]
533 frq = [data[5]]
534 remap_table = [data[6]]
535 noe_r1_table = [data[7]]
536 gx = [periodic_table.gyromagnetic_ratio(spin.isotope)]
537 if sim_index == None:
538 csa = [spin.csa]
539 else:
540 csa = [spin.csa_sim[sim_index]]
541
542
543 interatoms = return_interatom_list(spin_hash=spin._hash)
544 for i in range(len(interatoms)):
545
546 if not interatoms[i].dipole_pair:
547 continue
548
549
550 if spin_id != interatoms[i].spin_id1:
551 spin_id2 = interatoms[i].spin_id1
552 else:
553 spin_id2 = interatoms[i].spin_id2
554 spin2 = return_spin(spin_id=spin_id2)
555
556
557 if sim_index == None:
558 r = [interatoms[i].r]
559 else:
560 r = [interatoms[i].r_sim[sim_index]]
561
562
563 if model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere':
564 xh_unit_vectors = [interatoms[i].vector]
565 else:
566 xh_unit_vectors = [None]
567
568
569 gh = [periodic_table.gyromagnetic_ratio(spin2.isotope)]
570
571
572 num_params = [len(spin.params)]
573
574
575 param_values = [assemble_param_vector(model_type='mf')]
576
577
578 if model_type == 'local_tm':
579 diff_params = [spin.local_tm]
580 diff_type = 'sphere'
581 else:
582
583 diff_type = cdp.diff_tensor.type
584
585
586 if diff_type == 'sphere':
587 diff_params = [cdp.diff_tensor.tm]
588
589
590 elif diff_type == 'spheroid':
591 diff_params = [cdp.diff_tensor.tm, cdp.diff_tensor.Da, cdp.diff_tensor.theta, cdp.diff_tensor.phi]
592
593
594 elif diff_type == 'ellipsoid':
595 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]
596
597
598 mf = Mf(init_params=param_vector, model_type='mf', diff_type=diff_type, diff_params=diff_params, num_spins=1, equations=[spin.equation], param_types=[spin.params], param_values=param_values, relax_data=ri_data, errors=ri_data_err, bond_length=r, csa=csa, num_frq=num_frq, frq=frq, num_ri=num_ri, remap_table=remap_table, noe_r1_table=noe_r1_table, ri_labels=ri_labels, gx=gx, gh=gh, h_bar=h_bar, mu0=mu0, num_params=num_params, vectors=xh_unit_vectors)
599
600
601 try:
602 chi2 = mf.func(param_vector)
603 except OverflowError:
604 chi2 = 1e200
605
606
607 if model_type == 'all' or model_type == 'diff':
608 cdp.chi2 = cdp.chi2 + chi2
609 else:
610 spin.chi2 = chi2
611
612
614 """Create the Monte Carlo Ri data.
615
616 @keyword data_id: The spin identification string, as yielded by the base_data_loop() generator method.
617 @type data_id: str
618 @return: The Monte Carlo simulation data.
619 @rtype: list of floats
620 """
621
622
623 mc_data = []
624
625
626 spin = return_spin(spin_id=data_id)
627 global_index = find_index(data_id)
628
629
630 if not spin.select:
631 return
632
633
634 if not hasattr(spin, 'model') or not spin.model:
635 return None
636
637
638 for ri_id in cdp.ri_ids:
639
640 value = self.back_calc_ri(spin_index=global_index, ri_id=ri_id, ri_type=cdp.ri_type[ri_id], frq=cdp.spectrometer_frq[ri_id])
641
642
643 mc_data.append(value)
644
645
646 return mc_data
647
648
650 """Initialise the spin specific data structures.
651
652 @param data: The spin ID string from the _base_data_loop_spin() method.
653 @type data: str
654 @keyword sim: The Monte Carlo simulation flag, which if true will initialise the simulation data structure.
655 @type sim: bool
656 """
657
658
659 spin = return_spin(spin_id=data)
660
661
662 for name in self._PARAMS.loop(scope='spin'):
663
664 if name in ['ri_data', 'ri_data_bc', 'ri_data_err']:
665 continue
666
667
668 list_data = [ 'params' ]
669 if name in list_data:
670 init_data = []
671
672
673 init_data = None
674 if self._PARAMS.type(name) == bool:
675 init_data = False
676 if name == 'select':
677 init_data = True
678
679
680 if not hasattr(spin, name):
681 setattr(spin, name, init_data)
682
683
684 - def deselect(self, sim_index=None, model_info=None):
685 """Deselect models or simulations.
686
687 @keyword sim_index: The optional Monte Carlo simulation index. If None, then models will be deselected, otherwise the given simulation will.
688 @type sim_index: None or int
689 @keyword model_info: The model information from model_loop(). This index is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
690 @type model_info: int
691 """
692
693
694 model_type = determine_model_type()
695
696
697 if model_type == 'mf' or model_type == 'local_tm':
698
699 spin = return_spin_from_index(global_index=model_info)
700
701
702 if sim_index == None:
703 spin.select = False
704
705
706 else:
707 spin.select_sim[sim_index] = False
708
709
710 else:
711
712 if sim_index == None:
713 raise RelaxError("Cannot deselect the global model.")
714
715
716 else:
717
718 cdp.select_sim[sim_index] = False
719
720
721 - def duplicate_data(self, pipe_from=None, pipe_to=None, model_info=None, global_stats=False, verbose=True):
722 """Duplicate the data specific to a single model-free model.
723
724 @keyword pipe_from: The data pipe to copy the data from.
725 @type pipe_from: str
726 @keyword pipe_to: The data pipe to copy the data to.
727 @type pipe_to: str
728 @keyword model_info: The model information from model_loop(). This index is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
729 @type model_info: int
730 @keyword global_stats: The global statistics flag.
731 @type global_stats: bool
732 @keyword verbose: A flag which if True will cause info about each spin to be printed out as the sequence is generated.
733 @type verbose: bool
734 """
735
736
737 if model_info == None:
738 raise RelaxError("The model_info argument cannot be None.")
739
740
741 if not pipes.has_pipe(pipe_to):
742 pipes.create(pipe_to, pipe_type='mf', switch=False)
743
744
745 dp_from = pipes.get_pipe(pipe_from)
746 dp_to = pipes.get_pipe(pipe_to)
747
748
749 for data_name in dir(dp_from):
750
751 if data_name in ['diff_tensor', 'mol', 'interatomic', 'structure', 'exp_info']:
752 continue
753
754
755 if search('^_', data_name) or data_name in dp_from.__class__.__dict__:
756 continue
757
758
759 data_from = getattr(dp_from, data_name)
760
761
762 if hasattr(dp_to, data_name):
763
764 data_to = getattr(dp_to, data_name)
765
766
767 if data_from != data_to:
768 raise RelaxError("The object " + repr(data_name) + " is not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".")
769
770
771 continue
772
773
774 setattr(dp_to, data_name, deepcopy(data_from))
775
776
777 if hasattr(dp_from, 'diff_tensor'):
778
779 if not hasattr(dp_to, 'diff_tensor'):
780 setattr(dp_to, 'diff_tensor', deepcopy(dp_from.diff_tensor))
781
782
783 else:
784
785 for data_name in dp_from.diff_tensor._mod_attr:
786
787 data_from = None
788 if hasattr(dp_from.diff_tensor, data_name):
789 data_from = getattr(dp_from.diff_tensor, data_name)
790
791
792 if data_from and not hasattr(dp_to.diff_tensor, data_name):
793 raise RelaxError("The diffusion tensor object " + repr(data_name) + " of the " + repr(pipe_from) + " data pipe is not located in the " + repr(pipe_to) + " data pipe.")
794 elif data_from:
795 data_to = getattr(dp_to.diff_tensor, data_name)
796 else:
797 continue
798
799
800 if data_from != data_to:
801 raise RelaxError("The object " + repr(data_name) + " is not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".")
802
803
804 if hasattr(dp_from, 'structure'):
805
806 if not hasattr(dp_to, 'structure'):
807 setattr(dp_to, 'structure', deepcopy(dp_from.structure))
808
809
810 else:
811
812 compare_objects(dp_from.structure, dp_to.structure, pipe_from, pipe_to)
813
814
815 if len(dp_from.structure.structural_data) != len(dp_from.structure.structural_data):
816 raise RelaxError("The number of structural models is not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".")
817
818
819 for i in range(len(dp_from.structure.structural_data)):
820
821 model_from = dp_from.structure.structural_data[i]
822 model_to = dp_to.structure.structural_data[i]
823
824
825 if model_from.num != model_to.num:
826 raise RelaxError("The structure models are not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".")
827
828
829 if len(model_from.mol) != len(model_to.mol):
830 raise RelaxError("The number of molecules is not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".")
831
832
833 for mol_index in range(len(model_from.mol)):
834
835 compare_objects(model_from.mol[mol_index], model_to.mol[mol_index], pipe_from, pipe_to)
836
837
838 if dp_from.mol.is_empty():
839 return
840
841
842 if dp_to.mol.is_empty():
843 sequence.copy(pipe_from=pipe_from, pipe_to=pipe_to, preserve_select=True, verbose=verbose)
844
845
846 if dp_to.interatomic.is_empty():
847 interatomic.copy(pipe_from=pipe_from, pipe_to=pipe_to, verbose=verbose)
848
849
850 pipes.switch(pipe_from)
851 model_type = determine_model_type()
852
853
854 spin, spin_id = return_spin_from_index(global_index=model_info, pipe=pipe_from, return_spin_id=True)
855 if model_type == 'mf' or (model_type == 'local_tm' and not global_stats):
856
857 for name in dir(spin):
858
859 if search('^__', name):
860 continue
861
862
863 obj = getattr(spin, name)
864
865
866 if isinstance(obj, MethodType):
867 continue
868
869
870 new_obj = deepcopy(getattr(spin, name))
871 setattr(dp_to.mol[spin._mol_index].res[spin._res_index].spin[spin._spin_index], name, new_obj)
872
873
874 interatoms = interatomic.return_interatom_list(spin_hash=spin._hash)
875 for interatom in interatoms:
876
877 if not interatom.dipole_pair:
878 continue
879
880
881 if spin_id != interatom.spin_id1:
882 spin_id2 = interatom.spin_id1
883 else:
884 spin_id2 = interatom.spin_id2
885 spin2 = return_spin(spin_id=spin_id2)
886
887
888 mol_index, res_index, spin_index = return_spin_indices(spin_id=spin_id2)
889 dp_to.mol[mol_index].res[res_index].spin[spin_index] = deepcopy(spin2)
890
891
892 else:
893
894 dp_to.mol = deepcopy(dp_from.mol)
895
896
897 - def eliminate(self, name, value, args, sim=None, model_info=None):
898 """Model-free model elimination, parameter by parameter.
899
900 @param name: The parameter name.
901 @type name: str
902 @param value: The parameter value.
903 @type value: float
904 @param args: The c1 and c2 elimination constant overrides.
905 @type args: None or tuple of float
906 @keyword sim: The Monte Carlo simulation index.
907 @type sim: int
908 @keyword model_info: The model information from model_loop(). This index is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
909 @type model_info: int
910 @return: True if the model is to be eliminated, False otherwise.
911 @rtype: bool
912 """
913
914
915 c1 = 50.0 * 1e-9
916 c2 = 1.5
917
918
919 if args != None:
920 c1, c2 = args
921
922
923 model_type = determine_model_type()
924
925
926 if model_type != 'mf' and model_type != 'local_tm':
927 raise RelaxError("Elimination of the global model is not yet supported.")
928
929
930 spin, spin_id = return_spin_from_index(global_index=model_info, return_spin_id=True)
931
932
933 if model_type == 'local_tm':
934 tm = spin.local_tm
935 else:
936 tm = cdp.diff_tensor.tm
937
938
939 if tm == None:
940 return False
941
942
943 if name == 'local_tm' and value >= c1:
944 if sim == None:
945 print("Data pipe '%s': The local tm parameter of %.5g is greater than %.5g, eliminating spin system '%s'." % (pipes.cdp_name(), value, c1, spin_id))
946 else:
947 print("Data pipe '%s': The local tm parameter of %.5g is greater than %.5g, eliminating simulation %i of spin system '%s'." % (pipes.cdp_name(), value, c1, sim, spin_id))
948 return True
949
950
951 if match('t[efs]', name) and value >= c2 * tm:
952 if sim == None:
953 print("Data pipe '%s': The %s value of %.5g is greater than %.5g, eliminating spin system '%s'." % (pipes.cdp_name(), name, value, c2*tm, spin_id))
954 else:
955 print("Data pipe '%s': The %s value of %.5g is greater than %.5g, eliminating simulation %i of spin system '%s'." % (pipes.cdp_name(), name, value, c2*tm, sim, spin_id))
956 return True
957
958
959 return False
960
961
983
984
1017
1018
1019 - def grid_search(self, lower=None, upper=None, inc=None, scaling_matrix=None, constraints=True, verbosity=1, sim_index=None):
1020 """The model-free grid search function.
1021
1022 @keyword lower: The per-model lower bounds of the grid search which must be equal to the number of parameters in the model.
1023 @type lower: list of lists of numbers
1024 @keyword upper: The per-model upper bounds of the grid search which must be equal to the number of parameters in the model.
1025 @type upper: list of lists of numbers
1026 @keyword inc: The per-model increments for each dimension of the space for the grid search. The number of elements in the array must equal to the number of parameters in the model.
1027 @type inc: list of lists of int
1028 @keyword scaling_matrix: The per-model list of diagonal and square scaling matrices.
1029 @type scaling_matrix: list of numpy rank-2, float64 array or list of None
1030 @keyword constraints: If True, constraints are applied during the grid search (eliminating parts of the grid). If False, no constraints are used.
1031 @type constraints: bool
1032 @keyword verbosity: A flag specifying the amount of information to print. The higher the value, the greater the verbosity.
1033 @type verbosity: int
1034 @keyword sim_index: The index of the simulation to apply the grid search to. If None, the normal model is optimised.
1035 @type sim_index: int
1036 """
1037
1038
1039 self.minimise(min_algor='grid', lower=lower, upper=upper, inc=inc, scaling_matrix=scaling_matrix, constraints=constraints, verbosity=verbosity, sim_index=sim_index)
1040
1041
1043 """Create bounds for the OpenDX mapping function.
1044
1045 @param param: The name of the parameter to return the lower and upper bounds of.
1046 @type param: str
1047 @param spin_id: The spin identification string.
1048 @type spin_id: str
1049 @return: The upper and lower bounds of the parameter.
1050 @rtype: list of float
1051 """
1052
1053
1054 if self._PARAMS.scope(param) == 'global':
1055 return diffusion_tensor.map_bounds(param)
1056
1057
1058 spin = return_spin(spin_id=spin_id)
1059
1060
1061 if search('^s2', param):
1062 return [0.0, 1.0]
1063
1064
1065 elif search('^t', param) or param == 'local_tm':
1066 return [0.0, 1e-8]
1067
1068
1069 elif param == 'rex':
1070 return [0.0, 30.0 / (2.0 * pi * cdp.spectrometer_frq[cdp.ri_ids[0]])**2]
1071
1072
1073 elif param == 'r':
1074 return [1.0 * 1e-10, 1.1 * 1e-10]
1075
1076
1077 elif param == 'csa':
1078 return [-100 * 1e-6, -300 * 1e-6]
1079
1080
1081 - def minimise(self, min_algor=None, min_options=None, func_tol=None, grad_tol=None, max_iterations=None, constraints=False, scaling_matrix=None, verbosity=0, sim_index=None, lower=None, upper=None, inc=None):
1082 """Model-free minimisation function.
1083
1084 Three categories of models exist for which the approach to minimisation is different. These
1085 are:
1086
1087 Single spin optimisations: The 'mf' and 'local_tm' model types which are the
1088 model-free parameters for single spins, optionally with a local tm parameter. These
1089 models have no global parameters.
1090
1091 Diffusion tensor optimisations: The 'diff' diffusion tensor model type. No spin
1092 specific parameters exist.
1093
1094 Optimisation of everything: The 'all' model type consisting of all model-free and all
1095 diffusion tensor parameters.
1096
1097
1098 @keyword min_algor: The minimisation algorithm to use.
1099 @type min_algor: str
1100 @keyword min_options: An array of options to be used by the minimisation algorithm.
1101 @type min_options: array of str
1102 @keyword func_tol: The function tolerance which, when reached, terminates optimisation. Setting this to None turns of the check.
1103 @type func_tol: None or float
1104 @keyword grad_tol: The gradient tolerance which, when reached, terminates optimisation. Setting this to None turns of the check.
1105 @type grad_tol: None or float
1106 @keyword max_iterations: The maximum number of iterations for the algorithm.
1107 @type max_iterations: int
1108 @keyword constraints: If True, constraints are used during optimisation.
1109 @type constraints: bool
1110 @keyword scaling_matrix: The per-model list of diagonal and square scaling matrices.
1111 @type scaling_matrix: list of numpy rank-2, float64 array or list of None
1112 @keyword verbosity: The amount of information to print. The higher the value, the greater the verbosity.
1113 @type verbosity: int
1114 @keyword sim_index: The index of the simulation to optimise. This should be None if normal optimisation is desired.
1115 @type sim_index: None or int
1116 @keyword lower: The per-model lower bounds of the grid search which must be equal to the number of parameters in the model. This optional argument is only used when doing a grid search.
1117 @type lower: list of lists of numbers
1118 @keyword upper: The per-model upper bounds of the grid search which must be equal to the number of parameters in the model. This optional argument is only used when doing a grid search.
1119 @type upper: list of lists of numbers
1120 @keyword inc: The per-model increments for each dimension of the space for the grid search. The number of elements in the array must equal to the number of parameters in the model. This argument is only used when doing a grid search.
1121 @type inc: list of lists of int
1122 """
1123
1124
1125 if not exists_mol_res_spin_data():
1126 raise RelaxNoSequenceError
1127
1128
1129 for spin in spin_loop():
1130
1131 if not spin.select:
1132 continue
1133
1134
1135 if not spin.model:
1136 raise RelaxNoModelError
1137
1138
1139 if not hasattr(spin, 'isotope'):
1140 raise RelaxSpinTypeError
1141
1142
1143 data_store = Data_container()
1144 opt_params = Data_container()
1145
1146
1147 data_store.h_bar = h_bar
1148 data_store.mu0 = mu0
1149 opt_params.min_algor = min_algor
1150 opt_params.min_options = min_options
1151 opt_params.func_tol = func_tol
1152 opt_params.grad_tol = grad_tol
1153 opt_params.max_iterations = max_iterations
1154
1155
1156 opt_params.verbosity = verbosity
1157
1158
1159 data_store.model_type = determine_model_type()
1160 if not data_store.model_type:
1161 return
1162
1163
1164 if min_algor == 'back_calc' and data_store.model_type != 'local_tm':
1165 data_store.model_type = 'mf'
1166
1167
1168 if data_store.model_type != 'local_tm' and not diffusion_tensor.diff_data_exists():
1169 raise RelaxNoTensorError('diffusion')
1170
1171
1172 if data_store.model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere':
1173
1174 if not hasattr(cdp, 'structure'):
1175 raise RelaxNoPdbError
1176
1177
1178 for spin, spin_id in spin_loop(return_id=True):
1179
1180 if not spin.select:
1181 continue
1182
1183
1184 interatoms = return_interatom_list(spin_hash=spin._hash)
1185
1186
1187 for i in range(len(interatoms)):
1188
1189 if not interatoms[i].dipole_pair:
1190 continue
1191
1192
1193 if not hasattr(interatoms[i], 'vector'):
1194 raise RelaxNoVectorsError
1195
1196
1197 if data_store.model_type == 'diff':
1198
1199 for spin in spin_loop():
1200 unset_param = are_mf_params_set(spin)
1201 if unset_param != None:
1202 raise RelaxNoValueError(unset_param)
1203
1204
1205 if verbosity >= 1:
1206 if data_store.model_type == 'mf':
1207 print("Only the model-free parameters for single spins will be used.")
1208 elif data_store.model_type == 'local_mf':
1209 print("Only a local tm value together with the model-free parameters for single spins will be used.")
1210 elif data_store.model_type == 'diff':
1211 print("Only diffusion tensor parameters will be used.")
1212 elif data_store.model_type == 'all':
1213 print("The diffusion tensor parameters together with the model-free parameters for all spins will be used.")
1214
1215
1216 for spin, spin_id in spin_loop(return_id=True):
1217
1218 if not spin.select:
1219 continue
1220
1221
1222 if not hasattr(spin, 'csa') or spin.csa == None:
1223 raise RelaxNoValueError("CSA")
1224
1225
1226 interatoms = return_interatom_list(spin_hash=spin._hash)
1227
1228
1229 count = 0
1230 for i in range(len(interatoms)):
1231
1232 if not interatoms[i].dipole_pair:
1233 continue
1234
1235
1236 if not hasattr(interatoms[i], 'r') or interatoms[i].r == None:
1237 raise RelaxNoValueError("interatomic distance", spin_id=interatoms[i].spin_id1, spin_id2=interatoms[i].spin_id2)
1238
1239
1240 count += 1
1241
1242
1243 if count > 1:
1244 raise RelaxError("The spin '%s' has %s dipolar relaxation interactions defined, but only a maximum of one is currently supported." % (spin_id, count))
1245
1246
1247 if data_store.model_type == 'mf' or data_store.model_type == 'local_tm':
1248 num_data_sets = 1
1249 data_store.num_spins = 1
1250 elif data_store.model_type == 'diff' or data_store.model_type == 'all':
1251 num_data_sets = count_spins(skip_desel=False)
1252 data_store.num_spins = count_spins()
1253
1254
1255 if min_algor == 'back_calc':
1256 num_data_sets = 0
1257 data_store.num_spins = 1
1258
1259
1260 processor_box = Processor_box()
1261 processor = processor_box.processor
1262
1263
1264 for index in self.model_loop():
1265
1266 if data_store.model_type == 'diff' or data_store.model_type == 'all':
1267 spin_index = None
1268 spin, data_store.spin_id = None, None
1269 elif min_algor == 'back_calc':
1270 spin_index = opt_params.min_options[0]
1271 spin, data_store.spin_id = return_spin_from_index(global_index=spin_index, return_spin_id=True)
1272 else:
1273 spin_index = index
1274 spin, data_store.spin_id = return_spin_from_index(global_index=spin_index, return_spin_id=True)
1275
1276
1277 if spin and (data_store.model_type == 'mf' or data_store.model_type == 'local_tm') and not min_algor == 'back_calc':
1278
1279 if not spin.select:
1280 continue
1281
1282
1283 if not hasattr(spin, 'ri_data') or not hasattr(spin, 'ri_data_err'):
1284 continue
1285
1286
1287 if spin and (data_store.model_type == 'mf' or data_store.model_type == 'local_tm'):
1288 interatoms = return_interatom_list(spin_hash=spin._hash)
1289 if not len(interatoms):
1290 continue
1291
1292
1293 if min_algor == 'back_calc':
1294
1295 opt_params.param_vector = assemble_param_vector(spin=spin, model_type=data_store.model_type)
1296
1297
1298 data_store.scaling_matrix = None
1299
1300 else:
1301
1302 opt_params.param_vector = assemble_param_vector(spin=spin, sim_index=sim_index)
1303
1304
1305 num_params = len(opt_params.param_vector)
1306
1307
1308 data_store.scaling_matrix = scaling_matrix[index]
1309 if data_store.scaling_matrix is not None:
1310 opt_params.param_vector = dot(inv(data_store.scaling_matrix), opt_params.param_vector)
1311
1312
1313 opt_params.lower, opt_params.upper, opt_params.inc = None, None, None
1314 if lower != None:
1315 opt_params.lower = lower[index]
1316 if upper != None:
1317 opt_params.upper = upper[index]
1318 if inc != None:
1319 opt_params.inc = inc[index]
1320
1321
1322 if match('^[Ss]et', min_algor):
1323 opt_params.min_options = dot(inv(data_store.scaling_matrix), opt_params.min_options)
1324
1325
1326 if constraints:
1327 opt_params.A, opt_params.b = linear_constraints(num_params, model_type=data_store.model_type, spin=spin, scaling_matrix=data_store.scaling_matrix)
1328 else:
1329 opt_params.A, opt_params.b = None, None
1330
1331
1332 minimise_data_setup(data_store, min_algor, num_data_sets, opt_params.min_options, spin=spin, sim_index=sim_index)
1333
1334
1335 if constraints and not match('^[Gg]rid', min_algor):
1336 algor = opt_params.min_options[0]
1337 else:
1338 algor = min_algor
1339
1340
1341 if min_algor == 'back_calc' or match('[Ll][Mm]$', algor) or match('[Ll]evenburg-[Mm]arquardt$', algor):
1342 mf = Mf(init_params=opt_params.param_vector, model_type=data_store.model_type, diff_type=data_store.diff_type, diff_params=data_store.diff_params, scaling_matrix=data_store.scaling_matrix, num_spins=data_store.num_spins, equations=data_store.equations, param_types=data_store.param_types, param_values=data_store.param_values, relax_data=data_store.ri_data, errors=data_store.ri_data_err, bond_length=data_store.r, csa=data_store.csa, num_frq=data_store.num_frq, frq=data_store.frq, num_ri=data_store.num_ri, remap_table=data_store.remap_table, noe_r1_table=data_store.noe_r1_table, ri_labels=data_store.ri_types, gx=data_store.gx, gh=data_store.gh, h_bar=data_store.h_bar, mu0=data_store.mu0, num_params=data_store.num_params, vectors=data_store.xh_unit_vectors)
1343
1344
1345 if match('[Ll][Mm]$', algor) or match('[Ll]evenburg-[Mm]arquardt$', algor):
1346
1347 number_ri = 0
1348 for k in range(len(ri_data_err)):
1349 number_ri = number_ri + len(ri_data_err[k])
1350
1351
1352 lm_error = zeros(number_ri, float64)
1353 index = 0
1354 for k in range(len(ri_data_err)):
1355 lm_error[index:index+len(ri_data_err[k])] = ri_data_err[k]
1356 index = index + len(ri_data_err[k])
1357
1358 opt_params.min_options = opt_params.min_options + (mf.lm_dri, lm_error)
1359
1360
1361 if min_algor == 'back_calc':
1362 return mf.calc_ri()
1363
1364
1365 if match('^[Gg]rid', min_algor) and data_store.model_type == 'diff':
1366
1367 print("Parallelised diffusion tensor grid search.")
1368
1369
1370 for subdivision in grid_split(divisions=processor.processor_size(), lower=opt_params.lower, upper=opt_params.upper, inc=opt_params.inc, verbosity=verbosity):
1371
1372 opt_params.subdivision = subdivision
1373
1374
1375 command = MF_grid_command()
1376
1377
1378 command.store_data(deepcopy(data_store), deepcopy(opt_params))
1379
1380
1381 memo = MF_memo(model_free=self, model_type=data_store.model_type, spin=spin, sim_index=sim_index, scaling_matrix=data_store.scaling_matrix)
1382 processor.add_to_queue(command, memo)
1383
1384
1385 processor.run_queue()
1386
1387
1388 return
1389
1390
1391 if search('^[Gg]rid', min_algor):
1392 command = MF_grid_command()
1393
1394
1395 else:
1396 command = MF_minimise_command()
1397
1398
1399 command.store_data(deepcopy(data_store), deepcopy(opt_params))
1400
1401
1402 memo = MF_memo(model_free=self, model_type=data_store.model_type, spin=spin, sim_index=sim_index, scaling_matrix=data_store.scaling_matrix)
1403 processor.add_to_queue(command, memo)
1404
1405
1406 processor.run_queue()
1407
1408
1410 """Return a description of the model.
1411
1412 @keyword model_info: The model information from model_loop(). This index is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
1413 @type model_info: int
1414 @return: The model description.
1415 @rtype: str
1416 """
1417
1418
1419 model_type = determine_model_type()
1420
1421
1422 if model_type == 'all':
1423 return "Global model - all diffusion tensor parameters and spin specific model-free parameters."
1424 elif model_type == 'diff':
1425 return "Diffusion tensor model."
1426
1427
1428 else:
1429
1430 spin, spin_id = return_spin_from_index(model_info, return_spin_id=True)
1431
1432
1433 return "Model-free model of spin '%s'." % spin_id
1434
1435
1437 """Generator method for looping over the models (global or local).
1438
1439 If the model type is 'all' or 'diff', then this yields the single value of zero. Otherwise
1440 the global spin index is yielded.
1441
1442
1443 @return: The model index. This index is zero for the global models or equal to the global spin
1444 index (which covers the molecule, residue, and spin indices).
1445 @rtype: int
1446 """
1447
1448
1449 model_type = determine_model_type()
1450
1451
1452 if model_type == 'all' or model_type == 'diff':
1453 yield 0
1454
1455
1456 else:
1457
1458 global_index = -1
1459 for spin in spin_loop():
1460
1461 global_index = global_index + 1
1462
1463
1464 yield global_index
1465
1466
1468 """Return the k, n, and chi2 model statistics.
1469
1470 k - number of parameters.
1471 n - number of data points.
1472 chi2 - the chi-squared value.
1473
1474
1475 @keyword model_info: The model information from model_loop(). This index is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
1476 @type model_info: int
1477 @keyword spin_id: The spin identification string. Either this or the instance keyword argument must be supplied.
1478 @type spin_id: None or str
1479 @keyword global_stats: A parameter which determines if global or local statistics are returned. If None, then the appropriateness of global or local statistics is automatically determined.
1480 @type global_stats: None or bool
1481 @return: The optimisation statistics, in tuple format, of the number of parameters (k), the number of data points (n), and the chi-squared value (chi2).
1482 @rtype: tuple of (int, int, float)
1483 """
1484
1485
1486 if model_info == None and spin_id == None:
1487 raise RelaxError("Either the model_info or spin_id argument must be supplied.")
1488 elif model_info != None and spin_id != None:
1489 raise RelaxError("The model_info arg " + repr(model_info) + " and spin_id arg " + repr(spin_id) + " clash. Only one should be supplied.")
1490
1491
1492 model_type = determine_model_type()
1493
1494
1495 if global_stats == None:
1496 if model_type in ['mf', 'local_tm']:
1497 global_stats = False
1498 else:
1499 global_stats = True
1500
1501
1502 if not global_stats:
1503
1504 if spin_id:
1505 spin = return_spin(spin_id)
1506 else:
1507 spin = return_spin_from_index(model_info)
1508
1509
1510 if not spin.select:
1511 return None, None, None
1512
1513
1514 if not hasattr(spin, 'ri_data'):
1515 return None, None, None
1516
1517
1518 param_vector = assemble_param_vector(spin=spin)
1519 k = len(param_vector)
1520
1521
1522 n = len(spin.ri_data)
1523
1524
1525 chi2 = spin.chi2
1526
1527
1528 elif global_stats:
1529
1530 param_vector = assemble_param_vector()
1531 k = len(param_vector)
1532
1533
1534 n = 0
1535 chi2 = 0
1536 for spin in spin_loop():
1537
1538 if not spin.select:
1539 continue
1540
1541
1542 if not hasattr(spin, 'ri_data') or not len(spin.ri_data):
1543 continue
1544
1545 n = n + len(spin.ri_data)
1546
1547
1548 if model_type == 'local_tm':
1549 chi2 = chi2 + spin.chi2
1550
1551
1552 if model_type != 'local_tm':
1553 if not hasattr(cdp, 'chi2'):
1554 raise RelaxError("Global statistics are not available, most likely because the global model has not been optimised.")
1555 chi2 = cdp.chi2
1556
1557
1558 return k, n, chi2
1559
1560
1562 """Return the type of the model, either being 'local' or 'global'.
1563
1564 @return: The model type, one of 'local' or 'global'.
1565 @rtype: str
1566 """
1567
1568
1569 model_type = determine_model_type()
1570
1571
1572 if model_type in ['all', 'diff']:
1573 return 'global'
1574
1575
1576 else:
1577 return 'local'
1578
1579
1581 """Function for returning the number of instances.
1582
1583 @return: The number of instances used for optimisation. Either the number of spins if
1584 the local optimisations are setup ('mf' and 'local_tm'), or 1 for the global
1585 models.
1586 @rtype: int
1587 """
1588
1589
1590 if not exists_mol_res_spin_data():
1591 return 0
1592
1593
1594 model_type = determine_model_type()
1595
1596
1597 if model_type == 'mf' or model_type == 'local_tm':
1598 return count_spins()
1599
1600
1601 elif model_type == 'diff' or model_type == 'all':
1602 return 1
1603
1604
1605 else:
1606 raise RelaxFault
1607
1608
1610 """Deselect spins which have insufficient data to support minimisation.
1611
1612 @keyword data_check: A flag to signal if the presence of base data is to be checked for.
1613 @type data_check: bool
1614 @keyword verbose: A flag which if True will allow printouts.
1615 @type verbose: bool
1616 """
1617
1618
1619 if verbose:
1620 print("\nOver-fit spin deselection:")
1621
1622
1623 if not exists_mol_res_spin_data():
1624 raise RelaxNoSequenceError
1625
1626
1627 need_vect = False
1628 if hasattr(cdp, 'diff_tensor') and (cdp.diff_tensor.type == 'spheroid' or cdp.diff_tensor.type == 'ellipsoid'):
1629 need_vect = True
1630
1631
1632 deselect_flag = False
1633 spin_count = 0
1634 for spin, spin_id in spin_loop(return_id=True):
1635
1636 if not spin.select:
1637 continue
1638
1639
1640 interatoms = interatomic.return_interatom_list(spin_hash=spin._hash)
1641
1642
1643 dipole_relax = False
1644 for i in range(len(interatoms)):
1645
1646 if not interatoms[i].dipole_pair:
1647 continue
1648
1649
1650 if spin_id != interatoms[i].spin_id1:
1651 spin_id2 = interatoms[i].spin_id1
1652 else:
1653 spin_id2 = interatoms[i].spin_id2
1654 spin2 = return_spin(spin_id2)
1655
1656
1657 dipole_relax = True
1658
1659
1660 if not dipole_relax or not hasattr(spin, 'csa') or spin.csa == None:
1661 warn(RelaxDeselectWarning(spin_id, 'an absence of relaxation mechanisms'))
1662 spin.select = False
1663 deselect_flag = True
1664 continue
1665
1666
1667 if data_check:
1668
1669 data_points = 0
1670 inf_data = False
1671 if hasattr(cdp, 'ri_ids') and hasattr(spin, 'ri_data'):
1672 for id in cdp.ri_ids:
1673 if id in spin.ri_data and spin.ri_data[id] != None:
1674 data_points += 1
1675
1676
1677 if isInf(spin.ri_data[id]):
1678 inf_data = True
1679
1680
1681 if inf_data:
1682 warn(RelaxDeselectWarning(spin_id, 'infinite relaxation data'))
1683 spin.select = False
1684 deselect_flag = True
1685 continue
1686
1687
1688 if not hasattr(spin, 'ri_data'):
1689 warn(RelaxDeselectWarning(spin_id, 'missing relaxation data'))
1690 spin.select = False
1691 deselect_flag = True
1692 continue
1693
1694
1695 elif data_points < 3:
1696 warn(RelaxDeselectWarning(spin_id, 'insufficient relaxation data, 3 or more data points are required'))
1697 spin.select = False
1698 deselect_flag = True
1699 continue
1700
1701
1702 elif hasattr(spin, 'params') and spin.params and len(spin.params) > data_points:
1703 warn(RelaxDeselectWarning(spin_id, 'over-fitting - more parameters than data points'))
1704 spin.select = False
1705 deselect_flag = True
1706 continue
1707
1708
1709 for i in range(len(interatoms)):
1710
1711 if not interatoms[i].dipole_pair:
1712 continue
1713
1714
1715 if need_vect:
1716 if not hasattr(interatoms[i], 'vector') or interatoms[i].vector is None:
1717 warn(RelaxDeselectWarning(spin_id, 'missing structural data'))
1718 spin.select = False
1719 deselect_flag = True
1720 continue
1721
1722
1723 spin_count += 1
1724
1725
1726 if spin_count == 0:
1727 warn(RelaxWarning("No spins are selected therefore the optimisation or calculation cannot proceed."))
1728
1729
1730 if verbose and not deselect_flag:
1731 print("No spins have been deselected.")
1732
1733
1735 """Print out the model title.
1736
1737 @keyword prefix: The starting text of the title. This should be printed out first, followed by the model information text.
1738 @type prefix: str
1739 @keyword model_info: The model information from model_loop().
1740 @type model_info: unknown
1741 """
1742
1743
1744 model_type = determine_model_type()
1745
1746
1747 if model_type == 'mf' or model_type == 'local_tm':
1748 spin, spin_id = return_spin_from_index(global_index=model_info, return_spin_id=True)
1749 text = "%sSpin '%s'" % (prefix, spin_id)
1750
1751
1752 else:
1753 text = prefix + "Global model"
1754
1755
1756 subsection(file=sys.stdout, text=text, prespace=2)
1757
1758
1759 - def set_error(self, index, error, model_info=None):
1760 """Set the parameter errors.
1761
1762 @param index: The index of the parameter to set the errors for.
1763 @type index: int
1764 @param error: The error value.
1765 @type error: float
1766 @keyword model_info: The model information from model_loop(). This index is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
1767 @type model_info: int
1768 """
1769
1770
1771 inc = 0
1772
1773
1774 model_type = determine_model_type()
1775
1776
1777 param_names = self.data_names(set='params', scope='spin')
1778
1779
1780
1781
1782
1783 if model_type == 'diff' or model_type == 'all':
1784
1785 if cdp.diff_tensor.type == 'sphere':
1786
1787 if index == 0:
1788 cdp.diff_tensor.set(param='tm', value=error, category='err')
1789
1790
1791 inc = inc + 1
1792
1793
1794 elif cdp.diff_tensor.type == 'spheroid':
1795
1796 if index == 0:
1797 cdp.diff_tensor.set(param='tm', value=error, category='err')
1798 elif index == 1:
1799 cdp.diff_tensor.set(param='Da', value=error, category='err')
1800 elif index == 2:
1801 cdp.diff_tensor.set(param='theta', value=error, category='err')
1802 elif index == 3:
1803 cdp.diff_tensor.set(param='phi', value=error, category='err')
1804
1805
1806 inc = inc + 4
1807
1808
1809 elif cdp.diff_tensor.type == 'ellipsoid':
1810
1811 if index == 0:
1812 cdp.diff_tensor.set(param='tm', value=error, category='err')
1813 elif index == 1:
1814 cdp.diff_tensor.set(param='Da', value=error, category='err')
1815 elif index == 2:
1816 cdp.diff_tensor.set(param='Dr', value=error, category='err')
1817 elif index == 3:
1818 cdp.diff_tensor.set(param='alpha', value=error, category='err')
1819 elif index == 4:
1820 cdp.diff_tensor.set(param='beta', value=error, category='err')
1821 elif index == 5:
1822 cdp.diff_tensor.set(param='gamma', value=error, category='err')
1823
1824
1825 inc = inc + 6
1826
1827
1828
1829
1830
1831 if model_type == 'all':
1832
1833 for spin in spin_loop():
1834
1835 if not spin.select:
1836 continue
1837
1838
1839 for param in param_names:
1840
1841 if index == inc:
1842 setattr(spin, param + "_err", error)
1843
1844
1845 inc = inc + 1
1846
1847
1848
1849
1850
1851 if model_type == 'mf' or model_type == 'local_tm':
1852
1853 spin = return_spin_from_index(model_info)
1854
1855
1856 if not spin.select:
1857 return
1858
1859
1860 for param in param_names:
1861
1862 if index == inc:
1863 setattr(spin, param + "_err", error)
1864
1865
1866 inc = inc + 1
1867
1868
1869 - def set_param_values(self, param=None, value=None, index=None, spin_id=None, error=False, force=True):
1870 """Set the model-free parameter values.
1871
1872 @keyword param: The parameter name list.
1873 @type param: list of str
1874 @keyword value: The parameter value list.
1875 @type value: list
1876 @keyword index: The index for parameters which are of the list-type. This is unused.
1877 @type index: None or int
1878 @keyword spin_id: The spin identification string, only used for spin specific parameters.
1879 @type spin_id: None or str
1880 @keyword error: A flag which if True will allow the parameter errors to be set instead of the values.
1881 @type error: bool
1882 @keyword force: A flag which if True will cause current values to be overwritten. If False, a RelaxError will raised if the parameter value is already set.
1883 @type force: bool
1884 """
1885
1886
1887 is_str_list(param, 'parameter name')
1888
1889
1890 diff_params = []
1891 diff_vals = []
1892 mf_params = []
1893 mf_vals = []
1894 for i in range(len(param)):
1895
1896 if self._PARAMS.scope(param[i]) == 'global':
1897 if error:
1898 diff_params.append(param[i] + '_err')
1899 else:
1900 diff_params.append(param[i])
1901 diff_vals.append(value[i])
1902
1903
1904 else:
1905 mf_params.append(param[i])
1906 mf_vals.append(value[i])
1907
1908
1909 if diff_params:
1910 diffusion_tensor.set(value=diff_vals, param=diff_params)
1911
1912
1913 for i in range(len(mf_params)):
1914
1915 if mf_params[i] not in self.data_names(set='params', scope='spin') and mf_params[i] not in self.data_names(set='generic', scope='spin'):
1916 raise RelaxError("The parameter '%s' is unknown. It should be one of %s or %s" % (mf_params[i], self.data_names(set='params', scope='spin'), self.data_names(set='generic', scope='spin')))
1917
1918
1919 if error:
1920 mf_params[i] += '_err'
1921
1922
1923 for spin in spin_loop(spin_id):
1924 setattr(spin, mf_params[i], mf_vals[i])
1925
1926
1928 """Set all simulation selection flags.
1929
1930 @param select_sim: The selection flags.
1931 @type select_sim: bool
1932 @keyword model_info: The model information from model_loop(). This index is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
1933 @type model_info: int
1934 """
1935
1936
1937 model_type = determine_model_type()
1938
1939
1940 if model_type == 'all' or model_type == 'diff':
1941 cdp.select_sim = select_sim
1942
1943
1944 else:
1945
1946 spin = return_spin_from_index(model_info)
1947
1948
1949 if not spin.select:
1950 return
1951
1952
1953 spin.select_sim = deepcopy(select_sim)
1954
1955
1957 """Function to update the other model-free parameters.
1958
1959 @param param: The name of the parameter which has been changed.
1960 @type param: str
1961 @param spin: The SpinContainer object.
1962 @type spin: SpinContainer
1963 """
1964
1965
1966 if param == 's2f':
1967
1968 if hasattr(spin, 's2s') and spin.s2s != None:
1969 spin.s2 = spin.s2f * spin.s2s
1970
1971
1972
1973 if param == 's2s':
1974
1975 if hasattr(spin, 's2f') and spin.s2f != None:
1976 spin.s2 = spin.s2f * spin.s2s
1977
1978
1980 """Initialise the Monte Carlo parameter values."""
1981
1982
1983 model_type = determine_model_type()
1984
1985
1986 param_names = self.data_names(set='params', scope='spin')
1987
1988
1989 min_names = self.data_names(set='min', scope='spin')
1990
1991
1992 if model_type == 'diff' or model_type == 'all':
1993
1994 if cdp.diff_tensor.type == 'sphere':
1995 diff_params = ['tm']
1996
1997
1998 elif cdp.diff_tensor.type == 'spheroid':
1999 diff_params = ['tm', 'Da', 'theta', 'phi']
2000
2001
2002 elif cdp.diff_tensor.type == 'ellipsoid':
2003 diff_params = ['tm', 'Da', 'Dr', 'alpha', 'beta', 'gamma']
2004
2005
2006
2007
2008
2009
2010 if model_type == 'diff' or model_type == 'all':
2011
2012 for object_name in diff_params:
2013
2014 sim_object_name = object_name + '_sim'
2015
2016
2017 if hasattr(cdp.diff_tensor, sim_object_name):
2018 raise RelaxError("Monte Carlo parameter values have already been set.")
2019
2020
2021 for object_name in min_names:
2022
2023 sim_object_name = object_name + '_sim'
2024
2025
2026 if hasattr(cdp, sim_object_name):
2027 raise RelaxError("Monte Carlo parameter values have already been set.")
2028
2029
2030 if model_type != 'diff':
2031 for spin in spin_loop():
2032
2033 if not spin.select:
2034 continue
2035
2036
2037 for object_name in param_names:
2038
2039 sim_object_name = object_name + '_sim'
2040
2041
2042 if hasattr(spin, sim_object_name):
2043 raise RelaxError("Monte Carlo parameter values have already been set.")
2044
2045
2046
2047
2048
2049
2050 for object_name in min_names:
2051
2052 if not hasattr(cdp, object_name):
2053 continue
2054
2055
2056 sim_object_name = object_name + '_sim'
2057
2058
2059 setattr(cdp, sim_object_name, [])
2060
2061
2062 sim_object = getattr(cdp, sim_object_name)
2063
2064
2065 for j in range(cdp.sim_number):
2066
2067 object = getattr(cdp, object_name)
2068
2069
2070 sim_object.append(deepcopy(object))
2071
2072
2073 if model_type == 'diff' or model_type == 'all':
2074
2075 cdp.diff_tensor.set_sim_num(cdp.sim_number)
2076
2077
2078 for object_name in diff_params:
2079 for j in range(cdp.sim_number):
2080 cdp.diff_tensor.set(param=object_name, value=deepcopy(getattr(cdp.diff_tensor, object_name)), category='sim', sim_index=j)
2081
2082
2083 if model_type != 'diff':
2084 for spin in spin_loop():
2085
2086 if not spin.select:
2087 continue
2088
2089
2090 for object_name in param_names:
2091
2092 sim_object_name = object_name + '_sim'
2093
2094
2095 setattr(spin, sim_object_name, [])
2096
2097
2098 sim_object = getattr(spin, sim_object_name)
2099
2100
2101 for j in range(cdp.sim_number):
2102
2103 sim_object.append(deepcopy(getattr(spin, object_name)))
2104
2105
2106 for object_name in min_names:
2107
2108 sim_object_name = object_name + '_sim'
2109
2110
2111 setattr(spin, sim_object_name, [])
2112
2113
2114 sim_object = getattr(spin, sim_object_name)
2115
2116
2117 for j in range(cdp.sim_number):
2118
2119 sim_object.append(deepcopy(getattr(spin, object_name)))
2120
2121
2123 """Return the simulation chi-squared values.
2124
2125 @keyword index: The optional simulation index.
2126 @type index: int
2127 @keyword model_info: The model information from model_loop(). This index is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
2128 @type model_info: int
2129 @return: The list of simulation chi-squared values. If the index is supplied, only a single value will be returned.
2130 @rtype: list of float or float
2131 """
2132
2133
2134 model_type = determine_model_type()
2135
2136
2137 if model_type == 'all' or model_type == 'diff':
2138 return cdp.chi2_sim
2139
2140
2141 else:
2142
2143 spin = return_spin_from_index(model_info)
2144
2145
2146 return spin.chi2_sim
2147
2148
2150 """Return the array of simulation parameter values.
2151
2152 @param index: The index of the parameter to return the array of values for.
2153 @type index: int
2154 @keyword model_info: The model information from model_loop(). This index is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
2155 @type model_info: int
2156 @return: The array of simulation parameter values.
2157 @rtype: list of float
2158 """
2159
2160
2161 inc = 0
2162
2163
2164 model_type = determine_model_type()
2165
2166
2167 param_names = self.data_names(set='params', scope='spin')
2168
2169
2170
2171
2172
2173 if model_type == 'diff' or model_type == 'all':
2174
2175 if cdp.diff_tensor.type == 'sphere':
2176
2177 if index == 0:
2178 return cdp.diff_tensor.tm_sim
2179
2180
2181 inc = inc + 1
2182
2183
2184 elif cdp.diff_tensor.type == 'spheroid':
2185
2186 if index == 0:
2187 return cdp.diff_tensor.tm_sim
2188 elif index == 1:
2189 return cdp.diff_tensor.Da_sim
2190 elif index == 2:
2191 return cdp.diff_tensor.theta_sim
2192 elif index == 3:
2193 return cdp.diff_tensor.phi_sim
2194
2195
2196 inc = inc + 4
2197
2198
2199 elif cdp.diff_tensor.type == 'ellipsoid':
2200
2201 if index == 0:
2202 return cdp.diff_tensor.tm_sim
2203 elif index == 1:
2204 return cdp.diff_tensor.Da_sim
2205 elif index == 2:
2206 return cdp.diff_tensor.Dr_sim
2207 elif index == 3:
2208 return cdp.diff_tensor.alpha_sim
2209 elif index == 4:
2210 return cdp.diff_tensor.beta_sim
2211 elif index == 5:
2212 return cdp.diff_tensor.gamma_sim
2213
2214
2215 inc = inc + 6
2216
2217
2218
2219
2220
2221 if model_type == 'all':
2222
2223 for spin in spin_loop():
2224
2225 if not spin.select:
2226 continue
2227
2228
2229 for param in param_names:
2230
2231 if index == inc:
2232 return getattr(spin, param + "_sim")
2233
2234
2235 inc = inc + 1
2236
2237
2238
2239
2240
2241 if model_type == 'mf' or model_type == 'local_tm':
2242
2243 spin = return_spin_from_index(model_info)
2244
2245
2246 if not spin.select:
2247 return
2248
2249
2250 for param in param_names:
2251
2252 if index == inc:
2253 return getattr(spin, param + "_sim")
2254
2255
2256 inc = inc + 1
2257
2258
2260 """Return the array of selected simulation flags for the spin.
2261
2262 @keyword model_info: The model information from model_loop(). This index is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
2263 @type model_info: int
2264 @return: The array of selected simulation flags.
2265 @rtype: list of int
2266 """
2267
2268
2269 model_type = determine_model_type()
2270
2271
2272 if model_type == 'all' or model_type == 'diff':
2273 return cdp.select_sim
2274
2275
2276 else:
2277
2278 spin = return_spin_from_index(model_info)
2279
2280
2281 if not spin.select:
2282 return
2283
2284
2285 return spin.select_sim
2286
2287
2289 """Skip certain data.
2290
2291 @keyword model_info: The model information from model_loop(). This index is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
2292 @type model_info: int
2293 @return: True if the data should be skipped, False otherwise.
2294 @rtype: bool
2295 """
2296
2297
2298 model_type = determine_model_type()
2299
2300
2301 if (model_type == 'mf' or model_type == 'local_tm') and not return_spin_from_index(model_info).select:
2302 return True
2303
2304
2305 return False
2306
2307
2308
2310 """Empty class to be used for data storage."""
2311