Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/0.8.x' into HEAD
Browse files Browse the repository at this point in the history
  • Loading branch information
francisco-dlp committed May 26, 2016
2 parents c586137 + 699fccf commit 9d1572d
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 83 deletions.
4 changes: 2 additions & 2 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ and `documentation
Importantly, the way to start HyperSpy changes in this release. Read :ref:`importing_hyperspy-label` for details.

It also includes some new features and introduces important API changes that
will be fully enforced in HyperSpy 0.9.
will be fully enforced in Hyperspy 1.0.

New features
------------
Expand Down Expand Up @@ -87,7 +87,7 @@ API changes

In HyperSpy 0.8.1 the full content of :py:mod:`~.hyperspy.hspy` is still
imported in the user namespace, but this can now be disabled in
``hs.preferences.General.import_hspy``. In HyperSpy 0.9 it will be
``hs.preferences.General.import_hspy``. In Hyperspy 1.0 it will be
disabled by default and the :py:mod:`~.hyperspy.hspy` module will be fully
removed in HyperSpy 0.10. We encourage all users to migrate to the new
syntax. For more details see :ref:`importing_hyperspy-label`.
Expand Down
6 changes: 0 additions & 6 deletions doc/user_guide/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,6 @@ but some features such as navigation sliders may be missing.
In [3]: import hyperspy.api as hs
.. warning::
When using the qt4 backend it is important to import hyperspy
before executing the ``%matplotlib`` magic as above to ensure that
matplotlib uses version 2 of the PyQt API. This is necessary to avoid
conflicts with other libraries.
This documentation assumes that numpy and matplotlib are also imported as
Expand All @@ -80,7 +75,6 @@ follows:
>>> import matplotlib.pyplot as plt



Getting help
------------

Expand Down
59 changes: 0 additions & 59 deletions hyperspy/_signals/pes.py

This file was deleted.

5 changes: 3 additions & 2 deletions hyperspy/io_plugins/ripple.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,15 +158,16 @@ def parse_ripple(fp):
line = line.split(sep) # now it's a list
if (line[0] in rpl_keys) is True:
# is rpl_keys[line[0]] an iterable?
if hasattr(rpl_keys[line[0]], '__iter__'):
try:
hasattr(rpl_keys[line[0]], '__iter__')
if line[1] not in rpl_keys[line[0]]:
err = \
'Wrong value for key %s.\n' \
'Value read is %s' \
' but it should be one of %s' % \
(line[0], line[1], str(rpl_keys[line[0]]))
raise IOError(err)
else:
except:
# rpl_keys[line[0]] must then be a type
line[1] = rpl_keys[line[0]](line[1])

Expand Down
48 changes: 37 additions & 11 deletions hyperspy/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,32 @@ def set_mpfit_parameters_info(self):
{'limited': limited,
'limits': limits},) * param._number_of_elements)

def ensure_parameters_in_bounds(self):
"""For all active components, snaps their free parameter values to
be within their boundaries (if bounded). Does not touch the array of
values.
"""
for component in self:
if component.active:
for param in component.free_parameters:
bmin = -np.inf if param.bmin is None else param.bmin
bmax = np.inf if param.bmax is None else param.bmax
if param._number_of_elements == 1:
if not bmin <= param.value <= bmax:
min_d = np.abs(param.value - bmin)
max_d = np.abs(param.value - bmax)
if min_d < max_d:
param.value = bmin
else:
param.value = bmax
else:
values = np.array(param.value)
minmask = values < bmin
maxmask = values > bmax
values[maxmask] = bmax
values[minmask] = bmin
param.value = tuple(values)

def store_current_values(self):
""" Store the parameters of the current coordinates into the
parameters array.
Expand Down Expand Up @@ -690,6 +716,16 @@ def fit(self, fitter=None, method='ls', grad=False,
else:
cm = dummy_context_manager

if bounded is True:
if fitter not in ("mpfit", "tnc", "l_bfgs_b"):
raise NotImplementedError("Bounded optimization is only"
"available for the mpfit "
"optimizer.")
else:
# this has to be done before setting the p0, so moved things
# around
self.ensure_parameters_in_bounds()

with cm(update_on_resume=True):
self.p_std = None
self._set_p0()
Expand All @@ -708,10 +744,6 @@ def fit(self, fitter=None, method='ls', grad=False,
grad_ml = self._gradient_ml
grad_ls = self._gradient_ls

if bounded is True and fitter not in ("mpfit", "tnc", "l_bfgs_b"):
raise NotImplementedError(
"Bounded optimization is only available for the mpfit "
"optimizer.")
if method == 'ml':
weights = None
if fitter != "fmin":
Expand Down Expand Up @@ -945,13 +977,7 @@ def multifit(self, mask=None, fetch_only_fixed=False,
pbar = progressbar.progressbar(maxval=maxval,
disabled=not show_progressbar)
if 'bounded' in kwargs and kwargs['bounded'] is True:
if kwargs['fitter'] == 'mpfit':
self.set_mpfit_parameters_info()
kwargs['bounded'] = None
elif kwargs['fitter'] in ("tnc", "l_bfgs_b"):
self.set_boundaries()
kwargs['bounded'] = None
else:
if kwargs['fitter'] not in ("tnc", "l_bfgs_b", "mpfit"):
_logger.info(
"The chosen fitter does not suppport bounding."
"If you require bounding please select one of the "
Expand Down
4 changes: 2 additions & 2 deletions hyperspy/signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -4588,8 +4588,8 @@ def map(self, function,
scale = set()
units = set()
for i in range(len(self.axes_manager.signal_axes)):
scale.add(self.axes_manager[i].scale)
units.add(self.axes_manager[i].units)
scale.add(self.axes_manager.signal_axes[i].scale)
units.add(self.axes_manager.signal_axes[i].units)
if len(units) != 1 or len(scale) != 1:
warnings.warn(
"The function you applied does not take into "
Expand Down
85 changes: 84 additions & 1 deletion hyperspy/tests/model/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,68 @@ def test_components_class_change_name_del_default(self):
g1.name = "test"
getattr(m.components, slugify(invalid_name))

def test_snap_parameter_bounds(self):
m = self.model
g1 = hs.model.components.Gaussian()
m.append(g1)
g2 = hs.model.components.Gaussian()
m.append(g2)
g3 = hs.model.components.Gaussian()
m.append(g3)
g4 = hs.model.components.Gaussian()
m.append(g4)

g1.A.value = 3.
g1.centre.bmin = 300.
g1.centre.value = 1.
g1.sigma.bmax = 15.
g1.sigma.value = 30

g2.A.value = 1
g2.A.bmin = 0.
g2.A.bmax = 3.
g2.centre.value = 0
g2.centre.bmin = 1
g2.centre.bmax = 3.
g2.sigma.value = 4
g2.sigma.bmin = 1
g2.sigma.bmax = 3.

g3.A.bmin = 0
g3.A.value = -3
g3.A.free = False

g3.centre.value = 15
g3.centre.bmax = 10
g3.centre.free = False

g3.sigma.value = 1
g3.sigma.bmin = 0
g3.sigma.bmax = 0

g4.active = False
g4.A.value = 300
g4.A.bmin = 500
g4.centre.value = 0
g4.centre.bmax = -1
g4.sigma.value = 1
g4.sigma.bmin = 10
m.ensure_parameters_in_bounds()
np.testing.assert_almost_equal(g1.A.value, 3.)
np.testing.assert_almost_equal(g2.A.value, 1.)
np.testing.assert_almost_equal(g3.A.value, -3.)
np.testing.assert_almost_equal(g4.A.value, 300.)

np.testing.assert_almost_equal(g1.centre.value, 300.)
np.testing.assert_almost_equal(g2.centre.value, 1.)
np.testing.assert_almost_equal(g3.centre.value, 15.)
np.testing.assert_almost_equal(g4.centre.value, 0)

np.testing.assert_almost_equal(g1.sigma.value, 15.)
np.testing.assert_almost_equal(g2.sigma.value, 3.)
np.testing.assert_almost_equal(g3.sigma.value, 0.)
np.testing.assert_almost_equal(g4.sigma.value, 1)


class TestModel2D:

Expand Down Expand Up @@ -579,7 +641,16 @@ def test_fit_odr_grad(self):

def test_fit_bounded(self):
self.m[0].centre.bmin = 0.5
self.m[0].bounded = True
# self.m[0].bounded = True
self.m.fit(fitter="mpfit", bounded=True)
np.testing.assert_almost_equal(self.m[0].A.value, 9991.65422046, 4)
np.testing.assert_almost_equal(self.m[0].centre.value, 0.5)
np.testing.assert_almost_equal(self.m[0].sigma.value, 2.08398236966)

def test_fit_bounded_bad_starting_values(self):
self.m[0].centre.bmin = 0.5
self.m[0].centre.value = -1
# self.m[0].bounded = True
self.m.fit(fitter="mpfit", bounded=True)
np.testing.assert_almost_equal(self.m[0].A.value, 9991.65422046, 4)
np.testing.assert_almost_equal(self.m[0].centre.value, 0.5)
Expand Down Expand Up @@ -792,6 +863,18 @@ def test_fetch_only_fixed_true(self):
np.testing.assert_array_almost_equal(self.m[0].A.map['values'],
[2., 2.])

def test_bounded_snapping(self):
m = self.m
m[0].A.free = True
m.signal.data *= 2.
m[0].A.value = 2.
m[0].A.bmin = 3.
m.multifit(fitter='mpfit', bounded=True, show_progressbar=None)
np.testing.assert_array_almost_equal(self.m[0].r.map['values'],
[3., 3.])
np.testing.assert_array_almost_equal(self.m[0].A.map['values'],
[4., 4.])


class TestStoreCurrentValues:

Expand Down

0 comments on commit 9d1572d

Please sign in to comment.