Exemplo n.º 1
0
def frequency_to_rad_per_s(frq=None, B0=None, isotope=None):
    """Convert the given frequency from ppm to rad/s units.

    @keyword frq:       The frequency in ppm.
    @type frq:          float
    @keyword B0:        The magnetic field strength as the proton frequency in Hertz.
    @type B0:           float
    @keyword isotope:   The isotope type of the nucleus of interest.
    @type isotope:      str
    @return:            The frequency in rad/s.
    @rtype:             float
    """

    # Convert and return.
    return frq * 2.0 * pi * B0 / periodic_table.gyromagnetic_ratio('1H') * periodic_table.gyromagnetic_ratio(isotope) * 1e-6
Exemplo n.º 2
0
def frequency_to_rad_per_s(frq=None, B0=None, isotope=None):
    """Convert the given frequency from ppm to rad/s units.

    @keyword frq:       The frequency in ppm.
    @type frq:          float
    @keyword B0:        The magnetic field strength as the proton frequency in Hertz.
    @type B0:           float
    @keyword isotope:   The isotope type of the nucleus of interest.
    @type isotope:      str
    @return:            The frequency in rad/s.
    @rtype:             float
    """

    # Convert and return.
    return frq * 2.0 * pi * B0 / periodic_table.gyromagnetic_ratio(
        '1H') * periodic_table.gyromagnetic_ratio(isotope) * 1e-6
Exemplo n.º 3
0
    def _assemble_experiment(self):
        """Assemble the experimental data."""

        # Get the spectrometer info.
        frq_Hz = get_frequencies(units='MHz')
        frq_T = get_frequencies(units='T')

        # Loop over all data points.
        for exp_type, frq, point, time, ei, mi, di, ti in loop_exp_frq_point_time(
                return_indices=True):
            # The frequency data.
            self.cpmg_delay[mi] = str(time)

        # Loop over the experiments.
        for i in range(cdp.spectrometer_frq_count):
            # Spectrometer info.
            self.spec_frq[i] = str(frq_Hz[i] /
                                   periodic_table.gyromagnetic_ratio('1H') *
                                   periodic_table.gyromagnetic_ratio('15N'))
            self.B0[i] = str(frq_T[i])
Exemplo n.º 4
0
def kappa(nuc1='15N', nuc2='1H'):
    """Function for calculating the kappa constant.

    The kappa constant is::

        kappa = -3/(8pi^2).gI.gS.mu0.h_bar,

    where gI and gS are the gyromagnetic ratios of the I and S spins, mu0 is the permeability of
    free space, and h_bar is Planck's constant divided by 2pi.

    @param nuc1:    The first nucleus type.
    @type nuc1:     str
    @param nuc2:    The first nucleus type.
    @type nuc2:     str
    @return:        The kappa constant value.
    @rtype:         float
    """

    # Gyromagnetic ratios.
    gI = periodic_table.gyromagnetic_ratio(nuc1)
    gS = periodic_table.gyromagnetic_ratio(nuc2)

    # Kappa.
    return -3.0/(8.0*pi**2) * gI * gS * mu0 * h_bar
Exemplo n.º 5
0
def kappa(nuc1='15N', nuc2='1H'):
    """Function for calculating the kappa constant.

    The kappa constant is::

        kappa = -3/(8pi^2).gI.gS.mu0.h_bar,

    where gI and gS are the gyromagnetic ratios of the I and S spins, mu0 is the permeability of
    free space, and h_bar is Planck's constant divided by 2pi.

    @param nuc1:    The first nucleus type.
    @type nuc1:     str
    @param nuc2:    The first nucleus type.
    @type nuc2:     str
    @return:        The kappa constant value.
    @rtype:         float
    """

    # Gyromagnetic ratios.
    gI = periodic_table.gyromagnetic_ratio(nuc1)
    gS = periodic_table.gyromagnetic_ratio(nuc2)

    # Kappa.
    return -3.0 / (8.0 * pi**2) * gI * gS * mu0 * h_bar
Exemplo n.º 6
0
    def _assemble_experiment(self):
        """Assemble the experimental data."""

        # Get the spectrometer info.
        frq_Hz = get_frequencies(units='MHz')
        frq_T = get_frequencies(units='T')

        # Loop over all data points.
        for exp_type, frq, point, time, ei, mi, di, ti in loop_exp_frq_point_time(return_indices=True):
            # The frequency data.
            self.cpmg_delay[mi] = str(time)

        # Loop over the experiments.
        for i in range(cdp.spectrometer_frq_count):
            # Spectrometer info.
            self.spec_frq[i] = str(frq_Hz[i] / periodic_table.gyromagnetic_ratio('1H') * periodic_table.gyromagnetic_ratio('15N'))
            self.B0[i] = str(frq_T[i])
Exemplo n.º 7
0
def create_mfpar(file,
                 spin=None,
                 spin_id=None,
                 res_num=None,
                 atom1=None,
                 atom2=None):
    """Create the Modelfree4 input file 'mfpar'.

    @param file:        The writable file object.
    @type file:         file object
    @keyword spin:      The spin container.
    @type spin:         SpinContainer instance
    @keyword spin_id:   The spin identification string.
    @type spin_id       str
    @keyword res_num:   The residue number from the PDB file corresponding to the spin.
    @type res_num:      int
    @keyword atom1:     The name of the heteronucleus in the PDB file.
    @type atom1:        str
    @keyword atom2:     The name of the proton in the PDB file.
    @type atom2:        str
    """

    # Get the interatomic data containers.
    interatoms = return_interatom_list(spin_hash=spin._hash)
    if len(interatoms) == 0:
        raise RelaxNoInteratomError
    elif len(interatoms) > 1:
        raise RelaxError(
            "Only one interatomic data container, hence dipole-dipole interaction, is supported per spin."
        )

    # Spin title.
    file.write("\nspin     " + spin_id + "\n")

    file.write('%-14s' % "constants")
    file.write('%-6i' % res_num)
    file.write('%-7s' % spin.isotope)
    file.write('%-8.4f' %
               (periodic_table.gyromagnetic_ratio(spin.isotope) / 1e7))
    file.write('%-8.3f' % (interatoms[0].r * 1e10))
    file.write('%-8.3f\n' % (spin.csa * 1e6))

    file.write('%-10s' % "vector")
    file.write('%-4s' % atom1)
    file.write('%-4s\n' % atom2)
Exemplo n.º 8
0
def get_frequencies(units='Hz'):
    """Return a list of all the current spectrometer frequencies.

    The returned values can be changed with the units argument which can have the following values:

        - 'Hz' will return the proton frequency (wH),
        - 'MHz' will return the proton frequency in megahertz,
        - 'T' will return the B0 field in Tesla.


    @keyword units: The magnetic field units to return.  This can be one of 'Hz', 'MHz', or 'T'.
    @type units:    str
    @return:        The frequency list for the current data pipe.
    @rtype:         list of float
    """

    # No frequency data.
    if not hasattr(cdp, 'spectrometer_frq'):
        return []

    # Convert the values.
    frq = []
    for value in cdp.spectrometer_frq_list:
        # Hertz.
        if units == 'Hz':
            frq.append(value)

        # MHz.
        elif units == 'MHz':
            frq.append(value * 1e-6)

        # Tesla.
        elif units == 'T':
            frq.append(value * 2.0 * pi / periodic_table.gyromagnetic_ratio('1H'))

        # Unknown units.
        else:
            raise RelaxError("The units of '%s' should be one of 'Hz', 'MHz', or 'T'.")

    # Return the frqs.
    return frq
Exemplo n.º 9
0
def get_frequencies(units='Hz'):
    """Return a list of all the current spectrometer frequencies.

    The returned values can be changed with the units argument which can have the following values:

        - 'Hz' will return the proton frequency (wH),
        - 'MHz' will return the proton frequency in megahertz,
        - 'T' will return the B0 field in Tesla.


    @keyword units: The magnetic field units to return.  This can be one of 'Hz', 'MHz', or 'T'.
    @type units:    str
    @return:        The frequency list for the current data pipe.
    @rtype:         list of float
    """

    # No frequency data.
    if not hasattr(cdp, 'spectrometer_frq'):
        return []

    # Convert the values.
    frq = []
    for value in cdp.spectrometer_frq_list:
        # Hertz.
        if units == 'Hz':
            frq.append(value)

        # MHz.
        elif units == 'MHz':
            frq.append(value * 1e-6)

        # Tesla.
        elif units == 'T':
            frq.append(value * 2.0 * pi / periodic_table.gyromagnetic_ratio('1H'))

        # Unknown units.
        else:
            raise RelaxError("The units of '%s' should be one of 'Hz', 'MHz', or 'T'.")

    # Return the frqs.
    return frq
Exemplo n.º 10
0
def calc_chi_tensor(A, B0, T):
    """Convert the alignment tensor into the magnetic susceptibility (chi) tensor.

    A can be either the full tensor (3D or 5D), a component Aij of the tensor, Aa, or Ar, anything that can be multiplied by the constants to convert from one to the other.


    @param A:       The alignment tensor or alignment tensor component.
    @type A:        numpy array or float
    @param B0:      The magnetic field strength in Hz.
    @type B0:       float
    @param T:       The temperature in Kalvin.
    @type T:        float
    @return:        A multiplied by the PCS constant.
    @rtype:         numpy array or float
    """

    # B0 in Tesla.
    B0 = 2.0 * pi * B0 / periodic_table.gyromagnetic_ratio('1H')

    # The conversion factor.
    conv = 15.0 * mu0 * kB * T / B0**2

    # Return the converted value.
    return conv * A
Exemplo n.º 11
0
def calc_chi_tensor(A, B0, T):
    """Convert the alignment tensor into the magnetic susceptibility (chi) tensor.

    A can be either the full tensor (3D or 5D), a component Aij of the tensor, Aa, or Ar, anything that can be multiplied by the constants to convert from one to the other.


    @param A:       The alignment tensor or alignment tensor component.
    @type A:        numpy array or float
    @param B0:      The magnetic field strength in Hz.
    @type B0:       float
    @param T:       The temperature in Kalvin.
    @type T:        float
    @return:        A multiplied by the PCS constant.
    @rtype:         numpy array or float
    """

    # B0 in Tesla.
    B0 = 2.0 * pi * B0 / periodic_table.gyromagnetic_ratio('1H')

    # The conversion factor.
    conv = 15.0 * mu0 * kB * T / B0**2

    # Return the converted value.
    return conv * A
Exemplo n.º 12
0
    def rdc_analysis(self):
        """Perform the RDC part of the analysis."""

        # Redirect STDOUT to a log file.
        if self.log:
            sys.stdout = open(
                self.results_dir + sep + "logs" + sep +
                "RDC_%s_analysis.log" % self.rdc_name, 'w')

        # The dipolar constant.
        d = 0.0
        if self.bond_length != None:
            d = 3.0 / (2.0 * pi) * dipolar_constant(
                periodic_table.gyromagnetic_ratio('13C'),
                periodic_table.gyromagnetic_ratio('1H'), self.bond_length)

        # Create a directory for the save files.
        dir = self.results_dir + sep + "RDC_%s_results" % self.rdc_name
        mkdir_nofail(dir=dir)

        # Loop over the configurations.
        for config in self.configs:
            # Print out.
            print("\n" * 10 + "# Set up for config " + config + " #" + "\n")

            # Open the results files.
            out = open(self.results_dir + sep + "Q_factors_" + config, 'w')
            out_sorted = open(
                self.results_dir + sep + "Q_factors_" + config + "_sorted",
                'w')
            out.write("%-20s%20s%20s\n" % ("# Ensemble", "RDC_Q_factor(pales)",
                                           "RDC_Q_factor(standard)"))
            out_sorted.write("%-20s%20s\n" %
                             ("# Ensemble", "RDC_Q_factor(pales)"))

            # Create the data pipe.
            self.interpreter.pipe.create("rdc_analysis_%s" % config, "N-state")

            # Read the first structure.
            self.interpreter.structure.read_pdb(
                "ensembles_superimposed" + sep + config + "0.pdb",
                dir=self.results_dir,
                set_mol_name=config,
                set_model_num=list(range(1, self.num_models + 1)))

            # Load all spins as the sequence.
            self.interpreter.structure.load_spins(ave_pos=False)

            # Create the pseudo-atoms.
            for i in range(len(self.pseudo)):
                self.interpreter.spin.create_pseudo(
                    spin_name=self.pseudo[i][0],
                    members=self.pseudo[i][1],
                    averaging="linear")
            self.interpreter.sequence.display()

            # Read the RDC data.
            self.interpreter.rdc.read(align_id=self.rdc_file,
                                      file=self.rdc_file,
                                      spin_id1_col=self.rdc_spin_id1_col,
                                      spin_id2_col=self.rdc_spin_id2_col,
                                      data_col=self.rdc_data_col,
                                      error_col=self.rdc_error_col)

            # Define the magnetic dipole-dipole relaxation interaction.
            if self.bond_length != None:
                self.interpreter.interatom.set_dist(spin_id1='@C*',
                                                    spin_id2='@H*',
                                                    ave_dist=self.bond_length)
                self.interpreter.interatom.set_dist(spin_id1='@C*',
                                                    spin_id2='@Q*',
                                                    ave_dist=self.bond_length)
            else:
                self.interpreter.interatom.read_dist(
                    file=self.bond_length_file,
                    spin_id1_col=1,
                    spin_id2_col=2,
                    data_col=3)

            # Set the nuclear isotope.
            self.interpreter.spin.isotope(isotope='13C', spin_id='@C*')
            self.interpreter.spin.isotope(isotope='1H', spin_id='@H*')
            self.interpreter.spin.isotope(isotope='1H', spin_id='@Q*')

            # Set up the model.
            self.interpreter.n_state_model.select_model(model="fixed")

            # Print out.
            print("\n" * 2 + "# Set up complete #" + "\n" * 10)

            # Loop over each ensemble.
            q_factors = []
            for ens in range(self.num_ens):
                # Print out the ensemble to both the log and screen.
                if self.log:
                    sys.stdout.write(config + repr(ens) + "\n")
                sys.stderr.write(config + repr(ens) + "\n")

                # Delete the old structures.
                self.interpreter.structure.delete()

                # Read the ensemble.
                self.interpreter.structure.read_pdb(
                    "ensembles_superimposed" + sep + config + repr(ens) +
                    ".pdb",
                    dir=self.results_dir,
                    set_mol_name=config,
                    set_model_num=list(range(1, self.num_models + 1)))

                # Get the positional information, then load the CH vectors.
                self.interpreter.structure.get_pos(ave_pos=False)
                if self.bond_length != None:
                    self.interpreter.interatom.set_dist(
                        spin_id1='@C*',
                        spin_id2='@H*',
                        ave_dist=self.bond_length)
                else:
                    self.interpreter.interatom.read_dist(
                        file=self.bond_length_file,
                        spin_id1_col=1,
                        spin_id2_col=2,
                        data_col=3)
                self.interpreter.interatom.unit_vectors(ave=False)

                # Minimisation.
                #minimise.grid_search(inc=4)
                self.interpreter.minimise.execute("simplex", constraints=False)

                # Store and write out the Q factors.
                q_factors.append([cdp.q_rdc_norm_squared_sum, ens])
                out.write("%-20i%20.15f%20.15f\n" %
                          (ens, cdp.q_rdc_norm_squared_sum,
                           cdp.q_rdc_norm_squared_sum))

                # Calculate the alignment tensor in Hz, and store it for reference.
                cdp.align_tensor_Hz = d * cdp.align_tensors[0].A
                cdp.align_tensor_Hz_5D = d * cdp.align_tensors[0].A_5D

                # Save the state.
                self.interpreter.results.write(file="%s_results_%s" %
                                               (config, ens),
                                               dir=dir,
                                               force=True)

            # Sort the NOE violations.
            q_factors.sort()

            # Write the data.
            for i in range(len(q_factors)):
                out_sorted.write("%-20i%20.15f\n" %
                                 (q_factors[i][1], q_factors[i][0]))
Exemplo n.º 13
0
def create_spin_input(function=None, spin=None, spin_id=None, dir=None):
    """Generate the CPMGFit file for the given spin.

    @keyword function:  The CPMGFit model or function name.
    @type function:     str
    @keyword spin:      The spin container to generate the input file for.
    @type spin:         SpinContainer instance
    @keyword spin_id:   The spin ID string corresponding to the spin container.
    @type spin_id:      str
    @keyword dir:       The directory to place the file into.
    @type dir:          str or None
    @return:            The name of the file created.
    @rtype:             str
    """

    # The output file.
    file_name = spin_file_name(spin_id=spin_id)
    file = open_write_file(file_name=file_name, dir=dir, force=True)

    # The title.
    file.write("title %s\n" % spin_id)

    # The proton frequencies.
    frq = get_frequencies(units='T')

    # The frequency info.
    file.write("fields %s" % len(frq))
    for i in range(len(frq)):
        file.write(" %.10f" % frq[i])
    file.write("\n")

    # The function and parameters.
    if function == 'CPMG':
        # Function.
        file.write("function CPMG\n")

        # Parameters.
        file.write("R2 1 10 20\n")
        file.write("Rex 0 100.0 100\n")
        file.write("Tau 0 10.0 100\n")

    # The function and parameters.
    elif function == 'Full_CPMG':
        # Function.
        file.write("function Full_CPMG\n")

        # Parameters.
        file.write("R2 1 10 20\n")
        file.write("papb 0.01 0.49 20\n")
        file.write("dw 0 10.0 100\n")
        file.write("kex 0.1 1.0 100\n")

    # The function and parameters.
    elif function == "Ishima":
        # Function.
        file.write("function Ishima\n")

        # Parameters.
        file.write("R2 1 10 20\n")
        file.write("Rex 0 100.0 50\n")
        file.write("PaDw 2 10.0 50\n")
        file.write("Tau 0.1 10.0 50\n")

    # The function and parameters.
    if function == '3-site_CPMG':
        # Function.
        file.write("function 3-site_CPMG\n")

        # Parameters.
        file.write("R2 1 10 20\n")
        file.write("Rex1 0 100.0 20\n")
        file.write("Tau1 0 10.0 20\n")
        file.write("Rex2 0 100.0 20\n")
        file.write("Tau2 0 10.0 20\n")

    # The Grace setup.
    file.write("xmgr\n")
    file.write("@ xaxis label \"1/tcp (1/ms)\"\n")
    file.write("@ yaxis label \"R2(tcp) (rad/s)\"\n")
    file.write("@ xaxis ticklabel format decimal\n")
    file.write("@ yaxis ticklabel format decimal\n")
    file.write("@ xaxis ticklabel char size 0.8\n")
    file.write("@ yaxis ticklabel char size 0.8\n")
    file.write("@ world xmin 0.0\n")

    # The data.
    file.write("data\n")
    for exp_type, frq, offset, point in loop_exp_frq_offset_point():
        # The parameter key.
        param_key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point)

        # No data.
        if param_key not in spin.r2eff:
            continue

        # Tesla units.
        B0 = frq * 2.0 * pi / periodic_table.gyromagnetic_ratio('1H')

        # The X value of 1/tcp (or 1/tau_CPMG) in ms.  This assumes Art's usage of the definition that nu_CPMG = 1 / (2 * tau_CPMG).
        x = 2.0 * point / 1000.0

        # Write out the data and error.
        file.write("%-20f %-20f %-20f %-20f\n" % (x, spin.r2eff[param_key], spin.r2eff_err[param_key], B0))

    # Close the file and return its name.
    file.close()
    return file_name
Exemplo n.º 14
0
def sherekhan_input(spin_id=None, force=False, dir='ShereKhan'):
    """Create the ShereKhan input files.

    @keyword spin_id:           The spin ID string to restrict the file creation to.
    @type spin_id:              str
    @keyword force:             A flag which if True will cause all pre-existing files to be overwritten.
    @type force:                bool
    @keyword dir:               The optional directory to place the files into.  If None, then the files will be placed into the current directory.
    @type dir:                  str or None
    """

    # Test if the current pipe exists.
    check_pipe()

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

    # Test if the experiment type has been set.
    if not hasattr(cdp, 'exp_type'):
        raise RelaxError("The relaxation dispersion experiment type has not been specified.")

    # Test if the model has been set.
    if not hasattr(cdp, 'model_type'):
        raise RelaxError("The relaxation dispersion model has not been specified.")

    # Directory creation.
    if dir != None:
        mkdir_nofail(dir, verbosity=0)

    # Loop over the spin blocks.
    cluster_index = 0
    for spin_ids in loop_cluster():
        # The spin containers.
        spins = spin_ids_to_containers(spin_ids)

        # Loop over the magnetic fields.
        for exp_type, frq, ei, mi in loop_exp_frq(return_indices=True):
            # Loop over the time, and count it.
            time_i = 0
            for time, ti in loop_time(exp_type=exp_type, frq=frq, return_indices=True):
                time_i += 1

            # Check that not more than one time point is returned.
            if time_i > 1:
                raise RelaxError("Number of returned time poins is %i. Only 1 time point is expected."%time_i)

            # The ShereKhan input file for the spin cluster.
            file_name = 'sherekhan_frq%s.in' % (mi+1)
            if dir != None:
                dir_name = dir + sep + 'cluster%s' % (cluster_index+1)
            else:
                dir_name = 'cluster%s' % (cluster_index+1)
            file = open_write_file(file_name=file_name, dir=dir_name, force=force)

            # The B0 field for the nuclei of interest in MHz (must be positive to be accepted by the server).
            file.write("%.10f\n" % abs(frq / periodic_table.gyromagnetic_ratio('1H') * periodic_table.gyromagnetic_ratio('15N') / 1e6))

            # The constant relaxation time for the CPMG experiment in seconds.
            file.write("%s\n" % (time))

            # The comment line.
            file.write("# %-18s %-20s %-20s\n" % ("nu_cpmg (Hz)", "R2eff (rad/s)", "Error"))

            # Loop over the spins of the cluster.
            for i in range(len(spins)):
                # Get the residue container.
                res = return_residue(spin_ids[i])

                # Name the residue if needed.
                res_name = res.name
                if res_name == None:
                    res_name = 'X'

                # Initialise the lines to output (to be able to catch missing data).
                lines = []

                # The residue ID line.
                lines.append("# %s%s\n" % (res_name, res.num))

                # Loop over the dispersion points.
                for offset, point in loop_offset_point(exp_type=exp_type, frq=frq, skip_ref=True):
                    # The parameter key.
                    param_key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point)

                    # No data.
                    if param_key not in spins[i].r2eff:
                        continue

                    # Store the data.
                    lines.append("%20.15g %20.13g %20.13g\n" % (point, spins[i].r2eff[param_key], spins[i].r2eff_err[param_key]))

                # No data.
                if len(lines) == 1:
                    continue

                # Write out the data.
                for line in lines:
                    file.write(line)

            # Close the file.
            file.close()

        # Increment the cluster index.
        cluster_index += 1
Exemplo n.º 15
0
    def _calculate_pcs(self):
        """Calculate the averaged PCS for all states."""

        # Printout.
        sys.stdout.write("\n\nRotating %s states for the PCS:\n\n" % locale.format("%d", self.N**self.MODES, grouping=True))

        # Turn off the relax interpreter echoing to allow the progress meter to be shown correctly.
        self.interpreter.off()

        # Set up some data structures for faster calculations.
        spins = []
        spin_pos = []
        d = {}
        for tag in self._tensors:
            d[tag] = []
        for spin in spin_loop():
            # Nothing to do.
            if not hasattr(spin, 'pos'):
                continue

            # Initialise the PCS structure (as a 1D numpy.float128 array for speed and minimising truncation artifacts).
            spin.pcs = {}
            for tag in self._tensors:
                spin.pcs[tag] = zeros(1, float128)

            # Pack the spin containers and positions.
            spins.append(spin)
            spin_pos.append(spin.pos[0])

            # Calculate the partial PCS constant (with no vector length).
            for tag in self._tensors:
                d[tag].append(pcs_constant(cdp.temperature[tag], cdp.spectrometer_frq[tag] * 2.0 * pi / periodic_table.gyromagnetic_ratio('1H'), 1.0))

        # Repackage the data for speed.
        spin_pos = array(spin_pos, float64)
        num_spins = len(spin_pos)
        for tag in self._tensors:
            d[tag] = array(d[tag], float64)

        # Store the alignment tensors.
        A = []
        for i in range(len(self._tensors)):
            A.append(cdp.align_tensors[i].A)

        # Loop over each position.
        for global_index, mode_indices in self._state_loop():
            # The progress meter.
            self._progress(global_index)

            # Data initialisation.
            new_pos = spin_pos

            # Loop over each motional mode.
            for motion_index in range(self.MODES):
                # Generate the distribution specific rotation.
                self.rotation(mode_indices[motion_index], motion_index=motion_index)

                # Rotate the atomic positions.
                new_pos = transpose(tensordot(self.R, transpose(new_pos - self.PIVOT[motion_index]), axes=1)) + self.PIVOT[motion_index]

            # The vectors.
            vectors = new_pos - cdp.paramagnetic_centre

            # The lengths.
            r = norm(vectors, axis=1)

            # The scaling factor that includes the Angstrom to meter converted length cubed and the ppm conversion.
            fact = 1e6 / (r / 1e10)**3

            # Normalise.
            vectors = transpose(vectors) / r

            # Loop over each alignment.
            for i in range(len(self._tensors)):
                # Calculate the PCS as quickly as possible (the 1e36 is from the 1e10**3 Angstrom conversion and the 1e6 ppm conversion).
                pcss = d[self._tensors[i]] * fact * tensordot(transpose(vectors), tensordot(A[i], vectors, axes=1), axes=1)

                # Store the values.
                for j in range(len(spins)):
                    spins[j].pcs[self._tensors[i]][0] += pcss[j, j]

        # Print out.
        sys.stdout.write('\n\n')

        # Reactive the interpreter echoing.
        self.interpreter.on()

        # Average the PCS and write the data.
        for tag in self._tensors:
            # Average.
            for spin in spin_loop():
                spin.pcs[tag] = spin.pcs[tag][0] / self.N**self.MODES

            # Save.
            self.interpreter.pcs.write(align_id=tag, file='pcs_%s.txt'%tag, dir=self.save_path, force=True)
Exemplo n.º 16
0
    def _calculate_rdc(self):
        """Calculate the averaged RDC for all states."""

        # Open the output files.
        if self.ROT_FILE:
            rot_file = open_write_file('rotations', dir=self.save_path, compress_type=1, force=True)

        # Printout.
        sys.stdout.write("\n\nRotating %s states for the RDC:\n\n" % locale.format("%d", self.N**self.MODES, grouping=True))

        # Turn off the relax interpreter echoing to allow the progress meter to be shown correctly.
        self.interpreter.off()

        # Set up some data structures for faster calculations.
        interatoms = []
        vectors = []
        d = []
        for interatom in interatomic_loop():
            # Nothing to do.
            if not hasattr(interatom, 'vector'):
                continue

            # Initialise the RDC structure (as a 1D numpy.float128 array for speed and minimising truncation artifacts).
            interatom.rdc = {}
            for tag in self._tensors:
                interatom.rdc[tag] = zeros(1, float128)

            # Pack the interatomic containers and vectors.
            interatoms.append(interatom)
            vectors.append(interatom.vector)

            # Get the spins.
            spin1 = return_spin(interatom.spin_id1)
            spin2 = return_spin(interatom.spin_id2)

            # Gyromagnetic ratios.
            g1 = periodic_table.gyromagnetic_ratio(spin1.isotope)
            g2 = periodic_table.gyromagnetic_ratio(spin2.isotope)

            # Calculate the RDC dipolar constant (in Hertz, and the 3 comes from the alignment tensor), and append it to the list.
            d.append(3.0/(2.0*pi) * dipolar_constant(g1, g2, interatom.r))

        # Repackage the data for speed.
        vectors = transpose(array(vectors, float64))
        d = array(d, float64)
        num_interatoms = len(vectors)

        # Store the alignment tensors.
        A = []
        for i in range(len(self._tensors)):
            A.append(cdp.align_tensors[i].A)

        # Loop over each position.
        for global_index, mode_indices in self._state_loop():
            # The progress meter.
            self._progress(global_index)

            # Total rotation matrix (for construction of the frame order matrix).
            total_R = eye(3)

            # Data initialisation.
            new_vect = vectors

            # Loop over each motional mode.
            for motion_index in range(self.MODES):
                # Generate the distribution specific rotation.
                self.rotation(mode_indices[motion_index], motion_index=motion_index)

                # Rotate the NH vector.
                new_vect = dot(self.R, new_vect)

                # Decompose the rotation into Euler angles and store them.
                if self.ROT_FILE:
                    a, b, g = R_to_euler_zyz(self.R)
                    rot_file.write('Mode %i:  %10.7f %10.7f %10.7f\n' % (motion_index, a, b, g))

                # Contribution to the total rotation.
                total_R = dot(self.R, total_R)

            # Loop over each alignment.
            for i in range(len(self._tensors)):
                # Calculate the RDC as quickly as possible.
                rdcs = d * tensordot(transpose(new_vect), tensordot(A[i], new_vect, axes=1), axes=1)

                # Store the values.
                for j in range(len(interatoms)):
                    interatoms[j].rdc[self._tensors[i]][0] += rdcs[j, j]

            # The frame order matrix component.
            self.daeg += kron_prod(total_R, total_R)

        # Print out.
        sys.stdout.write('\n\n')

        # Frame order matrix averaging.
        self.daeg = self.daeg / self.N**self.MODES

        # Write out the frame order matrix.
        file = open(self.save_path+sep+'frame_order_matrix', 'w')
        print_frame_order_2nd_degree(self.daeg, file=file, places=8)

        # Reactive the interpreter echoing.
        self.interpreter.on()

        # Average the RDC and write the data.
        for tag in self._tensors:
            # Average.
            for interatom in interatomic_loop():
                interatom.rdc[tag] = interatom.rdc[tag][0] / self.N**self.MODES

            # Save.
            self.interpreter.rdc.write(align_id=tag, file='rdc_%s.txt'%tag, dir=self.save_path, force=True)
Exemplo n.º 17
0
def return_pcs_data(sim_index=None, verbosity=0):
    """Set up the data structures for optimisation using PCSs as base data sets.

    @keyword sim_index: The index of the simulation to optimise.  This should be None if normal optimisation is desired.
    @type sim_index:    None or int
    @keyword verbosity: A flag specifying the amount of information to print.  The higher the value, the greater the verbosity.
    @type verbosity:    int
    @return:            The assembled data structures for using PCSs as the base data for optimisation.  These include:
                            - the PCS values.
                            - the unit vectors connecting the paramagnetic centre (the electron spin) to the spin.
                            - the PCS weight.
                            - the experimental temperatures.
                            - the spectrometer frequencies.
                            - pseudo_flags, the list of flags indicating if the interatomic data contains a pseudo-atom (as 1's and 0's).
    @rtype:             tuple of (numpy rank-2 float64 array, numpy rank-2 float64 array, numpy rank-2 float64 array, list of float, list of float, numpy rank-1 int32 array)
    """

    # Initial printout.
    if verbosity:
        print("\nPCS data counts:")

    # Data setup tests.
    if not hasattr(cdp, 'paramagnetic_centre') and (hasattr(cdp, 'paramag_centre_fixed') and cdp.paramag_centre_fixed):
        raise RelaxError("The paramagnetic centre has not yet been specified.")
    if not hasattr(cdp, 'temperature'):
        raise RelaxError("The experimental temperatures have not been set.")
    if not hasattr(cdp, 'spectrometer_frq'):
        raise RelaxError("The spectrometer frequencies of the experiments have not been set.")

    # Sort out pseudo-atoms first.  This only needs to be called once.
    setup_pseudoatom_pcs()

    # Initialise.
    pcs = []
    pcs_err = []
    pcs_weight = []
    temp = []
    frq = []
    pseudo_flags = []

    # The PCS data.
    for i in range(len(cdp.align_ids)):
        # Alias the ID.
        align_id = cdp.align_ids[i]

        # Skip non-optimised data.
        if not opt_uses_align_data(align_id):
            continue

        # Append empty arrays to the PCS structures.
        pcs.append([])
        pcs_err.append([])
        pcs_weight.append([])

        # Get the temperature for the PCS constant.
        if align_id in cdp.temperature:
            temp.append(cdp.temperature[align_id])

        # The temperature must be given!
        else:
            raise RelaxError("The experimental temperature for the alignment ID '%s' has not been set." % align_id)

        # Get the spectrometer frequency in Tesla units for the PCS constant.
        if align_id in cdp.spectrometer_frq:
            frq.append(cdp.spectrometer_frq[align_id] * 2.0 * pi / periodic_table.gyromagnetic_ratio('1H'))

        # The frequency must be given!
        else:
            raise RelaxError("The spectrometer frequency for the alignment ID '%s' has not been set." % align_id)

        # Spin loop.
        j = 0
        for spin in spin_loop():
            # Skip deselected spins.
            if not spin.select:
                continue

            # Skip spins without PCS data.
            if not hasattr(spin, 'pcs'):
                continue

            # Append the PCSs to the list.
            if align_id in spin.pcs:
                if sim_index != None:
                    pcs[-1].append(spin.pcs_sim[align_id][sim_index])
                else:
                    pcs[-1].append(spin.pcs[align_id])

                # Increment the PCS count.
                if pcs[-1][-1] != None:
                    j += 1

            # No data.
            else:
                pcs[-1].append(None)

            # Append the PCS errors.
            if hasattr(spin, 'pcs_err') and align_id in spin.pcs_err:
                pcs_err[-1].append(spin.pcs_err[align_id])
            else:
                pcs_err[-1].append(None)

            # Append the weight.
            if hasattr(spin, 'pcs_weight') and align_id in spin.pcs_weight:
                pcs_weight[-1].append(spin.pcs_weight[align_id])
            else:
                pcs_weight[-1].append(1.0)

        # ID and PCS count printout.
        if verbosity:
            print("    Alignment ID '%s':  %i" % (align_id, j))

    # Pseudo-atom.
    for spin in spin_loop():
        if is_pseudoatom(spin):
            pseudo_flags.append(1)
        else:
            pseudo_flags.append(0)

    # Convert to numpy objects.
    pcs = array(pcs, float64)
    pcs_err = array(pcs_err, float64)
    pcs_weight = array(pcs_weight, float64)
    pseudo_flags = array(pseudo_flags, int32)

    # Convert the PCS from ppm to no units.
    pcs = pcs * 1e-6
    pcs_err = pcs_err * 1e-6

    # Return the data structures.
    return pcs, pcs_err, pcs_weight, temp, frq, pseudo_flags
