class PipeContainer(Prototype):
    """Class containing all the program data."""

    def __init__(self):
        """Set up all the PipeContainer data structures."""

        # The molecule-residue-spin object.
        self.mol = MoleculeList()

        # The interatomic data object.
        self.interatomic = InteratomList()

        # The data pipe type.
        self.pipe_type = None

        # Hybrid models.
        self.hybrid_pipes = []


    def __repr__(self):
        """The string representation of the object.

        Rather than using the standard Python conventions (either the string representation of the
        value or the "<...desc...>" notation), a rich-formatted description of the object is given.
        """

        # Intro text.
        text = "The data pipe storage object.\n"

        # Special objects/methods (to avoid the getattr() function call on).
        spec_obj = ['exp_info', 'mol', 'interatomic', 'diff_tensor', 'structure']

        # Objects.
        text = text + "\n"
        text = text + "Objects:\n"
        for name in dir(self):
            # Molecular list.
            if name == 'mol':
                text = text + "  mol: The molecule list (for the storage of the spin system specific data)\n"

            # Interatomic data list.
            if name == 'interatomic':
                text = text + "  interatomic: The interatomic data list (for the storage of the inter-spin system data)\n"

            # Diffusion tensor.
            if name == 'diff_tensor':
                text = text + "  diff_tensor: The Brownian rotational diffusion tensor data object\n"

            # Molecular structure.
            if name == 'structure':
                text = text + "  structure: The 3D molecular data object\n"

            # The experimental info data container.
            if name == 'exp_info':
                text = text + "  exp_info: The data container for experimental information\n"

            # Skip the PipeContainer methods.
            if name in list(self.__class__.__dict__.keys()):
                continue

            # Skip certain objects.
            if match("^_", name) or name in spec_obj:
                continue

            # Add the object's attribute to the text string.
            text = text + "  " + name + ": " + repr(getattr(self, name)) + "\n"

        # Return the text representation.
        return text


    def _back_compat_hook(self, file_version=None):
        """Method for converting old data structures to the new ones.

        @keyword file_version:  The relax XML version of the XML file.
        @type file_version:     int
        """

        # Relaxation data.
        self._back_compat_hook_ri_data()


    def _back_compat_hook_ri_data(self):
        """Converting the old relaxation data structures to the new ones."""

        # Nothing to do.
        if not (hasattr(cdp, 'frq_labels') and hasattr(cdp, 'noe_r1_table') and hasattr(cdp, 'remap_table')):
            return

        # Initialise the new structures.
        cdp.ri_ids = []
        cdp.ri_type = {}
        frq = {}    # This will be placed into cdp later as cdp.spectrometer_frq still exists.

        # Generate the new structures.
        for i in range(cdp.num_ri):
            # The ID.
            ri_id = "%s_%s" % (cdp.ri_labels[i], cdp.frq_labels[cdp.remap_table[i]])

            # Not unique.
            if ri_id in cdp.ri_ids:
                # Loop until a unique ID is found.
                for j in range(100):
                    # New id.
                    new_id = "%s_%s" % (ri_id, j)

                    # Unique.
                    if not new_id in cdp.ri_ids:
                        ri_id = new_id
                        break

            # Add the ID.
            cdp.ri_ids.append(ri_id)

            # The relaxation data type.
            cdp.ri_type[ri_id] = cdp.ri_labels[i]

            # The frequency data.
            frq[ri_id] = cdp.frq[cdp.remap_table[i]]

        # Delete the old structures.
        del cdp.frq
        del cdp.frq_labels
        del cdp.noe_r1_table
        del cdp.num_frq
        del cdp.num_ri
        del cdp.remap_table
        del cdp.ri_labels

        # Set the frequencies.
        cdp.frq = frq


    def from_xml(self, pipe_node, file_version=None, dir=None):
        """Read a pipe container XML element and place the contents into this pipe.

        @param pipe_node:       The data pipe XML node.
        @type pipe_node:        xml.dom.minidom.Element instance
        @keyword file_version:  The relax XML version of the XML file.
        @type file_version:     int
        @keyword dir:           The name of the directory containing the results file (needed for loading external files).
        @type dir:              str
        """

        # Test if empty.
        if not self.is_empty():
            raise RelaxFromXMLNotEmptyError(self.__class__.__name__)

        # Get the global data node, and fill the contents of the pipe.
        global_node = pipe_node.getElementsByTagName('global')[0]
        xml_to_object(global_node, self, file_version=file_version)

        # Backwards compatibility transformations.
        self._back_compat_hook(file_version)

        # Get the hybrid node (and its sub-node), and recreate the hybrid object.
        hybrid_node = pipe_node.getElementsByTagName('hybrid')[0]
        pipes_node = hybrid_node.getElementsByTagName('pipes')[0]
        setattr(self, 'hybrid_pipes', node_value_to_python(pipes_node.childNodes[0]))

        # Get the experimental information data nodes and, if they exist, fill the contents.
        exp_info_nodes = pipe_node.getElementsByTagName('exp_info')
        if exp_info_nodes:
            # Create the data container.
            self.exp_info = ExpInfo()

            # Fill its contents.
            self.exp_info.from_xml(exp_info_nodes[0], file_version=file_version)

        # Get the diffusion tensor data nodes and, if they exist, fill the contents.
        diff_tensor_nodes = pipe_node.getElementsByTagName('diff_tensor')
        if diff_tensor_nodes:
            # Create the diffusion tensor object.
            self.diff_tensor = DiffTensorData()

            # Fill its contents.
            self.diff_tensor.from_xml(diff_tensor_nodes[0], file_version=file_version)

        # Get the alignment tensor data nodes and, if they exist, fill the contents.
        align_tensor_nodes = pipe_node.getElementsByTagName('align_tensors')
        if align_tensor_nodes:
            # Create the alignment tensor object.
            self.align_tensors = AlignTensorList()

            # Fill its contents.
            self.align_tensors.from_xml(align_tensor_nodes[0], file_version=file_version)

        # Recreate the interatomic data structure (this needs to be before the 'mol' structure as the backward compatibility hooks can create interatomic data containers!).
        interatom_nodes = pipe_node.getElementsByTagName('interatomic')
        self.interatomic.from_xml(interatom_nodes, file_version=file_version)

        # Recreate the molecule, residue, and spin data structure.
        mol_nodes = pipe_node.getElementsByTagName('mol')
        self.mol.from_xml(mol_nodes, file_version=file_version)

        # Get the structural object nodes and, if they exist, fill the contents.
        str_nodes = pipe_node.getElementsByTagName('structure')
        if str_nodes:
            # Create the structural object.
            fail = False
            self.structure = Internal()

            # Fill its contents.
            if not fail:
                self.structure.from_xml(str_nodes[0], dir=dir, file_version=file_version)


    def is_empty(self):
        """Method for testing if the data pipe is empty.

        @return:    True if the data pipe is empty, False otherwise.
        @rtype:     bool
        """

        # Is the molecule structure data object empty?
        if hasattr(self, 'structure'):
            return False

        # Is the molecule/residue/spin data object empty?
        if not self.mol.is_empty():
            return False

        # Is the interatomic data object empty?
        if not self.interatomic.is_empty():
            return False

        # Tests for the initialised data (the pipe type can be set in an empty data pipe, so this isn't checked).
        if self.hybrid_pipes:
            return False

        # An object has been added to the container.
        for name in dir(self):
            # Skip the objects initialised in __init__().
            if name in ['mol', 'interatomic', 'pipe_type', 'hybrid_pipes']:
                continue

            # Skip the PipeContainer methods.
            if name in list(self.__class__.__dict__.keys()):
                continue

            # Skip special objects.
            if match("^_", name):
                continue

            # An object has been added.
            return False

        # The data pipe is empty.
        return True


    def to_xml(self, doc, element):
        """Create a XML element for the current data pipe.

        @param doc:     The XML document object.
        @type doc:      xml.dom.minidom.Document instance
        @param element: The XML element to add the pipe XML element to.
        @type element:  XML element object
        """

        # Add all simple python objects within the PipeContainer to the global element.
        global_element = doc.createElement('global')
        element.appendChild(global_element)
        global_element.setAttribute('desc', 'Global data located in the top level of the data pipe')
        fill_object_contents(doc, global_element, object=self, blacklist=['align_tensors', 'diff_tensor', 'exp_info', 'interatomic', 'hybrid_pipes', 'mol', 'pipe_type', 'structure'] + list(self.__class__.__dict__.keys()))

        # Hybrid info.
        self.xml_create_hybrid_element(doc, element)

        # Add the experimental information.
        if hasattr(self, 'exp_info'):
            self.exp_info.to_xml(doc, element)

        # Add the diffusion tensor data.
        if hasattr(self, 'diff_tensor'):
            self.diff_tensor.to_xml(doc, element)

        # Add the alignment tensor data.
        if hasattr(self, 'align_tensors'):
            self.align_tensors.to_xml(doc, element)

        # Add the molecule-residue-spin data.
        self.mol.to_xml(doc, element)

        # Add the interatomic data.
        self.interatomic.to_xml(doc, element)

        # Add the structural data, if it exists.
        if hasattr(self, 'structure'):
            self.structure.to_xml(doc, element)


    def xml_create_hybrid_element(self, doc, element):
        """Create an XML element for the data pipe hybridisation information.

        @param doc:     The XML document object.
        @type doc:      xml.dom.minidom.Document instance
        @param element: The element to add the hybridisation info to.
        @type element:  XML element object
        """

        # Create the hybrid element and add it to the higher level element.
        hybrid_element = doc.createElement('hybrid')
        element.appendChild(hybrid_element)

        # Set the hybridisation attributes.
        hybrid_element.setAttribute('desc', 'Data pipe hybridisation information')

        # Create an element to store the pipes list.
        list_element = doc.createElement('pipes')
        hybrid_element.appendChild(list_element)

        # Add the pipes list.
        text_val = doc.createTextNode(str(self.hybrid_pipes))
        list_element.appendChild(text_val)
