Esempio n. 1
0
    def test_value_set_r1_rit(self):
        """Test of the pipe_control.value.set() function."""

        # Set the current data pipe to 'mf'.
        pipes.switch('relax_disp')

        # Set variables.
        exp_type = 'R1rho'
        frq = 800.1 * 1E6

        # Set an experiment type to the pipe.
        set_exp_type(spectrum_id='test', exp_type=exp_type)

        # Set a frequency to loop through.
        spectrometer.set_frequency(id='test', frq=frq, units='Hz')

        # Generate dic key.
        r20_key = generate_r20_key(exp_type=exp_type, frq=frq)

        # Set first similar to r2.
        value.set(val=None, param='r2')
        self.assertEqual(cdp.mol[0].res[0].spin[0].r2[r20_key], 10.0)

        # Then set for r1.
        value.set(val=None, param='r1')
        print(cdp.mol[0].res[0].spin[0])
        self.assertEqual(cdp.mol[0].res[0].spin[0].r1[r20_key], 2.0)
Esempio n. 2
0
    def test_value_set_r1_rit(self):
        """Test of the pipe_control.value.set() function."""

        # Set the current data pipe to 'mf'.
        pipes.switch('relax_disp')

        # Set variables.
        exp_type = 'R1rho'
        frq = 800.1 * 1E6

        # Set an experiment type to the pipe.
        set_exp_type(spectrum_id='test', exp_type=exp_type)

        # Set a frequency to loop through.
        spectrometer.set_frequency(id='test', frq=frq, units='Hz')

        # Generate dic key.
        r20_key = generate_r20_key(exp_type=exp_type, frq=frq)

        # Set first similar to r2.
        value.set(val=None, param='r2')
        self.assertEqual(cdp.mol[0].res[0].spin[0].r2[r20_key], 10.0)

        # Then set for r1.
        value.set(val=None, param='r1')
        print(cdp.mol[0].res[0].spin[0])
        self.assertEqual(cdp.mol[0].res[0].spin[0].r1[r20_key], 2.0)