Exemplo n.º 18
0
def back_calc(align_id=None):
    """Back calculate the PCS from the alignment tensor.

    @keyword align_id:      The alignment tensor ID string.
    @type align_id:         str
    """

    # Check the pipe setup.
    check_pipe_setup(pcs_id=align_id, sequence=True, N=True, tensors=True, paramag_centre=True)

    # Convert the align IDs to an array, or take all IDs.
    if align_id:
        align_ids = [align_id]
    else:
        align_ids = cdp.align_ids

    # Add the ID to the PCS IDs, if needed.
    for align_id in align_ids:
        # Init.
        if not hasattr(cdp, 'pcs_ids'):
            cdp.pcs_ids = []

        # Add the ID.
        if align_id not in cdp.pcs_ids:
            cdp.pcs_ids.append(align_id)

    # The weights.
    weights = ones(cdp.N, float64) / cdp.N

    # Unit vector data structure init.
    unit_vect = zeros((cdp.N, 3), float64)

    # Loop over the spins.
    count = 0
    for spin in spin_loop():
        # Skip spins with no position.
        if not hasattr(spin, 'pos'):
            continue

        # Atom positions.
        pos = spin.pos
        if type(pos[0]) in [float, float64]:
            pos = [pos] * cdp.N

        # Loop over the alignments.
        for id in align_ids:
            # Vectors.
            vect = zeros((cdp.N, 3), float64)
            r = zeros(cdp.N, float64)
            dj = zeros(cdp.N, float64)
            for c in range(cdp.N):
                # The vector.
                vect[c] = pos[c] - cdp.paramagnetic_centre

                # The length.
                r[c] = norm(vect[c])

                # Normalise (only if the vector has length).
                if r[c]:
                    vect[c] = vect[c] / r[c]

                # Calculate the PCS constant.
                dj[c] = pcs_constant(cdp.temperature[id], cdp.spectrometer_frq[id] * 2.0 * pi / periodic_table.gyromagnetic_ratio('1H'), r[c]/1e10)

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

            # Calculate the PCSs (in ppm).
            spin.pcs_bc[id] = ave_pcs_tensor(dj, vect, cdp.N, cdp.align_tensors[get_tensor_index(align_id=id)].A, weights=weights) * 1e6

        # Increment the counter.
        count += 1

    # No PCSs calculated.
    if not count:
        warn(RelaxWarning("No PCSs have been back calculated, probably due to missing spin position information."))
Exemplo n.º 19
0

# Path of the files.
str_path = status.install_path + sep+'test_suite'+sep+'shared_data'+sep+'structures'

# The data pipe.
self._execute_uf(uf_name='pipe.create', pipe_name='pcs_back_calc', pipe_type='N-state')

# Load the structures.
self._execute_uf(uf_name='structure.read_pdb', file='trunc_ubi_pcs.pdb', dir=str_path)

# Load the proton spins.
self._execute_uf(uf_name='structure.load_spins', spin_id='@H')

# The dipolar constant.
const = 3.0 / (2.0*pi) * dipolar_constant(periodic_table.gyromagnetic_ratio('15N'), periodic_table.gyromagnetic_ratio('1H'), NH_BOND_LENGTH_RDC)

# The tensor.
tensor = 'A'
align_id = tensor
self._execute_uf(uf_name='align_tensor.init', tensor=tensor, params=(4.724/const,  11.856/const, 0, 0, 0), align_id=align_id, param_types=2)

# The temperature.
self._execute_uf(uf_name='spectrometer.temperature', id=align_id, temp=298)

# The frequency.
self._execute_uf(uf_name='spectrometer.frequency', id=align_id, frq=900.0 * 1e6)

# One state model.
self._execute_uf(uf_name='n_state_model.select_model', model='fixed')
self._execute_uf(uf_name='n_state_model.number_of_states', N=1)
Exemplo n.º 20
0
def create_spin_input(function=None, spin=None, spin_id=None, dir=None):
    """Generate the CPMGFit file for the given spin.

    @keyword function:  The CPMGFit model or function name.
    @type function:     str
    @keyword spin:      The spin container to generate the input file for.
    @type spin:         SpinContainer instance
    @keyword spin_id:   The spin ID string corresponding to the spin container.
    @type spin_id:      str
    @keyword dir:       The directory to place the file into.
    @type dir:          str or None
    @return:            The name of the file created.
    @rtype:             str
    """

    # The output file.
    file_name = spin_file_name(spin_id=spin_id)
    file = open_write_file(file_name=file_name, dir=dir, force=True)

    # The title.
    file.write("title %s\n" % spin_id)

    # The proton frequencies.
    frq = get_frequencies(units='T')

    # The frequency info.
    file.write("fields %s" % len(frq))
    for i in range(len(frq)):
        file.write(" %.10f" % frq[i])
    file.write("\n")

    # The function and parameters.
    if function == 'CPMG':
        # Function.
        file.write("function CPMG\n")

        # Parameters.
        file.write("R2 1 10 20\n")
        file.write("Rex 0 100.0 100\n")
        file.write("Tau 0 10.0 100\n")

    # The function and parameters.
    elif function == 'Full_CPMG':
        # Function.
        file.write("function Full_CPMG\n")

        # Parameters.
        file.write("R2 1 10 20\n")
        file.write("papb 0.01 0.49 20\n")
        file.write("dw 0 10.0 100\n")
        file.write("kex 0.1 1.0 100\n")

    # The function and parameters.
    elif function == "Ishima":
        # Function.
        file.write("function Ishima\n")

        # Parameters.
        file.write("R2 1 10 20\n")
        file.write("Rex 0 100.0 50\n")
        file.write("PaDw 2 10.0 50\n")
        file.write("Tau 0.1 10.0 50\n")

    # The function and parameters.
    if function == '3-site_CPMG':
        # Function.
        file.write("function 3-site_CPMG\n")

        # Parameters.
        file.write("R2 1 10 20\n")
        file.write("Rex1 0 100.0 20\n")
        file.write("Tau1 0 10.0 20\n")
        file.write("Rex2 0 100.0 20\n")
        file.write("Tau2 0 10.0 20\n")

    # The Grace setup.
    file.write("xmgr\n")
    file.write("@ xaxis label \"1/tcp (1/ms)\"\n")
    file.write("@ yaxis label \"R2(tcp) (rad/s)\"\n")
    file.write("@ xaxis ticklabel format decimal\n")
    file.write("@ yaxis ticklabel format decimal\n")
    file.write("@ xaxis ticklabel char size 0.8\n")
    file.write("@ yaxis ticklabel char size 0.8\n")
    file.write("@ world xmin 0.0\n")

    # The data.
    file.write("data\n")
    for exp_type, frq, offset, point in loop_exp_frq_offset_point():
        # The parameter key.
        param_key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point)

        # No data.
        if param_key not in spin.r2eff:
            continue

        # Tesla units.
        B0 = frq * 2.0 * pi / periodic_table.gyromagnetic_ratio('1H')

        # The X value of 1/tcp (or 1/tau_CPMG) in ms.  This assumes Art's usage of the definition that nu_CPMG = 1 / (2 * tau_CPMG).
        x = 2.0 * point / 1000.0

        # Write out the data and error.
        file.write("%-20f %-20f %-20f %-20f\n" % (x, spin.r2eff[param_key], spin.r2eff_err[param_key], B0))

    # Close the file and return its name.
    file.close()
    return file_name
Exemplo n.º 21
0
def sherekhan_input(spin_id=None, force=False, dir='ShereKhan'):
    """Create the ShereKhan input files.

    @keyword spin_id:           The spin ID string to restrict the file creation to.
    @type spin_id:              str
    @keyword force:             A flag which if True will cause all pre-existing files to be overwritten.
    @type force:                bool
    @keyword dir:               The optional directory to place the files into.  If None, then the files will be placed into the current directory.
    @type dir:                  str or None
    """

    # Test if the current pipe exists.
    check_pipe()

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

    # Test if the experiment type has been set.
    if not hasattr(cdp, 'exp_type'):
        raise RelaxError("The relaxation dispersion experiment type has not been specified.")

    # Test if the model has been set.
    if not hasattr(cdp, 'model_type'):
        raise RelaxError("The relaxation dispersion model has not been specified.")

    # Directory creation.
    if dir != None:
        mkdir_nofail(dir, verbosity=0)

    # Loop over the spin blocks.
    cluster_index = 0
    for spin_ids in loop_cluster():
        # The spin containers.
        spins = spin_ids_to_containers(spin_ids)

        # Loop over the magnetic fields.
        for exp_type, frq, ei, mi in loop_exp_frq(return_indices=True):
            # Loop over the time, and count it.
            time_i = 0
            for time, ti in loop_time(exp_type=exp_type, frq=frq, return_indices=True):
                time_i += 1

            # Check that not more than one time point is returned.
            if time_i > 1:
                raise RelaxError("Number of returned time poins is %i. Only 1 time point is expected."%time_i)

            # The ShereKhan input file for the spin cluster.
            file_name = 'sherekhan_frq%s.in' % (mi+1)
            if dir != None:
                dir_name = dir + sep + 'cluster%s' % (cluster_index+1)
            else:
                dir_name = 'cluster%s' % (cluster_index+1)
            file = open_write_file(file_name=file_name, dir=dir_name, force=force)

            # The B0 field for the nuclei of interest in MHz (must be positive to be accepted by the server).
            file.write("%.10f\n" % abs(frq / periodic_table.gyromagnetic_ratio('1H') * periodic_table.gyromagnetic_ratio('15N') / 1e6))

            # The constant relaxation time for the CPMG experiment in seconds.
            file.write("%s\n" % (time))

            # The comment line.
            file.write("# %-18s %-20s %-20s\n" % ("nu_cpmg (Hz)", "R2eff (rad/s)", "Error"))

            # Loop over the spins of the cluster.
            for i in range(len(spins)):
                # Get the residue container.
                res = return_residue(spin_ids[i])

                # Name the residue if needed.
                res_name = res.name
                if res_name == None:
                    res_name = 'X'

                # Initialise the lines to output (to be able to catch missing data).
                lines = []

                # The residue ID line.
                lines.append("# %s%s\n" % (res_name, res.num))

                # Loop over the dispersion points.
                for offset, point in loop_offset_point(exp_type=exp_type, frq=frq, skip_ref=True):
                    # The parameter key.
                    param_key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point)

                    # No data.
                    if param_key not in spins[i].r2eff:
                        continue

                    # Store the data.
                    lines.append("%20.15g %20.13g %20.13g\n" % (point, spins[i].r2eff[param_key], spins[i].r2eff_err[param_key]))

                # No data.
                if len(lines) == 1:
                    continue

                # Write out the data.
                for line in lines:
                    file.write(line)

            # Close the file.
            file.close()

        # Increment the cluster index.
        cluster_index += 1
