Esempio n. 1
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)))
Esempio n. 2
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
Esempio n. 3
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)
Esempio n. 4
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
Esempio n. 5
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
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)