Esempio n. 3
0
def pack_data(ri_id,
              ri_type,
              frq,
              values,
              errors,
              spin_ids=None,
              mol_names=None,
              res_nums=None,
              res_names=None,
              spin_nums=None,
              spin_names=None,
              spin_id=None,
              gen_seq=False,
              verbose=True):
    """Pack the relaxation data into the data pipe and spin containers.

    The values, errors, and spin_ids arguments must be lists of equal length or None.  Each element i corresponds to a unique spin.

    @param ri_id:           The relaxation data ID string.
    @type ri_id:            str
    @param ri_type:         The relaxation data type, ie 'R1', 'R2', or 'NOE'.
    @type ri_type:          str
    @param frq:             The spectrometer proton frequency in Hz.
    @type frq:              float
    @keyword values:        The relaxation data for each spin.
    @type values:           None or list of float or float array
    @keyword errors:        The relaxation data errors for each spin.
    @type errors:           None or list of float or float array
    @keyword spin_ids:      The list of spin ID strings.  If the other spin identifiers are given, i.e. mol_names, res_nums, res_names, spin_nums, and/or spin_names, then this argument is not necessary.
    @type spin_ids:         None or list of str
    @keyword mol_names:     The list of molecule names used for creating the spin IDs (if not given) or for generating the sequence data.
    @type mol_names:        None or list of str
    @keyword res_nums:      The list of residue numbers used for creating the spin IDs (if not given) or for generating the sequence data.
    @type res_nums:         None or list of str
    @keyword res_names:     The list of residue names used for creating the spin IDs (if not given) or for generating the sequence data.
    @type res_names:        None or list of str
    @keyword spin_nums:     The list of spin numbers used for creating the spin IDs (if not given) or for generating the sequence data.
    @type spin_nums:        None or list of str
    @keyword spin_names:    The list of spin names used for creating the spin IDs (if not given) or for generating the sequence data.
    @type spin_names:       None or list of str
    @keyword gen_seq:       A flag which if True will cause the molecule, residue, and spin sequence data to be generated.
    @type gen_seq:          bool
    @keyword verbose:       A flag which if True will cause all relaxation data loaded to be printed out.
    @type verbose:          bool
    """

    # The number of spins.
    N = len(values)

    # Test the data.
    if errors != None and len(errors) != N:
        raise RelaxError(
            "The length of the errors arg (%s) does not match that of the value arg (%s)."
            % (len(errors), N))
    if spin_ids and len(spin_ids) != N:
        raise RelaxError(
            "The length of the spin ID strings arg (%s) does not match that of the value arg (%s)."
            % (len(mol_names), N))
    if mol_names and len(mol_names) != N:
        raise RelaxError(
            "The length of the molecule names arg (%s) does not match that of the value arg (%s)."
            % (len(mol_names), N))
    if res_nums and len(res_nums) != N:
        raise RelaxError(
            "The length of the residue numbers arg (%s) does not match that of the value arg (%s)."
            % (len(res_nums), N))
    if res_names and len(res_names) != N:
        raise RelaxError(
            "The length of the residue names arg (%s) does not match that of the value arg (%s)."
            % (len(res_names), N))
    if spin_nums and len(spin_nums) != N:
        raise RelaxError(
            "The length of the spin numbers arg (%s) does not match that of the value arg (%s)."
            % (len(spin_nums), N))
    if spin_names and len(spin_names) != N:
        raise RelaxError(
            "The length of the spin names arg (%s) does not match that of the value arg (%s)."
            % (len(spin_names), N))

    # Generate some empty lists.
    if not mol_names:
        mol_names = [None] * N
    if not res_nums:
        res_nums = [None] * N
    if not res_names:
        res_names = [None] * N
    if not spin_nums:
        spin_nums = [None] * N
    if not spin_names:
        spin_names = [None] * N
    if errors == None:
        errors = [None] * N

    # Generate the spin IDs.
    if not spin_ids:
        spin_ids = []
        for i in range(N):
            spin_ids.append(
                generate_spin_id_unique(spin_num=spin_nums[i],
                                        spin_name=spin_names[i],
                                        res_num=res_nums[i],
                                        res_name=res_names[i],
                                        mol_name=mol_names[i]))

    # Initialise the global data for the current pipe if necessary.
    if not hasattr(cdp, 'ri_type'):
        cdp.ri_type = {}
    if not hasattr(cdp, 'ri_ids'):
        cdp.ri_ids = []

    # Set the spectrometer frequency.
    set_frequency(id=ri_id, frq=frq)

    # Update the global data.
    cdp.ri_ids.append(ri_id)
    cdp.ri_type[ri_id] = ri_type

    # The selection object.
    select_obj = None
    if spin_id:
        select_obj = Selection(spin_id)

    # Loop over the spin data.
    data = []
    for i in range(N):
        # A selection union.
        select_id = spin_ids[i]
        if spin_id != None:
            select_id = "%s&%s" % (select_id, spin_id)

        # Get the corresponding spin container.
        match_mol_names, match_res_nums, match_res_names, spins = return_spin_from_selection(
            selection=select_id, full_info=True, multi=True)

        # No spin.
        if len(spins) == 0:
            continue

        # Check that multiple spins are not present.
        if len(spins) > 1:
            # Generate the list of spin IDs.
            new_ids = []
            for j in range(len(spins)):
                new_ids.append(
                    generate_spin_id_unique(mol_name=match_mol_names[j],
                                            res_num=match_res_nums[j],
                                            res_name=match_res_names[j],
                                            spin_num=spins[j].num,
                                            spin_name=spins[j].name))

            # Raise the error.
            raise RelaxMultiSpinIDError(spin_ids[i], new_ids)

        # Check that at least one spin is present.
        if len(spins) == 0:
            raise RelaxNoSpinError(spin_ids[i])

        # Loop over the spins.
        for j in range(len(spins)):
            # No match to the selection.
            if select_obj and not select_obj.contains_spin(
                    spin_num=spins[j].num,
                    spin_name=spins[j].name,
                    res_num=res_nums[j],
                    res_name=res_names[j],
                    mol=mol_names[j]):
                continue

            # Initialise the spin data if necessary.
            if not hasattr(spins[j], 'ri_data') or spins[j].ri_data == None:
                spins[j].ri_data = {}
            if not hasattr(spins[j],
                           'ri_data_err') or spins[j].ri_data_err == None:
                spins[j].ri_data_err = {}

            # Update all data structures.
            spins[j].ri_data[ri_id] = values[i]
            spins[j].ri_data_err[ri_id] = errors[i]

            # Append the data for printing out.
            data.append([spin_ids[i], repr(values[i]), repr(errors[i])])

    # Print out.
    if verbose:
        print(
            "\nThe following %s MHz %s relaxation data with the ID '%s' has been loaded into the relax data store:\n"
            % (frq / 1e6, ri_type, ri_id))
        write_data(out=sys.stdout,
                   headings=["Spin_ID", "Value", "Error"],
                   data=data)
