class Atom(StaticSelection):
    """
    Atom representation.

    This class is a proxy to a atom in molecule loaded into VMD.
    """
    # Large amounts of these objects can be created, slots has some performance benefits.
    __slots__ = ()

    def __init__(self, index, molecule=None, frame=NOW):
        """
        Creates atom representation.

        @param index: Index of the atom
        @param molecule: Atom's molecule. Top if not provider.
        @type molecule: Molecule or None
        @param frame: Atom's frame
        @type frame: Non-negative integer or NOW
        """
        super(Atom, self).__init__(index, molecule=molecule, frame=frame)
        # Check if index makes sense
        if index >= _molecule.numatoms(self._molecule.molid):
            raise ValueError("Atom %d doesn't exist in '%s' at %s" % (index, self._molecule, frame))

    @classmethod
    def pick(cls, selection, molecule=None, frame=NOW):
        """
        Creates atom from selection text.

        @param selection: Selection text
        @param molecule: Molecule to select from. Top if not defined.
        @type molecule: Molecule
        @param frame: Atom's frame
        @type frame: Non-negative integer or NOW
        """
        if molecule is None:
            molecule = MOLECULES.top
        else:
            assert isinstance(molecule, Molecule)
        assert frame == NOW or frame >= 0

        sel = _atomsel(selection, frame=frame, molid=molecule.molid)
        if len(sel) != 1:
            raise ValueError("Selection '%s' doesn't define single atom in '%s' at %s" % (selection, molecule, frame))
        self = cls(sel.get('index')[0], molecule, frame)
        return self

    @property
    def atomsel(self):
        """
        Returns respective 'VMD.atomsel' instance.
        """
        if self._atomsel is None:
            self._atomsel = _atomsel('index %d' % self._index, frame=self._frame, molid=self._molecule.molid)
        return self._atomsel

    ############################################################################
    # Atom's data
    # Coordinates
    x = _object_property('x', doc="Coordinate in 'x' dimension.")
    y = _object_property('y', doc="Coordinate in 'y' dimension.")
    z = _object_property('z', doc="Coordinate in 'z' dimension.")

    def _get_coords(self):
        # XXX: This is unintuitive, but very fast. The atom's center is the location of the atom.
        # Apparently getting the coordinates all at once has lower overhead than underlying conputation of the center.
        return array(self.atomsel.center())

    def _set_coords(self, value):
        self.x, self.y, self.z = value

    coords = property(_get_coords, _set_coords, doc="Array of (x, y, z) coordinates.")

    # Other data
    name = _object_property('name', doc="Atom name.")
    type = _object_property('type', doc="Atom type.")
    element = _object_property('element', doc="Atom element.")
    beta = _object_property('beta', doc="Atom beta factor.")
    occupancy = _object_property('occupancy', doc="Atom occupancy.")
    mass = _object_property('mass', doc="Atom mass.")
    charge = _object_property('charge', doc="Atom charge.")
    radius = _object_property('radius', doc="Atom radius.")

    ############################################################################
    # Connections to other objects
    @property
    def bonded(self):
        """
        Returns iterator over Atoms bonded to this one.
        """
        return (Atom(i, self._molecule, self._frame) for i in self.atomsel.bonds[0])

    @property
    def residue(self):
        """
        Returns atom's residue.
        """
        return Residue(self._getter('residue'), self._molecule, self._frame)

    def _get_chain(self):
        return Chain(self._getter('chain'), self._molecule, self._frame)

    def _set_chain(self, chain):
        assert isinstance(chain, Chain)
        self._setter('chain', chain.name)

    chain = property(_get_chain, _set_chain, doc="Atom chain")

    def _get_segment(self):
        return Segment(self._getter('segname'), self._molecule, self._frame)

    def _set_segment(self, segment):
        assert isinstance(segment, Segment)
        self._setter('segname', segment.name)

    segment = property(_get_segment, _set_segment, doc="Atom segment") ANGLE = _label.ANGLE ANGLE_LABELS = LabelManager(ANGLE, AngleLabel) class AngleLabel(BaseLabel):
    _category = ANGLE

    def __init__(self, a, b, c):
        assert isinstance(a, Atom)
        assert isinstance(b, Atom)
        assert isinstance(c, Atom)
        super(AngleLabel, self).__init__(a, b, c)

    @property
    def angles(self):
        """
        Returns angles between the atoms throughout the loaded trajectory.
        """
        return _label.getvalues(self._category, {'molid': self._molids, 'atomid': self._atomids}) ATOM = _label.ATOM ATOM_LABELS = LabelManager(ATOM, AtomLabel) class AtomLabel(BaseLabel):
    _category = ATOM

    def __init__(self, a):
        assert isinstance(a, Atom)
        super(AtomLabel, self).__init__(a)

    @classmethod
    def create(cls, a):
        return super(AtomLabel, cls).create(a)

    @property
    def atom(self):
        """
        Labeled atom.
        """
        return self._atoms[0] BOND = _label.BOND BOND_LABELS = LabelManager(BOND, BondLabel) class BondLabel(BaseLabel):
    _category = BOND

    def __init__(self, a, b):
        assert isinstance(a, Atom)
        assert isinstance(b, Atom)
        super(BondLabel, self).__init__(a, b)

    @property
    def distances(self):
        """
        Returns distances between the atoms throughout the loaded trajectory.
        """
        return _label.getvalues(self._category, {'molid': self._molids, 'atomid': self._atomids}) DIHEDRAL = _label.DIHEDRAL DIHEDRAL_LABELS = LabelManager(DIHEDRAL, DihedralLabel) class DihedralLabel(BaseLabel):
    _category = DIHEDRAL

    def __init__(self, a, b, c, d):
        assert isinstance(a, Atom)
        assert isinstance(b, Atom)
        assert isinstance(c, Atom)
        assert isinstance(d, Atom)
        super(DihedralLabel, self).__init__(a, b, c, d)

    @property
    def dihedrals(self):
        """
        Returns dihedral angles between the atoms throughout the loaded trajectory.
        """
        return _label.getvalues(self._category, {'molid': self._molids, 'atomid': self._atomids}) class Molecule(object):
    """
    Molecule representation.

    This class is a proxy for molecule loaded into VMD.
    """
    def __init__(self, molid):
        """
        Creates a new molecule.

        @param molid: ID of existing molecule
        @type molid: Non-negative integer
        """
        assert molid >= 0
        if not _molecule.exists(molid):
            raise ValueError("Molecule %d does not exist." % molid)
        self.molid = molid
        self._molecule = None

    def __repr__(self):
        return "<%s: %s(%d)>" % (type(self).__name__, self.name, self.molid)

    def __eq__(self, other):
        return type(self) == type(other) and self.molid == other.molid

    def __ne__(self, other):
        return not self.__eq__(other)

    @classmethod
    def create(cls, name=None):
        """
        Creates new molecule.

        @name: Name of the molecule.
        """
        molid = _molecule.new(name or 'molecule')
        return cls(molid)

    def delete(self):
        """
        Deletes the molecule.
        """
        _molecule.delete(self.molid)

    def load(self, filename, filetype=None, start=0, stop=-1, step=1, wait=True, volsets=None):
        """
        Loads data from file into the molecule.

        @param filename: Name of file to be loaded
        @type filename: String
        @param filetype: Format of file. If not present or `None` it is guessed.
        @type filetype: One of `FORMAT_` constants, string or `None`
        @param start: First frame to be loaded. Default is first frame in the file.
        @type start: Non-negative integer
        @param stop: Last frame to be loaded. Default (-1) is last frame in the file.
        @type stop: Non-negative integer or -1
        @param step: Load every step'th frame. Default is every frame.
        @type step: Positive integer
        @param wait: Whather to wait until file is completely loaded.
        @type wait: Boolean
        """
        assert start >= 0
        assert stop >= -1
        assert step > 0
        if filetype is None:
            filetype = guess_file_format(filename)
            if filetype is None:
                raise ValueError("Cannot detect filetype for '%s'" % filename)
        waitfor = wait and -1 or 0
        volsets = volsets or []
        _molecule.read(self.molid, filetype, filename, beg=start, end=stop, skip=step, waitfor=waitfor,
                       volsets=volsets)

    @property
    def molecule(self):
        """
        Returns respective VMD.Molecule instance.
        """
        return _Molecule(id=self.molid)

    def _get_frame(self):
        return _molecule.get_frame(self.molid)

    def _set_frame(self, frame):
        """
        Sets the active frame

        @type frame: Non-negative integer
        """
        assert frame >= 0
        _molecule.set_frame(self.molid, frame)

    frame = property(_get_frame, _set_frame, doc="Molecule's frame")

    @property
    def frames(self):
        """
        Returns frames descriptor.
        """
        return Frames(self)

    def _get_name(self):
        return _molecule.name(self.molid)

    def _set_name(self, name):
        _molecule.rename(self.molid, name)

    name = property(_get_name, _set_name, doc="Molecule's name")

    def _get_visible(self):
        return _molecule.get_visible(self.molid)

    def _set_visible(self, value):
        """
        Sets molecule visibility

        @type value: Boolean
        """
        _molecule.set_visible(self.molid, value)

    visible = property(_get_visible, _set_visible, doc="Visibility")

    @property
    def representations(self):
        """
        Returns molecule representations manager.
        """
        return RepresentationManager(self) MOLECULES = MoleculeManager() def data(filename):
    """
    Return full filename of the test datafile.
    """
    return os.path.join(os.path.dirname(__file__), 'data', filename) class PyvmdTestCase(unittest.TestCase):
    """
    Enhanced test case for pyvmd tests.
    """
    def tearDown(self):
        # Delete all molecule when we're finished
        for molid in VMD.molecule.listall():
            VMD.molecule.delete(molid)
        # Restore Collector's auto_name_counter
        Collector.auto_name_counter = 0

    def assertAlmostEqualSeqs(self, seq1, seq2, places=None, msg=None, delta=None):
        """
        An assertion for ordered sequences. Compares items one by one with
        their differences rounded to the given number of decimal places (default 7).

        Note that decimal places (from zero) are usually not the same
        as significant digits (measured from the most signficant digit).

        If the two objects compare equal then they will automatically
        compare almost equal.
        """
        # This method is copied from unittest's assertSequenceEqual method.
        seq_type_name = "sequence"
        differing = None
        try:
            len1 = len(seq1)
        except (TypeError, NotImplementedError):
            differing = 'First %s has no length.    Non-sequence?' % (
                        seq_type_name)

        if differing is None:
            try:
                len2 = len(seq2)
            except (TypeError, NotImplementedError):
                differing = 'Second %s has no length.    Non-sequence?' % (
                            seq_type_name)

        if differing is None:
            if seq1 == seq2:
                return

            seq1_repr = safe_repr(seq1)
            seq2_repr = safe_repr(seq2)
            if len(seq1_repr) > 30:
                seq1_repr = seq1_repr[:30] + '...'
            if len(seq2_repr) > 30:
                seq2_repr = seq2_repr[:30] + '...'
            elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
            differing = '%ss differ: %s != %s\n' % elements

            for i in xrange(min(len1, len2)):
                try:
                    item1 = seq1[i]
                except (TypeError, IndexError, NotImplementedError):
                    differing += ('\nUnable to index element %d of first %s\n' %
                                  (i, seq_type_name))
                    break

                try:
                    item2 = seq2[i]
                except (TypeError, IndexError, NotImplementedError):
                    differing += ('\nUnable to index element %d of second %s\n' %
                                  (i, seq_type_name))
                    break

                try:
                    self.assertAlmostEqual(item1, item2, places=places, delta=delta)
                except self.failureException, error:
                    differing += ('\nFirst differing element %d:\n%s\n' %
                                  (i, error))
                    break
            else:
                if len1 == len2:
                    # The sequences are the same.
                    return

            if len1 > len2:
                differing += ('\nFirst %s contains %d additional '
                              'elements.\n' % (seq_type_name, len1 - len2))
                try:
                    differing += ('First extra element %d:\n%s\n' %
                                  (len2, seq1[len2]))
                except (TypeError, IndexError, NotImplementedError):
                    differing += ('Unable to index element %d '
                                  'of first %s\n' % (len2, seq_type_name))
            elif len1 < len2:
                differing += ('\nSecond %s contains %d additional '
                              'elements.\n' % (seq_type_name, len2 - len1))
                try:
                    differing += ('First extra element %d:\n%s\n' %
                                  (len1, seq2[len1]))
                except (TypeError, IndexError, NotImplementedError):
                    differing += ('Unable to index element %d '
                                  'of second %s\n' % (len1, seq_type_name))
        standardMsg = differing
        diffMsg = '\n' + '\n'.join(
            difflib.ndiff(pprint.pformat(seq1).splitlines(),
                          pprint.pformat(seq2).splitlines()))
        standardMsg = self._truncateMessage(standardMsg, diffMsg)
        msg = self._formatMessage(msg, standardMsg)
        self.fail(msg)
import VMD
from pyvmd.atoms import Atom
from pyvmd.labels import (ANGLE, ANGLE_LABELS, AngleLabel, ATOM, ATOM_LABELS, AtomLabel, BOND, BOND_LABELS, BondLabel,
                          DIHEDRAL, DIHEDRAL_LABELS, DihedralLabel)
from pyvmd.molecules import Molecule, MOLECULES
from .utils import data, PyvmdTestCase
"""
Tests for labels utilities.
"""




def clear_labels():
    """
    Utility to delete all labels.
    """
    for category in ATOM, BOND, ANGLE, DIHEDRAL:
        for label in VMD.label.listall(category):
            VMD.label.delete(category, label)



class TestLabels(PyvmdTestCase):