def mol_to_parmed(mol):
    """ Convert MDT Molecule to parmed Structure
    Args:
        mol (moldesign.Molecule):

    Returns:
        parmed.Structure
    """
    struc = parmed.Structure()
    struc.title = mol.name

    pmedatoms = []
    for atom in mol.atoms:
        pmedatm = parmed.Atom(atomic_number=atom.atomic_number,
                              name=atom.name,
                              mass=atom.mass.value_in(u.dalton),
                              number=utils.if_not_none(atom.pdbindex, -1))
        pmedatm.xx, pmedatm.xy, pmedatm.xz = atom.position.value_in(u.angstrom)
        pmedatoms.append(pmedatm)
        struc.add_atom(pmedatm,
                       resname=utils.if_not_none(atom.residue.resname, 'UNL'),
                       resnum=utils.if_not_none(atom.residue.pdbindex, -1),
                       chain=utils.if_not_none(atom.chain.name, ''))

    for bond in mol.bonds:
        struc.bonds.append(parmed.Bond(pmedatoms[bond.a1.index],
                                       pmedatoms[bond.a2.index],
                                       order=bond.order))
    return struc
def mol_to_parmed(mol):
    """ Convert MDT Molecule to parmed Structure
    Args:
        mol (moldesign.Molecule):

    Returns:
        parmed.Structure
    """
    struc = parmed.Structure()
    struc.title = mol.name

    pmedatoms = []
    for atom in mol.atoms:
        pmedatm = parmed.Atom(atomic_number=atom.atomic_number,
                              name=atom.name,
                              mass=atom.mass.value_in(u.dalton),
                              number=utils.if_not_none(atom.pdbindex, -1))
        pmedatm.xx, pmedatm.xy, pmedatm.xz = atom.position.value_in(u.angstrom)
        pmedatoms.append(pmedatm)
        struc.add_atom(pmedatm,
                       resname=utils.if_not_none(atom.residue.resname, 'UNL'),
                       resnum=utils.if_not_none(atom.residue.pdbindex, -1),
                       chain=utils.if_not_none(atom.chain.name, ''))

    for bond in mol.bonds:
        struc.bonds.append(
            parmed.Bond(pmedatoms[bond.a1.index],
                        pmedatoms[bond.a2.index],
                        order=bond.order))
    return struc
def run_job(job, engine=None, image=None, wait=True, jobname=None, display=True,
            _return_result=False):
    """ Helper for running jobs.

    Args:
        job (pyccc.Job): The job to run
        engine (pyccc.Engine): Engine to run this job on (default:
            ``moldesign.compute.get_engine()``)
        image (str): URL for the docker image
        wait (bool): if True, block until this function completes and return the function's
            return value. Otherwise, return a job object immediately that can be queried later.
        display (bool): if True, show logging output for this job

    Returns:
        pyccc job object OR function's return value
    """

    engine = utils.if_not_none(engine, mdt.compute.get_engine())

    if engine is None:
        raise ValueError('No compute engine configured! Configure MDT using '
                         'moldesign.compute.config')

    engine.submit(job)

    jobname = utils.if_not_none(jobname, job.name)

    if display:
        mdt.uibase.display_log(job.get_display_object(), jobname)

    if wait:
        job.wait()
        if _return_result: return job.result

    return job
        def wrapper(*args, **kwargs):
            """ Wraps a python function so that it will be executed remotely using a compute engine

            Note:
                At runtime, this documentation should be replaced with that of the wrapped function
            """
            # If the wrapper is not enabled, just run the wrapped function as normal.
            f = func  # keeps a reference to the original function in this closure
            if not wrapper.enabled:
                return f(*args, **kwargs)

            wait = kwargs.get('wait', True)

            # Bind instance methods to their objects
            if self.is_imethod:
                f, args = _bind_instance_method(f, args)

            # Submit job to remote engine
            python_call = bpy.PythonCall(f, *args, **kwargs)
            image = utils.if_not_none(self.image, configuration.config.default_python_image)
            engine = utils.if_not_none(self.engine, mdt.compute.get_engine())
            job = bpy.PythonJob(engine,
                                image,
                                python_call,
                                name=self.jobname,
                                sendsource=self.sendsource)

            if self.display:
                uibase.display_log(job.get_display_object(), title=f.__name__)

            if wait:
                job.wait()
                return job.result
            else:
                return job
示例#5
0
 def __init__(self,
              name,
              short_description=None,
              type=None,
              default=None,
              choices=None,
              select_multiple=False,
              help_url=None):
     """
     A method's parameter
     :param default: the default value. If this does not match any spec in choices, it must be set.
     :param choices: A list of allowable values for the parameter
     :param types: a list of types for the parameter (does not check choices if parameter is one of these types)
     :param number: Number of values (>1 should be passed in list). '+' indicates arbitrary list size
     :return:
     """
     self.name = name
     self.displayname = if_not_none(short_description, name)
     self.value = None
     self.default = default
     self.choices = if_not_none(choices, [])
     self.type = type
     self.help_url = help_url
     if isinstance(type, u.MdtQuantity):
         type = type.units
     if isinstance(type, u.MdtUnit):
         self.type = float
         self.units = type
     else:
         self.units = None
     self.select_multiple = select_multiple
