Commit 59b6b410 authored by Berk Onat's avatar Berk Onat

Initial code for upper-level python interface.

parent 77a9bcec
......@@ -2,8 +2,9 @@ LICENSE for pymolfile
---------------------
All files of pymolfile except the files under vmd_molfile_plugins directory
which are licensed below after "LICENSE for VMD molfile_plugins" is licensed under
with the following UIUC Open Source License:
which are licensed below with "LICENSE for VMD molfile_plugins" are
licensed under the following UIUC Open Source License:
-----------------------------------------------------------------------------
University of Illinois Open Source License
......
from __future__ import absolute_import
from __future__ import print_function
import os
import re
import sys
import numpy as np
import warnings
if sys.version_info > (3,):
long = int
try:
from .molfile import libpymolfile
except ImportError:
warnings.warn("libpymolfile package not available, pymolfile does not work without its library!")
def plugins():
""" Information on the available molfile plugins
Example tuple: ('psf', 'psf', 1, 1, 1, 0, 1, 1, 1, 0,
'CHARMM,NAMD,XPLOR PSF', 'mol file reader',
'Justin Gullingsrud, John Stone', 1, 9, 17, 1)
The fields in the tuple represent info in ordered as follows:
1: format extension
2: format name
3: read_structure is avaliable if 1
4: read_bonds is avaliable if 1
5: read_angles is avaliable if 1
6: read_next_timestep is avaliable if 1
7: write_structure is avaliable if 1
8: write_bonds is avaliable if 1
9: write_angles is avaliable if 1
10: write_timestep is avaliable if 1
11: long name of the plugin
12: type of plugin
13: authors of the plugin
14: major version of the plugin
15: minor version of the plugin
16: ABI version of the plugin
17: 1 if is reentrant (returns is_reentrant)
Returns: A list of tuples that includes the information and
capabilities of each molfile plugin. The information is
extracted from molfile_plugin_t.
"""
max_num_plugins = 200
c_list = libpymolfile.molfile_plugin_list(max_num_plugins)
numlist = libpymolfile.molfile_init()
plugins_list = [libpymolfile.molfile_plugin_info(c_list, i) for i in range(numlist)]
libpymolfile.molfile_finish()
return plugins_list
def open(file_name_with_path, topology=None,
file_format=None, topology_format=None,
plugin=None, topology_plugin=None):
""" The main function to read topology and
trajectory files
Returns: Depends on the file format and arguments:
If structure file is supplied, it returns topology class.
If only trajectory file is supplied, it returns trajectory class
without topology information. (the number of atoms must be known)
If both files are supplied, it returns trajectory class with
topology information.
"""
pass
def get_dir_base_extension(file_name):
""" Splits directory, file base and file extensions
Returns: directory without leading '/',
file base name, and file extension without '.'
"""
file_base, file_extension_with_dot = os.path.splitext(os.path.basename(file_name))
file_extension = file_extension_with_dot.split(".")[-1]
file_dir = os.path.dirname(file_name)
return file_dir, file_base, file_extension
def get_extension(file_name):
""" Gets file extension of a file
Returns: file extension without '.'
"""
file_extension_with_dot = os.path.splitext(os.path.basename(file_name))[1]
return file_extension_with_dot.split(".")[-1]
def get_plugin_with_ext(file_ext):
""" Search molfile plugins list and returns the plugin info
for the first matched extension.
Returns: Plugin no in the list and the list item (the plugin info tuple)
"""
if not MOLFILE_PLUGINS:
MOLFILE_PLUGINS = plugins()
if MOLFILE_PLUGINS:
plugin_no = -1
for plugin_info in MOLFILE_PLUGINS:
plugin_no += 1
if file_ext == plugin_info[1]:
return (plugin_no, plugin_info)
return None
def get_plugin_with_name(plugin_name):
""" Search molfile plugins list and returns the plugin info
for the first matching name in plugin name field.
Returns: Plugin no in the list and the list item (the plugin info tuple)
"""
if not MOLFILE_PLUGINS:
MOLFILE_PLUGINS = plugins()
if MOLFILE_PLUGINS:
plugin_no = -1
for plugin_info in MOLFILE_PLUGINS:
plugin_no += 1
if plugin_name == plugin_info[2]:
return (plugin_no, plugin_info)
return None
class OpenMolfile(object):
self.plugin_list = MOLFILE_PLUGINS
self.trajectory = None
self.topology = None
self.smolobject = None
self.cmolobject = None
self.kwords = {
"file_format" : None,
"file_plugin" : None,
"topology" : None,
"topology_format" : None,
"topology_plugin" : None,
"natoms" : None
}
def __init__(self, file_name, **kwargs):
if kwargs:
for k, v in kwargs.items():
if k in self.kwords:
self.kwords[k] = v
if file_name:
if self.kwords["file_format"] is None:
file_dir, file_base, file_ext = get_dir_base_extension(file_name)
if file_ext:
self.kwords["file_format"] = file_ext
else:
self.kwords["file_format"] = file_base
if self.kwords["file_plugin"] is None:
self.kwords["file_plugin"] = "auto"
if "auto" in self.kwords["file_plugin"]:
plugin_item = get_plugin_with_ext(self.kwords["file_format"])
self.kwords["file_plugin"] =
if self.kwords["file_plugin"]:
if not MOLFILE_PLUGINS:
MOLFILE_PLUGINS = plugins()
c_list = libpymolfile.molfile_plugin_list(max_num_plugins)
numlist = libpymolfile.molfile_init()
self.cmolobject = libpymolfile.get_plugin(MOLFILE_PLUGINS, 83) #trr
else:
return None
def get_listof_parts( filename, filepath, fileformats ):
pattern = re.escape( filename[1:-4] ) + "\.part[0-9]{4,4}\.(xtc|trr)$"
parts = []
for f in os.listdir( directory ):
m = re.match( pattern, f )
if m and os.path.isfile( os.path.join( directory, f ) ):
parts.append( os.path.join( directory, f ) )
return sorted( parts )
def get_trajectory( file_name ):
ext = os.path.splitext( file_name )[1].lower()
types = {
".xtc": XtcTrajectory,
".trr": TrrTrajectory,
".netcdf": NetcdfTrajectory,
".nc": NetcdfTrajectory,
".dcd": DcdTrajectory,
}
if ext in types:
return types[ ext ]( file_name )
else:
raise Exception( "extension '%s' not supported" % ext )
class Topology( object ):
self.structure = None
self.bonds = None
self.angles = None
def __init__( self, file_name ):
pass
class Trajectory( object ):
def __init__( self, file_name ):
pass
def update( self, force=False ):
pass
def _get_frame( self, index ):
pass
def get_frame( self, index, atom_indices=None ):
box, coords, time = self._get_frame( int( index ) )
if atom_indices:
coords = np.concatenate([
])
return {
"coords": coords
"velocities": coords
}
def get_frame_string( self, index, atom_indices=None ):
frame = self.get_frame( index, atom_indices=atom_indices )
return (
)
def __del__( self ):
pass
......@@ -3,7 +3,7 @@
* molfile.c : C and Fortran interfaces for molfile_plugins
* Copyright (c) Berk Onat <b.onat@warwick.ac.uk> 2017
*
* This program is under BSD LICENSE
* This program is under UIUC LICENSE
*/
/*
......@@ -31,8 +31,8 @@ extern "C"
#include <numpy/arrayobject.h>
enum { pluginOK, pluginNOINIT, pluginCLOSE, pluginNOMEM,
pluginENDOFFILE, pluginFILENOTFOUND, pluginFORMATERROR };
//enum { pluginOK, pluginNOINIT, pluginCLOSE, pluginNOMEM,
// pluginENDOFFILE, pluginFILENOTFOUND, pluginFORMATERROR };
#ifndef MAXPLUGINS
#define MAXPLUGINS 200
......
This diff is collapsed.
......@@ -67,11 +67,20 @@ def open(file_name_with_path, topology=None,
If both files are supplied, it returns trajectory class with
topology information.
"""
if MOLFILE_PLUGINS
pass
def get_dir_base_extension(file_name):
""" Splits directory, file base and file extensions
Returns: directory without leading '/',
file base name, and file extension without '.'
"""
file_base, file_extension_with_dot = os.path.splitext(os.path.basename(file_name))
file_extension = file_extension_with_dot.split(".")[-1]
file_dir = os.path.dirname(file_name)
return file_dir, file_base, file_extension
def get_listof_parts_xtc_trr( filename, filepath ):
def get_listof_parts( filename, filepath, fileformats ):
pattern = re.escape( filename[1:-4] ) + "\.part[0-9]{4,4}\.(xtc|trr)$"
parts = []
for f in os.listdir( directory ):
......@@ -80,78 +89,159 @@ def get_listof_parts_xtc_trr( filename, filepath ):
parts.append( os.path.join( directory, f ) )
return sorted( parts )
def get_extension(file_name):
""" Gets file extension of a file
Returns: file extension without '.'
"""
file_extension_with_dot = os.path.splitext(os.path.basename(file_name))[1]
return file_extension_with_dot.split(".")[-1]
def get_plugin_with_ext(file_ext):
""" Search molfile plugins list and returns the plugin info
for the first matching extension.
Returns: Plugin no in the list and the list item (the plugin info tuple)
"""
if not MOLFILE_PLUGINS:
MOLFILE_PLUGINS = plugins()
if MOLFILE_PLUGINS:
plugin_no = -1
for plugin_info in MOLFILE_PLUGINS:
plugin_no += 1
if file_ext == plugin_info[1]:
return (plugin_no, plugin_info)
return None
def get_plugin_with_name(plugin_name):
""" Search molfile plugins list and returns the plugin info
for the first matching name in plugin name field.
Returns: Plugin no in the list and the list item (the plugin info tuple)
"""
if not MOLFILE_PLUGINS:
MOLFILE_PLUGINS = plugins()
if MOLFILE_PLUGINS:
plugin_no = -1
for plugin_info in MOLFILE_PLUGINS:
plugin_no += 1
if plugin_name == plugin_info[2]:
return (plugin_no, plugin_info)
def get_trajectory( file_name ):
ext = os.path.splitext( file_name )[1].lower()
types = {
".xtc": XtcTrajectory,
".trr": TrrTrajectory,
".netcdf": NetcdfTrajectory,
".nc": NetcdfTrajectory,
".dcd": DcdTrajectory,
}
if ext in types:
return types[ ext ]( file_name )
else:
raise Exception( "extension '%s' not supported" % ext )
return None
class Topology( object ):
def __init__( self, file_name ):
self.structure = None
self.bonds = None
self.angles = None
def __init__(self):
pass
class Trajectory( object ):
def __init__( self, file_name ):
pass
self.atoms = None
def update( self, force=False ):
def __init__(self):
pass
def _get_frame( self, index ):
# return box, coords, time
# box, coords in angstrom
# time in ???
def get_frame(self, index):
def iread(self, chunk=None):
def read(self, index, chunk=None):
def __del__(self):
pass
def get_frame( self, index, atom_indices=None ):
box, coords, time = self._get_frame( int( index ) )
if atom_indices:
coords = np.concatenate([
coords[ i:j ].ravel() for i, j in atom_indices
])
return {
"numframes": self.numframes,
"time": time,
"box": box,
"coords": coords
class Molfile(object):
self.plugin_list = MOLFILE_PLUGINS
self.trajectory = None
self.topology = None
self.fplugin = None
self.tplugin = None
self.fmolobject = None
self.tmolobject = None
self.kwords = {
"file_format" : None,
"file_plugin" : None,
"topology" : None,
"topology_format" : None,
"topology_plugin" : None,
"natoms" : None
}
def get_frame_string( self, index, atom_indices=None ):
frame = self.get_frame( index, atom_indices=atom_indices )
return (
array.array( "i", [ frame[ "numframes" ] ] ).tostring() +
array.array( "f", [ frame[ "time" ] ] ).tostring() +
array.array( "f", frame[ "box" ].flatten() ).tostring() +
array.array( "f", frame[ "coords" ].flatten() ).tostring()
)
def get_path( self, atom_index, frame_indices=None ):
if( frame_indices ):
size = len( frame_indices )
frames = map( int, frame_indices )
else:
size = self.numframes
frames = range( size )
path = np.zeros( ( size, 3 ), dtype=np.float32 )
for i in frames:
box, coords, time = self._get_frame( i )
path[ i ] = coords[ atom_index ]
return path
def get_path_string( self, atom_index, frame_indices=None ):
path = self.get_path( atom_index, frame_indices=frame_indices )
return array.array( "f", path.flatten() ).tostring()
def __init__(self, file_name, **kwargs):
pass
def __del__( self ):
pass
class OpenMolfile(Molfile):
def __init__(self, file_name, **kwargs):
if kwargs:
for k, v in kwargs.items():
if k in self.kwords:
self.kwords[k] = v
if file_name:
if self.kwords["file_format"] is None:
file_dir, file_base, file_ext = get_dir_base_extension(file_name)
if file_ext:
self.kwords["file_format"] = file_ext
else:
self.kwords["file_format"] = file_base
if self.kwords["file_plugin"] is None:
self.kwords["file_plugin"] = "auto"
if "auto" in self.kwords["file_plugin"]:
plugin_item = get_plugin_with_ext(self.kwords["file_format"])
if plugin_item:
self.fplugin = plugin_item
self.kwords["file_plugin"] = plugin_item[2][2]
if self.kwords["file_plugin"]:
# Check if file_plugin reads structure info
# for the given file format.
if self.fplugin[2][3] == 1:
# Topology may be read with the plugin.
# This will override topology information
# if a 'topology' is supplied in keywords.
else:
# Topology can not be read with plugin from
# the file. If 'topology' is not set but 'natoms'
# is only the trajectory will be available.
c_list = libpymolfile.molfile_plugin_list(max_num_plugins)
numlist = libpymolfile.molfile_init()
self.cmolobject = libpymolfile.get_plugin(MOLFILE_PLUGINS, 83) #trr
return self
else:
return None
import numpy
import libpymolfile as pym
import molfile.libpymolfile as pym
mylist = pym.molfile_plugin_list(200)
numlist = pym.molfile_init()
......@@ -9,8 +9,8 @@ for i in range(numlist):
print(i, testplugin)
#splugin = pym.get_plugin(mylist, 99) #pdb
#cplugin = pym.get_plugin(mylist, 83) #trr
cplugin = pym.get_plugin(mylist, 85) #xtc
cplugin = pym.get_plugin(mylist, 83) #trr
#cplugin = pym.get_plugin(mylist, 85) #xtc
#splugin = pym.get_plugin(mylist, 105) #psf
splugin = pym.get_plugin(mylist, 81) #gro
#cplugin = pym.get_plugin(mylist, 69) #dcd
......@@ -18,23 +18,23 @@ splugin = pym.get_plugin(mylist, 81) #gro
print(splugin)
print(cplugin)
natoms=0
#sfname="../../test/DPDP.pdb"
#cfname="../../test/DPDP.nc"
#sfname="../test/DPDP.pdb"
#cfname="../test/DPDP.nc"
#sfname="../../test/ala3.pdb"
#sfname="../../test/ala3.psf"
#cfname="../../test/ala3.dcd"
#sfname="../test/ala3.pdb"
#sfname="../test/ala3.psf"
#cfname="../test/ala3.dcd"
sfname="../../test/md.gro"
#cfname="../../test/md.trr"
cfname="../../test/md.xtc"
sfname="../test/md.gro"
cfname="../test/md.trr"
#cfname="../test/md.xtc"
#sfname="../../test/md_1u19.gro"
#cfname="../../test/md_1u19.xtc"
#sfname="../test/md_1u19.gro"
#cfname="../test/md_1u19.xtc"
#sftype="pdb"
#cftype="trr"
cftype="xtc"
cftype="trr"
#cftype="xtc"
#sftype="psf"
sftype="gro"
#cftype="dcd"
......@@ -56,13 +56,30 @@ if pym.is_plugin_same(spluginhandle, cpluginhandle):
pym.close_file_read(cpluginhandle)
cpluginhandle = spluginhandle
#if 0 && vmdplugin_ABIVERSION > 17
# /* The new PDB file formats allows for much larger structures, */
# /* which can therefore require longer chain ID strings. The */
# /* new PDBx/mmCIF file formats do not have length limits on */
# /* fields, so PDB chains could be arbitrarily long strings */
# /* in such files. At present, we know we need at least 3-char */
# /* chains for existing PDBx/mmCIF files. */
# char chain[4]; /**< required chain name, or "" */
#else
# char chain[2]; /**< required chain name, or "" */
#endif
# Change 'chain', 'S4' to S2 for PDB
if 'pdb' in [sftype, cftype]:
print("file chain is set to S2")
chain_size = 'S2'
else:
chain_size = 'S4'
x = numpy.array([
('C1','C','ACE',0,'','','','',1.0,1.0,1.0,1.0,1.0,6),
('C2','C','ACE',0,'','','','',1.0,1.0,1.0,1.0,1.0,6)
],
dtype=[
('name', 'S16'), ('type', 'S16'), ('resname', 'S8'),
('resid', 'i4'), ('segid', 'S8'), ('chain', 'S2'),
('resid', 'i4'), ('segid', 'S8'), ('chain', chain_size),
('altloc', 'S2'), ('insertion', 'S2'), ('occupancy', 'f4'),
('bfactor', 'f4'), ('mass', 'f4'), ('charge', 'f4'),
('radius', 'f4'), ('atomicnumber', 'i4')
......@@ -94,19 +111,19 @@ if pym.is_plugin_same(spluginhandle, cpluginhandle):
else:
pym.close_file_read(spluginhandle)
step=0
while True:
try:
c = pym.read_fill_next_timestep(cpluginhandle)
if c is None:
break
step=step+1
print("Step:",step)
print(c)
if c["coords"] is not None:
print(len(c["coords"]))
except (AttributeError,OSError):
pass
#step=0
#while True:
# try:
# c = pym.read_fill_next_timestep(cpluginhandle)
# if c is None:
# break
# step=step+1
# print("Step:",step)
# print(c)
# if c["coords"] is not None:
# print(len(c["coords"]))
# except (AttributeError,OSError):
# pass
pym.close_file_read(cpluginhandle)
pym.molfile_finish()
......
[metadata]
description-file = README.md
\ No newline at end of file
description-file = README.md
......@@ -95,7 +95,7 @@ if __name__ == '__main__':
name = "pymolfile",
author = "Berk Onat",
author_email = "b.onat@warwick.ac.uk",
description = "Python interface for VMD molfile plugins.",
description = "Not just a Python interface for VMD molfile plugins.",
version = VERSION,
classifiers = CLASSIFIERS,
license = "UIUC",
......