Exemplo n.º 22
0
Arquivo: api.py Projeto: tlinnet/relax
    def calculate(self, spin_id=None, scaling_matrix=None, verbosity=1, sim_index=None):
        """Calculation of the consistency functions.

        @keyword spin_id:           The spin identification string.
        @type spin_id:              None or str
        @keyword scaling_matrix:    The per-model list of diagonal and square scaling matrices.
        @type scaling_matrix:       list of numpy rank-2, float64 array or list of None
        @keyword verbosity:         The amount of information to print.  The higher the value, the greater the verbosity.
        @type verbosity:            int
        @keyword sim_index:         The optional MC simulation index.
        @type sim_index:            None or int
        """

        # Test if the frequency has been set.
        if not hasattr(cdp, 'ct_frq') or not isinstance(cdp.ct_frq, float):
            raise RelaxError("The frequency has not been set up.")

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

        # Test if the spin data has been set.
        for spin, id in spin_loop(spin_id, return_id=True):
            # Skip deselected spins.
            if not spin.select:
                continue

            # Test if the nuclear isotope type has been set.
            if not hasattr(spin, 'isotope'):
                raise RelaxSpinTypeError

            # Test if the CSA value has been set.
            if not hasattr(spin, 'csa') or spin.csa == None:
                raise RelaxNoValueError("CSA")

            # Test if the angle Theta has been set.
            if not hasattr(spin, 'orientation') or spin.orientation == None:
                raise RelaxNoValueError("angle Theta")

            # Test if the correlation time has been set.
            if not hasattr(spin, 'tc') or spin.tc == None:
                raise RelaxNoValueError("correlation time")

            # Test the interatomic data.
            interatoms = return_interatom_list(spin_hash=spin._hash)
            for interatom in interatoms:
                # No relaxation mechanism.
                if not interatom.dipole_pair:
                    continue

                # The interacting spin.
                if id != interatom.spin_id1:
                    spin_id2 = interatom.spin_id1
                else:
                    spin_id2 = interatom.spin_id2
                spin2 = return_spin(spin_id=spin_id2)

                # Test if the nuclear isotope type has been set.
                if not hasattr(spin2, 'isotope'):
                    raise RelaxSpinTypeError

                # Test if the interatomic distance has been set.
                if not hasattr(interatom, 'r') or interatom.r == None:
                    raise RelaxNoValueError("interatomic distance", spin_id=spin_id, spin_id2=spin_id2)

        # Frequency index.
        if cdp.ct_frq not in list(cdp.spectrometer_frq.values()):
            raise RelaxError("No relaxation data corresponding to the frequency %s has been loaded." % cdp.ct_frq)

        # Consistency testing.
        for spin, id in spin_loop(spin_id, return_id=True):
            # Skip deselected spins.
            if not spin.select:
                continue

            # Set the r1, r2, and NOE to None.
            r1 = None
            r2 = None
            noe = None

            # Get the R1, R2, and NOE values corresponding to the set frequency.
            for ri_id in cdp.ri_ids:
                # The frequency does not match.
                if cdp.spectrometer_frq[ri_id] != cdp.ct_frq:
                    continue

                # R1.
                if cdp.ri_type[ri_id] == 'R1':
                    if sim_index == None:
                        r1 = spin.ri_data[ri_id]
                    else:
                        r1 = spin.ri_data_sim[ri_id][sim_index]

                # R2.
                if cdp.ri_type[ri_id] == 'R2':
                    if sim_index == None:
                        r2 = spin.ri_data[ri_id]
                    else:
                        r2 = spin.ri_data_sim[ri_id][sim_index]

                # NOE.
                if cdp.ri_type[ri_id] == 'NOE':
                    if sim_index == None:
                        noe = spin.ri_data[ri_id]
                    else:
                        noe = spin.ri_data_sim[ri_id][sim_index]

            # Skip the spin if not all of the three value exist.
            if r1 == None or r2 == None or noe == None:
                continue

            # Loop over the interatomic data.
            interatoms = return_interatom_list(spin_hash=spin._hash)
            for i in range(len(interatoms)):
                # No relaxation mechanism.
                if not interatoms[i].dipole_pair:
                    continue

                # The surrounding spins.
                if id != interatoms[i].spin_id1:
                    spin_id2 = interatoms[i].spin_id1
                else:
                    spin_id2 = interatoms[i].spin_id2
                spin2 = return_spin(spin_id=spin_id2)

                # Gyromagnetic ratios.
                gx = periodic_table.gyromagnetic_ratio(spin.isotope)
                gh = periodic_table.gyromagnetic_ratio(spin2.isotope)

                # The interatomic distance.
                r = interatoms[i].r

            # Initialise the function to calculate.
            ct = Consistency(frq=cdp.ct_frq, gx=gx, gh=gh, mu0=mu0, h_bar=h_bar)

            # Calculate the consistency tests values.
            j0, f_eta, f_r2 = ct.func(orientation=spin.orientation, tc=spin.tc, r=r, csa=spin.csa, r1=r1, r2=r2, noe=noe)

            # Consistency tests values.
            if sim_index == None:
                spin.j0 = j0
                spin.f_eta = f_eta
                spin.f_r2 = f_r2

            # Monte Carlo simulated consistency tests values.
            else:
                # Initialise the simulation data structures.
                self.data_init(id, sim=1)
                if spin.j0_sim == None:
                    spin.j0_sim = []
                    spin.f_eta_sim = []
                    spin.f_r2_sim = []

                # Consistency tests values.
                spin.j0_sim.append(j0)
                spin.f_eta_sim.append(f_eta)
                spin.f_r2_sim.append(f_r2)
Exemplo n.º 23
0
    def _calculate_pcs(self):
        """Calculate the averaged PCS for all states."""

        # Printout.
        sys.stdout.write("\n\nRotating %s states for the PCS:\n\n" % locale.format("%d", self.N**self.MODES, grouping=True))

        # Turn off the relax interpreter echoing to allow the progress meter to be shown correctly.
        self.interpreter.off()

        # Set up some data structures for faster calculations.
        spins = []
        spin_pos = []
        d = {}
        for tag in self._tensors:
            d[tag] = []
        for spin in spin_loop():
            # Nothing to do.
            if not hasattr(spin, 'pos'):
                continue

            # Initialise the PCS structure (as a 1D numpy.float128 array for speed and minimising truncation artifacts).
            spin.pcs = {}
            for tag in self._tensors:
                spin.pcs[tag] = zeros(1, float128)

            # Pack the spin containers and positions.
            spins.append(spin)
            spin_pos.append(spin.pos[0])

            # Calculate the partial PCS constant (with no vector length).
            for tag in self._tensors:
                d[tag].append(pcs_constant(cdp.temperature[tag], cdp.spectrometer_frq[tag] * 2.0 * pi / periodic_table.gyromagnetic_ratio('1H'), 1.0))

        # Repackage the data for speed.
        spin_pos = array(spin_pos, float64)
        num_spins = len(spin_pos)
        for tag in self._tensors:
            d[tag] = array(d[tag], float64)

        # Store the alignment tensors.
        A = []
        for i in range(len(self._tensors)):
            A.append(cdp.align_tensors[i].A)

        # Loop over each position.
        for global_index, mode_indices in self._state_loop():
            # The progress meter.
            self._progress(global_index)

            # Data initialisation.
            new_pos = spin_pos

            # Loop over each motional mode.
            for motion_index in range(self.MODES):
                # Generate the distribution specific rotation.
                self.rotation(mode_indices[motion_index], motion_index=motion_index)

                # Rotate the atomic positions.
                new_pos = transpose(tensordot(self.R, transpose(new_pos - self.PIVOT[motion_index]), axes=1)) + self.PIVOT[motion_index]

            # The vectors.
            vectors = new_pos - cdp.paramagnetic_centre

            # The lengths.
            r = norm(vectors, axis=1)

            # The scaling factor that includes the Angstrom to meter converted length cubed and the ppm conversion.
            fact = 1e6 / (r / 1e10)**3

            # Normalise.
            vectors = transpose(vectors) / r

            # Loop over each alignment.
            for i in range(len(self._tensors)):
                # Calculate the PCS as quickly as possible (the 1e36 is from the 1e10**3 Angstrom conversion and the 1e6 ppm conversion).
                pcss = d[self._tensors[i]] * fact * tensordot(transpose(vectors), tensordot(A[i], vectors, axes=1), axes=1)

                # Store the values.
                for j in range(len(spins)):
                    spins[j].pcs[self._tensors[i]][0] += pcss[j, j]

        # Print out.
        sys.stdout.write('\n\n')

        # Reactive the interpreter echoing.
        self.interpreter.on()

        # Average the PCS and write the data.
        for tag in self._tensors:
            # Average.
            for spin in spin_loop():
                spin.pcs[tag] = spin.pcs[tag][0] / self.N**self.MODES

            # Save.
            self.interpreter.pcs.write(align_id=tag, file='pcs_%s.txt'%tag, dir=self.save_path, force=True)
