Commit aa87f555 authored by eric pellegrini's avatar eric pellegrini
Browse files

repopulate MDANSE

parent 98d3a13b
'''
MDANSE : Molecular Dynamics Analysis for Neutron Scattering Experiments
------------------------------------------------------------------------------------------
Copyright (C)
2015- Eric C. Pellegrini Institut Laue-Langevin
BP 156
6, rue Jules Horowitz
38042 Grenoble Cedex 9
France
pellegrini[at]ill.fr
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Created on Mar 23, 2015
@author: pellegrini
'''
import abc
import os
import re
import StringIO
import tarfile
import numpy
from MDANSE.Core.Error import Error
from MDANSE.Core.ClassRegistry import ClassRegistry
from MDANSE.Externals.svgfig.svgfig import _hacks, Frame, Poly
_hacks["inkscape-text-vertical-shift"] = True
class FormatError(Error):
pass
def format_unit_string(unitString):
return re.sub('[%()]','',unitString)
class Format(object):
'''
This is the base class for nmoldyn data.
'''
__metaclass__ = ClassRegistry
type = "format"
@abc.abstractmethod
def write(self, filename, data, header=""):
pass
class ASCIIFormat(Format):
type = 'ascii'
extension = ".dat"
extensions = ['.dat','.txt']
def write(self, filename, data, header=""):
filename = os.path.splitext(filename)[0]
filename = "%s_%s.tar" % (filename,self.type)
tf = tarfile.open(filename,'w')
for var in data.values():
tempStr = StringIO.StringIO()
if header:
tempStr.write(header)
tempStr.write('\n\n')
tempStr.write(var.info())
tempStr.write('\n\n')
self.write_array(tempStr,var)
tempStr.seek(0)
info = tarfile.TarInfo(name='%s%s' % (var.name,self.extensions[0]))
info.size=tempStr.len
tf.addfile(tarinfo=info, fileobj=tempStr)
tf.close()
def write_array(self, fileobject, array, slices=None):
if slices is None:
slices = [0]*array.ndim
slices[-2:] = array.shape[-2:]
if array.ndim > 2:
for a in array:
self.write_array(fileobject,a, slices)
slices[len(slices)-array.ndim] = slices[len(slices)-array.ndim] + 1
else:
fileobject.write('#slice:%s\n' % slices)
numpy.savetxt(fileobject, array)
fileobject.write('\n')
class NetCDFFormat(Format):
type = 'netcdf'
extension = ".nc"
extensions = ['.nc','.cdf','.netcdf']
def write(self, filename, data, header=""):
'''
This method writes (or append) a list of nMOLDYN.Job.Output.OutputVariable objects to a NetCDF file.
@param filename: the path for the output NetCDF file.
@type filename: string
'''
filename = os.path.splitext(filename)[0]
filename = "%s%s" % (filename,self.extensions[0])
# Import the NetCDFFile function.
from Scientific.IO.NetCDF import NetCDFFile
# The NetCDF output file is opened for writing.
outputFile = NetCDFFile(filename, 'w')
if header:
outputFile.header = header
# Loop over the OutputVariable instances to write.
for var in data.values():
varName = str(var.name).strip().encode('string-escape').replace('/', '|')
# The NetCDF dimensions are created for all the dimensions of the OutputVariable instance.
dimensions = []
for i,v in enumerate(var.shape):
name = str("%s_%d" % (varName,i))
dimensions.append(name)
outputFile.createDimension(name, int(v))
# A NetCDF variable instance is created for the running OutputVariable instance.
NETCDFVAR = outputFile.createVariable(varName, numpy.dtype(var.dtype).char, tuple(dimensions))
# The array stored in the OutputVariable instance is written to the NetCDF file.
NETCDFVAR.assignValue(var)
# All the attributes stored in the OutputVariable instance are written to the NetCDF file.
for k, v in vars(var).items():
setattr(NETCDFVAR,str(k),str(v))
# The NetCDF file is closed.
outputFile.close()
class SVGFormat(Format):
type = 'svg'
extension = ".svg"
extensions = ['.svg']
def write(self,filename,data, header=""):
filename = os.path.splitext(filename)[0]
filename = "%s_%s.tar" % (filename,self.name)
tf = tarfile.open(filename,'w')
for var in data.values():
if var.ndim != 1:
continue
if var.axis in data:
axis = data[var.axis]
xtitle = "%s (%s)" % (axis.name,format_unit_string(axis.units))
else:
axis = numpy.arange(len(var))
xtitle = 'index'
ytitle = "%s (%s)" % (var.name,format_unit_string(var.units))
pl = Poly(zip(axis,var),stroke='blue')
svgfilename = os.path.join(os.path.dirname(filename),'%s%s' % (var.name,self.extensions[0]))
Frame(min(axis),max(axis),min(var),max(var),pl,xtitle=xtitle,ytitle=ytitle).SVG().save(svgfilename)
tf.add(svgfilename, arcname='%s%s' % (var.name,self.extensions[0]))
os.remove(svgfilename)
tf.close()
'''
MDANSE : Molecular Dynamics Analysis for Neutron Scattering Experiments
------------------------------------------------------------------------------------------
Copyright (C)
2015- Eric C. Pellegrini Institut Laue-Langevin
BP 156
6, rue Jules Horowitz
38042 Grenoble Cedex 9
France
pellegrini[at]ill.fr
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Created on Mar 23, 2015
@author: pellegrini
'''
import abc
import os
import collections
import numpy
from Scientific.IO.NetCDF import NetCDFFile
from MDANSE.Core.ClassRegistry import ClassRegistry
from MDANSE.Core.Error import Error
from nMOLDYN.Utilities.MolecularDynamics import get_chemical_objects_number, get_chemical_objects_size, MMTKTrajectory
class InputDataError(Error):
pass
class InputData(object):
__metaclass__ = ClassRegistry
def __init__(self, *args, **kwargs):
self._data = None
self._filename = None
@property
def filename(self):
return self._filename
@property
def basename(self):
return self._basename
@property
def data(self):
return self._data
def info(self):
return "No information available"
class EmptyData(InputData):
type = "empty_data"
extension = None
count = 0
def __init__(self, filename, *args, **kwargs):
InputData.__init__(self, filename, *args, **kwargs)
self._data = None
if filename is None:
self._filename = self._basename = 'empty_' + str(EmptyData.count)
EmptyData.count += 1
else:
self._filename = self._basename = filename
class InputFileData(InputData):
def __init__(self, filename, *args, **kwargs):
super(InputFileData, self).__init__()
self._filename = filename
self._dirname = os.path.dirname(self._filename)
self._basename = os.path.basename(self._filename)
self._data = None
self.load()
@property
def dirname(self):
return self._dirname
@abc.abstractmethod
def load(self):
pass
@abc.abstractmethod
def close(self):
pass
class MMTKTrajectoryInputData(InputFileData):
type = "mmtk_trajectory"
extension = "nc"
def load(self):
try:
traj = MMTKTrajectory(None, self._filename, "r")
except IOError:
raise InputDataError("The MMTK trajectory %r could not be loaded property." % self._filename)
self._data = traj
def close(self):
self._data.close()
def info(self):
val = []
val.append("Path:")
val.append("%s\n" % self._filename)
val.append("Number of steps:")
val.append("%s\n" % len(self._data))
val.append("Universe:")
val.append("%s\n" % self._data.universe)
if self._data.universe.is_periodic:
val.append("Direct cell:")
val.append("%s\n" % str(numpy.round(self._data.universe.basisVectors(),4)))
val.append("Reciprocal cell:")
val.append("%s\n" % str(numpy.round(self._data.universe.reciprocalBasisVectors(),4)))
val.append("Molecular types found:")
molSize = get_chemical_objects_size(self._data.universe)
molNumber = get_chemical_objects_number(self._data.universe)
for k,v in molSize.items():
val.append('\t- %d molecule(s) of %s (%d atoms)' % (molNumber[k],k,v))
val.append('\n')
val = "\n".join(val)
return val
@property
def trajectory(self):
return self._data
@property
def universe(self):
return self._data.universe
class NetCDFInputData(InputFileData):
type = "netcdf_data"
extension = "nc"
def load(self):
try:
self._netcdf = NetCDFFile(self._filename,"r")
except IOError:
raise InputDataError("The data stored in %r filename could not be loaded property." % self._filename)
else:
self._data = collections.OrderedDict()
variables = self._netcdf.variables
for k in variables:
self._data[k]={}
try :
if vars[k].axis:
self._data[k]['axis'] = variables[k].axis.split('|')
else:
self._data[k]['axis'] = []
except:
self._data[k]['axis'] = []
self._data[k]['data'] = variables[k].getValue()
self._data[k]['units'] = getattr(variables[k], 'units', 'au')
def close(self):
self._netcdf.close()
@property
def netcdf(self):
return self._netcdf
class MviTraceInputData(InputFileData):
type = "mvi_trace"
extension = "mvi"
def load(self):
pass
def close(self):
pass
class PeriodicTableData(InputData):
type = "periodic_table"
extension = None
def load(self):
pass
def close(self):
pass
\ No newline at end of file
'''
MDANSE : Molecular Dynamics Analysis for Neutron Scattering Experiments
------------------------------------------------------------------------------------------
Copyright (C)
2015- Eric C. Pellegrini Institut Laue-Langevin
BP 156
6, rue Jules Horowitz
38042 Grenoble Cedex 9
France
pellegrini[at]ill.fr
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Created on Mar 23, 2015
@author: pellegrini
'''
import collections
import numpy
from nMOLDYN import REGISTRY
from nMOLDYN.Core.Error import Error
from nMOLDYN.Framework.ExtendableObject import ExtendableObject
class OutputVariableError(Error):
pass
class OutputData(collections.OrderedDict):
def add(self, dataName, dataType, data, **kwargs):
self[dataName] = REGISTRY["outputvariable"](dataType, data, dataName, **kwargs)
def write(self, basename, formats, header=None):
for fmt in formats:
REGISTRY["format"](fmt).write(basename, self, header)
class OutputVariable(numpy.ndarray):
'''
Defines a nmoldyn output variable.
A nmoldyn output variable is defined as s subclass of Numpy array that stores additional attributes.
Those extra attributes will be contain information necessary for the the nmoldyn plotter.
'''
__metaclass__ = ExtendableObject
def __new__(cls, value, name, axis=(), units="unitless"):
'''
Instanciate a new nmoldyn output variable.
@param cls: the class to instantiate.
@type cls: an OutputVariable object
@param name: the name of the output variable.
@type name: string
@param value: the input numpy array.
@type value: numpy array
@note: This is the standard implementation for subclassing a numpy array.
Please look at http://docs.scipy.org/doc/numpy/user/basics.subclassing.html for more information.
'''
if isinstance(value, tuple):
value = numpy.zeros(value)
value = numpy.array(value, dtype=numpy.float64)
if value.ndim != cls._nDimensions:
raise OutputVariableError("Invalid number of dimensions for an output variable of type %r" % cls.name)
# Input array is an already formed ndarray instance
# We first cast to be our class type
obj = numpy.asarray(value).view(cls)
# The name of the output variable.
obj.name = name
obj.units = units
obj.axis = axis
return obj
def __array_finalize__(self, obj):
if obj is None:
return
self.name = getattr(obj, 'name', None)
self.axis = getattr(obj, 'axis',())
self.units = getattr(obj, 'units','unitless')
def __array_wrap__(self, out_arr, context=None):
return numpy.ndarray.__array_wrap__(self, out_arr, context)
def info(self):
info = []
info.append("# variable name: %s" % self.name)
info.append("# \ttype: %s" % self.type)
info.append("# \taxis: %s" % str(self.axis))
info.append("# \tunits: %s" % self.units)
info = "\n".join(info)
return info
class LineOutputVariable(OutputVariable):
type = "line"
_nDimensions = 1
class SurfaceOutputVariable(OutputVariable):
type = "surface"
_nDimensions = 2
class VolumeOutputVariable(OutputVariable):
type = "volume"
_nDimensions = 3
# The standard imports.
import abc
import ast
import collections
import operator
import os
import re
import subprocess
import time
# The numpy imports.
import numpy