Commit bf1576c5 authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

Merge branch 'master' into v1.4

parents d6c3becb 33ef6157
Pipeline #1279 failed with stages
in 10 minutes and 1 second
...@@ -2,17 +2,6 @@ ...@@ -2,17 +2,6 @@
set -e set -e
# Install $PY_VERSION, xvfb, and all
# of the wxpython dependencies.
apt-get update -y || true
apt-get install -y software-properties-common python-software-properties xvfb libgtk2.0-0 libnotify4 freeglut3 libsdl1.2debian
add-apt-repository -y ppa:deadsnakes/ppa
apt-get update -y || true
apt-get install -y $PY_VERSION "$PY_VERSION"-dev $PY_PACKAGES
$PY_VENV test.venv
source test.venv/bin/activate
pip install --upgrade pip setuptools
# If running on a fork repository, we merge in the # If running on a fork repository, we merge in the
# upstream/master branch. This is done so that merge # upstream/master branch. This is done so that merge
# requests from fork to the parent repository will # requests from fork to the parent repository will
...@@ -23,7 +12,7 @@ if [[ "$CI_PROJECT_PATH" != "$UPSTREAM_PROJECT" ]]; then ...@@ -23,7 +12,7 @@ if [[ "$CI_PROJECT_PATH" != "$UPSTREAM_PROJECT" ]]; then
git merge --no-commit --no-ff upstream/master; git merge --no-commit --no-ff upstream/master;
fi; fi;
$INSTALL_WX source /test.venv/bin/activate
# All other deps can be installed as normal. # All other deps can be installed as normal.
# We install test dependenciesd through pip, # We install test dependenciesd through pip,
......
...@@ -16,6 +16,11 @@ ...@@ -16,6 +16,11 @@
# 5. deploy: Uploading the build outputs to pypi/hosting servers, and the # 5. deploy: Uploading the build outputs to pypi/hosting servers, and the
# documentation to a hosting server. # documentation to a hosting server.
# #
# Custom docker images are used for several jobs - these images are
# available at:
#
# https://hub.docker.com/u/pauldmccarthy/
#
# The test and style stages are executed on all branches of upstream and fork # The test and style stages are executed on all branches of upstream and fork
# repositories. # repositories.
# #
...@@ -81,12 +86,6 @@ stages: ...@@ -81,12 +86,6 @@ stages:
# - TWINE_PASSWORD: - Password to use when uploading to pypi # - TWINE_PASSWORD: - Password to use when uploading to pypi
# #
# - TWINE_REPOSITORY_URL: - Pypi repository to upload to # - TWINE_REPOSITORY_URL: - Pypi repository to upload to
#
# - WXPYTHON_UBUNTU1404_URL: - Url to a location containg binary wheels
# for wxPython/ubuntu 14.04
#
# - WXPYTHON_UBUNTU1604_URL: - Url to a location containg binary wheels
# for wxPython/ubuntu 16.04
############################################################################### ###############################################################################
...@@ -161,48 +160,26 @@ variables: ...@@ -161,48 +160,26 @@ variables:
test:2.7: test:2.7:
stage: test stage: test
image: ubuntu:16.04 image: pauldmccarthy/fsleyes-py27-wxpy4-gtk2
<<: *test_template <<: *test_template
variables:
PY_VERSION: "python2.7"
PY_PACKAGES: "python-pip python-virtualenv"
PY_VENV: "virtualenv"
INSTALL_WX: "pip install --only-binary wxpython -f $WXPYTHON_UBUNTU1604_URL wxpython"
# we use ubuntu:14.04 for python 3.4, because
# wxpython is not available for 16.04/3.4
test:3.4: test:3.4:
stage: test stage: test
image: ubuntu:14.04 image: pauldmccarthy/fsleyes-py34-wxpy4-gtk2
<<: *test_template <<: *test_template
variables:
PY_VERSION: "python3.4"
PY_PACKAGES: "python3-pip python3.4-venv"
PY_VENV: "python3.4 -m venv"
INSTALL_WX: "pip install --pre -f $WXPYTHON_UBUNTU1404_URL wxpython"
test:3.5: test:3.5:
stage: test stage: test
image: ubuntu:16.04 image: pauldmccarthy/fsleyes-py35-wxpy4-gtk2
<<: *test_template <<: *test_template
variables:
PY_VERSION: "python3.5"
PY_PACKAGES: "python3-pip python3-venv"
PY_VENV: "python3.5 -m venv"
INSTALL_WX: "pip install --only-binary wxpython -f $WXPYTHON_UBUNTU1604_URL wxpython"
test:3.6: test:3.6:
stage: test stage: test
image: ubuntu:16.04 image: pauldmccarthy/fsleyes-py36-wxpy4-gtk2
<<: *test_template <<: *test_template
variables:
PY_VERSION: "python3.6"
PY_PACKAGES: "python3-pip python3.6-venv"
PY_VENV: "python3.6 -m venv"
INSTALL_WX: "pip install --only-binary wxpython -f $WXPYTHON_UBUNTU1604_URL wxpython"
############# #############
...@@ -212,13 +189,9 @@ test:3.6: ...@@ -212,13 +189,9 @@ test:3.6:
style: style:
stage: style stage: style
image: ubuntu:16.04 image: pauldmccarthy/fsleyes-py35-wxpy4-gtk2
<<: *test_template <<: *test_template
variables: variables:
PY_VERSION: "python3.5"
PY_PACKAGES: "python3-pip python3-venv"
PY_VENV: "python3.5 -m venv"
INSTALL_WX: "pip install --only-binary wxpython -f $WXPYTHON_UBUNTU1604_URL wxpython"
TEST_STYLE: "true" TEST_STYLE: "true"
......
...@@ -2,19 +2,28 @@ This document contains the ``fslpy`` release history in reverse chronological ...@@ -2,19 +2,28 @@ This document contains the ``fslpy`` release history in reverse chronological
order. order.
1.4.1 (Thursday 9th November 2017) 1.4.2 (Monday December 4th 2017)
--------------------------------
* New function :func:`.transform.rmsdev` function, which implements the RMS
deviation equation for comparing two affine transformations (FMRIB Technical
Report TR99MJ1, available at https://www.fmrib.ox.ac.uk/datasets/techrep/).
1.4.1 (Thursday November 9th 2017)
---------------------------------- ----------------------------------
* Fixed bug in ``setup.py``. * Fixed bug in ``setup.py``.
1.4.0 (Thursday 9th November 2017) 1.4.0 (Thursday November 9th 2017)
---------------------------------- ----------------------------------
* The :func:`.uniquePrefix` function now raises a :exc:`.PathError` instead * The :func:`.uniquePrefix` function now raises a :exc:`~.path.PathError`
of a :exc:`.ValueError`, when an invalid path is provided. instead of a :exc:`.ValueError`, when an invalid path is provided.
* The :mod:`fsl.utils.async` module is now deprecated, as ``async`` will * The :mod:`fsl.utils.async` module is now deprecated, as ``async`` will
become a reserved word in Python 3.7. It has been renamed to become a reserved word in Python 3.7. It has been renamed to
``fsl.utils.idle``, with no other API changes. ``fsl.utils.idle``, with no other API changes.
...@@ -32,7 +41,7 @@ order. ...@@ -32,7 +41,7 @@ order.
if incompatible shapes are provided. if incompatible shapes are provided.
1.3.1 (Wednesday 25th October 2017) 1.3.1 (Wednesday October 25th 2017)
----------------------------------- -----------------------------------
...@@ -40,7 +49,7 @@ order. ...@@ -40,7 +49,7 @@ order.
``WX_UNKNOWN``. ``WX_UNKNOWN``.
1.3.0 (Wednesday 25th October 2017) 1.3.0 (Wednesday October 25th 2017)
----------------------------------- -----------------------------------
......
...@@ -372,7 +372,7 @@ class Settings(object): ...@@ -372,7 +372,7 @@ class Settings(object):
try: try:
with open(configFile, 'rb') as f: with open(configFile, 'rb') as f:
return pickle.load(f) return pickle.load(f)
except (IOError, pickle.UnpicklingError): except (IOError, pickle.UnpicklingError, EOFError):
log.debug('Unable to load stored {} configuration file ' log.debug('Unable to load stored {} configuration file '
'{}'.format(self.__configID, configFile), '{}'.format(self.__configID, configFile),
exc_info=True) exc_info=True)
...@@ -391,7 +391,7 @@ class Settings(object): ...@@ -391,7 +391,7 @@ class Settings(object):
try: try:
with open(configFile, 'wb') as f: with open(configFile, 'wb') as f:
pickle.dump(config, f) pickle.dump(config, f)
except (IOError, pickle.PicklingError): except (IOError, pickle.PicklingError, EOFError):
log.warning('Unable to save {} configuration file ' log.warning('Unable to save {} configuration file '
'{}'.format(self.__configID, configFile), '{}'.format(self.__configID, configFile),
exc_info=True) exc_info=True)
...@@ -23,6 +23,7 @@ spaces. The following functions are provided: ...@@ -23,6 +23,7 @@ spaces. The following functions are provided:
axisBounds axisBounds
flirtMatrixToSform flirtMatrixToSform
sformToFlirtMatrix sformToFlirtMatrix
rmsdev
And a few more functions are provided for working with vectors: And a few more functions are provided for working with vectors:
...@@ -593,3 +594,49 @@ def sformToFlirtMatrix(srcImage, refImage, srcXform=None): ...@@ -593,3 +594,49 @@ def sformToFlirtMatrix(srcImage, refImage, srcXform=None):
refWorldToVoxMat, refWorldToVoxMat,
srcVoxToWorldMat, srcVoxToWorldMat,
srcScaledVoxToVoxMat) srcScaledVoxToVoxMat)
def rmsdev(T1, T2, R=None, xc=None):
"""Calculates the RMS deviation of the given affine transforms ``T1`` and
``T2``. This can be used as a measure of the 'distance' between two
affines.
The ``T1`` and ``T2`` arguments may be either full ``(4, 4)`` affines, or
``(3, 3)`` rotation matrices.
See FMRIB technical report TR99MJ1, available at:
https://www.fmrib.ox.ac.uk/datasets/techrep/
:arg T1: First affine
:arg T2: Second affine
:arg R: Sphere radius
:arg xc: Sphere centre
:returns: The RMS deviation between ``T1`` and ``T2``.
"""
if R is None:
R = 1
if xc is None:
xc = np.zeros(3)
# rotations only
if T1.shape == (3, 3):
M = np.dot(T2, invert(T1)) - np.eye(3)
A = M[:3, :3]
t = np.zeros(3)
# full affine
else:
M = np.dot(T2, invert(T1)) - np.eye(4)
A = M[:3, :3]
t = M[:3, 3]
Axc = np.dot(A, xc)
erms = np.dot((t + Axc).T, t + Axc)
erms = 0.2 * R ** 2 * np.dot(A.T, A).trace() + erms
erms = np.sqrt(erms)
return erms
...@@ -41,7 +41,7 @@ import re ...@@ -41,7 +41,7 @@ import re
import string import string
__version__ = '1.4.1' __version__ = '1.4.2'
"""Current version number, as a string. """ """Current version number, as a string. """
......
...@@ -537,3 +537,34 @@ def test_sformToFlirtMatrix(): ...@@ -537,3 +537,34 @@ def test_sformToFlirtMatrix():
assert np.all(np.isclose(result1, expected)) assert np.all(np.isclose(result1, expected))
assert np.all(np.isclose(result2, expected)) assert np.all(np.isclose(result2, expected))
def test_rmsdev():
t1 = np.eye(4)
t2 = transform.scaleOffsetXform([1, 1, 1], [2, 0, 0])
assert np.isclose(transform.rmsdev(t1, t2), 2)
assert np.isclose(transform.rmsdev(t1, t2, R=2), 2)
assert np.isclose(transform.rmsdev(t1, t2, R=2, xc=(1, 1, 1)), 2)
t1 = np.eye(3)
lastdist = 0
for i in range(1, 11):
rot = np.pi * i / 10.0
t2 = transform.axisAnglesToRotMat(rot, 0, 0)
result = transform.rmsdev(t1, t2)
assert result > lastdist
lastdist = result
for i in range(11, 20):
rot = np.pi * i / 10.0
t2 = transform.axisAnglesToRotMat(rot, 0, 0)
result = transform.rmsdev(t1, t2)
assert result < lastdist
lastdist = result
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment