1# Copyright 2017 Jacob D. Durrant 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15from __future__ import absolute_import 16from scoria import dumbpy as numpy 17from .FileIO import FileIO 18from .AtomsAndBonds import AtomsAndBonds 19from .Selections import Selections 20from .Manipulation import Manipulation 21from .Information import Information 22from .OtherMolecules import OtherMolecules 23from .Geometry import Geometry 24import copy 25 26 27class Molecule: # here's the actual Molecule class 28 """ 29 Loads, saves, and manupulates molecuar models. The main scoria 30 class. Contains Wrapper functions for subclasses. 31 32 Examples assume:: 33 34 >>> import scoria 35 >>> PDB = "./test_file.pdb" 36 >>> mol = scoria.Molecule() 37 >>> mol.load_pdb_into(PDB) 38 """ 39 40 def __init__(self, *args): 41 """ 42 Initializes the variables of the Molecule class. 43 44 :param files args: Additional files added to the end of the paramter 45 will be input with the method indicated by the fileType parameter. 46 """ 47 48 self.fileio = FileIO(self) 49 self.atoms_and_bonds = AtomsAndBonds(self) 50 self.selections = Selections(self) 51 self.manipulation = Manipulation(self) 52 self.information = Information(self) 53 self.other_molecules = OtherMolecules(self) 54 self.geometry = Geometry(self) 55 56 # Based on the file type, we will attempt to open the file. 57 if len(args) > 0: 58 if len(args) == 1: 59 file = args[0] 60 file_type = file.split('.')[-1].upper() 61 62 if file_type == 'PDB': 63 self.load_pdb_trajectory_into(file) 64 elif file_type == 'PDBQT': 65 self.load_pdbqt_trajectory_into(file) 66 elif file_type == 'PYM': 67 self.load_pym_into(file) 68 69 # Information methods 70 ### Wrappers ### 71 # Gets 72 def get_coordinates(self, frame = None): 73 """ 74 Returns the set of coordinates from the specified frame. 75 76 Wrapper function for :meth:`~scoria.Information.Information.get_coordinates` 77 78 :param int frame: The timestep from which the coordinates shoule be 79 returned. If ommitted, it defaults to the first 80 frame of the trajectory. 81 82 :returns: The set of coordinates from the specified frame. 83 :: 84 85 [[x1, y1, z1], ... [xn, yn, zn]] 86 87 :rtype: :any:`numpy.array` 88 89 :: 90 91 >>> print(mol.get_coordinates()) 92 [[ -30.85199928 -81.45800018 365.05499268] 93 [ -31.99500084 -80.69300079 365.66900635] 94 [ -32.0530014 -81.13200378 367.18200684] 95 ..., 96 [ -27.54199982 -96.25099945 402.83700562] 97 [ -23.54199982 -94.7539978 400.41900635] 98 [ -22.86100006 -93.72499847 400.55300903]] 99 100 >>> print(mol.get_coordinates(2)) 101 [[ -28.88899994 -80.45700073 365.51699829] 102 [ -30.20000076 -79.73699951 365.99700928] 103 [ -30.90699959 -80.5510025 367.13000488] 104 ..., 105 [ -26.0189991 -97.28099823 403.52600098] 106 [ -23.2140007 -94.73999786 400.94699097] 107 [ -22.52899933 -93.73300171 400.81399536]] 108 """ 109 110 return self.information.get_coordinates(frame) 111 112 def get_trajectory_coordinates(self): 113 """ 114 Returns the trajectory for the molecule. 115 116 Wrapper function for :meth:`~scoria.Information.Information.get_trajectory_coordinates` 117 118 :returns: The set of all coordinates. 119 :: 120 121 [[[x11, y11, z11], ... [x1n, y1n, z1n]], 122 ..., 123 [[xm1, ym1, zm1], ... [xmn, ymn, zmn]]] 124 125 :rtype: :any:`numpy.array` 126 127 :: 128 129 >>> for coord in mol.get_trajectory_coordinates(): 130 >>> print(coord) 131 >>> print() 132 [[ -30.85199928 -81.45800018 365.05499268] 133 [ -31.99500084 -80.69300079 365.66900635] 134 [ -32.0530014 -81.13200378 367.18200684] 135 ..., 136 [ -27.54199982 -96.25099945 402.83700562] 137 [ -23.54199982 -94.7539978 400.41900635] 138 [ -22.86100006 -93.72499847 400.55300903]] 139 140 [[ -30.6779995 -81.32499695 365.73199463] 141 [ -31.88100052 -80.38600159 366.0289917 ] 142 [ -32.40399933 -80.62799835 367.45700073] 143 ..., 144 [ -27.44400024 -96.71099854 402.64700317] 145 [ -23.79199982 -94.58899689 400.63598633] 146 [ -23.10700035 -93.56300354 400.79598999]] 147 <more> 148 """ 149 150 return self.information.get_trajectory_coordinates() 151 152 def get_filename(self): 153 """ 154 Returns the filename that the molecule was originally loaded from. 155 156 Wrapper function for :meth:`~scoria.Information.Information.get_filename` 157 158 :returns: The name of the file. 159 160 :rtype: :any:`str` 161 162 :: 163 164 >>> mol = scoria.Molecule() 165 >>> mol.load_pdb_into("single_frame.pdb") 166 >>> print(mol.get_filename()) 167 single_frame.pdb 168 """ 169 170 return self.information.get_filename() 171 172 def get_remarks(self): 173 """ 174 Returns the remarks from the file the molecule was loaded from. 175 176 Wrapper function for :meth:`~scoria.Information.Information.get_remarks` 177 178 :returns: The remarks from the file an a list of strings. 179 180 :rtype: :any:`list` 181 182 :: 183 184 >>> mol = scoria.Molecule() 185 >>> mol.load_pdb_into("single_frame.pdb") 186 >>> print(mol.get_remarks()) 187 [' This is a remark.'] 188 """ 189 190 return self.information.get_remarks() 191 192 def get_atom_information(self): 193 """ 194 Retreives the atomic information for the molecule. 195 196 Wrapper function for :meth:`~scoria.Information.Information.get_atom_information` 197 198 :returns: A masked array containing the atom information. 199 200 :rtype: :any:`numpy.ma.MaskedArray` 201 202 The contents of the array are as follows: 203 204 ================ ===== ================= ============================== 205 member name dtype Full Type Description 206 ================ ===== ================= ============================== 207 record_name S6 six char string What the atom belongs to 208 serial <i8 64-bit integer The index of the atom 209 name S5 five char string The atom name 210 resname S5 five char string The residue name 211 chainid S1 one char string The chain identifier 212 resseq <i8 64-bit integer The Residue sequence number 213 occupancy <f8 64-bit float Occupancy of atom 214 tempfactor <f8 64-bit float Tempature Factor 215 element S2 two char string The element symbol 216 charge S3 three char string Charge on the atom 217 name_stripped S5 five char string Atom name without space 218 resname_stripped S5 five char string Residue name without space 219 chainid_stripped S1 one char string Chain identifier without space 220 element_stripped S2 two char string Element symbol without space 221 ================ ===== ================= ============================== 222 223 An example for printing the elemental symbols of the first five atoms:: 224 225 >>> atom_info = mol.get_atom_information() 226 >>> print(atom_info['element'][0:5]) 227 ['N' 'C' 'C' 'O' 'C'] 228 """ 229 230 return self.information.get_atom_information() 231 232 def get_coordinates_undo_point(self): 233 """ 234 NEEDS CLARIFICATION. 235 Retreives a previously save set of coordinates to revert to. 236 237 Wrapper function for :meth:`~scoria.Information.Information.get_coordinates_undo_point` 238 239 :returns: A set of coordinates from which to return to. 240 241 :rtype: :any:`numpy.array` or :any:`None` 242 """ 243 244 return self.information.get_coordinates_undo_point() 245 246 def get_bonds(self): 247 """ 248 Retreives the bonds beteween atoms as a n x n matrix. 249 250 Wrapper function for :meth:`~scoria.Information.Information.get_bonds` 251 252 :returns: A binary n x n matrix, where bonds are represented by 1. 253 254 :rtype: :any:`numpy.array` 255 256 An example for finding all atoms bonded with atom 153:: 257 258 >>> bonds = mol.get_bonds() 259 >>> for i in range(0,len(bonds)): 260 ... if bonds[153][i] == 1: 261 ... print(153,"-",i) 262 153 - 152 263 153 - 154 264 153 - 155 265 """ 266 267 return self.information.get_bonds() 268 269 def get_hierarchy(self): 270 """ 271 NEEDS CLARIFICATION. 272 273 Wrapper function for :meth:`~scoria.Information.Information.get_hierarchy` 274 275 :returns: A dictionary? 276 277 :rtype: :any:`dict` 278 """ 279 280 return self.information.get_hierarchy() 281 282 def get_constants(self): 283 """ 284 Returns a dictionary containing the constants assumed for the molecular model. 285 286 Wrapper function for :meth:`~scoria.Information.Information.get_constants` 287 288 :returns: The constants assumed by the model. 289 290 :rtype: :any:`dict` 291 292 ============================== =============== =============================== 293 Dictionary Keys Value Type Contains 294 ============================== =============== =============================== 295 mass_dict dict{str:float} The mass of elements 296 rna_residues list(str) RNA residue names 297 f8_fields list(str) Atom Information floats 298 vdw_dict dict{str:float} Van der Waals force of elements 299 i8_fields list(str) Atom Information integers 300 protein_residues list(str) Protein residue names 301 bond_length_dict dict{str:float} Element-pair bond length 302 element_names_with_two_letters list(str) Element symbols with 2 letters 303 max_number_of_bonds_permitted dict{str:int} Max bonds per element 304 dna_residues list(str) DNA reside names 305 ============================== =============== =============================== 306 307 """ 308 309 return self.information.get_constants() 310 311 def get_center_of_mass(self, selection = None, frame = None): 312 """ 313 Determines the center of mass. 314 315 Wrapper function for :meth:`~scoria.Information.Information.get_center_of_mass` 316 317 :param numpy.array selection: The indices of 318 the atoms to consider when calculating the center of mass. 319 If ommitted, all atoms of the scoria.Molecule object 320 will be considered. 321 322 :param int frame: The timestep at which the center of mass 323 should be calculated. If ommitted, it defaults to the first 324 frame of the trajectory. 325 326 :returns: The x, y, and z coordinates of the center of mass. 327 328 :rtype: :any:`numpy.ma.MaskedArray` 329 330 :: 331 332 >>> mol = scoria.Molecule() 333 >>> mol.load_pdb_into("single_frame.pdb") 334 >>> print(mol.get_center_of_mass()) 335 [33.0643089093134 19.135747088722564 16.05629867850796] 336 """ 337 338 return self.information.get_center_of_mass(selection, frame) 339 340 def get_geometric_center(self, selection = None, frame = None): 341 """ 342 Determines the geometric center of the molecule. 343 344 Wrapper function for :meth:`~scoria.Information.Information.get_geometric_center` 345 346 :param numpy.array selection: The indices of 347 the atoms to consider when calculating the geometric. 348 If ommitted, all atoms of the scoria.Molecule object 349 will be considered. 350 351 :param int frame: The timestep at which the geometric center 352 should be calculated. If ommitted, it defaults to the first 353 frame of the trajectory. 354 355 :returns: The x, y, and z coordinates of the geometric center. 356 357 :rtype: :any:`numpy.array` 358 359 :: 360 361 >>> mol = scoria.Molecule() 362 >>> mol.load_pdb_into("single_frame.pdb") 363 >>> print(mol.get_geometric_center()) 364 [ 33.09860848 19.1221197 16.0426808 ] 365 """ 366 367 return self.information.get_geometric_center(selection, frame) 368 369 def get_total_mass(self, selection = None): 370 """ 371 Returns the total mass of all atoms within the molecule, or of a given 372 selection. 373 374 Wrapper function for :meth:`~scoria.Information.Information.get_total_mass` 375 376 :param numpy.array selection: The indices of 377 the atoms to consider when calculating the geometric. 378 If ommitted, all atoms of the scoria.Molecule object 379 will be considered. 380 381 :returns: The total mass of the atom or selection 382 383 :rtype: :any:`float` 384 385 :: 386 387 >>> print(mol.get_total_mass()) 388 5289.1729999999998 389 390 """ 391 392 return self.information.get_total_mass(selection) 393 394 def get_total_number_of_atoms(self, selection = None): 395 """ 396 Counts the number of atoms. 397 398 Wrapper function for 399 :meth:`~scoria.Information.Information.get_total_number_of_atoms` 400 401 :param numpy.array selection: An optional numpy.array containing the indices of 402 the atoms to count. If ommitted, all atoms of the 403 scoria.Molecule object will be considered. 404 :param int frame: An integer indicating at which timestep the center of 405 mass should be calculated. If ommitted, it defaults to the 406 first frame of the trajectory. 407 408 :returns: The total number of atoms. 409 :rtype: :any:`int` 410 """ 411 412 return self.information.get_total_number_of_atoms(selection) 413 414 def get_total_number_of_heavy_atoms(self, selection = None): 415 """ 416 Counts the number of heavy atoms (i.e., atoms that are not 417 hydrogens). 418 419 Wrapper function for 420 :meth:`~scoria.Information.Information.get_total_number_of_heavy_atoms` 421 422 :param numpy.array selection: An optional numpy.array containing the indices of 423 the atoms to count. If ommitted, all atoms of the 424 scoria.Molecule object will be considered. 425 426 :returns: The total number of heavy (non-hydrogen) atoms. 427 :rtype: :any:`int` 428 """ 429 430 return self.information.get_total_number_of_heavy_atoms(selection) 431 432 def get_bounding_box(self, selection = None, padding = 0.0, frame = None): 433 """ 434 Calculates a box that bounds (encompasses) a set of atoms. 435 436 Wrapper function for :meth:`~scoria.Information.Information.get_bounding_box` 437 438 :param numpy.array selection: An optional numpy.array containing the indices of 439 the atoms to consider. If ommitted, all atoms of the 440 scoria.Molecule object will be considered. 441 :param float padding: An optional float. The bounding box will extend this 442 many angstroms beyond the atoms being considered. 443 :param int frame: An integer indicating at which timestep the center of 444 mass should be calculated. If ommitted, it defaults to the 445 first frame of the trajectory. 446 447 :returns: A numpy array representing two 3D points, (min_x, min_y, min_z) 448 and (max_x, max_y, max_z), that bound the molecule. 449 :rtype: :any:`numpy.array` 450 """ 451 452 return self.information.get_bounding_box(selection, padding, frame) 453 454 def get_bounding_sphere(self, selection = None, padding = 0.0, frame = None): 455 """ 456 Calculates a sphere that bounds (encompasses) a set of atoms. 457 458 Requires the :any:`numpy` and :any:`scipy<scipy.spatial>` libraries. 459 460 Wrapper function for :meth:`~scoria.Information.Information.get_bounding_sphere` 461 462 :param numpy.array selection: An optional numpy.array containing the indices of 463 the atoms to consider. If ommitted, all atoms of the 464 scoria.Molecule object will be considered. 465 :param float padding: An optional float. The bounding sphere will extend 466 this many angstroms beyond the atoms being considered. 467 :param int frame: An integer indicating at which timestep the center of 468 mass should be calculated. If ommitted, it defaults to the 469 first frame of the trajectory. 470 471 :returns: A tuple containing two elements. The first is a numpy.array 472 representing a 3D point, the (x, y, z) center of the 473 sphere. The second is a float, the radius of the sphere. 474 :rtype: :any:`tuple` (:any:`numpy.array`, :any:`float`) 475 """ 476 477 return self.information.get_bounding_sphere(selection, padding, frame) 478 479 def get_default_trajectory_frame(self): 480 """ 481 Retreives the default trajectory frame index. 482 483 Wrapper function for :meth:`~scoria.Information.Information.get_default_trajectory_frame` 484 485 :returns: An *int* representing the index of the default trajectory frame. 486 """ 487 488 return self.information.get_default_trajectory_frame() 489 490 491 # Set 492 def set_filename(self, filename): 493 """ 494 Sets the __filename variable. Note: this does not reload or modify the 495 molecule in anyway. 496 497 Wrapper function for :meth:`~scoria.Information.Information.set_filename` 498 499 :param str filename: String representation of the filename. 500 """ 501 502 self.information.set_filename(filename) 503 504 def set_remarks(self, remarks): 505 """ 506 Sets the __remarks variable. 507 508 Wrapper function for :meth:`~scoria.Information.Information.set_remarks` 509 510 :param list(str) remarks: List containing remarks. 511 """ 512 513 self.information.set_remarks(remarks) 514 515 def set_atom_information(self, atom_information): 516 """ 517 Sets the __atom_information variable. See 518 :meth:`~scoria.Molecule.Molecule.get_atom_information` for 519 information on the numpy.array structure. 520 521 Wrapper function for :meth:`~scoria.Information.Information.set_atom_information` 522 523 :param numpy.array atom_information: An array containing details 524 on the constituent atoms. 525 """ 526 527 self.information.set_atom_information(atom_information) 528 529 def set_coordinates(self, coordinates, frame = None): 530 """ 531 Sets a specified frame of the __trajectory variable. 532 533 Wrapper function for :meth:`~scoria.Information.Information.set_coordinates` 534 535 :param numpy.array coordinates: An array of atomic coordinates. 536 :param int frame: An integer represeting the frame of the trajectory to be modified 537 """ 538 539 self.information.set_coordinates(coordinates, frame) 540 541 def set_trajectory_coordinates(self, trajectory): 542 """ 543 Sets the __trajectory variable. 544 545 Wrapper function for :meth:`~scoria.Information.Information.set_trajectory_coordinates` 546 547 :param numpy.array trajectory: An array of atomic coordinates. 548 """ 549 550 self.information.set_trajectory_coordinates(trajectory) 551 552 def set_coordinates_undo_point(self, coordinates_undo_point): 553 """ 554 Sets the __coordinates_undo_point variable. 555 556 Wrapper function for :meth:`~scoria.Information.Information.set_coordinates_undo_point` 557 558 :param numpy.array coordinates_undo_point: A coordinate set to revert 559 to after modification. 560 """ 561 562 self.information.set_coordinates_undo_point(coordinates_undo_point) 563 564 def set_bonds(self, bonds): 565 """ 566 Sets the __bonds variable. See 567 :meth:`~scoria.Molecule.Molecule.get_bonds` for additional 568 information. 569 570 Wrapper function for :meth:`~scoria.Information.Information.set_bonds` 571 572 :param numpy.array bonds: A binary n x n matrix containing bonding 573 information. 574 """ 575 576 self.information.set_bonds(bonds) 577 578 def set_hierarchy(self, hierarchy): 579 """ 580 DEPRECIATED? 581 582 Wrapper function for :meth:`~scoria.Information.Information.set_hierarchy` 583 """ 584 585 self.information.set_hierarchy(hierarchy) 586 587 def set_default_trajectory_frame(self, frame): 588 """ 589 Set's the default trajectory frame for various calculations. 590 591 Wrapper function for :meth:`~scoria.Information.Information.set_default_trajectory_frame` 592 593 :param int frame: The default frame for coordinate selection. 594 """ 595 596 self.information.set_default_trajectory_frame(frame) 597 598 # Information functions 599 def assign_masses(self): 600 """ 601 Assigns masses to the atoms of the scoria.Molecule object. 602 603 Wrapper function for :meth:`~scoria.Information.Information.assign_masses` 604 605 ``Note``: 606 This will autopopulate the masses according to their element 607 identification and takes no input. 608 """ 609 610 self.information.assign_masses() 611 612 def assign_elements_from_atom_names(self, selection = None): 613 """ 614 Determines the elements of all atoms from the atom names. Note that 615 this will overwrite any existing element assignments, including those 616 explicitly specified in loaded files. Note that this doesn't populate 617 elements_stripped. 618 619 Wrapper function for :meth:`~scoria.Information.Information.assign_elements_from_atom_names` 620 621 :param numpy.array selection: An optional numpy.array containing the indices of 622 the atoms to consider when calculating the center of mass. 623 If ommitted, all atoms of the scoria.Molecule object 624 will be considered. 625 """ 626 627 self.information.assign_elements_from_atom_names(selection) 628 629 def define_molecule_chain_residue_spherical_boundaries(self): 630 """ 631 Identifies spheres that bound (encompass) the entire molecule, the 632 chains, and the residues. This information is stored in 633 scoria.Information.Information.hierarchy. 634 635 Requires the :any:`numpy` and :any:`scipy<scipy.spatial>` libraries. 636 637 Wrapper function for 638 :meth:`~scoria.Information.Information.define_molecule_chain_residue_spherical_boundaries` 639 """ 640 641 self.information.define_molecule_chain_residue_spherical_boundaries() 642 643 def serial_reindex(self): 644 """ 645 Reindexes the serial field of the atoms in the molecule, starting 646 with 1. 647 648 Wrapper function for :meth:`~scoria.Information.Information.serial_reindex` 649 """ 650 651 self.information.serial_reindex() 652 653 def resseq_reindex(self): 654 """ 655 Reindexes the resseq field of the atoms in the molecule, starting 656 with 1. 657 658 Wrapper function for :meth:`~scoria.Information.Information.resseq_reindex` 659 """ 660 661 self.information.resseq_reindex() 662 663 def belongs_to_protein(self, atom_index): 664 """ 665 Checks if the atom is part of a protein. Taken primarily from Amber 666 residue names. 667 668 Wrapper function for :meth:`~scoria.Information.Information.belongs_to_protein` 669 670 :param int atom_index: An int, the index of the atom to consider. 671 672 :returns: A boolean. True if part of protein, False if not. 673 """ 674 675 return self.information.belongs_to_protein(atom_index) 676 677 def belongs_to_rna(self, atom_index): 678 """ 679 Checks if the atom is part of RNA. 680 681 Wrapper function for :meth:`~scoria.Information.Information.belongs_to_rna` 682 683 :param int atom_index: An int, the index of the atom to consider. 684 685 :returns: A boolean. True if part of rna, False if not. 686 687 """ 688 689 return self.information.belongs_to_rna(atom_index) 690 691 def belongs_to_dna(self, atom_index): 692 """ 693 Checks if the atom is part of DNA. 694 695 Wrapper function for :meth:`~scoria.Information.Information.belongs_to_dna` 696 697 :param int atom_index: An int, the index of the atom to consider. 698 699 :returns: A boolean. True if part of dna, False if not. 700 """ 701 702 return self.information.belongs_to_dna(atom_index) 703 704 def insert_trajectory_frame(self, index, coordinates): 705 """ 706 Inserts a new coordinate frame at the end of the trajectory. 707 708 Wrapper function for :meth:`~scoria.Information.Information.insert_trajectory_frame` 709 710 :param numpy.array coordinates: A single frame of coordinates to append. 711 :param int index: The location where the frame should be added. 712 """ 713 714 return self.information.insert_trajectory_frame(index, coordinates) 715 716 def delete_trajectory_frame(self, index): 717 """ 718 Removes a given frame from the trajectory. 719 720 Wrapper function for :meth:`~scoria.Information.Information.delete_trajectory_frame` 721 722 :param int index: Integer of the frame to remove. 723 """ 724 725 return self.information.delete_trajectory_frame(index) 726 727 def get_trajectory_frame_count(self): 728 """ 729 Returns the number of frames in __trajectory. 730 731 Wrapper function for :meth:`~scoria.Information.Information.get_trajectory_frame_count` 732 733 :returns: The number of frames in the trajectory. 734 :rtype: :any:`int` 735 """ 736 737 return self.information.get_trajectory_frame_count() 738 739 # File I/O class methods 740 def load_pym_into(self, filename): 741 """ 742 Loads the molecular data contained in a pym file into the current 743 scoria.Molecule object. 744 745 Requires the :any:`numpy` library. 746 747 Wrapper function for :meth:`~scoria.FileIO.FileIO.load_pym_into` 748 749 :param str filename: A string, the filename of the pym file. 750 """ 751 752 self.fileio.load_pym_into(filename) 753 754 def load_pdb_into(self, filename, bonds_by_distance = True, 755 serial_reindex = True, resseq_reindex = False, 756 is_trajectory = False): 757 """ 758 Loads the molecular data contained in a pdb file into the current 759 scoria.Molecule object. 760 761 Wrapper function for :meth:`~scoria.FileIO.FileIO.load_pdb_into` 762 763 :param str filename: A string, the filename of the pdb file. 764 :param bool bonds_by_distance: An optional boolean, whether or not to 765 determine atomic bonds based on atom proximity. True by 766 default. 767 :param bool serial_reindex: An optional boolean, whether or not to 768 reindex the pdb serial field. True by default. 769 :param bool resseq_reindex: An optional boolean, whether or not to 770 reindex the pdb resseq field. False by default. 771 :param bool is_trajectory: An optional boolean, whether or not the PDB 772 is multi-frame. 773 """ 774 775 self.fileio.load_pdb_into( 776 filename, bonds_by_distance, serial_reindex, 777 resseq_reindex, is_trajectory 778 ) 779 780 def load_pdb_into_using_file_object(self, file_obj, 781 bonds_by_distance = True, 782 serial_reindex = True, 783 resseq_reindex = False, 784 is_trajectory = False): 785 """ 786 Loads molecular data from a python file object (pdb formatted) into 787 the current scoria.Molecule object. Note that most users will want 788 to use the load_pdb_into() function instead, which is identical except 789 that it accepts a filename string instead of a python file object. 790 791 Requires the :any:`numpy` library. 792 793 Wrapper function for :meth:`~scoria.FileIO.FileIO.load_pdb_into_using_file_object` 794 795 :param file file_obj: A python file object, containing pdb-formatted 796 data. 797 :param bool bonds_by_distance: An optional boolean, whether or not to 798 determine atomic bonds based on atom proximity. True by 799 default. 800 :param bool serial_reindex: An optional boolean, whether or not to 801 reindex the pdb serial field. True by default. 802 :param bool resseq_reindex: An optional boolean, whether or not to 803 reindex the pdb resseq field. False by default. 804 :param bool is_trajectory: An optional boolean, whether or not the PDB 805 is multi-frame. 806 """ 807 808 self.fileio.load_pdb_into_using_file_object( 809 file_obj, bonds_by_distance, serial_reindex, 810 resseq_reindex, is_trajectory 811 ) 812 813 def load_pdbqt_into(self, filename, bonds_by_distance = False, 814 serial_reindex = True, resseq_reindex = False, 815 is_trajectory = False): 816 """ 817 Loads the molecular data contained in a pdbqt file into the current 818 scoria.Molecule object. Note that this implementation is 819 incomplete. It doesn't save atomic charges, for example. The atom 820 types are stored in the "element_padded" and "element" columns. 821 822 Wrapper function for :meth:`~scoria.FileIO.FileIO.load_pdbqt_into` 823 824 :param str filename: A string, the filename of the pdbqt file. 825 :param bool bonds_by_distance: An optional boolean, whether or not to 826 determine atomic bonds based on atom proximity. False by 827 default, unlike for PDB. 828 :param bool serial_reindex: An optional boolean, whether or not to 829 reindex the pdb serial field. True by default. 830 :param bool resseq_reindex: An optional boolean, whether or not to 831 reindex the pdbqt resseq field. False by default. 832 :param bool is_trajectory: An optional boolean, whether or not the PDB 833 is multi-frame. Defaults of False. 834 """ 835 836 self.fileio.load_pdbqt_into( 837 filename, bonds_by_distance, serial_reindex, resseq_reindex, 838 is_trajectory = is_trajectory 839 ) 840 841 def load_pdbqt_into_using_file_object(self, file_obj, 842 bonds_by_distance = False, 843 serial_reindex = True, 844 resseq_reindex = False, 845 is_trajectory = False): 846 """ 847 Loads molecular data from a python file object (pdbqt formatted) 848 into the current scoria.Molecule object. Note that most users will 849 want to use the load_pdb_into() function instead, which is identical 850 except that it accepts a filename string instead of a python file 851 object. 852 853 Requires the :any:`numpy` library. 854 855 Wrapper function for :meth:`~scoria.FileIO.FileIO.load_pdbqt_into_using_file_object` 856 857 :param file file_obj: A python file object, containing pdb-formatted 858 data. 859 :param bool bonds_by_distance: An optional boolean, whether or not to 860 determine atomic bonds based on atom proximity. False by 861 default, unlike for PDB. 862 :param bool serial_reindex: An optional boolean, whether or not to 863 reindex the pdb serial field. True by default. 864 :param bool resseq_reindex: An optional boolean, whether or not to 865 reindex the pdb resseq field. False by default. 866 :param bool is_trajectory: An optional boolean, whether or not the PDB 867 is multi-frame. Defaults of False. 868 """ 869 870 self.fileio.load_pdbqt_into_using_file_object( 871 file_obj, bonds_by_distance, serial_reindex, resseq_reindex, 872 is_trajectory = is_trajectory 873 ) 874 875 def save_pym(self, filename, save_bonds = False, save_filename = False, 876 save_remarks = False, save_hierarchy = False, 877 save_coordinates_undo_point = False): 878 """ 879 Saves the molecular data contained in a scoria.Molecule object 880 to a pym file. 881 882 Requires the :any:`numpy` library. 883 884 Wrapper function for :meth:`~scoria.FileIO.FileIO.save_pym` 885 886 :param str filename: An string, the filename to use for saving. (Note 887 that this is actually a directory, not a file.) 888 :param bool save_bonds: An optional boolean, whether or not to save 889 information about atomic bonds. False by default. 890 :param bool save_filename: An optional boolean, whether or not to save 891 the original (pdb) filename. False by default. 892 :param bool save_remarks: An optional boolean, whether or not to save 893 remarks associated with the molecule. False by default. 894 :param bool save_hierarchy: An optional boolean, whether or not to save 895 information about spheres the bound (encompass) the whole 896 molecule, the chains, and the residues. False by default. 897 :param bool save_coordinates_undo_point: An optional boolean, whether or 898 not to save the last coordinate undo point. False by 899 default. 900 """ 901 902 self.fileio.save_pym( 903 filename, save_bonds, save_filename, save_remarks, 904 save_hierarchy, save_coordinates_undo_point 905 ) 906 907 def save_pdb(self, filename = "", serial_reindex = True, 908 resseq_reindex = False, return_text = False, frame = None): 909 """ 910 Saves the molecular data contained in a scoria.Molecule object 911 to a pdb file. 912 913 Wrapper function for :meth:`~scoria.FileIO.FileIO.save_pdb` 914 915 :param str filename: An string, the filename to use for saving. 916 :param bool serial_reindex: An optional boolean, whether or not to 917 reindex the pdb serial field. True by default. 918 :param bool resseq_reindex: An optional boolean, whether or not to 919 reindex the pdb resseq field. False by default. 920 :param bool return_text: An optional boolean, whether or not to return 921 text instead of writing to a file. If True, the filename 922 variable is ignored. 923 :param int frame: If specified, a single-frame PDB will be generated. 924 If not specified, a multi-frame PDB will be generated if 925 the Molecule has multiple frames. Otherwise, the single 926 existing frame will be used. 927 928 929 :returns: If return_text is True, a PDB-formatted string. Otherwise, 930 returns nothing. 931 :rtype: :any:`str` or :any:`None` 932 """ 933 934 return self.fileio.save_pdb( 935 filename, serial_reindex, resseq_reindex, return_text, frame 936 ) 937 938 def load_pdbqt_trajectory_into(self, filename, bonds_by_distance = True, 939 serial_reindex = True, 940 resseq_reindex = False): 941 """ 942 Loads the molecular data contained in a pdbqt trajectoy file (e.g., an 943 AutoDock Vina output file) into the current scoria.Molecule 944 object. 945 946 Should be called via the wrapper function :meth:`scoria.Molecule.Molecule.load_pdbqt_trajectory_into` 947 948 :param str filename: A string, the filename of the pdbqt file. 949 :param bool bonds_by_distance: An optional boolean, whether or not to 950 determine atomic bonds based on atom proximity. True by 951 default. 952 :param bool serial_reindex: An optional boolean, whether or not to 953 reindex the pdb serial field. True by default. 954 :param bool resseq_reindex: An optional boolean, whether or not to 955 reindex the pdb resseq field. False by default. 956 """ 957 958 return self.fileio.load_pdbqt_trajectory_into(filename, 959 bonds_by_distance, 960 serial_reindex, 961 resseq_reindex) 962 963 def load_pdbqt_trajectory_into_using_file_object(self, file_obj, 964 bonds_by_distance = True, 965 serial_reindex = True, 966 resseq_reindex = False): 967 """ 968 Loads molecular data from a python file object (pdbqt trajectory 969 formatted) into the current scoria.Molecule object. Note that most 970 users will want to use the load_pdbqt_trajectory_into() function 971 instead, which is identical except that it accepts a filename string 972 instead of a python file object. 973 974 Wrapper function for 975 :meth:`~scoria.FileIO.FileIO.load_pdbqt_trajectory_into_using_file_object` 976 977 :param file file_obj: A python file object, containing pdbqt-formatted 978 trajectory data. 979 :param bool bonds_by_distance: An optional boolean, whether or not to 980 determine atomic bonds based on atom proximity. True by 981 default. 982 :param bool serial_reindex: An optional boolean, whether or not to 983 reindex the pdb serial field. True by default. 984 :param bool resseq_reindex: An optional boolean, whether or not to 985 reindex the pdb resseq field. False by default. 986 """ 987 988 return self.fileio.load_pdbqt_trajectory_into_using_file_object(file_obj, 989 bonds_by_distance, 990 serial_reindex, 991 resseq_reindex) 992 993 def load_pdb_trajectory_into(self, filename, bonds_by_distance = True, 994 serial_reindex = True, 995 resseq_reindex = False): 996 """ 997 Loads the molecular data contained in a pdb trajectory file into the 998 current scoria.Molecule object. 999 1000 Should be called via the wrapper function :meth:`scoria.Molecule.Molecule.load_pdb_trajectory_into` 1001 1002 :param str filename: A string, the filename of the pdb trajectory 1003 file. 1004 :param bool bonds_by_distance: An optional boolean, whether or not to 1005 determine atomic bonds based on atom proximity. True by 1006 default. 1007 :param bool serial_reindex: An optional boolean, whether or not to 1008 reindex the pdb serial field. True by default. 1009 :param bool resseq_reindex: An optional boolean, whether or not to 1010 reindex the pdb resseq field. False by default. 1011 """ 1012 1013 return self.fileio.load_pdb_trajectory_into(filename, bonds_by_distance, 1014 serial_reindex, resseq_reindex) 1015 1016 def load_pdb_trajectory_into_using_file_object(self, file_obj, 1017 bonds_by_distance = True, 1018 serial_reindex = True, 1019 resseq_reindex = False): 1020 """ 1021 Loads molecular data from a python file object (pdb trajectory 1022 formatted) into the current scoria.Molecule object. Note that most 1023 users will want to use the load_pdb_trajectory_into() function 1024 instead, which is identical except that it accepts a filename string 1025 instead of a python file object. 1026 1027 Should be called via the wrapper function :meth:`scoria.Molecule.Molecule.load_pdb_trajectory_into_using_file_object` 1028 1029 :param file file_obj: A python file object, containing pdb-formatted 1030 trajectory data. 1031 :param bool bonds_by_distance: An optional boolean, whether or not to 1032 determine atomic bonds based on atom proximity. True by 1033 default. 1034 :param bool serial_reindex: An optional boolean, whether or not to 1035 reindex the pdb serial field. True by default. 1036 :param bool resseq_reindex: An optional boolean, whether or not to 1037 reindex the pdb resseq field. False by default. 1038 """ 1039 1040 return self.fileio.load_pdb_trajectory_into_using_file_object(file_obj, 1041 bonds_by_distance, 1042 serial_reindex, 1043 resseq_reindex) 1044 1045 def load_MDAnalysis_into(self, *args): 1046 """ 1047 Allows import of molecular structure with MDAnalysis 1048 1049 Requires the :any:`MDAnalysis <MDAnalysis.core.AtomGroup>` library. 1050 1051 Wrapper function for 1052 :meth:`~scoria.FileIO.FileIO.load_MDAnalysis_into` 1053 1054 :param \*args: Filename, filenames, or list of file names. Used to 1055 inizalize a MDAnalysis.Universe object. 1056 """ 1057 1058 self.fileio.load_MDAnalysis_into(*args) 1059 1060 1061 def load_MDAnalysis_into_using_universe_object(self, universe): 1062 """ 1063 Allows import of molecular structure with MDAnalysis 1064 1065 Requires the :any:`MDAnalysis <MDAnalysis.core.AtomGroup>` library. 1066 1067 Wrapper function for 1068 :meth:`~scoria.FileIO.FileIO.load_MDAnalysis_into_using_universe_object` 1069 1070 :param MDAnalysis.core.Universe universe: MDAnalysis Universe object. 1071 """ 1072 1073 self.fileio.load_MDAnalysis_into_using_universe_object(universe) 1074 1075 1076 # Atoms and Bonds class methods 1077 def get_number_of_bond_partners_of_element(self, atom_index, the_element): 1078 """ 1079 Counts the number of atoms of a given element bonded to a specified 1080 atom of interest. 1081 1082 Requires the :any:`numpy` library. 1083 1084 Wrapper function for 1085 :meth:`~scoria.AtomsAndBonds.AtomsAndBonds.get_number_of_bond_partners_of_element` 1086 1087 :param int atom_index: An int, the index of the atom of interest. 1088 :param str the_element: A string describing the element of the neighbors 1089 to be counted. 1090 1091 :returns: An int, the number of neighboring atoms of the specified 1092 element. 1093 :rtype: :any:`int` 1094 """ 1095 1096 return self.atoms_and_bonds.get_number_of_bond_partners_of_element( 1097 atom_index, the_element 1098 ) 1099 1100 def get_index_of_first_bond_partner_of_element(self, atom_index, 1101 the_element): 1102 """ 1103 For a given atom of interest, returns the index of the first 1104 neighbor of a specified element. 1105 1106 Wrapper function for :meth:`~scoria.AtomsAndBonds.AtomsAndBonds.get_index_of_first_bond_partner_of_element` 1107 1108 :param int atom_index: An int, the index of the atom of interest. 1109 :param str the_element: A string specifying the desired element of the 1110 neighbor. 1111 1112 :returns: An int, the index of the first neighbor atom of the specified 1113 element. If no such neighbor exists, returns -1. 1114 :rtype: :any:`int` 1115 """ 1116 1117 return self.atoms_and_bonds.get_index_of_first_bond_partner_of_element( 1118 atom_index, the_element 1119 ) 1120 1121 def create_bonds_by_distance(self, remove_old_bond_data = True, 1122 delete_excessive_bonds = True): 1123 """ 1124 Determines which atoms are bound to each other based on their 1125 proximity. 1126 1127 Requires the :any:`numpy` and :any:`scipy<scipy.spatial>` libraries. 1128 1129 Wrapper function for 1130 :meth:`~scoria.AtomsAndBonds.AtomsAndBonds.create_bonds_by_distance` 1131 1132 :param bool remove_old_bond_data: An optional boolean, whether or not to 1133 discard old bond data before adding in bonds determined by 1134 distance. True by default. 1135 :param bool delete_excessive_bonds: An optional boolean, whether or not 1136 to check for and delete excessive bonds. True by default. 1137 """ 1138 1139 self.atoms_and_bonds.create_bonds_by_distance( 1140 remove_old_bond_data, delete_excessive_bonds 1141 ) 1142 1143 def delete_bond(self, index1, index2): 1144 """ 1145 Deletes a bond. 1146 1147 Wrapper function for :meth:`~scoria.AtomsAndBonds.AtomsAndBonds.delete_bond` 1148 1149 :param int index1: An int, the index of the first atom of the bonded 1150 pair. 1151 :param int index2: An int, the index of the second atom of the bonded 1152 pair. 1153 """ 1154 1155 self.atoms_and_bonds.delete_bond(index1, index2) 1156 1157 def add_bond(self, index1, index2, order = 1): 1158 """ 1159 Adds a bond. 1160 1161 Wrapper function for :meth:`~scoria.AtomsAndBonds.AtomsAndBonds.add_bond` 1162 1163 :param int index1: An int, the index of the first atom of the bonded 1164 pair. 1165 :param int index2: An int, the index of the second atom of the bonded 1166 pair. 1167 :param int order: An optional int, the order of the bond. 1 by default. 1168 """ 1169 1170 self.atoms_and_bonds.add_bond(index1, index2, order) 1171 1172 def delete_atom(self, index): 1173 """ 1174 Deletes an atom. 1175 1176 Wrapper function for :meth:`~scoria.AtomsAndBonds.AtomsAndBonds.delete_atom` 1177 1178 :param int index: An int, the index of the atom to delete. 1179 """ 1180 1181 self.atoms_and_bonds.delete_atom(index) 1182 1183 def add_atom(self, record_name = "ATOM", serial = 1, name = "X", 1184 resname = "XXX", chainid = "X", resseq = 1, occupancy = 0.0, 1185 tempfactor = 0.0, charge = '', element = "X", 1186 coordinates = numpy.array([0.0, 0.0, 0.0]), autoindex = True): 1187 """ 1188 Adds an atom. 1189 1190 Wrapper function for :meth:`~scoria.AtomsAndBonds.AtomsAndBonds.add_atom` 1191 1192 :param str record_name: An optional string, the record name of the atom. 1193 "ATOM" is the default. 1194 :param int serial: An optional int, the serial field of the atom. 1 is 1195 the default. 1196 :param str name: An optional string, the name of the atom. 'X' is the 1197 default. 1198 :param str resname: An optional string, the resname of the atom. 'XXX' 1199 is the default. 1200 :param str chainid: An optional string, chainid of the atom. 'X' is the 1201 default. 1202 :param int resseq: An optional int, the resseq field of the atom. 1 is 1203 the default. 1204 :param float occupancy: An optional float, the occupancy of the atom. 0.0 1205 is the default. 1206 :param float tempfactor: An optional float, the tempfactor of the atom. 1207 0.0 is the default. 1208 :param str charge: An optional string, the charge of the atom. '' is the 1209 default. 1210 :param str element: An optional string, the element of the atom. 'X' is 1211 the default. 1212 :param numpy.array coordinates: An optional numpy.array, the (x, y, z) 1213 coordinates of the atom. numpy.array([0.0, 0.0, 0.0]) is 1214 the default. 1215 """ 1216 1217 self.atoms_and_bonds.add_atom( 1218 record_name, serial, name, resname, chainid, resseq, occupancy, 1219 tempfactor, charge, element, coordinates, autoindex 1220 ) 1221 1222 # Selections class 1223 def get_molecule_from_selection(self, selection, serial_reindex = True, 1224 resseq_reindex = False): 1225 """ 1226 Creates a scoria.Molecule from a user-defined atom selection. 1227 1228 Wrapper function for :meth:`~scoria.Selections.Selections.get_molecule_from_selection` 1229 1230 :param numpy.array selection: A numpy.array containing the indices of the atoms 1231 in the user-defined selection. 1232 :param bool serial_reindex: An optional boolean, whether or not to 1233 reindex the atom serial fields. Default is True. 1234 :param bool resseq_reindex: An optional boolean, whether or not to 1235 reindex the atom resseq fields. Default is False. 1236 1237 :returns: A scoria.Molecule object containing the atoms of the 1238 user-defined selection. 1239 """ 1240 1241 return self.selections.get_molecule_from_selection( 1242 selection, serial_reindex, resseq_reindex 1243 ) 1244 1245 def select_atoms(self, selection_criteria): 1246 """ 1247 Select a set of atoms based on user-specified criteria. 1248 1249 Wrapper function for :meth:`~scoria.Selections.Selections.select_atoms` 1250 1251 :param dict selection_criteria: A dictionary, where the keys correspond 1252 to keys in the 1253 self.__parent_Information.Information.get_atom_information() 1254 structured numpy array, and the values are lists of 1255 acceptable matches. The selection is a logical "AND" 1256 between dictionary entries, but "OR" within the value lists 1257 themselves. For example: {'atom':['CA', 'O'], 'chain':'A', 1258 'resname':'PRO'} would select all atoms with the names CA 1259 or O that are located in the PRO residues of chain A. 1260 1261 :returns: A numpy.array containing the indices of the atoms of the 1262 selection. 1263 """ 1264 1265 return self.selections.select_atoms(selection_criteria) 1266 1267 def select_atoms_in_bounding_box(self, bounding_box): 1268 """ 1269 Selects all the atoms that are within a bounding box. 1270 1271 Requires the :any:`numpy` library. 1272 1273 Wrapper function for :meth:`~scoria.Selections.Selections.select_atoms_in_bounding_box` 1274 1275 :param numpy.array bounding_box: A 2x3 numpy.array containing the minimum and 1276 maximum points of the bounding box. Example: 1277 numpy.array( [[min_x, min_y, min_z], [max_x, max_y, max_z]] ). 1278 1279 :returns: A numpy.array containing the indices of the atoms that are 1280 within the bounding box. 1281 """ 1282 1283 return self.selections.select_atoms_in_bounding_box(bounding_box) 1284 1285 def select_branch(self, root_atom_index, directionality_atom_index): 1286 """ 1287 Identify an isolated "branch" of a molecular model. Assumes the 1288 atoms with indices root_atom_index and directionality_atom_index are 1289 bound to one another and that the branch starts at root_atom_index one 1290 and "points" in the direction of directionality_atom_index. 1291 1292 Requires the :any:`numpy` library. 1293 1294 Wrapper function for :meth:`~scoria.Selections.Selections.select_branch` 1295 1296 :param int root_atom_index: An int, the index of the first atom in the 1297 branch (the "root"). 1298 :param int directionality_atom_index: An int, the index of the second atom 1299 in the branch, used to establish directionality 1300 1301 :returns: A numpy array containing the indices of the atoms of the branch. 1302 """ 1303 1304 return self.selections.select_branch( 1305 root_atom_index, directionality_atom_index 1306 ) 1307 1308 def select_all_atoms_bound_to_selection(self, selections): 1309 """ 1310 Selects all the atoms that are bound to a user-specified selection. 1311 1312 Requires the :any:`numpy` library. 1313 1314 Wrapper function for :meth:`~scoria.Selections.Selections.select_all_atoms_bound_to_selection` 1315 1316 :param numpy.array selection: A numpy.array containing the indices of the 1317 user-specified selection. 1318 1319 :returns: A numpy.array containing the indices of the atoms that are 1320 bound to the user-specified selection. Note that this new 1321 selection does not necessarily include the indices of the 1322 original user-specified selection. 1323 """ 1324 1325 return self.selections.select_all_atoms_bound_to_selection(selections) 1326 1327 def select_atoms_from_same_molecule(self, selection): 1328 """ 1329 Selects all the atoms that belong to the same molecule as a 1330 user-defined selection, assuming that the scoria.Molecule object 1331 actually contains multiple physically distinct molecules that are not 1332 bound to each other via covalent bonds. 1333 1334 Requires the :any:`numpy` library. 1335 1336 Wrapper function for :meth:`~scoria.Selections.Selections.select_atoms_from_same_molecule` 1337 1338 :param numpy.array selection: A numpy.array containing the indices of the 1339 user-defined selection. 1340 1341 :returns: A numpy.array containing the indices of the atoms belonging to 1342 the same molecules as the atoms of the user-defined 1343 selection. 1344 """ 1345 1346 return self.selections.select_atoms_from_same_molecule(selection) 1347 1348 def selections_of_constituent_molecules(self): 1349 """ 1350 Identifies the indices of atoms belonging to separate molecules, 1351 assuming that the scoria.Molecule object actually contains multiple 1352 physically distinct molecules that are not bound to each other via 1353 covalent bonds. 1354 1355 Requires the :any:`numpy` library. 1356 1357 Wrapper function for :meth:`~scoria.Selections.Selections.selections_of_constituent_molecules` 1358 1359 :Returns: A python list of numpy.array objects containing the indices of 1360 the atoms belonging to each molecule of the composite 1361 scoria.Molecule object. 1362 """ 1363 1364 return self.selections.selections_of_constituent_molecules() 1365 1366 def select_atoms_near_other_selection(self, selection, cutoff): 1367 """ 1368 Selects all atoms that are near the atoms of a user-defined 1369 selection. 1370 1371 Requires the :any:`numpy` and :any:`scipy<scipy.spatial>` libraries. 1372 1373 Wrapper function for :meth:`~scoria.Selections.Selections.select_atoms_near_other_selection` 1374 1375 :param numpy.array selection: A numpy.array containing the indices of the 1376 user-defined selection. 1377 :param float cutoff: A float, the distance cutoff (in Angstroms). 1378 1379 :returns: A numpy.array containing the indices of all atoms near the 1380 user-defined selection, not including the atoms of the 1381 user-defined selection themselves. 1382 """ 1383 1384 return self.selections.select_atoms_near_other_selection( 1385 selection, cutoff 1386 ) 1387 1388 def select_atoms_in_same_residue(self, selection): 1389 """ 1390 Selects all atoms that are in the same residue as any of the atoms 1391 of a user-defined seleciton. Residues are considered unique if they 1392 have a unique combination of resname, resseq, and chainid fields. 1393 1394 Wrapper function for :meth:`~scoria.Selections.Selections.select_atoms_in_same_residue` 1395 1396 :param numpy.array selection: A numpy.array containing the indices of the 1397 user-defined selection. 1398 1399 :returns: A numpy.array containing the indices of all atoms in the same 1400 residue as any of the atoms of the user-defined selection. 1401 """ 1402 1403 return self.selections.select_atoms_in_same_residue(selection) 1404 1405 def invert_selection(self, selection): 1406 """ 1407 Inverts a user-defined selection (i.e., identifies all atoms that 1408 are not in the seleciton). 1409 1410 Wrapper function for :meth:`~scoria.Selections.Selections.invert_selection` 1411 1412 :param numpy.array selection: A numpy.array containing the indices of the 1413 user-defined selection. 1414 1415 :returns: A numpy.array containing the indices of all atoms that are not 1416 in the user-defined seleciton. 1417 """ 1418 1419 return self.selections.invert_selection(selection) 1420 1421 def select_all(self): 1422 """ 1423 Selects all the atoms in a scoria.Molecule object. 1424 1425 Wrapper function for :meth:`~scoria.Selections.Selections.select_all` 1426 1427 :returns: A numpy.array containing the indices of all atoms in the 1428 scoria.Molecule object. 1429 """ 1430 1431 return self.selections.select_all() 1432 1433 def select_close_atoms_from_different_molecules(self, other_mol, cutoff, 1434 pairwise_comparison = True, 1435 terminate_early = False): 1436 """ 1437 Effectively detects steric clashes between self and another 1438 scoria.Molecule. 1439 1440 Requires the :any:`numpy` and :any:`scipy<scipy.spatial>` libraries. 1441 1442 Wrapper function for :meth:`~scoria.Selections.Selections.select_close_atoms_from_different_molecules` 1443 1444 :param scoria.Molecule other_mol: A scoria.Molecule object of the other 1445 molecule. 1446 :param float cutoff: A float, the user-defined distance cutoff in 1447 Angstroms. 1448 :param bool pairwise_comparison: An optional boolean, whether or not to 1449 perform a simple pairwise distance comparison (if True) or 1450 to use a more sophisitcated method (if False). True by 1451 default. 1452 :param bool terminate_early: An optional boolean, whether or not to stop 1453 looking for steric clashes once one is found. False by 1454 default. 1455 1456 :returns: A tuple containing two elements. The first is a numpy.array 1457 containing the indices of all nearby atoms from this 1458 scoria.Molecule object (self). The second is a 1459 numpy.array containing the indices of all nearby atoms from 1460 the other molecule. 1461 """ 1462 1463 return self.selections.select_close_atoms_from_different_molecules( 1464 other_mol, cutoff, pairwise_comparison, terminate_early 1465 ) 1466 1467 def selections_of_chains(self): 1468 """ 1469 Identifies the atom selections of each chain. 1470 1471 Requires the :any:`numpy` library. 1472 1473 Wrapper function for :meth:`~scoria.Selections.Selections.selections_of_chains` 1474 1475 :returns: A dictionary. The keys of the dictionary correspond to the 1476 chainids, and the values are numpy.array objects containing 1477 the indices of the associated chain atoms. 1478 """ 1479 1480 return self.selections.selections_of_chains() 1481 1482 def selections_of_residues(self): 1483 """ 1484 Identifies the atom selections of each residue. 1485 1486 Requires the :any:`numpy` library. 1487 1488 Wrapper function for :meth:`~scoria.Selections.Selections.selections_of_residues` 1489 1490 :returns: A dictionary. The keys of this dictionary correspond to the 1491 unique resname-resseq-chainid residue identifiers, and the 1492 values are numpy.array objects containing the indices of 1493 the associated residue atoms. 1494 """ 1495 1496 return self.selections.selections_of_residues() 1497 1498 # Manipulation class 1499 def set_atom_location(self, atom_index, new_location): 1500 """ 1501 Translates the entire molecular model (without rotating) so that the 1502 atom with the specified index is located at the specified coordinate. 1503 1504 Wrapper function for :meth:`~scoria.Manipulation.Manipulation.set_atom_location` 1505 1506 :param int atom_index: An int, the index of the target atom. 1507 :param numpy.array new_location: A numpy.array specifying the new (x, y, z) 1508 coordinate of the specified atom. 1509 1510 :returns: A numpy.array specifying the (delta_x, delta_y, delta_z) vector 1511 by which the pmolecule.Molecule was translated. 1512 """ 1513 1514 return self.manipulation.set_atom_location(atom_index, new_location) 1515 1516 def set_coordinate_undo_point(self): 1517 """ 1518 Sets ("saves") the undo point of the atom coordinates. Any 1519 subsequent manipulations of atomic coordinates can be "undone" by 1520 reseting to this configuration via the coordinate_undo function. 1521 1522 Wrapper function for :meth:`~scoria.Manipulation.Manipulation.set_coordinate_undo_point` 1523 """ 1524 1525 self.manipulation.set_coordinate_undo_point() 1526 1527 def coordinate_undo(self): 1528 """ 1529 Resets the coordinates of all atoms to those saved using the 1530 set_coordinate_undo_point function. 1531 1532 Wrapper function for :meth:`~scoria.Manipulation.Manipulation.coordinate_undo` 1533 """ 1534 1535 self.manipulation.coordinate_undo() 1536 1537 def translate_molecule(self, delta): 1538 """ 1539 Translate all the atoms of the molecular model by a specified 1540 vector. 1541 1542 Wrapper function for :meth:`~scoria.Manipulation.Manipulation.translate_molecule` 1543 1544 :param numpy.array delta: A numpy.array (delta_x, delta_y, delta_z) specifying the 1545 amount to move each atom along the x, y, and z coordinates. 1546 """ 1547 1548 self.manipulation.translate_molecule(delta) 1549 1550 def rotate_molecule_around_a_line_between_points(self, line_point1, 1551 line_point2, rotate): 1552 """ 1553 Rotate the molecular model about a line segment. The end points of 1554 the line segment are explicitly specified coordinates. 1555 1556 Wrapper function for :meth:`~scoria.Manipulation.Manipulation.rotate_molecule_around_a_line_between_points` 1557 1558 :param numpy.array line_point1: A numpy.array (x, y, z) corresponding to one end 1559 of the line segment. 1560 :param numpy.array line_point2: A numpy.array (x, y, z) corresponding to the 1561 other end of the line segment. 1562 :param float rotate: A float, the angle of rotation, in radians. 1563 """ 1564 1565 self.manipulation.rotate_molecule_around_a_line_between_points( 1566 line_point1, line_point2, rotate 1567 ) 1568 1569 def rotate_molecule_around_a_line_between_atoms(self, line_point1_index, 1570 line_point2_index, rotate): 1571 """ 1572 Rotate the molecular model about a line segment. The end points of 1573 the line segment are atoms of specified indices. 1574 1575 Wrapper function for :meth:`~scoria.Manipulation.Manipulation.rotate_molecule_around_a_line_between_atoms` 1576 1577 :param int line_point1_index: An int, the index of the first atom at one 1578 end of the line segment. 1579 :param int line_point2_index: An int, the index of the second atom at 1580 the other end of the line segment. 1581 :param float rotate: A float, the angle of rotation, in radians. 1582 """ 1583 1584 self.manipulation.rotate_molecule_around_a_line_between_atoms( 1585 line_point1_index, line_point2_index, rotate 1586 ) 1587 1588 def rotate_molecule_around_pivot_point(self, pivot, thetax, 1589 thetay, thetaz): 1590 """ 1591 Rotate the molecular model around a specified atom. 1592 1593 Requires the :any:`numpy` library. 1594 1595 Wrapper function for :meth:`~scoria.Manipulation.Manipulation.rotate_molecule_around_pivot_point` 1596 1597 :param numpy.array pivot: A numpy.array, the (x, y, z) coordinate about which 1598 the molecular model will be rotated. 1599 :param float thetax: A float, the angle to rotate relative to the x axis, 1600 in radians. 1601 :param float thetay: A float, the angle to rotate relative to the y axis, 1602 in radians. 1603 :param float thetaz: A float, the angle to rotate relative to the z axis, 1604 in radians. 1605 """ 1606 1607 self.manipulation.rotate_molecule_around_pivot_point( 1608 pivot, thetax, thetay, thetaz 1609 ) 1610 1611 def rotate_molecule_around_pivot_atom(self, pivot_index, thetax, 1612 thetay, thetaz): 1613 """ 1614 Rotate the molecular model around a specified atom. 1615 1616 Requires the :any:`numpy` library. 1617 1618 Wrapper function for :meth:`~scoria.Manipulation.Manipulation.rotate_molecule_around_pivot_atom` 1619 1620 :param int pivot_index: An int, the index of the atom about which the 1621 molecular model will be rotated. 1622 :param float thetax: A float, the angle to rotate relative to the x axis, 1623 in radians. 1624 :param float thetay: A float, the angle to rotate relative to the y axis, 1625 in radians. 1626 :param float thetaz: A float, the angle to rotate relative to the z axis, 1627 in radians. 1628 """ 1629 1630 self.manipulation.rotate_molecule_around_pivot_atom( 1631 pivot_index, thetax, thetay, thetaz 1632 ) 1633 1634 # Geometry class 1635 def get_angle_between_three_points(self, pt1, pt2, pt3): 1636 """ 1637 Computes the angle (in radians) formed by three points (numpy.array 1638 objects). 1639 1640 Wrapper function for :meth:`~scoria.Geometry.Geometry.get_angle_between_three_points` 1641 1642 :param numpy.array pt1: A numpy.array (x, y, z) representing the first of the 1643 three 3D points. 1644 :param numpy.array pt2: A numpy.array (x, y, z) representing the second of the 1645 three 3D points. 1646 :param numpy.array pt3: A numpy.array (x, y, z) representing the third of the 1647 three 3D points. 1648 1649 :returns: A float containing the angle between the three points, in 1650 radians. 1651 """ 1652 1653 return self.geometry.get_angle_between_three_points(pt1, pt2, pt3) 1654 1655 def get_dihedral_angle(self, pt1, pt2, pt3, pt4): 1656 """ 1657 Calculates the dihedral angle formed by four points (numpy.array 1658 objects). 1659 1660 Wrapper function for :meth:`~scoria.Geometry.Geometry.get_dihedral_angle` 1661 1662 :param numpy.array pt1: A numpy.array (x, y, z) representing the first 3D 1663 point. 1664 :param numpy.array pt2: A numpy.array (x, y, z) representing the second 3D 1665 point. 1666 :param numpy.array pt3: A numpy.array (x, y, z) representing the third 3D 1667 point. 1668 :param numpy.array pt4: A numpy.array (x, y, z) representing the fourth 3D 1669 point. 1670 1671 :returns: A float containing the dihedral angle between the four points, 1672 in radians. 1673 """ 1674 1675 return self.geometry.get_dihedral_angle(pt1, pt2, pt3, pt4) 1676 1677 def get_planarity_deviation(self, pt1, pt2, pt3, pt4): 1678 """ 1679 Determines how close four points (numpy.array objects) come to lying 1680 in a common plane. 1681 1682 Wrapper function for :meth:`~scoria.Geometry.Geometry.get_planarity_deviation` 1683 1684 :param numpy.array pt1: A numpy.array (x, y, z) representing a 3D point. 1685 :param numpy.array pt2: A numpy.array (x, y, z) representing a 3D point. 1686 :param numpy.array pt3: A numpy.array (x, y, z) representing a 3D point. 1687 :param numpy.array pt4: A numpy.array (x, y, z) representing a 3D point. 1688 1689 :returns: A float, the minimum distance between one point and the plane 1690 formed by the other three. 1691 """ 1692 1693 return self.geometry.get_planarity_deviation(pt1, pt2, pt3, pt4) 1694 1695 def is_planar(self, pt1, pt2, pt3, pt4, planarity_cutoff = 0.2): 1696 """ 1697 Checks whether four points (numpy.array) lie in a common plane. 1698 1699 Wrapper function for :meth:`~scoria.Geometry.Geometry.is_planar` 1700 1701 :param numpy.array pt1: A numpy.array (x, y, z) representing a 3D point. 1702 :param numpy.array pt2: A numpy.array (x, y, z) representing a 3D point. 1703 :param numpy.array pt3: A numpy.array (x, y, z) representing a 3D point. 1704 :param numpy.array pt4: A numpy.array (x, y, z) representing a 3D point. 1705 :param float planarity_cutoff: An optional float. How much the points can 1706 deviate (in Angstroms) and still be considered planar. The 1707 default is 0.2. 1708 1709 :returns: A boolean, whether the 4 points can be considered planar. 1710 """ 1711 1712 return self.geometry.is_planar(pt1, pt2, pt3, pt4, planarity_cutoff) 1713 1714 # Other molecule class 1715 def get_other_molecules_aligned_to_this(self, other_mol, tethers): 1716 """ 1717 Aligns a molecule to self (this scoria.Molecule object) using a 1718 quaternion RMSD alignment. 1719 1720 Requires the :any:`numpy` library. 1721 1722 Wrapper function for :meth:`~scoria.OtherMolecules.OtherMolecules.get_other_molecules_aligned_to_this` 1723 1724 :param scoria.Molecule other_mol: A scoria.Molecule that is to be aligned to 1725 this one. 1726 :param tuple tethers: A tuple of two numpy.array objects, where each array 1727 contains the indices of self and other_mol, respectively, 1728 such that equivalent atoms are listed in the same order. 1729 So, for example, if (atom 1, self = atom 3, other) and 1730 (atom2, self = atom6, other) than the tethers would be 1731 (numpy.array([1, 2]), numpy.array([3, 6])). 1732 1733 :returns: The new molecule. 1734 """ 1735 1736 # Add Weight Matrix 1737 return self.other_molecules.get_other_molecules_aligned_to_this( 1738 other_mol, tethers 1739 ) 1740 1741 def get_distance_to_another_molecule(self, other_molecules, 1742 pairwise_comparison = True): 1743 """ 1744 Computes the minimum distance between any of the atoms of this 1745 molecular model and any of the atoms of a second specified model. 1746 1747 Requires the :any:`numpy` and :any:`scipy<scipy.spatial>` libraries. 1748 1749 Wrapper function for :meth:`~scoria.OtherMolecules.OtherMolecules.get_distance_to_another_molecule` 1750 1751 :param scoria.Molecule other_molecules: a scoria.Molecule, the other molecular 1752 model. 1753 :param bool pairwise_comparison: An optional boolean, whether or not to 1754 perform a simple pairwise distance comparison (if True) or 1755 to use a more sophisitcated method (if False). True by 1756 default. 1757 1758 :returns: A float, the minimum distance between any two atoms of the two 1759 specified molecular models (self and other_molecules). 1760 """ 1761 1762 return self.other_molecules.get_distance_to_another_molecule( 1763 other_molecules, pairwise_comparison 1764 ) 1765 1766 def get_distance_to_another_molecules(self, other_molecules, 1767 pairwise_comparison = True): 1768 """ 1769 DEPRECATION WARNING: Please use :meth:`~scoria.Molecule.Molecule.get_distance_to_another_molecule` 1770 1771 Computes the minimum distance between any of the atoms of this 1772 molecular model and any of the atoms of a second specified model. 1773 1774 Requires the :any:`numpy` and :any:`scipy<scipy.spatial>` libraries. 1775 1776 Wrapper function for :meth:`~scoria.OtherMolecules.OtherMolecules.get_distance_to_another_molecule` 1777 1778 :param scoria.Molecule other_molecules: a scoria.Molecule, the other molecular 1779 model. 1780 :param bool pairwise_comparison: An optional boolean, whether or not to 1781 perform a simple pairwise distance comparison (if True) or 1782 to use a more sophisitcated method (if False). True by 1783 default. 1784 1785 :returns: A float, the minimum distance between any two atoms of the two 1786 specified molecular models (self and other_molecules). 1787 """ 1788 1789 return self.other_molecules.get_distance_to_another_molecule( 1790 other_molecules, pairwise_comparison 1791 ) 1792 1793 def get_rmsd_equivalent_atoms_specified(self, other_mol, tethers): 1794 """ 1795 Calculates the RMSD between this scoria.Molecle object and 1796 another, where equivalent atoms are explicitly specified. 1797 1798 Wrapper function for :meth:`~scoria.OtherMolecules.OtherMolecules.get_rmsd_equivalent_atoms_specified` 1799 1800 :param scoria.Molecule other_mol: The other scoria.Molecule object. 1801 :param tuple tethers: A tuple of two numpy.array objects, where each array 1802 contains the indices of self and other_mol, respectively, 1803 such that equivalent atoms are listed in the same order. 1804 So, for example, if (atom 1, self = atom 3, other) and 1805 (atom2, self = atom6, other) than the tethers would be 1806 (numpy.array([1, 2]), numpy.array([3, 6])). 1807 1808 :returns: A float, the RMSD between self and other_mol. 1809 """ 1810 1811 return self.other_molecules.get_rmsd_equivalent_atoms_specified( 1812 other_mol, tethers 1813 ) 1814 1815 def get_rmsd_order_dependent(self, other_mol): 1816 """ 1817 Calculates the RMSD between two structures, where equivalent atoms 1818 are listed in the same order. 1819 1820 Wrapper function for :meth:`~scoria.OtherMolecules.OtherMolecules.get_rmsd_order_dependent` 1821 1822 :param scoria.Molecule other_mol: The other scoria.Molecule object. 1823 1824 :returns: A float, the RMSD between self and other_mol. 1825 """ 1826 1827 return self.other_molecules.get_rmsd_order_dependent(other_mol) 1828 1829 def get_rmsd_heuristic(self, other_mol): 1830 """ 1831 Caluclates the RMSD between two identical molecules with different 1832 conformations, per the definition given in "AutoDock Vina: Improving 1833 the speed and accuracy of docking with a new scoring function, 1834 efficient optimization, and multithreading,"" by Oleg Trott and Arthur 1835 J. Olson. Note: Identical means the order of the atoms is the same as 1836 well. 1837 1838 Requires the :any:`numpy` library. 1839 1840 Wrapper function for :meth:`~scoria.OtherMolecules.OtherMolecules.get_rmsd_heuristic` 1841 1842 :param scoria.Molecule other_mol: The other scoria.Molecule object. 1843 1844 :returns: A float, the RMSD between self and other_mol. 1845 """ 1846 1847 return self.other_molecules.get_rmsd_heuristic(other_mol) 1848 1849 def steric_clash_with_another_molecules(self, other_mol, cutoff, 1850 pairwise_comparison = True): 1851 """ 1852 DEPRECATION WARNING: Please use :meth:`~scoria.Molecule.Molecule.steric_clash_with_another_molecule` 1853 Detects steric clashes between the scoria.Molecule (self) and 1854 another scoria.Molecule. 1855 1856 Requires the :any:`numpy` and :any:`scipy<scipy.spatial>` libraries. 1857 1858 Wrapper function for :meth:`~scoria.OtherMolecules.OtherMolecules.steric_clash_with_another_molecule` 1859 1860 :param scoria.Molecule other_mol: The scoria.Molecule object that will be 1861 evaluated for steric clashes. 1862 :param float cutoff: A float, the user-defined distance cutoff in 1863 Angstroms. 1864 :param bool pairwise_comparison: An optional boolean, whether or not to 1865 perform a simple pairwise distance comparison (if True) or 1866 to use a more sophisitcated method (if False). True by 1867 default. 1868 1869 :returns: A boolean. True if steric clashes are present, False if they 1870 are not. 1871 """ 1872 1873 return self.other_molecules.steric_clash_with_another_molecule( 1874 other_mol, cutoff, pairwise_comparison 1875 ) 1876 1877 def steric_clash_with_another_molecule(self, other_mol, cutoff, 1878 pairwise_comparison = True): 1879 """ 1880 Detects steric clashes between the scoria.Molecule (self) and 1881 another scoria.Molecule. 1882 1883 Requires the :any:`numpy` and :any:`scipy<scipy.spatial>` libraries. 1884 1885 Wrapper function for :meth:`~scoria.OtherMolecules.OtherMolecules.steric_clash_with_another_molecule` 1886 1887 :param scoria.Molecule other_mol: The scoria.Molecule object that will be 1888 evaluated for steric clashes. 1889 :param float cutoff: A float, the user-defined distance cutoff in 1890 Angstroms. 1891 :param bool pairwise_comparison: An optional boolean, whether or not to 1892 perform a simple pairwise distance comparison (if True) or 1893 to use a more sophisitcated method (if False). True by 1894 default. 1895 1896 :returns: A boolean. True if steric clashes are present, False if they 1897 are not. 1898 """ 1899 1900 return self.other_molecules.steric_clash_with_another_molecule( 1901 other_mol, cutoff, pairwise_comparison 1902 ) 1903 1904 def merge_with_another_molecules(self, other_molecules): 1905 """ 1906 DEPRECATION WARNING: Please use :meth:`~scoria.Molecule.Molecule.merge_with_another_molecule` 1907 Merges two molecular models into a single model. 1908 1909 Wrapper function for :meth:`~scoria.OtherMolecules.OtherMolecules.merge_with_another_molecule` 1910 1911 :param scoria.Molecule other_molecules: A molecular model (scoria.Molecule 1912 object). 1913 1914 :returns: A single scoria.Molecule object containing the atoms of 1915 this model combined with the atoms of other_molecules. 1916 """ 1917 1918 return self.other_molecules.merge_with_another_molecule(other_molecules) 1919 1920 def merge_with_another_molecule(self, other_molecules): 1921 """ 1922 Merges two molecular models into a single model. 1923 1924 Wrapper function for :meth:`~scoria.OtherMolecules.OtherMolecules.merge_with_another_molecule` 1925 1926 :param scoria.Molecule other_molecules: A molecular model (scoria.Molecule 1927 object). 1928 1929 :returns: A single scoria.Molecule object containing the atoms of 1930 this model combined with the atoms of other_molecules. 1931 """ 1932 1933 return self.other_molecules.merge_with_another_molecule(other_molecules) 1934 1935 ######## Supporting functions ######## 1936 1937 def numpy_structured_array_remove_field(self, narray, field_names): 1938 """ 1939 Removes a specific field name from a structured numpy array. 1940 1941 :param numpy.array narray: A structured numpy array. 1942 :param list(str) field_names: A list of strings, where each string is one of 1943 the field names of narray. 1944 1945 :returns: A structured numpy array identical to narray, but with the 1946 field names in field_names removed. 1947 """ 1948 1949 # surprised this doesn't come with numpy 1950 1951 # now remove the coordinates from the atom_information object to save 1952 # memory 1953 names = list(narray.dtype.names) 1954 for f in field_names: 1955 names.remove(f) 1956 1957 return narray[names] 1958 1959 def __is_number(self, s): 1960 """ 1961 Determines whether or not a string represents a number. 1962 1963 :param str s: A string (e.g., "5.4"). 1964 1965 :returns: A boolean, whether or not the string can be represented by a 1966 float. 1967 """ 1968 1969 try: 1970 float(s) 1971 return True 1972 except ValueError: 1973 return False 1974 1975 def copy(self): 1976 """ 1977 Returns an exact copy (scoria.Molecule) of this Molecule object. 1978 Undo points are NOT copied. 1979 1980 :returns: A scoria.Molecule, containing to the same atomic 1981 information as this scoria.Molecule object. 1982 """ 1983 1984# new_molecule = Molecule() 1985# new_molecule.set_filename(self.get_filename()[:]) 1986# new_molecule.set_remarks(self.get_remarks()[:]) 1987# new_molecule.set_atom_information(self.get_atom_information().copy()) 1988# new_molecule.set_trajectory_coordinates(self.get_trajectory_coordinates().copy()) 1989# 1990# if not self.get_bonds() is None: 1991# new_molecule.set_bonds(self.get_bonds().copy()) 1992# else: 1993# new_molecule.set_bonds(None) 1994# 1995# new_molecule.set_hierarchy(copy.deepcopy(self.get_hierarchy())) 1996 1997 new_molecule = copy.deepcopy(self) 1998 1999 return new_molecule 2000