Esempio n. 4
0
def back_calc(ri_id=None, ri_type=None, frq=None):
    """Back calculate the relaxation data.

    If no relaxation data currently exists, then the ri_id, ri_type, and frq args are required.


    @keyword ri_id:     The relaxation data ID string.  If not given, all relaxation data will be back calculated.
    @type ri_id:        None or str
    @keyword ri_type:   The relaxation data type.  This should be one of 'R1', 'R2', or 'NOE'.
    @type ri_type:      None or str
    @keyword frq:       The spectrometer proton frequency in Hz.
    @type frq:          None or float
    """

    # Test if the current pipe exists.
    check_pipe()

    # Test if sequence data is loaded.
    if not exists_mol_res_spin_data():
        raise RelaxNoSequenceError

    # Check that ri_type and frq are supplied if no relaxation data exists.
    if ri_id and (not hasattr(cdp, 'ri_ids') or ri_id
                  not in cdp.ri_ids) and (ri_type == None or frq == None):
        raise RelaxError(
            "The 'ri_type' and 'frq' arguments must be supplied as no relaxation data corresponding to '%s' exists."
            % ri_id)

    # Check if the type is valid.
    if ri_type and ri_type not in VALID_TYPES:
        raise RelaxError("The relaxation data type '%s' must be one of %s." %
                         (ri_type, VALID_TYPES))

    # Frequency checks.
    frequency_checks(frq)

    # Initialise the global data for the current pipe if necessary.
    if not hasattr(cdp, 'ri_type'):
        cdp.ri_type = {}
    if not hasattr(cdp, 'ri_ids'):
        cdp.ri_ids = []

    # Update the global data if needed.
    if ri_id and ri_id not in cdp.ri_ids:
        cdp.ri_ids.append(ri_id)
        cdp.ri_type[ri_id] = ri_type
        set_frequency(id=ri_id, frq=frq)

    # The specific analysis API object.
    api = return_api()

    # The IDs to loop over.
    if ri_id == None:
        ri_ids = cdp.ri_ids
    else:
        ri_ids = [ri_id]

    # The data types.
    if ri_type == None:
        ri_types = cdp.ri_type
    else:
        ri_types = {ri_id: ri_type}

    # The frequencies.
    if frq == None:
        frqs = cdp.spectrometer_frq
    else:
        frqs = {ri_id: frq}

    # Loop over the spins.
    for spin, spin_id in spin_loop(return_id=True):
        # Skip deselected spins.
        if not spin.select:
            continue

        # The global index.
        spin_index = find_index(spin_id)

        # Initialise the spin data if necessary.
        if not hasattr(spin, 'ri_data_bc'):
            spin.ri_data_bc = {}

        # Back-calculate the relaxation value.
        for ri_id in ri_ids:
            spin.ri_data_bc[ri_id] = api.back_calc_ri(spin_index=spin_index,
                                                      ri_id=ri_id,
                                                      ri_type=ri_types[ri_id],
                                                      frq=frqs[ri_id])
