Пример #1
0
 def _process_subdialog(self, sd_type):
     sd = self.subdialogs[sd_type]
     from chimerax.core.commands import run
     if sd_type == "H-Bonds":
         cmd_name, spec, args = sd.hbonds_gui.get_command()
         res = self.mgr.base_residue
         base_spec = "#!%s & ~%s" % (res.structure.id_string,
                                     res.string(style="command"))
         if self.ignore_solvent_button.isChecked():
             base_spec += " & ~solvent"
         hbs = run(
             self.session, "%s %s %s restrict #%s & ~@c,ca,n" %
             (cmd_name, base_spec, args, self.mgr.group.id_string))
         AtomicStructure.register_attr(self.session,
                                       "num_hbonds",
                                       self.registerer,
                                       attr_type=int)
         for rotamer in self.mgr.rotamers:
             rotamer.num_hbonds = 0
         for d, a in hbs:
             if d.structure == res.structure:
                 a.structure.num_hbonds += 1
             else:
                 d.structure.num_hbonds += 1
         if sd_type in self.opt_columns:
             self.table.update_column(self.opt_columns[sd_type], data=True)
         else:
             self.opt_columns[sd_type] = self.table.add_column(sd_type,
                                                               "num_hbonds",
                                                               format="%d")
     elif sd_type == "Clashes":
         cmd_name, spec, args = sd.clashes_gui.get_command()
         res = self.mgr.base_residue
         base_spec = "#!%s & ~%s" % (res.structure.id_string,
                                     res.string(style="command"))
         if self.ignore_solvent_button.isChecked():
             base_spec += " & ~solvent"
         clashes = run(
             self.session, "%s %s %s restrict #%s & ~@c,ca,n" %
             (cmd_name, base_spec, args, self.mgr.group.id_string))
         AtomicStructure.register_attr(self.session,
                                       "num_clashes",
                                       self.registerer,
                                       attr_type=int)
         for rotamer in self.mgr.rotamers:
             rotamer.num_clashes = 0
         for a, clashing in clashes.items():
             if a.structure != res.structure:
                 a.structure.num_clashes += len(clashing)
         if sd_type in self.opt_columns:
             self.table.update_column(self.opt_columns[sd_type], data=True)
         else:
             self.opt_columns[sd_type] = self.table.add_column(
                 sd_type, "num_clashes", format="%d")
     else:  # Density
         vol = sd.vol_list.value
         if not vol:
             return
         self._eval_vol(vol)
     self._update_button_text()
Пример #2
0
 def take_snapshot(self, session, flags):
     data = {
         'version':
         1,
         'atomic structure state':
         AtomicStructure.take_snapshot(self, session, flags)
     }
     return data
Пример #3
0
def duplicate(session, selection, newModel=True):
    # dict for unique models, residues, and atoms
    models = {}
    # dict for just models and atoms
    atom_list = {}
    for atom in selection:
        if atom.structure not in models:
            models[atom.structure] = {}
            atom_list[atom.structure] = []

        if atom.residue not in models[atom.structure]:
            models[atom.structure][atom.residue] = []

        models[atom.structure][atom.residue].append(atom)
        atom_list[atom.structure].append(atom)

    for model in models:
        if newModel:
            struc = AtomicStructure(session,
                                    name="copy of %s" % model.atomspec)
        else:
            struc = model
            offset = len(model.atoms)
        for res in models[model]:
            residue = struc.new_residue(res.name, res.chain_id, res.number)
            for atom in models[model][res]:
                dup_atom = struc.new_atom(atom.name, atom.element)
                dup_atom.coord = atom.coord
                dup_atom.serial_number = len(struc.atoms)
                res.add_atom(dup_atom)

        for i, atom1 in enumerate(atom_list[model]):
            atom1.selected = False
            if newModel:
                struc.atoms[i].selected = True
                struc.atoms[i].color = atom1.color
                struc.atoms[i].radius = atom1.radius
                struc.atoms[i].draw_mode = atom1.draw_mode
            else:
                struc.atoms[i + offset].selected = True
                struc.atoms[i + offset].color = atom1.color
                struc.atoms[i + offset].radius = atom1.radius
                struc.atoms[i + offset].draw_mode = atom1.draw_mode

            for j, atom2 in enumerate(atom_list[model][:i]):
                if atom2 in atom1.neighbors:
                    if newModel:
                        struc.new_bond(struc.atoms[i], struc.atoms[j])
                    else:
                        struc.new_bond(struc.atoms[i + offset],
                                       struc.atoms[j + offset])

        if newModel:
            session.models.add([struc])

    session.triggers.activate_trigger(SELECTION_CHANGED, None)
Пример #4
0
def _read_block(session, stream):
    # First line should be an integer count of the number of
    # atoms in the block.  Each block gets turned into an
    # AtomicStructure instance.
    count_line = stream.readline()
    if not count_line:
        return None
    try:
        count = int(count_line)
    except ValueError:
        # XXX: Should emit an error message
        return None
    from chimerax.atomic import AtomicStructure
    s = AtomicStructure(session)

    # Next line is a comment line
    s.comment = stream.readline().strip()

    # There should be "count" lines of atoms.
    from numpy import array, float64
    residue = s.new_residue("UNK", 'A', 1)
    element_count = {}
    for n in range(count):
        atom_line = stream.readline()
        if not atom_line:
            # XXX: Should emit an error message
            return None
        parts = atom_line.split()
        if len(parts) != 4:
            # XXX: Should emit an error message
            return None
        # Extract available data
        element = parts[0]
        xyz = [float(v) for v in parts[1:]]

        # Convert to required initializers
        # XXX: May need to convert element to usable form
        n = element_count.get(element, 0) + 1
        name = element + str(n)
        element_count[element] = n

        # Create atom
        atom = s.new_atom(name, element)
        atom.coord = array(xyz, dtype=float64)
        residue.add_atom(atom)
    s.connect_structure()
    s.new_atoms()  # tell structure it needs to update
    return s
Пример #5
0
 def _eval_vol(self, vol):
     AtomicStructure.register_attr(self.session,
                                   "sum_density",
                                   self.registerer,
                                   attr_type=float)
     for rot in self.mgr.rotamers:
         values = vol.interpolated_values(rot.atoms.coords,
                                          point_xform=rot.scene_position)
         total = 0
         for a, val in zip(rot.atoms, values):
             # 'is_side_chain' only works for actual polymers
             if a.name not in a.residue.aa_max_backbone_names:
                 total += val
         rot.sum_density = total
     sd_type = "Density"
     if sd_type in self.opt_columns:
         self.table.update_column(self.opt_columns[sd_type], data=True)
     else:
         self.opt_columns[sd_type] = self.table.add_column(sd_type,
                                                           "sum_density",
                                                           format="%g")
Пример #6
0
def open_pdb(session,
             stream,
             file_name,
             *,
             auto_style=True,
             coordsets=False,
             atomic=True,
             max_models=None,
             log_info=True,
             combine_sym_atoms=True):
    from chimerax.atomic import AtomicStructure
    return [AtomicStructure(session, name="test model")], 'message'
Пример #7
0
def open_mmcif(session,
               path,
               file_name=None,
               auto_style=True,
               coordsets=False,
               atomic=True,
               max_models=None,
               log_info=True,
               extra_categories=(),
               combine_sym_atoms=True):
    from chimerax.atomic import AtomicStructure
    return [AtomicStructure(session, name="test model")], 'message'
Пример #8
0
def make_gaussian_cube_atoms(session):
    from chimerax.map import Volume
    from chimerax.map_data.gaussian.gaussian_grid import GaussianGrid
    glist = [m.data for m in session.models
             if isinstance(m, Volume) and isinstance(m.data, GaussianGrid)]
    slist = []
    for g in glist:
        atoms = g.gc.atoms
        if atoms:
            from chimerax.atomic import AtomicStructure, Element
            s = AtomicStructure(session)
            r = s.new_residue('UNK', 'A', 1)
            for i, (n,q,x,y,z) in enumerate(atoms):
                e = Element.get_element(n)
                a = s.new_atom(e.name, e)
                b = bohr_radius = 0.5291772108      # Angstroms
                a.coord = (b*x,b*y,b*z)
                a.serial_number = i
                r.add_atom(a)
            s.connect_structure()
            slist.append(s)

    session.models.add(slist)
    session.logger.info('Created %d atomic models for %d Gaussian Cube files'
                        % (len(slist), len(glist)))