Beispiel #2
0
class PipeContainer(Prototype):
    """Class containing all the program data."""
    def __init__(self):
        """Set up all the PipeContainer data structures."""

        # The molecule-residue-spin object.
        self.mol = MoleculeList()

        # The interatomic data object.
        self.interatomic = InteratomList()

        # The data pipe type.
        self.pipe_type = None

        # Hybrid models.
        self.hybrid_pipes = []

    def __repr__(self):
        """The string representation of the object.

        Rather than using the standard Python conventions (either the string representation of the
        value or the "<...desc...>" notation), a rich-formatted description of the object is given.
        """

        # Intro text.
        text = "The data pipe storage object.\n"

        # Special objects/methods (to avoid the getattr() function call on).
        spec_obj = [
            'exp_info', 'mol', 'interatomic', 'diff_tensor', 'structure'
        ]

        # Objects.
        text = text + "\n"
        text = text + "Objects:\n"
        for name in dir(self):
            # Molecular list.
            if name == 'mol':
                text = text + "  mol: The molecule list (for the storage of the spin system specific data)\n"

            # Interatomic data list.
            if name == 'interatomic':
                text = text + "  interatomic: The interatomic data list (for the storage of the inter-spin system data)\n"

            # Diffusion tensor.
            if name == 'diff_tensor':
                text = text + "  diff_tensor: The Brownian rotational diffusion tensor data object\n"

            # Molecular structure.
            if name == 'structure':
                text = text + "  structure: The 3D molecular data object\n"

            # The experimental info data container.
            if name == 'exp_info':
                text = text + "  exp_info: The data container for experimental information\n"

            # Skip the PipeContainer methods.
            if name in self.__class__.__dict__:
                continue

            # Skip certain objects.
            if match("^_", name) or name in spec_obj:
                continue

            # Add the object's attribute to the text string.
            text = text + "  " + name + ": " + repr(getattr(self, name)) + "\n"

        # Return the text representation.
        return text

    def _back_compat_hook(self, file_version=None):
        """Method for converting old data structures to the new ones.

        @keyword file_version:  The relax XML version of the XML file.
        @type file_version:     int
        """

        # Relaxation data.
        self._back_compat_hook_ri_data()

    def _back_compat_hook_ri_data(self):
        """Converting the old relaxation data structures to the new ones."""

        # Nothing to do.
        if not (hasattr(cdp, 'frq_labels') and hasattr(cdp, 'noe_r1_table')
                and hasattr(cdp, 'remap_table')):
            return

        # Initialise the new structures.
        cdp.ri_ids = []
        cdp.ri_type = {}
        frq = {
        }  # This will be placed into cdp later as cdp.spectrometer_frq still exists.

        # Generate the new structures.
        for i in range(cdp.num_ri):
            # The ID.
            ri_id = "%s_%s" % (cdp.ri_labels[i],
                               cdp.frq_labels[cdp.remap_table[i]])

            # Not unique.
            if ri_id in cdp.ri_ids:
                # Loop until a unique ID is found.
                for j in range(100):
                    # New id.
                    new_id = "%s_%s" % (ri_id, j)

                    # Unique.
                    if not new_id in cdp.ri_ids:
                        ri_id = new_id
                        break

            # Add the ID.
            cdp.ri_ids.append(ri_id)

            # The relaxation data type.
            cdp.ri_type[ri_id] = cdp.ri_labels[i]

            # The frequency data.
            frq[ri_id] = cdp.frq[cdp.remap_table[i]]

        # Delete the old structures.
        del cdp.frq
        del cdp.frq_labels
        del cdp.noe_r1_table
        del cdp.num_frq
        del cdp.num_ri
        del cdp.remap_table
        del cdp.ri_labels

        # Set the frequencies.
        cdp.frq = frq

    def from_xml(self, pipe_node, file_version=None, dir=None):
        """Read a pipe container XML element and place the contents into this pipe.

        @param pipe_node:       The data pipe XML node.
        @type pipe_node:        xml.dom.minidom.Element instance
        @keyword file_version:  The relax XML version of the XML file.
        @type file_version:     int
        @keyword dir:           The name of the directory containing the results file (needed for loading external files).
        @type dir:              str
        """

        # Test if empty.
        if not self.is_empty():
            raise RelaxFromXMLNotEmptyError(self.__class__.__name__)

        # Get the global data node, and fill the contents of the pipe.
        global_node = pipe_node.getElementsByTagName('global')[0]
        xml_to_object(global_node, self, file_version=file_version)

        # Backwards compatibility transformations.
        self._back_compat_hook(file_version)

        # Get the hybrid node (and its sub-node), and recreate the hybrid object.
        hybrid_node = pipe_node.getElementsByTagName('hybrid')[0]
        pipes_node = hybrid_node.getElementsByTagName('pipes')[0]
        setattr(self, 'hybrid_pipes',
                node_value_to_python(pipes_node.childNodes[0]))

        # Get the experimental information data nodes and, if they exist, fill the contents.
        exp_info_nodes = pipe_node.getElementsByTagName('exp_info')
        if exp_info_nodes:
            # Create the data container.
            self.exp_info = ExpInfo()

            # Fill its contents.
            self.exp_info.from_xml(exp_info_nodes[0],
                                   file_version=file_version)

        # Get the diffusion tensor data nodes and, if they exist, fill the contents.
        diff_tensor_nodes = pipe_node.getElementsByTagName('diff_tensor')
        if diff_tensor_nodes:
            # Create the diffusion tensor object.
            self.diff_tensor = DiffTensorData()

            # Fill its contents.
            self.diff_tensor.from_xml(diff_tensor_nodes[0],
                                      file_version=file_version)

        # Get the alignment tensor data nodes and, if they exist, fill the contents.
        align_tensor_nodes = pipe_node.getElementsByTagName('align_tensors')
        if align_tensor_nodes:
            # Create the alignment tensor object.
            self.align_tensors = AlignTensorList()

            # Fill its contents.
            self.align_tensors.from_xml(align_tensor_nodes[0],
                                        file_version=file_version)

        # Recreate the interatomic data structure (this needs to be before the 'mol' structure as the backward compatibility hooks can create interatomic data containers!).
        interatom_nodes = pipe_node.getElementsByTagName('interatomic')
        self.interatomic.from_xml(interatom_nodes, file_version=file_version)

        # Recreate the molecule, residue, and spin data structure.
        mol_nodes = pipe_node.getElementsByTagName('mol')
        self.mol.from_xml(mol_nodes, file_version=file_version)

        # Get the structural object nodes and, if they exist, fill the contents.
        str_nodes = pipe_node.getElementsByTagName('structure')
        if str_nodes:
            # Create the structural object.
            fail = False
            self.structure = Internal()

            # Fill its contents.
            if not fail:
                self.structure.from_xml(str_nodes[0],
                                        dir=dir,
                                        file_version=file_version)

    def is_empty(self):
        """Method for testing if the data pipe is empty.

        @return:    True if the data pipe is empty, False otherwise.
        @rtype:     bool
        """

        # Is the molecule structure data object empty?
        if hasattr(self, 'structure'):
            return False

        # Is the molecule/residue/spin data object empty?
        if not self.mol.is_empty():
            return False

        # Is the interatomic data object empty?
        if not self.interatomic.is_empty():
            return False

        # Tests for the initialised data (the pipe type can be set in an empty data pipe, so this isn't checked).
        if self.hybrid_pipes:
            return False

        # An object has been added to the container.
        for name in dir(self):
            # Skip the objects initialised in __init__().
            if name in ['mol', 'interatomic', 'pipe_type', 'hybrid_pipes']:
                continue

            # Skip the PipeContainer methods.
            if name in self.__class__.__dict__:
                continue

            # Skip special objects.
            if match("^_", name):
                continue

            # An object has been added.
            return False

        # The data pipe is empty.
        return True

    def to_xml(self, doc, element, pipe_type=None):
        """Create a XML element for the current data pipe.

        @param doc:         The XML document object.
        @type doc:          xml.dom.minidom.Document instance
        @param element:     The XML element to add the pipe XML element to.
        @type element:      XML element object
        @keyword pipe_type: The type of the pipe being converted to XML.
        @type pipe_type:    str
        """

        # Add all simple python objects within the PipeContainer to the global element.
        global_element = doc.createElement('global')
        element.appendChild(global_element)
        global_element.setAttribute(
            'desc', 'Global data located in the top level of the data pipe')
        fill_object_contents(
            doc,
            global_element,
            object=self,
            blacklist=[
                'align_tensors', 'diff_tensor', 'exp_info', 'interatomic',
                'hybrid_pipes', 'mol', 'pipe_type', 'structure'
            ] + list(self.__class__.__dict__.keys()))

        # Hybrid info.
        self.xml_create_hybrid_element(doc, element)

        # Add the experimental information.
        if hasattr(self, 'exp_info'):
            self.exp_info.to_xml(doc, element)

        # Add the diffusion tensor data.
        if hasattr(self, 'diff_tensor'):
            self.diff_tensor.to_xml(doc, element)

        # Add the alignment tensor data.
        if hasattr(self, 'align_tensors'):
            self.align_tensors.to_xml(doc, element)

        # Add the molecule-residue-spin data.
        self.mol.to_xml(doc, element, pipe_type=pipe_type)

        # Add the interatomic data.
        self.interatomic.to_xml(doc, element, pipe_type=pipe_type)

        # Add the structural data, if it exists.
        if hasattr(self, 'structure'):
            self.structure.to_xml(doc, element)

    def xml_create_hybrid_element(self, doc, element):
        """Create an XML element for the data pipe hybridisation information.

        @param doc:     The XML document object.
        @type doc:      xml.dom.minidom.Document instance
        @param element: The element to add the hybridisation info to.
        @type element:  XML element object
        """

        # Create the hybrid element and add it to the higher level element.
        hybrid_element = doc.createElement('hybrid')
        element.appendChild(hybrid_element)

        # Set the hybridisation attributes.
        hybrid_element.setAttribute('desc',
                                    'Data pipe hybridisation information')

        # Create an element to store the pipes list.
        list_element = doc.createElement('pipes')
        hybrid_element.appendChild(list_element)

        # Add the pipes list.
        text_val = doc.createTextNode(str(self.hybrid_pipes))
        list_element.appendChild(text_val)
    def from_xml(self, pipe_node, file_version=None, dir=None):
        """Read a pipe container XML element and place the contents into this pipe.

        @param pipe_node:       The data pipe XML node.
        @type pipe_node:        xml.dom.minidom.Element instance
        @keyword file_version:  The relax XML version of the XML file.
        @type file_version:     int
        @keyword dir:           The name of the directory containing the results file (needed for loading external files).
        @type dir:              str
        """

        # Test if empty.
        if not self.is_empty():
            raise RelaxFromXMLNotEmptyError(self.__class__.__name__)

        # Get the global data node, and fill the contents of the pipe.
        global_node = pipe_node.getElementsByTagName('global')[0]
        xml_to_object(global_node, self, file_version=file_version)

        # Backwards compatibility transformations.
        self._back_compat_hook(file_version)

        # Get the hybrid node (and its sub-node), and recreate the hybrid object.
        hybrid_node = pipe_node.getElementsByTagName('hybrid')[0]
        pipes_node = hybrid_node.getElementsByTagName('pipes')[0]
        setattr(self, 'hybrid_pipes', node_value_to_python(pipes_node.childNodes[0]))

        # Get the experimental information data nodes and, if they exist, fill the contents.
        exp_info_nodes = pipe_node.getElementsByTagName('exp_info')
        if exp_info_nodes:
            # Create the data container.
            self.exp_info = ExpInfo()

            # Fill its contents.
            self.exp_info.from_xml(exp_info_nodes[0], file_version=file_version)

        # Get the diffusion tensor data nodes and, if they exist, fill the contents.
        diff_tensor_nodes = pipe_node.getElementsByTagName('diff_tensor')
        if diff_tensor_nodes:
            # Create the diffusion tensor object.
            self.diff_tensor = DiffTensorData()

            # Fill its contents.
            self.diff_tensor.from_xml(diff_tensor_nodes[0], file_version=file_version)

        # Get the alignment tensor data nodes and, if they exist, fill the contents.
        align_tensor_nodes = pipe_node.getElementsByTagName('align_tensors')
        if align_tensor_nodes:
            # Create the alignment tensor object.
            self.align_tensors = AlignTensorList()

            # Fill its contents.
            self.align_tensors.from_xml(align_tensor_nodes[0], file_version=file_version)

        # Recreate the interatomic data structure (this needs to be before the 'mol' structure as the backward compatibility hooks can create interatomic data containers!).
        interatom_nodes = pipe_node.getElementsByTagName('interatomic')
        self.interatomic.from_xml(interatom_nodes, file_version=file_version)

        # Recreate the molecule, residue, and spin data structure.
        mol_nodes = pipe_node.getElementsByTagName('mol')
        self.mol.from_xml(mol_nodes, file_version=file_version)

        # Get the structural object nodes and, if they exist, fill the contents.
        str_nodes = pipe_node.getElementsByTagName('structure')
        if str_nodes:
            # Create the structural object.
            fail = False
            self.structure = Internal()

            # Fill its contents.
            if not fail:
                self.structure.from_xml(str_nodes[0], dir=dir, file_version=file_version)
