Beispiel #1
0
    def setUp(self):
        """Create a mol-res-spin structure for testing all the object methods."""

        # The initial empty structure.
        self.mol = MoleculeList()

        # Add a test object to the first molecule, first residue, first spin.
        self.mol[0].res[0].spin[0].x = 1
Beispiel #2
0
    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 setUp(self):
        """Create a mol-res-spin structure for testing all the object methods."""

        # The initial empty structure.
        self.mol = MoleculeList()

        # Add a test object to the first molecule, first residue, first spin.
        self.mol[0].res[0].spin[0].x = 1
    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 = []
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)
class Test_mol_res_spin(TestCase):
    """Unit tests for the data.mol_res_spin relax module."""

    def setUp(self):
        """Create a mol-res-spin structure for testing all the object methods."""

        # The initial empty structure.
        self.mol = MoleculeList()

        # Add a test object to the first molecule, first residue, first spin.
        self.mol[0].res[0].spin[0].x = 1


    def test_add_mol(self):
        """Unit test for the 'add_item()' method of the MolecularList class."""

        # The name of the new molecule.
        name = 'Ap4Aase'

        # Add a molecule.
        self.mol.add_item(mol_name=name)

        # Test that the molecule exists.
        self.assertEqual(self.mol[1].name, name)

        # Test that the molecule's single spin system container does not have the object 'x'.
        self.assert_(not hasattr(self.mol[1].res[0].spin[0], 'x'))


    def test_add_res(self):
        """Unit test for the 'add_item()' method of the ResidueList class."""

        # The name and number of the new residue.
        name = 'LEU'
        num = -5

        # Add the residue.
        self.mol[0].res.add_item(res_name=name, res_num=num)

        # Test that the residue exists.
        self.assertEqual(self.mol[0].res[1].name, name)
        self.assertEqual(self.mol[0].res[1].num, num)

        # Test that the residues' single spin system container does not have the object 'x'.
        self.assert_(not hasattr(self.mol[0].res[1].spin[0], 'x'))


    def test_add_spin(self):
        """Unit test for the 'add_item()' method of the SpinList class."""

        # The name and number of the new spin.
        name = 'N'
        num = 1409

        # Add the spin.
        self.mol[0].res[0].spin.add_item(spin_name=name, spin_num=num, select=0)

        # Test that the spin exists.
        self.assertEqual(self.mol[0].res[0].spin[1].name, name)
        self.assertEqual(self.mol[0].res[0].spin[1].num, num)
        self.assertEqual(self.mol[0].res[0].spin[1].select, 0)

        # Test that the spin system container does not have the object 'x'.
        self.assert_(not hasattr(self.mol[0].res[0].spin[1], 'x'))


    def test_mol_container_repr(self):
        """Unit test for the validity of the MoleculeContainer.__repr__() method."""

        # Test that __repr__() returns a string.
        self.assert_(type(self.mol[0].__repr__()), str)


    def test_mol_list_repr(self):
        """Unit test for the validity of the MoleculeList.__repr__() method."""

        # Test that __repr__() returns a string.
        self.assert_(type(self.mol.__repr__()), str)


    def test_res_container_repr(self):
        """Unit test for the validity of the ResidueContainer.__repr__() method."""

        # Test that __repr__() returns a string.
        self.assert_(type(self.mol[0].res[0].__repr__()), str)


    def test_res_list_repr(self):
        """Unit test for the validity of the ResidueList.__repr__() method."""

        # Test that __repr__() returns a string.
        self.assert_(type(self.mol[0].res.__repr__()), str)


    def test_spin_container_repr(self):
        """Unit test for the validity of the SpinContainer.__repr__() method."""

        # Test that __repr__() returns a string.
        self.assert_(type(self.mol[0].res[0].spin[0].__repr__()), str)


    def test_spin_list_repr(self):
        """Unit test for the validity of the SpinList.__repr__() method."""

        # Test that __repr__() returns a string.
        self.assert_(type(self.mol[0].res[0].spin.__repr__()), str)
Beispiel #7
0
class Test_mol_res_spin(TestCase):
    """Unit tests for the data.mol_res_spin relax module."""

    def setUp(self):
        """Create a mol-res-spin structure for testing all the object methods."""

        # The initial empty structure.
        self.mol = MoleculeList()

        # Add a test object to the first molecule, first residue, first spin.
        self.mol[0].res[0].spin[0].x = 1


    def test_add_mol(self):
        """Unit test for the 'add_item()' method of the MolecularList class."""

        # The name of the new molecule.
        name = 'Ap4Aase'

        # Add a molecule.
        self.mol.add_item(mol_name=name)

        # Test that the molecule exists.
        self.assertEqual(self.mol[1].name, name)

        # Test that the molecule's single spin system container does not have the object 'x'.
        self.assert_(not hasattr(self.mol[1].res[0].spin[0], 'x'))


    def test_add_res(self):
        """Unit test for the 'add_item()' method of the ResidueList class."""

        # The name and number of the new residue.
        name = 'LEU'
        num = -5

        # Add the residue.
        self.mol[0].res.add_item(res_name=name, res_num=num)

        # Test that the residue exists.
        self.assertEqual(self.mol[0].res[1].name, name)
        self.assertEqual(self.mol[0].res[1].num, num)

        # Test that the residues' single spin system container does not have the object 'x'.
        self.assert_(not hasattr(self.mol[0].res[1].spin[0], 'x'))


    def test_add_spin(self):
        """Unit test for the 'add_item()' method of the SpinList class."""

        # The name and number of the new spin.
        name = 'N'
        num = 1409

        # Add the spin.
        self.mol[0].res[0].spin.add_item(spin_name=name, spin_num=num, select=0)

        # Test that the spin exists.
        self.assertEqual(self.mol[0].res[0].spin[1].name, name)
        self.assertEqual(self.mol[0].res[0].spin[1].num, num)
        self.assertEqual(self.mol[0].res[0].spin[1].select, 0)

        # Test that the spin system container does not have the object 'x'.
        self.assert_(not hasattr(self.mol[0].res[0].spin[1], 'x'))


    def test_mol_container_repr(self):
        """Unit test for the validity of the MoleculeContainer.__repr__() method."""

        # Test that __repr__() returns a string.
        self.assert_(type(self.mol[0].__repr__()), str)


    def test_mol_list_repr(self):
        """Unit test for the validity of the MoleculeList.__repr__() method."""

        # Test that __repr__() returns a string.
        self.assert_(type(self.mol.__repr__()), str)


    def test_res_container_repr(self):
        """Unit test for the validity of the ResidueContainer.__repr__() method."""

        # Test that __repr__() returns a string.
        self.assert_(type(self.mol[0].res[0].__repr__()), str)


    def test_res_list_repr(self):
        """Unit test for the validity of the ResidueList.__repr__() method."""

        # Test that __repr__() returns a string.
        self.assert_(type(self.mol[0].res.__repr__()), str)


    def test_spin_container_repr(self):
        """Unit test for the validity of the SpinContainer.__repr__() method."""

        # Test that __repr__() returns a string.
        self.assert_(type(self.mol[0].res[0].spin[0].__repr__()), str)


    def test_spin_list_repr(self):
        """Unit test for the validity of the SpinList.__repr__() method."""

        # Test that __repr__() returns a string.
        self.assert_(type(self.mol[0].res[0].spin.__repr__()), str)
Beispiel #8
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)