Пример #9
0
    def get_chimera(self, session, coordsets=False, filereader=None):
        """returns a chimerax equivalent of self"""
        struc = AtomicStructure(session, name=self.name)
        struc.comment = self.comment

        self.update_chix(struc)

        if coordsets and filereader is not None and filereader.all_geom is not None:
            #make a trajectory
            #each list of atoms in filereader.all_geom is a frame in the trajectory
            #replace previous coordinates
            #this matters when a filereader is given because the
            #geometry created from a filereader (which was probably passed as geom)
            #is the last geometry in the log or xyz file
            xyzs = self.all_geom_coordsets(filereader)
            struc.add_coordsets(xyzs, replace=True)
            struc.active_coordset_id = len(xyzs)

        # if it's a frequency file, draw TS bonds for imaginary modes
        if filereader is not None and "frequency" in filereader.other:
            for mode in filereader.other["frequency"].data:
                if mode.frequency < 0:
                    max_disp = max(np.linalg.norm(x) for x in mode.vector)
                    cur_coords = self.coords
                    coord_forward = self.coords + (0.2 /
                                                   max_disp) * mode.vector
                    coord_reverse = self.coords - (0.2 /
                                                   max_disp) * mode.vector
                    forward_connectivity = np.zeros(
                        (len(self.atoms), len(self.atoms)))
                    reverse_connectivity = np.zeros(
                        (len(self.atoms), len(self.atoms)))
                    self.update_geometry(coord_forward)
                    self.refresh_connected()
                    for i, atom1 in enumerate(self.atoms):
                        for j, atom2 in enumerate(self.atoms[:i]):
                            if atom1 in atom2.connected:
                                forward_connectivity[i, j] = 1
                                forward_connectivity[j, i] = 1

                    self.update_geometry(coord_reverse)
                    self.refresh_connected()
                    for i, atom1 in enumerate(self.atoms):
                        for j, atom2 in enumerate(self.atoms[:i]):
                            if atom1 in atom2.connected:
                                reverse_connectivity[i, j] = 1
                                reverse_connectivity[j, i] = 1

                    changes = forward_connectivity - reverse_connectivity
                    for i, atom1 in enumerate(self.atoms):
                        for j, atom1 in enumerate(self.atoms[:i]):
                            if changes[i, j] != 0:
                                sel = _FauxAtomSelection(
                                    atoms=(struc.atoms[i], struc.atoms[j]))
                                tsbond(session, sel)

                    self.update_geometry(cur_coords)

        return struc
Пример #10
0
def place_residues(session,
                   coords,
                   sequence,
                   residue_templates,
                   status_interval=1000):
    '''
    Use placements specified by coords (map of index to Place instance) to
    position nucleotides with given sequence.  The nucleotide single letter
    code (A,C,G,U) maps to a Residue given by map residue_templates.
    Index i corresponds to sequence position i-1.
    '''
    from chimerax.atomic import AtomicStructure
    m = AtomicStructure(session, name='RNA', auto_style=False)
    n = len(sequence)
    rlist = []
    for p, tf in sorted(coords.items()):
        if p <= n:
            t = sequence[p - 1].upper()
            if t in residue_templates:
                rt = residue_templates[t]
                r = copy_residue(rt, p, tf, m)
                rlist.append(r)
                if status_interval and len(rlist) % status_interval == 0:
                    session.logger.status('Created %d of %d residues' %
                                          (len(rlist), len(coords)))

    # Join consecutive residues
    rprev = rlist[0]
    for r in rlist[1:]:
        if r.number == 1 + rprev.number:
            a2 = r.find_atom('P')
            a1 = rprev.find_atom("O3'")
            if a1 and a2:
                m.new_bond(a1, a2)
        rprev = r

    session.models.add([m])
    return m
Пример #11
0
def cmd_start_structure(session, method, model_info, subargs):
    from .manager import manager
    if manager.is_indirect(method):
        raise UserError("No command support for '%s' start-structure method" %
                        method)
    if isinstance(model_info, str):
        from chimerax.atomic import AtomicStructure
        model = AtomicStructure(session, name=model_info)
    else:
        model = model_info
    try:
        ret_val = manager.execute_command(method, model, subargs)
    except BaseException:
        if isinstance(model_info, str):
            model.delete()
        raise
    if model.num_atoms == 0:
        model.delete()
    elif isinstance(model_info, str):
        session.models.add([model])
    return ret_val
Пример #12
0
def _prep_add(session,
              structures,
              unknowns_info,
              template,
              need_all=False,
              **prot_schemes):
    global _serial
    _serial = None
    atoms = []
    type_info_for_atom = {}
    naming_schemas = {}
    idatm_type = {}  # need this later; don't want a recomp
    hydrogen_totals = {}

    # add missing OXTs of "real" C termini;
    # delete hydrogens of "fake" N termini after protonation
    # and add a single "HN" back on, using same dihedral as preceding residue;
    # delete extra hydrogen of "fake" C termini after protonation
    logger = session.logger
    real_N, real_C, fake_N, fake_C = determine_termini(session, structures)
    logger.info("Chain-initial residues that are actual N"
                " termini: %s" % ", ".join([str(r) for r in real_N]))
    logger.info("Chain-initial residues that are not actual N"
                " termini: %s" % ", ".join([str(r) for r in fake_N]))
    logger.info("Chain-final residues that are actual C"
                " termini: %s" % ", ".join([str(r) for r in real_C]))
    logger.info("Chain-final residues that are not actual C"
                " termini: %s" % ", ".join([str(r) for r in fake_C]))
    for rc in real_C:
        complete_terminal_carboxylate(session, rc)

    # ensure that N termini are protonated as N3+ (since Npl will fail)
    from chimerax.atomic import Sequence
    for nter in real_N + fake_N:
        n = nter.find_atom("N")
        if not n:
            continue
        # if residue wasn't templated, leave atom typing alone
        if Sequence.protein3to1(n.residue.name) == 'X':
            continue
        if not (n.residue.name == "PRO" and n.num_bonds >= 2):
            n.idatm_type = "N3+"

    coordinations = {}
    for struct in structures:
        pbg = struct.pseudobond_group(struct.PBG_METAL_COORDINATION,
                                      create_type=None)
        if not pbg:
            continue
        for pb in pbg.pseudobonds:
            for a in pb.atoms:
                if not need_all and a.structure not in structures:
                    continue
                if not a.element.is_metal:
                    coordinations.setdefault(a, []).append(pb.other_atom(a))

    remaining_unknowns = {}
    type_info_class = type_info['H'].__class__
    from chimerax.atomic import Residue
    for struct in structures:
        for atom in struct.atoms:
            if atom.element.number == 0:
                res = atom.residue
                struct.delete_atom(atom)
        idatm_lookup = {}
        if template:
            template_lookup = {}
            from chimerax.atomic import TmplResidue
            get_template = TmplResidue.get_template
            for res in struct.residues:
                if get_template(res.name):
                    continue
                try:
                    exemplar = template_lookup[res.name]
                except KeyError:
                    from chimerax.mmcif import find_template_residue
                    tmpl = find_template_residue(session, res.name)
                    if not tmpl:
                        continue
                    from chimerax.atomic import AtomicStructure
                    s = AtomicStructure(session)
                    r = exemplar = template_lookup[res.name] = s.new_residue(
                        res.name, 'A', 1)
                    atom_map = {}
                    for ta in tmpl.atoms:
                        if ta.element.number > 1:
                            a = s.new_atom(ta.name, ta.element)
                            a.coord = ta.coord
                            r.add_atom(a)
                            atom_map[ta] = a
                            for tnb in ta.neighbors:
                                if tnb in atom_map:
                                    s.new_bond(a, atom_map[tnb])
                for a in res.atoms:
                    ea = exemplar.find_atom(a.name)
                    if ea:
                        a.idatm_type = ea.idatm_type
            for r in template_lookup.values():
                r.structure.delete()
            template_lookup.clear()

        for atom in struct.atoms:
            atom_type = atom.idatm_type
            idatm_type[atom] = atom_type
            if atom_type in type_info:
                # don't want to ask for idatm_type in middle
                # of hydrogen-adding loop (since that will
                # force a recomp), so remember here
                type_info_for_atom[atom] = type_info[atom_type]
                # if atom is in standard residue but has missing bonds to
                # heavy atoms, skip it instead of incorrectly protonating
                # (or possibly throwing an error if e.g. it's planar)
                # also
                # UNK/N residues will be missing some or all of their side-chain atoms, so
                # skip atoms that would otherwise be incorrectly protonated due to their
                # missing neighbors
                truncated = \
                        atom.is_missing_heavy_template_neighbors(no_template_okay=True) \
                    or \
                        (atom.residue.name in ["UNK", "N"] and atom.residue.polymer_type != Residue.PT_NONE
                        and unk_atom_truncated(atom)) \
                    or \
                        (atom.residue.polymer_type == Residue.PT_NUCLEIC and atom.name == "P"
                        and atom.num_explicit_bonds < 4)

                if truncated:
                    session.logger.warning(
                        "Not adding hydrogens to %s because it is missing heavy-atom"
                        " bond partners" % atom)
                    type_info_for_atom[atom] = type_info_class(
                        4, atom.num_bonds, atom.name)
                else:
                    atoms.append(atom)
                # sulfonamide nitrogens coordinating a metal
                # get an additional hydrogen stripped
                if coordinations.get(atom, []) and atom.element.name == "N":
                    if "Son" in [nb.idatm_type for nb in atom.neighbors]:
                        orig_ti = type_info[atom_type]
                        type_info_for_atom[atom] = orig_ti.__class__(
                            orig_ti.geometry, orig_ti.substituents - 1,
                            orig_ti.description)
                continue
            if atom in unknowns_info:
                type_info_for_atom[atom] = unknowns_info[atom]
                atoms.append(atom)
                continue
            remaining_unknowns.setdefault(atom.residue.name,
                                          set()).add(atom.name)
            # leave remaining unknown atoms alone
            type_info_for_atom[atom] = type_info_class(4, atom.num_bonds,
                                                       atom.name)

        for rname, atom_names in remaining_unknowns.items():
            names_text = ", ".join([nm for nm in atom_names])
            atom_text, obj_text = ("atoms",
                                   "them") if len(atom_names) > 1 else ("atom",
                                                                        "it")
            logger.warning(
                "Unknown hybridization for %s (%s) of residue type %s;"
                " not adding hydrogens to %s" %
                (atom_text, names_text, rname, obj_text))
        naming_schemas.update(
            determine_naming_schemas(struct, type_info_for_atom))

    if need_all:
        from chimerax.atomic import AtomicStructure
        for struct in [
                m for m in session.models if isinstance(m, AtomicStructure)
        ]:
            if struct in structures:
                continue
            for atom in struct.atoms:
                idatm_type[atom] = atom.idatm_type
                if atom.idatm_type in type_info:
                    type_info_for_atom[atom] = type_info[atom.idatm_type]

    for atom in atoms:
        if atom not in type_info_for_atom:
            continue
        bonding_info = type_info_for_atom[atom]
        total_hydrogens = bonding_info.substituents - atom.num_bonds
        for bonded in atom.neighbors:
            if bonded.element.number == 1:
                total_hydrogens += 1
        hydrogen_totals[atom] = total_hydrogens

    schemes = {}
    # HIS and CYS treated as 'unspecified'; use built-in typing
    for scheme_type, res_names, res_check, typed_atoms in [
        ('his', ["HID", "HIE", "HIP"], None, []),
        ('asp', asp_res_names, _asp_check, asp_prot_names),
        ('glu', glu_res_names, _glu_check, glu_prot_names),
        ('lys', ["LYS", "LYN"], _lys_check, ["NZ"]),
        ('cys', ["CYM"], _cys_check, ["SG"])
    ]:
        scheme = prot_schemes.get(scheme_type + '_scheme', None)
        if scheme is None:
            by_name = True
            scheme = {}
        else:
            by_name = False
        if not scheme:
            for s in structures:
                for r in s.residues:
                    if r.name in res_names and res_check and res_check(r):
                        if by_name:
                            scheme[r] = r.name
                        elif scheme_type != 'his':
                            scheme[r] = res_names[0]
                        # unset any explicit typing...
                        for ta in typed_atoms:
                            a = r.find_atom(ta)
                            if a:
                                a.idatm_type = None
        else:
            for r in scheme.keys():
                if res_check and not res_check(r, scheme[r]):
                    del scheme[r]
        schemes[scheme_type] = scheme
    # create dictionary keyed on histidine residue with value of another
    # dictionary keyed on the nitrogen atoms with boolean values: True
    # equals should be protonated
    his_Ns = {}
    for r, protonation in schemes["his"].items():
        delta = r.find_atom("ND1")
        epsilon = r.find_atom("NE2")
        if delta is None or epsilon is None:
            # find the ring, etc.
            rings = r.structure.rings()
            for ring in rings:
                if r in rings.atoms.residues:
                    break
            else:
                continue
            # find CG by locating CB-CG bond
            ring_bonds = ring.bonds
            for ra in ring.atoms:
                if ra.element.name != "C":
                    continue
                for ba, b in zip(ra.neighbors, ra.bonds):
                    if ba.element.name == "C" and b not in ring_bonds:
                        break
                else:
                    continue
                break
            else:
                continue
            nitrogens = [a for a in ring.atoms if a.element.name == "N"]
            if len(nitrogens) != 2:
                continue
            if ra in nitrogens[0].neighbors:
                delta, epsilon = nitrogens
            else:
                epsilon, delta = nitrogens
        if protonation == "HID":
            his_Ns.update({delta: True, epsilon: False})
        elif protonation == "HIE":
            his_Ns.update({delta: False, epsilon: True})
        elif protonation == "HIP":
            his_Ns.update({delta: True, epsilon: True})
        else:
            continue
    for n, do_prot in his_Ns.items():
        if do_prot:
            type_info_for_atom[n] = type_info["Npl"]
            n.idatm_type = idatm_type[n] = "Npl"
        else:
            type_info_for_atom[n] = type_info["N2"]
            n.idatm_type = idatm_type[n] = "N2"

    for r, protonation in schemes["asp"].items():
        _handle_acid_protonation_scheme_item(r, protonation, asp_res_names,
                                             asp_prot_names, type_info,
                                             type_info_for_atom)

    for r, protonation in schemes["glu"].items():
        _handle_acid_protonation_scheme_item(r, protonation, glu_res_names,
                                             glu_prot_names, type_info,
                                             type_info_for_atom)

    for r, protonation in schemes["lys"].items():
        nz = r.find_atom("NZ")
        if protonation == "LYS":
            it = 'N3+'
        else:
            it = 'N3'
        ti = type_info[it]
        if nz is not None:
            type_info_for_atom[nz] = ti
            # avoid explicitly setting type if possible
            if nz.idatm_type != it:
                nz.idatm_type = it

    for r, protonation in schemes["cys"].items():
        sg = r.find_atom("SG")
        if protonation == "CYS":
            it = 'S3'
        else:
            it = 'S3-'
        ti = type_info[it]
        if sg is not None:
            type_info_for_atom[sg] = ti
            # avoid explicitly setting type if possible
            if sg.idatm_type != it:
                sg.idatm_type = it

    return atoms, type_info_for_atom, naming_schemas, idatm_type, \
            hydrogen_totals, his_Ns, coordinations, fake_N, fake_C