示例#6
0
    def __init__(self, name=None, atnum=None, mass=None, chain=None, residue=None,
                 formal_charge=None, pdbname=None, pdbindex=None, element=None,
                 metadata=None):

        # Allow user to instantiate an atom as Atom(6) or Atom('C')
        if atnum is None and element is None:
            if isinstance(name, int):
                atnum = name
                name = None
            else: element = name

        if element: self.atnum = data.ATOMIC_NUMBERS[element]
        else: self.atnum = atnum

        self.name = utils.if_not_none(name, self.elem)
        self.pdbname = utils.if_not_none(pdbname, self.name)
        self.pdbindex = pdbindex

        if mass is None: self.mass = data.ATOMIC_MASSES[self.atnum]
        else: self.mass = mass

        self.formal_charge = utils.if_not_none(formal_charge, 0.0 * u.q_e)
        self.residue = residue
        self.chain = chain
        self.molecule = None
        self.index = None
        self._position = np.zeros(3) * u.default.length
        self._momentum = np.zeros(3) * (u.default.length*
                                       u.default.mass/u.default.time)
        self._bond_graph = {}
        self.metadata = mdt.utils.DotDict()
        if metadata:
            self.metadata.update(metadata)
 def __init__(self, mol, unit_system=None, first_frame=False, name=None):
     self._init = True
     self.info = "Trajectory"
     self.frames = []
     self.mol = mol
     self.unit_system = utils.if_not_none(unit_system, mdt.units.default)
     self.properties = utils.DotDict()
     self._reset()
     self._tempmol.dynamic_dof = self.mol.dynamic_dof
     self.name = utils.if_not_none(name, 'untitled')
     if first_frame: self.new_frame()
 def __init__(self, mol, unit_system=None, first_frame=False, name=None):
     self._init = True
     self.info = "Trajectory"
     self.frames = []
     self.mol = mol
     self.unit_system = utils.if_not_none(unit_system, mdt.units.default)
     self.properties = utils.DotDict()
     self._tempmol = mdt.Molecule(self.mol.atoms, copy_atoms=True)
     self._tempmol.dynamic_dof = self.mol.dynamic_dof
     self._viz = None
     self._atoms = None
     self.name = utils.if_not_none(name, 'untitled')
     if first_frame: self.new_frame()
def _antechamber_calc_charges(mol, ambname, chargename, kwargs):
    charge = utils.if_not_none(mol.charge, 0)
    command = 'antechamber -fi mol2 -i mol.mol2 -fo mol2 -o out.mol2 -c %s -an n'%ambname
    if charge != 0:
        command += ' -nc %d' % charge.value_in(u.q_e)

    def finish_job(job):
        """Callback to complete the job"""
        lines = iter(job.get_output('out.mol2').read().split('\n'))
        charges = utils.DotDict(type='atomic')

        line = lines.next()
        while line.strip()[:len('@<TRIPOS>ATOM')] != '@<TRIPOS>ATOM':
            line = lines.next()

        line = lines.next()
        while line.strip()[:len('@<TRIPOS>BOND')] != '@<TRIPOS>BOND':
            fields = line.split()
            idx = int(fields[0])-1
            assert mol.atoms[idx].name == fields[1]
            charges[mol.atoms[idx]] = u.q_e*float(fields[-1])
            line = lines.next()

        mol.properties[chargename] = charges
        return charges

    job = pyccc.Job(image=mdt.compute.get_image_path(IMAGE),
                    command=command,
                    name="%s, %s" % (chargename, mol.name),
                    inputs={'mol.mol2': mol.write(format='mol2')},
                    when_finished=finish_job)
    return compute.run_job(job, _return_result=True, **kwargs)
示例#10
0
def run_nbo(mol, requests=('nlmo', 'nbo'), image='nbo', engine=None):
    wfn = mol.wfn
    inputs = {'in.47': make_nbo_input_file(mol, requests)}
    command = 'gennbo.i4.exe in.47'
    engine = utils.if_not_none(engine, mdt.compute.config.get_engine())
    imagename = mdt.compute.get_image_path(image)
    job = engine.launch(imagename,
                        command,
                        inputs=inputs,
                        name="nbo, %s" % mol.name)
    moldesign.uibase.display_log(job.get_display_object(),
                                 "nbo, %s" % mol.name)

    job.wait()
    parsed_data = parse_nbo(job.get_output('FILE.10'), len(mol.wfn.aobasis))

    for orbtype, data in parsed_data.iteritems():
        if orbtype[0] == 'P':  # copy data from the orthogonal orbitals
            orthdata = parsed_data[orbtype[1:]]
            for key in 'bond_names iatom jatom stars bondnums num_bonded_atoms'.split(
            ):
                data[key] = orthdata[key]
            data.occupations = [None for orb in data.coeffs]

        add_orbitals(mol, wfn, data, orbtype)
    wfn._nbo_job = job
    def __init__(self, paramlist, paramdefs, title=None):
        super(Configurator, self).__init__(layout=ipy.Layout(display='flex',
                                                             flex_flow='column',
                                                             align_self='flex-start',
                                                             align_items='stretch',
                                                             max_width='100%'))
        self.paramlist = paramlist
        self.paramdefs = paramdefs

        self.apply_button = ipy.Button(description='Apply')
        self.apply_button.on_click(self.apply_values)

        self.reset_button = ipy.Button(description='Reset')
        self.reset_button.on_click(self.reset_values)
        self.buttons = ipy.Box([self.reset_button, self.apply_button],
                               layout=ipy.Layout(align_self='center'))

        self.selectors = collections.OrderedDict([(p.name, ParamSelector(p)) for p in paramdefs])
        self.reset_values()

        title = utils.if_not_none(title, 'Configuration')
        self.title = ipy.HTML('<center><h4>%s</h4></center><hr>' % title,
                              align_self='center')

        self.currentconfig = ipy.Textarea(description='Current params:',
                                          disabled=True,
                                          value=str(paramlist).replace(', ', ',\n   '),
                                          width='350px')
        self.middle = ipy.HBox([ipy.VBox(self.selectors.values()), self.currentconfig])
        self.children = [self.title, self.middle, self.buttons]
    def __init__(self, paramlist, paramdefs, title=None):
        super(Configurator, self).__init__(layout=ipy.Layout(display='flex',
                                                             flex_flow='column',
                                                             align_self='flex-start',
                                                             align_items='stretch',
                                                             max_width='100%'))
        self.paramlist = paramlist
        self.paramdefs = paramdefs

        self.apply_button = ipy.Button(description='Apply')
        self.apply_button.on_click(self.apply_values)

        self.reset_button = ipy.Button(description='Reset')
        self.reset_button.on_click(self.reset_values)
        self.buttons = ipy.Box([self.reset_button, self.apply_button],
                               layout=ipy.Layout(align_self='center'))

        self.selectors = collections.OrderedDict([(p.name, ParamSelector(p)) for p in paramdefs])
        self.reset_values()

        title = utils.if_not_none(title, 'Configuration')
        self.title = ipy.HTML('<center><h4>%s</h4></center><hr>' % title,
                              align_self='center')

        self.currentconfig = ipy.Textarea(description='<i>Current params</i>',
                                          disabled=True,
                                          value=self._pretty_print_config(),
                                          layout=ipy.Layout(width='350px', min_height='300px',
                                                            max_height='500px',
                                                            display='flex', flex_flow='column'))
        self.middle = HBox([VBox(list(self.selectors.values())), self.currentconfig])
        self.children = [self.title, self.middle, self.buttons]
