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
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
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
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