Esempio n. 5
0
    def _load_relax_data(self, spin_line, col, data_set, spin, verbosity=1):
        """Load the relaxation data.

        @param spin_line:   The line of data for a single spin.
        @type spin_line:    list of str
        @param col:         The column indices.
        @type col:          dict of int
        @param data_set:    The data set type, one of 'value', 'error', or 'sim_xxx' (where xxx is
                            a number).
        @type data_set:     str
        @param spin:        The spin container.
        @type spin:         SpinContainer instance
        @keyword verbosity: A variable specifying the amount of information to print.  The higher
                            the value, the greater the verbosity.
        @type verbosity:    int
        """

        # Skip the error 'data_set'.
        if data_set == 'error':
            return

        # Relaxation data structures.
        ri_labels = eval(spin_line[col['ri_labels']])
        remap_table = eval(spin_line[col['remap_table']])
        frq_labels = eval(spin_line[col['frq_labels']])
        frq = eval(spin_line[col['frq']])

        # No relaxation data.
        if not ri_labels:
            return

        # Initialise the value and error arrays.
        values = []
        errors = []

        # Loop over the relaxation data of the residue.
        for i in range(len(ri_labels)):
            # Determine the data and error columns for this relaxation data set.
            data_col = col['frq'] + i + 1
            error_col = col['frq'] + len(ri_labels) + i + 1

            # Append the value and error.
            values.append(eval(spin_line[data_col]))
            errors.append(eval(spin_line[error_col]))

        # Simulations.
        sim = True
        if data_set == 'value' or data_set == 'error':
            sim = False

        # Loop over the relaxation data sets.
        for i in range(len(ri_labels)):
            # The ID string.
            ri_id = "%s_%s" % (ri_labels[i], frq_labels[remap_table[i]])

            # Initialise the global structures if necessary.
            if not hasattr(cdp, 'ri_ids'):
                cdp.ri_ids = []
            if not hasattr(cdp, 'ri_type'):
                cdp.ri_type = {}

            # Update the global structures if necessary.
            if ri_id not in cdp.ri_ids:
                cdp.ri_ids.append(ri_id)
                cdp.ri_type[ri_id] = ri_labels[i]
                set_frequency(id=ri_id, frq=frq[remap_table[i]])

            # Simulation data.
            if sim:
                # Initialise.
                if not hasattr(spin, 'ri_data_sim'):
                    spin.ri_data_sim = {}

                # Set the value.
                spin.ri_data_sim[ri_id] = values[i]

            # Normal data.
            else:
                # Initialise.
                if not hasattr(spin, 'ri_data'):
                    spin.ri_data = {}
                if not hasattr(spin, 'ri_data_err'):
                    spin.ri_data_err = {}

                # Set the value.
                if values[i] != None:
                    spin.ri_data[ri_id] = values[i]
                if errors[i] != None:
                    spin.ri_data_err[ri_id] = errors[i]
Esempio n. 6
0
def load_relax_data(spin_line, col, data_set, spin, verbosity=1):
    """Load the relaxation data.

    @param spin_line:   The line of data for a single spin.
    @type spin_line:    list of str
    @param col:         The column indices.
    @type col:          dict of int
    @param data_set:    The data set type, one of 'value', 'error', or 'sim_xxx' (where xxx is
                        a number).
    @type data_set:     str
    @param spin:        The spin container.
    @type spin:         SpinContainer instance
    @keyword verbosity: A variable specifying the amount of information to print.  The higher
                        the value, the greater the verbosity.
    @type verbosity:    int
    """

    # Skip the error 'data_set'.
    if data_set == 'error':
        return

    # Relaxation data structures.
    ri_labels = eval(spin_line[col['ri_labels']])
    remap_table = eval(spin_line[col['remap_table']])
    frq_labels = eval(spin_line[col['frq_labels']])
    frq = eval(spin_line[col['frq']])

    # No relaxation data.
    if not ri_labels:
        return

    # Initialise the value and error arrays.
    values = []
    errors = []

    # Loop over the relaxation data of the residue.
    for i in range(len(ri_labels)):
        # Determine the data and error columns for this relaxation data set.
        data_col = col['frq'] + i + 1
        error_col = col['frq'] + len(ri_labels) + i + 1

        # Append the value and error.
        values.append(eval(spin_line[data_col]))
        errors.append(eval(spin_line[error_col]))

    # Simulations.
    sim = True
    if data_set == 'value' or data_set == 'error':
        sim = False

    # Loop over the relaxation data sets.
    for i in range(len(ri_labels)):
        # The ID string.
        ri_id = "%s_%s" % (ri_labels[i], frq_labels[remap_table[i]])

        # Initialise the global structures if necessary.
        if not hasattr(cdp, 'ri_ids'):
            cdp.ri_ids = []
        if not hasattr(cdp, 'ri_type'):
            cdp.ri_type = {}

        # Update the global structures if necessary.
        if ri_id not in cdp.ri_ids:
            cdp.ri_ids.append(ri_id)
            cdp.ri_type[ri_id] = ri_labels[i]
            set_frequency(id=ri_id, frq=frq[remap_table[i]])

        # Simulation data.
        if sim:
            # Initialise.
            if not hasattr(spin, 'ri_data_sim'):
                spin.ri_data_sim = {}

            # Set the value.
            spin.ri_data_sim[ri_id] = values[i]

        # Normal data.
        else:
            # Initialise.
            if not hasattr(spin, 'ri_data'):
                spin.ri_data = {}
            if not hasattr(spin, 'ri_data_err'):
                spin.ri_data_err = {}

            # Set the value.
            if values[i] != None:
                spin.ri_data[ri_id] = values[i]
            if errors[i] != None:
                spin.ri_data_err[ri_id] = errors[i]
Esempio n. 7
0
def pack_data(ri_id, ri_type, frq, values, errors, spin_ids=None, mol_names=None, res_nums=None, res_names=None, spin_nums=None, spin_names=None, spin_id=None, gen_seq=False, verbose=True):
    """Pack the relaxation data into the data pipe and spin containers.

    The values, errors, and spin_ids arguments must be lists of equal length or None.  Each element i corresponds to a unique spin.

    @param ri_id:           The relaxation data ID string.
    @type ri_id:            str
    @param ri_type:         The relaxation data type, ie 'R1', 'R2', or 'NOE'.
    @type ri_type:          str
    @param frq:             The spectrometer proton frequency in Hz.
    @type frq:              float
    @keyword values:        The relaxation data for each spin.
    @type values:           None or list of float or float array
    @keyword errors:        The relaxation data errors for each spin.
    @type errors:           None or list of float or float array
    @keyword spin_ids:      The list of spin ID strings.  If the other spin identifiers are given, i.e. mol_names, res_nums, res_names, spin_nums, and/or spin_names, then this argument is not necessary.
    @type spin_ids:         None or list of str
    @keyword mol_names:     The list of molecule names used for creating the spin IDs (if not given) or for generating the sequence data.
    @type mol_names:        None or list of str
    @keyword res_nums:      The list of residue numbers used for creating the spin IDs (if not given) or for generating the sequence data.
    @type res_nums:         None or list of str
    @keyword res_names:     The list of residue names used for creating the spin IDs (if not given) or for generating the sequence data.
    @type res_names:        None or list of str
    @keyword spin_nums:     The list of spin numbers used for creating the spin IDs (if not given) or for generating the sequence data.
    @type spin_nums:        None or list of str
    @keyword spin_names:    The list of spin names used for creating the spin IDs (if not given) or for generating the sequence data.
    @type spin_names:       None or list of str
    @keyword gen_seq:       A flag which if True will cause the molecule, residue, and spin sequence data to be generated.
    @type gen_seq:          bool
    @keyword verbose:       A flag which if True will cause all relaxation data loaded to be printed out.
    @type verbose:          bool
    """

    # The number of spins.
    N = len(values)

    # Test the data.
    if errors != None and len(errors) != N:
        raise RelaxError("The length of the errors arg (%s) does not match that of the value arg (%s)." % (len(errors), N))
    if spin_ids and len(spin_ids) != N:
        raise RelaxError("The length of the spin ID strings arg (%s) does not match that of the value arg (%s)." % (len(mol_names), N))
    if mol_names and len(mol_names) != N:
        raise RelaxError("The length of the molecule names arg (%s) does not match that of the value arg (%s)." % (len(mol_names), N))
    if res_nums and len(res_nums) != N:
        raise RelaxError("The length of the residue numbers arg (%s) does not match that of the value arg (%s)." % (len(res_nums), N))
    if res_names and len(res_names) != N:
        raise RelaxError("The length of the residue names arg (%s) does not match that of the value arg (%s)." % (len(res_names), N))
    if spin_nums and len(spin_nums) != N:
        raise RelaxError("The length of the spin numbers arg (%s) does not match that of the value arg (%s)." % (len(spin_nums), N))
    if spin_names and len(spin_names) != N:
        raise RelaxError("The length of the spin names arg (%s) does not match that of the value arg (%s)." % (len(spin_names), N))

    # Generate some empty lists.
    if not mol_names:
        mol_names = [None] * N
    if not res_nums:
        res_nums = [None] * N
    if not res_names:
        res_names = [None] * N
    if not spin_nums:
        spin_nums = [None] * N
    if not spin_names:
        spin_names = [None] * N
    if errors == None:
        errors = [None] * N

    # Generate the spin IDs.
    if not spin_ids:
        spin_ids = []
        for i in range(N):
            spin_ids.append(generate_spin_id_unique(spin_num=spin_nums[i], spin_name=spin_names[i], res_num=res_nums[i], res_name=res_names[i], mol_name=mol_names[i]))

    # Initialise the global data for the current pipe if necessary.
    if not hasattr(cdp, 'ri_type'):
        cdp.ri_type = {}
    if not hasattr(cdp, 'ri_ids'):
        cdp.ri_ids = []

    # Set the spectrometer frequency.
    set_frequency(id=ri_id, frq=frq)

    # Update the global data.
    cdp.ri_ids.append(ri_id)
    cdp.ri_type[ri_id] = ri_type

    # The selection object.
    select_obj = None
    if spin_id:
        select_obj = Selection(spin_id)

    # Loop over the spin data.
    data = []
    for i in range(N):
        # Get the corresponding spin container.
        match_mol_names, match_res_nums, match_res_names, spins = return_spin_from_selection(spin_ids[i], full_info=True, multi=True)
        if spins in [None, []]:
            raise RelaxNoSpinError(spin_ids[i])

        # Remove non-matching spins.
        if select_obj:
            new_spins = []
            new_mol_names = []
            new_res_nums = []
            new_res_names = []
            new_ids = []
            for j in range(len(spins)):
                if select_obj.contains_spin(spin_num=spins[j].num, spin_name=spins[j].name, res_num=match_res_nums[j], res_name=match_res_names[j], mol=match_mol_names[j]):
                    new_spins.append(spins[j])
                    new_mol_names.append(match_mol_names[j])
                    new_res_nums.append(match_res_nums[j])
                    new_res_names.append(match_res_names[j])
                    new_ids.append(generate_spin_id_unique(mol_name=mol_names[i], res_num=res_nums[i], res_name=res_names[i], spin_num=spins[j].num, spin_name=spins[j].name))
            new_id = new_ids[0]

        # Aliases for normal operation.
        else:
            new_spins = spins
            new_mol_names = match_mol_names
            new_res_nums = match_res_nums
            new_res_names = match_res_names
            new_id = spin_ids[i]
            new_ids = None

        # Check that only a singe spin is present.
        if len(new_spins) > 1:
            if new_ids:
                raise RelaxMultiSpinIDError(spin_ids[i], new_ids)
            else:
                raise RelaxMultiSpinIDError(spin_ids[i], new_ids)
        if len(new_spins) == 0:
            raise RelaxNoSpinError(spin_ids[i])

        # Loop over the spins.
        for j in range(len(new_spins)):
            # No match to the selection.
            if select_obj and not select_obj.contains_spin(spin_num=new_spins[j].num, spin_name=new_spins[j].name, res_num=new_res_nums[j], res_name=new_res_names[j], mol=new_mol_names[j]):
                continue

            # Initialise the spin data if necessary.
            if not hasattr(new_spins[j], 'ri_data') or new_spins[j].ri_data == None:
                new_spins[j].ri_data = {}
            if not hasattr(new_spins[j], 'ri_data_err') or new_spins[j].ri_data_err == None:
                new_spins[j].ri_data_err = {}

            # Update all data structures.
            new_spins[j].ri_data[ri_id] = values[i]
            new_spins[j].ri_data_err[ri_id] = errors[i]

            # Append the data for printing out.
            data.append([new_id, repr(values[i]), repr(errors[i])])

    # Print out.
    if verbose:
        print("\nThe following %s MHz %s relaxation data with the ID '%s' has been loaded into the relax data store:\n" % (frq/1e6, ri_type, ri_id))
        write_data(out=sys.stdout, headings=["Spin_ID", "Value", "Error"], data=data)