Пример #13
0
    def openFile(self):
        fileName, filt = QFileDialog.getOpenFileName(caption="Open Trajectory File",
                                                     filter="PDB File (*.pdb);;" \
                                                            "H5 Trajectory File (*.h5);;" \
                                                            "HDF5 Trajectory File (*.hdf5)" \
                                                            "GRO Topology File (*.gro)"
                                                     )
        print(fileName)
        print(filt)

        if fileName == "":
            return

        if filt == "(*.gro)":
            gro_fileName = fileName
            fileName, filt = QFileDialog.getOpenFileName(caption="Open Trajectory File",
                                                         filter="XTC Trajectory File (*.xtc);;" \
                                                                "TRR Trajectory File (*.trr);;" \
                                                         )
            print(fileName)
            print(filt)
        else:
            gro_fileName = None

        if self.atomStruct != None:
            self.deleteModel()

        # This create a simple Oxygen atom
        # Need to get this to display
        self.atomStruct = AtomicStructure(self.session)

        if filt in ["(*.xtc)", "(*.trr)"]:
            trj = mdtraj.load(fileName, topology=gro_fileName)
        else:
            trj = mdtraj.load(fileName)
        trj.atom_slice(trj.topology.select("not element H"))

        table, bond_table = trj.topology.to_dataframe()
        table.rename(columns={
            "name": "atomname",
            "resName": "residue_name",
            "chainID": "chain_id",
            "resSeq": "pos"
        },
                     inplace=True)
        table["pos"] = table["pos"].astype(int)
        xyz = trj.xyz[0]
        table["loc"] = [array(x, dtype=float64) for x in xyz]
        res_infos = table[["residue_name", "chain_id", "pos"
                           ]].drop_duplicates(keep="first").to_dict("records")
        for res in res_infos:
            residue = self.atomStruct.new_residue(**res)
            qry = ' and '.join(
                ['{} == {}'.format(k, v) for k, v in res.items()])
            res_atoms = table.query(qry)[["name", "element",
                                          "loc"]].to_dict("records")
            for a in res_atoms:
                atom = self.atomStruct.new_atom({
                    "name": a["name"],
                    "element": a["element"]
                })
                atom.coord = a["loc"]
                residue.add_atom(atom)

        for frame in range(1, trj.n_frames):
            xyz = trj.xyz[frame]
            self.atomLocation.append(array(xyz, dtype=float64))

        self.atomStruct.connect_structure()
        self.session.models.add([self.atomStruct])

        for i in range(len(self.atomLocation)):
            self.surfacePositions.append(None)

        self.atomStruct.atoms.coords = self.atomLocation[0]
        fileName = fileName.split("/")[-1]

        js = "modelName = '" + fileName + "'; frameCount = " + str(
            len(self.atomLocation)) + "; reset();"
        self.html_view.runJavaScript(js)
        run(self.session, "lighting full", log=False)