def run_nbo(mol, requests=('nlmo', 'nbo'),
            image='nbo',
            engine=None):
    wfn = mol.wfn
    inputs = {'in.47': make_nbo_input_file(mol, requests)}
    command = 'gennbo.i4.exe in.47'
    engine = utils.if_not_none(engine, mdt.compute.config.get_engine())
    imagename = mdt.compute.get_image_path(image)
    job = engine.launch(imagename,
                          command,
                          inputs=inputs,
                          name="nbo, %s" % mol.name)
    moldesign.uibase.display_log(job.get_display_object(), "nbo, %s"%mol.name)

    job.wait()
    parsed_data = parse_nbo(job.get_output('FILE.10'),
                            len(mol.wfn.aobasis))

    for orbtype, data in parsed_data.iteritems():
        if orbtype[0] == 'P':  # copy data from the orthogonal orbitals
            orthdata = parsed_data[orbtype[1:]]
            for key in 'bond_names iatom jatom stars bondnums num_bonded_atoms'.split():
                data[key] = orthdata[key]
            data.occupations = [None for orb in data.coeffs]

        add_orbitals(mol, wfn, data, orbtype)
    wfn._nbo_job = job
示例#14
0
def am1_bcc_charges(mol, minsteps=None, wait=True):
    """ Doesn't work yet ..."""
    charge = utils.if_not_none(mol.charge, 0)

    engine = mdt.compute.get_engine()
    image = compute.get_image_path(IMAGE, engine)
    command = 'antechamber -fi pdb -i mol.pdb -fo mol2 -o out.mol2 -c bcc -an n'
    if charge != 0: command += ' -nc %d' % charge
    if minsteps is not None: command += ' -ek "maxcyc=%d"' % minsteps

    def parse_mol2(job):
        """Callback to complete the job"""
        atom_info = utils.DotDict(job=job)
        lines = iter(job.get_output('out.mol2').read().split('\n'))
        while True:
            line = lines.next()
            fields = line.split()
            if fields[0] == 'ATOM':
                idx = int(fields[1]) - 1
                name = fields[2]
                assert mol.atoms[idx].name == name
                atom_info[mol.atoms[idx]] = utils.DotDict(partialcharge=u.q_e *
                                                          float(fields[-2]),
                                                          atomtype=fields[-1])
        return atom_info

    job = engine.launch(image,
                        command=command,
                        name="am1-bcc, %s" % mol.name,
                        inputs={'mol.pdb': mol.write(format='pdb')},
                        when_finished=parse_mol2)
    uibase.display_log(job.get_display_object(), job.name)
    if not wait: return job()
    else: job.wait()
 def _highlight_atoms(self, atoms, color=None):
     color = utils.if_not_none(color, self.viewer.HIGHLIGHT_COLOR)
     self._highlighted_atoms += atoms
     self.viewer.add_style('vdw', atoms=atoms,
                           radius=self.viewer.ATOMRADIUS * 1.1,
                           color=color,
                           opacity=self.HIGHLIGHTOPACITY)
示例#16
0
def _antechamber_calc_charges(mol, ambname, chargename, kwargs):
    charge = utils.if_not_none(mol.charge, 0)
    command = 'antechamber -fi mol2 -i mol.mol2 -fo mol2 -o out.mol2 -c %s -an n' % ambname
    if charge != 0:
        command += ' -nc %d' % charge.value_in(u.q_e)

    def finish_job(job):
        """Callback to complete the job"""
        lines = iter(job.get_output('out.mol2').read().split('\n'))
        charges = utils.DotDict(type='atomic')

        line = lines.next()
        while line.strip()[:len('@<TRIPOS>ATOM')] != '@<TRIPOS>ATOM':
            line = lines.next()

        line = lines.next()
        while line.strip()[:len('@<TRIPOS>BOND')] != '@<TRIPOS>BOND':
            fields = line.split()
            idx = int(fields[0]) - 1
            assert mol.atoms[idx].name == fields[1]
            charges[mol.atoms[idx]] = u.q_e * float(fields[-1])
            line = lines.next()

        mol.properties[chargename] = charges
        return charges

    job = pyccc.Job(image=mdt.compute.get_image_path(IMAGE),
                    command=command,
                    name="%s, %s" % (chargename, mol.name),
                    inputs={'mol.mol2': mol.write(format='mol2')},
                    when_finished=finish_job)
    return compute.run_job(job, _return_result=True, **kwargs)
    def unset_color(self, atoms=None, _store=True):
        if _store:
            for atom in utils.if_not_none(atoms, self.mol.atoms):
                self._colored_as.pop(atom, None)

        result = super(GeometryViewer, self).unset_color(atoms=atoms)
        if self.atom_highlights: self._redraw_highlights()
        return result
    def unset_color(self, atoms=None, _store=True):
        if _store:
            for atom in utils.if_not_none(atoms, self.mol.atoms):
                self._colored_as.pop(atom, None)

        result = super(GeometryViewer, self).unset_color(atoms=atoms)
        if self.atom_highlights: self._redraw_highlights()
        return result
 def _highlight_atoms(self, atoms, color=None):
     color = utils.if_not_none(color, self.viewer.HIGHLIGHT_COLOR)
     self._highlighted_atoms += atoms
     self.viewer.add_style('vdw',
                           atoms=atoms,
                           radius=self.viewer.ATOMRADIUS * 1.1,
                           color=color,
                           opacity=self.HIGHLIGHTOPACITY)
    def __init__(self,
                 atomcontainer,
                 name=None,
                 bond_graph=None,
                 copy_atoms=False,
                 pdbname=None,
                 charge=0):
        # NEW_FEATURE: deal with random number generators per-geometry
        # NEW_FEATURE: per-geometry output logging
        super(Molecule, self).__init__()

        # copy atoms from another object (i.e., a molecule)
        oldatoms = helpers.get_all_atoms(atomcontainer)

        if copy_atoms or (oldatoms[0].molecule is not None):
            #print 'INFO: Copying atoms into new molecule'
            atoms = oldatoms.copy()
            if name is None:  # Figure out a reasonable name
                if oldatoms[0].molecule is not None:
                    name = oldatoms[0].molecule.name + ' copy'
                elif hasattr(atomcontainer, 'name') and isinstance(
                        atomcontainer.name, str):
                    name = utils.if_not_none(name,
                                             atomcontainer.name + ' copy')
                else:
                    name = 'unnamed'
        else:
            atoms = oldatoms

        self.atoms = atoms
        self.time = 0.0 * u.default.time
        self.name = 'uninitialized molecule'
        self._defres = None
        self._defchain = None
        self.pdbname = pdbname
        self.charge = charge
        self.constraints = []
        self.energy_model = None
        self.integrator = None

        # Builds the internal memory structures
        self.chains = Instance(molecule=self)
        self.residues = []
        self._rebuild_topology(bond_graph=bond_graph)

        if name is not None:
            self.name = name
        elif not self.is_small_molecule:
            self.name = 'unnamed macromolecule'
        else:
            self.name = self.get_stoichiometry()

        self._properties = MolecularProperties(self)
        self.ff = utils.DotDict()
 def __init__(self, mol, unit_system=None, first_frame=False):
     self._init = True
     self.info = "Trajectory"
     self.frames = []
     self.mol = mol
     self.unit_system = utils.if_not_none(unit_system, mdt.units.default)
     self._property_keys = None
     self._tempmol = mdt.Molecule(self.mol.atoms, copy_atoms=True)
     self._tempmol.dynamic_dof = self.mol.dynamic_dof
     self._viz = None
     self.atoms = [_TrajAtom(self, i) for i in xrange(self.mol.num_atoms)]
     if first_frame: self.new_frame()