Esempio n. 8
0
def back_calc(ri_id=None, ri_type=None, frq=None):
    """Back calculate the relaxation data.

    If no relaxation data currently exists, then the ri_id, ri_type, and frq args are required.


    @keyword ri_id:     The relaxation data ID string.  If not given, all relaxation data will be back calculated.
    @type ri_id:        None or str
    @keyword ri_type:   The relaxation data type.  This should be one of 'R1', 'R2', or 'NOE'.
    @type ri_type:      None or str
    @keyword frq:       The spectrometer proton frequency in Hz.
    @type frq:          None or float
    """

    # Test if the current pipe exists.
    pipes.test()

    # Test if sequence data is loaded.
    if not exists_mol_res_spin_data():
        raise RelaxNoSequenceError

    # Check that ri_type and frq are supplied if no relaxation data exists.
    if ri_id and (not hasattr(cdp, 'ri_ids') or ri_id not in cdp.ri_ids) and (ri_type == None or frq == None):
        raise RelaxError("The 'ri_type' and 'frq' arguments must be supplied as no relaxation data corresponding to '%s' exists." % ri_id)

    # Check if the type is valid.
    if ri_type and ri_type not in VALID_TYPES:
        raise RelaxError("The relaxation data type '%s' must be one of %s." % (ri_type, VALID_TYPES))

    # Frequency checks.
    frequency_checks(frq)

    # Initialise the global data for the current pipe if necessary.
    if not hasattr(cdp, 'ri_type'):
        cdp.ri_type = {}
    if not hasattr(cdp, 'ri_ids'):
        cdp.ri_ids = []

    # Update the global data if needed.
    if ri_id and ri_id not in cdp.ri_ids:
        cdp.ri_ids.append(ri_id)
        cdp.ri_type[ri_id] = ri_type
        set_frequency(id=ri_id, frq=frq)

    # Specific Ri back calculate function setup.
    back_calculate = specific_analyses.setup.get_specific_fn('back_calc_ri', pipes.get_type())

    # The IDs to loop over.
    if ri_id == None:
        ri_ids = cdp.ri_ids
    else:
        ri_ids = [ri_id]

    # The data types.
    if ri_type == None:
        ri_types = cdp.ri_type
    else:
        ri_types = {ri_id: ri_type}

    # The frequencies.
    if frq == None:
        frqs = cdp.spectrometer_frq
    else:
        frqs = {ri_id: frq}

    # Loop over the spins.
    for spin, spin_id in spin_loop(return_id=True):
        # Skip deselected spins.
        if not spin.select:
            continue

        # The global index.
        spin_index = find_index(spin_id)

        # Initialise the spin data if necessary.
        if not hasattr(spin, 'ri_data_bc'):
            spin.ri_data_bc = {}

        # Back-calculate the relaxation value.
        for ri_id in ri_ids:
            spin.ri_data_bc[ri_id] = back_calculate(spin_index=spin_index, ri_id=ri_id, ri_type=ri_types[ri_id], frq=frqs[ri_id])