Exemplo n.º 24
0
    def _calculate_rdc(self):
        """Calculate the averaged RDC for all states."""

        # Open the output files.
        if self.ROT_FILE:
            rot_file = open_write_file('rotations', dir=self.save_path, compress_type=1, force=True)

        # Printout.
        sys.stdout.write("\n\nRotating %s states for the RDC:\n\n" % locale.format("%d", self.N**self.MODES, grouping=True))

        # Turn off the relax interpreter echoing to allow the progress meter to be shown correctly.
        self.interpreter.off()

        # Set up some data structures for faster calculations.
        interatoms = []
        vectors = []
        d = []
        for interatom in interatomic_loop():
            # Nothing to do.
            if not hasattr(interatom, 'vector'):
                continue

            # Initialise the RDC structure (as a 1D numpy.float128 array for speed and minimising truncation artifacts).
            interatom.rdc = {}
            for tag in self._tensors:
                interatom.rdc[tag] = zeros(1, float128)

            # Pack the interatomic containers and vectors.
            interatoms.append(interatom)
            vectors.append(interatom.vector)

            # Get the spins.
            spin1 = return_spin(spin_id=interatom.spin_id1)
            spin2 = return_spin(spin_id=interatom.spin_id2)

            # Gyromagnetic ratios.
            g1 = periodic_table.gyromagnetic_ratio(spin1.isotope)
            g2 = periodic_table.gyromagnetic_ratio(spin2.isotope)

            # Calculate the RDC dipolar constant (in Hertz, and the 3 comes from the alignment tensor), and append it to the list.
            d.append(3.0/(2.0*pi) * dipolar_constant(g1, g2, interatom.r))

        # Repackage the data for speed.
        vectors = transpose(array(vectors, float64))
        d = array(d, float64)
        num_interatoms = len(vectors)

        # Store the alignment tensors.
        A = []
        for i in range(len(self._tensors)):
            A.append(cdp.align_tensors[i].A)

        # Loop over each position.
        for global_index, mode_indices in self._state_loop():
            # The progress meter.
            self._progress(global_index)

            # Total rotation matrix (for construction of the frame order matrix).
            total_R = eye(3)

            # Data initialisation.
            new_vect = vectors

            # Loop over each motional mode.
            for motion_index in range(self.MODES):
                # Generate the distribution specific rotation.
                self.rotation(mode_indices[motion_index], motion_index=motion_index)

                # Rotate the NH vector.
                new_vect = dot(self.R, new_vect)

                # Decompose the rotation into Euler angles and store them.
                if self.ROT_FILE:
                    a, b, g = R_to_euler_zyz(self.R)
                    rot_file.write('Mode %i:  %10.7f %10.7f %10.7f\n' % (motion_index, a, b, g))

                # Contribution to the total rotation.
                total_R = dot(self.R, total_R)

            # Loop over each alignment.
            for i in range(len(self._tensors)):
                # Calculate the RDC as quickly as possible.
                rdcs = d * tensordot(transpose(new_vect), tensordot(A[i], new_vect, axes=1), axes=1)

                # Store the values.
                for j in range(len(interatoms)):
                    interatoms[j].rdc[self._tensors[i]][0] += rdcs[j, j]

            # The frame order matrix component.
            self.daeg += kron_prod(total_R, total_R)

        # Print out.
        sys.stdout.write('\n\n')

        # Frame order matrix averaging.
        self.daeg = self.daeg / self.N**self.MODES

        # Write out the frame order matrix.
        file = open(self.save_path+sep+'frame_order_matrix', 'w')
        print_frame_order_2nd_degree(self.daeg, file=file, places=8)

        # Reactive the interpreter echoing.
        self.interpreter.on()

        # Average the RDC and write the data.
        for tag in self._tensors:
            # Average.
            for interatom in interatomic_loop():
                interatom.rdc[tag] = interatom.rdc[tag][0] / self.N**self.MODES

            # Save.
            self.interpreter.rdc.write(align_id=tag, file='rdc_%s.txt'%tag, dir=self.save_path, force=True)
Exemplo n.º 25
0
def minimise_data_setup(data_store, min_algor, num_data_sets, min_options, spin=None, sim_index=None):
    """Set up all the data required for minimisation.

    @param data_store:      A data storage container.
    @type data_store:       class instance
    @param min_algor:       The minimisation algorithm to use.
    @type min_algor:        str
    @param num_data_sets:   The number of data sets.
    @type num_data_sets:    int
    @param min_options:     The minimisation options array.
    @type min_options:      list
    @keyword spin:          The spin data container.
    @type spin:             SpinContainer instance
    @keyword sim_index:     The optional MC simulation index.
    @type sim_index:        int
    @return:                An insane tuple.  The full tuple is (ri_data, ri_data_err, equations, param_types, param_values, r, csa, num_frq, frq, num_ri, remap_table, noe_r1_table, ri_types, num_params, xh_unit_vectors, diff_type, diff_params)
    @rtype:                 tuple
    """

    # Initialise the data structures for the model-free function.
    data_store.ri_data = []
    data_store.ri_data_err = []
    data_store.equations = []
    data_store.param_types = []
    data_store.param_values = None
    data_store.r = []
    data_store.csa = []
    data_store.num_frq = []
    data_store.frq = []
    data_store.num_ri = []
    data_store.remap_table = []
    data_store.noe_r1_table = []
    data_store.ri_types = []
    data_store.gx = []
    data_store.gh = []
    data_store.num_params = []
    data_store.xh_unit_vectors = []
    if data_store.model_type == "local_tm":
        data_store.mf_params = []
    elif data_store.model_type == "diff":
        data_store.param_values = []

    # Set up the data for the back_calc function.
    if min_algor == "back_calc":
        # The spin data.
        data_store.ri_data = [0.0]
        data_store.ri_data_err = [0.000001]
        data_store.equations = [spin.equation]
        data_store.param_types = [spin.params]
        data_store.csa = [spin.csa]
        data_store.num_frq = [1]
        data_store.frq = [[min_options[3]]]
        data_store.num_ri = [1]
        data_store.remap_table = [[0]]
        data_store.noe_r1_table = [[None]]
        data_store.ri_types = [[min_options[2]]]
        data_store.gx = [periodic_table.gyromagnetic_ratio(spin.isotope)]

        # The interatomic data.
        interatoms = return_interatom_list(data_store.spin_id)
        for i in range(len(interatoms)):
            # No relaxation mechanism.
            if not interatoms[i].dipole_pair:
                continue

            # The surrounding spins.
            if data_store.spin_id != interatoms[i].spin_id1:
                spin_id2 = interatoms[i].spin_id1
            else:
                spin_id2 = interatoms[i].spin_id2
            spin2 = return_spin(spin_id2)

            # The data.
            data_store.r = [interatoms[i].r]
            data_store.gh = [periodic_table.gyromagnetic_ratio(spin2.isotope)]
            if data_store.model_type != "local_tm" and cdp.diff_tensor.type != "sphere":
                data_store.xh_unit_vectors = [interatoms[i].vector]
            else:
                data_store.xh_unit_vectors = [None]

        # Count the number of model-free parameters for the spin index.
        data_store.num_params = [len(spin.params)]

    # Loop over the number of data sets.
    for j in range(num_data_sets):
        # Set the spin index and get the spin, if not already set.
        if data_store.model_type == "diff" or data_store.model_type == "all":
            spin_index = j
            spin, data_store.spin_id = return_spin_from_index(global_index=spin_index, return_spin_id=True)

        # Skip deselected spins.
        if not spin.select:
            continue

        # Skip spins where there is no data or errors.
        if not hasattr(spin, "ri_data") or not hasattr(spin, "ri_data_err"):
            continue

        # Make sure that the errors are strictly positive numbers.
        for ri_id in cdp.ri_ids:
            # Skip missing data.
            if not ri_id in spin.ri_data_err:
                continue

            # Alias.
            err = spin.ri_data_err[ri_id]

            # Checks.
            if err != None and err == 0.0:
                raise RelaxError(
                    "Zero error for spin '%s' for the relaxation data ID '%s', minimisation not possible."
                    % (data_store.spin_id, ri_id)
                )
            elif err != None and err < 0.0:
                raise RelaxError(
                    "Negative error of %s for spin '%s' for the relaxation data ID '%s', minimisation not possible."
                    % (err, data_store.spin_id, ri_id)
                )

        # The relaxation data optimisation structures.
        data = relax_data_opt_structs(spin, sim_index=sim_index)

        # Append the data.
        data_store.ri_data.append(data[0])
        data_store.ri_data_err.append(data[1])
        data_store.num_frq.append(data[2])
        data_store.num_ri.append(data[3])
        data_store.ri_types.append(data[4])
        data_store.frq.append(data[5])
        data_store.remap_table.append(data[6])
        data_store.noe_r1_table.append(data[7])
        if sim_index == None or data_store.model_type == "diff":
            data_store.csa.append(spin.csa)
        else:
            data_store.csa.append(spin.csa_sim[sim_index])

        # Repackage the spin data.
        data_store.equations.append(spin.equation)
        data_store.param_types.append(spin.params)
        data_store.gx.append(periodic_table.gyromagnetic_ratio(spin.isotope))

        # Repackage the interatomic data.
        interatoms = return_interatom_list(data_store.spin_id)
        for i in range(len(interatoms)):
            # No relaxation mechanism.
            if not interatoms[i].dipole_pair:
                continue

            # The surrounding spins.
            if data_store.spin_id != interatoms[i].spin_id1:
                spin_id2 = interatoms[i].spin_id1
            else:
                spin_id2 = interatoms[i].spin_id2
            spin2 = return_spin(spin_id2)

            # The data.
            data_store.gh.append(periodic_table.gyromagnetic_ratio(spin2.isotope))
            if sim_index == None or data_store.model_type == "diff" or not hasattr(interatoms[i], "r_sim"):
                data_store.r.append(interatoms[i].r)
            else:
                data_store.r.append(interatoms[i].r_sim[sim_index])

            # Vectors.
            if data_store.model_type != "local_tm" and cdp.diff_tensor.type != "sphere":
                # Check that this is a single vector!
                if lib.arg_check.is_num_list(interatoms[i].vector[0], raise_error=False):
                    raise RelaxMultiVectorError(data_store.spin_id)

                # Store the vector.
                data_store.xh_unit_vectors.append(interatoms[i].vector)

            # No vector.
            else:
                data_store.xh_unit_vectors.append(None)

            # Stop - only one mechanism is current supported.
            break

        # Model-free parameter values.
        if data_store.model_type == "local_tm":
            pass

        # Count the number of model-free parameters for the spin index.
        data_store.num_params.append(len(spin.params))

        # Repackage the parameter values for minimising just the diffusion tensor parameters.
        if data_store.model_type == "diff":
            data_store.param_values.append(assemble_param_vector(model_type="mf"))

    # Convert to numpy arrays.
    for k in range(len(data_store.ri_data)):
        data_store.ri_data[k] = array(data_store.ri_data[k], float64)
        data_store.ri_data_err[k] = array(data_store.ri_data_err[k], float64)

    # Diffusion tensor type.
    if data_store.model_type == "local_tm":
        data_store.diff_type = "sphere"
    else:
        data_store.diff_type = cdp.diff_tensor.type

    # Package the diffusion tensor parameters.
    data_store.diff_params = None
    if data_store.model_type == "mf":
        # Spherical diffusion.
        if data_store.diff_type == "sphere":
            data_store.diff_params = [cdp.diff_tensor.tm]

        # Spheroidal diffusion.
        elif data_store.diff_type == "spheroid":
            data_store.diff_params = [
                cdp.diff_tensor.tm,
                cdp.diff_tensor.Da,
                cdp.diff_tensor.theta,
                cdp.diff_tensor.phi,
            ]

        # Ellipsoidal diffusion.
        elif data_store.diff_type == "ellipsoid":
            data_store.diff_params = [
                cdp.diff_tensor.tm,
                cdp.diff_tensor.Da,
                cdp.diff_tensor.Dr,
                cdp.diff_tensor.alpha,
                cdp.diff_tensor.beta,
                cdp.diff_tensor.gamma,
            ]
    elif min_algor == "back_calc" and data_store.model_type == "local_tm":
        # Spherical diffusion.
        data_store.diff_params = [spin.local_tm]