Пример #14
0
def read_sdf(session, stream, file_name):

    path = stream.name if hasattr(stream, 'name') else None

    structures = []
    nonblank = False
    state = "init"
    from chimerax.core.errors import UserError
    from chimerax.atomic.struct_edit import add_atom
    from chimerax.atomic import AtomicStructure, Element, Bond, Atom, AtomicStructure
    from numpy import array
    Bond.register_attr(session, "order", "SDF format", attr_type=float)
    Atom.register_attr(session, "charge", "SDF format", attr_type=float)
    AtomicStructure.register_attr(session, "charge_model", "SDF format", attr_type=str)
    try:
        for l in stream:
            line = l.strip()
            nonblank = nonblank or line
            if state == "init":
                state = "post header 1"
                mol_name = line
            elif state == "post header 1":
                state = "post header 2"
            elif state == "post header 2":
                state = "counts"
            elif state == "counts":
                if not line:
                    break
                state = "atoms"
                serial = 1
                anums = {}
                atoms = []
                try:
                    num_atoms = int(l[:3].strip())
                    num_bonds = int(l[3:6].strip())
                except ValueError:
                    raise UserError("Atom/bond counts line of MOL/SDF file '%s' is botched" % file_name)
                from chimerax.atomic.structure import is_informative_name
                name = mol_name if is_informative_name(mol_name) else file_name
                s = AtomicStructure(session, name=name)
                structures.append(s)
                r = s.new_residue("UNL", " ", 1)
            elif state == "atoms":
                num_atoms -= 1
                if num_atoms == 0:
                    if num_bonds:
                        state = "bonds"
                    else:
                        state = "properties"
                try:
                    x = float(l[:10].strip())
                    y = float(l[10:20].strip())
                    z = float(l[20:30].strip())
                    elem = l[31:34].strip()
                except ValueError:
                    s.delete()
                    raise UserError("Atom line of MOL/SDF file '%s' is not x y z element...: '%s'"
                        % (file_name, l))
                element = Element.get_element(elem)
                if element.number == 0:
                    # lone pair of somesuch
                    atoms.append(None)
                    continue
                anum = anums.get(element.name, 0) + 1
                anums[element.name] = anum
                a = add_atom("%s%d" % (element.name, anum), element, r, array([x,y,z]), serial_number=serial)
                serial += 1
                atoms.append(a)
            elif state == "bonds":
                num_bonds -= 1
                if num_bonds == 0:
                    state = "properties"
                try:
                    a1_index = int(l[:3].strip())
                    a2_index = int(l[3:6].strip())
                    order = float(l[6:9].strip())
                except ValueError:
                    raise UserError("Bond line of MOL/SDF file '%s' is not a1 a2 order...: '%s'"
                        % (file_name, 1))
                a1 = atoms[a1_index-1]
                a2 = atoms[a2_index-1]
                if not a1 or not a2:
                    continue
                s.new_bond(a1, a2).order = order
            elif state == "properties":
                if not s.atoms:
                    raise UserError("No atoms found for compound '%s' in MOL/SDF file '%s'" % (name, file_name))
                if line.split() == ["M", "END"]:
                    state = "data"
                    reading_data = None
            elif state == "data":
                if line == "$$$$":
                    nonblank = False
                    state = "init"
                elif reading_data == "charges":
                    data_item = line.strip()
                    if data_item:
                        try:
                            data.append(float(data_item))
                        except ValueError:
                            try:
                                index, charge = data_item.split()
                                index = int(index) - 1
                                charge = float(charge)
                            except ValueError:
                                raise UserError("Charge data (%s) in %s data is not either a floating-point"
                                    " number or an atom index and a floating-point number" % (data_item,
                                    orig_data_name))
                            else:
                                if not indexed_charges:
                                    # for indexed charges, the first thing is a count
                                    data.pop()
                                    indexed_charges = True
                                data.append((index, charge))
                    else:
                        if not indexed_charges and len(atoms) != len(data):
                            raise UserError("Number of charges (%d) in %s data not equal to number of atoms"
                                " (%d)" % (len(data), orig_data_name, len(atoms)))
                        if indexed_charges:
                            for a in atoms:
                                # charge defaults to 0.0, so don't need to set non-indexed
                                for index, charge in data:
                                    atoms[index].charge = charge
                        else:
                            for a, charge in zip(atoms, data):
                                a.charge = charge
                        if "mmff94" in data_name:
                            s.charge_model = "MMFF94"
                        reading_data = None
                elif reading_data == "cid":
                    data_item = line.strip()
                    if data_item:
                        try:
                            cid = int(data_item)
                        except ValueError:
                            raise UserError("PubChem CID (%s) is %s data is not an integer" % (data_item,
                                orid_data_name))
                        s.name = "pubchem:%d" % cid
                        s.prefix_html_title = False
                        s.get_html_title = lambda *args, cid=cid: 'PubChem entry <a href="https://pubchem.ncbi.nlm.nih.gov/compound/%d">%d</a>' % (cid, cid)
                        s.has_formatted_metadata = lambda *args: False
                        reading_data = None
                elif line.startswith('>'):
                    try:
                        lp = line.index('<')
                        rp = line[lp+1:].index('>') + lp + 1
                    except (IndexError, ValueError):
                        continue
                    orig_data_name = line[lp+1:rp]
                    data_name = orig_data_name.lower()
                    if data_name.endswith("charges") and "partial" in data_name:
                        reading_data = "charges"
                        indexed_charges = False
                        data = []
                    elif data_name == "pubchem_compound_cid":
                        reading_data = "cid"
    except BaseException:
        for s in structures:
            s.delete()
        raise
    finally:
        stream.close()

    if nonblank and state not in ["data", "init"]:
        if structures:
            session.logger.warning("Extraneous text after final $$$$ in MOL/SDF file '%s'" % file_name)
        else:
            raise UserError("Unexpected end of file (parser state: %s) in MOL/SDF file '%s'"
                % (state, file_name))

    return structures, ""
Пример #15
0
def get_rotamers(session,
                 res,
                 phi=None,
                 psi=None,
                 cis=False,
                 res_type=None,
                 rot_lib="Dunbrack",
                 log=False):
    """Takes a Residue instance and optionally phi/psi angles (if different from the Residue), residue
       type (e.g. "TYR"), and/or rotamer library name.  Returns a list of AtomicStructure instances (sublass of
       AtomicStructure).  The AtomicStructure are each a single residue (a rotamer) and are in descending
       probability order.  Each has an attribute "rotamer_prob" for the probability and "chis" for the
       chi angles.
    """
    res_type = res_type or res.name
    if res_type == "ALA" or res_type == "GLY":
        raise NoResidueRotamersError("No rotamers for %s" % res_type)

    if not isinstance(rot_lib, RotamerLibrary):
        rot_lib = session.rotamers.library(rot_lib)

    # check that the residue has the n/c/ca atoms needed to position the rotamer
    # and to ensure that it is an amino acid
    from chimerax.atomic import Residue
    match_atoms = {}
    for bb_name in Residue.aa_min_backbone_names:
        match_atoms[bb_name] = a = res.find_atom(bb_name)
        if a is None:
            raise LimitationError("%s missing from %s; needed to position CB" %
                                  (bb_name, res))
    match_atoms["CB"] = res.find_atom("CB")
    if not phi and not psi:
        phi, psi = res.phi, res.psi
        omega = res.omega
        cis = False if omega is None or abs(omega) > 90 else True
        if log:

            def _info(ang):
                if ang is None:
                    return "none"
                return "%.1f" % ang

            if match_atoms["CA"].alt_locs:
                al_info = " (alt loc %s)" % match_atoms["CA"].alt_loc
            else:
                al_info = ""
            session.logger.info("%s%s: phi %s, psi %s %s" %
                                (res, al_info, _info(phi), _info(psi),
                                 "cis" if cis else "trans"))
    session.logger.status("Retrieving rotamers from %s library" %
                          rot_lib.display_name)
    res_template_func = rot_lib.res_template_func
    params = rot_lib.rotamer_params(res_type, phi, psi, cis=cis)
    session.logger.status("Rotamers retrieved from %s library" %
                          rot_lib.display_name)

    mapped_res_type = rot_lib.res_name_mapping.get(res_type, res_type)
    template = rot_lib.res_template_func(mapped_res_type)
    tmpl_N = template.find_atom("N")
    tmpl_CA = template.find_atom("CA")
    tmpl_C = template.find_atom("C")
    tmpl_CB = template.find_atom("CB")
    if match_atoms['CB']:
        res_match_atoms, tmpl_match_atoms = [
            match_atoms[x] for x in ("C", "CA", "CB")
        ], [tmpl_C, tmpl_CA, tmpl_CB]
    else:
        res_match_atoms, tmpl_match_atoms = [
            match_atoms[x] for x in ("N", "CA", "C")
        ], [tmpl_N, tmpl_CA, tmpl_C]
    from chimerax.geometry import align_points
    from numpy import array
    xform, rmsd = align_points(array([fa.coord for fa in tmpl_match_atoms]),
                               array([ta.coord for ta in res_match_atoms]))
    n_coord = xform * tmpl_N.coord
    ca_coord = xform * tmpl_CA.coord
    cb_coord = xform * tmpl_CB.coord
    info = Residue.chi_info[mapped_res_type]
    bond_cache = {}
    angle_cache = {}
    from chimerax.atomic.struct_edit import add_atom, add_dihedral_atom, add_bond
    structs = []
    middles = {}
    ends = {}
    for i, rp in enumerate(params):
        s = AtomicStructure(session, name="rotamer %d" % (i + 1))
        structs.append(s)
        r = s.new_residue(mapped_res_type, 'A', 1)
        registerer = "swap_res get_rotamers"
        AtomicStructure.register_attr(session,
                                      "rotamer_prob",
                                      registerer,
                                      attr_type=float)
        s.rotamer_prob = rp.p
        AtomicStructure.register_attr(session, "chis", registerer)
        s.chis = rp.chis
        rot_N = add_atom("N", tmpl_N.element, r, n_coord)
        rot_CA = add_atom("CA", tmpl_CA.element, r, ca_coord, bonded_to=rot_N)
        rot_CB = add_atom("CB", tmpl_CB.element, r, cb_coord, bonded_to=rot_CA)
        todo = []
        for j, chi in enumerate(rp.chis):
            n3, n2, n1, new = info[j]
            b_len, angle = _len_angle(new, n1, n2, template, bond_cache,
                                      angle_cache)
            n3 = r.find_atom(n3)
            n2 = r.find_atom(n2)
            n1 = r.find_atom(n1)
            new = template.find_atom(new)
            a = add_dihedral_atom(new.name,
                                  new.element,
                                  n1,
                                  n2,
                                  n3,
                                  b_len,
                                  angle,
                                  chi,
                                  bonded=True)
            todo.append(a)
            middles[n1] = [a, n1, n2]
            ends[a] = [a, n1, n2]

        # if there are any heavy non-backbone atoms bonded to template
        # N and they haven't been added by the above (which is the
        # case for Richardson proline parameters) place them now
        for tnnb in tmpl_N.neighbors:
            if r.find_atom(tnnb.name) or tnnb.element.number == 1:
                continue
            tnnb_coord = xform * tnnb.coord
            add_atom(tnnb.name, tnnb.element, r, tnnb_coord, bonded_to=rot_N)

        # fill out bonds and remaining heavy atoms
        from chimerax.geometry import distance, align_points
        done = set([rot_N, rot_CA])
        while todo:
            a = todo.pop(0)
            if a in done:
                continue
            tmpl_A = template.find_atom(a.name)
            for bonded, bond in zip(tmpl_A.neighbors, tmpl_A.bonds):
                if bonded.element.number == 1:
                    continue
                rbonded = r.find_atom(bonded.name)
                if rbonded is None:
                    # use middles if possible...
                    try:
                        p1, p2, p3 = middles[a]
                        conn = p3
                    except KeyError:
                        p1, p2, p3 = ends[a]
                        conn = p2
                    t1 = template.find_atom(p1.name)
                    t2 = template.find_atom(p2.name)
                    t3 = template.find_atom(p3.name)
                    xform = align_points(
                        array([t.coord for t in [t1, t2, t3]]),
                        array([p.coord for p in [p1, p2, p3]]))[0]
                    pos = xform * template.find_atom(bonded.name).coord
                    rbonded = add_atom(bonded.name,
                                       bonded.element,
                                       r,
                                       pos,
                                       bonded_to=a)
                    middles[a] = [rbonded, a, conn]
                    ends[rbonded] = [rbonded, a, conn]
                if a not in rbonded.neighbors:
                    add_bond(a, rbonded)
                if rbonded not in done:
                    todo.append(rbonded)
            done.add(a)
    return structs
