diff --git a/postpic/analyzer/fields.py b/postpic/analyzer/fields.py index ac7eacfd933c4c2e5b5d7261a2dde3dc94edd2c1..9a8d3b80fb7bd1bd5a2cd1a36bc835325e2eae65 100644 --- a/postpic/analyzer/fields.py +++ b/postpic/analyzer/fields.py @@ -82,7 +82,7 @@ class FieldAnalyzer(object): # General interface for everything def createfieldfromkey(self, key): - ret = Field(self._returnfunc(self.dumpreader[key])) + ret = Field(self._returnfunc(self.dumpreader.getdata(key))) ret.name = key self.setspacialtofield(ret) return ret diff --git a/postpic/analyzer/particles.py b/postpic/analyzer/particles.py index c3467330aa3695efef0bbc3148f013935323e71d..1bbb63f1c077f19c0e4697d79c9fdbe76372b19e 100644 --- a/postpic/analyzer/particles.py +++ b/postpic/analyzer/particles.py @@ -145,6 +145,8 @@ class _SingleSpeciesAnalyzer(object): def __len__(self): # = number of particles # find a valid dataset to count number of paricles + # return 0 if no valid dataset can be found + ret = 0 if self._compressboollist is not None: return np.count_nonzero(self._compressboollist) for key in self._atomicprops: @@ -600,13 +602,19 @@ class ParticleAnalyzer(object): def createHistgram1d(self, scalarfx, optargsh={}, simextent=False, simgrid=False, rangex=None, - weights=lambda x: 1): + weights=lambda x: 1, force=False): optargshdefs = {'bins': 300, 'shape': 0} optargshdefs.update(optargsh) optargsh = optargshdefs if simgrid: simextent = True - xdata = scalarfx(self) + if force: + try: + xdata = scalarfx(self) + except (KeyError): + xdata = [] # Return empty histogram + else: + xdata = scalarfx(self) # In case there are no particles if len(xdata) == 0: return [], [] @@ -635,7 +643,7 @@ class ParticleAnalyzer(object): def createHistgram2d(self, scalarfx, scalarfy, optargsh={}, simextent=False, simgrid=False, rangex=None, rangey=None, - weights=lambda x: 1): + weights=lambda x: 1, force=False): """ Creates an 2d Histogram. @@ -661,8 +669,15 @@ class ParticleAnalyzer(object): optargsh = optargshdefs if simgrid: simextent = True - xdata = scalarfx(self) - ydata = scalarfy(self) + if force: + try: + xdata = scalarfx(self) + ydata = scalarfy(self) + except (KeyError): + xdata = [] # Return empty histogram + else: + xdata = scalarfx(self) + ydata = scalarfy(self) if len(xdata) == 0: return [[]], [0, 1], [1] # TODO: Falls rangex oder rangy gegeben ist, @@ -701,7 +716,7 @@ class ParticleAnalyzer(object): def createHistgram3d(self, scalarfx, scalarfy, scalarfz, optargsh={}, simextent=False, simgrid=False, rangex=None, rangey=None, rangez=None, - weights=lambda x: 1): + weights=lambda x: 1, force=False): """ Creates an 3d Histogram. @@ -729,9 +744,17 @@ class ParticleAnalyzer(object): optargsh = optargshdefs if simgrid: simextent = True - xdata = scalarfx(self) - ydata = scalarfy(self) - zdata = scalarfz(self) + if force: + try: + xdata = scalarfx(self) + ydata = scalarfy(self) + zdata = scalarfz(self) + except (KeyError): + xdata = [] # Return empty histogram + else: + xdata = scalarfx(self) + ydata = scalarfy(self) + zdata = scalarfz(self) if len(xdata) == 0: return [[]], [0, 1], [1], [1] # TODO: Falls rangex oder rangy gegeben ist, diff --git a/postpic/cythonfunctions.pyx b/postpic/cythonfunctions.pyx index 8bd7c1101a9b289e0f103b61d137f6e99b3db743..2269749cbe27dbec456dd42e39c1ab0dc843ef98 100644 --- a/postpic/cythonfunctions.pyx +++ b/postpic/cythonfunctions.pyx @@ -49,9 +49,13 @@ def histogram(np.ndarray[np.double_t, ndim=1] data, range=None, int bins=20, else: min = range[0] max = range[1] + # ensure max != min + if np.abs(max-min) < 1e-100: + max += 1e-100 + min -= 1e-100 bin_edges = np.linspace(min, max, bins+1) cdef int n = len(data) - cdef double dx = 1.0 / (max - min) * bins + cdef double dx = 1.0 / (max - min) * bins # actually: 1/dx cdef np.ndarray[np.double_t, ndim=1] ret cdef int shape_supp cdef double x @@ -132,12 +136,19 @@ def histogram2d(np.ndarray[np.double_t, ndim=1] datax, np.ndarray[np.double_t, n xmax = range[0][1] ymin = range[1][0] ymax = range[1][1] + # ensure max != min + if np.abs(xmax-xmin) < 1e-100: + xmax += 1e-100 + xmin -= 1e-100 + if np.abs(ymax-ymin) < 1e-100: + ymax += 1e-100 + ymin -= 1e-100 cdef int xbins = bins[0] cdef int ybins = bins[1] xedges = np.linspace(xmin, xmax, xbins+1) yedges = np.linspace(ymin, ymax, ybins+1) - cdef double dx = 1.0 / (xmax - xmin) * xbins - cdef double dy = 1.0 / (ymax - ymin) * ybins + cdef double dx = 1.0 / (xmax - xmin) * xbins # actually: 1/dx + cdef double dy = 1.0 / (ymax - ymin) * ybins # actually: 1/dy cdef np.ndarray[np.double_t, ndim=2] ret cdef int shape_supp, xs, ys, xoffset, yoffset cdef double x, y, xd, yd @@ -251,15 +262,25 @@ def histogram3d(np.ndarray[np.double_t, ndim=1] datax, np.ndarray[np.double_t, n ymax = range[1][1] zmin = range[2][0] zmax = range[2][1] + # ensure max != min + if np.abs(xmax-xmin) < 1e-100: + xmax += 1e-100 + xmin -= 1e-100 + if np.abs(ymax-ymin) < 1e-100: + ymax += 1e-100 + ymin -= 1e-100 + if np.abs(zmax-zmin) < 1e-100: + zmax += 1e-100 + zmin -= 1e-100 cdef int xbins = bins[0] cdef int ybins = bins[1] cdef int zbins = bins[2] xedges = np.linspace(xmin, xmax, xbins+1) yedges = np.linspace(ymin, ymax, ybins+1) zedges = np.linspace(zmin, zmax, zbins+1) - cdef double dx = 1.0 / (xmax - xmin) * xbins - cdef double dy = 1.0 / (ymax - ymin) * ybins - cdef double dz = 1.0 / (zmax - zmin) * zbins + cdef double dx = 1.0 / (xmax - xmin) * xbins # actually: 1/dx + cdef double dy = 1.0 / (ymax - ymin) * ybins # actually: 1/dy + cdef double dz = 1.0 / (zmax - zmin) * zbins # actually: 1/dz cdef np.ndarray[np.double_t, ndim=3] ret cdef int shape_supp, xs, ys, zs, xoffset, yoffset, zoffset cdef double x, y, z, xd, yd, zd diff --git a/postpic/datareader/__init__.py b/postpic/datareader/__init__.py index 1e097bc334198173c16e1c0f0057ebca60b1b320..3e7b5852cf34cbc22b724bd0b69723178e9fc799 100644 --- a/postpic/datareader/__init__.py +++ b/postpic/datareader/__init__.py @@ -106,6 +106,9 @@ class Dumpreader_ifc(FieldAnalyzer): def __getitem__(self, key): pass + def getdata(self, key): + return self[key] + # --- General Information --- @abc.abstractmethod def timestep(self): diff --git a/postpic/datareader/epochsdf.py b/postpic/datareader/epochsdf.py index 2327fd53dfbb3ce5ffd41dd7e52a813e8037708d..8465695f8d10503a56e77ada6ee753d182103f4a 100644 --- a/postpic/datareader/epochsdf.py +++ b/postpic/datareader/epochsdf.py @@ -69,6 +69,9 @@ class Sdfreader(Dumpreader_ifc): def __getitem__(self, key): return self._data[key] + def getdata(self, key): + return self[key].data + def timestep(self): return self['Header']['step'] @@ -127,7 +130,10 @@ class Sdfreader(Dumpreader_ifc): 4: lambda s: self['Particles/Py/' + s].data, 5: lambda s: self['Particles/Pz/' + s].data, 10: lambda s: self['Particles/ID/' + s].data} - ret = np.float64(options[attribid](species)) + try: + ret = np.float64(options[attribid](species)) + except(IndexError): + raise KeyError return ret def getderived(self): diff --git a/postpic/plotting/plotter_matplotlib.py b/postpic/plotting/plotter_matplotlib.py index 9d6361deee86150544f999082fe27944208e6caf..5c76c73210b56c8d58393efa9332de62eb5bdbb9 100644 --- a/postpic/plotting/plotter_matplotlib.py +++ b/postpic/plotting/plotter_matplotlib.py @@ -320,7 +320,7 @@ class MatplotlibPlotter(object): import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(1, 1, 1) - name = kwargs.pop('name') if 'name' in kwargs else fields[0].name + name = kwargs.pop('name', fields[0].name) MatplotlibPlotter.addFields1d(ax, *fields, **kwargs) self._plotfinalize(fig) self.annotate(fig, project=self.project) @@ -362,8 +362,10 @@ class MatplotlibPlotter(object): if field is None: ret = self._skipplot('none') elif field.dimensions <= 0: - ret = self._skipplot(field.name) + ret = self._skipplot(name if name else field.name) elif field.dimensions == 1: + if name: + kwargs.update({'name': name}) ret = self.plotFields1d(field, **kwargs) elif field.dimensions == 2: ret = self.plotField2d(field, name, **kwargs)