Skip to content

Commit

Permalink
Merge pull request #723 from wright-group/development
Browse files Browse the repository at this point in the history
3.1.2
  • Loading branch information
ksunden committed Aug 18, 2018
2 parents 316646d + 5285c37 commit 4628d76
Show file tree
Hide file tree
Showing 39 changed files with 17,138 additions and 356 deletions.
17 changes: 13 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
language: python
python:
- "3.5"
- "3.6"
matrix:
include:
- python: 3.5
dist: trusty
sudo: false
- python: 3.6
dist: trusty
sudo: false
- python: 3.7
dist: xenial
sudo: true
addons:
apt:
packages:
- libfreetype6-dev
- libopenblas-dev
install:
- python setup.py install
- pip install cython
- pip install .
- pip install -U pytest pytest-mp
before_script:
- "export DISPLAY=:99.0"
Expand Down
2 changes: 1 addition & 1 deletion WrightTools/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.1.1
3.1.2
12 changes: 6 additions & 6 deletions WrightTools/_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
class Dataset(h5py.Dataset):
"""Array-like data container."""

instances = {}
_instances = {}
class_name = "Dataset"

def __getitem__(self, index):
Expand Down Expand Up @@ -88,12 +88,12 @@ def __init__(self, *args, **kwargs):
def __new__(cls, parent, id, **kwargs):
"""New object formation handler."""
fullpath = parent.fullpath + h5py.h5i.get_name(id).decode()
if fullpath in cls.instances.keys():
return cls.instances[fullpath]
if fullpath in cls._instances.keys():
return cls._instances[fullpath]
else:
instance = super(Dataset, cls).__new__(cls)
cls.__init__(instance, parent, id, **kwargs)
cls.instances[fullpath] = instance
cls._instances[fullpath] = instance
return instance

def __repr__(self):
Expand Down Expand Up @@ -363,7 +363,7 @@ def max(self):
def f(dataset, s):
return np.nanmax(dataset[s])

self.attrs["max"] = max(self.chunkwise(f).values())
self.attrs["max"] = np.nanmax(list(self.chunkwise(f).values()))
return self.attrs["max"]

def min(self):
Expand All @@ -373,7 +373,7 @@ def min(self):
def f(dataset, s):
return np.nanmin(dataset[s])

self.attrs["min"] = min(self.chunkwise(f).values())
self.attrs["min"] = np.nanmin(list(self.chunkwise(f).values()))
return self.attrs["min"]

def slices(self):
Expand Down
25 changes: 13 additions & 12 deletions WrightTools/_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def __call__(cls, *args, **kwargs):
class Group(h5py.Group, metaclass=MetaClass):
"""Container of groups and datasets."""

instances = {}
_instances = {}
class_name = "Group"

def __init__(self, file=None, parent=None, name=None, **kwargs):
Expand Down Expand Up @@ -154,11 +154,11 @@ def __new__(cls, *args, **kwargs):
elif edit_local and filepath:
p = filepath
p = str(p)
for i in cls.instances.keys():
for i in cls._instances.keys():
if i.startswith(os.path.abspath(p) + "::"):
file = cls.instances[i].file
if hasattr(cls.instances[i], "_tmpfile"):
tmpfile = cls.instances[i]._tmpfile
file = cls._instances[i].file
if hasattr(cls._instances[i], "_tmpfile"):
tmpfile = cls._instances[i]._tmpfile
break
if file is None:
file = h5py.File(p, "a")
Expand All @@ -171,14 +171,14 @@ def __new__(cls, *args, **kwargs):
fullpath = p + "::" + parent + name
# create and/or return
try:
instance = cls.instances[fullpath]
instance = cls._instances[fullpath]
except KeyError:
kwargs["file"] = file
kwargs["parent"] = parent
kwargs["name"] = natural_name
instance = super(Group, cls).__new__(cls)
cls.__init__(instance, **kwargs)
cls.instances[fullpath] = instance
cls._instances[fullpath] = instance
if tmpfile:
setattr(instance, "_tmpfile", tmpfile)
weakref.finalize(instance, instance.close)
Expand Down Expand Up @@ -232,27 +232,28 @@ def parent(self):
from .collection import Collection

key = posixpath.dirname(self.fullpath) + posixpath.sep
self._parent = Collection.instances[key]
self._parent = Collection._instances[key]
finally:
return self._parent

def close(self):
"""Close the file that contains the Group.
All groups which are in the file will be closed and removed from the instances dictionaries.
Tempfiles, if they exist, will be removed.
All groups which are in the file will be closed and removed from the
_instances dictionaries.
Tempfiles, if they exist, will be removed
"""
from .collection import Collection
from .data._data import Channel, Data, Variable

path = os.path.abspath(self.filepath) + "::"
for kind in (Collection, Channel, Data, Variable, Group):
rm = []
for key in kind.instances.keys():
for key in kind._instances.keys():
if key.startswith(path):
rm.append(key)
for key in rm:
kind.instances.pop(key, None)
kind._instances.pop(key, None)

if self.fid.valid > 0:
# for some reason, the following file operations sometimes fail
Expand Down
2 changes: 1 addition & 1 deletion WrightTools/artists/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ def add_subplot(self, *args, **kwargs):
self._axstack.add(key, a)
self.sca(a)
if int(matplotlib.__version__.split(".")[0]) > 1:
a._remove_method = self.__remove_ax
a._remove_method = lambda ax: self.delaxes(ax)
self.stale = True
a.stale_callback = matplotlib.figure._stale_figure_callback
# finish
Expand Down
30 changes: 20 additions & 10 deletions WrightTools/artists/_interact.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,14 @@ def get_clim(channel, current_state):
return clim


def gen_ticklabels(points):
def gen_ticklabels(points, signed=None):
step = np.nanmin(np.diff(points))
if step == 0:
ticklabels = ["NaN" for point in points]
if step == 0: # zeros everywhere
ticklabels = ['' for i in range(11)]
if signed:
ticklabels[5] = '0'
else:
ticklabels[0] = '0'
return ticklabels
ordinal = np.log10(np.abs(step))
ndigits = -int(np.floor(ordinal))
Expand Down Expand Up @@ -216,6 +220,9 @@ def interact2D(data, xaxis=0, yaxis=1, channel=0, local=False, verbose=True):
verbose=False,
)[0]
clim = get_clim(channel, current_state)
ticklabels = gen_ticklabels(np.linspace(*clim, 11), channel.signed)
if clim[0] == clim[1]:
clim = [-1 if channel.signed else 0, 1]
obj2D = ax0.pcolormesh(
current_state.dat,
cmap=cmap,
Expand All @@ -229,6 +236,8 @@ def interact2D(data, xaxis=0, yaxis=1, channel=0, local=False, verbose=True):
colorbar = plot_colorbar(
cax, cmap=cmap, label=channel.natural_name, ticks=np.linspace(clim[0], clim[1], 11)
)
colorbar.set_ticklabels(ticklabels)
fig.canvas.draw_idle()

def draw_sideplot_projections():
arr = current_state.dat[channel.natural_name][:]
Expand Down Expand Up @@ -353,9 +362,10 @@ def update_local(index):
print("normalization:", index)
current_state.local = radio.value_selected[1:] == "local"
clim = get_clim(channel, current_state)
colorbar = plot_colorbar(
cax, cmap=cmap, label=channel.natural_name, ticks=np.linspace(clim[0], clim[1], 11)
)
ticklabels = gen_ticklabels(np.linspace(*clim, 11), channel.signed)
colorbar.set_ticklabels(ticklabels)
if clim[0] == clim[1]:
clim = [-1 if channel.signed else 0, 1]
obj2D.set_clim(*clim)
fig.canvas.draw_idle()

Expand All @@ -378,11 +388,11 @@ def update(info):
)
obj2D.set_array(current_state.dat[channel.natural_name][:].ravel())
clim = get_clim(channel, current_state)
ticklabels = gen_ticklabels(np.linspace(*clim, 11), channel.signed)
if clim[0] == clim[1]:
clim = [-1 if channel.signed else 0, 1]
obj2D.set_clim(*clim)
ticklabels = gen_ticklabels(np.linspace(*clim, 11))
colorbar = plot_colorbar(
cax, cmap=cmap, label=channel.natural_name, ticks=np.linspace(clim[0], clim[1], 11)
)
colorbar.set_ticklabels(ticklabels)
sp_x.collections.clear()
sp_y.collections.clear()
draw_sideplot_projections()
Expand Down
49 changes: 25 additions & 24 deletions WrightTools/data/_axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import numpy as np