def run_job(job,
            engine=None,
            image=None,
            wait=True,
            jobname=None,
            display=True,
            _return_result=False):
    """ Helper for running jobs.

    Args:
        job (pyccc.Job): The job to run
        engine (pyccc.Engine): Engine to run this job on (default:
            ``moldesign.compute.get_engine()``)
        image (str): URL for the docker image
        wait (bool): if True, block until this function completes and return the function's
            return value. Otherwise, return a job object immediately that can be queried later.
        display (bool): if True, show logging output for this job

    Returns:
        pyccc job object OR function's return value
    """

    engine = utils.if_not_none(engine, mdt.compute.get_engine())

    if engine is None:
        raise ValueError('No compute engine configured! Configure MDT using '
                         'moldesign.compute.config')

    engine.submit(job)

    jobname = utils.if_not_none(jobname, job.name)

    if display:
        mdt.uibase.display_log(job.get_display_object(), jobname)

    if wait:
        job.wait()
        if _return_result: return job.result

    return job
示例#23
0
 def __init__(self, name,
              short_description=None,
              type=None,
              default=None,
              choices=None,
              help_url=None,
              relevance=None):
     self.name = name
     self.displayname = utils.if_not_none(short_description, name)
     self.value = None
     self.default = default
     self.choices = utils.if_not_none(choices, [])
     self.type = type
     self.help_url = help_url
     if isinstance(type, u.MdtQuantity):
         type = type.units
     if isinstance(type, u.MdtUnit):
         self.type = float
         self.units = type
     else:
         self.units = None
     self.relevance = relevance
    def rotate(self, angle, axis, center=None):
        """Rotate this object in 3D space

        Args:
            angle (u.Scalar[angle]): angle to rotate by
            axis (u.Vector[length]): axis to rotate about (len=3)
            center (u.Vector[length]): center of rotation (len=3) (default: origin)
        """
        center = utils.if_not_none(center, self.com)

        if hasattr(angle, 'units'): angle = angle.value_in(u.radians)
        rotmat = external.transformations.rotation_matrix(angle, axis, point=center)
        self.transform(rotmat)
示例#25
0
    def __init__(self,
                 name=None,
                 atnum=None,
                 mass=None,
                 chain=None,
                 residue=None,
                 formal_charge=None,
                 pdbname=None,
                 pdbindex=None,
                 element=None):

        # Allow user to instantiate an atom as Atom(6) or Atom('C')
        if atnum is None and element is None:
            if isinstance(name, int):
                atnum = name
                name = None
            else:
                element = name

        if element: self.atnum = data.ATOMIC_NUMBERS[element]
        else: self.atnum = atnum

        self.name = utils.if_not_none(name, self.elem)
        self.pdbname = utils.if_not_none(pdbname, self.name)
        self.pdbindex = pdbindex

        if mass is None: self.mass = data.ATOMIC_MASSES[self.atnum]
        else: self.mass = mass

        self.formal_charge = utils.if_not_none(formal_charge, 0.0 * u.q_e)
        self.residue = residue
        self.chain = chain
        self.molecule = None
        self.index = None
        self._position = np.zeros(3) * u.default.length
        self._momentum = np.zeros(3) * (u.default.length * u.default.mass /
                                        u.default.time)
        self._bond_graph = {}
示例#26
0
    def rotate(self, angle, axis, center=None):
        """Rotate this object in 3D space

        Args:
            angle (u.Scalar[angle]): angle to rotate by
            axis (u.Vector[length]): axis to rotate about (len=3)
            center (u.Vector[length]): center of rotation (len=3) (default: origin)
        """
        center = utils.if_not_none(center, self.com)

        if hasattr(angle, 'units'): angle = angle.value_in(u.radians)
        rotmat = external.transformations.rotation_matrix(angle,
                                                          axis,
                                                          point=center)
        self.transform(rotmat)
