diff --git a/docs/_modules/pywindow/molecular.html b/docs/_modules/pywindow/molecular.html index 797dbc7..384a4c4 100644 --- a/docs/_modules/pywindow/molecular.html +++ b/docs/_modules/pywindow/molecular.html @@ -910,19 +910,19 @@

Source code for pywindow.molecular

 
     .. code-block:: python
 
-        pywindow.MolecularSystem.load_file(`filepath`)
+        pywindow.molecular.MolecularSystem.load_file(`filepath`)
 
     2. Using RDKit molecule object as an input:
 
     .. code-block:: python
 
-        pywindow.MolecularSystem.load_rdkit_mol(rdkit.Chem.rdchem.Mol)
+        pywindow.molecular.MolecularSystem.load_rdkit_mol(rdkit.Chem.rdchem.Mol)
 
     3. Using a dictionary (or another :attr:`MoleculeSystem.system`) as input:
 
     .. code-block:: python
 
-        pywindow.MolecularSystem.load_system({...})
+        pywindow.molecular.MolecularSystem.load_system({...})
 
     Attributes
     ----------
@@ -1076,7 +1076,7 @@ 

Source code for pywindow.molecular

 
         .. code-block:: python
 
-            pywindow.MolecularSystem.swap_atom_keys({'he': 'H'})
+            pywindow.molecular.MolecularSystem.swap_atom_keys({'he': 'H'})
 
         Parameters
         ----------
diff --git a/docs/_modules/pywindow/trajectory.html b/docs/_modules/pywindow/trajectory.html
index 4c0f22f..db04c08 100644
--- a/docs/_modules/pywindow/trajectory.html
+++ b/docs/_modules/pywindow/trajectory.html
@@ -139,7 +139,39 @@
            

Source code for pywindow.trajectory

-"""Module intended for the analysis of molecular dynamics trajectories."""
+"""
+Module intended for the analysis of molecular dynamics trajectories.
+
+The trajectory file (DL_POLY_C:HISTORY, PDB or XYZ) should be loaded with
+the one of the corresponding classes (DLPOLY, PDB or XYZ, respectively).
+
+Example
+-------
+In this example a DL_POLY_C HISTORY trajectory file is loaded.
+
+.. code-block:: python
+
+    pywindow.trajectory.DLPOLY('path/to/HISTORY')
+
+Then, each of the trajectory frames can be extracted and returned as a
+:class:`pywindow.molecular.MolecularSystem` object for analysis. See
+:mod:`pywindow.molecular` docstring for more information.
+
+Alternatively, the analysis can be performed on a whole or a chunk of
+the trajectory with the :func:`analysis()` function. The benefit is
+that the analysis can be performed in parallel and the results stored as a
+single JSON dictionary in a straightforward way. Also, the deciphering of the
+force field atom ids and the rebuilding of molecules can be applied to each
+frame in a consitent and automated manner. The downfall is that at the
+moment it is not possible to choose the set of parameters that are being
+calculated in the :class:`pywindow.molecular.Molecule` as the
+:func:`pywindow.molecular.Molecule.full_analysis()` is invoked by default.
+However, the computational cost of calculating majority of the structural
+properties is miniscule and it is usually the
+:func:`pywindow.molecular.MolecularSystem.rebuild_system()` step that is the
+bottleneck.
+
+"""
 import os
 import numpy as np
 from copy import deepcopy
@@ -175,12 +207,65 @@ 

Source code for pywindow.trajectory

 
 
 
[docs]def make_supercell(system, matrix, supercell=[1, 1, 1]): + """ + Return a supercell. + + This functions takes the input unitcell and creates a supercell of it that + is returned as a new :class:`pywindow.molecular.MolecularSystem`. + + Parameters + ---------- + system : :attr:`pywindow.molecular.MolecularSystem.system` + The unit cell for creation of the supercell + + matrix : :class:`numpy.array` + The unit cell parameters in form of a lattice. + + supercell : :class:`list`, optional + A list that specifies the size of the supercell in the a, b and c + direction. (default=[1, 1, 1]) + + Returns + ------- + :class:`pywindow.molecular.MolecularSystem` + Returns the created supercell as a new :class:`MolecularSystem`. + + """ user_supercell = [[1, supercell[0]], [1, supercell[1]], [1, supercell[1]]] system = create_supercell(system, matrix, supercell=user_supercell) return MolecularSystem.load_system(system)
[docs]class DLPOLY(object): + """ + A container for a DL_POLY_C type trajectory (HISTORY). + + This function takes a DL_POLY_C trajectory file and maps it for the + binary points in the file where each frame starts/ends. This way the + process is fast, as it not require loading the trajectory into computer + memory. When a frame is being extracted, it is only this frame that gets + loaded to the memory. + + Frames can be accessed individually and loaded as an unmodified string, + returned as a :class:`pywindow.molecular.MolecularSystem` (and analysed), + dumped as PDB or XYZ or JSON (if dumped as a + :attr:`pywindow.molecular.MolecularSystem.system`) + + Attributes + ---------- + filepath : :class:`str` + The filepath. + + system_id : :class:`str` + The system id inherited from the filename. + + frames : :class:`dict` + A dictionary that is populated, on the fly, with the extracted frames. + + analysis_output : :class:`dict` + A dictionary that is populated, on the fly, with the analysis output. + + """ def __init__(self, filepath): # Image conventions - periodic boundary key. self._imcon = { @@ -270,7 +355,50 @@

Source code for pywindow.trajectory

         self.no_of_atoms = header[2]
         return header
 
-
[docs] def get_frames(self, frames, override=False, **kwargs): +
[docs] def get_frames(self, frames='all', override=False, **kwargs): + """ + Extract frames from the trajectory file. + + Depending on the passed parameters a frame, a list of particular + frames, a range of frames (from, to), or all frames can be extracted + with this function. + + Parameters + ---------- + frames : :class:`int` or :class:`list` or :class:`touple` or :class:`str` + Specified frame (:class:`int`), or frames (:class:`list`), or + range (:class:`touple`), or `all`/`everything` (:class:`str`). + (default=`all`) + + override : :class:`bool` + If True, a frame already storred in :attr:`frames` can be override. + (default=False) + + extract_data : :class:`bool`, optional + If False, a frame is returned as a :class:`str` block as in the + trajectory file. Ohterwise, it is extracted and returned as + :class:`pywindow.molecular.MolecularSystem`. (default=True) + + swap_atoms : :class:`dict`, optional + If this kwarg is passed with an appropriate dictionary a + :func:`pywindow.molecular.MolecularSystem.swap_atom_keys()` will + be applied to the extracted frame. + + forcefield : :class:`str`, optional + If this kwarg is passed with appropriate forcefield keyword a + :func:`pywindow.molecular.MolecularSystem.decipher_atom_keys()` + will be applied to the extracted frame. + + Returns + ------- + :class:`pywindow.molecular.MolecularSystem` + If a single frame is extracted. + + None : :class:`NoneType` + If more than one frame is extracted, the frames are returned to + :attr:`frames` + + """ if override is True: self.frames = {} if isinstance(frames, int): @@ -382,7 +510,74 @@

Source code for pywindow.trajectory

 
[docs] def analysis( self, frames='all', ncpus=1, _ncpus=1, override=False, **kwargs ): - """ """ + """ + Perform structural analysis on a frame/ set of frames. + + Depending on the passed parameters a frame, a list of particular + frames, a range of frames (from, to), or all frames can be analysed + with this function. + + The analysis is performed on each frame and each discrete molecule in + that frame separately. The steps are as follows: + + 1. A frame is extracted and returned as a :class:`MolecularSystem`. + 2. If `swap_atoms` is set the atom ids are swapped. + 3. If `forcefield` is set the atom ids are deciphered. + 4. If `rebuild` is set the molecules in the system are rebuild. + 5. Each discrete molecule is extracted as :class:`Molecule` + 6. Each molecule is analysed with :func:`Molecule.full_analysis()` + 7. Analysis output populates the :attr:`analysis_output` dictionary. + + As the analysis of trajectories often have to be unique, many options + are conditional. + + A side effect of this function is that the analysed frames are also + returned to the :attr:`frames` mimicking the behaviour of the + :func:`get_frames()`. + + Parameters + ---------- + frames : :class:`int` or :class:`list` or :class:`touple` or :class:`str` + Specified frame (:class:`int`), or frames (:class:`list`), or + range (:class:`touple`), or `all`/`everything` (:class:`str`). + (default='all') + + override : :class:`bool` + If True, an output already storred in :attr:`analysis_output` can + be override. (default=False) + + swap_atoms : :class:`dict`, optional + If this kwarg is passed with an appropriate dictionary a + :func:`pywindow.molecular.MolecularSystem.swap_atom_keys()` will + be applied to the extracted frame. + + forcefield : :class:`str`, optional + If this kwarg is passed with appropriate forcefield keyword a + :func:`pywindow.molecular.MolecularSystem.decipher_atom_keys()` + will be applied to the extracted frame. + + modular : :class:`bool`, optional + If this kwarg is passed a + :func:`pywindow.molecular.MolecularSystem.make_modular()` + will be applied to the extracted frame. (default=False) + + rebuild : :class:`bool`, optional + If this kwarg is passed a `rebuild=True` is passed to + :func:`pywindow.molecular.MolecularSystem.make_modular()` that + will be applied to the extracted frame. (default=False) + + ncpus : :class:`int`, optional + If ncpus > 1, then the analysis is performed in parallel for the + specified number of parallel jobs. Otherwise, it runs in serial. + (default=1) + + Returns + ------- + None : :class:`NoneType` + The function returns `None`, the analysis output is + returned to :attr:`analysis_output` dictionary. + + """ frames_for_analysis = [] # First populate the frames_for_analysis list. if isinstance(frames, int): @@ -617,6 +812,18 @@

Source code for pywindow.trajectory

                         raise _TrajectoryError(error)
 
 
[docs] def save_analysis(self, filepath=None, **kwargs): + """ + Dump the content of :attr:`analysis_output` as JSON dictionary. + + Parameters + ---------- + filepath : :class:`str` + The filepath for the JSON file. + + Returns + ------- + None : :class:`NoneType` + """ # We pass a copy of the analysis attribute dictionary. dict_obj = deepcopy(self.analysis_output) # If no filepath is provided we create one. @@ -682,6 +889,38 @@

