diff --git a/AUTHORS b/AUTHORS index 3e1a3ac..550c6d4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -15,4 +15,5 @@ Contributors: * Max Linke * Jan Domanski * Dominik Mierzejewski -* Tyler Luchko \ No newline at end of file +* Tyler Luchko +* Giacomo Fiorin diff --git a/CHANGELOG b/CHANGELOG index 2c8d602..852036e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,15 @@ The rules for this file: * accompany each entry with github issue/PR number (Issue #xyz) ------------------------------------------------------------------------------ +??/??/2019 giacomofiorin + + * 0.5.0 + + Fixes + + * Allow parsing DX files by NAMD's GridForces module (typequote keyword, #58) + * Allow parsing DX files by Pymol's buggy floating-point parser (#58) + 04/06/2019 rathann, tluchko, orbeckst * 0.4.1 diff --git a/gridData/OpenDX.py b/gridData/OpenDX.py index da18ec6..2390fa5 100644 --- a/gridData/OpenDX.py +++ b/gridData/OpenDX.py @@ -301,7 +301,8 @@ class array(DXclass): # "string" not automatically supported } - def __init__(self, classid, array=None, type=None, **kwargs): + def __init__(self, classid, array=None, type=None, typequote='"', + **kwargs): """ Parameters ---------- @@ -347,6 +348,7 @@ def __init__(self, classid, array=None, type=None, **kwargs): "types are: {1}".format(type, list(self.dx_types.values())))) self.type = type + self.typequote = typequote def write(self, file): """Write the *class array* section. @@ -367,18 +369,23 @@ def write(self, file): "Supported valus are: {}\n" "Use the type= keyword argument.").format( self.type, list(self.dx_types.keys()))) + typelabel = (self.typequote+self.type+self.typequote) DXclass.write(self,file, - 'type "{0}" rank 0 items {1} data follows'.format( - self.type, self.array.size)) + 'type {0} rank 0 items {1} data follows'.format( + typelabel, self.array.size)) # grid data, serialized as a C array (z fastest varying) # (flat iterator is equivalent to: for x: for y: for z: grid[x,y,z]) # VMD's DX reader requires exactly 3 values per line + fmt_string = "{:d}" + if (self.array.dtype.kind == 'f' or self.array.dtype.kind == 'c'): + precision = numpy.finfo(self.array.dtype).precision + fmt_string = "{:."+"{:d}".format(precision)+"f}" values_per_line = 3 values = self.array.flat while 1: try: for i in range(values_per_line): - file.write(str(next(values)) + "\t") + file.write(fmt_string.format(next(values)) + "\t") file.write('\n') except StopIteration: file.write('\n') diff --git a/gridData/core.py b/gridData/core.py index 1425ef2..5be5819 100644 --- a/gridData/core.py +++ b/gridData/core.py @@ -407,7 +407,7 @@ def _load_plt(self, filename): grid, edges = g.histogramdd() self.__init__(grid=grid, edges=edges, metadata=self.metadata) - def export(self, filename, file_format=None, type=None): + def export(self, filename, file_format=None, type=None, typequote='"'): """export density to file using the given format. The format can also be deduced from the suffix of the filename @@ -426,25 +426,34 @@ def export(self, filename, file_format=None, type=None): Parameters ---------- + filename : str name of the output file + file_format : {'dx', 'pickle', None} (optional) output file format, the default is "dx" + type : str (optional) - for DX, set the output DX array type, e.g., "double" or - "float"; note that PyMOL only understands "double" (see - issue `#35`_). By default (``None``), the DX type is - determined from the numpy dtype of the array of the grid - (and this will typically result in "double"). + for DX, set the output DX array type, e.g., "double" or "float". + By default (``None``), the DX type is determined from the numpy + dtype of the array of the grid (and this will typically result in + "double"). .. versionadded:: 0.4.0 - .. _`#35`: https://github.com/MDAnalysis/GridDataFormats/issues/35 + typequote : str (optional) + For DX, set the character used to quote the type string; + by default this is a double-quote character, '"'. + Custom parsers like the one from NAMD-GridForces (backend for MDFF) + expect no quotes, and typequote='' may be used to appease them. + + .. versionadded:: 0.5.0 + """ exporter = self._get_exporter(filename, file_format=file_format) - exporter(filename, type=type) + exporter(filename, type=type, typequote=typequote) # note: the _export_FORMAT() methods all take the filename as a mandatory # argument. They can process kwargs but they are not required to do @@ -460,7 +469,7 @@ def _export_python(self, filename, **kwargs): with open(filename, 'wb') as f: cPickle.dump(data, f, cPickle.HIGHEST_PROTOCOL) - def _export_dx(self, filename, type=None, **kwargs): + def _export_dx(self, filename, type=None, typequote='"', **kwargs): """Export the density grid to an OpenDX file. The file format is the simplest regular grid array and it is @@ -494,7 +503,7 @@ def _export_dx(self, filename, type=None, **kwargs): positions=OpenDX.gridpositions(1, self.grid.shape, self.origin, self.delta), connections=OpenDX.gridconnections(2, self.grid.shape), - data=OpenDX.array(3, self.grid, type=type), + data=OpenDX.array(3, self.grid, type=type, typequote=typequote), ) dx = OpenDX.field('density', components=components, comments=comments) dx.write(filename)