diff --git a/.circleci/config.yml b/.circleci/config.yml index 849d72a..bbb755d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,48 +1,66 @@ version: 2 jobs: - build: + build_docs: docker: - - image: circleci/python:3.6-jessie + - image: circleci/python:3.7-stretch steps: - # Get our data and merge with upstream - checkout - - run: echo $(git log -1 --pretty=%B) | tee gitlog.txt - - run: echo ${CI_PULL_REQUEST//*pull\//} | tee merge.txt - run: - command: | - if [[ $(cat merge.txt) != "" ]]; then - echo "Merging $(cat merge.txt)"; - git pull --ff-only origin "refs/pull/$(cat merge.txt)/merge"; - fi + name: Set BASH_ENV + command: | + echo "set -e" >> $BASH_ENV; + echo "export SUBJECTS_DIR=~/subjects" >> $BASH_ENV; + echo "export DISPLAY=:99" >> $BASH_ENV; + echo "export OPENBLAS_NUM_THREADS=4" >> $BASH_ENV; + echo "export PATH=~/.local/bin:$PATH" >> $BASH_ENV; + - run: + name: Merge with upstream + command: | + echo $(git log -1 --pretty=%B) | tee gitlog.txt + echo ${CI_PULL_REQUEST//*pull\//} | tee merge.txt + if [[ $(cat merge.txt) != "" ]]; then + echo "Merging $(cat merge.txt)"; + git remote add upstream git://github.com/nipy/PySurfer.git; + git pull --ff-only upstream "refs/pull/$(cat merge.txt)/merge"; + git fetch upstream master; + fi # Load our data - restore_cache: keys: - - data-cache + - data-cache-0 - pip-cache - # Fix libgcc_s.so.1 pthread_cancel bug: + - run: + name: Spin up Xvfb + command: | + /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 1400x900x24 -ac +extension GLX +render -noreset; + # https://github.com/ContinuumIO/anaconda-issues/issues/9190#issuecomment-386508136 # https://github.com/golemfactory/golem/issues/1019 - - run: sudo apt-get install libgl1-mesa-glx libegl1-mesa libxrandr2 libxrandr2 libxss1 libxcursor1 libxcomposite1 libasound2 libxi6 libxtst6 qt5-default - - run: echo "export SUBJECTS_DIR=~/subjects" >> $BASH_ENV - - run: echo "export PATH=~/.local/bin:$PATH" >> $BASH_ENV - - run: echo "export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4200.1" >> $BASH_ENV - # Spin up Xvfb - - run: echo "export DISPLAY=:99" >> $BASH_ENV - - run: /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 1400x900x24 -ac +extension GLX +render -noreset; - # Python env - - run: pip install -U --user --progress-bar off numpy scipy matplotlib vtk PyQt5 sip PyQt5-sip nibabel sphinx numpydoc pillow imageio https://api.github.com/repos/sphinx-gallery/sphinx-gallery/zipball/master - - run: pip install -U --user --progress-bar off mayavi + - run: + name: Fix libgcc_s.so.1 pthread_cancel bug + command: | + sudo apt-get install qt5-default + + - run: + name: Get Python running + command: | + pip install --user -q --upgrade pip numpy + pip install --user -q --upgrade --progress-bar off scipy matplotlib vtk pyqt5 pyqt5-sip nibabel sphinx numpydoc pillow imageio imageio-ffmpeg https://api.github.com/repos/sphinx-gallery/sphinx-gallery/zipball/master mayavi - save_cache: key: pip-cache paths: - - "~/.cache/pip" - - run: python setup.py develop --user - # Check libs - - run: LIBGL_DEBUG=verbose python -c "from mayavi import mlab; import matplotlib.pyplot as plt; mlab.figure(); plt.figure()" - - run: echo $SUBJECTS_DIR + - ~/.cache/pip + + # Look at what we have and fail early if there is some library conflict + - run: + name: Check installation + command: | + LIBGL_DEBUG=verbose python -c "from mayavi import mlab; import matplotlib.pyplot as plt; mlab.figure(); plt.figure()" + echo $SUBJECTS_DIR - run: + name: Get data command: | if [ ! -d $SUBJECTS_DIR ]; then mkdir $SUBJECTS_DIR; @@ -51,14 +69,31 @@ jobs: unzip fsaverage_min.zip; rm fsaverage_min.zip; fi; - - run: ls $SUBJECTS_DIR - - run: cd doc && sphinx-build -D plot_gallery=1 -D sphinx_gallery_conf.filename_pattern=^\(\(?\!plot_fmri_activation_volume\|plot_morphometry\|plot_label\.py\|plot_probabilistic_label\|plot_resting_correlations\|plot_transparent_brain\|rotate_animation\|save_movie\|save_views\).\)*\$ -b html -d _build/doctrees . _build/html + ls $SUBJECTS_DIR + - run: + name: Install PySurfer + command: | + python setup.py develop --user + + - run: + name: Build docs + command: | + cd doc + sphinx-build -D plot_gallery=1 -D sphinx_gallery_conf.filename_pattern=^\(\(?\!plot_fmri_activation_volume\|plot_morphometry\|plot_label\.py\|plot_probabilistic_label\|plot_resting_correlations\|plot_transparent_brain\|rotate_animation\|save_movie\|save_views\).\)*\$ -b html -d _build/doctrees . _build/html - store_artifacts: path: doc/_build/html/ destination: html - save_cache: - key: data-cache + key: data-cache-0 paths: - "~/subjects" + +workflows: + version: 2 + + default: + jobs: + - build_docs + diff --git a/.travis.yml b/.travis.yml index f44bb7c..ed5c16c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,9 @@ language: c sudo: false env: - global: PYTHON_VERSION=3.6 + global: PYTHON_VERSION=3.7 CONDA_DEPENDENCIES="numpy scipy matplotlib pyqt>=5.9 coverage pytest pytest-cov flake8 pygments traits traitsui pyface" - PIP_DEPENDENCIES="codecov pytest-sugar pytest-faulthandler nibabel imageio" + PIP_DEPENDENCIES="codecov pytest-sugar pytest-faulthandler nibabel imageio imageio-ffmpeg" DISPLAY=:99.0 matrix: @@ -57,9 +57,6 @@ before_script: - unzip ../fsaverage_min.zip - cd .. - export SUBJECTS_DIR="${PWD}/subjects" - - if [[ $PIP_DEPENDENCIES == *"imageio"* ]] || [ ! -z "$CONDA_ENVIRONMENT" ]; then - python -c "import imageio; imageio.plugins.ffmpeg.download()"; - fi script: - cd ${SRC_DIR} diff --git a/appveyor.yml b/appveyor.yml index 4a79ae0..39520c5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,9 +6,8 @@ environment: install: - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" - "python --version" - - "pip install numpy scipy matplotlib nose pillow pytest pytest-cov pytest-faulthandler coverage imageio codecov pyqt5==5.9" + - "pip install numpy scipy matplotlib nose pillow pytest pytest-cov pytest-faulthandler coverage imageio imageio-ffmpeg codecov pyqt5==5.9" - "pip install traits traitsui pyface vtk mayavi nibabel" - - "python -c \"import imageio; imageio.plugins.ffmpeg.download()\"" - "powershell make/get_fsaverage.ps1" - "python setup.py develop" - "SET SUBJECTS_DIR=%CD%\\subjects" diff --git a/setup.cfg b/setup.cfg index 133852e..d9bfc29 100644 --- a/setup.cfg +++ b/setup.cfg @@ -8,4 +8,7 @@ filterwarnings = ignore:can't resolve package from __spec__ or __package__, falling back on __name__ and __path__:ImportWarning ignore:The binary mode of fromstring is deprecated, as it behaves surprisingly on unicode inputs. Use frombuffer instead:DeprecationWarning ignore:elementwise == comparison failed:DeprecationWarning - ignore:Matplotlib is building the font cache using fc-list. This may take a moment.:UserWarning \ No newline at end of file + ignore:Importing from numpy:DeprecationWarning + ignore:.*ufunc size changed.*:RuntimeWarning + ignore:Using or importing the ABCs:DeprecationWarning + ignore:Matplotlib is building the font cache using fc-list. This may take a moment.:UserWarning diff --git a/surfer/tests/test_utils.py b/surfer/tests/test_utils.py index 8d71382..d9a6d72 100644 --- a/surfer/tests/test_utils.py +++ b/surfer/tests/test_utils.py @@ -32,12 +32,12 @@ def _slow_compute_normals(rr, tris): @utils.requires_fsaverage() def test_surface(): """Test IO for Surface class""" - subj_dir = utils._get_subjects_dir() + extra, subj_dir = utils._get_extra() for subjects_dir in [None, subj_dir]: surface = utils.Surface('fsaverage', 'lh', 'inflated', subjects_dir=subjects_dir) surface.load_geometry() - surface.load_label('BA1') + surface.load_label('BA1' + extra) surface.load_curvature() xfm = np.eye(4) xfm[:3, -1] += 2 # translation diff --git a/surfer/tests/test_viz.py b/surfer/tests/test_viz.py index 5d534a2..158518d 100644 --- a/surfer/tests/test_viz.py +++ b/surfer/tests/test_viz.py @@ -13,7 +13,8 @@ from unittest import SkipTest from surfer import Brain, io, utils -from surfer.utils import requires_fsaverage, requires_imageio, requires_fs +from surfer.utils import (requires_fsaverage, requires_imageio, requires_fs, + _get_extra) warnings.simplefilter('always') @@ -247,30 +248,30 @@ def test_label(): brain = Brain(subject_id, hemi, surf) view = get_view(brain) - brain.add_label("BA1") + extra, subj_dir = _get_extra() + brain.add_label("BA1" + extra) check_view(brain, view) - brain.add_label("BA1", color="blue", scalar_thresh=.5) - subj_dir = utils._get_subjects_dir() + brain.add_label("BA1" + extra, color="blue", scalar_thresh=.5) label_file = pjoin(subj_dir, subject_id, - "label", "%s.MT.label" % hemi) + "label", "%s.MT%s.label" % (hemi, extra)) brain.add_label(label_file) - brain.add_label("BA44", borders=True) - brain.add_label("BA6", alpha=.7) + brain.add_label("BA44" + extra, borders=True) + brain.add_label("BA6" + extra, alpha=.7) brain.show_view("medial") - brain.add_label("V1", color="steelblue", alpha=.6) - brain.add_label("V2", color="#FF6347", alpha=.6) - brain.add_label("entorhinal", color=(.2, 1, .5), alpha=.6) + brain.add_label("V1" + extra, color="steelblue", alpha=.6) + brain.add_label("V2" + extra, color="#FF6347", alpha=.6) + brain.add_label("entorhinal" + extra, color=(.2, 1, .5), alpha=.6) brain.set_surf('white') brain.show_view(dict(elevation=40, distance=430), distance=430) with pytest.raises(ValueError, match='!='): brain.show_view(dict(elevation=40, distance=430), distance=431) # remove labels - brain.remove_labels('V1') - assert 'V2' in brain.labels_dict - assert 'V1' not in brain.labels_dict + brain.remove_labels('V1' + extra) + assert 'V2' + extra in brain.labels_dict + assert 'V1' + extra not in brain.labels_dict brain.remove_labels() - assert 'V2' not in brain.labels_dict + assert 'V2' + extra not in brain.labels_dict brain.close() @@ -354,7 +355,8 @@ def test_morphometry(): def test_movie(tmpdir): """Test saving a movie of an MEG inverse solution.""" import imageio - + if sys.version_info < (3,): + raise SkipTest('imageio ffmpeg requires Python 3') # create and setup the Brain instance _set_backend() brain = Brain(*std_args) @@ -432,15 +434,15 @@ def test_probabilistic_labels(): brain = Brain("fsaverage", "lh", "inflated", cortex="low_contrast") - brain.add_label("BA1", color="darkblue") - - brain.add_label("BA1", color="dodgerblue", scalar_thresh=.5) + extra, subj_dir = _get_extra() + brain.add_label("BA1" + extra, color="darkblue") + brain.add_label("BA1" + extra, color="dodgerblue", scalar_thresh=.5) + brain.add_label("BA45" + extra, color="firebrick", borders=True) + brain.add_label("BA45" + extra, color="salmon", borders=True, + scalar_thresh=.5) - brain.add_label("BA45", color="firebrick", borders=True) - brain.add_label("BA45", color="salmon", borders=True, scalar_thresh=.5) - - subj_dir = utils._get_subjects_dir() - label_file = pjoin(subj_dir, "fsaverage", "label", "lh.BA6.label") + label_file = pjoin(subj_dir, "fsaverage", "label", + "lh.BA6%s.label" % (extra,)) prob_field = np.zeros_like(brain.geo['lh'].x) ids, probs = nib.freesurfer.read_label(label_file, read_scalars=True) prob_field[ids] = probs diff --git a/surfer/utils.py b/surfer/utils.py index cd2b9f3..8e3e22c 100644 --- a/surfer/utils.py +++ b/surfer/utils.py @@ -745,3 +745,10 @@ def requires_fs(): has = ('FREESURFER_HOME' in os.environ) return pytest.mark.skipif( not has, reason='Requires FreeSurfer command line tools') + + +def _get_extra(): + # Get extra label for newer freesurfer + subj_dir = _get_subjects_dir() + fname = op.join(subj_dir, 'fsaverage', 'label', 'lh.BA1.label') + return '_exvivo' if not op.isfile(fname) else '', subj_dir diff --git a/surfer/viz.py b/surfer/viz.py index 75eab52..4fcde5d 100644 --- a/surfer/viz.py +++ b/surfer/viz.py @@ -208,7 +208,7 @@ def _make_viewer(figure, n_row, n_col, title, scene_size, offscreen, try: mlab.options.offscreen = True with warnings.catch_warnings(record=True): # traits - figures = [[mlab.figure(size=(h / n_row, w / n_col)) + figures = [[mlab.figure(size=(w / n_col, h / n_row)) for _ in range(n_col)] for __ in range(n_row)] finally: mlab.options.offscreen = orig_val