def determine_model_type(): """Determine the global model type. @return: The name of the model type, which will be one of 'all', 'diff', 'mf', or 'local_tm'. If all parameters are fixed (and no spins selected), None is returned. @rtype: str or None """ # Test if sequence data is loaded. if not exists_mol_res_spin_data(): raise RelaxNoSequenceError # If there is a local tm, fail if not all residues have a local tm parameter. local_tm = False for spin in spin_loop(): # Skip deselected spins. if not spin.select: continue # No params. if not hasattr(spin, 'params') or not spin.params: continue # Local tm. if not local_tm and 'local_tm' in spin.params: local_tm = True # Inconsistencies. elif local_tm and not 'local_tm' in spin.params: raise RelaxError("All spins must either have a local tm parameter or not.") # Check if any model-free parameters are allowed to vary. mf_all_fixed = True mf_all_deselected = True for spin in spin_loop(): # Skip deselected spins. if not spin.select: continue # At least one spin is selected. mf_all_deselected = False # Test the fixed flag. if not hasattr(spin, 'fixed'): mf_all_fixed = False break if not spin.fixed: mf_all_fixed = False break # No spins selected?!? if mf_all_deselected: # All parameters fixed! if not hasattr(cdp, 'diff_tensor') or cdp.diff_tensor.fixed: return None return 'diff' # Local tm. if local_tm: return 'local_tm' # Test if the diffusion tensor data is loaded. if not diffusion_tensor.diff_data_exists(): # Catch when the local tm value is set but not in the parameter list. for spin in spin_loop(): if hasattr(spin, 'local_tm') and spin.local_tm != None and not 'local_tm' in spin.params: raise RelaxError("The local tm value is set but not located in the model parameter list.") # Normal error. raise RelaxNoTensorError('diffusion') # 'diff' model type. if mf_all_fixed: # All parameters fixed! if cdp.diff_tensor.fixed: return None return 'diff' # 'mf' model type. if cdp.diff_tensor.fixed: return 'mf' # 'all' model type. else: return 'all'
def determine_model_type(): """Determine the global model type. @return: The name of the model type, which will be one of 'all', 'diff', 'mf', or 'local_tm'. If all parameters are fixed (and no spins selected), None is returned. @rtype: str or None """ # Test if sequence data is loaded. if not exists_mol_res_spin_data(): raise RelaxNoSequenceError # If there is a local tm, fail if not all residues have a local tm parameter. local_tm = False for spin in spin_loop(): # Skip deselected spins. if not spin.select: continue # No params. if not hasattr(spin, 'params') or not spin.params: continue # Local tm. if not local_tm and 'local_tm' in spin.params: local_tm = True # Inconsistencies. elif local_tm and not 'local_tm' in spin.params: raise RelaxError( "All spins must either have a local tm parameter or not.") # Check if any model-free parameters are allowed to vary. mf_all_fixed = True mf_all_deselected = True for spin in spin_loop(): # Skip deselected spins. if not spin.select: continue # At least one spin is selected. mf_all_deselected = False # Test the fixed flag. if not hasattr(spin, 'fixed'): mf_all_fixed = False break if not spin.fixed: mf_all_fixed = False break # No spins selected?!? if mf_all_deselected: # All parameters fixed! if not hasattr(cdp, 'diff_tensor') or cdp.diff_tensor.fixed: return None return 'diff' # Local tm. if local_tm: return 'local_tm' # Test if the diffusion tensor data is loaded. if not diffusion_tensor.diff_data_exists(): # Catch when the local tm value is set but not in the parameter list. for spin in spin_loop(): if hasattr( spin, 'local_tm' ) and spin.local_tm != None and not 'local_tm' in spin.params: raise RelaxError( "The local tm value is set but not located in the model parameter list." ) # Normal error. raise RelaxNoTensorError('diffusion') # 'diff' model type. if mf_all_fixed: # All parameters fixed! if cdp.diff_tensor.fixed: return None return 'diff' # 'mf' model type. if cdp.diff_tensor.fixed: return 'mf' # 'all' model type. else: return 'all'
def linear_constraints(num_params, model_type=None, spin=None, spin_id=None, scaling_matrix=None): """Set up the model-free linear constraint matrices A and b. Standard notation ================= The order parameter constraints are:: 0 <= S2 <= 1 0 <= S2f <= 1 0 <= S2s <= 1 By substituting the formula S2 = S2f.S2s into the above inequalities, the additional two inequalities can be derived:: S2 <= S2f S2 <= S2s Correlation time constraints are:: te >= 0 tf >= 0 ts >= 0 tf <= ts te, tf, ts <= 2 * tm Additional constraints used include:: Rex >= 0 0.9e-10 <= r <= 2e-10 -300e-6 <= CSA <= 0 Rearranged notation =================== The above inequality constraints can be rearranged into:: S2 >= 0 -S2 >= -1 S2f >= 0 -S2f >= -1 S2s >= 0 -S2s >= -1 S2f - S2 >= 0 S2s - S2 >= 0 te >= 0 tf >= 0 ts >= 0 ts - tf >= 0 Rex >= 0 r >= 0.9e-10 -r >= -2e-10 CSA >= -300e-6 -CSA >= 0 Matrix notation =============== In the notation A.x >= b, where A is an matrix of coefficients, x is an array of parameter values, and b is a vector of scalars, these inequality constraints are:: | 1 0 0 0 0 0 0 0 0 | | 0 | | | | | |-1 0 0 0 0 0 0 0 0 | | -1 | | | | | | 0 1 0 0 0 0 0 0 0 | | 0 | | | | | | 0 -1 0 0 0 0 0 0 0 | | -1 | | | | | | 0 0 1 0 0 0 0 0 0 | | S2 | | 0 | | | | | | | | 0 0 -1 0 0 0 0 0 0 | | S2f | | -1 | | | | | | | |-1 1 0 0 0 0 0 0 0 | | S2s | | 0 | | | | | | | |-1 0 1 0 0 0 0 0 0 | | te | | 0 | | | | | | | | 0 0 0 1 0 0 0 0 0 | . | tf | >= | 0 | | | | | | | | 0 0 0 0 1 0 0 0 0 | | ts | | 0 | | | | | | | | 0 0 0 0 0 1 0 0 0 | | Rex | | 0 | | | | | | | | 0 0 0 0 -1 1 0 0 0 | | r | | 0 | | | | | | | | 0 0 0 0 0 0 1 0 0 | | CSA | | 0 | | | | | | 0 0 0 0 0 0 0 1 0 | | 0.9e-10 | | | | | | 0 0 0 0 0 0 0 -1 0 | | -2e-10 | | | | | | 0 0 0 0 0 0 0 0 1 | | -300e-6 | | | | | | 0 0 0 0 0 0 0 0 -1 | | 0 | @param num_params: The number of parameters in the model. @type num_params: int @keyword model_type: The model type, one of 'all', 'diff', 'mf', or 'local_tm'. @type model_type: str @keyword spin: The spin data container. If this argument is supplied, then the spin_id argument will be ignored. @type spin: SpinContainer instance @keyword spin_id: The spin identification string. @type spin_id: str @keyword scaling_matrix: The diagonal, square scaling matrix. @type scaling_matrix: numpy diagonal matrix """ # Upper limit flag for correlation times. upper_time_limit = 1 # Initialisation (0..j..m). A = [] b = [] zero_array = zeros(num_params, float64) i = 0 j = 0 # Diffusion tensor parameters. if model_type != 'mf' and diffusion_tensor.diff_data_exists(): # Spherical diffusion. if cdp.diff_tensor.type == 'sphere': # 0 <= tm <= 200 ns. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(0.0 / scaling_matrix[i, i]) b.append(-200.0 * 1e-9 / scaling_matrix[i, i]) i = i + 1 j = j + 2 # Spheroidal diffusion. elif cdp.diff_tensor.type == 'spheroid': # 0 <= tm <= 200 ns. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(0.0 / scaling_matrix[i, i]) b.append(-200.0 * 1e-9 / scaling_matrix[i, i]) i = i + 1 j = j + 2 # Prolate diffusion, Da >= 0. if cdp.diff_tensor.spheroid_type == 'prolate': A.append(zero_array * 0.0) A[j][i] = 1.0 b.append(0.0 / scaling_matrix[i, i]) i = i + 1 j = j + 1 # Add two to i for the theta and phi parameters. i = i + 2 # Oblate diffusion, Da <= 0. elif cdp.diff_tensor.spheroid_type == 'oblate': A.append(zero_array * 0.0) A[j][i] = -1.0 b.append(0.0 / scaling_matrix[i, i]) i = i + 1 j = j + 1 # Add two to i for the theta and phi parameters. i = i + 2 else: # Add three to i for the Da, theta and phi parameters. i = i + 3 # Ellipsoidal diffusion. elif cdp.diff_tensor.type == 'ellipsoid': # 0 <= tm <= 200 ns. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(0.0 / scaling_matrix[i, i]) b.append(-200.0 * 1e-9 / scaling_matrix[i, i]) i = i + 1 j = j + 2 # Da >= 0. A.append(zero_array * 0.0) A[j][i] = 1.0 b.append(0.0 / scaling_matrix[i, i]) i = i + 1 j = j + 1 # 0 <= Dr <= 1. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(0.0 / scaling_matrix[i, i]) b.append(-1.0 / scaling_matrix[i, i]) i = i + 1 j = j + 2 # Add three to i for the alpha, beta, and gamma parameters. i = i + 3 # Model-free parameters. if model_type != 'diff': # The loop. if spin: loop = [spin] else: loop = spin_loop(spin_id) # Loop over the spins. for spin in loop: # Skip deselected spins. if not spin.select: continue # Save current value of i. old_i = i # Loop over the model-free parameters. for l in range(len(spin.params)): # Local tm. if spin.params[l] == 'local_tm': if upper_time_limit: # 0 <= tm <= 200 ns. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(0.0 / scaling_matrix[i, i]) b.append(-200.0 * 1e-9 / scaling_matrix[i, i]) j = j + 2 else: # 0 <= tm. A.append(zero_array * 0.0) A[j][i] = 1.0 b.append(0.0 / scaling_matrix[i, i]) j = j + 1 # Order parameters {S2, S2f, S2s}. elif match('s2', spin.params[l]): # 0 <= S2 <= 1. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(0.0 / scaling_matrix[i, i]) b.append(-1.0 / scaling_matrix[i, i]) j = j + 2 # S2 <= S2f and S2 <= S2s. if spin.params[l] == 's2': for m in range(len(spin.params)): if spin.params[m] == 's2f' or spin.params[ m] == 's2s': A.append(zero_array * 0.0) A[j][i] = -1.0 A[j][old_i + m] = 1.0 b.append(0.0) j = j + 1 # Correlation times {te, tf, ts}. elif match('t[efs]', spin.params[l]): # te, tf, ts >= 0. A.append(zero_array * 0.0) A[j][i] = 1.0 b.append(0.0 / scaling_matrix[i, i]) j = j + 1 # tf <= ts. if spin.params[l] == 'ts': for m in range(len(spin.params)): if spin.params[m] == 'tf': A.append(zero_array * 0.0) A[j][i] = 1.0 A[j][old_i + m] = -1.0 b.append(0.0) j = j + 1 # te, tf, ts <= 2 * tm. (tf not needed because tf <= ts). if upper_time_limit: if not spin.params[l] == 'tf': if model_type == 'mf': A.append(zero_array * 0.0) A[j][i] = -1.0 b.append(-2.0 * cdp.diff_tensor.tm / scaling_matrix[i, i]) else: A.append(zero_array * 0.0) A[j][0] = 2.0 A[j][i] = -1.0 b.append(0.0) j = j + 1 # Rex. elif spin.params[l] == 'rex': A.append(zero_array * 0.0) A[j][i] = 1.0 b.append(0.0 / scaling_matrix[i, i]) j = j + 1 # Bond length. elif spin.params[l] == 'r': # 0.9e-10 <= r <= 2e-10. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(0.9e-10 / scaling_matrix[i, i]) b.append(-2e-10 / scaling_matrix[i, i]) j = j + 2 # CSA. elif spin.params[l] == 'csa': # -300e-6 <= CSA <= 0. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(-300e-6 / scaling_matrix[i, i]) b.append(0.0 / scaling_matrix[i, i]) j = j + 2 # Increment i. i = i + 1 # Convert to numpy data structures. A = array(A, int8) b = array(b, float64) return A, b
def linear_constraints(num_params, model_type=None, spin=None, spin_id=None, scaling_matrix=None): """Set up the model-free linear constraint matrices A and b. Standard notation ================= The order parameter constraints are:: 0 <= S2 <= 1 0 <= S2f <= 1 0 <= S2s <= 1 By substituting the formula S2 = S2f.S2s into the above inequalities, the additional two inequalities can be derived:: S2 <= S2f S2 <= S2s Correlation time constraints are:: te >= 0 tf >= 0 ts >= 0 tf <= ts te, tf, ts <= 2 * tm Additional constraints used include:: Rex >= 0 0.9e-10 <= r <= 2e-10 -300e-6 <= CSA <= 0 Rearranged notation =================== The above inequality constraints can be rearranged into:: S2 >= 0 -S2 >= -1 S2f >= 0 -S2f >= -1 S2s >= 0 -S2s >= -1 S2f - S2 >= 0 S2s - S2 >= 0 te >= 0 tf >= 0 ts >= 0 ts - tf >= 0 Rex >= 0 r >= 0.9e-10 -r >= -2e-10 CSA >= -300e-6 -CSA >= 0 Matrix notation =============== In the notation A.x >= b, where A is an matrix of coefficients, x is an array of parameter values, and b is a vector of scalars, these inequality constraints are:: | 1 0 0 0 0 0 0 0 0 | | 0 | | | | | |-1 0 0 0 0 0 0 0 0 | | -1 | | | | | | 0 1 0 0 0 0 0 0 0 | | 0 | | | | | | 0 -1 0 0 0 0 0 0 0 | | -1 | | | | | | 0 0 1 0 0 0 0 0 0 | | S2 | | 0 | | | | | | | | 0 0 -1 0 0 0 0 0 0 | | S2f | | -1 | | | | | | | |-1 1 0 0 0 0 0 0 0 | | S2s | | 0 | | | | | | | |-1 0 1 0 0 0 0 0 0 | | te | | 0 | | | | | | | | 0 0 0 1 0 0 0 0 0 | . | tf | >= | 0 | | | | | | | | 0 0 0 0 1 0 0 0 0 | | ts | | 0 | | | | | | | | 0 0 0 0 0 1 0 0 0 | | Rex | | 0 | | | | | | | | 0 0 0 0 -1 1 0 0 0 | | r | | 0 | | | | | | | | 0 0 0 0 0 0 1 0 0 | | CSA | | 0 | | | | | | 0 0 0 0 0 0 0 1 0 | | 0.9e-10 | | | | | | 0 0 0 0 0 0 0 -1 0 | | -2e-10 | | | | | | 0 0 0 0 0 0 0 0 1 | | -300e-6 | | | | | | 0 0 0 0 0 0 0 0 -1 | | 0 | @param num_params: The number of parameters in the model. @type num_params: int @keyword model_type: The model type, one of 'all', 'diff', 'mf', or 'local_tm'. @type model_type: str @keyword spin: The spin data container. If this argument is supplied, then the spin_id argument will be ignored. @type spin: SpinContainer instance @keyword spin_id: The spin identification string. @type spin_id: str @keyword scaling_matrix: The diagonal, square scaling matrix. @type scaling_matrix: numpy diagonal matrix """ # Upper limit flag for correlation times. upper_time_limit = 1 # Initialisation (0..j..m). A = [] b = [] zero_array = zeros(num_params, float64) i = 0 j = 0 # Diffusion tensor parameters. if model_type != "mf" and diffusion_tensor.diff_data_exists(): # Spherical diffusion. if cdp.diff_tensor.type == "sphere": # 0 <= tm <= 200 ns. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(0.0 / scaling_matrix[i, i]) b.append(-200.0 * 1e-9 / scaling_matrix[i, i]) i = i + 1 j = j + 2 # Spheroidal diffusion. elif cdp.diff_tensor.type == "spheroid": # 0 <= tm <= 200 ns. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(0.0 / scaling_matrix[i, i]) b.append(-200.0 * 1e-9 / scaling_matrix[i, i]) i = i + 1 j = j + 2 # Prolate diffusion, Da >= 0. if cdp.diff_tensor.spheroid_type == "prolate": A.append(zero_array * 0.0) A[j][i] = 1.0 b.append(0.0 / scaling_matrix[i, i]) i = i + 1 j = j + 1 # Add two to i for the theta and phi parameters. i = i + 2 # Oblate diffusion, Da <= 0. elif cdp.diff_tensor.spheroid_type == "oblate": A.append(zero_array * 0.0) A[j][i] = -1.0 b.append(0.0 / scaling_matrix[i, i]) i = i + 1 j = j + 1 # Add two to i for the theta and phi parameters. i = i + 2 else: # Add three to i for the Da, theta and phi parameters. i = i + 3 # Ellipsoidal diffusion. elif cdp.diff_tensor.type == "ellipsoid": # 0 <= tm <= 200 ns. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(0.0 / scaling_matrix[i, i]) b.append(-200.0 * 1e-9 / scaling_matrix[i, i]) i = i + 1 j = j + 2 # Da >= 0. A.append(zero_array * 0.0) A[j][i] = 1.0 b.append(0.0 / scaling_matrix[i, i]) i = i + 1 j = j + 1 # 0 <= Dr <= 1. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(0.0 / scaling_matrix[i, i]) b.append(-1.0 / scaling_matrix[i, i]) i = i + 1 j = j + 2 # Add three to i for the alpha, beta, and gamma parameters. i = i + 3 # Model-free parameters. if model_type != "diff": # The loop. if spin: loop = [spin] else: loop = spin_loop(spin_id) # Loop over the spins. for spin in loop: # Skip deselected spins. if not spin.select: continue # Save current value of i. old_i = i # Loop over the model-free parameters. for l in range(len(spin.params)): # Local tm. if spin.params[l] == "local_tm": if upper_time_limit: # 0 <= tm <= 200 ns. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(0.0 / scaling_matrix[i, i]) b.append(-200.0 * 1e-9 / scaling_matrix[i, i]) j = j + 2 else: # 0 <= tm. A.append(zero_array * 0.0) A[j][i] = 1.0 b.append(0.0 / scaling_matrix[i, i]) j = j + 1 # Order parameters {S2, S2f, S2s}. elif match("s2", spin.params[l]): # 0 <= S2 <= 1. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(0.0 / scaling_matrix[i, i]) b.append(-1.0 / scaling_matrix[i, i]) j = j + 2 # S2 <= S2f and S2 <= S2s. if spin.params[l] == "s2": for m in range(len(spin.params)): if spin.params[m] == "s2f" or spin.params[m] == "s2s": A.append(zero_array * 0.0) A[j][i] = -1.0 A[j][old_i + m] = 1.0 b.append(0.0) j = j + 1 # Correlation times {te, tf, ts}. elif match("t[efs]", spin.params[l]): # te, tf, ts >= 0. A.append(zero_array * 0.0) A[j][i] = 1.0 b.append(0.0 / scaling_matrix[i, i]) j = j + 1 # tf <= ts. if spin.params[l] == "ts": for m in range(len(spin.params)): if spin.params[m] == "tf": A.append(zero_array * 0.0) A[j][i] = 1.0 A[j][old_i + m] = -1.0 b.append(0.0) j = j + 1 # te, tf, ts <= 2 * tm. (tf not needed because tf <= ts). if upper_time_limit: if not spin.params[l] == "tf": if model_type == "mf": A.append(zero_array * 0.0) A[j][i] = -1.0 b.append(-2.0 * cdp.diff_tensor.tm / scaling_matrix[i, i]) else: A.append(zero_array * 0.0) A[j][0] = 2.0 A[j][i] = -1.0 b.append(0.0) j = j + 1 # Rex. elif spin.params[l] == "rex": A.append(zero_array * 0.0) A[j][i] = 1.0 b.append(0.0 / scaling_matrix[i, i]) j = j + 1 # Bond length. elif spin.params[l] == "r": # 0.9e-10 <= r <= 2e-10. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(0.9e-10 / scaling_matrix[i, i]) b.append(-2e-10 / scaling_matrix[i, i]) j = j + 2 # CSA. elif spin.params[l] == "csa": # -300e-6 <= CSA <= 0. A.append(zero_array * 0.0) A.append(zero_array * 0.0) A[j][i] = 1.0 A[j + 1][i] = -1.0 b.append(-300e-6 / scaling_matrix[i, i]) b.append(0.0 / scaling_matrix[i, i]) j = j + 2 # Increment i. i = i + 1 # Convert to numpy data structures. A = array(A, int8) b = array(b, float64) return A, b