Пример #16
0
class MolecularDynamicsTool(HtmlToolInstance):
    '''
     # Properties for the tool
    '''
    SESSION_ENDURING = False
    SESSION_SAVE = False
    CUSTOM_SCHEME = "kmd"

    def __init__(self, session, tool_name):
        super().__init__(session,
                         tool_name,
                         size_hint=(500, 500),
                         show_http_in_help=False)
        self.display_name = DISPLAY_NAME
        self._build_ui()

        self.atomStruct = None
        self.atomLocation = []
        self.surfacePositions = []
        self.attributeFile = False

    # Loads the html view to be shown
    def _build_ui(self):
        html_file = os.path.join(os.path.dirname(__file__), "dynamics.html")
        self.html_view.setUrl(pathlib.Path(html_file).as_uri())

    # This is to delete the model from the view
    def delete(self):
        super(HtmlToolInstance, self).delete()
        self.deleteModel()

    '''
     # This handles when a window.location becomes kmd:<command>
     #
     # @param url - The command
    '''

    def handle_scheme(self, url):
        command = url.path()

        if command.startswith("log"):
            self.session.logger.info(command[len("log_"):])
        elif command == "Open":
            self.openFile()
        elif command.startswith("FrameChange"):
            frame = int(command[len("FrameChange_T_"):])
            self.changeModel(frame, command[12] == 'T')
        elif command == "MovieDone":
            movie_encode(self.session, output=[self.movieName], format="h264")
        elif command == "MovieStart":
            fileName, filt = QFileDialog.getSaveFileName(
                caption="Save Movie", filter="MP4 File (*.mp4)")

            if fileName == "":
                return

            if fileName[-4:] != ".mp4":
                fileName = fileName + ".mp4"

            self.movieName = fileName
            movie_record(self.session)
            self.html_view.runJavaScript("startMovie()")
        elif command == "Attribute":
            self.loadAttributeFile()
        else:
            self.session.logger.info("Unknown Command: " + str(url))

    def loadAttributeFile(self):
        fileName, filt = QFileDialog.getOpenFileName(
            caption="Open Attribute File", filter="Attribute File (*.dat)")

        if fileName == "":
            return

        fileObj = open(fileName)
        lines = fileObj.readlines()[3:]
        fileObj.close()
        mapVals = {}

        for line in lines:
            parts = line.split('\t')[1:]
            mapVals[int(parts[0][1:])] = float(parts[1])

        maxValue = max(mapVals.values())
        minValue = min(mapVals.values())
        midValue = (maxValue + minValue) / 2

        # Color from min (blue) to mid (white) to max (red)

        for key in mapVals.keys():
            value = mapVals[key]
            per = (value - minValue) / (midValue - minValue) - 1
            color = abs(per) * 255
            colorSet = [255, 255 - color, 255 - color, 255
                        ] if per > 0 else [255 - color, 255 - color, 255, 255]
            colorSet = array(colorSet)

            self.atomStruct.residues[key - 1].ribbon_color = colorSet
            self.atomStruct.residues[key - 1].atoms.colors = colorSet

        js = "attributeName = '" + fileName.split(
            "/")[-1] + "';updateDisplay()"
        self.html_view.runJavaScript(js)
        self.attributeFile = True

        if self.atomStruct.surfaces() != []:
            run(self.session,
                "color #" + self.atomStruct.surfaces()[0].id_string +
                " fromatoms",
                log=False)

    # This is to remove model for changing
    def deleteModel(self):
        if self.atomStruct == None:
            return

        if self.atomStruct.deleted:
            return

        if self.atomStruct.surfaces() != []:
            self.session.models.remove([self.atomStruct.surfaces()[0]])

        self.session.models.remove([self.atomStruct])
        self.attributeFile = False
        self.atomStruct = None
        self.atomLocation = []
        self.surfacePositions = []
        js = "modelName = null; frameCount = 0; reset();"
        self.html_view.runJavaScript(js)

    # This is to move the atoms
    def changeModel(self, frame, surf):
        locs = self.atomLocation[frame]
        atms = self.atomStruct.atoms

        atms.coords = locs

        if surf:
            ### Need to recalculate the surfce here
            if self.atomStruct.surfaces() == []:
                surface(self.session, atoms=self.atomStruct.atoms)
            else:
                surfPos = self.surfacePositions[frame]

                if surfPos is None:
                    self.session.models.remove([self.atomStruct.surfaces()[0]])
                    surface(self.session, atoms=self.atomStruct.atoms)
                    self.surfacePositions[frame] = self.atomStruct.surfaces(
                    )[0]
                else:
                    self.session.models.remove([self.atomStruct.surfaces()[0]])
                    self.atomStruct.add([surfPos])
            ###
            run(self.session,
                "color #" + self.atomStruct.surfaces()[0].id_string +
                " fromatoms",
                log=False)
        elif self.atomStruct.surfaces() != []:
            self.session.models.remove([self.atomStruct.surfaces()[0]])

    # This opens a file
    def openFile(self):
        fileName, filt = QFileDialog.getOpenFileName(
            caption="Open PDB Trajectory File", filter="PDB File (*.pdb)")

        if fileName == "":
            return

        if self.atomStruct != None:
            self.deleteModel()

        # This create a simple Oxygen atom
        # Need to get this to display
        self.atomStruct = AtomicStructure(self.session)

        myFile = open(fileName)

        coords = []
        prevRes = None
        res = None
        modelNum = -1

        for line in myFile:
            if line.startswith("MODEL"):
                modelNum = modelNum + 1
                coords = []
                prevRes = None
                res = None
            elif line.startswith("ENDMDL"):
                self.atomLocation.append(array(coords))
            elif line.startswith("ATOM"):
                x = float(line[30:38].strip())
                y = float(line[38:46].strip())
                z = float(line[46:54].strip())

                name = line[12:16].strip()
                resName = line[17:20].strip()
                chain = line[21]
                resSeq = line[22:26].strip()
                element = line[76:78].strip()

                if element == "H":
                    continue

                coords.append([x, y, z])

                if modelNum != 0:
                    continue

                if resName + resSeq != prevRes:
                    prevRes = resName + resSeq
                    res = self.atomStruct.new_residue(resName, chain,
                                                      int(resSeq))

                atom = self.atomStruct.new_atom(name, element)
                atom.coord = array([x, y, z], dtype=float64)
                res.add_atom(atom)

        myFile.close()
        self.atomStruct.connect_structure()

        self.session.models.add([self.atomStruct])

        for i in range(len(self.atomLocation)):
            self.surfacePositions.append(None)

        self.atomStruct.atoms.coords = self.atomLocation[0]
        fileName = fileName.split("/")[-1]

        js = "modelName = '" + fileName + "'; frameCount = " + str(
            len(self.atomLocation)) + "; reset();"
        self.html_view.runJavaScript(js)
        run(self.session, "lighting full", log=False)
Пример #17
0
    def openFile(self):
        fileName, filt = QFileDialog.getOpenFileName(
            caption="Open PDB Trajectory File", filter="PDB File (*.pdb)")

        if fileName == "":
            return

        if self.atomStruct != None:
            self.deleteModel()

        # This create a simple Oxygen atom
        # Need to get this to display
        self.atomStruct = AtomicStructure(self.session)

        myFile = open(fileName)

        coords = []
        prevRes = None
        res = None
        modelNum = -1

        for line in myFile:
            if line.startswith("MODEL"):
                modelNum = modelNum + 1
                coords = []
                prevRes = None
                res = None
            elif line.startswith("ENDMDL"):
                self.atomLocation.append(array(coords))
            elif line.startswith("ATOM"):
                x = float(line[30:38].strip())
                y = float(line[38:46].strip())
                z = float(line[46:54].strip())

                name = line[12:16].strip()
                resName = line[17:20].strip()
                chain = line[21]
                resSeq = line[22:26].strip()
                element = line[76:78].strip()

                if element == "H":
                    continue

                coords.append([x, y, z])

                if modelNum != 0:
                    continue

                if resName + resSeq != prevRes:
                    prevRes = resName + resSeq
                    res = self.atomStruct.new_residue(resName, chain,
                                                      int(resSeq))

                atom = self.atomStruct.new_atom(name, element)
                atom.coord = array([x, y, z], dtype=float64)
                res.add_atom(atom)

        myFile.close()
        self.atomStruct.connect_structure()

        self.session.models.add([self.atomStruct])

        for i in range(len(self.atomLocation)):
            self.surfacePositions.append(None)

        self.atomStruct.atoms.coords = self.atomLocation[0]
        fileName = fileName.split("/")[-1]

        js = "modelName = '" + fileName + "'; frameCount = " + str(
            len(self.atomLocation)) + "; reset();"
        self.html_view.runJavaScript(js)
        run(self.session, "lighting full", log=False)
