class ViewerToolBase(ipy.Box): """ The base for most viewer-based widgets - it consists of a viewer in the top-left, UI controls on the right, and some additional widgets underneath the viewer """ VIEWERTYPE = viewers.GeometryViewer VIEWERWIDTH = '600px' selected_atom_indices = utils.Alias('viewer.selected_atom_indices') selected_atoms = utils.Alias('viewer.selected_atoms') def __init__(self, mol): self.mol = mol self.toolpane = VBox() self.viewer = self.VIEWERTYPE(mol, width=self.VIEWERWIDTH) self.subtools = ipy.Box() self.viewer_pane = VBox([self.viewer, self.subtools]) self.main_pane = HBox([self.viewer_pane, self.toolpane]) super().__init__([self.main_pane]) def __getattr__(self, item): if hasattr(self.viewer, item): return getattr(self.viewer, item) else: raise AttributeError(item)
class _DatabaseEntry(object): """ Maps into a field stored in the database """ def __init__(self, hostdb, keyname): self.hostdb = hostdb self.keyname = keyname self.index = self.hostdb['__FIELDS__']['RESFIELDS'].index(keyname) def __repr__(self): return '<Chemical component dictionary: "%s" entries>' % self.keyname def __getitem__(self, item): return self.hostdb[item][self.index] __contains__ = utils.Alias('hostdb.__contains__') def keys(self): for key in self.hostdb.keys(): if key == '__FIELDS__': continue yield key def items(self): for key in self: yield key, self[key] __iter__ = keys
class AtomPropertyMixin(object): """ Functions accessing computed atomic properties. Note: This is a mixin class designed only to be mixed into the :class:`Atom` class. Routines are separated are here for code organization only - they could be included in the main Atom class without changing any functionality """ distance = utils.Alias('_container.distance') atoms_within = utils.Alias('_container.atoms_within') residues_within = utils.Alias('_container.residues_within') @utils.args_from(AtomContainer.calc_distance_array) def calc_distances(self, *args, **kwargs): array = self._container.calc_distance_array(*args, **kwargs) return array[0] @property def _container(self): """ AtomContainer: a container with just this atom in it. This is a convenience method for accessing to all of the :class:`AtomContainer`'s useful methods for dealing with geometry """ return AtomList([self]) @property def ff(self): """ moldesign.utils.DotDict: This atom's force field parameters, if available (``None`` otherwise) """ try: ff = self.molecule.energy_model.mdtforcefield except AttributeError: return None if ff is None: return None return utils.DotDict(partialcharge=ff.partial_charges[self], lj=ff.lennard_jones[self]) @property def basis_functions(self): """ List[mdt.orbitals.AtomicBasisFunction]: This atom's basis functions, if available (``None`` otherwise) """ if self.molecule is None: return None try: wfn = self.molecule.wfn except mdt.exceptions.NotCalculatedError: return None return wfn.aobasis.on_atom.get(self, []) @property def properties(self): """ moldesign.utils.DotDict: Returns any calculated properties for this atom """ props = utils.DotDict() for name, p in self.molecule.properties.iteritems(): if hasattr(p, 'type') and p.type == 'atomic': props[name] = p[self] return props
class ChildList(AtomContainer): """ A list of biochemical objects that can be accessed by name or by index. """ __len__ = utils.Alias('_childinorder.__len__') __iter__ = utils.Alias('_childinorder.__iter__') index = utils.Alias('_childinorder.index') def __str__(self): return str(self._childinorder._items) def __repr__(self): try: return '<Children of %s: %s>' % (self.parent, self) except (KeyError, AttributeError): return '<ChildList @ %x (exception in self.__repr__)>' % id(self) def __init__(self, parent): super(ChildList, self).__init__() self.parent = parent self._childbyname = {} self._childinorder = utils.SortedCollection(key=_sortkey) def __dir__(self): return self.__dict__.keys() + self.__class__.__dict__.keys( ) + self._childbyname.keys() def __getitem__(self, item): if isinstance(item, basestring): return self._childbyname[item] else: return self._childinorder[item] def __setitem__(self, key, val): if key in self._childbyname: raise KeyError('%s already exists in %s' % (key, self.parent)) self._childbyname[key] = val self._childinorder.insert_right(val) def __contains__(self, item): if isinstance(item, basestring) or item is None: return (item in self._childbyname) else: return (item in self._childinorder) def __getattr__(self, item): if item == '_childbyname': return self.__getattribute__('_childbyname') try: return self._childbyname[item] except KeyError: raise AttributeError( 'ChildList object in %s has no attribute %s.' % (self.parent.__repr__(), item)) def iteratoms(self): """Iterate over all atoms Yields: Atom: all atoms in this entity and/or its children """ for child in self: if isinstance(child, mdt.Atom): yield child else: for atom in child.iteratoms(): yield atom @property def atoms(self): """ AtomList: a sorted list of all atoms in this entity and/or its children """ return AtomList(self.iteratoms()) def rebuild(self): self._childbyname = {obj.name: obj for obj in self._childinorder}
class BioContainer(AtomContainer): """ Generalized storage mechanism for hierarchical representation of biomolecules, e.g. by residue, chain, etc. Permits other groupings, provided that everything is tree-like. All children of a given entity must have unique names. An individual child can be retrieved with ``biocontainer.childname`` or ``biocontainer['childname']`` or ``biocontainer[index]`` Yields: BioContainer or mdt.Atom: this entity's children, in order """ __getitem__ = utils.Alias('children.__getitem__') __len__ = utils.Alias('children.__len__') __iter__ = utils.Alias('children.__iter__') __contains__ = utils.Alias('children.__contains__') atoms = utils.Alias('children.atoms') iteratoms = utils.Alias('children.iteratoms') rebuild = utils.Alias('children.rebuild') def __init__(self, name=None, molecule=None, index=None, pdbname=None, pdbindex=None, **kwargs): """ Initialization: Args: name (str): Name of this biocontainer parent (mdt.Molecule): molecule this biocontainer belongs to index (int): index of this biocontainer in the parent molecule pdbname (str): PDB-format name of this biocontainer pdbindex (str): Index of this biocontainer in PDB format """ super(BioContainer, self).__init__() self.children = ChildList(self) self.molecule = molecule self.name = name self.index = index self.pdbname = pdbname self.pdbindex = pdbindex for name, val in kwargs.iteritems(): setattr(self, name, val) def add(self, item, key=None): """ Add a child to this entity. Raises: KeyError: if an object with this key already exists Args: item (BioContainer or mdt.Atom): the child object to add key (str): Key to retrieve this item (default: ``item.name`` ) """ if key is None: key = item.name self.children[key] = item __setitem__ = add def __dir__(self): return (self.__dict__.keys() + self.__class__.__dict__.keys() + [x.name for x in self.children]) def __hash__(self): """ Explicitly hash by object id """ return id(self) def __eq__(self, other): return self is other def __repr__(self): try: if self.molecule is not None: return '<%s in %s>' % (self, self.molecule) else: return '<%s (no molecule)>' % self except (KeyError, AttributeError): return '<%s at %s (exception in __repr__)>' % ( self.__class__.__name__, id(self)) def __str__(self): return '%s %s (index=%s)' % (self.__class__.__name__, self.name, str(self.index)) def __call__(self, **kwargs): """ Allow for some simple queries, i.e. mol.chain['A'].residue(pdbname='ALA') """ retlist = [] for child in self: for key, val in kwargs.iteritems(): if hasattr(child, key) and getattr(child, key) == val: retlist.append(child) return retlist