from ._variable import Variable
from .. import exceptions as wt_exceptions
from .. import kit as wt_kit
from .. import units as wt_units
Expand Down Expand Up @@ -63,7 +64,7 @@ def __getitem__(self, index):
vs[variable.natural_name] = wt_units.converter(arr, variable.units, self.units)
return numexpr.evaluate(self.expression.split("=")[0], local_dict=vs)

def __repr__(self):
def __repr__(self) -> str:
return "<WrightTools.Axis {0} ({1}) at {2}>".format(
self.expression, str(self.units), id(self)
)
Expand All @@ -72,50 +73,49 @@ def __repr__(self):
def _leaf(self):
out = self.expression
if self.units is not None:
out += " ({0}) {1}".format(self.units, self.shape)
out += " ({0})".format(self.units)
out += " {0}".format(self.shape)
return out

@property
def full(self):
def full(self) -> np.ndarray:
arr = self[:]
for i in range(arr.ndim):
if arr.shape[i] == 1:
arr = np.repeat(arr, self.parent.shape[i], axis=i)
return arr

@property
def identity(self):
def identity(self) -> str:
"""Complete identifier written to disk in data.attrs['axes']."""
return self.natural_name + " {%s}" % self.units

@property
def label(self):
symbol = wt_units.get_symbol(self.units)
label = self.expression
for v in self.variables:
vl = "%s_{%s}" % (symbol, v.label)
vl = vl.replace("_{}", "") # label can be empty, no empty subscripts
label = label.replace(v.natural_name, vl)
def label(self) -> str:
label = self.expression.replace("_", "\\;")
if self.units_kind:
symbol = wt_units.get_symbol(self.units)
for v in self.variables:
vl = "%s_{%s}" % (symbol, v.label)
vl = vl.replace("_{}", "") # label can be empty, no empty subscripts
label = label.replace(v.natural_name, vl)
units_dictionary = getattr(wt_units, self.units_kind)
label += r"\,"
label += r"\left("
label += units_dictionary[self.units][2]
label += r"\right)"
else:
pass
label = r"$\mathsf{%s}$" % label
return label

@property
def natural_name(self):
def natural_name(self) -> str:
name = self.expression.strip()
for op in operators:
name = name.replace(op, operator_to_identifier[op])
return wt_kit.string2identifier(name)

@property
def ndim(self):
def ndim(self) -> int:
"""Get number of dimensions."""
try:
assert self._ndim is not None
Expand All @@ -125,27 +125,27 @@ def ndim(self):
return self._ndim

@property
def points(self):
def points(self) -> np.ndarray:
"""Squeezed array."""
return np.squeeze(self[:])

@property
def shape(self):
def shape(self) -> tuple:
"""Shape."""
return wt_kit.joint_shape(*self.variables)

@property
def size(self):
def size(self) -> int:
"""Size."""
return functools.reduce(operator.mul, self.shape)

@property
def units_kind(self):
def units_kind(self) -> str:
"""Units kind."""
return wt_units.kind(self.units)

@property
def variables(self):
def variables(self) -> list:
"""Variables."""
try:
assert self._variables is not None
Expand All @@ -170,9 +170,10 @@ def convert(self, destination_units, *, convert_variables=False):
convert_variables : boolean (optional)
Toggle conversion of stored arrays. Default is False.
"""
if self.units is None and (destination_units is None or destination_units == "None"):
return
if not wt_units.is_valid_conversion(self.units, destination_units):
kind = wt_units.kind(self.units)
valid = list(wt_units.dicts[kind].keys())
valid = wt_units.get_valid_conversions(self.units)
raise wt_exceptions.UnitsError(valid, destination_units)
if convert_variables:
for v in self.variables:
Expand All @@ -181,8 +182,8 @@ def convert(self, destination_units, *, convert_variables=False):

def max(self):
"""Axis max."""
return np.max(self[:])
return np.nanmax(self[:])

def min(self):
"""Axis min."""
return np.min(self[:])
return np.nanmin(self[:])
2 changes: 1 addition & 1 deletion WrightTools/data/_brunold.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
# --- from function -------------------------------------------------------------------------------


def from_BrunoldrRaman(filepath, name=None, parent=None, verbose=True):
def from_BrunoldrRaman(filepath, name=None, parent=None, verbose=True) -> Data:
"""Create a data object from the Brunold rRaman instrument.
Expects one energy (in wavenumbers) and one counts value.
Expand Down

0 comments on commit 4628d76

Please sign in to comment.