示例#27
0
def name_to_smiles(name,
                   image='opsin',
                   engine=None):

    command = 'opsin -osmi input.txt output.txt'

    # TODO: this boilerplate has to go
    engine = utils.if_not_none(engine, mdt.compute.get_engine())
    imagename = mdt.compute.get_image_path(image)
    job = engine.launch(imagename,
                          command,
                          inputs={'input.txt': name + '\n'},
                          name="opsin, %s" % name)
    mdt.uibase.display_log(job.get_display_object(), "opsin, %s"%name)
    job.wait()
    return job.get_output('output.txt').read().strip()
 def _get_initializing_atoms(self, atomcontainer, name, copy_atoms):
     """ Make a copy of the passed atoms as necessary, return the name of the molecule
     """
     # copy atoms from another object (i.e., a molecule)
     oldatoms = helpers.get_all_atoms(atomcontainer)
     if copy_atoms or (oldatoms[0].molecule is not None):
         atoms = oldatoms.copy_atoms()
         if name is None:  # Figure out a reasonable name
             if oldatoms[0].molecule is not None:
                 name = oldatoms[0].molecule.name+' copy'
             elif hasattr(atomcontainer, 'name') and isinstance(atomcontainer.name, str):
                 name = utils.if_not_none(name, atomcontainer.name+' copy')
             else:
                 name = 'unnamed'
     else:
         atoms = oldatoms
     return atoms, name
示例#29
0
 def _get_initializing_atoms(self, atomcontainer, name, copy_atoms):
     """ Make a copy of the passed atoms as necessary, return the name of the molecule
     """
     # copy atoms from another object (i.e., a molecule)
     oldatoms = helpers.get_all_atoms(atomcontainer)
     if copy_atoms or (oldatoms[0].molecule is not None):
         atoms = oldatoms.copy()
         if name is None:  # Figure out a reasonable name
             if oldatoms[0].molecule is not None:
                 name = oldatoms[0].molecule.name+' copy'
             elif hasattr(atomcontainer, 'name') and isinstance(atomcontainer.name, str):
                 name = utils.if_not_none(name, atomcontainer.name+' copy')
             else:
                 name = 'unnamed'
     else:
         atoms = oldatoms
     return atoms, name
示例#30
0
    def colormap(self,
                 atomvalues,
                 atoms=None,
                 mplmap='auto',
                 categorical=None,
                 save=True):
        """ Color atoms according to categorical or numeric data

        Args:
            atomvalues (callable OR list or str): Either:
              - a callable that takes an atom and the data,
              - a list of values of each atom
              - the name of an atomic property (e.g., 'residue' or 'mass')
            atoms (moldesign.molecules.AtomContainer): atoms to color (default: self.mol.atoms)
            mplmap (str): name of the matplotlib colormap to use if colors aren't explicitly
               specified)
            categorical (bool): If None (the default), automatically detect whether the
               data is categorical or numerical. Otherwise, use this flag to force
               interpretation of the data as categorical (True) or numerical (False)
            save (bool): permanently color theses atoms this way (until self.unset_color is called)


        Returns:
            dict: mapping of categories to colors
        """
        atoms = utils.if_not_none(atoms, self.mol.atoms)
        if isinstance(atomvalues, basestring):
            # shortcut to use strings to access atom attributes, i.e. "ff.partial_charge"
            attrs = atomvalues.split('.')
            atomvalues = []
            for atom in atoms:
                obj = atom
                for attr in attrs:
                    obj = getattr(obj, attr)
                atomvalues.append(obj)

        elif callable(atomvalues):
            atomvalues = list(map(atomvalues, atoms))

        colors = colormaps.colormap(atomvalues,
                                    mplmap=mplmap,
                                    categorical=categorical)
        self.set_colors(colors, atoms=atoms, save=save)

        return {v: c for v, c in zip(atomvalues, colors)}
示例#31
0
    def _build_theories(self):
        if self.params.theory in self.NEEDS_REFERENCE:
            scf_ref = if_not_none(self.params.scf_reference, 'rhf')
            reference = self.THEORIES[scf_ref](self.pyscfmol)
            if 'scf_cycles' in self.params:
                reference.max_cycle = self.params.scf_cycles
            reference.callback = StatusLogger(
                '%s/%s reference procedure:' % (scf_ref, self.params.basis),
                ['cycle', 'e_tot'], self.logger)
        else:
            reference = None

        theory = self.THEORIES[self.params.theory](self.pyscfmol)
        theory.callback = StatusLogger(
            '%s/%s procedure:' % (self.params.theory, self.params.basis),
            ['cycle', 'e_tot'], self.logger)

        if 'scf_cycles' in self.params:
            theory.max_cycle = self.params.scf_cycles
        return theory, reference
def mol_to_pyscf(mol, basis, symmetry=None, charge=0, positions=None):
    """Convert an MDT molecule to a PySCF "Mole" object"""
    pyscfmol = gto.Mole()

    positions = if_not_none(positions, mol.atoms.position)
    pyscfmol.atom = [[atom.elem, pos.value_in(u.angstrom)]
                     for atom, pos in zip(mol.atoms, positions)]
    pyscfmol.basis = basis
    pyscfmol.charge = charge
    if symmetry is not None:
        pyscfmol.symmetry = symmetry
    with redirect_stderr(StringIO()) as builderr:
        pyscfmol.build()
    builderr.seek(0)
    for line in builderr:
        if line.strip() == 'Warn: Ipython shell catchs sys.args':
            continue
        else:
            print 'PYSCF: ' + line
    return pyscfmol