Beispiel #4
0
    def from_xml(self, pipe_node, file_version=None, dir=None):
        """Read a pipe container XML element and place the contents into this pipe.

        @param pipe_node:       The data pipe XML node.
        @type pipe_node:        xml.dom.minidom.Element instance
        @keyword file_version:  The relax XML version of the XML file.
        @type file_version:     int
        @keyword dir:           The name of the directory containing the results file (needed for loading external files).
        @type dir:              str
        """

        # Test if empty.
        if not self.is_empty():
            raise RelaxFromXMLNotEmptyError(self.__class__.__name__)

        # Get the global data node, and fill the contents of the pipe.
        global_node = pipe_node.getElementsByTagName('global')[0]
        xml_to_object(global_node, self, file_version=file_version)

        # Backwards compatibility transformations.
        self._back_compat_hook(file_version)

        # Get the hybrid node (and its sub-node), and recreate the hybrid object.
        hybrid_node = pipe_node.getElementsByTagName('hybrid')[0]
        pipes_node = hybrid_node.getElementsByTagName('pipes')[0]
        setattr(self, 'hybrid_pipes',
                node_value_to_python(pipes_node.childNodes[0]))

        # Get the experimental information data nodes and, if they exist, fill the contents.
        exp_info_nodes = pipe_node.getElementsByTagName('exp_info')
        if exp_info_nodes:
            # Create the data container.
            self.exp_info = ExpInfo()

            # Fill its contents.
            self.exp_info.from_xml(exp_info_nodes[0],
                                   file_version=file_version)

        # Get the diffusion tensor data nodes and, if they exist, fill the contents.
        diff_tensor_nodes = pipe_node.getElementsByTagName('diff_tensor')
        if diff_tensor_nodes:
            # Create the diffusion tensor object.
            self.diff_tensor = DiffTensorData()

            # Fill its contents.
            self.diff_tensor.from_xml(diff_tensor_nodes[0],
                                      file_version=file_version)

        # Get the alignment tensor data nodes and, if they exist, fill the contents.
        align_tensor_nodes = pipe_node.getElementsByTagName('align_tensors')
        if align_tensor_nodes:
            # Create the alignment tensor object.
            self.align_tensors = AlignTensorList()

            # Fill its contents.
            self.align_tensors.from_xml(align_tensor_nodes[0],
                                        file_version=file_version)

        # Recreate the interatomic data structure (this needs to be before the 'mol' structure as the backward compatibility hooks can create interatomic data containers!).
        interatom_nodes = pipe_node.getElementsByTagName('interatomic')
        self.interatomic.from_xml(interatom_nodes, file_version=file_version)

        # Recreate the molecule, residue, and spin data structure.
        mol_nodes = pipe_node.getElementsByTagName('mol')
        self.mol.from_xml(mol_nodes, file_version=file_version)

        # Get the structural object nodes and, if they exist, fill the contents.
        str_nodes = pipe_node.getElementsByTagName('structure')
        if str_nodes:
            # Create the structural object.
            fail = False
            self.structure = Internal()

            # Fill its contents.
            if not fail:
                self.structure.from_xml(str_nodes[0],
                                        dir=dir,
                                        file_version=file_version)
    def setUp(self):
        """Set 'self.diff_data' to an empty instance of the DiffTensorData class."""

        self.diff_data = DiffTensorData()