Source code for pywindow.trajectory

 
 
 
[docs]class XYZ(object): + """ + A container for an XYZ type trajectory. + + This function takes an XYZ trajectory file and maps it for the + binary points in the file where each frame starts/ends. This way the + process is fast, as it not require loading the trajectory into computer + memory. When a frame is being extracted, it is only this frame that gets + loaded to the memory. + + Frames can be accessed individually and loaded as an unmodified string, + returned as a :class:`pywindow.molecular.MolecularSystem` (and analysed), + dumped as PDB or XYZ or JSON (if dumped as a + :attr:`pywindow.molecular.MolecularSystem.system`) + + Attributes + ---------- + filepath : :class:`str` + The filepath. + + filename : :class:`str` + The filename. + + system_id : :class:`str` + The system id inherited from the filename. + + frames : :class:`dict` + A dictionary that is populated, on the fly, with the extracted frames. + + analysis_output : :class:`dict` + A dictionary that is populated, on the fly, with the analysis output. + + """ def __init__(self, filepath): self.filepath = filepath self.filename = os.path.basename(filepath) @@ -726,7 +965,50 @@

Source code for pywindow.trajectory

                     progress = progress + len(bline)
             self.no_of_frames = frame + 1
 
-
[docs] def get_frames(self, frames, override=False, **kwargs): +
[docs] def get_frames(self, frames='all', override=False, **kwargs): + """ + Extract frames from the trajectory file. + + Depending on the passed parameters a frame, a list of particular + frames, a range of frames (from, to), or all frames can be extracted + with this function. + + Parameters + ---------- + frames : :class:`int` or :class:`list` or :class:`touple` or :class:`str` + Specified frame (:class:`int`), or frames (:class:`list`), or + range (:class:`touple`), or `all`/`everything` (:class:`str`). + (default=`all`) + + override : :class:`bool` + If True, a frame already storred in :attr:`frames` can be override. + (default=False) + + extract_data : :class:`bool`, optional + If False, a frame is returned as a :class:`str` block as in the + trajectory file. Ohterwise, it is extracted and returned as + :class:`pywindow.molecular.MolecularSystem`. (default=True) + + swap_atoms : :class:`dict`, optional + If this kwarg is passed with an appropriate dictionary a + :func:`pywindow.molecular.MolecularSystem.swap_atom_keys()` will + be applied to the extracted frame. + + forcefield : :class:`str`, optional + If this kwarg is passed with appropriate forcefield keyword a + :func:`pywindow.molecular.MolecularSystem.decipher_atom_keys()` + will be applied to the extracted frame. + + Returns + ------- + :class:`pywindow.molecular.MolecularSystem` + If a single frame is extracted. + + None : :class:`NoneType` + If more than one frame is extracted, the frames are returned to + :attr:`frames` + + """ if override is True: self.frames = {} if isinstance(frames, int): @@ -800,6 +1082,74 @@

Source code for pywindow.trajectory

         return frame_data
 
 
[docs] def analysis(self, frames='all', ncpus=1, override=False, **kwargs): + """ + Perform structural analysis on a frame/ set of frames. + + Depending on the passed parameters a frame, a list of particular + frames, a range of frames (from, to), or all frames can be analysed + with this function. + + The analysis is performed on each frame and each discrete molecule in + that frame separately. The steps are as follows: + + 1. A frame is extracted and returned as a :class:`MolecularSystem`. + 2. If `swap_atoms` is set the atom ids are swapped. + 3. If `forcefield` is set the atom ids are deciphered. + 4. If `rebuild` is set the molecules in the system are rebuild. + 5. Each discrete molecule is extracted as :class:`Molecule` + 6. Each molecule is analysed with :func:`Molecule.full_analysis()` + 7. Analysis output populates the :attr:`analysis_output` dictionary. + + As the analysis of trajectories often have to be unique, many options + are conditional. + + A side effect of this function is that the analysed frames are also + returned to the :attr:`frames` mimicking the behaviour of the + :func:`get_frames()`. + + Parameters + ---------- + frames : :class:`int` or :class:`list` or :class:`touple` or :class:`str` + Specified frame (:class:`int`), or frames (:class:`list`), or + range (:class:`touple`), or `all`/`everything` (:class:`str`). + (default='all') + + override : :class:`bool` + If True, an output already storred in :attr:`analysis_output` can + be override. (default=False) + + swap_atoms : :class:`dict`, optional + If this kwarg is passed with an appropriate dictionary a + :func:`pywindow.molecular.MolecularSystem.swap_atom_keys()` will + be applied to the extracted frame. + + forcefield : :class:`str`, optional + If this kwarg is passed with appropriate forcefield keyword a + :func:`pywindow.molecular.MolecularSystem.decipher_atom_keys()` + will be applied to the extracted frame. + + modular : :class:`bool`, optional + If this kwarg is passed a + :func:`pywindow.molecular.MolecularSystem.make_modular()` + will be applied to the extracted frame. (default=False) + + rebuild : :class:`bool`, optional + If this kwarg is passed a `rebuild=True` is passed to + :func:`pywindow.molecular.MolecularSystem.make_modular()` that + will be applied to the extracted frame. (default=False) + + ncpus : :class:`int`, optional + If ncpus > 1, then the analysis is performed in parallel for the + specified number of parallel jobs. Otherwise, it runs in serial. + (default=1) + + Returns + ------- + None : :class:`NoneType` + The function returns `None`, the analysis output is + returned to :attr:`analysis_output` dictionary. + + """ if override is True: self.analysis_output = {} if isinstance(frames, int): @@ -932,6 +1282,18 @@

Source code for pywindow.trajectory

             raise _ParallelAnalysisError("Parallel analysis failed.")
 
 
[docs] def save_analysis(self, filepath=None, **kwargs): + """ + Dump the content of :attr:`analysis_output` as JSON dictionary. + + Parameters + ---------- + filepath : :class:`str` + The filepath for the JSON file. + + Returns + ------- + None : :class:`NoneType` + """ # We pass a copy of the analysis attribute dictionary. dict_obj = deepcopy(self.analysis_output) # If no filepath is provided we create one. @@ -942,11 +1304,94 @@

Source code for pywindow.trajectory

             filepath = '/'.join((os.getcwd(), filepath))
         # Dump the dictionary to json file.
         Output().dump2json(dict_obj, filepath, default=to_list, **kwargs)
-        return
+ return
+ +
[docs] def save_frames(self, frames, filepath=None, filetype='pdb', **kwargs): + settings = { + "pdb": Output()._save_pdb, + "xyz": Output()._save_xyz, + "decipher": True, + "forcefield": None, + } + settings.update(kwargs) + if filetype.lower() not in settings.keys(): + raise _FormatError("The '{0}' file format is not supported".format( + filetype)) + frames_to_get = [] + if isinstance(frames, int): + frames_to_get.append(frames) + if isinstance(frames, list): + frames_to_get = frames + if isinstance(frames, tuple): + for frame in range(frames[0], frames[1]): + frames_to_get.append(frame) + if isinstance(frames, str): + if frames in ['all', 'everything']: + for frame in range(0, self.no_of_frames): + frames_to_get.append(frame) + for frame in frames_to_get: + if frame not in self.frames.keys(): + _ = self.get_frames(frame) + # If no filepath is provided we create one. + if filepath is None: + filepath = '/'.join((os.getcwd(), str(self.system_id))) + for frame in frames_to_get: + frame_molsys = self.frames[frame] + if settings[ + 'decipher'] is True and settings['forcefield'] is not None: + if "swap_atoms" in settings.keys(): + if isinstance(settings["swap_atoms"], dict): + frame_molsys.swap_atom_keys(settings["swap_atoms"]) + else: + raise _FunctionError( + "The swap_atom_keys function only accepts " + "'swap_atoms' argument in form of a dictionary.") + frame_molsys.decipher_atom_keys(settings["forcefield"]) + ffilepath = '_'.join((filepath, str(frame))) + if 'elements' not in frame_molsys.system.keys(): + raise _FunctionError( + "The frame (MolecularSystem object) needs to have " + "'elements' attribute within the system dictionary. " + "It is, therefore, neccessary that you set a decipher " + "keyword to True. (see manual)") + settings[filetype.lower()](frame_molsys.system, ffilepath, ** + kwargs)
[docs]class PDB(object): def __init__(self, filepath): + """ + A container for an PDB type trajectory. + + This function takes an PDB trajectory file and maps it for the + binary points in the file where each frame starts/ends. This way the + process is fast, as it not require loading the trajectory into computer + memory. When a frame is being extracted, it is only this frame that gets + loaded to the memory. + + Frames can be accessed individually and loaded as an unmodified string, + returned as a :class:`pywindow.molecular.MolecularSystem` (and analysed), + dumped as PDB or XYZ or JSON (if dumped as a + :attr:`pywindow.molecular.MolecularSystem.system`) + + Attributes + ---------- + filepath : :class:`str` + The filepath. + + filename : :class:`str` + The filename. + + system_id : :class:`str` + The system id inherited from the filename. + + frames : :class:`dict` + A dictionary that is populated, on the fly, with the extracted frames. + + analysis_output : :class:`dict` + A dictionary that is populated, on the fly, with the analysis output. + + """ self.filepath = filepath self.filename = os.path.basename(filepath) self.system_id = self.filename.split(".")[0] @@ -992,7 +1437,50 @@

Source code for pywindow.trajectory

                     progress = progress + len(bline)
             self.no_of_frames = frame
 
-
[docs] def get_frames(self, frames, override=False, **kwargs): +
[docs] def get_frames(self, frames='all', override=False, **kwargs): + """ + Extract frames from the trajectory file. + + Depending on the passed parameters a frame, a list of particular + frames, a range of frames (from, to), or all frames can be extracted + with this function. + + Parameters + ---------- + frames : :class:`int` or :class:`list` or :class:`touple` or :class:`str` + Specified frame (:class:`int`), or frames (:class:`list`), or + range (:class:`touple`), or `all`/`everything` (:class:`str`). + (default=`all`) + + override : :class:`bool` + If True, a frame already storred in :attr:`frames` can be override. + (default=False) + + extract_data : :class:`bool`, optional + If False, a frame is returned as a :class:`str` block as in the + trajectory file. Ohterwise, it is extracted and returned as + :class:`pywindow.molecular.MolecularSystem`. (default=True) + + swap_atoms : :class:`dict`, optional + If this kwarg is passed with an appropriate dictionary a + :func:`pywindow.molecular.MolecularSystem.swap_atom_keys()` will + be applied to the extracted frame. + + forcefield : :class:`str`, optional + If this kwarg is passed with appropriate forcefield keyword a + :func:`pywindow.molecular.MolecularSystem.decipher_atom_keys()` + will be applied to the extracted frame. + + Returns + ------- + :class:`pywindow.molecular.MolecularSystem` + If a single frame is extracted. + + None : :class:`NoneType` + If more than one frame is extracted, the frames are returned to + :attr:`frames` + + """ if override is True: self.frames = {} if isinstance(frames, int): @@ -1073,6 +1561,74 @@