Пример #18
0
def _read_block(session, stream, line_number):
    # XYZ files are stored in blocks, with each block representing
    # a set of atoms.  This function reads a single block
    # and builds a ChimeraX AtomStructure instance containing
    # the atoms listed in the block.

    # First line should be an integer count of the number of
    # atoms in the block.
    count_line = stream.readline()
    if not count_line:
        # Reached EOF, normal termination condition
        return None, line_number
    line_number += 1
    try:
        count = int(count_line)
    except ValueError:
        session.logger.error("line %d: atom count missing" % line_number)
        return None, line_number

    # Create the AtomicStructure instance for atoms in this block.
    # All atoms in the structure are placed in one residue
    # since XYZ format does not partition atoms into groups.
    from chimerax.atomic import AtomicStructure
    from numpy import array, float64
    s = AtomicStructure(session)
    residue = s.new_residue("UNK", 'A', 1)

    # XYZ format supplies the atom element type only, but
    # ChimeraX keeps track of both the element type and
    # a unique name for each atom.  To construct the unique
    # atom name, the # 'element_count' dictionary is used
    # to track the number of atoms of each element type so far,
    # and the current count is used to build unique atom names.
    element_count = {}

    # Next line is a comment line
    s.comment = stream.readline().strip()
    line_number += 1

    # There should be "count" lines of atoms.
    for n in range(count):
        atom_line = stream.readline()
        if not atom_line:
            session.logger.error("line %d: atom data missing" % line_number)
            return None, line_number
        line_number += 1

        # Extract available data
        parts = atom_line.split()
        if len(parts) != 4:
            session.logger.error("line %d: atom data malformatted" %
                                 line_number)
            return None, line_number

        # Convert to required parameters for creating atom.
        # Since XYZ format only required atom element, we
        # create a unique atom name by putting a number after
        # the element name.
        xyz = [float(v) for v in parts[1:]]
        element = parts[0]
        n = element_count.get(element, 0) + 1
        name = element + str(n)
        element_count[element] = n

        # Create atom in AtomicStructure instance 's',
        # set its coordinates, and add to residue
        atom = s.new_atom(name, element)
        atom.coord = array(xyz, dtype=float64)
        residue.add_atom(atom)

    # Use AtomicStructure method to add bonds based on interatomic distances
    s.connect_structure()

    # Updating state such as atom types while adding atoms iteratively
    # is unnecessary (and generally incorrect for partial structures).
    # When all atoms have been added, the instance is notified to
    # tell it to update internal state.
    s.new_atoms()

    # Return AtomicStructure instance and current line number
    return s, line_number
Пример #19
0
    def process_ok_models(self, ok_models_text, stdout_text, get_pdb_model):
        ok_models_lines = ok_models_text.rstrip().split('\n')
        headers = [h.strip() for h in ok_models_lines[0].split('\t')][1:]
        for i, hdr in enumerate(headers):
            if hdr.endswith(" score"):
                headers[i] = hdr[:-6]
        from chimerax.core.utils import string_to_attr
        attr_names = [
            string_to_attr(hdr, prefix="modeller_") for hdr in headers
        ]
        from chimerax.atomic import AtomicStructure
        for attr_name in attr_names:
            AtomicStructure.register_attr(self.session,
                                          attr_name,
                                          "Modeller",
                                          attr_type=float)

        from chimerax import match_maker as mm
        models = []
        match_okay = True
        for i, line in enumerate(ok_models_lines[1:]):
            fields = line.strip().split()
            pdb_name, scores = fields[0], [float(f) for f in fields[1:]]
            model = get_pdb_model(pdb_name)
            for attr_name, val in zip(attr_names, scores):
                setattr(model, attr_name, val)
            model.name = self.target_seq_name
            if model.num_chains == len(self.match_chains):
                pairings = list(zip(self.match_chains, model.chains))
                mm.match(self.session,
                         mm.CP_SPECIFIC_SPECIFIC,
                         pairings,
                         mm.defaults['matrix'],
                         mm.defaults['alignment_algorithm'],
                         mm.defaults['gap_open'],
                         mm.defaults['gap_extend'],
                         cutoff_distance=mm.defaults['iter_cutoff'])
            else:
                match_okay = False
            models.append(model)
        if not match_okay:
            self.session.logger.warning(
                "The number of model chains does not match the number used from"
                " the template structure(s) [which can be okay if you closed or modified template"
                " structures while the job was running], so no superposition of the models onto the"
                " templates was performed.")

        reset_alignments = []
        for alignment, target_seq in self.targets:
            alignment.associate(models, seq=target_seq)
            if alignment.auto_associate:
                alignment.auto_associate = False
                reset_alignments.append(alignment)
        self.session.models.add_group(models,
                                      name=self.target_seq_name + " models")
        for alignment in reset_alignments:
            alignment.auto_associate = True

        if self.show_gui and self.session.ui.is_gui:
            from .tool import ModellerResultsViewer
            ModellerResultsViewer(self.session, "Modeller Results", models,
                                  attr_names)
Пример #20
0
 def _make_structure(self):
     """Build ChimeraX structure and reset structure data cache"""
     try:
         if self._molecule is None:
             return
         if self.atomic:
             from chimerax.atomic import AtomicStructure as SC
         else:
             from chimerax.atomic import Structure as SC
         # Create structure
         s = SC(self.session, auto_style=self.auto_style)
         s.name = self._molecule.mol_name
         SC.register_attr(self.session, "viewdockx_data", "ViewDockX")
         s.viewdockx_data = self._data
         if self._molecule.charge_type:
             s.charge_model = self._molecule.charge_type
         if self._molecule.mol_type:
             s.mol2_type = self._molecule.mol_type
         if self._molecule.mol_comment:
             s.mol2_comment = self._molecule.mol_comment
         # Create residues
         substid2residue = {}
         for subst_data in self._substs:
             # ChimeraX limitation: 4-letter residue type
             name = subst_data.subst_name[:4]
             chain = subst_data.chain
             if chain is None or chain == "****":
                 chain = ''
             residue = s.new_residue(name, chain, subst_data.subst_id)
             substid2residue[subst_data.subst_id] = residue
         # Create atoms
         atomid2atom = {}
         from numpy import array, float64
         for atom_data in self._atoms:
             name = atom_data.atom_name
             element = atom_data.atom_type
             if '.' in element:
                 element = element.split('.')[0]
             atom = s.new_atom(name, element)
             atom.coord = array([atom_data.x, atom_data.y, atom_data.z],
                                dtype=float64)
             if atom_data.charge is not None:
                 atom.charge = atom_data.charge
             try:
                 residue = substid2residue[atom_data.subst_id]
             except KeyError:
                 # Must not have been a substructure section
                 residue = s.new_residue("UNK", '', atom_data.subst_id)
                 substid2residue[atom_data.subst_id] = residue
             residue.add_atom(atom)
             atomid2atom[atom_data.atom_id] = atom
         # Create bonds
         for bond_data in self._bonds:
             try:
                 origin = atomid2atom[bond_data.origin_atom_id]
                 target = atomid2atom[bond_data.target_atom_id]
             except KeyError:
                 self.session.logger.warning("bad atom index in bond")
             else:
                 s.new_bond(origin, target)
         self.structures.append(s)
     finally:
         self._reset_structure()
Пример #21
0
    def _make_structure(self, block):
        from numpy import array
        from .maestro import IndexAttribute
        if self.atomic:
            from chimerax.atomic import AtomicStructure as SC
        else:
            from chimerax.atomic import Structure as SC
        from chimerax.atomic import Element
        atoms = block.get_sub_block("m_atom")
        if atoms is None:
            print("No m_atom block found")
            return None
        bonds = block.get_sub_block("m_bond")
        s = SC(self.session, auto_style=self.auto_style)
        SC.register_attr(self.session, "viewdockx_data", "ViewDockX")

        residue_map = {}
        atom_map = {}
        for row in range(atoms.size):
            attrs = atoms.get_attribute_map(row)
            index = attrs[IndexAttribute]

            # Get residue data and create if necessary
            res_seq = attrs["i_m_residue_number"]
            insert_code = attrs.get("s_m_insertion_code", None)
            if not insert_code:
                insert_code = ' '
            chain_id = attrs.get("s_m_chain_name", ' ')
            res_key = (chain_id, res_seq, insert_code)
            try:
                r = residue_map[res_key]
            except KeyError:
                res_name = attrs.get("s_m_pdb_residue_name", "UNK")
                r = s.new_residue(res_name, chain_id, res_seq, insert_code)
                residue_map[res_key] = r
            rgb = attrs.get("s_m_ribbon_color_rgb", None)
            if rgb:
                r.ribbon_color = self._get_color(rgb)

            # Get atom data and create
            try:
                name = attrs["s_m_pdb_atom_name"]
            except KeyError:
                name = attrs.get("s_m_atom_name", "")
            name = name.strip()
            atomic_number = attrs.get("i_m_atomic_number", 6)
            element = Element.get_element(atomic_number)
            if not name:
                name = element.name
            a = s.new_atom(name, element)
            a.coord = array([atoms.get_attribute("r_m_x_coord", row),
                             atoms.get_attribute("r_m_y_coord", row),
                             atoms.get_attribute("r_m_z_coord", row)])
            try:
                a.bfactor = attrs["r_m_pdb_tfactor"]
            except (KeyError, TypeError):
                a.bfactor = 0.0
            try:
                a.occupancy = attrs["r_m_pdb_occupancy"]
            except (KeyError, TypeError):
                a.occupancy = 1.0
            rgb = attrs.get("s_m_color_rgb", None)
            if rgb:
                a.color = self._get_color(rgb)

            # Add atom to residue and to atom map for bonding later
            r.add_atom(a)
            atom_map[index] = a
        if bonds is None or bonds.size == 0:
            s.connect_structure()
        else:
            for row in range(bonds.size):
                attrs = bonds.get_attribute_map(row)
                fi = attrs["i_m_from"]
                ti = attrs["i_m_to"]
                if ti < fi:
                    # Bonds are reported in both directions. We only need one.
                    continue
                afi = atom_map[fi]
                ati = atom_map[ti]
                b = s.new_bond(afi, ati)
                b.order = attrs["i_m_order"]
        return s