class Test_diff_tensor(TestCase):
    """Unit tests for the data.diff_tensor relax module."""

    def calc_spheroid_objects(self, tm, Da, theta, phi):
        """Function for calculating the spheroidal diffusion tensor objects."""

        # The parameter values.
        Diso = 1/(6*tm)
        Dpar = Diso + 2.0/3.0 * Da
        Dper = Diso - 1.0/3.0 * Da
        Dratio = Dpar / Dper

        # Vectors.
        Dpar_unit = array([sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)])

        # Matrices.
        if Dpar > Dper:
            axis = array([0, 0, 1], float64)
            tensor_diag = array([[ Dper,  0.0,  0.0],
                                 [  0.0, Dper,  0.0],
                                 [  0.0,  0.0, Dpar]])
        else:
            axis = array([1, 0, 0], float64)
            tensor_diag = array([[ Dpar,  0.0,  0.0],
                                 [  0.0, Dper,  0.0],
                                 [  0.0,  0.0, Dper]])

        # The rotation.
        rotation = zeros((3, 3), float64)
        two_vect_to_R(Dpar_unit, axis, rotation)

        # The diffusion tensor.
        tensor = dot(rotation, dot(tensor_diag, transpose(rotation)))

        # Return the objects.
        return Diso, Dpar, Dper, Dratio, Dpar_unit, tensor_diag, rotation, tensor


    def setUp(self):
        """Set 'self.diff_data' to an empty instance of the DiffTensorData class."""

        self.diff_data = DiffTensorData()


    def test_append_spheroid_sim(self):
        """Test the appending of Monte Carlo simulation spheroidal diffusion tensor parameters.

        The following parameters will be appended to empty lists:
            - tm: 8 ns
            - Da: -1e7
            - theta: 150 degrees
            - phi: 30 degrees
        """

        # The MC sim parameter values.
        tm = 8e-9
        Da = -1e7
        theta = (150 / 360.0) * 2.0 * pi
        phi = (30 / 360.0) * 2.0 * pi

        # Set the diffusion type.
        self.diff_data.set(param='type', value='spheroid')
        self.diff_data.set(param='spheroid_type', value='oblate')

        # Set the number of MC sims.
        self.diff_data.set_sim_num(1)

        # Set the initial values.
        self.diff_data.set(param='tm', value=tm, category='sim', sim_index=0)
        self.diff_data.set(param='Da', value=Da, category='sim', sim_index=0)
        self.diff_data.set(param='theta', value=theta, category='sim', sim_index=0)
        self.diff_data.set(param='phi', value=phi, category='sim', sim_index=0)

        # Test the set values.
        self.assertEqual(self.diff_data.type, 'spheroid')
        self.assertEqual(self.diff_data.tm_sim[0], tm)
        self.assertEqual(self.diff_data.Da_sim[0], Da)
        self.assertEqual(self.diff_data.theta_sim[0], theta)
        self.assertEqual(self.diff_data.phi_sim[0], phi)

        # Calculate the diffusion tensor objects.
        Diso, Dpar, Dper, Dratio, Dpar_unit, tensor_diag, rotation, tensor = self.calc_spheroid_objects(tm, Da, theta, phi)

        # Test the automatically created values.
        self.assertEqual(self.diff_data.Diso_sim[0], Diso)
        self.assertEqual(self.diff_data.Dpar_sim[0], Dpar)
        self.assertEqual(self.diff_data.Dper_sim[0], Dper)
        self.assertEqual(self.diff_data.Dratio_sim[0], Dratio)

        # Test the vectors.
        self.assertEqual(self.diff_data.Dpar_unit_sim[0].tostring(), Dpar_unit.tostring())

        # Test the matrices.
        self.assertEqual(self.diff_data.tensor_diag_sim[0].tostring(), tensor_diag.tostring())
        self.assertEqual(self.diff_data.rotation_sim[0].tostring(), rotation.tostring())
        self.assertEqual(self.diff_data.tensor_sim[0].tostring(), tensor.tostring())


    def test_display(self):
        """Test that the contents of the diffusion tensor object can be displayed."""

        print(self.diff_data)


    def test_set_Diso(self):
        """Test that the Diso parameter cannot be set."""

        # Assert that a RelaxError occurs when Diso is set (to the tm value of 10 ns).
        self.assertRaises(RelaxError, setattr, self.diff_data, 'Diso', 1/(6*1e-8))

        # Make sure that the Diso parameter has not been set.
        self.assert_(not hasattr(self.diff_data, 'Diso'))


    def test_set_spheroid_errors(self):
        """Test the setting of spheroidal diffusion tensor parameter errors.

        The following parameter errors will be set:
            - tm: 1 ns
            - Da: 1e3
            - theta: 3 degrees
            - phi: 5 degrees
        """

        # The parameter errors.
        tm = 1e-8
        Da = 1e3
        theta = (3 / 360.0) * 2.0 * pi
        phi = (5 / 360.0) * 2.0 * pi

        # Set the diffusion type.
        self.diff_data.set(param='type', value='spheroid')
        self.diff_data.set(param='spheroid_type', value='prolate')

        # Set the diffusion parameter errors.
        self.diff_data.set(param='tm', value=tm, category='err')
        self.diff_data.set(param='Da', value=Da, category='err')
        self.diff_data.set(param='theta', value=theta, category='err')
        self.diff_data.set(param='phi', value=phi, category='err')

        # Test the set values.
        self.assertEqual(self.diff_data.type, 'spheroid')
        self.assertEqual(self.diff_data.tm_err, tm)
        self.assertEqual(self.diff_data.Da_err, Da)
        self.assertEqual(self.diff_data.theta_err, theta)
        self.assertEqual(self.diff_data.phi_err, phi)

        # Calculate the diffusion tensor objects.
        Diso, Dpar, Dper, Dratio, Dpar_unit, tensor_diag, rotation, tensor = self.calc_spheroid_objects(tm, Da, theta, phi)

        # Test the automatically created values.
        self.assertEqual(self.diff_data.Diso_err, Diso)
        self.assertEqual(self.diff_data.Dpar_err, Dpar)
        self.assertEqual(self.diff_data.Dper_err, Dper)
        self.assertEqual(self.diff_data.Dratio_err, Dratio)

        # Test the vectors.
        self.assertEqual(self.diff_data.Dpar_unit_err.tostring(), Dpar_unit.tostring())


    def test_set_spheroid_params(self):
        """Test the setting of spheroidal diffusion tensor parameters.

        The following parameters will be set:
            - tm: 20 ns
            - Da: 2e6
            - theta: 60 degrees
            - phi: 290 degrees
        """

        # The parameter values.
        tm = 2e-8
        Da = 2e6
        theta = (60 / 360.0) * 2.0 * pi
        phi = (290 / 360.0) * 2.0 * pi

        # Set the diffusion type.
        self.diff_data.set(param='type', value='spheroid')
        self.diff_data.set(param='spheroid_type', value='prolate')

        # Set the diffusion parameters.
        self.diff_data.set(param='tm', value=tm)
        self.diff_data.set(param='Da', value=Da)
        self.diff_data.set(param='theta', value=theta)
        self.diff_data.set(param='phi', value=phi)

        # Test the set values.
        self.assertEqual(self.diff_data.type, 'spheroid')
        self.assertEqual(self.diff_data.tm, tm)
        self.assertEqual(self.diff_data.Da, Da)
        self.assertEqual(self.diff_data.theta, theta)
        self.assertEqual(self.diff_data.phi, phi)

        # Calculate the diffusion tensor objects.
        Diso, Dpar, Dper, Dratio, Dpar_unit, tensor_diag, rotation, tensor = self.calc_spheroid_objects(tm, Da, theta, phi)

        # Test the automatically created values.
        self.assertEqual(self.diff_data.Diso, Diso)
        self.assertEqual(self.diff_data.Dpar, Dpar)
        self.assertEqual(self.diff_data.Dper, Dper)
        self.assertEqual(self.diff_data.Dratio, Dratio)

        # Test the vectors.
        self.assertEqual(self.diff_data.Dpar_unit.tostring(), Dpar_unit.tostring())

        # Test the matrices.
        self.assertEqual(self.diff_data.tensor_diag.tostring(), tensor_diag.tostring())
        self.assertEqual(self.diff_data.rotation.tostring(), rotation.tostring())
        self.assertEqual(self.diff_data.tensor.tostring(), tensor.tostring())


    def test_set_spheroid_sim(self):
        """Test the setting of Monte Carlo simulation spheroidal diffusion tensor parameters.

        Firstly the following parameters will be appended to empty lists:
            - tm: 2 ns
            - Da: 1e5
            - theta: 0 degrees
            - phi: 360 degrees

        These MC sim values will then be explicity overwritten by setting the first elements of the
        lists to:
            - tm: 0.5 ns
            - Da: 3e5
            - theta: 2 degrees
            - phi: 0 degrees
        """

        # Set the diffusion type.
        self.diff_data.set(param='type', value='spheroid')
        self.diff_data.set(param='spheroid_type', value='prolate')

        # Set the number of MC sims.
        self.diff_data.set_sim_num(1)

        # Set the initial values.
        self.diff_data.set(param='tm', value=2e-9, category='sim', sim_index=0)
        self.diff_data.set(param='Da', value=1e5, category='sim', sim_index=0)
        self.diff_data.set(param='theta', value=0.0, category='sim', sim_index=0)
        self.diff_data.set(param='phi', value=2.0 * pi, category='sim', sim_index=0)

        # The new MC sim parameter values.
        tm = 0.5e-9
        Da = 3e5
        theta = (2 / 360.0) * 2.0 * pi
        phi = 0.0

        # Set the MC sim parameter values (overwriting the initial values).
        self.diff_data.set(param='tm', value=tm, category='sim', sim_index=0)
        self.diff_data.set(param='Da', value=Da, category='sim', sim_index=0)
        self.diff_data.set(param='theta', value=theta, category='sim', sim_index=0)
        self.diff_data.set(param='phi', value=phi, category='sim', sim_index=0)

        # Test the set values.
        self.assertEqual(self.diff_data.type, 'spheroid')
        self.assertEqual(self.diff_data.tm_sim[0], tm)
        self.assertEqual(self.diff_data.Da_sim[0], Da)
        self.assertEqual(self.diff_data.theta_sim[0], theta)
        self.assertEqual(self.diff_data.phi_sim[0], phi)

        # Calculate the diffusion tensor objects.
        Diso, Dpar, Dper, Dratio, Dpar_unit, tensor_diag, rotation, tensor = self.calc_spheroid_objects(tm, Da, theta, phi)

        # Test the automatically created values.
        self.assertEqual(self.diff_data.Diso_sim[0], Diso)
        self.assertEqual(self.diff_data.Dpar_sim[0], Dpar)
        self.assertEqual(self.diff_data.Dper_sim[0], Dper)
        self.assertEqual(self.diff_data.Dratio_sim[0], Dratio)

        # Test the vectors.
        self.assertEqual(self.diff_data.Dpar_unit_sim[0].tostring(), Dpar_unit.tostring())

        # Test the matrices.
        self.assertEqual(self.diff_data.tensor_diag_sim[0].tostring(), tensor_diag.tostring())
        self.assertEqual(self.diff_data.rotation_sim[0].tostring(), rotation.tostring())
        self.assertEqual(self.diff_data.tensor_sim[0].tostring(), tensor.tostring())


    def test_set_tm(self):
        """Test the setting of the tm parameter.

        The tm parameter will be set to 10 ns.  The setting of tm should automatically create the
        Diso parameter.
        """

        # Set the diffusion type.
        self.diff_data.set(param='type', value='sphere')

        # Set the tm value to 10 ns.
        self.diff_data.set(param='tm', value=1e-8)

        # Test that the tm parameter has been set correctly.
        self.assert_(hasattr(self.diff_data, 'tm'))
        self.assertEqual(self.diff_data.tm, 1e-8)

        # Test that the Diso parameter has been set correctly.
        self.assert_(hasattr(self.diff_data, 'Diso'))
        self.assertEqual(self.diff_data.Diso, 1/(6*1e-8))