Source code for pywindow.trajectory

         return frame_data
 
 
[docs] def analysis(self, frames='all', ncpus=1, override=False, **kwargs): + """ + Perform structural analysis on a frame/ set of frames. + + Depending on the passed parameters a frame, a list of particular + frames, a range of frames (from, to), or all frames can be analysed + with this function. + + The analysis is performed on each frame and each discrete molecule in + that frame separately. The steps are as follows: + + 1. A frame is extracted and returned as a :class:`MolecularSystem`. + 2. If `swap_atoms` is set the atom ids are swapped. + 3. If `forcefield` is set the atom ids are deciphered. + 4. If `rebuild` is set the molecules in the system are rebuild. + 5. Each discrete molecule is extracted as :class:`Molecule` + 6. Each molecule is analysed with :func:`Molecule.full_analysis()` + 7. Analysis output populates the :attr:`analysis_output` dictionary. + + As the analysis of trajectories often have to be unique, many options + are conditional. + + A side effect of this function is that the analysed frames are also + returned to the :attr:`frames` mimicking the behaviour of the + :func:`get_frames()`. + + Parameters + ---------- + frames : :class:`int` or :class:`list` or :class:`touple` or :class:`str` + Specified frame (:class:`int`), or frames (:class:`list`), or + range (:class:`touple`), or `all`/`everything` (:class:`str`). + (default='all') + + override : :class:`bool` + If True, an output already storred in :attr:`analysis_output` can + be override. (default=False) + + swap_atoms : :class:`dict`, optional + If this kwarg is passed with an appropriate dictionary a + :func:`pywindow.molecular.MolecularSystem.swap_atom_keys()` will + be applied to the extracted frame. + + forcefield : :class:`str`, optional + If this kwarg is passed with appropriate forcefield keyword a + :func:`pywindow.molecular.MolecularSystem.decipher_atom_keys()` + will be applied to the extracted frame. + + modular : :class:`bool`, optional + If this kwarg is passed a + :func:`pywindow.molecular.MolecularSystem.make_modular()` + will be applied to the extracted frame. (default=False) + + rebuild : :class:`bool`, optional + If this kwarg is passed a `rebuild=True` is passed to + :func:`pywindow.molecular.MolecularSystem.make_modular()` that + will be applied to the extracted frame. (default=False) + + ncpus : :class:`int`, optional + If ncpus > 1, then the analysis is performed in parallel for the + specified number of parallel jobs. Otherwise, it runs in serial. + (default=1) + + Returns + ------- + None : :class:`NoneType` + The function returns `None`, the analysis output is + returned to :attr:`analysis_output` dictionary. + + """ if override is True: self.analysis_output = {} if isinstance(frames, int): @@ -1205,6 +1761,18 @@

Source code for pywindow.trajectory

             raise _ParallelAnalysisError("Parallel analysis failed.")
 
 
[docs] def save_analysis(self, filepath=None, **kwargs): + """ + Dump the content of :attr:`analysis_output` as JSON dictionary. + + Parameters + ---------- + filepath : :class:`str` + The filepath for the JSON file. + + Returns + ------- + None : :class:`NoneType` + """ # We pass a copy of the analysis attribute dictionary. dict_obj = deepcopy(self.analysis_output) # If no filepath is provided we create one. @@ -1215,7 +1783,58 @@

Source code for pywindow.trajectory

             filepath = '/'.join((os.getcwd(), filepath))
         # Dump the dictionary to json file.
         Output().dump2json(dict_obj, filepath, default=to_list, **kwargs)
-        return
+ return
+ +
[docs] def save_frames(self, frames, filepath=None, filetype='pdb', **kwargs): + settings = { + "pdb": Output()._save_pdb, + "xyz": Output()._save_xyz, + "decipher": True, + "forcefield": None, + } + settings.update(kwargs) + if filetype.lower() not in settings.keys(): + raise _FormatError("The '{0}' file format is not supported".format( + filetype)) + frames_to_get = [] + if isinstance(frames, int): + frames_to_get.append(frames) + if isinstance(frames, list): + frames_to_get = frames + if isinstance(frames, tuple): + for frame in range(frames[0], frames[1]): + frames_to_get.append(frame) + if isinstance(frames, str): + if frames in ['all', 'everything']: + for frame in range(0, self.no_of_frames): + frames_to_get.append(frame) + for frame in frames_to_get: + if frame not in self.frames.keys(): + _ = self.get_frames(frame) + # If no filepath is provided we create one. + if filepath is None: + filepath = '/'.join((os.getcwd(), str(self.system_id))) + for frame in frames_to_get: + frame_molsys = self.frames[frame] + if settings[ + 'decipher'] is True and settings['forcefield'] is not None: + if "swap_atoms" in settings.keys(): + if isinstance(settings["swap_atoms"], dict): + frame_molsys.swap_atom_keys(settings["swap_atoms"]) + else: + raise _FunctionError( + "The swap_atom_keys function only accepts " + "'swap_atoms' argument in form of a dictionary.") + frame_molsys.decipher_atom_keys(settings["forcefield"]) + ffilepath = '_'.join((filepath, str(frame))) + if 'elements' not in frame_molsys.system.keys(): + raise _FunctionError( + "The frame (MolecularSystem object) needs to have " + "'elements' attribute within the system dictionary. " + "It is, therefore, neccessary that you set a decipher " + "keyword to True. (see manual)") + settings[filetype.lower()](frame_molsys.system, ffilepath, ** + kwargs)
diff --git a/docs/genindex.html b/docs/genindex.html index 5474450..3986cba 100644 --- a/docs/genindex.html +++ b/docs/genindex.html @@ -181,6 +181,12 @@

A