示例#33
0
    def calc_distance_array(self, other=None):
        """ Calculate an array of pairwise distance between all atoms in self and other

        Args:
            other (AtomContainer): object to calculate distances to (default: self)

        Returns:
            u.Array[length]: 2D array of pairwise distances between the two objects

        Example:
            >>> dists = self.calc_distance_array(other)
            >>> dists[i, j] == self.atoms[i].distance(other.atoms[j])
        """
        other = utils.if_not_none(other, self)
        try:
            other_positions = other.positions.value_in(u.ang)
        except AttributeError:
            other_positions = np.array([other.position.value_in(u.ang)])

        distances = spd.cdist(self.position.value_in(u.ang), other_positions)
        return distances * u.ang
    def highlight_atoms(self, atoms=None):
        """

        Args:
            atoms (list[Atoms]): list of atoms to highlight. If None, remove all highlights
        """
        # TODO: Need to handle style changes
        if self.atom_highlights:  # first, unhighlight old highlights
            to_unset = []
            for atom in self.atom_highlights:
                if atom in self._colored_as: self.set_color(atoms=[atom],
                                                            color=self._colored_as[atom],
                                                            _store=False)
                else:
                    to_unset.append(atom)

            if to_unset:
                self.atom_highlights = []
                self.unset_color(to_unset, _store=False)

        self.atom_highlights = utils.if_not_none(atoms, [])
        self._redraw_highlights()
    def colormap(self, atomvalues, atoms=None, mplmap='auto', categorical=None, save=True):
        """ Color atoms according to categorical or numeric data

        Args:
            atomvalues (callable OR list or str): Either:
              - a callable that takes an atom and the data,
              - a list of values of each atom
              - the name of an atomic property (e.g., 'residue' or 'mass')
            atoms (moldesign.molecules.AtomContainer): atoms to color (default: self.mol.atoms)
            mplmap (str): name of the matplotlib colormap to use if colors aren't explicitly
               specified)
            categorical (bool): If None (the default), automatically detect whether the
               data is categorical or numerical. Otherwise, use this flag to force
               interpretation of the data as categorical (True) or numerical (False)
            save (bool): permanently color theses atoms this way (until self.unset_color is called)


        Returns:
            dict: mapping of categories to colors
        """
        atoms = utils.if_not_none(atoms, self.mol.atoms)
        if isinstance(atomvalues, basestring):
            # shortcut to use strings to access atom attributes, i.e. "ff.partial_charge"
            attrs = atomvalues.split('.')
            atomvalues = []
            for atom in atoms:
                obj = atom
                for attr in attrs:
                    obj = getattr(obj, attr)
                atomvalues.append(obj)

        elif callable(atomvalues):
            atomvalues = list(map(atomvalues, atoms))

        colors = colormaps.colormap(atomvalues, mplmap=mplmap, categorical=categorical)
        self.set_colors(colors, atoms=atoms, save=save)

        return {v:c for v,c in zip(atomvalues, colors)}
    def calc_distance_array(self, other=None):
        """ Calculate an array of pairwise distance between all atoms in self and other

        Args:
            other (AtomContainer): object to calculate distances to (default: self)

        Returns:
            u.Array[length]: 2D array of pairwise distances between the two objects

        Example:
            >>> dists = self.calc_distance_array(other)
            >>> dists[i, j] == self.atoms[i].distance(other.atoms[j])
        """
        from scipy.spatial.distance import cdist

        other = utils.if_not_none(other, self)
        try:
            other_positions = other.positions.defunits_value()
        except AttributeError:
            other_positions = np.array([other.position.defunits_value()])

        distances = cdist(self.positions.defunits_value(), other_positions)
        return distances * u.default.length
    def highlight_atoms(self, atoms=None):
        """ Highlight a subset of atoms in the system

        Args:
            atoms (list[Atoms]): list of atoms to highlight. If None, remove all highlights
        """
        # TODO: Need to handle style changes
        if self.atom_highlights:  # first, unhighlight old highlights
            to_unset = []
            for atom in self.atom_highlights:
                if atom in self._colored_as:
                    self.set_color(atoms=[atom],
                                   color=self._colored_as[atom],
                                   _store=False)
                else:
                    to_unset.append(atom)

            if to_unset:
                self.atom_highlights = []
                self.unset_color(to_unset, _store=False)

        self.atom_highlights = utils.if_not_none(atoms, [])
        self._redraw_highlights()
def run_symmol(mol,
               tolerance=0.1 * u.angstrom,
               image='symmol',
               engine=None):
    infile = ['1.0 1.0 1.0 90.0 90.0 90.0',  # line 1: indicates XYZ coordinates
              # line 2: numbers indicate: mass weighted moment of inertia,
              #         tolerance interpretation, tolerance value,
              #         larger tolerance value (not used)
              '1 0 %f 0.0' % tolerance.value_in(u.angstrom)]
    for atom in mol.atoms:
        infile.append(line_writer.write((atom.element, 1,
                                         atom.x.value_in(u.angstrom),
                                         atom.y.value_in(u.angstrom),
                                         atom.z.value_in(u.angstrom),
                                         0.0, 0.0, 0.0)))
    infile.append('')
    command = 'symmol < sym.in'
    inputs = {'sym.in': '\n'.join(infile)}

    # TODO: this boilerplate has to go
    engine = utils.if_not_none(engine, mdt.compute.get_engine())
    imagename = mdt.compute.get_image_path(image)
    job = engine.launch(imagename,
                          command,
                          inputs=inputs,
                          name="symmol, %s" % mol.name)
    mdt.uibase.display_log(job.get_display_object(), "symmol, %s"%mol.name)
    job.wait()

    data = parse_output(job.get_output('symmol.out'))
    symm = mdt.geom.MolecularSymmetry(
            mol, data.symbol, data.rms,
            orientation=get_aligned_coords(mol, data),
            elems=data.elems,
            job=job)
    return symm
    def highlight_atoms(self, atoms=None, render=True):
        """

        Args:
            atoms (list[Atoms]): list of atoms to highlight. If None, remove all highlights
            render (bool): render this change immediately
        """
        # TODO: Need to handle style changes
        if self.atom_highlights:  # first, unhighlight old highlights
            to_unset = []
            for atom in self.atom_highlights:
                if atom in self._colored_as: self.set_color(atoms=[atom],
                                                            color=self._colored_as[atom],
                                                            _store=False,
                                                            render=False)
                else:
                    to_unset.append(atom)

            if to_unset:
                self.atom_highlights = []
                self.unset_color(to_unset, _store=False, render=False)

        self.atom_highlights = utils.if_not_none(atoms, [])
        self._redraw_highlights(render=render)
