Example #1
0
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'
Example #2
0
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'
Example #3
0
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
Example #4
0
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