Пример #22
0
    def finalize_init(self, mgr, res_type, rot_lib, *, table_info=None):
        self.mgr = mgr
        self.res_type = res_type
        self.rot_lib = rot_lib

        self.subdialogs = {}
        from collections import OrderedDict
        self.opt_columns = OrderedDict()
        self.handlers = [
            self.mgr.triggers.add_handler('fewer rotamers',
                                          self._fewer_rots_cb),
            self.mgr.triggers.add_handler('self destroyed',
                                          self._mgr_destroyed_cb),
        ]
        from chimerax.ui.widgets import ItemTable
        global _settings
        if _settings is None:
            from chimerax.core.settings import Settings

            class _RotamerSettings(Settings):
                EXPLICIT_SAVE = {ItemTable.DEFAULT_SETTINGS_ATTR: {}}

            _settings = _RotamerSettings(self.session, "Rotamers")
        from chimerax.ui import MainToolWindow
        self.tool_window = tw = MainToolWindow(self)
        parent = tw.ui_area
        from PyQt5.QtWidgets import QVBoxLayout, QLabel, QCheckBox, QGroupBox, QWidget, QHBoxLayout, \
            QPushButton, QRadioButton, QButtonGroup, QGridLayout
        from PyQt5.QtCore import Qt
        self.layout = layout = QVBoxLayout()
        parent.setLayout(layout)
        lib_display_name = self.session.rotamers.library(rot_lib).display_name
        layout.addWidget(
            QLabel("%s %s rotamers" % (lib_display_name, res_type)))
        column_disp_widget = QWidget()

        class RotamerTable(ItemTable):
            def sizeHint(self):
                from PyQt5.QtCore import QSize
                return QSize(350, 450)

        self.table = RotamerTable(column_control_info=(column_disp_widget,
                                                       _settings, {}, True,
                                                       None, None, False),
                                  auto_multiline_headers=False)
        for i in range(len(self.mgr.rotamers[0].chis)):
            self.table.add_column("Chi %d" % (i + 1),
                                  lambda r, i=i: r.chis[i],
                                  format="%6.1f")
        self.table.add_column("Probability", "rotamer_prob", format="%.6f ")

        if table_info:
            table_state, additional_col_info = table_info
            for col_type, title, data_fetch, display_format in additional_col_info:
                AtomicStructure.register_attr(
                    self.session,
                    data_fetch,
                    self.registerer,
                    attr_type=(int if data_fetch.startswith("num") else float))
                self.opt_columns[col_type] = self.table.add_column(
                    title, data_fetch, format=display_format)
        else:
            table_state = None
        self.table.data = self.mgr.rotamers
        self.table.launch(session_info=table_state)
        if not table_info:
            self.table.sortByColumn(len(self.mgr.rotamers[0].chis),
                                    Qt.DescendingOrder)
        self.table.selection_changed.connect(self._selection_change)
        layout.addWidget(self.table)
        if mgr.base_residue.name == res_type:
            self.retain_side_chain = QCheckBox("Retain original side chain")
            self.retain_side_chain.setChecked(False)
            layout.addWidget(self.retain_side_chain)
        else:
            self.retain_side_chain = None

        column_group = QGroupBox("Column display")
        layout.addWidget(column_group)
        cg_layout = QVBoxLayout()
        cg_layout.setContentsMargins(0, 0, 0, 0)
        cg_layout.setSpacing(0)
        column_group.setLayout(cg_layout)
        cg_layout.addWidget(column_disp_widget)

        add_col_layout = QGridLayout()
        add_col_layout.setContentsMargins(0, 0, 0, 0)
        add_col_layout.setSpacing(0)
        cg_layout.addLayout(add_col_layout)
        self.add_col_button = QPushButton("Calculate")
        add_col_layout.addWidget(self.add_col_button,
                                 0,
                                 0,
                                 alignment=Qt.AlignRight)
        radio_layout = QVBoxLayout()
        radio_layout.setContentsMargins(0, 0, 0, 0)
        add_col_layout.addLayout(radio_layout, 0, 1, alignment=Qt.AlignLeft)
        self.button_group = QButtonGroup()
        self.add_col_button.clicked.connect(
            lambda checked, *, bg=self.button_group: self._show_subdialog(
                bg.checkedButton().text()))
        for add_type in ["H-Bonds", "Clashes", "Density"]:
            rb = QRadioButton(add_type)
            rb.clicked.connect(self._update_button_text)
            radio_layout.addWidget(rb)
            if not self.button_group.buttons():
                rb.setChecked(True)
            self.button_group.addButton(rb)
        self.ignore_solvent_button = QCheckBox("Ignore solvent")
        self.ignore_solvent_button.setChecked(True)
        add_col_layout.addWidget(self.ignore_solvent_button,
                                 1,
                                 0,
                                 1,
                                 2,
                                 alignment=Qt.AlignCenter)

        from PyQt5.QtWidgets import QDialogButtonBox as qbbox
        bbox = qbbox(qbbox.Ok | qbbox.Cancel | qbbox.Help)
        bbox.accepted.connect(self._apply_rotamer)
        bbox.rejected.connect(self.tool_window.destroy)
        from chimerax.core.commands import run
        bbox.helpRequested.connect(
            lambda run=run, ses=self.session: run(ses, "help " + self.help))
        layout.addWidget(bbox)
        self.tool_window.manage(placement=None)
Пример #23
0
    def get_chimera(self, session, coordsets=False, filereader=None):
        """returns a chimerax equivalent of self"""
        struc = AtomicStructure(session, name=self.name)
        struc.comment = self.comment

        self.update_chix(struc)

        if coordsets and filereader is not None and filereader.all_geom is not None:
            #make a trajectory
            #each list of atoms in filereader.all_geom is a frame in the trajectory
            #replace previous coordinates
            #this matters when a filereader is given because the
            #geometry created from a filereader (which was probably passed as geom)
            #is the last geometry in the log or xyz file
            xyzs = self.all_geom_coordsets(filereader)
            struc.add_coordsets(xyzs, replace=True)
            struc.active_coordset_id = len(xyzs)

        # if it's a frequency file, draw TS bonds for imaginary modes
        if filereader is not None and "frequency" in filereader.other:
            for mode in filereader.other["frequency"].data:
                if mode.frequency < 0:
                    max_disp = max(np.linalg.norm(x) for x in mode.vector)
                    cur_coords = self.coords
                    coord_forward = self.coords + (0.2 /
                                                   max_disp) * mode.vector
                    coord_reverse = self.coords - (0.2 /
                                                   max_disp) * mode.vector
                    forward_connectivity = np.zeros(
                        (len(self.atoms), len(self.atoms)))
                    reverse_connectivity = np.zeros(
                        (len(self.atoms), len(self.atoms)))
                    self.update_geometry(coord_forward)
                    self.refresh_connected()
                    for i, atom1 in enumerate(self.atoms):
                        for j, atom2 in enumerate(self.atoms[:i]):
                            if atom1 in atom2.connected:
                                forward_connectivity[i, j] = 1
                                forward_connectivity[j, i] = 1

                    self.update_geometry(coord_reverse)
                    self.refresh_connected()
                    for i, atom1 in enumerate(self.atoms):
                        for j, atom2 in enumerate(self.atoms[:i]):
                            if atom1 in atom2.connected:
                                reverse_connectivity[i, j] = 1
                                reverse_connectivity[j, i] = 1

                    changes = forward_connectivity - reverse_connectivity
                    for i, atom1 in enumerate(self.atoms):
                        for j, atom1 in enumerate(self.atoms[:i]):
                            if changes[i, j] != 0:
                                sel = _FauxAtomSelection(
                                    atoms=(struc.atoms[i], struc.atoms[j]))
                                tsbond(session, sel)

                    self.update_geometry(cur_coords)

        if filereader is not None and "Mulliken Charges" in filereader.other:
            for atom, charge in zip(struc.atoms,
                                    filereader.other["Mulliken Charges"]):
                atom.mullikenCharge = charge
                atom.charge = charge

                if not any(attr[0] == "mullikenCharge"
                           for attr in atom.custom_attrs):
                    atom.register_attr(session,
                                       "mullikenCharge",
                                       "seqcrow ResidueCollection.get_chimera",
                                       attr_type=float)
                if not any(attr[0] == "charge" for attr in atom.custom_attrs):
                    atom.register_attr(session,
                                       "charge",
                                       "seqcrow ResidueCollection.get_chimera",
                                       attr_type=float)

        if filereader is not None and "NPA Charges" in filereader.other:
            for atom, charge in zip(struc.atoms,
                                    filereader.other["NPA Charges"]):
                atom.npaCharge = charge
                atom.charge = charge

                if not any(attr[0] == "npaCharge"
                           for attr in atom.custom_attrs):
                    atom.register_attr(session,
                                       "npaCharge",
                                       "seqcrow ResidueCollection.get_chimera",
                                       attr_type=float)
                if not any(attr[0] == "charge" for attr in atom.custom_attrs):
                    atom.register_attr(session,
                                       "charge",
                                       "seqcrow ResidueCollection.get_chimera",
                                       attr_type=float)

        if filereader is not None and "Nuclear ZEff" in filereader.other:
            for atom, zeff in zip(struc.atoms,
                                  filereader.other["Nuclear ZEff"]):
                atom.Zeff = zeff

                if not any(attr[0] == "Zeff" for attr in atom.custom_attrs):
                    atom.register_attr(session,
                                       "Zeff",
                                       "seqcrow ResidueCollection.get_chimera",
                                       attr_type=float)

        if filereader is not None and "Nuclear spins" in filereader.other:
            for atom, spin in zip(struc.atoms,
                                  filereader.other["Nuclear spins"]):
                atom.nuclearSpin = spin

                if not any(attr[0] == "nuclearSpin"
                           for attr in atom.custom_attrs):
                    atom.register_attr(session,
                                       "nuclearSpin",
                                       "seqcrow ResidueCollection.get_chimera",
                                       attr_type=int)

        if filereader is not None:
            if any(attr[0] == "aarontools_filereader"
                   for attr in struc.custom_attrs):
                struc.register_attr(
                    session,
                    "filereader",
                    "SEQCROW",
                    attr_type=FileReader,
                )

            struc.filereader = filereader

        return struc