示例#40
0
def run_symmol(mol, tolerance=0.1 * u.angstrom, image='symmol', engine=None):
    infile = [
        '1.0 1.0 1.0 90.0 90.0 90.0',  # line 1: indicates XYZ coordinates
        # line 2: numbers indicate: mass weighted moment of inertia,
        #         tolerance interpretation, tolerance value,
        #         larger tolerance value (not used)
        '1 0 %f 0.0' % tolerance.value_in(u.angstrom)
    ]
    for atom in mol.atoms:
        infile.append(
            line_writer.write((atom.element, 1, atom.x.value_in(u.angstrom),
                               atom.y.value_in(u.angstrom),
                               atom.z.value_in(u.angstrom), 0.0, 0.0, 0.0)))
    infile.append('')
    command = 'symmol < sym.in'
    inputs = {'sym.in': '\n'.join(infile)}

    # TODO: this boilerplate has to go
    engine = utils.if_not_none(engine, mdt.compute.get_engine())
    imagename = mdt.compute.get_image_path(image)
    job = engine.launch(imagename,
                        command,
                        inputs=inputs,
                        name="symmol, %s" % mol.name)
    mdt.uibase.display_log(job.get_display_object(), "symmol, %s" % mol.name)
    job.wait()

    data = parse_output(job.get_output('symmol.out'))
    symm = mdt.geom.MolecularSymmetry(mol,
                                      data.symbol,
                                      data.rms,
                                      orientation=get_aligned_coords(
                                          mol, data),
                                      elems=data.elems,
                                      job=job)
    return symm
示例#41
0
def _parse_tleap_errors(job, molin):
    from moldesign.widgets.parameterization import (UnusualBond, UnknownAtom,
                                                    UnknownResidue,
                                                    MissingTerms)

    # TODO: special messages for known problems (e.g. histidine)
    msg = []
    unknown_res = set()  # so we can print only one error per unkonwn residue
    lineiter = iter(job.stdout.split('\n'))
    offset = utils.if_not_none(molin.residues[0].pdbindex, 1)
    reslookup = {str(i + offset): r for i, r in enumerate(molin.residues)}

    def _atom_from_re(s):
        resname, residx, atomname, atomidx = s
        r = reslookup[residx]
        a = r[atomname]
        return a

    def unusual_bond(l):
        atomre1, atomre2 = ATOMSPEC.findall(l)
        try:
            a1, a2 = _atom_from_re(atomre1), _atom_from_re(atomre2)
        except KeyError:
            a1 = a2 = None
        r1 = reslookup[atomre1[1]]
        r2 = reslookup[atomre2[1]]
        return UnusualBond(l, (a1, a2), (r1, r2))

    while True:
        try:
            line = lineiter.next()
        except StopIteration:
            break

        fields = line.split()
        if fields[0:2] == ['Unknown', 'residue:']:
            # EX: "Unknown residue: 3TE   number: 499   type: Terminal/beginning"
            res = molin.residues[int(fields[4])]
            unknown_res.add(res)
            msg.append(UnknownResidue(line, res))

        elif fields[:4] == 'Warning: Close contact of'.split():
            # EX: "Warning: Close contact of 1.028366 angstroms between .R<DC5 1>.A<HO5' 1> and .R<DC5 81>.A<P 9>"
            msg.append(unusual_bond(line))

        elif fields[:6] == 'WARNING: There is a bond of'.split():
            # Matches two lines, EX:
            # "WARNING: There is a bond of 34.397700 angstroms between:"
            # "-------  .R<DG 92>.A<O3' 33> and .R<DG 93>.A<P 1>"
            nextline = lineiter.next()
            msg.append(unusual_bond(line + nextline))

        elif fields[:5] == 'Created a new atom named:'.split():
            # EX: "Created a new atom named: P within residue: .R<DC5 81>"
            residue = reslookup[fields[-1][:-1]]
            if residue in unknown_res:
                continue  # suppress atoms from an unknown res ...
            atom = residue[fields[5]]
            msg.append(UnknownAtom(line, residue, atom))

        elif (fields[:5] == '** No torsion terms for'.split()
              or fields[:5] == 'Could not find angle parameter:'.split()):
            # EX: " ** No torsion terms for  ca-ce-c3-hc"
            msg.append(MissingTerms(line.strip()))

    return msg
def _parse_tleap_errors(job, molin):
    from moldesign.widgets.parameterization import (UnusualBond, UnknownAtom,
                                                    UnknownResidue, MissingTerms)

    # TODO: special messages for known problems (e.g. histidine)
    msg = []
    unknown_res = set()  # so we can print only one error per unkonwn residue
    lineiter = iter(job.stdout.split('\n'))
    offset = utils.if_not_none(molin.residues[0].pdbindex, 1)
    reslookup = {str(i+offset): r for i,r in enumerate(molin.residues)}

    def _atom_from_re(s):
        resname, residx, atomname, atomidx = s
        r = reslookup[residx]
        a = r[atomname]
        return a

    def unusual_bond(l):
        atomre1, atomre2 = ATOMSPEC.findall(l)
        try:
            a1, a2 = _atom_from_re(atomre1), _atom_from_re(atomre2)
        except KeyError:
            a1 = a2 = None
        r1 = reslookup[atomre1[1]]
        r2 = reslookup[atomre2[1]]
        return UnusualBond(l, (a1, a2), (r1, r2))

    while True:
        try:
            line = lineiter.next()
        except StopIteration:
            break

        fields = line.split()
        if fields[0:2] == ['Unknown', 'residue:']:
            # EX: "Unknown residue: 3TE   number: 499   type: Terminal/beginning"
            res = molin.residues[int(fields[4])]
            unknown_res.add(res)
            msg.append(UnknownResidue(line, res))

        elif fields[:4] == 'Warning: Close contact of'.split():
            # EX: "Warning: Close contact of 1.028366 angstroms between .R<DC5 1>.A<HO5' 1> and .R<DC5 81>.A<P 9>"
            msg.append(unusual_bond(line))

        elif fields[:6] == 'WARNING: There is a bond of'.split():
            # Matches two lines, EX:
            # "WARNING: There is a bond of 34.397700 angstroms between:"
            # "-------  .R<DG 92>.A<O3' 33> and .R<DG 93>.A<P 1>"
            nextline = lineiter.next()
            msg.append(unusual_bond(line + nextline))

        elif fields[:5] == 'Created a new atom named:'.split():
            # EX: "Created a new atom named: P within residue: .R<DC5 81>"
            residue = reslookup[fields[-1][:-1]]
            if residue in unknown_res: continue  # suppress atoms from an unknown res ...
            atom = residue[fields[5]]
            msg.append(UnknownAtom(line, residue, atom))

        elif (fields[:5] == '** No torsion terms for'.split() or
                      fields[:5] == 'Could not find angle parameter:'.split()):
            # EX: " ** No torsion terms for  ca-ce-c3-hc"
            msg.append(MissingTerms(line.strip()))

    return msg
 def set_color(self, color, atoms=None, _store=True):
     if _store:
         for atom in utils.if_not_none(atoms, self.mol.atoms):
             self._colored_as[atom] = color
     return super(GeometryViewer, self).set_color(color, atoms=atoms)