diff --git a/docs/searchindex.js b/docs/searchindex.js index e3f10fe..509d58f 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["index","modules","pywindow"],envversion:53,filenames:["index.rst","modules.rst","pywindow.rst"],objects:{"":{pywindow:[2,0,0,"-"]},"pywindow.io_tools":{Input:[2,1,1,""],Output:[2,1,1,""]},"pywindow.io_tools.Input":{load_file:[2,2,1,""],load_rdkit_mol:[2,2,1,""]},"pywindow.io_tools.Output":{dump2file:[2,2,1,""],dump2json:[2,2,1,""]},"pywindow.molecular":{MolecularSystem:[2,1,1,""],Molecule:[2,1,1,""]},"pywindow.molecular.MolecularSystem":{decipher_atom_keys:[2,2,1,""],dump_system:[2,2,1,""],dump_system_json:[2,2,1,""],load_file:[2,3,1,""],load_rdkit_mol:[2,3,1,""],load_system:[2,3,1,""],make_modular:[2,2,1,""],molecules:[2,4,1,""],rebuild_system:[2,2,1,""],swap_atom_keys:[2,2,1,""],system:[2,4,1,""],system_id:[2,4,1,""],system_to_molecule:[2,2,1,""]},"pywindow.molecular.Molecule":{atom_ids:[2,4,1,""],calculate_average_diameter:[2,2,1,""],calculate_centre_of_mass:[2,2,1,""],calculate_maximum_diameter:[2,2,1,""],calculate_pore_diameter:[2,2,1,""],calculate_pore_diameter_opt:[2,2,1,""],calculate_pore_volume:[2,2,1,""],calculate_pore_volume_opt:[2,2,1,""],calculate_windows:[2,2,1,""],coordinates:[2,4,1,""],dump_molecule:[2,2,1,""],dump_properties_json:[2,2,1,""],elements:[2,4,1,""],full_analysis:[2,2,1,""],mol:[2,4,1,""],molecular_weight:[2,2,1,""],molecule_id:[2,4,1,""],no_of_atoms:[2,4,1,""],parent_system:[2,4,1,""],properties:[2,4,1,""],shift_to_origin:[2,2,1,""]},"pywindow.trajectory":{DLPOLY:[2,1,1,""],PDB:[2,1,1,""],XYZ:[2,1,1,""],make_supercell:[2,5,1,""]},"pywindow.trajectory.DLPOLY":{analysis:[2,2,1,""],get_frames:[2,2,1,""],save_analysis:[2,2,1,""],save_frames:[2,2,1,""]},"pywindow.trajectory.PDB":{analysis:[2,2,1,""],get_frames:[2,2,1,""],save_analysis:[2,2,1,""]},"pywindow.trajectory.XYZ":{analysis:[2,2,1,""],get_frames:[2,2,1,""],save_analysis:[2,2,1,""]},"pywindow.utilities":{acylidricity:[2,5,1,""],align_principal_ax:[2,5,1,""],angle_between_vectors:[2,5,1,""],asphericity:[2,5,1,""],calc_acylidricity:[2,5,1,""],calc_asphericity:[2,5,1,""],calc_relative_shape_anisotropy:[2,5,1,""],calculate_pore_shape:[2,5,1,""],calculate_window_diameter:[2,5,1,""],cart2frac_all:[2,5,1,""],cartisian_from_fractional:[2,5,1,""],center_of_coor:[2,5,1,""],center_of_mass:[2,5,1,""],circumcircle:[2,5,1,""],circumcircle_window:[2,5,1,""],compose_atom_list:[2,5,1,""],correct_pore_diameter:[2,5,1,""],create_supercell:[2,5,1,""],decipher_atom_key:[2,5,1,""],decompose_atom_list:[2,5,1,""],discrete_molecules:[2,5,1,""],distance:[2,5,1,""],dlf_notation:[2,5,1,""],find_average_diameter:[2,5,1,""],find_windows:[2,5,1,""],find_windows_new:[2,5,1,""],frac2cart_all:[2,5,1,""],fractional_from_cartesian:[2,5,1,""],get_gyration_tensor:[2,5,1,""],get_inertia_tensor:[2,5,1,""],get_tensor_eigenvalues:[2,5,1,""],get_window_com:[2,5,1,""],is_inside_polyhedron:[2,5,1,""],is_number:[2,5,1,""],lattice_array_to_unit_cell:[2,5,1,""],max_dim:[2,5,1,""],molecular_weight:[2,5,1,""],normal_vector:[2,5,1,""],normalize_vector:[2,5,1,""],opls_notation:[2,5,1,""],opt_pore_diameter:[2,5,1,""],optimise_xy:[2,5,1,""],optimise_z:[2,5,1,""],pore_diameter:[2,5,1,""],principal_axes:[2,5,1,""],relative_shape_anisotropy:[2,5,1,""],rotation_matrix_arbitrary_axis:[2,5,1,""],shift_com:[2,5,1,""],sphere_volume:[2,5,1,""],to_list:[2,5,1,""],unique:[2,5,1,""],unit_cell_to_lattice_array:[2,5,1,""],vector_analysis:[2,5,1,""],vector_analysis_pore_shape:[2,5,1,""],vector_analysis_reversed:[2,5,1,""],vector_preanalysis:[2,5,1,""],volume_from_cell_parameters:[2,5,1,""],volume_from_lattice_array:[2,5,1,""],window_analysis:[2,5,1,""],window_shape:[2,5,1,""]},pywindow:{io_tools:[2,0,0,"-"],molecular:[2,0,0,"-"],tables:[2,0,0,"-"],trajectory:[2,0,0,"-"],utilities:[2,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","classmethod","Python class method"],"4":["py","attribute","Python attribute"],"5":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method","3":"py:classmethod","4":"py:attribute","5":"py:function"},terms:{"20system":2,"20transform":2,"3x3":2,"case":2,"class":2,"default":2,"float":2,"function":2,"import":[0,2],"int":2,"new":2,"return":2,"true":2,"void":2,Added:2,EPS:2,For:[0,2],Not:2,The:2,Uses:2,Using:[0,2],_functionerror:2,_ncpu:2,_shape:2,about:2,access:2,acylidr:2,acylindr:2,adjust:2,after:2,aka:2,align_principal_ax:2,all:2,allow:[0,2],also:2,analys:2,analysi:[0,2],angl:2,angle_between_vector:2,angstrom:2,ani:2,anisotropi:2,anoth:[0,2],applic:2,appropri:2,approxim:2,arai:2,arg:2,argument:2,arrai:2,aspher:2,assembl:2,atom:[0,2],atom_id:2,atom_id_1:2,atom_id_2:2,atom_kei:2,atom_list:2,atom_set:2,averag:2,axi:2,back:2,base:2,belong:2,better:2,between:2,blake:2,bond:2,bool:2,bound:2,boundari:0,build:2,calc_acylidr:2,calc_aspher:2,calc_relative_shape_anisotropi:2,calcul:2,calculate_average_diamet:2,calculate_centre_of_mass:2,calculate_maximum_diamet:2,calculate_pore_diamet:2,calculate_pore_diameter_opt:2,calculate_pore_shap:2,calculate_pore_volum:2,calculate_pore_volume_opt:2,calculate_window:2,calculate_window_diamet:2,cam:2,can:[0,2],carri:2,cart2frac_al:2,cartesian:2,cartisian_from_fract:2,caten:2,caviti:2,ccdc:2,ccdcresourc:2,cell:2,center:2,center_of_coor:2,center_of_mass:2,centr:2,chang:2,check:2,chem:[0,2],chemic:2,circular:2,circumcircl:2,circumcircle_window:2,classmethod:2,coincid:2,com:[0,2],com_adjust:2,compos:2,compose_atom_list:2,comput:2,condit:2,condition:2,consid:2,conta:2,contain:2,content:1,convers:2,convert:2,coordin:2,correct:2,correct_pore_diamet:2,correspond:2,coval:2,cpu:2,creat:2,create_supercel:2,creation:2,criteria:2,cryst:2,crystallograph:2,cse:2,current:2,custom:0,daresburi:2,data:[0,2],date:[0,2],dbscan:2,deciph:[0,2],decipher_atom_kei:[0,2],decompos:2,decompose_atom_list:2,defin:2,defualt:2,depend:2,der:2,descript:2,descriptor:2,determin:2,develop:2,diamens:2,diamet:2,dict:2,dict_:2,dict_kei:2,dictionari:[0,2],dimens:2,direct:2,directli:2,discreet:2,discret:2,discrete_molecul:2,distanc:2,dl_f:2,dl_field:2,dl_poli:2,dlf:2,dlf_notat:2,dlpoli:2,docstr:2,done:2,dummi:2,dump2fil:2,dump2json:2,dump:2,dump_molecul:2,dump_properties_json:2,dump_system:2,dump_system_json:2,dynam:2,each:2,element:2,elemental_radii:2,elements_vdw:2,engin:2,entiti:2,equal:2,equival:2,equval:2,esenti:2,especi:2,essenti:2,estim:2,exampl:2,except:2,exchang:2,exclud:2,explain:2,express:2,extens:2,extract:2,fals:2,featur:2,field:[0,2],file:[0,2],filenam:2,filepath:2,filetyp:2,find:2,find_average_diamet:2,find_window:2,find_windows_new:2,finit:2,first:2,fit:2,fix:2,float64:2,follow:0,forc:[0,2],forcefield:2,forcfield:2,format:2,formula:2,found:2,frac2cart_al:2,frac_coordin:2,fraction:2,fractional_from_cartesian:2,frame:2,from:[0,2],frontfront:2,frontier:2,full:2,full_analysi:2,gener:[0,2],geometr:2,get:2,get_fram:2,get_gyration_tensor:2,get_inertia_tensor:2,get_tensor_eigenvalu:2,get_window_com:2,github:0,gyrat:2,have:2,head:0,here:2,how:2,howev:2,htm:2,http:[0,2],idea:2,ids:[0,2],implement:2,includ:2,include_com:2,increas:2,increment2:2,increment:2,index:0,individu:2,individuum:2,inertia:2,inf:2,inform:2,inherit:2,initi:2,initial_com:2,initialis:2,input:2,input_list:2,inspir:2,instanc:2,instead:2,intend:2,interact:2,interconnect:2,intersect:2,intrins:2,invari:2,invok:2,io_tool:1,is_inside_polyhedron:2,is_numb:2,item:2,itself:2,jelfsmaterialsgroup:0,json:2,jul:2,kei:2,keyword:2,known:2,kwarg:2,laboratori:2,lattic:2,lattice_arrai:2,lattice_array_to_unit_cel:2,lb_z:2,librari:0,line:2,list:1,load:2,load_fil:[0,2],load_rdkit_mol:[0,2],load_system:[0,2],loader:2,locali:2,log:1,look:2,main:2,make_modular:2,make_supercel:2,marcinmiklitz:0,mass:2,match:2,math:2,matrix:2,max_dim:2,maximum:2,mayb:2,meant:2,measur:2,method:[0,2],model:2,modifi:2,modul:[0,1],modular:2,mol2:0,mol:2,mol_id:2,mol_siz:2,molecul:[0,2],molecular:[0,1],molecular_weight:2,molecularsystem:[0,2],molecule_id:2,moleculesystem:[0,2],molfrommol2fil:0,molsi:0,molsys2:0,moment:2,mongodb:2,more:2,most:[0,2],name:2,natur:2,ncpu:2,ndarrai:2,need:2,neg:2,nest:2,no_of_atom:2,none:2,nonetyp:2,normal:2,normal_vector:2,normalize_vector:2,notat:2,note:2,now:2,number:2,numpi:2,obj:2,object:[0,2],occur:2,oct:2,old:2,onc:2,one:2,onli:2,open:2,oper:2,opl:[0,2],opls2005:2,opls3:2,opls_not:2,oplsaa:2,opt_pore_diamet:2,optimis:2,optimise_xi:2,optimise_z:2,option:2,org:2,origin:2,other:2,otherwis:2,our:0,out:2,output:2,over:2,overlai:2,overrid:2,p38:2,packag:1,page:0,parallelis:2,parallelpip:2,param:2,paramet:2,parent_system:2,part:2,pass:2,path:2,pdb:2,perform:2,period:[0,2],point:2,polyhedron:2,popul:2,pore:[0,2],pore_diamet:2,pore_opt:2,posit:2,pre:2,principal_ax:2,process:2,properti:2,pudx:0,purpos:2,python:[0,2],pywindowfunct:2,quick:0,radian:2,radii:2,radiu:2,rais:2,rang:2,rather:2,rcov:2,rdchem:2,rdkit:[0,2],rdkit_mol:0,readabl:2,realtiv:2,rebuild:[0,2],rebuild_molsi:0,rebuild_system:[0,2],recogn:2,refin:2,rel:2,relat:2,relative_shape_anisotropi:2,releas:0,remain:2,repres:2,requir:[0,2],resourc:2,resourcefilelist:2,result:2,retriev:2,revers:2,rotat:2,rotation_matrix_arbitrary_axi:2,run:2,ruppweb:2,same:2,sampl:2,save:2,save_analysi:2,save_fram:2,scienc:2,search:0,second:2,see:[0,2],sensit:2,separ:2,serial:2,set:2,shape:2,share:2,shift:2,shift_com:2,shift_to_origin:2,should:2,similar:2,similarli:2,simul:2,singl:2,size:2,some:2,some_forcefield:0,sort:2,sourc:2,space:2,spacer:2,special:2,specifi:2,sphere:2,sphere_radiu:2,sphere_volum:2,split:2,spreadsheet:2,stabl:0,stand:2,start:[0,2],step:2,stfc:2,stor:2,store:2,str:2,string:2,structur:[0,2],submodul:1,supercel:2,support:[0,2],swap:2,swap_atom_kei:[0,2],swap_dict:2,system:[0,2],system_id:2,system_nam:2,system_to_molecul:2,tabl:1,take:2,tensor:2,than:2,thei:2,them:2,therefor:2,thi:2,through:[0,2],to_list:2,tol:2,tolarenac:2,tool:[0,2],toupl:2,trajectori:1,translat:2,triclin:2,tutori:2,two:2,type:2,uniqu:2,unit:2,unit_cell_to_lattice_arrai:2,updat:2,use:[0,2],used:2,user:2,uses:2,using:2,util:1,v3000:2,valid:2,valu:2,van:2,vari:2,vector:2,vector_analysi:2,vector_analysis_pore_shap:2,vector_analysis_revers:2,vector_preanalysi:2,version:2,vestor:2,volum:2,volume_from_cell_paramet:2,volume_from_lattice_arrai:2,waal:2,wai:2,weight:2,were:2,what:2,when:2,where:2,which:2,whole:2,widnow:2,window:2,window_analysi:2,window_shap:2,within:2,work:2,wrong:2,www:2,xlsx:2,xrai:2,xyz:[0,2],yong:2,z_bound:2,z_second_mini:2},titles:["Welcome to pywindow\u2019s documentation!","pywindow","pywindow package"],titleterms:{content:2,document:0,exampl:0,indic:0,input:0,io_tool:2,list:2,load:0,log:2,modul:2,molecular:2,overview:0,packag:2,pre:0,process:0,pywindow:[0,1,2],submodul:2,tabl:[0,2],test:[],trajectori:2,util:2,welcom:0}}) \ No newline at end of file +Search.setIndex({docnames:["index","modules","pywindow"],envversion:53,filenames:["index.rst","modules.rst","pywindow.rst"],objects:{"":{pywindow:[2,0,0,"-"]},"pywindow.io_tools":{Input:[2,1,1,""],Output:[2,1,1,""]},"pywindow.io_tools.Input":{load_file:[2,2,1,""],load_rdkit_mol:[2,2,1,""]},"pywindow.io_tools.Output":{dump2file:[2,2,1,""],dump2json:[2,2,1,""]},"pywindow.molecular":{MolecularSystem:[2,1,1,""],Molecule:[2,1,1,""]},"pywindow.molecular.MolecularSystem":{decipher_atom_keys:[2,2,1,""],dump_system:[2,2,1,""],dump_system_json:[2,2,1,""],load_file:[2,3,1,""],load_rdkit_mol:[2,3,1,""],load_system:[2,3,1,""],make_modular:[2,2,1,""],molecules:[2,4,1,""],rebuild_system:[2,2,1,""],swap_atom_keys:[2,2,1,""],system:[2,4,1,""],system_id:[2,4,1,""],system_to_molecule:[2,2,1,""]},"pywindow.molecular.Molecule":{atom_ids:[2,4,1,""],calculate_average_diameter:[2,2,1,""],calculate_centre_of_mass:[2,2,1,""],calculate_maximum_diameter:[2,2,1,""],calculate_pore_diameter:[2,2,1,""],calculate_pore_diameter_opt:[2,2,1,""],calculate_pore_volume:[2,2,1,""],calculate_pore_volume_opt:[2,2,1,""],calculate_windows:[2,2,1,""],coordinates:[2,4,1,""],dump_molecule:[2,2,1,""],dump_properties_json:[2,2,1,""],elements:[2,4,1,""],full_analysis:[2,2,1,""],mol:[2,4,1,""],molecular_weight:[2,2,1,""],molecule_id:[2,4,1,""],no_of_atoms:[2,4,1,""],parent_system:[2,4,1,""],properties:[2,4,1,""],shift_to_origin:[2,2,1,""]},"pywindow.trajectory":{DLPOLY:[2,1,1,""],PDB:[2,1,1,""],XYZ:[2,1,1,""],make_supercell:[2,5,1,""]},"pywindow.trajectory.DLPOLY":{analysis:[2,2,1,""],analysis_output:[2,4,1,""],filepath:[2,4,1,""],frames:[2,4,1,""],get_frames:[2,2,1,""],save_analysis:[2,2,1,""],save_frames:[2,2,1,""],system_id:[2,4,1,""]},"pywindow.trajectory.PDB":{analysis:[2,2,1,""],get_frames:[2,2,1,""],save_analysis:[2,2,1,""],save_frames:[2,2,1,""]},"pywindow.trajectory.XYZ":{analysis:[2,2,1,""],analysis_output:[2,4,1,""],filename:[2,4,1,""],filepath:[2,4,1,""],frames:[2,4,1,""],get_frames:[2,2,1,""],save_analysis:[2,2,1,""],save_frames:[2,2,1,""],system_id:[2,4,1,""]},"pywindow.utilities":{acylidricity:[2,5,1,""],align_principal_ax:[2,5,1,""],angle_between_vectors:[2,5,1,""],asphericity:[2,5,1,""],calc_acylidricity:[2,5,1,""],calc_asphericity:[2,5,1,""],calc_relative_shape_anisotropy:[2,5,1,""],calculate_pore_shape:[2,5,1,""],calculate_window_diameter:[2,5,1,""],cart2frac_all:[2,5,1,""],cartisian_from_fractional:[2,5,1,""],center_of_coor:[2,5,1,""],center_of_mass:[2,5,1,""],circumcircle:[2,5,1,""],circumcircle_window:[2,5,1,""],compose_atom_list:[2,5,1,""],correct_pore_diameter:[2,5,1,""],create_supercell:[2,5,1,""],decipher_atom_key:[2,5,1,""],decompose_atom_list:[2,5,1,""],discrete_molecules:[2,5,1,""],distance:[2,5,1,""],dlf_notation:[2,5,1,""],find_average_diameter:[2,5,1,""],find_windows:[2,5,1,""],find_windows_new:[2,5,1,""],frac2cart_all:[2,5,1,""],fractional_from_cartesian:[2,5,1,""],get_gyration_tensor:[2,5,1,""],get_inertia_tensor:[2,5,1,""],get_tensor_eigenvalues:[2,5,1,""],get_window_com:[2,5,1,""],is_inside_polyhedron:[2,5,1,""],is_number:[2,5,1,""],lattice_array_to_unit_cell:[2,5,1,""],max_dim:[2,5,1,""],molecular_weight:[2,5,1,""],normal_vector:[2,5,1,""],normalize_vector:[2,5,1,""],opls_notation:[2,5,1,""],opt_pore_diameter:[2,5,1,""],optimise_xy:[2,5,1,""],optimise_z:[2,5,1,""],pore_diameter:[2,5,1,""],principal_axes:[2,5,1,""],relative_shape_anisotropy:[2,5,1,""],rotation_matrix_arbitrary_axis:[2,5,1,""],shift_com:[2,5,1,""],sphere_volume:[2,5,1,""],to_list:[2,5,1,""],unique:[2,5,1,""],unit_cell_to_lattice_array:[2,5,1,""],vector_analysis:[2,5,1,""],vector_analysis_pore_shape:[2,5,1,""],vector_analysis_reversed:[2,5,1,""],vector_preanalysis:[2,5,1,""],volume_from_cell_parameters:[2,5,1,""],volume_from_lattice_array:[2,5,1,""],window_analysis:[2,5,1,""],window_shape:[2,5,1,""]},pywindow:{io_tools:[2,0,0,"-"],molecular:[2,0,0,"-"],tables:[2,0,0,"-"],trajectory:[2,0,0,"-"],utilities:[2,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","classmethod","Python class method"],"4":["py","attribute","Python attribute"],"5":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method","3":"py:classmethod","4":"py:attribute","5":"py:function"},terms:{"20system":2,"20transform":2,"3x3":2,"case":2,"class":2,"default":2,"float":2,"function":2,"import":[0,2],"int":2,"new":2,"return":2,"true":2,"void":2,Added:2,EPS:2,For:[0,2],Not:2,The:2,Then:2,Uses:2,Using:[0,2],_functionerror:2,_ncpu:2,_shape:2,about:2,access:2,acylidr:2,acylindr:2,adjust:2,after:2,aka:2,align_principal_ax:2,all:2,allow:[0,2],alreadi:2,also:2,altern:2,analys:2,analysi:[0,2],analysis_output:2,angl:2,angle_between_vector:2,angstrom:2,ani:2,anisotropi:2,anoth:[0,2],appli:2,applic:2,appropri:2,approxim:2,arai:2,arg:2,argument:2,arrai:2,aspher:2,assembl:2,atom:[0,2],atom_id:2,atom_id_1:2,atom_id_2:2,atom_kei:2,atom_list:2,atom_set:2,autom:2,averag:2,axi:2,back:2,base:2,behaviour:2,being:2,belong:2,benefit:2,better:2,between:2,binari:2,blake:2,block:2,bond:2,bool:2,bottleneck:2,bound:2,boundari:0,build:2,calc_acylidr:2,calc_aspher:2,calc_relative_shape_anisotropi:2,calcul:2,calculate_average_diamet:2,calculate_centre_of_mass:2,calculate_maximum_diamet:2,calculate_pore_diamet:2,calculate_pore_diameter_opt:2,calculate_pore_shap:2,calculate_pore_volum:2,calculate_pore_volume_opt:2,calculate_window:2,calculate_window_diamet:2,cam:2,can:[0,2],carri:2,cart2frac_al:2,cartesian:2,cartisian_from_fract:2,caten:2,caviti:2,ccdc:2,ccdcresourc:2,cell:2,center:2,center_of_coor:2,center_of_mass:2,centr:2,chang:2,check:2,chem:[0,2],chemic:2,choos:2,chunk:2,circular:2,circumcircl:2,circumcircle_window:2,classmethod:2,coincid:2,com:[0,2],com_adjust:2,compos:2,compose_atom_list:2,comput:2,condit:2,condition:2,consid:2,consit:2,conta:2,contain:2,content:1,convers:2,convert:2,coordin:2,correct:2,correct_pore_diamet:2,correspond:2,cost:2,coval:2,cpu:2,creat:2,create_supercel:2,creation:2,criteria:2,cryst:2,crystallograph:2,cse:2,current:2,custom:0,daresburi:2,data:[0,2],date:[0,2],dbscan:2,deciph:[0,2],decipher_atom_kei:[0,2],decompos:2,decompose_atom_list:2,defin:2,defualt:2,depend:2,der:2,descript:2,descriptor:2,determin:2,develop:2,diamens:2,diamet:2,dict:2,dict_:2,dict_kei:2,dictionari:[0,2],dimens:2,direct:2,directli:2,discreet:2,discret:2,discrete_molecul:2,distanc:2,dl_f:2,dl_field:2,dl_poli:2,dl_poly_c:2,dlf:2,dlf_notat:2,dlpoli:2,docstr:2,done:2,downfal:2,dummi:2,dump2fil:2,dump2json:2,dump:2,dump_molecul:2,dump_properties_json:2,dump_system:2,dump_system_json:2,dynam:2,each:2,effect:2,element:2,elemental_radii:2,elements_vdw:2,end:2,engin:2,entiti:2,equal:2,equival:2,equval:2,esenti:2,especi:2,essenti:2,estim:2,everyth:2,exampl:2,except:2,exchang:2,exclud:2,explain:2,express:2,extens:2,extract:2,extract_data:2,fals:2,fast:2,featur:2,field:[0,2],file:[0,2],filenam:2,filepath:2,filetyp:2,find:2,find_average_diamet:2,find_window:2,find_windows_new:2,finit:2,first:2,fit:2,fix:2,float64:2,fly:2,follow:[0,2],forc:[0,2],forcefield:2,forcfield:2,form:2,format:2,formula:2,found:2,frac2cart_al:2,frac_coordin:2,fraction:2,fractional_from_cartesian:2,frame:2,from:[0,2],frontfront:2,frontier:2,full:2,full_analysi:2,gener:[0,2],geometr:2,get:2,get_fram:2,get_gyration_tensor:2,get_inertia_tensor:2,get_tensor_eigenvalu:2,get_window_com:2,github:0,gyrat:2,have:2,head:0,here:2,histori:2,how:2,howev:2,htm:2,http:[0,2],idea:2,ids:[0,2],implement:2,includ:2,include_com:2,increas:2,increment2:2,increment:2,index:0,individu:2,individuum:2,inertia:2,inf:2,inform:2,inherit:2,initi:2,initial_com:2,initialis:2,input:2,input_list:2,inspir:2,instanc:2,instead:2,intend:2,interact:2,interconnect:2,intersect:2,intrins:2,invari:2,invok:2,io_tool:1,is_inside_polyhedron:2,is_numb:2,item:2,itself:2,jelfsmaterialsgroup:0,job:2,json:2,jul:2,kei:2,keyword:2,known:2,kwarg:2,laboratori:2,lattic:2,lattice_arrai:2,lattice_array_to_unit_cel:2,lb_z:2,librari:0,line:2,list:1,load:2,load_fil:[0,2],load_rdkit_mol:[0,2],load_system:[0,2],loader:2,locali:2,log:1,look:2,main:2,major:2,make_modular:2,make_supercel:2,mani:2,manner:2,map:2,marcinmiklitz:0,mass:2,match:2,math:2,matrix:2,max_dim:2,maximum:2,mayb:2,meant:2,measur:2,memori:2,method:[0,2],mimick:2,miniscul:2,model:2,modifi:2,modul:[0,1],modular:2,mol2:0,mol:2,mol_id:2,mol_siz:2,molecul:[0,2],molecular:[0,1],molecular_weight:2,molecularsystem:[0,2],molecule_id:2,moleculesystem:[0,2],molfrommol2fil:0,molsi:0,molsys2:0,moment:2,mongodb:2,more:2,most:[0,2],name:2,natur:2,ncpu:2,ndarrai:2,need:2,neg:2,nest:2,no_of_atom:2,none:2,nonetyp:2,normal:2,normal_vector:2,normalize_vector:2,notat:2,note:2,now:2,number:2,numpi:2,obj:2,object:[0,2],occur:2,oct:2,often:2,ohterwis:2,old:2,onc:2,one:2,onli:2,open:2,oper:2,opl:[0,2],opls2005:2,opls3:2,opls_not:2,oplsaa:2,opt_pore_diamet:2,optimis:2,optimise_xi:2,optimise_z:2,option:2,org:2,origin:2,other:2,otherwis:2,our:0,out:2,output:2,over:2,overlai:2,overrid:2,p38:2,packag:1,page:0,parallel:2,parallelis:2,parallelpip:2,param:2,paramet:2,parent_system:2,part:2,particular:2,pass:2,path:2,pdb:2,perform:2,period:[0,2],point:2,polyhedron:2,popul:2,pore:[0,2],pore_diamet:2,pore_opt:2,posit:2,possibl:2,pre:2,principal_ax:2,process:2,properti:2,pudx:0,purpos:2,python:[0,2],pywindowfunct:2,quick:0,radian:2,radii:2,radiu:2,rais:2,rang:2,rather:2,rcov:2,rdchem:2,rdkit:[0,2],rdkit_mol:0,readabl:2,realtiv:2,rebuild:[0,2],rebuild_molsi:0,rebuild_system:[0,2],recogn:2,refin:2,rel:2,relat:2,relative_shape_anisotropi:2,releas:0,remain:2,repres:2,requir:[0,2],resourc:2,resourcefilelist:2,respect:2,result:2,retriev:2,revers:2,rotat:2,rotation_matrix_arbitrary_axi:2,run:2,ruppweb:2,same:2,sampl:2,save:2,save_analysi:2,save_fram:2,scienc:2,search:0,second:2,see:[0,2],sensit:2,separ:2,serial:2,set:2,shape:2,share:2,shift:2,shift_com:2,shift_to_origin:2,should:2,side:2,similar:2,similarli:2,simul:2,singl:2,size:2,some:2,some_forcefield:0,sort:2,sourc:2,space:2,spacer:2,special:2,specifi:2,sphere:2,sphere_radiu:2,sphere_volum:2,split:2,spreadsheet:2,stabl:0,stand:2,start:[0,2],step:2,stfc:2,stor:2,store:2,str:2,straightforward:2,string:2,structur:[0,2],submodul:1,supercel:2,support:[0,2],swap:2,swap_atom:2,swap_atom_kei:[0,2],swap_dict:2,system:[0,2],system_id:2,system_nam:2,system_to_molecul:2,tabl:1,take:2,tensor:2,than:2,thei:2,them:2,therefor:2,thi:2,through:[0,2],to_list:2,tol:2,tolarenac:2,tool:[0,2],toupl:2,trajectori:1,translat:2,triclin:2,tutori:2,two:2,type:2,uniqu:2,unit:2,unit_cell_to_lattice_arrai:2,unitcel:2,unmodifi:2,updat:2,use:[0,2],used:2,user:2,uses:2,using:2,usual:2,util:1,v3000:2,valid:2,valu:2,van:2,vari:2,vector:2,vector_analysi:2,vector_analysis_pore_shap:2,vector_analysis_revers:2,vector_preanalysi:2,version:2,vestor:2,volum:2,volume_from_cell_paramet:2,volume_from_lattice_arrai:2,waal:2,wai:2,weight:2,were:2,what:2,when:2,where:2,which:2,whole:2,widnow:2,window:2,window_analysi:2,window_shap:2,within:2,work:2,wrong:2,www:2,xlsx:2,xrai:2,xyz:[0,2],yong:2,z_bound:2,z_second_mini:2},titles:["Welcome to pywindow\u2019s documentation!","pywindow","pywindow package"],titleterms:{content:2,document:0,exampl:0,indic:0,input:0,io_tool:2,list:2,load:0,log:2,modul:2,molecular:2,overview:0,packag:2,pre:0,process:0,pywindow:[0,1,2],submodul:2,tabl:[0,2],test:[],trajectori:2,util:2,welcom:0}}) \ No newline at end of file diff --git a/pywindow/molecular.py b/pywindow/molecular.py index 23118da..d1dfc9e 100644 --- a/pywindow/molecular.py +++ b/pywindow/molecular.py @@ -769,19 +769,19 @@ class MolecularSystem: .. code-block:: python - pywindow.MolecularSystem.load_file(`filepath`) + pywindow.molecular.MolecularSystem.load_file(`filepath`) 2. Using RDKit molecule object as an input: .. code-block:: python - pywindow.MolecularSystem.load_rdkit_mol(rdkit.Chem.rdchem.Mol) + pywindow.molecular.MolecularSystem.load_rdkit_mol(rdkit.Chem.rdchem.Mol) 3. Using a dictionary (or another :attr:`MoleculeSystem.system`) as input: .. code-block:: python - pywindow.MolecularSystem.load_system({...}) + pywindow.molecular.MolecularSystem.load_system({...}) Attributes ---------- @@ -935,7 +935,7 @@ def swap_atom_keys(self, swap_dict, dict_key='atom_ids'): .. code-block:: python - pywindow.MolecularSystem.swap_atom_keys({'he': 'H'}) + pywindow.molecular.MolecularSystem.swap_atom_keys({'he': 'H'}) Parameters ---------- diff --git a/pywindow/trajectory.py b/pywindow/trajectory.py index a5bbbcb..12ff3b8 100644 --- a/pywindow/trajectory.py +++ b/pywindow/trajectory.py @@ -1,4 +1,36 @@ -"""Module intended for the analysis of molecular dynamics trajectories.""" +""" +Module intended for the analysis of molecular dynamics trajectories. + +The trajectory file (DL_POLY_C:HISTORY, PDB or XYZ) should be loaded with +the one of the corresponding classes (DLPOLY, PDB or XYZ, respectively). + +Example +------- +In this example a DL_POLY_C HISTORY trajectory file is loaded. + +.. code-block:: python + + pywindow.trajectory.DLPOLY('path/to/HISTORY') + +Then, each of the trajectory frames can be extracted and returned as a +:class:`pywindow.molecular.MolecularSystem` object for analysis. See +:mod:`pywindow.molecular` docstring for more information. + +Alternatively, the analysis can be performed on a whole or a chunk of +the trajectory with the :func:`analysis()` function. The benefit is +that the analysis can be performed in parallel and the results stored as a +single JSON dictionary in a straightforward way. Also, the deciphering of the +force field atom ids and the rebuilding of molecules can be applied to each +frame in a consitent and automated manner. The downfall is that at the +moment it is not possible to choose the set of parameters that are being +calculated in the :class:`pywindow.molecular.Molecule` as the +:func:`pywindow.molecular.Molecule.full_analysis()` is invoked by default. +However, the computational cost of calculating majority of the structural +properties is miniscule and it is usually the +:func:`pywindow.molecular.MolecularSystem.rebuild_system()` step that is the +bottleneck. + +""" import os import numpy as np from copy import deepcopy @@ -34,12 +66,65 @@ def __init__(self, message): def make_supercell(system, matrix, supercell=[1, 1, 1]): + """ + Return a supercell. + + This functions takes the input unitcell and creates a supercell of it that + is returned as a new :class:`pywindow.molecular.MolecularSystem`. + + Parameters + ---------- + system : :attr:`pywindow.molecular.MolecularSystem.system` + The unit cell for creation of the supercell + + matrix : :class:`numpy.array` + The unit cell parameters in form of a lattice. + + supercell : :class:`list`, optional + A list that specifies the size of the supercell in the a, b and c + direction. (default=[1, 1, 1]) + + Returns + ------- + :class:`pywindow.molecular.MolecularSystem` + Returns the created supercell as a new :class:`MolecularSystem`. + + """ user_supercell = [[1, supercell[0]], [1, supercell[1]], [1, supercell[1]]] system = create_supercell(system, matrix, supercell=user_supercell) return MolecularSystem.load_system(system) class DLPOLY(object): + """ + A container for a DL_POLY_C type trajectory (HISTORY). + + This function takes a DL_POLY_C trajectory file and maps it for the + binary points in the file where each frame starts/ends. This way the + process is fast, as it not require loading the trajectory into computer + memory. When a frame is being extracted, it is only this frame that gets + loaded to the memory. + + Frames can be accessed individually and loaded as an unmodified string, + returned as a :class:`pywindow.molecular.MolecularSystem` (and analysed), + dumped as PDB or XYZ or JSON (if dumped as a + :attr:`pywindow.molecular.MolecularSystem.system`) + + Attributes + ---------- + filepath : :class:`str` + The filepath. + + system_id : :class:`str` + The system id inherited from the filename. + + frames : :class:`dict` + A dictionary that is populated, on the fly, with the extracted frames. + + analysis_output : :class:`dict` + A dictionary that is populated, on the fly, with the analysis output. + + """ def __init__(self, filepath): # Image conventions - periodic boundary key. self._imcon = { @@ -129,7 +214,50 @@ def _decode_head(self, header_coordinates): self.no_of_atoms = header[2] return header - def get_frames(self, frames, override=False, **kwargs): + def get_frames(self, frames='all', override=False, **kwargs): + """ + Extract frames from the trajectory file. + + Depending on the passed parameters a frame, a list of particular + frames, a range of frames (from, to), or all frames can be extracted + with this function. + + Parameters + ---------- + frames : :class:`int` or :class:`list` or :class:`touple` or :class:`str` + Specified frame (:class:`int`), or frames (:class:`list`), or + range (:class:`touple`), or `all`/`everything` (:class:`str`). + (default=`all`) + + override : :class:`bool` + If True, a frame already storred in :attr:`frames` can be override. + (default=False) + + extract_data : :class:`bool`, optional + If False, a frame is returned as a :class:`str` block as in the + trajectory file. Ohterwise, it is extracted and returned as + :class:`pywindow.molecular.MolecularSystem`. (default=True) + + swap_atoms : :class:`dict`, optional + If this kwarg is passed with an appropriate dictionary a + :func:`pywindow.molecular.MolecularSystem.swap_atom_keys()` will + be applied to the extracted frame. + + forcefield : :class:`str`, optional + If this kwarg is passed with appropriate forcefield keyword a + :func:`pywindow.molecular.MolecularSystem.decipher_atom_keys()` + will be applied to the extracted frame. + + Returns + ------- + :class:`pywindow.molecular.MolecularSystem` + If a single frame is extracted. + + None : :class:`NoneType` + If more than one frame is extracted, the frames are returned to + :attr:`frames` + + """ if override is True: self.frames = {} if isinstance(frames, int): @@ -241,7 +369,74 @@ def _decode_frame(self, frame): def analysis( self, frames='all', ncpus=1, _ncpus=1, override=False, **kwargs ): - """ """ + """ + Perform structural analysis on a frame/ set of frames. + + Depending on the passed parameters a frame, a list of particular + frames, a range of frames (from, to), or all frames can be analysed + with this function. + + The analysis is performed on each frame and each discrete molecule in + that frame separately. The steps are as follows: + + 1. A frame is extracted and returned as a :class:`MolecularSystem`. + 2. If `swap_atoms` is set the atom ids are swapped. + 3. If `forcefield` is set the atom ids are deciphered. + 4. If `rebuild` is set the molecules in the system are rebuild. + 5. Each discrete molecule is extracted as :class:`Molecule` + 6. Each molecule is analysed with :func:`Molecule.full_analysis()` + 7. Analysis output populates the :attr:`analysis_output` dictionary. + + As the analysis of trajectories often have to be unique, many options + are conditional. + + A side effect of this function is that the analysed frames are also + returned to the :attr:`frames` mimicking the behaviour of the + :func:`get_frames()`. + + Parameters + ---------- + frames : :class:`int` or :class:`list` or :class:`touple` or :class:`str` + Specified frame (:class:`int`), or frames (:class:`list`), or + range (:class:`touple`), or `all`/`everything` (:class:`str`). + (default='all') + + override : :class:`bool` + If True, an output already storred in :attr:`analysis_output` can + be override. (default=False) + + swap_atoms : :class:`dict`, optional + If this kwarg is passed with an appropriate dictionary a + :func:`pywindow.molecular.MolecularSystem.swap_atom_keys()` will + be applied to the extracted frame. + + forcefield : :class:`str`, optional + If this kwarg is passed with appropriate forcefield keyword a + :func:`pywindow.molecular.MolecularSystem.decipher_atom_keys()` + will be applied to the extracted frame. + + modular : :class:`bool`, optional + If this kwarg is passed a + :func:`pywindow.molecular.MolecularSystem.make_modular()` + will be applied to the extracted frame. (default=False) + + rebuild : :class:`bool`, optional + If this kwarg is passed a `rebuild=True` is passed to + :func:`pywindow.molecular.MolecularSystem.make_modular()` that + will be applied to the extracted frame. (default=False) + + ncpus : :class:`int`, optional + If ncpus > 1, then the analysis is performed in parallel for the + specified number of parallel jobs. Otherwise, it runs in serial. + (default=1) + + Returns + ------- + None : :class:`NoneType` + The function returns `None`, the analysis output is + returned to :attr:`analysis_output` dictionary. + + """ frames_for_analysis = [] # First populate the frames_for_analysis list. if isinstance(frames, int): @@ -476,6 +671,18 @@ def _check_HISTORY(self): raise _TrajectoryError(error) def save_analysis(self, filepath=None, **kwargs): + """ + Dump the content of :attr:`analysis_output` as JSON dictionary. + + Parameters + ---------- + filepath : :class:`str` + The filepath for the JSON file. + + Returns + ------- + None : :class:`NoneType` + """ # We pass a copy of the analysis attribute dictionary. dict_obj = deepcopy(self.analysis_output) # If no filepath is provided we create one. @@ -541,6 +748,38 @@ def save_frames(self, frames, filepath=None, filetype='pdb', **kwargs): class XYZ(object): + """ + A container for an XYZ type trajectory. + + This function takes an XYZ trajectory file and maps it for the + binary points in the file where each frame starts/ends. This way the + process is fast, as it not require loading the trajectory into computer + memory. When a frame is being extracted, it is only this frame that gets + loaded to the memory. + + Frames can be accessed individually and loaded as an unmodified string, + returned as a :class:`pywindow.molecular.MolecularSystem` (and analysed), + dumped as PDB or XYZ or JSON (if dumped as a + :attr:`pywindow.molecular.MolecularSystem.system`) + + Attributes + ---------- + filepath : :class:`str` + The filepath. + + filename : :class:`str` + The filename. + + system_id : :class:`str` + The system id inherited from the filename. + + frames : :class:`dict` + A dictionary that is populated, on the fly, with the extracted frames. + + analysis_output : :class:`dict` + A dictionary that is populated, on the fly, with the analysis output. + + """ def __init__(self, filepath): self.filepath = filepath self.filename = os.path.basename(filepath) @@ -585,7 +824,50 @@ def _map_trajectory(self): progress = progress + len(bline) self.no_of_frames = frame + 1 - def get_frames(self, frames, override=False, **kwargs): + def get_frames(self, frames='all', override=False, **kwargs): + """ + Extract frames from the trajectory file. + + Depending on the passed parameters a frame, a list of particular + frames, a range of frames (from, to), or all frames can be extracted + with this function. + + Parameters + ---------- + frames : :class:`int` or :class:`list` or :class:`touple` or :class:`str` + Specified frame (:class:`int`), or frames (:class:`list`), or + range (:class:`touple`), or `all`/`everything` (:class:`str`). + (default=`all`) + + override : :class:`bool` + If True, a frame already storred in :attr:`frames` can be override. + (default=False) + + extract_data : :class:`bool`, optional + If False, a frame is returned as a :class:`str` block as in the + trajectory file. Ohterwise, it is extracted and returned as + :class:`pywindow.molecular.MolecularSystem`. (default=True) + + swap_atoms : :class:`dict`, optional + If this kwarg is passed with an appropriate dictionary a + :func:`pywindow.molecular.MolecularSystem.swap_atom_keys()` will + be applied to the extracted frame. + + forcefield : :class:`str`, optional + If this kwarg is passed with appropriate forcefield keyword a + :func:`pywindow.molecular.MolecularSystem.decipher_atom_keys()` + will be applied to the extracted frame. + + Returns + ------- + :class:`pywindow.molecular.MolecularSystem` + If a single frame is extracted. + + None : :class:`NoneType` + If more than one frame is extracted, the frames are returned to + :attr:`frames` + + """ if override is True: self.frames = {} if isinstance(frames, int): @@ -659,6 +941,74 @@ def _decode_frame(self, frame): return frame_data def analysis(self, frames='all', ncpus=1, override=False, **kwargs): + """ + Perform structural analysis on a frame/ set of frames. + + Depending on the passed parameters a frame, a list of particular + frames, a range of frames (from, to), or all frames can be analysed + with this function. + + The analysis is performed on each frame and each discrete molecule in + that frame separately. The steps are as follows: + + 1. A frame is extracted and returned as a :class:`MolecularSystem`. + 2. If `swap_atoms` is set the atom ids are swapped. + 3. If `forcefield` is set the atom ids are deciphered. + 4. If `rebuild` is set the molecules in the system are rebuild. + 5. Each discrete molecule is extracted as :class:`Molecule` + 6. Each molecule is analysed with :func:`Molecule.full_analysis()` + 7. Analysis output populates the :attr:`analysis_output` dictionary. + + As the analysis of trajectories often have to be unique, many options + are conditional. + + A side effect of this function is that the analysed frames are also + returned to the :attr:`frames` mimicking the behaviour of the + :func:`get_frames()`. + + Parameters + ---------- + frames : :class:`int` or :class:`list` or :class:`touple` or :class:`str` + Specified frame (:class:`int`), or frames (:class:`list`), or + range (:class:`touple`), or `all`/`everything` (:class:`str`). + (default='all') + + override : :class:`bool` + If True, an output already storred in :attr:`analysis_output` can + be override. (default=False) + + swap_atoms : :class:`dict`, optional + If this kwarg is passed with an appropriate dictionary a + :func:`pywindow.molecular.MolecularSystem.swap_atom_keys()` will + be applied to the extracted frame. + + forcefield : :class:`str`, optional + If this kwarg is passed with appropriate forcefield keyword a + :func:`pywindow.molecular.MolecularSystem.decipher_atom_keys()` + will be applied to the extracted frame. + + modular : :class:`bool`, optional + If this kwarg is passed a + :func:`pywindow.molecular.MolecularSystem.make_modular()` + will be applied to the extracted frame. (default=False) + + rebuild : :class:`bool`, optional + If this kwarg is passed a `rebuild=True` is passed to + :func:`pywindow.molecular.MolecularSystem.make_modular()` that + will be applied to the extracted frame. (default=False) + + ncpus : :class:`int`, optional + If ncpus > 1, then the analysis is performed in parallel for the + specified number of parallel jobs. Otherwise, it runs in serial. + (default=1) + + Returns + ------- + None : :class:`NoneType` + The function returns `None`, the analysis output is + returned to :attr:`analysis_output` dictionary. + + """ if override is True: self.analysis_output = {} if isinstance(frames, int): @@ -791,6 +1141,18 @@ def _analysis_parallel(self, frames, ncpus, **kwargs): raise _ParallelAnalysisError("Parallel analysis failed.") def save_analysis(self, filepath=None, **kwargs): + """ + Dump the content of :attr:`analysis_output` as JSON dictionary. + + Parameters + ---------- + filepath : :class:`str` + The filepath for the JSON file. + + Returns + ------- + None : :class:`NoneType` + """ # We pass a copy of the analysis attribute dictionary. dict_obj = deepcopy(self.analysis_output) # If no filepath is provided we create one. @@ -803,9 +1165,92 @@ def save_analysis(self, filepath=None, **kwargs): Output().dump2json(dict_obj, filepath, default=to_list, **kwargs) return + def save_frames(self, frames, filepath=None, filetype='pdb', **kwargs): + settings = { + "pdb": Output()._save_pdb, + "xyz": Output()._save_xyz, + "decipher": True, + "forcefield": None, + } + settings.update(kwargs) + if filetype.lower() not in settings.keys(): + raise _FormatError("The '{0}' file format is not supported".format( + filetype)) + frames_to_get = [] + if isinstance(frames, int): + frames_to_get.append(frames) + if isinstance(frames, list): + frames_to_get = frames + if isinstance(frames, tuple): + for frame in range(frames[0], frames[1]): + frames_to_get.append(frame) + if isinstance(frames, str): + if frames in ['all', 'everything']: + for frame in range(0, self.no_of_frames): + frames_to_get.append(frame) + for frame in frames_to_get: + if frame not in self.frames.keys(): + _ = self.get_frames(frame) + # If no filepath is provided we create one. + if filepath is None: + filepath = '/'.join((os.getcwd(), str(self.system_id))) + for frame in frames_to_get: + frame_molsys = self.frames[frame] + if settings[ + 'decipher'] is True and settings['forcefield'] is not None: + if "swap_atoms" in settings.keys(): + if isinstance(settings["swap_atoms"], dict): + frame_molsys.swap_atom_keys(settings["swap_atoms"]) + else: + raise _FunctionError( + "The swap_atom_keys function only accepts " + "'swap_atoms' argument in form of a dictionary.") + frame_molsys.decipher_atom_keys(settings["forcefield"]) + ffilepath = '_'.join((filepath, str(frame))) + if 'elements' not in frame_molsys.system.keys(): + raise _FunctionError( + "The frame (MolecularSystem object) needs to have " + "'elements' attribute within the system dictionary. " + "It is, therefore, neccessary that you set a decipher " + "keyword to True. (see manual)") + settings[filetype.lower()](frame_molsys.system, ffilepath, ** + kwargs) + class PDB(object): def __init__(self, filepath): + """ + A container for an PDB type trajectory. + + This function takes an PDB trajectory file and maps it for the + binary points in the file where each frame starts/ends. This way the + process is fast, as it not require loading the trajectory into computer + memory. When a frame is being extracted, it is only this frame that gets + loaded to the memory. + + Frames can be accessed individually and loaded as an unmodified string, + returned as a :class:`pywindow.molecular.MolecularSystem` (and analysed), + dumped as PDB or XYZ or JSON (if dumped as a + :attr:`pywindow.molecular.MolecularSystem.system`) + + Attributes + ---------- + filepath : :class:`str` + The filepath. + + filename : :class:`str` + The filename. + + system_id : :class:`str` + The system id inherited from the filename. + + frames : :class:`dict` + A dictionary that is populated, on the fly, with the extracted frames. + + analysis_output : :class:`dict` + A dictionary that is populated, on the fly, with the analysis output. + + """ self.filepath = filepath self.filename = os.path.basename(filepath) self.system_id = self.filename.split(".")[0] @@ -851,7 +1296,50 @@ def _map_trajectory(self): progress = progress + len(bline) self.no_of_frames = frame - def get_frames(self, frames, override=False, **kwargs): + def get_frames(self, frames='all', override=False, **kwargs): + """ + Extract frames from the trajectory file. + + Depending on the passed parameters a frame, a list of particular + frames, a range of frames (from, to), or all frames can be extracted + with this function. + + Parameters + ---------- + frames : :class:`int` or :class:`list` or :class:`touple` or :class:`str` + Specified frame (:class:`int`), or frames (:class:`list`), or + range (:class:`touple`), or `all`/`everything` (:class:`str`). + (default=`all`) + + override : :class:`bool` + If True, a frame already storred in :attr:`frames` can be override. + (default=False) + + extract_data : :class:`bool`, optional + If False, a frame is returned as a :class:`str` block as in the + trajectory file. Ohterwise, it is extracted and returned as + :class:`pywindow.molecular.MolecularSystem`. (default=True) + + swap_atoms : :class:`dict`, optional + If this kwarg is passed with an appropriate dictionary a + :func:`pywindow.molecular.MolecularSystem.swap_atom_keys()` will + be applied to the extracted frame. + + forcefield : :class:`str`, optional + If this kwarg is passed with appropriate forcefield keyword a + :func:`pywindow.molecular.MolecularSystem.decipher_atom_keys()` + will be applied to the extracted frame. + + Returns + ------- + :class:`pywindow.molecular.MolecularSystem` + If a single frame is extracted. + + None : :class:`NoneType` + If more than one frame is extracted, the frames are returned to + :attr:`frames` + + """ if override is True: self.frames = {} if isinstance(frames, int): @@ -932,6 +1420,74 @@ def _decode_frame(self, frame): return frame_data def analysis(self, frames='all', ncpus=1, override=False, **kwargs): + """ + Perform structural analysis on a frame/ set of frames. + + Depending on the passed parameters a frame, a list of particular + frames, a range of frames (from, to), or all frames can be analysed + with this function. + + The analysis is performed on each frame and each discrete molecule in + that frame separately. The steps are as follows: + + 1. A frame is extracted and returned as a :class:`MolecularSystem`. + 2. If `swap_atoms` is set the atom ids are swapped. + 3. If `forcefield` is set the atom ids are deciphered. + 4. If `rebuild` is set the molecules in the system are rebuild. + 5. Each discrete molecule is extracted as :class:`Molecule` + 6. Each molecule is analysed with :func:`Molecule.full_analysis()` + 7. Analysis output populates the :attr:`analysis_output` dictionary. + + As the analysis of trajectories often have to be unique, many options + are conditional. + + A side effect of this function is that the analysed frames are also + returned to the :attr:`frames` mimicking the behaviour of the + :func:`get_frames()`. + + Parameters + ---------- + frames : :class:`int` or :class:`list` or :class:`touple` or :class:`str` + Specified frame (:class:`int`), or frames (:class:`list`), or + range (:class:`touple`), or `all`/`everything` (:class:`str`). + (default='all') + + override : :class:`bool` + If True, an output already storred in :attr:`analysis_output` can + be override. (default=False) + + swap_atoms : :class:`dict`, optional + If this kwarg is passed with an appropriate dictionary a + :func:`pywindow.molecular.MolecularSystem.swap_atom_keys()` will + be applied to the extracted frame. + + forcefield : :class:`str`, optional + If this kwarg is passed with appropriate forcefield keyword a + :func:`pywindow.molecular.MolecularSystem.decipher_atom_keys()` + will be applied to the extracted frame. + + modular : :class:`bool`, optional + If this kwarg is passed a + :func:`pywindow.molecular.MolecularSystem.make_modular()` + will be applied to the extracted frame. (default=False) + + rebuild : :class:`bool`, optional + If this kwarg is passed a `rebuild=True` is passed to + :func:`pywindow.molecular.MolecularSystem.make_modular()` that + will be applied to the extracted frame. (default=False) + + ncpus : :class:`int`, optional + If ncpus > 1, then the analysis is performed in parallel for the + specified number of parallel jobs. Otherwise, it runs in serial. + (default=1) + + Returns + ------- + None : :class:`NoneType` + The function returns `None`, the analysis output is + returned to :attr:`analysis_output` dictionary. + + """ if override is True: self.analysis_output = {} if isinstance(frames, int): @@ -1064,6 +1620,18 @@ def _analysis_parallel(self, frames, ncpus, **kwargs): raise _ParallelAnalysisError("Parallel analysis failed.") def save_analysis(self, filepath=None, **kwargs): + """ + Dump the content of :attr:`analysis_output` as JSON dictionary. + + Parameters + ---------- + filepath : :class:`str` + The filepath for the JSON file. + + Returns + ------- + None : :class:`NoneType` + """ # We pass a copy of the analysis attribute dictionary. dict_obj = deepcopy(self.analysis_output) # If no filepath is provided we create one. @@ -1075,3 +1643,54 @@ def save_analysis(self, filepath=None, **kwargs): # Dump the dictionary to json file. Output().dump2json(dict_obj, filepath, default=to_list, **kwargs) return + + def save_frames(self, frames, filepath=None, filetype='pdb', **kwargs): + settings = { + "pdb": Output()._save_pdb, + "xyz": Output()._save_xyz, + "decipher": True, + "forcefield": None, + } + settings.update(kwargs) + if filetype.lower() not in settings.keys(): + raise _FormatError("The '{0}' file format is not supported".format( + filetype)) + frames_to_get = [] + if isinstance(frames, int): + frames_to_get.append(frames) + if isinstance(frames, list): + frames_to_get = frames + if isinstance(frames, tuple): + for frame in range(frames[0], frames[1]): + frames_to_get.append(frame) + if isinstance(frames, str): + if frames in ['all', 'everything']: + for frame in range(0, self.no_of_frames): + frames_to_get.append(frame) + for frame in frames_to_get: + if frame not in self.frames.keys(): + _ = self.get_frames(frame) + # If no filepath is provided we create one. + if filepath is None: + filepath = '/'.join((os.getcwd(), str(self.system_id))) + for frame in frames_to_get: + frame_molsys = self.frames[frame] + if settings[ + 'decipher'] is True and settings['forcefield'] is not None: + if "swap_atoms" in settings.keys(): + if isinstance(settings["swap_atoms"], dict): + frame_molsys.swap_atom_keys(settings["swap_atoms"]) + else: + raise _FunctionError( + "The swap_atom_keys function only accepts " + "'swap_atoms' argument in form of a dictionary.") + frame_molsys.decipher_atom_keys(settings["forcefield"]) + ffilepath = '_'.join((filepath, str(frame))) + if 'elements' not in frame_molsys.system.keys(): + raise _FunctionError( + "The frame (MolecularSystem object) needs to have " + "'elements' attribute within the system dictionary. " + "It is, therefore, neccessary that you set a decipher " + "keyword to True. (see manual)") + settings[filetype.lower()](frame_molsys.system, ffilepath, ** + kwargs)