Beispiel #7
0
    def setUp(self):
        """Set 'self.diff_data' to an empty instance of the DiffTensorData class."""

        self.diff_data = DiffTensorData()
Beispiel #8
0
class Test_diff_tensor(TestCase):
    """Unit tests for the data.diff_tensor relax module."""
    def calc_spheroid_objects(self, tm, Da, theta, phi):
        """Function for calculating the spheroidal diffusion tensor objects."""

        # The parameter values.
        Diso = 1 / (6 * tm)
        Dpar = Diso + 2.0 / 3.0 * Da
        Dper = Diso - 1.0 / 3.0 * Da
        Dratio = Dpar / Dper

        # Vectors.
        Dpar_unit = array(
            [sin(theta) * cos(phi),
             sin(theta) * sin(phi),
             cos(theta)])

        # Matrices.
        if Dpar > Dper:
            axis = array([0, 0, 1], float64)
            tensor_diag = array([[Dper, 0.0, 0.0], [0.0, Dper, 0.0],
                                 [0.0, 0.0, Dpar]])
        else:
            axis = array([1, 0, 0], float64)
            tensor_diag = array([[Dpar, 0.0, 0.0], [0.0, Dper, 0.0],
                                 [0.0, 0.0, Dper]])

        # The rotation.
        rotation = zeros((3, 3), float64)
        two_vect_to_R(Dpar_unit, axis, rotation)

        # The diffusion tensor.
        tensor = dot(rotation, dot(tensor_diag, transpose(rotation)))

        # Return the objects.
        return Diso, Dpar, Dper, Dratio, Dpar_unit, tensor_diag, rotation, tensor

    def setUp(self):
        """Set 'self.diff_data' to an empty instance of the DiffTensorData class."""

        self.diff_data = DiffTensorData()

    def test_append_spheroid_sim(self):
        """Test the appending of Monte Carlo simulation spheroidal diffusion tensor parameters.

        The following parameters will be appended to empty lists:
            - tm: 8 ns
            - Da: -1e7
            - theta: 150 degrees
            - phi: 30 degrees
        """

        # The MC sim parameter values.
        tm = 8e-9
        Da = -1e7
        theta = (150 / 360.0) * 2.0 * pi
        phi = (30 / 360.0) * 2.0 * pi

        # Set the diffusion type.
        self.diff_data.set(param='type', value='spheroid')
        self.diff_data.set(param='spheroid_type', value='oblate')

        # Set the number of MC sims.
        self.diff_data.set_sim_num(1)

        # Set the initial values.
        self.diff_data.set(param='tm', value=tm, category='sim', sim_index=0)
        self.diff_data.set(param='Da', value=Da, category='sim', sim_index=0)
        self.diff_data.set(param='theta',
                           value=theta,
                           category='sim',
                           sim_index=0)
        self.diff_data.set(param='phi', value=phi, category='sim', sim_index=0)

        # Test the set values.
        self.assertEqual(self.diff_data.type, 'spheroid')
        self.assertEqual(self.diff_data.tm_sim[0], tm)
        self.assertEqual(self.diff_data.Da_sim[0], Da)
        self.assertEqual(self.diff_data.theta_sim[0], theta)
        self.assertEqual(self.diff_data.phi_sim[0], phi)

        # Calculate the diffusion tensor objects.
        Diso, Dpar, Dper, Dratio, Dpar_unit, tensor_diag, rotation, tensor = self.calc_spheroid_objects(
            tm, Da, theta, phi)

        # Test the automatically created values.
        self.assertEqual(self.diff_data.Diso_sim[0], Diso)
        self.assertEqual(self.diff_data.Dpar_sim[0], Dpar)
        self.assertEqual(self.diff_data.Dper_sim[0], Dper)
        self.assertEqual(self.diff_data.Dratio_sim[0], Dratio)

        # Test the vectors.
        self.assertEqual(self.diff_data.Dpar_unit_sim[0].tostring(),
                         Dpar_unit.tostring())

        # Test the matrices.
        self.assertEqual(self.diff_data.tensor_diag_sim[0].tostring(),
                         tensor_diag.tostring())
        self.assertEqual(self.diff_data.rotation_sim[0].tostring(),
                         rotation.tostring())
        self.assertEqual(self.diff_data.tensor_sim[0].tostring(),
                         tensor.tostring())

    def test_display(self):
        """Test that the contents of the diffusion tensor object can be displayed."""

        print(self.diff_data)

    def test_set_Diso(self):
        """Test that the Diso parameter cannot be set."""

        # Assert that a RelaxError occurs when Diso is set (to the tm value of 10 ns).
        self.assertRaises(RelaxError, setattr, self.diff_data, 'Diso',
                          1 / (6 * 1e-8))

        # Make sure that the Diso parameter has not been set.
        self.assert_(not hasattr(self.diff_data, 'Diso'))

    def test_set_spheroid_errors(self):
        """Test the setting of spheroidal diffusion tensor parameter errors.

        The following parameter errors will be set:
            - tm: 1 ns
            - Da: 1e3
            - theta: 3 degrees
            - phi: 5 degrees
        """

        # The parameter errors.
        tm = 1e-8
        Da = 1e3
        theta = (3 / 360.0) * 2.0 * pi
        phi = (5 / 360.0) * 2.0 * pi

        # Set the diffusion type.
        self.diff_data.set(param='type', value='spheroid')
        self.diff_data.set(param='spheroid_type', value='prolate')

        # Set the diffusion parameter errors.
        self.diff_data.set(param='tm', value=tm, category='err')
        self.diff_data.set(param='Da', value=Da, category='err')
        self.diff_data.set(param='theta', value=theta, category='err')
        self.diff_data.set(param='phi', value=phi, category='err')

        # Test the set values.
        self.assertEqual(self.diff_data.type, 'spheroid')
        self.assertEqual(self.diff_data.tm_err, tm)
        self.assertEqual(self.diff_data.Da_err, Da)
        self.assertEqual(self.diff_data.theta_err, theta)
        self.assertEqual(self.diff_data.phi_err, phi)

        # Calculate the diffusion tensor objects.
        Diso, Dpar, Dper, Dratio, Dpar_unit, tensor_diag, rotation, tensor = self.calc_spheroid_objects(
            tm, Da, theta, phi)

        # Test the automatically created values.
        self.assertEqual(self.diff_data.Diso_err, Diso)
        self.assertEqual(self.diff_data.Dpar_err, Dpar)
        self.assertEqual(self.diff_data.Dper_err, Dper)
        self.assertEqual(self.diff_data.Dratio_err, Dratio)

        # Test the vectors.
        self.assertEqual(self.diff_data.Dpar_unit_err.tostring(),
                         Dpar_unit.tostring())

    def test_set_spheroid_params(self):
        """Test the setting of spheroidal diffusion tensor parameters.

        The following parameters will be set:
            - tm: 20 ns
            - Da: 2e6
            - theta: 60 degrees
            - phi: 290 degrees
        """

        # The parameter values.
        tm = 2e-8
        Da = 2e6
        theta = (60 / 360.0) * 2.0 * pi
        phi = (290 / 360.0) * 2.0 * pi

        # Set the diffusion type.
        self.diff_data.set(param='type', value='spheroid')
        self.diff_data.set(param='spheroid_type', value='prolate')

        # Set the diffusion parameters.
        self.diff_data.set(param='tm', value=tm)
        self.diff_data.set(param='Da', value=Da)
        self.diff_data.set(param='theta', value=theta)
        self.diff_data.set(param='phi', value=phi)

        # Test the set values.
        self.assertEqual(self.diff_data.type, 'spheroid')
        self.assertEqual(self.diff_data.tm, tm)
        self.assertEqual(self.diff_data.Da, Da)
        self.assertEqual(self.diff_data.theta, theta)
        self.assertEqual(self.diff_data.phi, phi)

        # Calculate the diffusion tensor objects.
        Diso, Dpar, Dper, Dratio, Dpar_unit, tensor_diag, rotation, tensor = self.calc_spheroid_objects(
            tm, Da, theta, phi)

        # Test the automatically created values.
        self.assertEqual(self.diff_data.Diso, Diso)
        self.assertEqual(self.diff_data.Dpar, Dpar)
        self.assertEqual(self.diff_data.Dper, Dper)
        self.assertEqual(self.diff_data.Dratio, Dratio)

        # Test the vectors.
        self.assertEqual(self.diff_data.Dpar_unit.tostring(),
                         Dpar_unit.tostring())

        # Test the matrices.
        self.assertEqual(self.diff_data.tensor_diag.tostring(),
                         tensor_diag.tostring())
        self.assertEqual(self.diff_data.rotation.tostring(),
                         rotation.tostring())
        self.assertEqual(self.diff_data.tensor.tostring(), tensor.tostring())

    def test_set_spheroid_sim(self):
        """Test the setting of Monte Carlo simulation spheroidal diffusion tensor parameters.

        Firstly the following parameters will be appended to empty lists:
            - tm: 2 ns
            - Da: 1e5
            - theta: 0 degrees
            - phi: 360 degrees

        These MC sim values will then be explicity overwritten by setting the first elements of the
        lists to:
            - tm: 0.5 ns
            - Da: 3e5
            - theta: 2 degrees
            - phi: 0 degrees
        """

        # Set the diffusion type.
        self.diff_data.set(param='type', value='spheroid')
        self.diff_data.set(param='spheroid_type', value='prolate')

        # Set the number of MC sims.
        self.diff_data.set_sim_num(1)

        # Set the initial values.
        self.diff_data.set(param='tm', value=2e-9, category='sim', sim_index=0)
        self.diff_data.set(param='Da', value=1e5, category='sim', sim_index=0)
        self.diff_data.set(param='theta',
                           value=0.0,
                           category='sim',
                           sim_index=0)
        self.diff_data.set(param='phi',
                           value=2.0 * pi,
                           category='sim',
                           sim_index=0)

        # The new MC sim parameter values.
        tm = 0.5e-9
        Da = 3e5
        theta = (2 / 360.0) * 2.0 * pi
        phi = 0.0

        # Set the MC sim parameter values (overwriting the initial values).
        self.diff_data.set(param='tm', value=tm, category='sim', sim_index=0)
        self.diff_data.set(param='Da', value=Da, category='sim', sim_index=0)
        self.diff_data.set(param='theta',
                           value=theta,
                           category='sim',
                           sim_index=0)
        self.diff_data.set(param='phi', value=phi, category='sim', sim_index=0)

        # Test the set values.
        self.assertEqual(self.diff_data.type, 'spheroid')
        self.assertEqual(self.diff_data.tm_sim[0], tm)
        self.assertEqual(self.diff_data.Da_sim[0], Da)
        self.assertEqual(self.diff_data.theta_sim[0], theta)
        self.assertEqual(self.diff_data.phi_sim[0], phi)

        # Calculate the diffusion tensor objects.
        Diso, Dpar, Dper, Dratio, Dpar_unit, tensor_diag, rotation, tensor = self.calc_spheroid_objects(
            tm, Da, theta, phi)

        # Test the automatically created values.
        self.assertEqual(self.diff_data.Diso_sim[0], Diso)
        self.assertEqual(self.diff_data.Dpar_sim[0], Dpar)
        self.assertEqual(self.diff_data.Dper_sim[0], Dper)
        self.assertEqual(self.diff_data.Dratio_sim[0], Dratio)

        # Test the vectors.
        self.assertEqual(self.diff_data.Dpar_unit_sim[0].tostring(),
                         Dpar_unit.tostring())

        # Test the matrices.
        self.assertEqual(self.diff_data.tensor_diag_sim[0].tostring(),
                         tensor_diag.tostring())
        self.assertEqual(self.diff_data.rotation_sim[0].tostring(),
                         rotation.tostring())
        self.assertEqual(self.diff_data.tensor_sim[0].tostring(),
                         tensor.tostring())

    def test_set_tm(self):
        """Test the setting of the tm parameter.

        The tm parameter will be set to 10 ns.  The setting of tm should automatically create the
        Diso parameter.
        """

        # Set the diffusion type.
        self.diff_data.set(param='type', value='sphere')

        # Set the tm value to 10 ns.
        self.diff_data.set(param='tm', value=1e-8)

        # Test that the tm parameter has been set correctly.
        self.assert_(hasattr(self.diff_data, 'tm'))
        self.assertEqual(self.diff_data.tm, 1e-8)

        # Test that the Diso parameter has been set correctly.
        self.assert_(hasattr(self.diff_data, 'Diso'))
        self.assertEqual(self.diff_data.Diso, 1 / (6 * 1e-8))