示例#44
0
    def color_by(self, atom_callback, atoms=None, mplmap='auto', force_cmap=False):
        """
        Color atoms according to either:
          * an atomic attribute (e.g., 'chain', 'residue', 'mass')
          * a callback function that accepts an atom and returns a color or a category

        Args:
            atom_callback (callable OR str): callable f(atom) returns color OR
                category OR an atom attribute (e.g., ``atnum, mass, residue.type``)
            atoms (moldesign.molecules.AtomContainer): atoms to color (default: self.atoms)
            mplmap (str): name of the matplotlib colormap to use if colors aren't explicitly
               specified)
            force_cmap (bool): force the use of a colormap

        Notes:
            If you'd like to explicitly specify colors, the callback can return color
            specifications as an HTML string (``'#1234AB'``), a hexadecimal integer (
            ``0x12345AB``), or a CSS3 color keyword (``'green'``, ``'purple'``, etc., see
            https://developer.mozilla.org/en-US/docs/Web/CSS/color_value)

            If the callback returns an integer, it may be interpreted as a color spec (since RGB
            colors are just hexadecimal integers). Use ``force_cmap=True`` to force the creation
            of a colormap.

        Returns:
            dict: mapping of categories to colors
        """
        atoms = utils.if_not_none(atoms, self.mol.atoms)
        if isinstance(atom_callback, basestring):
            # shortcut to use strings to access atom attributes, i.e. "ff.partial_charge"
            attrs = atom_callback.split('.')

            # make sure that whatever value is returned doesn't get interpreted as a color
            force_cmap = True

            def atom_callback(atom):
                obj = atom
                for attr in attrs:
                    obj = getattr(obj, attr)
                return obj

        colors = utils.Categorizer(atom_callback, atoms)

        if force_cmap:
            name_is_color = [False]
        else:
            name_is_color = map(utils.is_color, colors.keys())

        if len(colors) <= 1:
            colors = {'gray': atoms}

        elif not all(name_is_color):
            assert not any(name_is_color), \
                "callback function returned a mix of colors and categories"
            categories = colors
            cats = categories.keys()
            # If there are >256 categories, this is a many-to-one mapping
            colornames = colormap(cats, mplmap=mplmap)
            colors = {c: [] for c in colornames}
            for cat, color in zip(cats, colornames):
                colors[color].extend(categories[cat])

        self.set_colors(colors)
    def color_by(self,
                 atom_callback,
                 atoms=None,
                 mplmap='auto',
                 force_cmap=False):
        """
        Color atoms according to either:
          * an atomic attribute (e.g., 'chain', 'residue', 'mass')
          * a callback function that accepts an atom and returns a color or a category

        Args:
            atom_callback (callable OR str): callable f(atom) returns color OR
                category OR an atom attribute (e.g., ``atnum, mass, residue.type``)
            atoms (moldesign.molecules.AtomContainer): atoms to color (default: self.atoms)
            mplmap (str): name of the matplotlib colormap to use if colors aren't explicitly
               specified)
            force_cmap (bool): force the use of a colormap

        Notes:
            If you'd like to explicitly specify colors, the callback can return color
            specifications as an HTML string (``'#1234AB'``), a hexadecimal integer (
            ``0x12345AB``), or a CSS3 color keyword (``'green'``, ``'purple'``, etc., see
            https://developer.mozilla.org/en-US/docs/Web/CSS/color_value)

            If the callback returns an integer, it may be interpreted as a color spec (since RGB
            colors are just hexadecimal integers). Use ``force_cmap=True`` to force the creation
            of a colormap.

        Returns:
            dict: mapping of categories to colors
        """
        atoms = utils.if_not_none(atoms, self.mol.atoms)
        if isinstance(atom_callback, basestring):
            # shortcut to use strings to access atom attributes, i.e. "ff.partial_charge"
            attrs = atom_callback.split('.')

            # make sure that whatever value is returned doesn't get interpreted as a color
            force_cmap = True

            def atom_callback(atom):
                obj = atom
                for attr in attrs:
                    obj = getattr(obj, attr)
                return obj

        colors = utils.Categorizer(atom_callback, atoms)

        if force_cmap:
            name_is_color = [False]
        else:
            name_is_color = map(utils.is_color, colors.keys())

        if len(colors) <= 1:
            colors = {'gray': atoms}

        elif not all(name_is_color):
            assert not any(name_is_color), \
                "callback function returned a mix of colors and categories"
            categories = colors
            cats = categories.keys()
            # If there are >256 categories, this is a many-to-one mapping
            colornames = colormap(cats, mplmap=mplmap)
            colors = {c: [] for c in colornames}
            for cat, color in zip(cats, colornames):
                colors[color].extend(categories[cat])

        self.set_colors(colors)
 def set_color(self, color, atoms=None, _store=True):
     if _store:
         for atom in utils.if_not_none(atoms, self.mol.atoms):
             self._colored_as[atom] = color
     return super(GeometryViewer, self).set_color(color, atoms=atoms)