Exemplo n.º 26
0
# Load the spins.
self._execute_uf(uf_name='structure.load_spins', spin_id='@N', ave_pos=False)
self._execute_uf(uf_name='structure.load_spins', spin_id='@H', ave_pos=False)

# Define the magnetic dipole-dipole relaxation interaction.
self._execute_uf(uf_name='interatom.define', spin_id1='@N', spin_id2='@H', direct_bond=True)
self._execute_uf(uf_name='interatom.set_dist', spin_id1='@N', spin_id2='@H', ave_dist=NH_BOND_LENGTH_RDC)
self._execute_uf(uf_name='interatom.unit_vectors', ave=True)

# Set the nuclear isotope.
self._execute_uf(uf_name='spin.isotope', isotope='15N', spin_id='@N')
self._execute_uf(uf_name='spin.isotope', isotope='1H', spin_id='@H')

# The dipolar constant.
const = 3.0 / (2.0*pi) * dipolar_constant(periodic_table.gyromagnetic_ratio('15N'), periodic_table.gyromagnetic_ratio('1H'), NH_BOND_LENGTH_RDC)

# The tensor.
tensor = 'A'
self._execute_uf(uf_name='align_tensor.init', tensor=tensor, params=(4.724/const,  11.856/const, 0, 0, 0), align_id=tensor, param_types=2)

# The temperature.
self._execute_uf(uf_name='spectrometer.temperature', id=tensor, temp=298)

# The frequency.
self._execute_uf(uf_name='spectrometer.frequency', id=tensor, frq=900.0 * 1e6)

# One state model.
self._execute_uf(uf_name='n_state_model.select_model', model='fixed')
self._execute_uf(uf_name='n_state_model.number_of_states', N=1)
Exemplo n.º 27
0
    def calculate(self, spin_id=None, scaling_matrix=None, verbosity=1, sim_index=None):
        """Calculation of the consistency functions.

        @keyword spin_id:           The spin identification string.
        @type spin_id:              None or str
        @keyword scaling_matrix:    The per-model list of diagonal and square scaling matrices.
        @type scaling_matrix:       list of numpy rank-2, float64 array or list of None
        @keyword verbosity:         The amount of information to print.  The higher the value, the greater the verbosity.
        @type verbosity:            int
        @keyword sim_index:         The optional MC simulation index.
        @type sim_index:            None or int
        """

        # Test if the frequency has been set.
        if not hasattr(cdp, 'ct_frq') or not isinstance(cdp.ct_frq, float):
            raise RelaxError("The frequency has not been set up.")

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

        # Test if the spin data has been set.
        for spin, id in spin_loop(spin_id, return_id=True):
            # Skip deselected spins.
            if not spin.select:
                continue

            # Test if the nuclear isotope type has been set.
            if not hasattr(spin, 'isotope'):
                raise RelaxSpinTypeError

            # Test if the CSA value has been set.
            if not hasattr(spin, 'csa') or spin.csa == None:
                raise RelaxNoValueError("CSA")

            # Test if the angle Theta has been set.
            if not hasattr(spin, 'orientation') or spin.orientation == None:
                raise RelaxNoValueError("angle Theta")

            # Test if the correlation time has been set.
            if not hasattr(spin, 'tc') or spin.tc == None:
                raise RelaxNoValueError("correlation time")

            # Test the interatomic data.
            interatoms = return_interatom_list(id)
            for interatom in interatoms:
                # No relaxation mechanism.
                if not interatom.dipole_pair:
                    continue

                # The interacting spin.
                if id != interatom.spin_id1:
                    spin_id2 = interatom.spin_id1
                else:
                    spin_id2 = interatom.spin_id2
                spin2 = return_spin(spin_id2)

                # Test if the nuclear isotope type has been set.
                if not hasattr(spin2, 'isotope'):
                    raise RelaxSpinTypeError

                # Test if the interatomic distance has been set.
                if not hasattr(interatom, 'r') or interatom.r == None:
                    raise RelaxNoValueError("interatomic distance", spin_id=spin_id, spin_id2=spin_id2)

        # Frequency index.
        if cdp.ct_frq not in list(cdp.spectrometer_frq.values()):
            raise RelaxError("No relaxation data corresponding to the frequency %s has been loaded." % cdp.ct_frq)

        # Consistency testing.
        for spin, id in spin_loop(spin_id, return_id=True):
            # Skip deselected spins.
            if not spin.select:
                continue

            # Set the r1, r2, and NOE to None.
            r1 = None
            r2 = None
            noe = None

            # Get the R1, R2, and NOE values corresponding to the set frequency.
            for ri_id in cdp.ri_ids:
                # The frequency does not match.
                if cdp.spectrometer_frq[ri_id] != cdp.ct_frq:
                    continue

                # R1.
                if cdp.ri_type[ri_id] == 'R1':
                    if sim_index == None:
                        r1 = spin.ri_data[ri_id]
                    else:
                        r1 = spin.ri_data_sim[ri_id][sim_index]

                # R2.
                if cdp.ri_type[ri_id] == 'R2':
                    if sim_index == None:
                        r2 = spin.ri_data[ri_id]
                    else:
                        r2 = spin.ri_data_sim[ri_id][sim_index]

                # NOE.
                if cdp.ri_type[ri_id] == 'NOE':
                    if sim_index == None:
                        noe = spin.ri_data[ri_id]
                    else:
                        noe = spin.ri_data_sim[ri_id][sim_index]

            # Skip the spin if not all of the three value exist.
            if r1 == None or r2 == None or noe == None:
                continue

            # Loop over the interatomic data.
            interatoms = return_interatom_list(id)
            for i in range(len(interatoms)):
                # No relaxation mechanism.
                if not interatoms[i].dipole_pair:
                    continue

                # The surrounding spins.
                if id != interatoms[i].spin_id1:
                    spin_id2 = interatoms[i].spin_id1
                else:
                    spin_id2 = interatoms[i].spin_id2
                spin2 = return_spin(spin_id2)

                # Gyromagnetic ratios.
                gx = periodic_table.gyromagnetic_ratio(spin.isotope)
                gh = periodic_table.gyromagnetic_ratio(spin2.isotope)

                # The interatomic distance.
                r = interatoms[i].r

            # Initialise the function to calculate.
            ct = Consistency(frq=cdp.ct_frq, gx=gx, gh=gh, mu0=mu0, h_bar=h_bar)

            # Calculate the consistency tests values.
            j0, f_eta, f_r2 = ct.func(orientation=spin.orientation, tc=spin.tc, r=r, csa=spin.csa, r1=r1, r2=r2, noe=noe)

            # Consistency tests values.
            if sim_index == None:
                spin.j0 = j0
                spin.f_eta = f_eta
                spin.f_r2 = f_r2

            # Monte Carlo simulated consistency tests values.
            else:
                # Initialise the simulation data structures.
                self.data_init(id, sim=1)
                if spin.j0_sim == None:
                    spin.j0_sim = []
                    spin.f_eta_sim = []
                    spin.f_r2_sim = []

                # Consistency tests values.
                spin.j0_sim.append(j0)
                spin.f_eta_sim.append(f_eta)
                spin.f_r2_sim.append(f_r2)