Пример #24
0
class MolecularDynamicsTool(HtmlToolInstance):
    '''
     # Properties for the tool
    '''
    SESSION_ENDURING = False
    SESSION_SAVE = False
    CUSTOM_SCHEME = "kmd"

    def __init__(self, session, tool_name):
        super().__init__(session,
                         tool_name,
                         size_hint=(500, 500),
                         show_http_in_help=False)
        self.display_name = DISPLAY_NAME
        self._build_ui()

        self.atomStruct = None
        self.atomLocation = []
        self.surfacePositions = []
        self.attributeFile = False

    # Loads the html view to be shown
    def _build_ui(self):
        html_file = os.path.join(os.path.dirname(__file__), "dynamics.html")
        self.html_view.setUrl(pathlib.Path(html_file).as_uri())

    # This is to delete the model from the view
    def delete(self):
        super(HtmlToolInstance, self).delete()
        self.deleteModel()

    '''
     # This handles when a window.location becomes kmd:<command>
     #
     # @param url - The command
    '''

    def handle_scheme(self, url):
        command = url.path()

        if command.startswith("log"):
            self.session.logger.info(command[len("log_"):])
        elif command == "Open":
            self.openFile()
        elif command.startswith("FrameChange"):
            frame = int(command[len("FrameChange_T_"):])
            self.changeModel(frame, command[12] == 'T')
        elif command == "MovieDone":
            movie_encode(self.session, output=[self.movieName], format="h264")
        elif command == "MovieStart":
            fileName, filt = QFileDialog.getSaveFileName(
                caption="Save Movie", filter="MP4 File (*.mp4)")

            if fileName == "":
                return

            if fileName[-4:] != ".mp4":
                fileName = fileName + ".mp4"

            self.movieName = fileName
            movie_record(self.session)
            self.html_view.runJavaScript("startMovie()")
        elif command == "Attribute":
            self.loadAttributeFile()
        else:
            self.session.logger.info("Unknown Command: " + str(url))

    def loadAttributeFile(self):
        fileName, filt = QFileDialog.getOpenFileName(
            caption="Open Attribute File", filter="Attribute File (*.dat)")

        if fileName == "":
            return

        fileObj = open(fileName)
        lines = fileObj.readlines()[3:]
        fileObj.close()
        mapVals = {}

        for line in lines:
            parts = line.split('\t')[1:]
            mapVals[int(parts[0][1:])] = float(parts[1])

        maxValue = max(mapVals.values())
        minValue = min(mapVals.values())
        midValue = (maxValue + minValue) / 2

        # Color from min (blue) to mid (white) to max (red)

        for key in mapVals.keys():
            value = mapVals[key]
            per = (value - minValue) / (midValue - minValue) - 1
            color = abs(per) * 255
            colorSet = [255, 255 - color, 255 - color, 255
                        ] if per > 0 else [255 - color, 255 - color, 255, 255]
            colorSet = array(colorSet)

            self.atomStruct.residues[key - 1].ribbon_color = colorSet
            self.atomStruct.residues[key - 1].atoms.colors = colorSet

        js = "attributeName = '" + fileName.split(
            "/")[-1] + "';updateDisplay()"
        self.html_view.runJavaScript(js)
        self.attributeFile = True

        if self.atomStruct.surfaces() != []:
            run(self.session,
                "color #" + self.atomStruct.surfaces()[0].id_string +
                " fromatoms",
                log=False)

    # This is to remove model for changing
    def deleteModel(self):
        if self.atomStruct == None:
            return

        if self.atomStruct.deleted:
            return

        if self.atomStruct.surfaces() != []:
            self.session.models.remove([self.atomStruct.surfaces()[0]])

        self.session.models.remove([self.atomStruct])
        self.attributeFile = False
        self.atomStruct = None
        self.atomLocation = []
        self.surfacePositions = []
        js = "modelName = null; frameCount = 0; reset();"
        self.html_view.runJavaScript(js)

    # This is to move the atoms
    def changeModel(self, frame, surf):
        locs = self.atomLocation[frame]
        atms = self.atomStruct.atoms

        atms.coords = locs

        if surf:
            ### Need to recalculate the surfce here
            if self.atomStruct.surfaces() == []:
                surface(self.session, atoms=self.atomStruct.atoms)
            else:
                surfPos = self.surfacePositions[frame]

                if surfPos is None:
                    self.session.models.remove([self.atomStruct.surfaces()[0]])
                    surface(self.session, atoms=self.atomStruct.atoms)
                    self.surfacePositions[frame] = self.atomStruct.surfaces(
                    )[0]
                else:
                    self.session.models.remove([self.atomStruct.surfaces()[0]])
                    self.atomStruct.add([surfPos])
            ###
            run(self.session,
                "color #" + self.atomStruct.surfaces()[0].id_string +
                " fromatoms",
                log=False)
        elif self.atomStruct.surfaces() != []:
            self.session.models.remove([self.atomStruct.surfaces()[0]])

    # This opens a file
    def openFile(self):
        fileName, filt = QFileDialog.getOpenFileName(caption="Open Trajectory File",
                                                     filter="PDB File (*.pdb);;" \
                                                            "H5 Trajectory File (*.h5);;" \
                                                            "HDF5 Trajectory File (*.hdf5)" \
                                                            "GRO Topology File (*.gro)"
                                                     )
        print(fileName)
        print(filt)

        if fileName == "":
            return

        if filt == "(*.gro)":
            gro_fileName = fileName
            fileName, filt = QFileDialog.getOpenFileName(caption="Open Trajectory File",
                                                         filter="XTC Trajectory File (*.xtc);;" \
                                                                "TRR Trajectory File (*.trr);;" \
                                                         )
            print(fileName)
            print(filt)
        else:
            gro_fileName = None

        if self.atomStruct != None:
            self.deleteModel()

        # This create a simple Oxygen atom
        # Need to get this to display
        self.atomStruct = AtomicStructure(self.session)

        if filt in ["(*.xtc)", "(*.trr)"]:
            trj = mdtraj.load(fileName, topology=gro_fileName)
        else:
            trj = mdtraj.load(fileName)
        trj.atom_slice(trj.topology.select("not element H"))

        table, bond_table = trj.topology.to_dataframe()
        table.rename(columns={
            "name": "atomname",
            "resName": "residue_name",
            "chainID": "chain_id",
            "resSeq": "pos"
        },
                     inplace=True)
        table["pos"] = table["pos"].astype(int)
        xyz = trj.xyz[0]
        table["loc"] = [array(x, dtype=float64) for x in xyz]
        res_infos = table[["residue_name", "chain_id", "pos"
                           ]].drop_duplicates(keep="first").to_dict("records")
        for res in res_infos:
            residue = self.atomStruct.new_residue(**res)
            qry = ' and '.join(
                ['{} == {}'.format(k, v) for k, v in res.items()])
            res_atoms = table.query(qry)[["name", "element",
                                          "loc"]].to_dict("records")
            for a in res_atoms:
                atom = self.atomStruct.new_atom({
                    "name": a["name"],
                    "element": a["element"]
                })
                atom.coord = a["loc"]
                residue.add_atom(atom)

        for frame in range(1, trj.n_frames):
            xyz = trj.xyz[frame]
            self.atomLocation.append(array(xyz, dtype=float64))

        self.atomStruct.connect_structure()
        self.session.models.add([self.atomStruct])

        for i in range(len(self.atomLocation)):
            self.surfacePositions.append(None)

        self.atomStruct.atoms.coords = self.atomLocation[0]
        fileName = fileName.split("/")[-1]

        js = "modelName = '" + fileName + "'; frameCount = " + str(
            len(self.atomLocation)) + "; reset();"
        self.html_view.runJavaScript(js)
        run(self.session, "lighting full", log=False)
Пример #25
0
def register_model_isolde_init_attr(session):
    from chimerax.atomic import AtomicStructure
    AtomicStructure.register_attr(session, 'isolde_initialized',
        'isolde', attr_type=bool)
Пример #26
0
 def set_state_from_snapshot(self, session, data):
     AtomicStructure.set_state_from_snapshot(self, session,
                                             data['atomic structure state'])