Exemplo n.º 28
0
def minimise_data_setup(data_store,
                        min_algor,
                        num_data_sets,
                        min_options,
                        spin=None,
                        sim_index=None):
    """Set up all the data required for minimisation.

    @param data_store:      A data storage container.
    @type data_store:       class instance
    @param min_algor:       The minimisation algorithm to use.
    @type min_algor:        str
    @param num_data_sets:   The number of data sets.
    @type num_data_sets:    int
    @param min_options:     The minimisation options array.
    @type min_options:      list
    @keyword spin:          The spin data container.
    @type spin:             SpinContainer instance
    @keyword sim_index:     The optional MC simulation index.
    @type sim_index:        int
    @return:                An insane tuple.  The full tuple is (ri_data, ri_data_err, equations, param_types, param_values, r, csa, num_frq, frq, num_ri, remap_table, noe_r1_table, ri_types, num_params, xh_unit_vectors, diff_type, diff_params)
    @rtype:                 tuple
    """

    # Initialise the data structures for the model-free function.
    data_store.ri_data = []
    data_store.ri_data_err = []
    data_store.equations = []
    data_store.param_types = []
    data_store.param_values = None
    data_store.r = []
    data_store.csa = []
    data_store.num_frq = []
    data_store.frq = []
    data_store.num_ri = []
    data_store.remap_table = []
    data_store.noe_r1_table = []
    data_store.ri_types = []
    data_store.gx = []
    data_store.gh = []
    data_store.num_params = []
    data_store.xh_unit_vectors = []
    if data_store.model_type == 'local_tm':
        data_store.mf_params = []
    elif data_store.model_type == 'diff':
        data_store.param_values = []

    # Set up the data for the back_calc function.
    if min_algor == 'back_calc':
        # The spin data.
        data_store.ri_data = [0.0]
        data_store.ri_data_err = [0.000001]
        data_store.equations = [spin.equation]
        data_store.param_types = [spin.params]
        data_store.csa = [spin.csa]
        data_store.num_frq = [1]
        data_store.frq = [[min_options[3]]]
        data_store.num_ri = [1]
        data_store.remap_table = [[0]]
        data_store.noe_r1_table = [[None]]
        data_store.ri_types = [[min_options[2]]]
        data_store.gx = [periodic_table.gyromagnetic_ratio(spin.isotope)]

        # The interatomic data.
        interatoms = return_interatom_list(spin_hash=spin._hash)
        for i in range(len(interatoms)):
            # No relaxation mechanism.
            if not interatoms[i].dipole_pair:
                continue

            # The surrounding spins.
            if data_store.spin_id != interatoms[i].spin_id1:
                spin_id2 = interatoms[i].spin_id1
            else:
                spin_id2 = interatoms[i].spin_id2
            spin2 = return_spin(spin_id=spin_id2)

            # The data.
            data_store.r = [interatoms[i].r]
            data_store.gh = [periodic_table.gyromagnetic_ratio(spin2.isotope)]
            if data_store.model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere':
                data_store.xh_unit_vectors = [interatoms[i].vector]
            else:
                data_store.xh_unit_vectors = [None]

        # Count the number of model-free parameters for the spin index.
        data_store.num_params = [len(spin.params)]

    # Loop over the number of data sets.
    for j in range(num_data_sets):
        # Set the spin index and get the spin, if not already set.
        if data_store.model_type == 'diff' or data_store.model_type == 'all':
            spin_index = j
            spin, data_store.spin_id = return_spin_from_index(
                global_index=spin_index, return_spin_id=True)

        # Skip deselected spins.
        if not spin.select:
            continue

        # Skip spins where there is no data or errors.
        if not hasattr(spin, 'ri_data') or not hasattr(spin, 'ri_data_err'):
            continue

        # Make sure that the errors are strictly positive numbers.
        for ri_id in cdp.ri_ids:
            # Skip missing data.
            if not ri_id in spin.ri_data_err:
                continue

            # Alias.
            err = spin.ri_data_err[ri_id]

            # Checks.
            if err != None and err == 0.0:
                raise RelaxError(
                    "Zero error for spin '%s' for the relaxation data ID '%s', minimisation not possible."
                    % (data_store.spin_id, ri_id))
            elif err != None and err < 0.0:
                raise RelaxError(
                    "Negative error of %s for spin '%s' for the relaxation data ID '%s', minimisation not possible."
                    % (err, data_store.spin_id, ri_id))

        # The relaxation data optimisation structures.
        data = relax_data_opt_structs(spin, sim_index=sim_index)

        # Append the data.
        data_store.ri_data.append(data[0])
        data_store.ri_data_err.append(data[1])
        data_store.num_frq.append(data[2])
        data_store.num_ri.append(data[3])
        data_store.ri_types.append(data[4])
        data_store.frq.append(data[5])
        data_store.remap_table.append(data[6])
        data_store.noe_r1_table.append(data[7])
        if sim_index == None or data_store.model_type == 'diff':
            data_store.csa.append(spin.csa)
        else:
            data_store.csa.append(spin.csa_sim[sim_index])

        # Repackage the spin data.
        data_store.equations.append(spin.equation)
        data_store.param_types.append(spin.params)
        data_store.gx.append(periodic_table.gyromagnetic_ratio(spin.isotope))

        # Repackage the interatomic data.
        interatoms = return_interatom_list(spin_hash=spin._hash)
        for i in range(len(interatoms)):
            # No relaxation mechanism.
            if not interatoms[i].dipole_pair:
                continue

            # The surrounding spins.
            if data_store.spin_id != interatoms[i].spin_id1:
                spin_id2 = interatoms[i].spin_id1
            else:
                spin_id2 = interatoms[i].spin_id2
            spin2 = return_spin(spin_id=spin_id2)

            # The data.
            data_store.gh.append(
                periodic_table.gyromagnetic_ratio(spin2.isotope))
            if sim_index == None or data_store.model_type == 'diff' or not hasattr(
                    interatoms[i], 'r_sim'):
                data_store.r.append(interatoms[i].r)
            else:
                data_store.r.append(interatoms[i].r_sim[sim_index])

            # Vectors.
            if data_store.model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere':
                # Check that this is a single vector!
                if lib.arg_check.is_num_list(interatoms[i].vector[0],
                                             raise_error=False):
                    raise RelaxMultiVectorError(data_store.spin_id)

                # Store the vector.
                data_store.xh_unit_vectors.append(interatoms[i].vector)

            # No vector.
            else:
                data_store.xh_unit_vectors.append(None)

            # Stop - only one mechanism is current supported.
            break

        # Model-free parameter values.
        if data_store.model_type == 'local_tm':
            pass

        # Count the number of model-free parameters for the spin index.
        data_store.num_params.append(len(spin.params))

        # Repackage the parameter values for minimising just the diffusion tensor parameters.
        if data_store.model_type == 'diff':
            data_store.param_values.append(
                assemble_param_vector(model_type='mf'))

    # Convert to numpy arrays.
    for k in range(len(data_store.ri_data)):
        data_store.ri_data[k] = array(data_store.ri_data[k], float64)
        data_store.ri_data_err[k] = array(data_store.ri_data_err[k], float64)

    # Diffusion tensor type.
    if data_store.model_type == 'local_tm':
        data_store.diff_type = 'sphere'
    else:
        data_store.diff_type = cdp.diff_tensor.type

    # Package the diffusion tensor parameters.
    data_store.diff_params = None
    if data_store.model_type == 'mf':
        # Spherical diffusion.
        if data_store.diff_type == 'sphere':
            data_store.diff_params = [cdp.diff_tensor.tm]

        # Spheroidal diffusion.
        elif data_store.diff_type == 'spheroid':
            data_store.diff_params = [
                cdp.diff_tensor.tm, cdp.diff_tensor.Da, cdp.diff_tensor.theta,
                cdp.diff_tensor.phi
            ]

        # Ellipsoidal diffusion.
        elif data_store.diff_type == 'ellipsoid':
            data_store.diff_params = [
                cdp.diff_tensor.tm, cdp.diff_tensor.Da, cdp.diff_tensor.Dr,
                cdp.diff_tensor.alpha, cdp.diff_tensor.beta,
                cdp.diff_tensor.gamma
            ]
    elif min_algor == 'back_calc' and data_store.model_type == 'local_tm':
        # Spherical diffusion.
        data_store.diff_params = [spin.local_tm]
Exemplo n.º 29
0
def structural_noise(align_id=None, rmsd=0.2, sim_num=1000, file=None, dir=None, force=False):
    """Determine the PCS error due to structural noise via simulation.

    For the simulation the following must already be set up in the current data pipe:

        - The position of the paramagnetic centre.
        - The alignment and magnetic susceptibility tensor.

    The protocol for the simulation is as follows:

        - The lanthanide or paramagnetic centre position will be fixed.  Its motion is assumed to be on the femto- to pico- and nanosecond timescales.  Hence the motion is averaged over the evolution of the PCS and can be ignored.
        - The positions of the nuclear spins will be randomised N times.  For each simulation a random unit vector will be generated.  Then a random distance along the unit vector will be generated by sampling from a Gaussian distribution centered at zero, the original spin position, with a standard deviation set to the given RMSD.  Both positive and negative displacements will be used.
        - The PCS for the randomised position will be back calculated.
        - The PCS standard deviation will be calculated from the N randomised PCS values.

    The standard deviation will both be stored in the spin container data structure in the relax data store as well as being added to the already present PCS error (using variance addition).  This will then be used in any optimisations involving the PCS.

    If the alignment ID string is not supplied, the procedure will be applied to the PCS data from all alignments.


    @keyword align_id:  The alignment tensor ID string.
    @type align_id:     str
    @keyword rmsd:      The atomic position RMSD, in Angstrom, to randomise the spin positions with for the simulations.
    @type rmsd:         float
    @keyword sim_num:   The number of simulations, N, to perform to determine the structural noise component of the PCS errors.
    @type sim_num:      int
    @keyword file:      The optional name of the Grace file to plot the structural errors verses the paramagnetic centre to spin distances.
    @type file:         None or str
    @keyword dir:       The directory name to place the Grace file into.
    @type dir:          None or str
    @keyword force:     A flag which if True will cause any pre-existing file to be overwritten.
    @type force:        bool
    """

    # Check the pipe setup.
    check_pipe_setup(sequence=True, pcs_id=align_id, pcs=True, paramag_centre=True)

    # Convert the align IDs to an array, or take all IDs.
    if align_id:
        align_ids = [align_id]
    else:
        align_ids = cdp.align_ids

    # Initialise some numpy data structures for use in the simulations.
    grace_data = []
    unit_vect = zeros(3, float64)
    pcs = {}
    for id in align_ids:
        grace_data.append([])
        pcs[id] = zeros(sim_num, float64)

    # Print out.
    print("Executing %i simulations for each spin system." % sim_num)

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

        # Skip spins with no PCS or position.
        if not hasattr(spin, 'pcs'):
            continue
        if not hasattr(spin, 'pos'):
            continue

        # Print out.
        print(spin_id)

        # Average the atom position.
        if type(spin.pos[0]) in [float, float64]:
            pos = spin.pos
        else:
            pos = zeros(3, float64)
            for i in range(len(spin.pos)):
                pos += spin.pos[i]
            pos = pos / len(spin.pos)

        # The original vector length (for the Grace plot).
        orig_vect = pos - cdp.paramagnetic_centre
        orig_r = norm(orig_vect)

        # Loop over the N randomisations.
        for i in range(sim_num):
            # The random unit vector.
            random_unit_vector(unit_vect)

            # The random displacement (in Angstrom).
            disp = gauss(0, rmsd)

            # Move the atom.
            new_pos = pos + disp*unit_vect

            # The vector and length.
            vect = new_pos - cdp.paramagnetic_centre
            r = norm(vect)
            vect = vect / r

            # Loop over the alignments.
            for id in align_ids:
                # No PCS value, so skip.
                if id not in spin.pcs:
                    continue

                # Calculate the PCS constant.
                dj = pcs_constant(cdp.temperature[id], cdp.spectrometer_frq[id] * 2.0 * pi / periodic_table.gyromagnetic_ratio('1H'), r/1e10)

                # Calculate the PCS value (in ppm).
                pcs[id][i] = pcs_tensor(dj, vect, cdp.align_tensors[get_tensor_index(id)].A) * 1e6

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

        # Loop over the alignments.
        align_index = 0
        for id in align_ids:
            # No PCS value, so skip.
            if id not in spin.pcs or spin.pcs[id] == None:
                align_index += 1
                continue

            # The PCS standard deviation.
            sd = std(pcs[id])

            # Remove the previous error.
            if id in spin.pcs_struct_err:
                warn(RelaxWarning("Removing the previous structural error value from the PCS error of the spin '%s' for the alignment ID '%s'." % (spin_id, id)))
                spin.pcs_err[id] = sqrt(spin.pcs_err[id]**2 - spin.pcs_struct_err[id]**2)

            # Store the structural error.
            spin.pcs_struct_err[id] = sd

            # Add it to the PCS error (with variance addition).
            spin.pcs_err[id] = sqrt(spin.pcs_err[id]**2 + sd**2)

            # Store the data for the Grace plot.
            grace_data[align_index].append([orig_r, sd, spin_id])

            # Increment the alignment index.
            align_index += 1

    # The Grace output.
    if file:
        # Open the Grace file for writing.
        file = open_write_file(file, dir, force)

        # The header.
        write_xy_header(format='grace', file=file, title="PCS structural noise", subtitle="%s Angstrom structural noise"%rmsd, data_type=['pcs_bc', 'pcs'], sets=[len(align_ids)], set_names=[align_ids], symbol_sizes=[[0.5]*len(align_ids)], linetype=[[0]*len(align_ids)], axis_labels=[["Ln\\S3+\\N to spin distance (Angstrom)", "PCS standard deviation (ppm)"]])

        # The main data.
        write_xy_data(format='grace', data=[grace_data], file=file, graph_type='xy')
Exemplo n.º 30
0
                 spin_id1='@N',
                 spin_id2='@H',
                 direct_bond=True)
self._execute_uf(uf_name='interatom.set_dist',
                 spin_id1='@N',
                 spin_id2='@H',
                 ave_dist=NH_BOND_LENGTH_RDC)
self._execute_uf(uf_name='interatom.unit_vectors', ave=True)

# Set the nuclear isotope.
self._execute_uf(uf_name='spin.isotope', isotope='15N', spin_id='@N')
self._execute_uf(uf_name='spin.isotope', isotope='1H', spin_id='@H')

# The dipolar constant.
const = 3.0 / (2.0 * pi) * dipolar_constant(
    periodic_table.gyromagnetic_ratio('15N'),
    periodic_table.gyromagnetic_ratio('1H'), NH_BOND_LENGTH_RDC)

# The tensor.
tensor = 'A'
self._execute_uf(uf_name='align_tensor.init',
                 tensor=tensor,
                 params=(4.724 / const, 11.856 / const, 0, 0, 0),
                 align_id=tensor,
                 param_types=2)

# The temperature.
self._execute_uf(uf_name='spectrometer.temperature', id=tensor, temp=298)

# The frequency.
self._execute_uf(uf_name='spectrometer.frequency', id=tensor, frq=900.0 * 1e6)