diff --git a/.circleci/config.yml b/.circleci/config.yml
index 95000f104e..9ec84ad53f 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -15,6 +15,7 @@ jobs:
NUMPY_VERSION: "*"
SCIPY_VERSION: "*"
SCIKIT_LEARN_VERSION: "*"
+ JOBLIB_VERSION: "*"
MATPLOTLIB_VERSION: "*"
steps:
diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000000..5e2d545938
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,5 @@
+[run]
+branch = True
+parallel = True
+omit =
+ */nilearn/externals/*
diff --git a/.travis.yml b/.travis.yml
index 0a6b0a866c..e63407049c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,49 +2,58 @@ sudo: required
dist: xenial
language: python
-python: "3.5"
-
-virtualenv:
- system_site_packages: true
env:
global:
- - TEST_RUN_FOLDER="/tmp" # folder where the tests are run from
+ - TEST_RUN_FOLDER="/tmp"
matrix:
# Do not wait for the allowed_failures entry to finish before
# setting the status
fast_finish: true
allow_failures:
- # allow_failures seems to be keyed on the python version.
- - python: 3.5
+ # allow_failures keyed to python 3.5 & skipping tests.
+ - python: "3.5"
+ env: DISTRIB="travisci" PYTHON_VERSION="3.5" FLAKE8_VERSION="*" SKIP_TESTS="true"
include:
- # without matplotlib
- - env: DISTRIB="conda" PYTHON_VERSION="3.5"
+ - name: "Python 3.5 minimum package versions without Matplotlib"
+ python: "3.5"
+ env: DISTRIB="travisci" PYTHON_VERSION="3.5"
NUMPY_VERSION="1.11" SCIPY_VERSION="0.19" PANDAS_VERSION="*"
- SCIKIT_LEARN_VERSION="0.19" COVERAGE="true"
+ SCIKIT_LEARN_VERSION="0.19" COVERAGE="true" JOBLIB_VERSION="0.11"
LXML_VERSION="*"
- - env: DISTRIB="conda" PYTHON_VERSION="3.5"
+ - name: "Python 3.5 latest package versions"
+ python: "3.5"
+ env: DISTRIB="travisci" PYTHON_VERSION="3.5"
NUMPY_VERSION="*" SCIPY_VERSION="*" PANDAS_VERSION="*"
SCIKIT_LEARN_VERSION="*" MATPLOTLIB_VERSION="*" COVERAGE="true"
+ JOBLIB_VERSION="0.11"
LXML_VERSION="*"
- - env: DISTRIB="conda" PYTHON_VERSION="3.6"
+ - name: "Python 3.6 latest package versions"
+ python: "3.6"
+ env: DISTRIB="travisci" PYTHON_VERSION="3.6"
NUMPY_VERSION="*" SCIPY_VERSION="*" PANDAS_VERSION="*"
SCIKIT_LEARN_VERSION="*" MATPLOTLIB_VERSION="*" COVERAGE="true"
- LXML_VERSION="*"
- - env: DISTRIB="conda" PYTHON_VERSION="3.7"
+ JOBLIB_VERSION="0.12" LXML_VERSION="*"
+ # joblib.Memory switches from keyword cachedir to location in version 0.12
+ # Making sure we get the deprecation warning.
+
+ - name: "Python 3.7 latest package versions"
+ python: "3.7"
+ env: DISTRIB="travisci" PYTHON_VERSION="3.7"
NUMPY_VERSION="*" SCIPY_VERSION="*" PANDAS_VERSION="*"
SCIKIT_LEARN_VERSION="*" MATPLOTLIB_VERSION="*" COVERAGE="true"
- LXML_VERSION="*"
+ JOBLIB_VERSION="*" LXML_VERSION="*"
# FLAKE8 linting on diff wrt common ancestor with upstream/master
# Note: the python value is only there to trigger allow_failures
- - python: 3.5
- env: DISTRIB="conda" PYTHON_VERSION="3.5" FLAKE8_VERSION="*" SKIP_TESTS="true"
+ - name: Python 3.5 Flake8 no tests
+ python: "3.5"
+ env: DISTRIB="travisci" PYTHON_VERSION="3.5" FLAKE8_VERSION="*" SKIP_TESTS="true"
install: source continuous_integration/install.sh
-before_script: make clean
+before_script: make clean
script: source continuous_integration/test_script.sh
diff --git a/AUTHORS.rst b/AUTHORS.rst
index c67751492c..ed04bc5d1a 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -3,38 +3,36 @@
People
------
-This work is made available by a community of people, amongst which
+This work is made available by a community of people, which
+originated from
the `INRIA Parietal Project Team `_
-and the `scikit-learn `_ folks, in
-particular:
-
-* Alexandre Abraham
-* `Alexandre Gramfort `_
-* Vincent Michel
-* Bertrand Thirion
-* `Fabian Pedregosa `_
-* `Gael Varoquaux `_
-* Philippe Gervais
-* Michael Eickenberg
-* Danilo Bzdok
-* Loïc Estève
-* Kamalakar Reddy Daddy
-* Elvis Dohmatob
-* Alexandre Abadie
-* Andres Hoyos Idrobo
-* Salma Bougacha
-* Mehdi Rahim
-* Sylvain Lanuzel
-* `Kshitij Chawla `_
-
-Many of also contributed outside of Parietal, notably:
-
-* `Chris Filo Gorgolewski `_
-* `Ben Cipollini `_
-* Julia Huntenburg
-* Martin Perez-Guevara
-
-Thanks to M. Hanke and Y. Halchenko for data and packaging.
+and the `scikit-learn `_ but grew much further.
+
+An up-to-date list of contributors can be seen in on `gitub
+`_
+
+Additional credit goes to M. Hanke and Y. Halchenko for data and packaging.
+
+.. _core_devs:
+
+Core developers
+.................
+
+The nilearn core developers are:
+
+* Alexandre Gramfort https://github.com/agramfort
+* Ben Cipollini https://github.com/bcipolli
+* Bertrand Thirion https://github.com/bthirion
+* Chris Gorgolewski https://github.com/chrisgorgo
+* Danilo Bzdok https://github.com/banilo
+* Elizabeth DuPre https://github.com/emdupre
+* Gael Varoquaux https://github.com/GaelVaroquaux
+* Jerome Dockes https://github.com/jeromedockes
+* Julia Huntenburg https://github.com/juhuntenburg
+* KamalakerDadi https://github.com/KamalakerDadi
+* Kshitij Chawla https://github.com/kchawla-pi
+* Medhi Rahim https://github.com/mrahim
+* Salma Bougacha https://github.com/salma1601
Funding
........
@@ -45,7 +43,8 @@ Mehdi Rahim, Philippe Gervais where payed by the `NiConnect
project, funded by the French `Investissement d'Avenir
`_.
-NiLearn is also supported by `DigiCosme `_ |digicomse logo|
+NiLearn is also supported by `DigiCosme `_
+|digicosme logo| and `DataIA `_ |dataia_logo|.
.. _citing:
@@ -74,6 +73,10 @@ See the scikit-learn documentation on `how to cite
`_.
-.. |digicomse logo| image:: logos/digi-saclay-logo-small.png
+.. |digicosme logo| image:: logos/digi-saclay-logo-small.png
+ :height: 25
+ :alt: DigiComse Logo
+
+.. |dataia_logo| image:: logos/dataia.png
:height: 25
- :alt: DigiComse Logo
\ No newline at end of file
+ :alt: DataIA Logo
diff --git a/Makefile b/Makefile
index 15d6f8d4dd..ec14caa46b 100644
--- a/Makefile
+++ b/Makefile
@@ -4,9 +4,6 @@
PYTHON ?= python
CYTHON ?= cython
-NOSETESTS ?= nosetests
-NOSETESTS_OPTIONS := $(shell pip list | grep nose-timer > /dev/null && \
- echo '--with-timer --timer-top-n 50')
CTAGS ?= ctags
all: clean test doc-noplot
@@ -32,15 +29,15 @@ inplace:
$(PYTHON) setup.py build_ext -i
test-code:
- $(NOSETESTS) -s nilearn $(NOSETESTS_OPTIONS)
+ python -m pytest --pyargs nilearn --cov=nilearn
+
test-doc:
- $(NOSETESTS) -s --with-doctest --doctest-tests --doctest-extension=rst \
- --doctest-extension=inc --doctest-fixtures=_fixture `find doc/ -name '*.rst'`
+ pytest --doctest-glob='*.rst' `find doc/ -name '*.rst'`
+
test-coverage:
rm -rf coverage .coverage
- $(NOSETESTS) -s --with-coverage --cover-html --cover-html-dir=coverage \
- --cover-package=nilearn nilearn
+ pytest --pyargs nilearn --showlocals --cov=nilearn --cov-report=html:coverage
test: test-code test-doc
@@ -66,4 +63,3 @@ doc:
.PHONY : pdf
pdf:
make -C doc pdf
-
diff --git a/README.rst b/README.rst
index f2d1b50d36..e2f42830a9 100644
--- a/README.rst
+++ b/README.rst
@@ -43,6 +43,7 @@ The required dependencies to use the software are:
* Numpy >= 1.11
* SciPy >= 0.19
* Scikit-learn >= 0.19
+* Joblib >= 0.11
* Nibabel >= 2.0.2
If you are using nilearn plotting functionalities or running the
diff --git a/appveyor.yml b/appveyor.yml
index 605c79581b..ed77a89874 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -24,10 +24,10 @@ install:
# See similar fix which made for travis and circleci
# https://github.com/nilearn/nilearn/pull/1525
# Should be removed after a new matplotlib release 2.1.1
- - "conda install pip numpy scipy scikit-learn nose wheel matplotlib -y -q"
+ - "conda install pip numpy scipy scikit-learn joblib nose pytest wheel matplotlib -y -q"
# Install other nilearn dependencies
- - "pip install nibabel coverage nose-timer"
+ - "pip install nibabel coverage nose-timer pytest-cov"
- "python setup.py bdist_wheel"
- ps: "ls dist"
@@ -41,7 +41,7 @@ test_script:
# Change to a non-source folder to make sure we run the tests on the
# installed library.
- "cd C:\\"
- - "python -c \"import nose; nose.main()\" -v -s nilearn --with-timer --timer-top-n 50"
+ - "pytest --pyargs nilearn -v"
artifacts:
# Archive the generated packages in the ci.appveyor.com build report.
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 4601af26a9..5ae4de4c1a 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -30,7 +30,7 @@ jobs:
- script: |
pip install .
- nosetests ./nilearn -v
+ pytest ./nilearn -v
displayName: 'test'
- task: PublishTestResults@2
diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 0000000000..9fd6de2da3
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,2 @@
+ignore:
+ - "*externals/.*" # ignore folders and all its contents
diff --git a/continuous_integration/install.sh b/continuous_integration/install.sh
index 43ef8eaf4b..a387010a74 100755
--- a/continuous_integration/install.sh
+++ b/continuous_integration/install.sh
@@ -22,21 +22,20 @@ create_new_venv() {
deactivate
virtualenv --system-site-packages testvenv
source testvenv/bin/activate
- pip install nose
+ pip install nose pytest
}
-print_conda_requirements() {
- # Echo a conda requirement string for example
+echo_requirements_string() {
+ # Echo a requirement string for example
# "pip nose python='2.7.3 scikit-learn=*". It has a hardcoded
# list of possible packages to install and looks at _VERSION
# environment variables to know whether to install a given package and
# if yes which version to install. For example:
# - for numpy, NUMPY_VERSION is used
# - for scikit-learn, SCIKIT_LEARN_VERSION is used
- TO_INSTALL_ALWAYS="pip nose"
+ TO_INSTALL_ALWAYS="pip nose pytest"
REQUIREMENTS="$TO_INSTALL_ALWAYS"
- TO_INSTALL_MAYBE="python numpy scipy matplotlib scikit-learn pandas \
-flake8 lxml"
+ TO_INSTALL_MAYBE="numpy scipy matplotlib scikit-learn pandas flake8 lxml joblib"
for PACKAGE in $TO_INSTALL_MAYBE; do
# Capitalize package name and add _VERSION
PACKAGE_VERSION_VARNAME="${PACKAGE^^}_VERSION"
@@ -45,44 +44,25 @@ flake8 lxml"
# dereference $PACKAGE_VERSION_VARNAME to figure out the
# version to install
PACKAGE_VERSION="${!PACKAGE_VERSION_VARNAME}"
- if [ -n "$PACKAGE_VERSION" ]; then
- REQUIREMENTS="$REQUIREMENTS $PACKAGE=$PACKAGE_VERSION"
+ if [[ -n "$PACKAGE_VERSION" ]]; then
+ if [[ "$PACKAGE_VERSION" == "*" ]]; then
+ REQUIREMENTS="$REQUIREMENTS $PACKAGE"
+ else
+ REQUIREMENTS="$REQUIREMENTS $PACKAGE==$PACKAGE_VERSION"
+ fi
fi
done
echo $REQUIREMENTS
}
-create_new_conda_env() {
- # Skip Travis related code on circle ci.
- if [ -z $CIRCLECI ]; then
- # Deactivate the travis-provided virtual environment and setup a
- # conda-based environment instead
- deactivate
- fi
-
- # Use the miniconda installer for faster download / install of conda
- # itself
- wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh \
- -O ~/miniconda.sh
- chmod +x ~/miniconda.sh && ~/miniconda.sh -b
- export PATH=$HOME/miniconda3/bin:$PATH
- echo $PATH
-
- # Configure the conda environment and put it in the path using the
- # provided versions
- REQUIREMENTS=$(print_conda_requirements)
- echo "conda requirements string: $REQUIREMENTS"
- conda create -n testenv --quiet --yes $REQUIREMENTS
- source activate testenv
+create_new_travisci_env() {
+ REQUIREMENTS=$(echo_requirements_string)
+ pip install ${REQUIREMENTS}
+ pip install pytest pytest-cov
if [[ "$INSTALL_MKL" == "true" ]]; then
# Make sure that MKL is used
- conda install --quiet --yes mkl
- elif [[ -z $CIRCLECI ]]; then
- # Travis doesn't use MKL but circle ci does for speeding up examples
- # generation in the html documentation.
- # Make sure that MKL is not used
- conda remove --yes --features mkl || echo "MKL not installed"
+ pip install mkl
fi
}
@@ -90,16 +70,16 @@ if [[ "$DISTRIB" == "neurodebian" ]]; then
create_new_venv
pip install nose-timer
bash <(wget -q -O- http://neuro.debian.net/_files/neurodebian-travis.sh)
- sudo apt-get install -qq python-scipy python-nose python-nibabel python-sklearn
+ sudo apt-get install -qq python-scipy python-nose python-nibabel python-sklearn python-joblib
-elif [[ "$DISTRIB" == "conda" ]]; then
- create_new_conda_env
+elif [[ "$DISTRIB" == "travisci" ]]; then
+ create_new_travisci_env
pip install nose-timer
# Note: nibabel is in setup.py install_requires so nibabel will
# always be installed eventually. Defining NIBABEL_VERSION is only
# useful if you happen to want a specific nibabel version rather
# than the latest available one.
- if [ -n "$NIBABEL_VERSION" ]; then
+ if [[ -n "$NIBABEL_VERSION" ]]; then
pip install nibabel=="$NIBABEL_VERSION"
fi
diff --git a/continuous_integration/show-python-packages-versions.py b/continuous_integration/show-python-packages-versions.py
index 1822dd172e..3c2f3319a3 100644
--- a/continuous_integration/show-python-packages-versions.py
+++ b/continuous_integration/show-python-packages-versions.py
@@ -1,6 +1,6 @@
import sys
-DEPENDENCIES = ['numpy', 'scipy', 'sklearn', 'matplotlib', 'nibabel']
+DEPENDENCIES = ['numpy', 'scipy', 'sklearn', 'joblib', 'matplotlib', 'nibabel']
def print_package_version(package_name, indent=' '):
diff --git a/continuous_integration/test_script.sh b/continuous_integration/test_script.sh
index 1dfa2578d1..4fbb32ba2e 100755
--- a/continuous_integration/test_script.sh
+++ b/continuous_integration/test_script.sh
@@ -11,6 +11,7 @@ if [[ "$SKIP_TESTS" != "true" ]]; then
# Copy setup.cfg to TEST_RUN_FOLDER where we are going to run the tests from
# Mainly for nose config settings
cp setup.cfg "$TEST_RUN_FOLDER"
+ cp .coveragerc "$TEST_RUN_FOLDER"
# We want to back out of the current working directory to make
# sure we are using nilearn installed in site-packages rather
# than the one from the current working directory
diff --git a/doc/conf.py b/doc/conf.py
index 3f88540004..392ccb353d 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -281,13 +281,18 @@
_python_doc_base = 'http://docs.python.org/3.6'
+# Scraper, copied from https://github.com/mne-tools/mne-python/
+from nilearn.reporting import _ReportScraper
+report_scraper = _ReportScraper()
+scrapers = ('matplotlib', report_scraper)
+
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {
'python': (_python_doc_base, None),
'numpy': ('http://docs.scipy.org/doc/numpy', None),
'scipy': ('http://docs.scipy.org/doc/scipy/reference', None),
'matplotlib': ('http://matplotlib.org/', None),
- 'sklearn': ('http://scikit-learn.org/0.18', None),
+ 'sklearn': ('http://scikit-learn.org/stable/', None),
'nibabel': ('http://nipy.org/nibabel', None),
'pandas': ('http://pandas.pydata.org', None),
}
@@ -302,6 +307,7 @@
'backreferences_dir': os.path.join('modules', 'generated'),
'reference_url': {'nilearn': None},
'junit': '../test-results/sphinx-gallery/junit.xml',
+ 'image_scrapers': scrapers,
}
# Get rid of spurious warnings due to some interaction between
@@ -310,7 +316,6 @@
# details
numpydoc_show_class_members = False
-
def touch_example_backreferences(app, what, name, obj, options, lines):
# generate empty examples files, so that we don't get
# inclusion errors if there are no examples for a class / module
@@ -327,3 +332,4 @@ def touch_example_backreferences(app, what, name, obj, options, lines):
def setup(app):
app.add_javascript('copybutton.js')
app.connect('autodoc-process-docstring', touch_example_backreferences)
+ report_scraper.app = app
diff --git a/doc/connectivity/connectome_extraction.rst b/doc/connectivity/connectome_extraction.rst
index 6707f081d4..fb62356326 100644
--- a/doc/connectivity/connectome_extraction.rst
+++ b/doc/connectivity/connectome_extraction.rst
@@ -49,12 +49,12 @@ conditioned on all the others.
To recover well the interaction structure, a **sparse inverse covariance
-estimator** is necessary. The GraphLasso, implemented in scikit-learn's
-estimator :class:`sklearn.covariance.GraphLassoCV` is a good, simple
+estimator** is necessary. The GraphicalLasso, implemented in scikit-learn's
+estimator :class:`sklearn.covariance.GraphicalLassoCV` is a good, simple
solution. To use it, you need to create an estimator object::
- >>> from sklearn.covariance import GraphLassoCV
- >>> estimator = GraphLassoCV()
+ >>> from sklearn.covariance import GraphicalLassoCV
+ >>> estimator = GraphicalLassoCV()
And then you can fit it on the activation time series, for instance
extracted in :ref:`the previous section `::
@@ -95,7 +95,7 @@ of the estimator::
The parameter controlling the sparsity is set by `cross-validation
`_
scheme. If you want to specify it manually, use the estimator
- :class:`sklearn.covariance.GraphLasso`.
+ :class:`sklearn.covariance.GraphicalLasso`.
.. topic:: **Full example**
@@ -126,7 +126,7 @@ differing connection values across subjects.
For this, nilearn provides the
:class:`nilearn.connectome.GroupSparseCovarianceCV`
-estimator. Its usage is similar to the GraphLassoCV object, but it takes
+estimator. Its usage is similar to the GraphicalLassoCV object, but it takes
a list of time series::
>>> estimator.fit([time_series_1, time_series_2, ...]) # doctest: +SKIP
@@ -186,7 +186,7 @@ with different precision matrices, but sharing a common sparsity pattern:
10 brain regions, for 20 subjects.
A single-subject estimation can be performed using the
-:class:`sklearn.covariance.GraphLassoCV` estimator from scikit-learn.
+:class:`sklearn.covariance.GraphicalLassoCV` estimator from scikit-learn.
It is also possible to fit a graph lasso on data from every subject all
together.
diff --git a/doc/developers/group_sparse_covariance.rst b/doc/developers/group_sparse_covariance.rst
index 56e15e1c45..b95eadf867 100644
--- a/doc/developers/group_sparse_covariance.rst
+++ b/doc/developers/group_sparse_covariance.rst
@@ -369,7 +369,7 @@ used), then a tighter grid near the found maximum is computed, and so
on. This allows for a very precise determination of the maximum
location while reducing a lot the required evaluation number. The code
is very close to what is done in
-:class:`sklearn.covariance.GraphLassoCV`.
+:class:`sklearn.covariance.GraphicalLassoCV`.
Warm restart
diff --git a/doc/development.rst b/doc/development.rst
index a0ea29cdd6..4edac4347f 100644
--- a/doc/development.rst
+++ b/doc/development.rst
@@ -122,12 +122,9 @@ Decisions are made public, through discussion on issues and pull requests
in Github.
The decisions are made by the core-contributors, ie people with write
-access to the repository, as listed `here
-`__
+access to the repository, as listed :ref:`here `
If there are open questions, final decisions are made by the Temporary
Benevolent Dictator, currently Gaël Varoquaux.
-
-
.. include:: ../CONTRIBUTING.rst
diff --git a/doc/images/niftimasker_report.png b/doc/images/niftimasker_report.png
new file mode 100644
index 0000000000..664469b9a3
Binary files /dev/null and b/doc/images/niftimasker_report.png differ
diff --git a/doc/images/niftimasker_report_params.png b/doc/images/niftimasker_report_params.png
new file mode 100644
index 0000000000..7528695bcf
Binary files /dev/null and b/doc/images/niftimasker_report_params.png differ
diff --git a/doc/install_doc_component.html b/doc/install_doc_component.html
index c6584d3961..d1e97934b9 100644
--- a/doc/install_doc_component.html
+++ b/doc/install_doc_component.html
@@ -53,7 +53,8 @@
as an alternative.
Nilearn requires a Python installation and the following
- dependencies: ipython, scipy, scikit-learn, matplotlib and nibabel.
+ dependencies: ipython, scipy, scikit-learn, joblib, matplotlib
+ and nibabel.
Nilearn requires a Python installation and the following
- dependencies: ipython, scipy, scikit-learn, matplotlib and nibabel.
+ dependencies: ipython, scipy, scikit-learn, joblib,
+ matplotlib and nibabel.
(Navigate to /Applications/Utilities and double-click on
@@ -114,7 +116,8 @@
Install or ask your system administrator to install the following
packages using the distribution package manager: ipython
, scipy, scikit-learn (sometimes called sklearn,
- or python-sklearn), matplotlib (sometimes
+ or python-sklearn), joblib,
+ matplotlib (sometimes
called python-matplotlib) and nibabel
(sometimes called python-nibabel).
diff --git a/doc/logos/dataia.png b/doc/logos/dataia.png
new file mode 100644
index 0000000000..fae26199d3
Binary files /dev/null and b/doc/logos/dataia.png differ
diff --git a/doc/manipulating_images/masker_objects.rst b/doc/manipulating_images/masker_objects.rst
index fa77719bda..dc2f06dafd 100644
--- a/doc/manipulating_images/masker_objects.rst
+++ b/doc/manipulating_images/masker_objects.rst
@@ -136,12 +136,25 @@ mask computation parameters.
The mask can be retrieved and visualized from the `mask_img_` attribute
of the masker:
+.. literalinclude:: ../../examples/04_manipulating_images/plot_mask_computation.py
+ :start-after: # A NiftiMasker with the default strategy
+ :end-before: # Plot the generated mask using the .generate_report method
+
+.. figure:: ../auto_examples/04_manipulating_images/images/sphx_glr_plot_mask_computation_002.png
+ :target: ../auto_examples/04_manipulating_images/plot_mask_computation.html
+ :align: center
+ :scale: 40
+
+Alternatively, the mask can be visualized using the `generate_report`
+method of the masker. The generated report can be viewed in a Jupyter notebook,
+opened in a new browser tab using `report.open_in_browser()`,
+or saved as a portable HTML file `report.save_as_html(output_filepath)`.
+
.. literalinclude:: ../../examples/04_manipulating_images/plot_mask_computation.py
:start-after: # We need to specify an 'epi' mask_strategy, as this is raw EPI data
:end-before: # Generate mask with strong opening
-
-.. figure:: ../auto_examples/04_manipulating_images/images/sphx_glr_plot_mask_computation_004.png
+.. figure:: /images/niftimasker_report.png
:target: ../auto_examples/04_manipulating_images/plot_mask_computation.html
:scale: 50%
@@ -163,7 +176,7 @@ Controling these arguments set the fine aspects of the mask. See the
functions documentation, or :doc:`the NiftiMasker example
<../auto_examples/04_manipulating_images/plot_mask_computation>`.
-.. figure:: ../auto_examples/04_manipulating_images/images/sphx_glr_plot_mask_computation_005.png
+.. figure:: /images/niftimasker_report_params.png
:target: ../auto_examples/04_manipulating_images/plot_mask_computation.html
:scale: 50%
@@ -180,9 +193,10 @@ preparation::
>>> masker # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
NiftiMasker(detrend=False, dtype=None, high_pass=None, low_pass=None,
mask_args=None, mask_img=None, mask_strategy='background',
- memory=Memory(...), memory_level=1, sample_mask=None,
- sessions=None, smoothing_fwhm=None, standardize=False, t_r=None,
- target_affine=None, target_shape=None, verbose=0)
+ memory=Memory(...), memory_level=1, reports=True,
+ sample_mask=None, sessions=None, smoothing_fwhm=None,
+ standardize=False, t_r=None, target_affine=None, target_shape=None,
+ verbose=0)
.. note::
@@ -234,7 +248,7 @@ Temporal Filtering and confound removal
properties, before conversion to voxel signals.
- **Standardization**. Parameter ``standardize``: Signals can be
- standardized (scaled to unit variance).
+ standardized (scaled to unit variance).
- **Frequency filtering**. Low-pass and high-pass filters can be used to
remove artifacts. Parameters: ``high_pass`` and ``low_pass``, specified
@@ -242,7 +256,7 @@ properties, before conversion to voxel signals.
the ``t_r`` parameter: ``loss_pass=.5, t_r=2.1``).
- **Confound removal**. Two ways of removing confounds are provided: simple
- detrending or using prespecified confounds, such as behavioral or movement
+ detrending or using prespecified confounds, such as behavioral or movement
information.
* Linear trends can be removed by activating the `detrend` parameter.
@@ -251,7 +265,7 @@ properties, before conversion to voxel signals.
signal of interest (e.g., the neural correlates of cognitive tasks).
It is not activated by default in :class:`NiftiMasker` but is recommended
in almost all scenarios.
-
+
* More complex confounds, measured during the acquision, can be removed
by passing them to :meth:`NiftiMasker.transform`. If the dataset
provides a confounds file, just pass its path to the masker.
diff --git a/doc/themes/nilearn/static/nature.css_t b/doc/themes/nilearn/static/nature.css_t
index 6d5c73b8ff..7397860e39 100644
--- a/doc/themes/nilearn/static/nature.css_t
+++ b/doc/themes/nilearn/static/nature.css_t
@@ -1689,3 +1689,22 @@ ul#tab li div.contents p{
p.sphx-glr-horizontal {
margin-top: 2em;
}
+
+
+/* Sphinx-gallery Report embedding */
+div.sg-report {
+ padding: 0pt;
+ transform: scale(.95);
+}
+
+div.sg-report iframe {
+ display: block;
+ border-style: none;
+ transform: scale(.85);
+ height: 470px;
+ margin-left: -12%; /* Negative because of .8 scaling */
+ margin-top: -4%;
+ padding: 0pt;
+ margin-bottom: 0pt;
+ width: 126%; /* More than 100% because of .8 scaling */
+}
diff --git a/doc/themes/nilearn/static/sphinxdoc.css b/doc/themes/nilearn/static/sphinxdoc.css
deleted file mode 100644
index b680a95710..0000000000
--- a/doc/themes/nilearn/static/sphinxdoc.css
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * sphinxdoc.css_t
- * ~~~~~~~~~~~~~~~
- *
- * Sphinx stylesheet -- sphinxdoc theme. Originally created by
- * Armin Ronacher for Werkzeug.
- *
- * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
- * :license: BSD, see LICENSE for details.
- *
- */
-
-@import url("basic.css");
-
-/* -- page layout ----------------------------------------------------------- */
-
-body {
- font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
- 'Verdana', sans-serif;
- font-size: 14px;
- letter-spacing: -0.01em;
- line-height: 150%;
- text-align: center;
- background-color: #BFD1D4;
- color: black;
- padding: 0;
- border: 1px solid #aaa;
-
- margin: 0px 80px 0px 80px;
- min-width: 740px;
-}
-
-div.document {
- background-color: white;
- text-align: left;
- background-image: url(contents.png);
- background-repeat: repeat-x;
-}
-
-div.bodywrapper {
- margin: 0 240px 0 0;
- border-right: 1px solid #ccc;
-}
-
-div.body {
- margin: 0;
- padding: 0.5em 20px 20px 20px;
-}
-
-div.related {
- font-size: 1em;
-}
-
-div.related ul {
- background-image: url(navigation.png);
- height: 2em;
- border-top: 1px solid #ddd;
- border-bottom: 1px solid #ddd;
-}
-
-div.related ul li {
- margin: 0;
- padding: 0;
- height: 2em;
- float: left;
-}
-
-div.related ul li.right {
- float: right;
- margin-right: 5px;
-}
-
-div.related ul li a {
- margin: 0;
- padding: 0 5px 0 5px;
- line-height: 1.75em;
- color: #EE9816;
-}
-
-div.related ul li a:hover {
- color: #3CA8E7;
-}
-
-div.sphinxsidebarwrapper {
- padding: 0;
-}
-
-div.sphinxsidebar {
- margin: 0;
- padding: 0.5em 15px 15px 0;
- width: 210px;
- float: right;
- font-size: 1em;
- text-align: left;
-}
-
-div.sphinxsidebar h3, div.sphinxsidebar h4 {
- margin: 1em 0 0.5em 0;
- font-size: 1em;
- padding: 0.1em 0 0.1em 0.5em;
- color: white;
- border: 1px solid #86989B;
- background-color: #AFC1C4;
-}
-
-div.sphinxsidebar h3 a {
- color: white;
-}
-
-div.sphinxsidebar ul {
- padding-left: 1.5em;
- margin-top: 7px;
- padding: 0;
- line-height: 130%;
-}
-
-div.sphinxsidebar ul ul {
- margin-left: 20px;
-}
-
-div.footer {
- background-color: #E3EFF1;
- color: #86989B;
- padding: 3px 8px 3px 0;
- clear: both;
- font-size: 0.8em;
- text-align: right;
-}
-
-div.footer a {
- color: #86989B;
- text-decoration: underline;
-}
-
-/* -- body styles ----------------------------------------------------------- */
-
-p {
- margin: 0.8em 0 0.5em 0;
-}
-
-a {
- color: #CA7900;
- text-decoration: none;
-}
-
-a:hover {
- color: #2491CF;
-}
-
-div.body a {
- text-decoration: underline;
-}
-
-h1 {
- margin: 0;
- padding: 0.7em 0 0.3em 0;
- font-size: 1.5em;
- color: #11557C;
-}
-
-h2 {
- margin: 1.3em 0 0.2em 0;
- font-size: 1.35em;
- padding: 0;
-}
-
-h3 {
- margin: 1em 0 -0.3em 0;
- font-size: 1.2em;
-}
-
-div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
- color: black!important;
-}
-
-h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
- display: none;
- margin: 0 0 0 0.3em;
- padding: 0 0.2em 0 0.2em;
- color: #aaa!important;
-}
-
-h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
-h5:hover a.anchor, h6:hover a.anchor {
- display: inline;
-}
-
-h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
-h5 a.anchor:hover, h6 a.anchor:hover {
- color: #777;
- background-color: #eee;
-}
-
-a.headerlink {
- color: #c60f0f!important;
- font-size: 1em;
- margin-left: 6px;
- padding: 0 4px 0 4px;
- text-decoration: none!important;
-}
-
-a.headerlink:hover {
- background-color: #ccc;
- color: white!important;
-}
-
-cite, code, tt {
- font-family: 'Consolas', 'Deja Vu Sans Mono',
- 'Bitstream Vera Sans Mono', monospace;
- font-size: 0.95em;
- letter-spacing: 0.01em;
-}
-
-tt {
- background-color: #f2f2f2;
- border-bottom: 1px solid #ddd;
- color: #333;
-}
-
-tt.descname, tt.descclassname, tt.xref {
- border: 0;
-}
-
-hr {
- border: 1px solid #abc;
- margin: 2em;
-}
-
-a tt {
- border: 0;
- color: #CA7900;
-}
-
-a tt:hover {
- color: #2491CF;
-}
-
-pre {
- font-family: 'Consolas', 'Deja Vu Sans Mono',
- 'Bitstream Vera Sans Mono', monospace;
- font-size: 0.95em;
- letter-spacing: 0.015em;
- line-height: 120%;
- padding: 0.5em;
- border: 1px solid #ccc;
- background-color: #f8f8f8;
-}
-
-pre a {
- color: inherit;
- text-decoration: underline;
-}
-
-td.linenos pre {
- padding: 0.5em 0;
-}
-
-div.quotebar {
- background-color: #f8f8f8;
- max-width: 250px;
- float: right;
- padding: 2px 7px;
- border: 1px solid #ccc;
-}
-
-div.topic {
- background-color: #f8f8f8;
-}
-
-table {
- border-collapse: collapse;
- margin: 0 -0.5em 0 -0.5em;
-}
-
-table td, table th {
- padding: 0.2em 0.5em 0.2em 0.5em;
-}
-
-div.admonition, div.warning {
- font-size: 0.9em;
- margin: 1em 0 1em 0;
- border: 1px solid #86989B;
- background-color: #f7f7f7;
- padding: 0;
-}
-
-div.admonition p, div.warning p {
- margin: 0.5em 1em 0.5em 1em;
- padding: 0;
-}
-
-div.admonition pre, div.warning pre {
- margin: 0.4em 1em 0.4em 1em;
-}
-
-div.admonition p.admonition-title,
-div.warning p.admonition-title {
- margin: 0;
- padding: 0.1em 0 0.1em 0.5em;
- color: white;
- border-bottom: 1px solid #86989B;
- font-weight: bold;
- background-color: #AFC1C4;
-}
-
-div.warning {
- border: 1px solid #940000;
-}
-
-div.warning p.admonition-title {
- background-color: #CF0000;
- border-bottom-color: #940000;
-}
-
-div.admonition ul, div.admonition ol,
-div.warning ul, div.warning ol {
- margin: 0.1em 0.5em 0.5em 3em;
- padding: 0;
-}
-
-div.versioninfo {
- margin: 1em 0 0 0;
- border: 1px solid #ccc;
- background-color: #DDEAF0;
- padding: 8px;
- line-height: 1.3em;
- font-size: 0.9em;
-}
-
-.viewcode-back {
- font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
- 'Verdana', sans-serif;
-}
-
-div.viewcode-block:target {
- background-color: #f4debf;
- border-top: 1px solid #ac9;
- border-bottom: 1px solid #ac9;
-}
\ No newline at end of file
diff --git a/doc/whats_new.rst b/doc/whats_new.rst
index ae194fa602..a96d2dd40f 100644
--- a/doc/whats_new.rst
+++ b/doc/whats_new.rst
@@ -13,6 +13,11 @@ NEW
| - Scikit-learn -- v0.19
| - Scipy -- v0.19
+- A new method for :class:`nilearn.input_data.NiftiMasker` instances
+ for generating reports viewable in a web browser, Jupyter Notebook, or VSCode.
+
+- joblib is now a dependency
+
- Parcellation method ReNA: Fast agglomerative clustering based on recursive
nearest neighbor grouping.
Yields very fast & accurate models, without creation of giant
@@ -28,6 +33,12 @@ NEW
:func:`nilearn.datasets.fetch_development_fmri` can be used to download
movie-watching data in children and adults. A light-weight dataset
implemented for teaching and usage in the examples.
+- New example in `examples/05_advanced/plot_age_group_prediction_cross_val.py`
+ to compare methods for classifying subjects into age groups based on
+ functional connectivity. Similar example in
+ `examples/03_connectivity/plot_group_level_connectivity.py` simplified.
+
+- the Localizer dataset now follows the BIDS organization.
Changes
-------
@@ -39,7 +50,17 @@ Changes
and :func:`nilearn.plotting.view_connectome` now allow disabling the colorbar,
and setting its height and the fontsize of its ticklabels.
+- :func:`nilearn.plotting.view_img_on_surf`, :func:`nilearn.plotting.view_surf`
+ and :func:`nilearn.plotting.view_connectome` can now display a title.
+
+- Rework of the standardize-options of :func:`nilearn.signal.clean` and the various Maskers
+ in `nilearn.input_data`. You can now set `standardize` to `zscore` or `psc`. `psc` stands
+ for `Percent Signal Change`, which can be a meaningful metric for BOLD.
+- :func:`nilearn.plotting.plot_img` now has explicit keyword arguments `bg_img`,
+ `vmin` and `vmax` to control the background image and the bounds of the
+ colormap. These arguments were already accepted in `kwargs` but not documented
+ before.
Fixes
-----
@@ -56,8 +77,17 @@ Fixes
half-transparent grey to maintain a 3D perception.
- :func:`nilearn.plotting.view_surf` now accepts surface data provided as a file
path.
-- plot_glass_brain now correctly displays the left 'l' orientation even when
+- :func:`nilearn.plotting.plot_glass_brain` now correctly displays the left 'l' orientation even when
the given images are completely masked (empty images).
+- :func:`nilearn.plotting.plot_matrix` providing labels=None, False, or an empty list now correctly disables labels.
+- :func:`nilearn.plotting.plot_surf_roi` now takes vmin, vmax parameters
+- :func:`nilearn.datasets.fetch_surf_nki_enhanced` is now downloading the correct
+ left and right functional surface data for each subject
+- :func:`nilearn.datasets.fetch_atlas_schaefer_2018` now downloads from release
+ version 0.14.3 (instead of 0.8.1) by default, which includes corrected region label
+ names along with 700 and 900 region parcelations.
+- Colormap creation functions have been updated to avoid matplotlib deprecation warnings
+ about colormap reversal
0.5.2
=====
diff --git a/examples/01_plotting/plot_3d_map_to_surface_projection.py b/examples/01_plotting/plot_3d_map_to_surface_projection.py
index c8d08a0e6e..0b01f4197e 100644
--- a/examples/01_plotting/plot_3d_map_to_surface_projection.py
+++ b/examples/01_plotting/plot_3d_map_to_surface_projection.py
@@ -85,15 +85,16 @@
view = plotting.view_surf(fsaverage.infl_right, texture, threshold='90%',
bg_map=fsaverage.sulc_right)
-# uncomment this to open the plot in a web browser:
-# view.open_in_browser()
-##############################################################################
# In a Jupyter notebook, if ``view`` is the output of a cell, it will
# be displayed below the cell
-
view
+##############################################################################
+
+# uncomment this to open the plot in a web browser:
+# view.open_in_browser()
+
##############################################################################
# We don't need to do the projection ourselves, we can use view_img_on_surf:
diff --git a/examples/01_plotting/plot_demo_plotting.py b/examples/01_plotting/plot_demo_plotting.py
index 629864a913..9123648522 100644
--- a/examples/01_plotting/plot_demo_plotting.py
+++ b/examples/01_plotting/plot_demo_plotting.py
@@ -33,6 +33,7 @@
motor_images = datasets.fetch_neurovault_motor_task()
stat_img = motor_images.images[0]
+
###############################################################################
# Plotting statistical maps with function `plot_stat_map`
# --------------------------------------------------------
@@ -54,15 +55,15 @@
# for more details.
view = plotting.view_img(stat_img, threshold=3)
+# In a Jupyter notebook, if ``view`` is the output of a cell, it will
+# be displayed below the cell
+view
+
+##############################################################################
# uncomment this to open the plot in a web browser:
# view.open_in_browser()
-##############################################################################
-# In a Jupyter notebook, if ``view`` is the output of a cell, it will
-# be displayed below the cell
-
-view
###############################################################################
# Plotting statistical maps in a glass brain with function `plot_glass_brain`
diff --git a/examples/01_plotting/plot_dim_plotting.py b/examples/01_plotting/plot_dim_plotting.py
index afecc379c3..11253a33ad 100644
--- a/examples/01_plotting/plot_dim_plotting.py
+++ b/examples/01_plotting/plot_dim_plotting.py
@@ -21,9 +21,9 @@
localizer_dataset = datasets.fetch_localizer_button_task()
# Contrast map of motor task
-localizer_tmap_filename = localizer_dataset.tmap
+localizer_tmap_filename = localizer_dataset.tmaps[0]
# Subject specific anatomical image
-localizer_anat_filename = localizer_dataset.anat
+localizer_anat_filename = localizer_dataset.anats[0]
###########################################################################
# Plotting with enhancement of background image with dim=-.5
# --------------------------------------------------------------------------
diff --git a/examples/01_plotting/plot_surf_atlas.py b/examples/01_plotting/plot_surf_atlas.py
index 90fb6996dd..85b35a3dab 100644
--- a/examples/01_plotting/plot_surf_atlas.py
+++ b/examples/01_plotting/plot_surf_atlas.py
@@ -124,14 +124,14 @@
view = plotting.view_surf(fsaverage.infl_left, parcellation,
cmap='gist_ncar', symmetric_cmap=False)
-# uncomment this to open the plot in a web browser:
-# view.open_in_browser()
-
-##############################################################################
# In a Jupyter notebook, if ``view`` is the output of a cell, it will
# be displayed below the cell
view
+##############################################################################
+
+# uncomment this to open the plot in a web browser:
+# view.open_in_browser()
##############################################################################
# you can also use :func:`nilearn.plotting.view_connectome` to open an
diff --git a/examples/02_decoding/plot_haxby_stimuli.py b/examples/02_decoding/plot_haxby_stimuli.py
index ba63648a27..ac72643b92 100644
--- a/examples/02_decoding/plot_haxby_stimuli.py
+++ b/examples/02_decoding/plot_haxby_stimuli.py
@@ -7,7 +7,6 @@
Cortex" (Science 2001)
"""
-from scipy.misc import imread
import matplotlib.pyplot as plt
from nilearn import datasets
@@ -16,22 +15,19 @@
haxby_dataset = datasets.fetch_haxby(subjects=[], fetch_stimuli=True)
stimulus_information = haxby_dataset.stimuli
-for stim_type in sorted(stimulus_information.keys()):
- if stim_type == b'controls':
- # skip control images, there are too many
- continue
-
- file_names = stimulus_information[stim_type]
-
- plt.figure()
- for i in range(48):
- plt.subplot(6, 8, i + 1)
- try:
- plt.imshow(imread(file_names[i]), cmap=plt.cm.gray)
- except:
- # just go to the next one if the file is not present
- pass
- plt.axis("off")
- plt.suptitle(stim_type)
+for stim_type in stimulus_information:
+ # skip control images, there are too many
+ if stim_type != 'controls':
+
+ file_names = stimulus_information[stim_type]
+
+ fig, axes = plt.subplots(6, 8)
+ fig.suptitle(stim_type)
+
+ for img_path, ax in zip(file_names, axes.ravel()):
+ ax.imshow(plt.imread(img_path), cmap=plt.cm.gray)
+
+ for ax in axes.ravel():
+ ax.axis("off")
show()
diff --git a/examples/02_decoding/plot_miyawaki_encoding.py b/examples/02_decoding/plot_miyawaki_encoding.py
index 8520076823..e0e3b3697b 100644
--- a/examples/02_decoding/plot_miyawaki_encoding.py
+++ b/examples/02_decoding/plot_miyawaki_encoding.py
@@ -152,7 +152,7 @@
# bring the scores into the shape of the background brain
score_map_img = masker.inverse_transform(cut_score)
-thresholded_score_map_img = threshold_img(score_map_img, threshold=1e-6)
+thresholded_score_map_img = threshold_img(score_map_img, threshold=1e-6, copy=False)
##############################################################################
# Plotting the statistical map on a background brain, we mark four voxels
diff --git a/examples/03_connectivity/plot_group_level_connectivity.py b/examples/03_connectivity/plot_group_level_connectivity.py
index 12542f4165..daf21f8f70 100644
--- a/examples/03_connectivity/plot_group_level_connectivity.py
+++ b/examples/03_connectivity/plot_group_level_connectivity.py
@@ -1,35 +1,17 @@
"""
-Functional connectivity matrices for group analysis of connectomes
-==================================================================
+Classification of age groups using functional connectivity
+==========================================================
This example compares different kinds of functional connectivity between
-regions of interest : correlation, partial correlation, as well as a kind
-called **tangent**.
+regions of interest : correlation, partial correlation, and tangent space
+embedding.
The resulting connectivity coefficients can be used to
-discriminate children from adults. In general, the **tangent kind**
+discriminate children from adults. In general, the tangent space embedding
**outperforms** the standard correlations: see `Dadi et al 2019
`_
for a careful study.
"""
-# Matrix plotting from Nilearn: nilearn.plotting.plot_matrix
-import numpy as np
-import matplotlib.pylab as plt
-
-
-def plot_matrices(matrices, matrix_kind):
- n_matrices = len(matrices)
- fig = plt.figure(figsize=(n_matrices * 4, 4))
- for n_subject, matrix in enumerate(matrices):
- plt.subplot(1, n_matrices, n_subject + 1)
- matrix = matrix.copy() # avoid side effects
- # Set diagonal to zero, for better visualization
- np.fill_diagonal(matrix, 0)
- vmax = np.max(np.abs(matrix))
- title = '{0}, subject {1}'.format(matrix_kind, n_subject)
- plotting.plot_matrix(matrix, vmin=-vmax, vmax=vmax, cmap='RdBu_r',
- title=title, figure=fig, colorbar=False)
-
###############################################################################
# Load brain development fMRI dataset and MSDL atlas
@@ -37,7 +19,7 @@ def plot_matrices(matrices, matrix_kind):
# We study only 30 subjects from the dataset, to save computation time.
from nilearn import datasets
-rest_data = datasets.fetch_development_fmri(n_subjects=30)
+development_dataset = datasets.fetch_development_fmri(n_subjects=30)
###############################################################################
# We use probabilistic regions of interest (ROIs) from the MSDL atlas.
@@ -57,7 +39,7 @@ def plot_matrices(matrices, matrix_kind):
masker = input_data.NiftiMapsMasker(
msdl_data.maps, resampling_target="data", t_r=2, detrend=True,
- low_pass=.1, high_pass=.01, memory='nilearn_cache', memory_level=1)
+ low_pass=.1, high_pass=.01, memory='nilearn_cache', memory_level=1).fit()
###############################################################################
# Then we compute region signals and extract useful phenotypic informations.
@@ -65,13 +47,13 @@ def plot_matrices(matrices, matrix_kind):
pooled_subjects = []
groups = [] # child or adult
for func_file, confound_file, phenotypic in zip(
- rest_data.func, rest_data.confounds, rest_data.phenotypic):
- time_series = masker.fit_transform(func_file, confounds=confound_file)
+ development_dataset.func,
+ development_dataset.confounds,
+ development_dataset.phenotypic):
+ time_series = masker.transform(func_file, confounds=confound_file)
pooled_subjects.append(time_series)
- is_child = phenotypic['Child_Adult'] == 'child'
- if is_child:
+ if phenotypic['Child_Adult'] == 'child':
children.append(time_series)
-
groups.append(phenotypic['Child_Adult'])
print('Data has {0} children.'.format(len(children)))
@@ -101,10 +83,14 @@ def plot_matrices(matrices, matrix_kind):
print('Mean correlation has shape {0}.'.format(mean_correlation_matrix.shape))
###############################################################################
-# We display the connectome matrices of the first 4 children
+# We display the connectome matrices of the first 3 children
from nilearn import plotting
+from matplotlib import pyplot as plt
-plot_matrices(correlation_matrices[:4], 'correlation')
+_, axes = plt.subplots(1, 3, figsize=(15, 5))
+for i, (matrix, ax) in enumerate(zip(correlation_matrices, axes)):
+ plotting.plot_matrix(matrix, tri='lower', colorbar=False, axes=ax,
+ title='correlation, child {}'.format(i))
###############################################################################
# The blocks structure that reflect functional networks are visible.
@@ -119,19 +105,17 @@ def plot_matrices(matrices, matrix_kind):
# We can also study **direct connections**, revealed by partial correlation
# coefficients. We just change the `ConnectivityMeasure` kind
partial_correlation_measure = ConnectivityMeasure(kind='partial correlation')
-
-###############################################################################
-# and repeat the previous operation.
partial_correlation_matrices = partial_correlation_measure.fit_transform(
children)
###############################################################################
-# Most of direct connections are weaker than full connections,
-plot_matrices(partial_correlation_matrices[:4], 'partial')
+# Most of direct connections are weaker than full connections.
+_, axes = plt.subplots(1, 3, figsize=(15, 5))
+for i, (matrix, ax) in enumerate(zip(partial_correlation_matrices, axes)):
+ plotting.plot_matrix(matrix, tri='lower', colorbar=False, axes=ax,
+ title='partial correlation, child {}'.format(i))
###############################################################################
-# Compared to a connectome computed on correlations, the connectome graph
-# with partial correlations is more sparse:
plotting.plot_connectome(
partial_correlation_measure.mean_, msdl_coords,
title='mean partial correlation over all children')
@@ -140,8 +124,8 @@ def plot_matrices(matrices, matrix_kind):
# Extract subjects variabilities around a group connectivity
# ----------------------------------------------------------
# We can use **both** correlations and partial correlations to capture
-# reproducible connectivity patterns at the group-level and build a **robust**
-# **group connectivity matrix**. This is done by the **tangent** kind.
+# reproducible connectivity patterns at the group-level.
+# This is done by the tangent space embedding.
tangent_measure = ConnectivityMeasure(kind='tangent')
###############################################################################
@@ -154,84 +138,80 @@ def plot_matrices(matrices, matrix_kind):
# `tangent_matrices` model individual connectivities as
# **perturbations** of the group connectivity matrix `tangent_measure.mean_`.
# Keep in mind that these subjects-to-group variability matrices do not
-# straight reflect individual brain connections. For instance negative
+# directly reflect individual brain connections. For instance negative
# coefficients can not be interpreted as anticorrelated regions.
-plot_matrices(tangent_matrices[:4], 'tangent variability')
+_, axes = plt.subplots(1, 3, figsize=(15, 5))
+for i, (matrix, ax) in enumerate(zip(tangent_matrices, axes)):
+ plotting.plot_matrix(matrix, tri='lower', colorbar=False, axes=ax,
+ title='tangent offset, child {}'.format(i))
+
###############################################################################
-# The average tangent matrix cannot be interpreted, as the average
-# variation is expected to be zero
+# The average tangent matrix cannot be interpreted, as individual matrices
+# represent deviations from the mean, which is set to 0.
###############################################################################
# What kind of connectivity is most powerful for classification?
# --------------------------------------------------------------
-# *ConnectivityMeasure* can output the estimated subjects coefficients
-# as a 1D arrays through the parameter *vectorize*.
-connectivity_biomarkers = {}
-kinds = ['correlation', 'partial correlation', 'tangent']
-for kind in kinds:
- conn_measure = ConnectivityMeasure(kind=kind, vectorize=True)
- connectivity_biomarkers[kind] = conn_measure.fit_transform(pooled_subjects)
-
-# For each kind, all individual coefficients are stacked in a unique 2D matrix.
-print('{0} correlation biomarkers for each subject.'.format(
- connectivity_biomarkers['correlation'].shape[1]))
-
-###############################################################################
-# Note that we use the **pooled groups**. This is crucial for **tangent** kind,
-# to get the displacements from a **unique** `mean_` of all subjects.
-
-###############################################################################
-# We stratify the dataset into homogeneous classes according to phenotypic
-# and scan site. We then split the subjects into 30 folds with the same
-# proportion of each class as in the whole cohort for cross-validation
+# We will use connectivity matrices as features to distinguish children from
+# adults. We use cross-validation and measure classification accuracy to
+# compare the different kinds of connectivity matrices.
+# We use random splits of the subjects into training/testing sets.
+# StratifiedShuffleSplit allows preserving the proportion of children in the
+# test set.
+from sklearn.svm import LinearSVC
from sklearn.model_selection import StratifiedShuffleSplit
+from sklearn.metrics import accuracy_score
+import numpy as np
+kinds = ['correlation', 'partial correlation', 'tangent']
_, classes = np.unique(groups, return_inverse=True)
-cv = StratifiedShuffleSplit(n_splits=30)
-###############################################################################
-# and use the connectivity coefficients to classify children vs adults.
+cv = StratifiedShuffleSplit(n_splits=15, random_state=0, test_size=5)
+pooled_subjects = np.asarray(pooled_subjects)
-# Note that in cv.split(X, y),
-# providing y is sufficient to generate the splits and
-# hence np.zeros(n_samples) may be used as a placeholder for X
-# instead of actual training data.
-from sklearn.svm import LinearSVC
-from sklearn.model_selection import cross_val_score
-
-mean_scores = []
+scores = {}
for kind in kinds:
- svc = LinearSVC(random_state=0)
- cv_scores = cross_val_score(svc,
- connectivity_biomarkers[kind],
- y=classes,
- cv=cv,
- groups=groups,
- scoring='accuracy',
- )
- mean_scores.append(cv_scores.mean())
-
-###############################################################################
-# Finally, we can display the classification scores.
-
-###############################################################################
-# Finally, we can display the classification scores.
-from nilearn.plotting import show
+ scores[kind] = []
+ for train, test in cv.split(pooled_subjects, classes):
+ # *ConnectivityMeasure* can output the estimated subjects coefficients
+ # as a 1D arrays through the parameter *vectorize*.
+ connectivity = ConnectivityMeasure(kind=kind, vectorize=True)
+ # build vectorized connectomes for subjects in the train set
+ connectomes = connectivity.fit_transform(pooled_subjects[train])
+ # fit the classifier
+ classifier = LinearSVC().fit(connectomes, classes[train])
+ # make predictions for the left-out test subjects
+ predictions = classifier.predict(
+ connectivity.transform(pooled_subjects[test]))
+ # store the accuracy for this cross-validation fold
+ scores[kind].append(accuracy_score(classes[test], predictions))
+
+
+######################################################################
+# display the results
+
+mean_scores = [np.mean(scores[kind]) for kind in kinds]
+scores_std = [np.std(scores[kind]) for kind in kinds]
plt.figure(figsize=(6, 4))
positions = np.arange(len(kinds)) * .1 + .1
-plt.barh(positions, mean_scores, align='center', height=.05)
-yticks = [kind.replace(' ', '\n') for kind in kinds]
+plt.barh(positions, mean_scores, align='center', height=.05, xerr=scores_std)
+yticks = [k.replace(' ', '\n') for k in kinds]
plt.yticks(positions, yticks)
-plt.xlabel('Classification accuracy')
-plt.grid(True)
+plt.gca().grid(True)
+plt.gca().set_axisbelow(True)
+plt.gca().axvline(.8, color='red', linestyle='--')
+plt.xlabel('Classification accuracy\n(red line = chance level)')
plt.tight_layout()
+
###############################################################################
-# While the comparison is not fully conclusive on this small dataset,
+# This is a small example to showcase nilearn features. In practice such
+# comparisons need to be performed on much larger cohorts and several
+# datasets.
# `Dadi et al 2019
# `_
# Showed that across many cohorts and clinical questions, the tangent
# kind should be preferred.
-show()
+plotting.show()
diff --git a/examples/03_connectivity/plot_inverse_covariance_connectome.py b/examples/03_connectivity/plot_inverse_covariance_connectome.py
index 5ee1cef823..88c430659b 100644
--- a/examples/03_connectivity/plot_inverse_covariance_connectome.py
+++ b/examples/03_connectivity/plot_inverse_covariance_connectome.py
@@ -51,9 +51,13 @@
##############################################################################
# Compute the sparse inverse covariance
# --------------------------------------
-from sklearn.covariance import GraphLassoCV
-estimator = GraphLassoCV()
+try:
+ from sklearn.covariance import GraphicalLassoCV
+except ImportError:
+ # for Scitkit-Learn < v0.20.0
+ from sklearn.covariance import GraphLassoCV as GraphicalLassoCV
+estimator = GraphicalLassoCV()
estimator.fit(time_series)
##############################################################################
@@ -103,11 +107,12 @@
view = plotting.view_connectome(-estimator.precision_, coords)
-# uncomment this to open the plot in a web browser:
-# view.open_in_browser()
-
-##############################################################################
# In a Jupyter notebook, if ``view`` is the output of a cell, it will
# be displayed below the cell
-
view
+
+##############################################################################
+
+# uncomment this to open the plot in a web browser:
+# view.open_in_browser()
+
diff --git a/examples/03_connectivity/plot_multi_subject_connectome.py b/examples/03_connectivity/plot_multi_subject_connectome.py
index c7f45f0ce4..78dc2ce2b6 100644
--- a/examples/03_connectivity/plot_multi_subject_connectome.py
+++ b/examples/03_connectivity/plot_multi_subject_connectome.py
@@ -52,7 +52,7 @@ def plot_matrices(cov, prec, title, labels):
from nilearn import input_data
# A "memory" to avoid recomputation
-from sklearn.externals.joblib import Memory
+from nilearn._utils.compat import Memory
mem = Memory('nilearn_cache')
masker = input_data.NiftiMapsMasker(
@@ -84,8 +84,13 @@ def plot_matrices(cov, prec, title, labels):
gsc = GroupSparseCovarianceCV(verbose=2)
gsc.fit(subject_time_series)
-from sklearn import covariance
-gl = covariance.GraphLassoCV(verbose=2)
+try:
+ from sklearn.covariance import GraphicalLassoCV
+except ImportError:
+ # for Scitkit-Learn < v0.20.0
+ from sklearn.covariance import GraphLassoCV as GraphicalLassoCV
+
+gl = GraphicalLassoCV(verbose=2)
gl.fit(np.concatenate(subject_time_series))
@@ -102,10 +107,10 @@ def plot_matrices(cov, prec, title, labels):
display_mode="lzr")
plotting.plot_connectome(-gl.precision_, atlas_region_coords,
edge_threshold='90%',
- title="Sparse inverse covariance (GraphLasso)",
+ title="Sparse inverse covariance (GraphicalLasso)",
display_mode="lzr",
edge_vmax=.5, edge_vmin=-.5)
-plot_matrices(gl.covariance_, gl.precision_, "GraphLasso", labels)
+plot_matrices(gl.covariance_, gl.precision_, "GraphicalLasso", labels)
title = "GroupSparseCovariance"
plotting.plot_connectome(-gsc.precisions_[..., 0],
diff --git a/examples/03_connectivity/plot_probabilistic_atlas_extraction.py b/examples/03_connectivity/plot_probabilistic_atlas_extraction.py
index 938cd97ca1..21fb2153b6 100644
--- a/examples/03_connectivity/plot_probabilistic_atlas_extraction.py
+++ b/examples/03_connectivity/plot_probabilistic_atlas_extraction.py
@@ -88,11 +88,12 @@
view = plotting.view_connectome(correlation_matrix, coords, threshold='80%')
-# uncomment this to open the plot in a web browser:
-# view.open_in_browser()
-
-##############################################################################
# In a Jupyter notebook, if ``view`` is the output of a cell, it will
# be displayed below the cell
-
view
+
+##############################################################################
+
+# uncomment this to open the plot in a web browser:
+# view.open_in_browser()
+
diff --git a/examples/03_connectivity/plot_simulated_connectome.py b/examples/03_connectivity/plot_simulated_connectome.py
index 385676c08d..3df491300c 100644
--- a/examples/03_connectivity/plot_simulated_connectome.py
+++ b/examples/03_connectivity/plot_simulated_connectome.py
@@ -49,8 +49,13 @@
# Fit one graph lasso per subject
-from sklearn.covariance import GraphLassoCV
-gl = GraphLassoCV(verbose=1)
+try:
+ from sklearn.covariance import GraphicalLassoCV
+except ImportError:
+ # for Scitkit-Learn < v0.20.0
+ from sklearn.covariance import GraphLassoCV as GraphicalLassoCV
+
+gl = GraphicalLassoCV(verbose=1)
for n, subject in enumerate(subjects[:n_displayed]):
gl.fit(subject)
diff --git a/examples/03_connectivity/plot_sphere_based_connectome.py b/examples/03_connectivity/plot_sphere_based_connectome.py
index 4ea44844e9..4c5bd58440 100644
--- a/examples/03_connectivity/plot_sphere_based_connectome.py
+++ b/examples/03_connectivity/plot_sphere_based_connectome.py
@@ -143,16 +143,15 @@
view = plotting.view_connectome(partial_correlation_matrix, dmn_coords)
-# uncomment this to open the plot in a web browser:
-# view.open_in_browser()
-
-
-##############################################################################
# In a Jupyter notebook, if ``view`` is the output of a cell, it will
# be displayed below the cell
-
view
+##############################################################################
+
+# uncomment this to open the plot in a web browser:
+# view.open_in_browser()
+
##########################################################################
# Extract signals on spheres from an atlas
@@ -211,13 +210,17 @@
###############################################################################
# in which situation the graphical lasso **sparse inverse covariance**
# estimator captures well the covariance **structure**.
-from sklearn.covariance import GraphLassoCV
+try:
+ from sklearn.covariance import GraphicalLassoCV
+except ImportError:
+ # for Scitkit-Learn < v0.20.0
+ from sklearn.covariance import GraphLassoCV as GraphicalLassoCV
-covariance_estimator = GraphLassoCV(cv=3, verbose=1)
+covariance_estimator = GraphicalLassoCV(cv=3, verbose=1)
###############################################################################
-# We just fit our regions signals into the `GraphLassoCV` object
+# We just fit our regions signals into the `GraphicalLassoCV` object
covariance_estimator.fit(timeseries)
@@ -271,7 +274,7 @@
timeseries = spheres_masker.fit_transform(func_filename,
confounds=confounds_filename)
-covariance_estimator = GraphLassoCV()
+covariance_estimator = GraphicalLassoCV()
covariance_estimator.fit(timeseries)
matrix = covariance_estimator.covariance_
@@ -321,7 +324,7 @@
timeseries = spheres_masker.fit_transform(func_filename,
confounds=confounds_filename)
-covariance_estimator = GraphLassoCV()
+covariance_estimator = GraphicalLassoCV()
covariance_estimator.fit(timeseries)
matrix = covariance_estimator.covariance_
@@ -340,8 +343,6 @@
###############################################################################
# .. seealso::
#
-# :ref:`sphx_glr_auto_examples_03_connectivity_plot_atlas_comparison.py`
-#
-# .. seealso::
+# * :ref:`sphx_glr_auto_examples_03_connectivity_plot_atlas_comparison.py`
#
-# :ref:`sphx_glr_auto_examples_03_connectivity_plot_multi_subject_connectome.py`
+# * :ref:`sphx_glr_auto_examples_03_connectivity_plot_multi_subject_connectome.py`
diff --git a/examples/04_manipulating_images/plot_extract_rois_statistical_maps.py b/examples/04_manipulating_images/plot_extract_rois_statistical_maps.py
index 72773ff068..d63f7518c6 100644
--- a/examples/04_manipulating_images/plot_extract_rois_statistical_maps.py
+++ b/examples/04_manipulating_images/plot_extract_rois_statistical_maps.py
@@ -28,12 +28,12 @@
# Two types of strategies can be used from this threshold function
# Type 1: strategy used will be based on scoreatpercentile
-threshold_percentile_img = threshold_img(tmap_filename, threshold='97%')
+threshold_percentile_img = threshold_img(tmap_filename, threshold='97%', copy=False)
# Type 2: threshold strategy used will be based on image intensity
# Here, threshold value should be within the limits i.e. less than max value.
-threshold_value_img = threshold_img(tmap_filename, threshold=3.0)
+threshold_value_img = threshold_img(tmap_filename, threshold=3.0, copy=False)
################################################################################
# Visualization
diff --git a/examples/04_manipulating_images/plot_mask_computation.py b/examples/04_manipulating_images/plot_mask_computation.py
index d6b76db8e2..470a2506c4 100644
--- a/examples/04_manipulating_images/plot_mask_computation.py
+++ b/examples/04_manipulating_images/plot_mask_computation.py
@@ -17,7 +17,6 @@
"""
-
from nilearn.input_data import NiftiMasker
import nilearn.image as image
from nilearn.plotting import plot_roi, plot_epi, show
@@ -48,10 +47,15 @@
masker = NiftiMasker()
masker.fit(miyawaki_filename)
-# Plot the generated mask
+# Plot the generated mask using the mask_img_ attribute
plot_roi(masker.mask_img_, miyawaki_mean_img,
title="Mask from already masked data")
+###############################################################################
+# Plot the generated mask using the .generate_report method
+report = masker.generate_report()
+report
+
###############################################################################
# Computing a mask from raw EPI data
@@ -77,7 +81,8 @@
# We need to specify an 'epi' mask_strategy, as this is raw EPI data
masker = NiftiMasker(mask_strategy='epi')
masker.fit(epi_img)
-plot_roi(masker.mask_img_, mean_img, title='EPI automatic mask')
+report = masker.generate_report()
+report
###############################################################################
# Generate mask with strong opening
@@ -90,7 +95,8 @@
# skull parts in the image.
masker = NiftiMasker(mask_strategy='epi', mask_args=dict(opening=10))
masker.fit(epi_img)
-plot_roi(masker.mask_img_, mean_img, title='EPI Mask with strong opening')
+report = masker.generate_report()
+report
###############################################################################
# Generate mask with a high lower cutoff
@@ -107,8 +113,8 @@
mask_args=dict(upper_cutoff=.9, lower_cutoff=.8,
opening=False))
masker.fit(epi_img)
-plot_roi(masker.mask_img_, mean_img,
- title='EPI Mask: high lower_cutoff')
+report = masker.generate_report()
+report
###############################################################################
# Computing the mask from the MNI template
@@ -119,9 +125,27 @@
masker = NiftiMasker(mask_strategy='template')
masker.fit(epi_img)
-plot_roi(masker.mask_img_, mean_img,
- title='Mask from template')
+report = masker.generate_report()
+report
+
+###############################################################################
+# Compute and resample a mask
+###############################################################################
+#
+# NiftiMasker also allows passing parameters directly to `image.resample_img`.
+# We can specify a `target_affine`, a `target_shape`, or both.
+# For more information on these arguments,
+# see :doc:`plot_affine_transformation`.
+#
+# The NiftiMasker report allows us to see the mask before and after resampling.
+# Simply hover over the report to see the mask from the original image.
+
+import numpy as np
+masker = NiftiMasker(mask_strategy='epi', target_affine=np.eye(3) * 8)
+masker.fit(epi_img)
+report = masker.generate_report()
+report
###############################################################################
# After mask computation: extracting time series
@@ -136,7 +160,6 @@
detrended_data = detrended.fit_transform(epi_img)
# The timeseries are numpy arrays, so we can manipulate them with numpy
-import numpy as np
print("Trended: mean %.2f, std %.2f" %
(np.mean(trended_data), np.std(trended_data)))
diff --git a/examples/04_manipulating_images/plot_nifti_simple.py b/examples/04_manipulating_images/plot_nifti_simple.py
index 6f3045f4c9..b24122490c 100644
--- a/examples/04_manipulating_images/plot_nifti_simple.py
+++ b/examples/04_manipulating_images/plot_nifti_simple.py
@@ -10,7 +10,7 @@
# Retrieve the brain development functional dataset
from nilearn import datasets
-dataset = datasets.fetch_haxby()
+dataset = datasets.fetch_development_fmri(n_subjects=1)
func_filename = dataset.func[0]
# print basic information on the dataset
@@ -30,7 +30,7 @@
mask_img = nifti_masker.mask_img_
###########################################################################
-# Visualize the mask
+# Visualize the mask using the plot_roi method
from nilearn.plotting import plot_roi
from nilearn.image.image import mean_img
@@ -39,6 +39,13 @@
plot_roi(mask_img, mean_func_img, display_mode='y', cut_coords=4, title="Mask")
+###########################################################################
+# Visualize the mask using the 'generate_report' method
+# This report can be displayed in a Jupyter Notebook,
+# opened in-browser using the .open_in_browser() method,
+# or saved to a file using the .save_as_html(output_filepath) method.
+report = nifti_masker.generate_report()
+report
###########################################################################
# Preprocess data with the NiftiMasker
@@ -60,6 +67,10 @@
# Visualize results
from nilearn.plotting import plot_stat_map, show
from nilearn.image import index_img
+from nilearn.image.image import mean_img
+
+# calculate mean image for the background
+mean_func_img = mean_img(func_filename)
plot_stat_map(index_img(components, 0), mean_func_img,
display_mode='y', cut_coords=4, title="Component 0")
diff --git a/examples/05_advanced/plot_age_group_prediction_cross_val.py b/examples/05_advanced/plot_age_group_prediction_cross_val.py
new file mode 100644
index 0000000000..8a4f193efe
--- /dev/null
+++ b/examples/05_advanced/plot_age_group_prediction_cross_val.py
@@ -0,0 +1,105 @@
+"""
+Functional connectivity predicts age group
+==========================================
+
+This example compares different kinds of functional connectivity between
+regions of interest : correlation, partial correlation, and tangent space
+embedding.
+
+The resulting connectivity coefficients can be used to
+discriminate children from adults. In general, the tangent space embedding
+**outperforms** the standard correlations: see `Dadi et al 2019
+`_
+for a careful study.
+"""
+
+###############################################################################
+# Load brain development fMRI dataset and MSDL atlas
+# -------------------------------------------------------------------
+# We study only 60 subjects from the dataset, to save computation time.
+from nilearn import datasets
+
+development_dataset = datasets.fetch_development_fmri(n_subjects=60)
+
+###############################################################################
+# We use probabilistic regions of interest (ROIs) from the MSDL atlas.
+from nilearn.input_data import NiftiMapsMasker
+
+msdl_data = datasets.fetch_atlas_msdl()
+msdl_coords = msdl_data.region_coords
+
+masker = NiftiMapsMasker(
+ msdl_data.maps, resampling_target="data", t_r=2, detrend=True,
+ low_pass=.1, high_pass=.01, memory='nilearn_cache', memory_level=1).fit()
+masked_data = [masker.transform(func, confounds) for
+ (func, confounds) in zip(
+ development_dataset.func, development_dataset.confounds)]
+
+###############################################################################
+# What kind of connectivity is most powerful for classification?
+# --------------------------------------------------------------
+# we will use connectivity matrices as features to distinguish children from
+# adults. We use cross-validation and measure classification accuracy to
+# compare the different kinds of connectivity matrices.
+
+# prepare the classification pipeline
+from sklearn.pipeline import Pipeline
+from nilearn.connectome import ConnectivityMeasure
+from sklearn.svm import LinearSVC
+from sklearn.dummy import DummyClassifier
+from sklearn.model_selection import GridSearchCV
+
+kinds = ['correlation', 'partial correlation', 'tangent']
+
+pipe = Pipeline(
+ [('connectivity', ConnectivityMeasure(vectorize=True)),
+ ('classifier', GridSearchCV(LinearSVC(), {'C': [.1, 1., 10.]}, cv=5))])
+
+param_grid = [
+ {'classifier': [DummyClassifier('most_frequent')]},
+ {'connectivity__kind': kinds}
+]
+
+######################################################################
+# We use random splits of the subjects into training/testing sets.
+# StratifiedShuffleSplit allows preserving the proportion of children in the
+# test set.
+from sklearn.model_selection import GridSearchCV, StratifiedShuffleSplit
+from sklearn.preprocessing import LabelEncoder
+
+groups = [pheno['Child_Adult'] for pheno in development_dataset.phenotypic]
+classes = LabelEncoder().fit_transform(groups)
+
+cv = StratifiedShuffleSplit(n_splits=30, random_state=0, test_size=10)
+gs = GridSearchCV(pipe, param_grid, scoring='accuracy', cv=cv, verbose=1,
+ refit=False, n_jobs=8)
+gs.fit(masked_data, classes)
+mean_scores = gs.cv_results_['mean_test_score']
+scores_std = gs.cv_results_['std_test_score']
+
+######################################################################
+# display the results
+from matplotlib import pyplot as plt
+
+plt.figure(figsize=(6, 4))
+positions = [.1, .2, .3, .4]
+plt.barh(positions, mean_scores, align='center', height=.05, xerr=scores_std)
+yticks = ['dummy'] + list(gs.cv_results_['param_connectivity__kind'].data[1:])
+yticks = [t.replace(' ', '\n') for t in yticks]
+plt.yticks(positions, yticks)
+plt.xlabel('Classification accuracy')
+plt.gca().grid(True)
+plt.gca().set_axisbelow(True)
+plt.tight_layout()
+
+
+###############################################################################
+# This is a small example to showcase nilearn features. In practice such
+# comparisons need to be performed on much larger cohorts and several
+# datasets.
+# `Dadi et al 2019
+# `_
+# Showed that across many cohorts and clinical questions, the tangent
+# kind should be preferred.
+
+plt.show()
diff --git a/examples/05_advanced/plot_localizer_mass_univariate_methods.py b/examples/05_advanced/plot_localizer_mass_univariate_methods.py
index 9c8f4d5e2a..12531abf6c 100644
--- a/examples/05_advanced/plot_localizer_mass_univariate_methods.py
+++ b/examples/05_advanced/plot_localizer_mass_univariate_methods.py
@@ -35,7 +35,7 @@
tested_var = localizer_dataset.ext_vars['pseudo']
# Quality check / Remove subjects with bad tested variate
-mask_quality_check = np.where(tested_var != b'None')[0]
+mask_quality_check = np.where(tested_var != b'n/a')[0]
n_samples = mask_quality_check.size
contrast_map_filenames = [localizer_dataset.cmaps[i]
for i in mask_quality_check]
diff --git a/nilearn/__init__.py b/nilearn/__init__.py
index 7bfee2f735..5d39246d7b 100644
--- a/nilearn/__init__.py
+++ b/nilearn/__init__.py
@@ -35,11 +35,17 @@
import gzip
import sys
import warnings
+import os
from distutils.version import LooseVersion
from .version import _check_module_dependencies, __version__
+# Workaround issue discovered in intel-openmp 2019.5:
+# https://github.com/ContinuumIO/anaconda-issues/issues/11294
+#
+# see also https://github.com/scikit-learn/scikit-learn/pull/15020
+os.environ.setdefault("KMP_INIT_AT_FORK", "FALSE")
def _py2_deprecation_warning():
py2_warning = ('Python2 support is deprecated and will be removed in '
diff --git a/nilearn/_utils/cache_mixin.py b/nilearn/_utils/cache_mixin.py
index 30bde14440..3f82def65f 100644
--- a/nilearn/_utils/cache_mixin.py
+++ b/nilearn/_utils/cache_mixin.py
@@ -13,16 +13,10 @@
import nibabel
import sklearn
-from sklearn.externals.joblib import Memory
+from nilearn._utils.compat import Memory
MEMORY_CLASSES = (Memory, )
-try:
- from joblib import Memory as JoblibMemory
- MEMORY_CLASSES = (Memory, JoblibMemory)
-except ImportError:
- pass
-
import nilearn
from .compat import _basestring
diff --git a/nilearn/_utils/compat.py b/nilearn/_utils/compat.py
index f76de77cae..27b648fdae 100644
--- a/nilearn/_utils/compat.py
+++ b/nilearn/_utils/compat.py
@@ -7,6 +7,7 @@
from distutils.version import LooseVersion
import nibabel
+import sklearn
if sys.version_info[0] == 3:
@@ -66,3 +67,15 @@ def md5_hash(string):
m = hashlib.md5()
m.update(string)
return m.hexdigest()
+
+
+if sklearn.__version__ < '0.21':
+ from sklearn.externals import joblib
+else:
+ import joblib
+
+Memory = joblib.Memory
+Parallel = joblib.Parallel
+hash = joblib.hash
+delayed = joblib.delayed
+cpu_count = joblib.cpu_count
diff --git a/nilearn/_utils/niimg_conversions.py b/nilearn/_utils/niimg_conversions.py
index efdfad485c..3ecf93a159 100644
--- a/nilearn/_utils/niimg_conversions.py
+++ b/nilearn/_utils/niimg_conversions.py
@@ -10,7 +10,7 @@
import nilearn as ni
import numpy as np
import itertools
-from sklearn.externals.joblib import Memory
+from nilearn._utils.compat import Memory
from .cache_mixin import cache
from .niimg import _safe_get_data, load_niimg
diff --git a/nilearn/conftest.py b/nilearn/conftest.py
new file mode 100644
index 0000000000..7d2d5abfe6
--- /dev/null
+++ b/nilearn/conftest.py
@@ -0,0 +1,30 @@
+from distutils.version import LooseVersion
+
+import numpy as np
+import pytest
+
+from _pytest.doctest import DoctestItem
+
+try:
+ import matplotlib
+except ImportError:
+ collect_ignore = ['plotting']
+else:
+ matplotlib # Prevents flake8 erring due to unused entities.
+
+
+def pytest_collection_modifyitems(items):
+
+ # numpy changed the str/repr formatting of numpy arrays in 1.14. We want to
+ # run doctests only for numpy >= 1.14.Adapted from scikit-learn
+ if LooseVersion(np.__version__) < LooseVersion('1.14'):
+ reason = 'doctests are only run for numpy >= 1.14'
+ skip_doctests = True
+ else:
+ skip_doctests = False
+
+ if skip_doctests:
+ skip_marker = pytest.mark.skip(reason=reason)
+ for item in items:
+ if isinstance(item, DoctestItem):
+ item.add_marker(skip_marker)
diff --git a/nilearn/connectome/connectivity_matrices.py b/nilearn/connectome/connectivity_matrices.py
index fce8fd064a..e2988d0632 100644
--- a/nilearn/connectome/connectivity_matrices.py
+++ b/nilearn/connectome/connectivity_matrices.py
@@ -486,7 +486,7 @@ def _fit_transform(self, X, do_transform=False, do_fit=False):
# Compute all the matrices, stored in "connectivities"
if self.kind == 'correlation':
covariances_std = [self.cov_estimator_.fit(
- signal._standardize(x, detrend=False, normalize=True)
+ signal._standardize(x, detrend=False, standardize=True)
).covariance_ for x in X]
connectivities = [cov_to_corr(cov) for cov in covariances_std]
else:
diff --git a/nilearn/connectome/group_sparse_cov.py b/nilearn/connectome/group_sparse_cov.py
index f43076b992..06317097aa 100644
--- a/nilearn/connectome/group_sparse_cov.py
+++ b/nilearn/connectome/group_sparse_cov.py
@@ -15,7 +15,7 @@
from sklearn.base import BaseEstimator
from sklearn.covariance import empirical_covariance
-from sklearn.externals.joblib import Memory, delayed, Parallel
+from nilearn._utils.compat import Memory, delayed, Parallel
from sklearn.model_selection import check_cv
from sklearn.utils.extmath import fast_logdet
@@ -891,7 +891,7 @@ class GroupSparseCovarianceCV(BaseEstimator, CacheMixin):
See also
--------
GroupSparseCovariance,
- sklearn.covariance.GraphLassoCV
+ sklearn.covariance.GraphicalLassoCV
Notes
-----
diff --git a/nilearn/datasets/atlas.py b/nilearn/datasets/atlas.py
index 2be84139d8..3897f95110 100644
--- a/nilearn/datasets/atlas.py
+++ b/nilearn/datasets/atlas.py
@@ -1275,7 +1275,7 @@ def fetch_atlas_schaefer_2018(n_rois=400, yeo_networks=7, resolution_mm=1,
----------
n_rois: int
number of regions of interest {100, 200, 300, 400 (default), 500, 600,
- 800, 1000}
+ 700, 800, 900, 1000}
yeo_networks: int
ROI annotation according to yeo networks {7 (default), 17}
@@ -1307,7 +1307,7 @@ def fetch_atlas_schaefer_2018(n_rois=400, yeo_networks=7, resolution_mm=1,
References
----------
For more information on this dataset, see
- https://github.com/ThomasYeoLab/CBIG/tree/v0.8.1-Schaefer2018_LocalGlobal/stable_projects/brain_parcellation/Schaefer2018_LocalGlobal
+ https://github.com/ThomasYeoLab/CBIG/tree/v0.14.3-Update_Yeo2011_Schaefer2018_labelname/stable_projects/brain_parcellation/Schaefer2018_LocalGlobal/Parcellations
Schaefer A, Kong R, Gordon EM, Laumann TO, Zuo XN, Holmes AJ,
Eickhoff SB, Yeo BTT. Local-Global parcellation of the human
@@ -1320,8 +1320,15 @@ def fetch_atlas_schaefer_2018(n_rois=400, yeo_networks=7, resolution_mm=1,
intrinsic functional connectivity. J Neurophysiol 106(3):1125-65, 2011.
Licence: MIT.
+
+ Notes
+ -----
+ Release v0.14.3 of the Schaefer 2018 parcellation is used by
+ default. Versions prior to v0.14.3 are known to contain erroneous region
+ label names. For more details, see
+ https://github.com/ThomasYeoLab/CBIG/blob/master/stable_projects/brain_parcellation/Schaefer2018_LocalGlobal/Parcellations/Updates/Update_20190916_README.md
"""
- valid_n_rois = [100, 200, 300, 400, 500, 600, 800, 1000]
+ valid_n_rois = list(range(100, 1100, 100))
valid_yeo_networks = [7, 17]
valid_resolution_mm = [1, 2]
if n_rois not in valid_n_rois:
@@ -1338,9 +1345,9 @@ def fetch_atlas_schaefer_2018(n_rois=400, yeo_networks=7, resolution_mm=1,
if base_url is None:
base_url = ('https://raw.githubusercontent.com/ThomasYeoLab/CBIG/'
- 'v0.8.1-Schaefer2018_LocalGlobal/stable_projects/'
- 'brain_parcellation/Schaefer2018_LocalGlobal/'
- 'Parcellations/MNI/'
+ 'v0.14.3-Update_Yeo2011_Schaefer2018_labelname/'
+ 'stable_projects/brain_parcellation/'
+ 'Schaefer2018_LocalGlobal/Parcellations/MNI/'
)
files = []
diff --git a/nilearn/datasets/func.py b/nilearn/datasets/func.py
index 64281abfdd..38844a93b1 100644
--- a/nilearn/datasets/func.py
+++ b/nilearn/datasets/func.py
@@ -13,7 +13,7 @@
from sklearn.utils import deprecated
from .utils import (_get_dataset_dir, _fetch_files, _get_dataset_descr,
- _read_md5_sum_file, _tree, _filter_columns)
+ _read_md5_sum_file, _tree, _filter_columns, _fetch_file)
from .._utils import check_niimg
from .._utils.compat import BytesIO, _basestring, _urllib
from .._utils.numpy_conversions import csv_to_array
@@ -824,7 +824,7 @@ def fetch_localizer_contrasts(contrasts, n_subjects=None, get_tmaps=False,
if n_subjects is None:
n_subjects = 94 # 94 subjects available
if (isinstance(n_subjects, numbers.Number) and
- ((n_subjects > 94) or (n_subjects < 1))):
+ ((n_subjects > 94) or (n_subjects < 1))):
warnings.warn("Wrong value for \'n_subjects\' (%d). The maximum "
"value will be used instead (\'n_subjects=94\')")
n_subjects = 94 # 94 subjects available
@@ -886,6 +886,7 @@ def fetch_localizer_contrasts(contrasts, n_subjects=None, get_tmaps=False,
"button press vs calculation and sentence listening/reading":
"auditory&visual motor vs cognitive processing"}
allowed_contrasts = list(contrast_name_wrapper.values())
+
# convert contrast names
contrasts_wrapped = []
# get a unique ID for each contrast. It is used to give a unique name to
@@ -893,21 +894,27 @@ def fetch_localizer_contrasts(contrasts, n_subjects=None, get_tmaps=False,
contrasts_indices = []
for contrast in contrasts:
if contrast in allowed_contrasts:
- contrasts_wrapped.append(contrast)
+ contrasts_wrapped.append(contrast.title().replace(" ", ""))
contrasts_indices.append(allowed_contrasts.index(contrast))
elif contrast in contrast_name_wrapper:
name = contrast_name_wrapper[contrast]
- contrasts_wrapped.append(name)
+ contrasts_wrapped.append(name.title().replace(" ", ""))
contrasts_indices.append(allowed_contrasts.index(name))
else:
raise ValueError("Contrast \'%s\' is not available" % contrast)
- # It is better to perform several small requests than a big one because:
- # - Brainomics server has no cache (can lead to timeout while the archive
- # is generated on the remote server)
- # - Local (cached) version of the files can be checked for each contrast
- opts = {'uncompress': True}
+ # Get the dataset OSF index
+ dataset_name = "brainomics_localizer"
+ index_url = "https://osf.io/hwbm2/download"
+ data_dir = _get_dataset_dir(dataset_name, data_dir=data_dir,
+ verbose=verbose)
+ index_file = _fetch_file(index_url, data_dir, verbose=verbose)
+ with open(index_file, "rt") as of:
+ index = json.load(of)
+ # Build data URLs that will be fetched
+ files = {}
+ root_url = "https://osf.io/download/{0}"
if isinstance(n_subjects, numbers.Number):
subject_mask = np.arange(1, n_subjects + 1)
subject_id_max = "S%02d" % n_subjects
@@ -916,26 +923,18 @@ def fetch_localizer_contrasts(contrasts, n_subjects=None, get_tmaps=False,
subject_id_max = "S%02d" % np.max(n_subjects)
n_subjects = len(n_subjects)
subject_ids = ["S%02d" % s for s in subject_mask]
- data_types = ["c map"]
+ data_types = ["cmaps"]
if get_tmaps:
- data_types.append("t map")
- rql_types = str.join(", ", ["\"%s\"" % x for x in data_types])
- root_url = "http://brainomics.cea.fr/localizer/"
-
- base_query = ("Any X,XT,XL,XI,XF,XD WHERE X is Scan, X type XT, "
- "X concerns S, "
- "X label XL, X identifier XI, "
- "X format XF, X description XD, "
- 'S identifier <= "%s", ' % (subject_id_max, ) +
- 'X type IN(%(types)s), X label "%(label)s"')
-
- urls = ["%sbrainomics_data_%d.zip?rql=%s&vid=data-zip"
- % (root_url, i,
- _urllib.parse.quote(base_query % {"types": rql_types,
- "label": c},
- safe=',()'))
- for c, i in zip(contrasts_wrapped, contrasts_indices)]
+ data_types.append("tmaps")
filenames = []
+
+ def _is_valid_path(path, index, verbose):
+ if path not in index:
+ if verbose > 0:
+ print("Skiping path '{0}'...".format(path))
+ return False
+ return True
+
for subject_id in subject_ids:
for data_type in data_types:
for contrast_id, contrast in enumerate(contrasts_wrapped):
@@ -943,80 +942,87 @@ def fetch_localizer_contrasts(contrasts, n_subjects=None, get_tmaps=False,
str.join('_', [data_type, contrast]), ' ', '_')
file_path = os.path.join(
"brainomics_data", subject_id, "%s.nii.gz" % name_aux)
- file_tarball_url = urls[contrast_id]
- filenames.append((file_path, file_tarball_url, opts))
+ path = "/".join([
+ "/localizer", "derivatives", "spm_1st_level",
+ "sub-%s" % subject_id,
+ "sub-%s_task-localizer_acq-%s_%s.nii.gz" % (
+ subject_id, contrast, data_type)])
+ if _is_valid_path(path, index, verbose=verbose):
+ file_url = root_url.format(index[path][1:])
+ opts = {"move": file_path}
+ filenames.append((file_path, file_url, opts))
+ files.setdefault(data_type, []).append(file_path)
+
# Fetch masks if asked by user
if get_masks:
- urls.append("%sbrainomics_data_masks.zip?rql=%s&vid=data-zip"
- % (root_url,
- _urllib.parse.quote(base_query % {"types": '"boolean mask"',
- "label": "mask"},
- safe=',()')))
for subject_id in subject_ids:
file_path = os.path.join(
"brainomics_data", subject_id, "boolean_mask_mask.nii.gz")
- file_tarball_url = urls[-1]
- filenames.append((file_path, file_tarball_url, opts))
+ path = "/".join([
+ "/localizer", "derivatives", "spm_1st_level",
+ "sub-%s" % subject_id, "sub-%s_mask.nii.gz" % subject_id])
+ if _is_valid_path(path, index, verbose=verbose):
+ file_url = root_url.format(index[path][1:])
+ opts = {"move": file_path}
+ filenames.append((file_path, file_url, opts))
+ files.setdefault("masks", []).append(file_path)
+
# Fetch anats if asked by user
if get_anats:
- urls.append("%sbrainomics_data_anats.zip?rql=%s&vid=data-zip"
- % (root_url,
- _urllib.parse.quote(base_query % {"types": '"normalized T1"',
- "label": "anatomy"},
- safe=',()')))
for subject_id in subject_ids:
file_path = os.path.join(
"brainomics_data", subject_id,
"normalized_T1_anat_defaced.nii.gz")
- file_tarball_url = urls[-1]
- filenames.append((file_path, file_tarball_url, opts))
- # Fetch subject characteristics (separated in two files)
- if url is None:
- url_csv = ("%sdataset/cubicwebexport.csv?rql=%s&vid=csvexport"
- % (root_url, _urllib.parse.quote("Any X WHERE X is Subject")))
- url_csv2 = ("%sdataset/cubicwebexport2.csv?rql=%s&vid=csvexport"
- % (root_url,
- _urllib.parse.quote("Any X,XI,XD WHERE X is QuestionnaireRun, "
- "X identifier XI, X datetime "
- "XD", safe=',')
- ))
- else:
- url_csv = "%s/cubicwebexport.csv" % url
- url_csv2 = "%s/cubicwebexport2.csv" % url
- filenames += [("cubicwebexport.csv", url_csv, {}),
- ("cubicwebexport2.csv", url_csv2, {})]
+ path = "/".join([
+ "/localizer", "derivatives", "spm_preprocessing",
+ "sub-%s" % subject_id, "sub-%s_T1w.nii.gz" % subject_id])
+ if _is_valid_path(path, index, verbose=verbose):
+ file_url = root_url.format(index[path][1:])
+ opts = {"move": file_path}
+ filenames.append((file_path, file_url, opts))
+ files.setdefault("anats", []).append(file_path)
+
+ # Fetch subject characteristics
+ participants_file = os.path.join("brainomics_data", "participants.tsv")
+ path = "/localizer/participants.tsv"
+ if _is_valid_path(path, index, verbose=verbose):
+ file_url = root_url.format(index[path][1:])
+ opts = {"move": participants_file}
+ filenames.append((participants_file, file_url, opts))
+
+ # Fetch behavioural
+ behavioural_file = os.path.join(
+ "brainomics_data", "phenotype", "behavioural.tsv")
+ path = "/localizer/phenotype/behavioural.tsv"
+ if _is_valid_path(path, index, verbose=verbose):
+ file_url = root_url.format(index[path][1:])
+ opts = {"move": behavioural_file}
+ filenames.append((behavioural_file, file_url, opts))
# Actual data fetching
- dataset_name = 'brainomics_localizer'
- data_dir = _get_dataset_dir(dataset_name, data_dir=data_dir,
- verbose=verbose)
fdescr = _get_dataset_descr(dataset_name)
- files = _fetch_files(data_dir, filenames, verbose=verbose)
- anats = None
- masks = None
- tmaps = None
- # combine data from both covariates files into one single recarray
+ _fetch_files(data_dir, filenames, verbose=verbose)
+ for key, value in files.items():
+ files[key] = [os.path.join(data_dir, val) for val in value]
+
+ # Load covariates file
from numpy.lib.recfunctions import join_by
- ext_vars_file2 = files[-1]
- csv_data2 = np.recfromcsv(ext_vars_file2, delimiter=';')
- files = files[:-1]
- ext_vars_file = files[-1]
- csv_data = np.recfromcsv(ext_vars_file, delimiter=';')
- files = files[:-1]
- # join_by sorts the output along the key
- csv_data = join_by('subject_id', csv_data, csv_data2,
- usemask=False, asrecarray=True)[subject_mask - 1]
- if get_anats:
- anats = files[-n_subjects:]
- files = files[:-n_subjects]
- if get_masks:
- masks = files[-n_subjects:]
- files = files[:-n_subjects]
- if get_tmaps:
- tmaps = files[1::2]
- files = files[::2]
- return Bunch(cmaps=files, tmaps=tmaps, masks=masks, anats=anats,
- ext_vars=csv_data, description=fdescr)
+ participants_file = os.path.join(data_dir, participants_file)
+ csv_data = np.recfromcsv(participants_file, delimiter='\t')
+ behavioural_file = os.path.join(data_dir, behavioural_file)
+ csv_data2 = np.recfromcsv(behavioural_file, delimiter='\t')
+ csv_data = join_by(
+ "participant_id", csv_data, csv_data2, usemask=False, asrecarray=True)
+ subject_names = csv_data["participant_id"].tolist()
+ subjects_indices = []
+ for name in subject_ids:
+ name = name.encode("utf8")
+ if name not in subject_names:
+ continue
+ subjects_indices.append(subject_names.index(name))
+ csv_data = csv_data[subjects_indices]
+
+ return Bunch(ext_vars=csv_data, description=fdescr, **files)
def fetch_localizer_calculation_task(n_subjects=1, data_dir=None, url=None,
@@ -1064,20 +1070,20 @@ def fetch_localizer_calculation_task(n_subjects=1, data_dir=None, url=None,
get_tmaps=False, get_masks=False,
get_anats=False, data_dir=data_dir,
url=url, resume=True, verbose=verbose)
- data.pop('tmaps')
- data.pop('masks')
- data.pop('anats')
return data
-def fetch_localizer_button_task(data_dir=None, url=None, verbose=1):
+def fetch_localizer_button_task(n_subjects=None, data_dir=None, url=None,
+ verbose=1):
"""Fetch left vs right button press contrast maps from the localizer.
- This function ships only 2nd subject (S02) specific tmap and
- its normalized T1 image.
-
Parameters
----------
+ n_subjects: int, optional
+ The number of subjects to load. If None is given,
+ this function ships only 2nd subject (S02) specific tmap and
+ its normalized T1 image.
+
data_dir: string, optional
Path of the data directory. Used to force data storage in a specified
location.
@@ -1093,6 +1099,7 @@ def fetch_localizer_button_task(data_dir=None, url=None, verbose=1):
-------
data: Bunch
Dictionary-like object, the interest attributes are :
+ 'cmaps': string list, giving paths to nifti contrast maps
'tmap': string, giving paths to nifti contrast maps
'anat': string, giving paths to normalized anatomical image
@@ -1109,30 +1116,19 @@ def fetch_localizer_button_task(data_dir=None, url=None, verbose=1):
nilearn.datasets.fetch_localizer_contrasts
"""
- # The URL can be retrieved from the nilearn account on OSF (Open
- # Science Framework). Uploaded files specific to S02 from
- # fetch_localizer_contrasts ['left vs right button press']
- if url is None:
- url = 'https://osf.io/dx9jn/download'
-
- tmap = "t_map_left_auditory_&_visual_click_vs_right_auditory&visual_click.nii.gz"
- anat = "normalized_T1_anat_defaced.nii.gz"
-
- opts = {'uncompress': True}
-
- options = ('tmap', 'anat')
- filenames = [(os.path.join('localizer_button_task', name), url, opts)
- for name in (tmap, anat)]
-
- dataset_name = 'brainomics'
- data_dir = _get_dataset_dir(dataset_name, data_dir=data_dir,
- verbose=verbose)
- files = _fetch_files(data_dir, filenames, verbose=verbose)
-
- fdescr = _get_dataset_descr('brainomics_localizer')
-
- params = dict([('description', fdescr)] + list(zip(options, files)))
- return Bunch(**params)
+ if n_subjects is None:
+ n_subjects = [2]
+ data = fetch_localizer_contrasts(["left vs right button press"],
+ n_subjects=n_subjects,
+ get_tmaps=True, get_masks=False,
+ get_anats=True, data_dir=data_dir,
+ url=url, resume=True, verbose=verbose)
+ # TODO: remove -> only here for compatibility
+ if len(data["tmaps"]) == 1:
+ setattr(data, "tmap", data["tmaps"][0])
+ if len(data["anats"]) == 1:
+ setattr(data, "anat", data["anats"][0])
+ return data
def fetch_abide_pcp(data_dir=None, n_subjects=None, pipeline='cpac',
@@ -1360,7 +1356,7 @@ def _load_mixed_gambles(zmap_imgs):
def fetch_mixed_gambles(n_subjects=1, data_dir=None, url=None, resume=True,
- return_raw_data=False, verbose=0):
+ return_raw_data=False, verbose=1):
"""Fetch Jimura "mixed gambles" dataset.
Parameters
@@ -1380,7 +1376,7 @@ def fetch_mixed_gambles(n_subjects=1, data_dir=None, url=None, resume=True,
resume: bool, optional (default True)
If true, try resuming download if possible.
- verbose: int, optional (default 0)
+ verbose: int, optional (default 1)
Defines the level of verbosity of the output.
return_raw_data: bool, optional (default True)
@@ -1808,7 +1804,7 @@ def fetch_surf_nki_enhanced(n_subjects=10, data_dir=None,
'A00056097', 'A00056098', 'A00056164', 'A00056372', 'A00056452',
'A00056489', 'A00056949']
- nitrc_ids = range(8260, 8470)
+ nitrc_ids = range(8260, 8464)
max_subjects = len(ids)
if n_subjects is None:
n_subjects = max_subjects
@@ -1816,7 +1812,6 @@ def fetch_surf_nki_enhanced(n_subjects=10, data_dir=None,
warnings.warn('Warning: there are only %d subjects' % max_subjects)
n_subjects = max_subjects
ids = ids[:n_subjects]
- nitrc_ids = nitrc_ids[:n_subjects]
# Dataset description
fdescr = _get_dataset_descr(dataset_name)
@@ -1850,13 +1845,13 @@ def fetch_surf_nki_enhanced(n_subjects=10, data_dir=None,
func = os.path.join('%s', '%s_%s_preprocessed_fwhm6.gii')
rh = _fetch_files(data_dir,
[(func % (ids[i], ids[i], 'right'),
- archive % (nitrc_ids[i], ids[i], 'rh'),
+ archive % (nitrc_ids[2*i+1], ids[i], 'rh'),
{'move': func % (ids[i], ids[i], 'right')}
)],
resume=resume, verbose=verbose)
lh = _fetch_files(data_dir,
[(func % (ids[i], ids[i], 'left'),
- archive % (nitrc_ids[i], ids[i], 'lh'),
+ archive % (nitrc_ids[2*i], ids[i], 'lh'),
{'move': func % (ids[i], ids[i], 'left')}
)],
resume=resume, verbose=verbose)
@@ -1995,7 +1990,7 @@ def _fetch_development_fmri_functional(participants, data_dir, url, verbose):
def fetch_development_fmri(n_subjects=None, reduce_confounds=True,
- data_dir=None, resume=True, verbose=0):
+ data_dir=None, resume=True, verbose=1):
"""Fetch movie watching based brain development dataset (fMRI)
The data is downsampled to 4mm resolution for convenience. The origin of
@@ -2024,7 +2019,7 @@ def fetch_development_fmri(n_subjects=None, reduce_confounds=True,
resume: bool, optional (default True)
Whether to resume download of a partly-downloaded file.
- verbose: int, optional (default 0)
+ verbose: int, optional (default 1)
Defines the level of verbosity of the output.
Returns
diff --git a/nilearn/datasets/neurovault.py b/nilearn/datasets/neurovault.py
index 0f51b319ac..7843ddcd3e 100644
--- a/nilearn/datasets/neurovault.py
+++ b/nilearn/datasets/neurovault.py
@@ -2629,8 +2629,6 @@ def fetch_neurovault_motor_task(data_dir=None, verbose=1):
Notes
------
- This function is only a caller for the fetch_localizer_contrasts in order
- to simplify examples reading and understanding.
The 'left vs right button press' contrast is used:
https://neurovault.org/images/10426/
@@ -2673,8 +2671,6 @@ def fetch_neurovault_auditory_computation_task(data_dir=None, verbose=1):
Notes
------
- This function is only a caller for the fetch_localizer_contrasts in order
- to simplify examples reading and understanding.
The 'auditory_calculation_vs_baseline' contrast is used:
https://neurovault.org/images/32980/
diff --git a/nilearn/datasets/tests/data/localizer_behavioural.tsv b/nilearn/datasets/tests/data/localizer_behavioural.tsv
new file mode 100644
index 0000000000..d7c18f0a3c
--- /dev/null
+++ b/nilearn/datasets/tests/data/localizer_behavioural.tsv
@@ -0,0 +1,95 @@
+participant_id nuage2 pente_dots_lin couleur nom_des_gens pb_phono lin_vs_log aspect pb_express facilite_addition espece_plante visu_vb_pour_calcul tv r2_dots_log ratio_pw_w pb_allocentrique pb_rotation details score_cal_complexe activites_pratiques_nb bruxe espece_animales mot pb_lecture moyenne_pw_w trajet score_3d nuage10 nuage11 nuage12 pb_ecriture gaucherie score_addition probleme_ecole facilite_soustraction pente_dots_log arc perspective score_multiplication r2_dots_lin pair1 pair3 pair2 pair5 pair4 itineraire_plan score_soustraction erreur_w imagerie type_pb_langage decomposition niveau_etude francais1erl geometrie coef_bisec pente_sujet_estim_lin pb_prononc seine parle_tard pb_a_l_ecole autoestimation_calcul lettre_miroir rapport_pente_lin_groupe comment nuage3 nuage1 nuage6 nuage7 nuage4 nuage5 strategie nuage8 nuage9 score_tableau_langage pb_binaire erreur_langage droitier erreur_ps_w pb_consonne facilite_multiplication dyslexie visage coef_estim_qt pb_nonlangage bilingue dessin_fini bus billet pente_sujet_estim_log autoevaluation_cx pb_reconnaissance difference_pw_w score_pb_g_d car synaesthete error difficult_apprend_lire pente_bisec orthophoniste lieux orientation normalized_pw autoevaluation_dessin bonne_reconnaissance lycee avion id difficulte_calc_localizer dessin_note_sur_20 rapport_pente_log_groupe score_imageur visuel_verbal algebre pain edimburgh arbre g_contrarie lecture_ok pb_en_3d pb_2eme_langue oiseau pb_egocentrique pseudo pente_estim_qt autoevaluation_rotation pb_orthogr
+S01 35.0 0.416922 n/a n/a False -0.0952051 4.0 False 4.0 n/a 1.0 17.0 0.916693 1.875 False False 2.0 0.966667 n/a 500.0 n/a 8.0 False 11.5 9.0 0.916667 20.0 10.0 35.0 False 0.0 10.0 0.0 4.0 0.749906 40.0 2.0 10.0 0.821488 3.0 23.0 5.0 68.0 43.0 n/a 10.0 1.0 3.0 0 False 4.0 True 4.0 0.985224 0.642131 False 60.0 False False 3.0 False 0.620551 n/a 10.0 25.0 20.0 40.0 50.0 65.0 u 15.0 30.0 4.0 False 0.0 True 3.0 False 4.0 False 1.0 0.969218 False False 1.0 17.0 13.0 0.862849 4.0 0 7.0 0.0 53.0 0 n/a False 0.953448 False 2.0 4.0 0.304348 2.0 lieux 4.0 70.0 165 n/a 18.0 0.85468 9.51389 4.0 4.0 60.0 10.0 30.0 False True False False 2.4 False 15.0 0.988097 4.0 False
+S02 30.0 0.529093 n/a n/a False 0.0151144 3.5 False 3.0 n/a 3.0 20.0 0.954898 1.77778 False False 1.0 0.933333 3.4 700.0 n/a 9.0 False 12.5 5.0 0.916667 30.0 10.0 40.0 False 0.0 10.0 0.0 4.0 0.76985 20.0 2.0 10.0 0.970012 3.0 29.0 4.0 65.0 43.0 n/a 8.0 0.0 3.0 0 True 3.0 True 3.0 0.999742 0.776734 False 50.0 False False 3.0 False 0.787507 n/a 15.0 25.0 20.0 50.0 55.0 70.0 n/a 20.0 60.0 2.5 False 0.0 True 2.0 False 5.0 False 1.0 0.90535 False False 1.0 8.0 10.0 0.873827 3.0 0 7.0 0.0 52.0 n/a n/a False 1.00269 False 1.0 3.0 0.28 1.0 0 3.0 20.0 174 n/a 15.0 0.87741 7.80556 8.0 4.0 90.0 10.0 80.0 False True False False 1.5 False 16.0 1.15221 3.0 False
+S03 35.0 0.45857 n/a n/a False -0.0038151 2.0 False 2.0 n/a 3.0 10.0 0.894501 1.55556 False False 1.0 0.866667 3.6 40.0 0.0 9.0 False 11.5 10.0 0.5 30.0 10.0 40.0 False 0.25 10.0 0.0 3.0 0.715695 100.0 2.0 10.0 0.890686 3.0 33.0 5.0 63.0 42.0 n/a 9.0 0.0 2.0 0 False 4.0 True 3.0 0.995588 0.682245 False 30.0 False False 2.0 False 0.68254 n/a 15.0 30.0 15.0 30.0 50.0 70.0 d 20.0 50.0 4.0 False 0.0 True 0.0 False 4.0 False 2.0 0.658032 False False 1.0 12.0 10.0 0.816513 2.33333 animaux 5.0 0.0 60.0 0 n/a False 0.966338 False 2.0 4.0 0.217391 2.0 visages, lieux 4.0 100.0 204 n/a 12.0 0.815689 7.375 6.0 4.0 80.0 11.0 80.0 False False False False 2.5 False 14.0 0.740778 2.0 False
+S04 20.0 0.240791 1.0 1.0 False 0.0366737 3.5 False 5.0 1.0 1.0 45.0 0.937822 1.58333 True True 2.0 0.766667 3.6 450.0 1.0 12.0 False 15.5 10.0 0.833333 15.0 10.0 25.0 False 0.333333 10.0 0.0 2.0 0.584904 70.0 2.0 9.0 0.974495 3.0 32.0 4.0 55.0 44.0 1.0 9.0 0.0 1.0 0 False 3.0 True 4.0 0.997322 0.356258 False 100.0 False False 3.0 False 0.358396 n/a 10.0 15.0 15.0 25.0 30.0 35.0 d 10.0 30.0 4.0 False 0.0 True 0.0 False 5.0 False 2.0 0.350432 False False 1.0 25.0 12.0 0.668016 4.0 LIEUX 7.0 2.0 50.0 0 n/a False 0.984509 False 0.0 2.0 0.225806 1.0 VISAGE 5.0 250.0 322 n/a 17.0 0.666625 5.52778 6.0 5.0 1.0 14.0 100.0 True True True False 3.5 False 19.0 0.791295 2.0 False
+S05 40.0 0.3345 1.0 1.0 False -0.0530016 1.5 False 3.0 1.0 1.0 10.0 0.914142 1.77778 False True 0.0 0.433333 1.8 400.0 1.0 9.0 False 12.5 8.0 0.583333 20.0 10.0 30.0 False 0.0 9.0 0.0 2.0 0.635478 20.0 0.0 6.0 0.86114 3.0 23.0 3.0 60.0 40.0 1.0 4.0 0.0 3.0 0 True 2.0 True 0.0 0.991584 0.503873 False 50.0 False False 2.0 False 0.497873 n/a 15.0 30.0 20.0 30.0 45.0 50.0 n/a 15.0 40.0 2.0 False 0.0 True 4.0 False 3.0 False 1.0 0.917151 False False 1.0 10.0 10.0 0.724752 0.0 n/a 7.0 0.0 30.0 0 n/a False 1.01049 False 1.0 2.5 0.28 1.0 n/a 0.0 30.0 298 n/a 5.0 0.724264 6.40278 6.0 2.0 40.0 11.0 15.0 False True True True 1.0 False 16.0 1.02732 3.0 False
+S06 30.0 0.52638 n/a n/a False -0.00565731 3.5 False 4.0 n/a 1.0 25.0 0.933403 2.0 False False 2.0 0.633333 3.6 400.0 n/a 9.0 False 13.5 8.0 0.75 20.0 10.0 50.0 False 0.0 10.0 2.0 3.0 0.834941 75.0 2.0 10.0 0.927745 3.0 34.0 4.0 64.0 43.0 n/a 8.0 0.0 3.0 0 False 2.0 True 5.0 0.998702 0.781213 False 20.0 True False 3.0 False 0.783469 n/a 10.0 20.0 20.0 50.0 50.0 70.0 u 20.0 50.0 2.0 True 0.0 True 5.0 False 5.0 False 2.0 0.881779 False False 1.0 15.0 10.0 0.951082 0.0 n/a 9.0 0.0 45.0 0 n/a True 1.01283 False 2.0 3.0 0.333333 1.0 LIEUX VISAGES 3.0 200.0 311 n/a 17.0 0.951596 8.0 4.0 4.0 75.0 10.0 75.0 False True False True 2.0 False 18.0 1.0508 n/a False
+S07 60.0 0.887654 1.0 1.0 False -0.013893 2.0 False 3.0 1.0 1.0 10.0 0.923668 2.0 False True 1.0 0.7 3.8 300.0 1.0 11.0 True 16.5 7.0 0.666667 50.0 15.0 80.0 False 0.25 9.0 2.0 2.0 0.967964 10.0 0.0 10.0 0.909775 3.0 30.0 3.0 62.0 40.0 1.0 6.0 0.0 3.0 aprentissage lecture , difference d/t , p/b a 6ans duree 1ans False 4.0 True 5.0 0.994361 1.30039 False 50.0 False False 2.0 False 1.32119 n/a 10.0 40.0 30.0 100.0 80.0 100.0 d 30.0 100.0 2.0 True 0.0 True 6.0 False 3.0 False 1.0 0.884219 False False 1.0 4.0 10.0 1.09569 2.0 n/a 11.0 0.0 40.0 0 n/a True 1.03761 True 2.0 1.0 0.333333 1.0 LIEUX 4.0 30.0 333 n/a 8.0 1.1032 5.84722 6.0 5.0 40.0 10.0 30.0 False True True False 2.0 False 22.0 0.958523 1.0 False
+S08 30.0 0.378301 n/a n/a False 0.0574613 3.0 False 4.0 n/a 2.0 5.0 0.914426 1.35714 False False 2.0 0.833333 7.0 350.0 n/a 14.0 False 16.5 64.0 0.416667 20.0 15.0 35.0 False 0.0 10.0 0.0 3.0 0.657123 80.0 2.0 10.0 0.971887 3.0 32.0 4.0 63.0 42.0 n/a 8.0 2.0 1.0 0 False 4.0 False 5.0 0.999458 0.551338 False 100.0 False False 3.0 True 0.563067 n/a 10.0 20.0 18.0 35.0 40.0 50.0 u 15.0 50.0 4.0 False 0.0 True 2.0 False 5.0 False 1.0 0.721875 False True 1.0 20.0 10.0 0.74894 4.0 LIEUX 5.0 0.0 30.0 0 n/a False 1.00225 False 0.0 1.5 0.151515 2.0 PHYSIONOMIE 4.0 100.0 290 n/a 16.0 0.748933 4.84722 8.0 4.0 90.0 10.0 80.0 False True False False 1.9 False 19.0 0.959285 3.0 False
+S09 100.0 1.29591 n/a n/a False -0.0193175 4.0 False 3.0 n/a 1.0 12.0 0.943651 1.47826 False True 2.0 0.533333 2.9 800.0 n/a 11.5 False 14.25 10.0 0.5 80.0 15.0 100.0 False 0.2 10.0 0.0 2.0 1.03413 200.0 2.0 10.0 0.924333 3.0 35.0 3.0 55.0 42.0 n/a 6.0 0.0 3.0 0 False 3.0 True 2.0 0.988621 1.94941 False 50.0 False False 1.0 False 1.92885 n/a 20.0 50.0 35.0 110.0 130.0 160.0 u 25.0 120.0 3.0 False 0.0 True 2.0 False 4.0 False 1.0 0.85892 False False 1.0 15.0 8.0 1.18304 0.0 n/a 5.5 0.0 50.0 0 n/a False 1.03538 False 2.0 3.0 0.192982 1.0 LIEUX 2.0 300.0 336 n/a 18.0 1.17861 7.5 4.0 2.0 45.0 14.0 30.0 False True True False 1.5 False 17.0 1.22631 1.0 False
+S10 43.0 0.534045 n/a n/a False 0.0017111 4.5 False 3.0 n/a 1.0 40.0 0.973282 1.66667 False True 2.0 0.6 4.2 500.0 0.0 9.0 True 12.0 10.0 0.583333 27.0 12.0 39.0 False 0.25 8.0 4.0 2.0 0.780877 50.0 2.0 10.0 0.974993 3.0 30.0 3.0 66.0 43.0 n/a 7.0 1.0 3.0 APPRENTISSAGE LECTURE/DYSLEXIE/BEGAIEMENT ZEZAIEMENT False 4.0 True 5.0 0.994773 0.792601 False 70.0 True False 2.0 False 0.794878 n/a 12.0 25.0 25.0 48.0 58.0 70.0 d 19.0 60.0 4.0 True 2.0 True 4.0 True 3.0 True 2.0 0.944997 False False 1.0 12.0 11.0 0.890339 2.33333 animaux 6.0 0.0 50.0 0 n/a True 1.05757 True 1.0 3.0 0.25 3.0 lieux 3.0 80.0 163 n/a 19.0 0.889978 8.06944 6.0 3.0 70.0 10.0 100.0 False True False False 3.0 False 15.0 0.999617 2.0 False
+S11 50.0 0.501391 n/a n/a False -0.155042 3.5 False 4.0 n/a 1.0 25.0 0.877283 1.25 True True 2.0 0.466667 1.6 400.0 n/a 8.0 False 9.0 8.0 0.583333 30.0 10.0 40.0 False 0.0 10.0 0.0 2.0 0.786632 200.0 2.0 7.0 0.722241 3.0 30.0 5.0 70.0 41.0 n/a 6.0 0.0 3.0 MATHS False 2.0 True 1.0 0.994483 0.767568 False 80.0 False True 1.0 True 0.746275 n/a 16.0 38.0 20.0 75.0 55.0 70.0 d 16.0 40.0 2.0 False 3.0 True 1.0 False 4.0 False 2.0 0.918997 False True 1.0 15.0 11.0 0.901555 2.66667 0 2.0 3.0 46.0 Lettres, chiffres, sons, temps, en espace et en couleur n/a False 0.973921 False 2.0 n/a 0.111111 3.0 visages, lieux 1.0 90.0 176 n/a 17.0 0.896537 4.81944 6.0 1.0 80.0 16.0 80.0 False True n/a False 3.0 True 10.0 1.03446 2.0 False
+S12 40.0 0.45318 n/a n/a False -0.0294667 0.5 False 4.0 n/a 2.0 5.0 0.923912 1.75 False True 1.0 0.633333 3.2 500.0 n/a 12.0 False 16.5 8.0 0.5 35.0 12.0 37.0 False 0.25 8.0 2.0 3.0 0.722995 20.0 1.0 7.0 0.894445 3.0 32.0 4.0 60.0 45.0 n/a 8.0 1.0 3.0 FRANCAIS ORTHOGRAPHE LECTURE False 3.0 True 3.0 0.999026 0.676939 False 100.0 False False 3.0 False 0.674518 n/a 12.0 30.0 25.0 35.0 50.0 70.0 u 15.0 50.0 2.0 True 0.0 True 4.0 False 3.0 False 1.0 0.883083 False False 1.0 8.0 15.0 0.822753 3.33333 0 9.0 0.0 56.0 n/a n/a True 1.00245 False 1.0 1.5 0.272727 2.0 0 4.0 40.0 182 n/a 7.0 0.824009 5.91667 6.0 4.0 50.0 11.0 80.0 True True True True 2.0 False 21.0 1.08707 2.0 True
+S13 30.0 0.553522 1.0 1.0 False -0.0442015 3.5 False 3.0 1.0 1.0 12.0 0.962172 1.54545 False True 2.0 1.0 3.8 350.0 1.0 11.0 False 14.0 10.0 0.666667 25.0 10.0 50.0 False 0.2 10.0 0.0 4.0 0.840788 80.0 2.0 10.0 0.91797 3.0 33.0 4.0 70.0 44.0 1.0 10.0 0.0 3.0 0 False 3.0 True 4.0 0.999519 0.797884 False 75.0 False False 3.0 False 0.823867 n/a 12.0 30.0 20.0 59.0 55.0 60.0 d 20.0 70.0 2.0 False 0.0 True 2.0 False 5.0 False 1.0 0.96621 False False 1.0 10.0 15.0 0.94617 5.0 n/a 6.0 0.0 60.0 0 n/a False 1.02888 False 2.0 1.5 0.214286 1.0 LIEUX 5.0 100.0 318 n/a 17.0 0.958259 6.84722 4.0 5.0 85.0 12.0 80.0 False True False False 2.5 False 17.0 1.04223 2.0 False
+S14 40.0 0.536215 n/a n/a False -0.0167022 1.5 False 4.0 n/a 1.0 7.0 0.982381 1.90909 False False 1.0 0.8 3.4 350.0 n/a 11.0 False 16.0 9.0 0.75 25.0 10.0 50.0 False 0.11 10.0 0.0 3.0 0.842689 50.0 1.0 10.0 0.965678 3.0 36.0 4.0 62.0 45.0 n/a 9.0 0.0 3.0 0 False 3.0 True 3.0 0.997089 0.788024 False 60.0 False False 3.0 False 0.798107 n/a 12.0 30.0 20.0 40.0 50.0 70.0 d 15.0 60.0 4.0 False 0.0 True 2.0 False 4.0 False 2.0 0.910639 False False 1.0 20.0 10.0 0.955723 3.33333 0 10.0 0.0 50.0 n/a n/a False 1.01764 False 2.0 2.5 0.3125 1.0 LIEUX VISAGES 4.0 100.0 219 n/a 9.0 0.960426 7.14583 5.0 3.0 60.0 10.0 30.0 False True True n/a 4.0 False 21.0 0.927176 2.0 False
+S15 n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a 366 n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a
+S16 55.0 0.432409 n/a n/a False -0.114653 2.0 False 3.0 n/a 1.0 40.0 0.930288 2.0 False False 1.0 0.633333 3.4 350.0 n/a 7.0 False 10.5 8.0 0.666667 30.0 10.0 55.0 False 0.0 9.0 0.0 2.0 0.735609 50.0 1.0 8.0 0.815635 3.0 30.0 4.0 67.0 43.0 n/a 6.0 0.0 3.0 0 False 4.0 True 3.0 0.99974 0.651471 False 100.0 False False 2.0 False 0.643601 n/a 15.0 35.0 25.0 45.0 50.0 60.0 d 20.0 50.0 4.0 False 0.0 True 3.0 False 3.0 False 2.0 0.896679 False False 1.0 15.0 15.0 0.835647 2.33333 0 7.0 2.0 50.0 n/a n/a False 1.01069 False 1.0 3.5 0.333333 2.0 physionomie 3.0 40.0 194 n/a 10.0 0.838385 7.74306 7.0 3.0 45.0 10.0 80.0 False True n/a False 2.0 True 14.0 0.951493 2.0 False
+S17 50.0 1.90848 n/a n/a False 0.00262361 5.0 False 2.0 n/a 1.0 20.0 0.934938 2.0 True True 2.0 0.266667 1.8 200.0 n/a 11.0 False 16.5 8.0 0.416667 20.0 10.0 100.0 False 0.0 8.0 0.0 n/a 1.48161 30.0 2.0 7.0 0.937562 3.0 30.0 5.0 60.0 40.0 n/a 0.0 1.0 3.0 0 False 3.0 True 4.0 0.995747 2.7377 False 200.0 False False 2.0 False 2.8406 n/a 10.0 50.0 20.0 100.0 130.0 200.0 u 10.0 200.0 3.0 False 0.0 True 2.0 False 3.0 False 2.0 0.744411 False False 1.0 50.0 8.0 1.67618 2.0 0 11.0 2.0 57.0 0 n/a False 0.944038 False 1.0 3.0 0.333333 3.0 Visages 3.0 150.0 205 n/a 20.0 1.68861 8.18056 4.0 3.0 50.0 11.0 100.0 False True False False 2.0 False 22.0 0.940993 3.0 False
+S18 40.0 2.15291 1.0 1.0 False -0.169848 3.5 False 3.0 1.0 1.0 10.0 0.890863 1.41667 False True 2.0 0.466667 3.0 300.0 1.0 12.0 False 14.5 9.0 0.583333 35.0 7.0 40.0 False 0.5 10.0 1.0 2.0 1.41522 20.0 2.0 10.0 0.721015 3.0 30.0 4.0 63.0 43.0 1.0 4.0 0.0 1.0 0 False 2.0 True 3.0 1.0 2.99655 False 10.0 False False 2.0 False 3.20441 n/a 10.0 35.0 25.0 70.0 150.0 200.0 u 20.0 300.0 3.0 True 0.0 True 2.0 False 5.0 False 2.0 0.764588 False False 1.0 4.0 15.0 1.59256 0.0 n/a 5.0 0.0 50.0 0 n/a True 1.0 False 1.0 3.0 0.172414 2.0 VISAGES 1.0 10.0 332 n/a 17.0 1.61294 5.98611 6.0 2.0 80.0 12.0 50.0 False True True True 1.5 False 17.0 0.944911 2.0 False
+S19 40.0 0.396693 n/a n/a False -0.018355 1.0 True 3.0 n/a 2.0 10.0 0.958646 1.64286 True False 1.0 0.5 3.4 600.0 n/a 14.0 False 18.5 8.5 0.666667 30.0 14.0 45.0 False 0.0 6.0 4.0 2.0 0.623431 50.0 0.0 8.0 0.940291 3.0 25.0 4.0 59.0 42.0 n/a 5.0 0.0 3.0 DYSLEXIE DYSORTHOGRAPHIE PB EXPRESSION False 2.0 True 4.0 0.997793 0.589586 False 60.0 True True 2.0 False 0.590441 n/a 15.0 35.0 20.0 45.0 50.0 58.0 d 25.0 50.0 1.0 True 1.0 True 3.0 False 4.0 True 1.0 0.969703 False False 1.0 12.0 11.0 0.708503 2.0 0 9.0 2.0 40.0 0 n/a False 0.970941 True 2.0 4.0 0.243243 1.0 lieux 2.0 110.0 183 n/a 6.0 0.710534 8.53472 5.0 2.0 50.0 10.0 60.0 False True False True 1.5 False 23.0 1.14744 3.0 True
+S20 65.0 0.580366 n/a n/a False -0.0676551 2.5 False 4.0 n/a 1.0 15.0 0.938926 1.875 False True 1.0 0.833333 2.0 300.0 n/a 8.0 False 11.5 8.0 0.666 30.0 15.0 45.0 False 0.0 9.0 0.0 3.0 0.757288 100.0 1.0 9.0 0.871271 3.0 30.0 5.0 63.0 45.0 n/a 8.0 0.0 3.0 0 False 4.0 True 2.0 0.996139 0.879881 False 50.0 False False 2.0 False 0.863822 n/a 15.0 40.0 25.0 50.0 70.0 80.0 d 20.0 60.0 3.0 False 0.0 True 2.0 False 5.0 False 2.0 0.675853 False True 1.0 10.0 20.0 0.867901 3.5 0 7.0 0.0 50.0 n/a n/a False 0.96733 False 1.0 3.0 0.304348 2.0 Visages 3.0 25.0 166 n/a 11.0 0.863093 7.51333 4.0 3.0 70.0 13.0 500.0 False True False False 7.0 False 15.0 0.861326 2.0 False
+S21 75.0 0.827894 n/a n/a False -0.0550406 1.0 False 3.0 n/a 3.0 10.0 0.933896 1.5 False True 1.0 0.6 2.8 500.0 n/a 10.0 False 12.5 11.0 0.25 25.0 10.0 60.0 False 0.2 6.0 0.0 3.0 0.97081 30.0 0.0 9.0 0.878856 3.0 30.0 5.0 60.0 40.0 n/a 4.0 0.0 1.0 n/a False 4.0 True 2.0 0.995747 1.23959 False 20.0 False False 3.0 False 1.23225 n/a 15.0 40.0 25.0 45.0 90.0 100.0 d 20.0 85.0 3.0 False 0.0 True 2.0 False 4.0 False 2.0 0.885648 False False 0.0 10.0 13.0 1.10749 3.0 lieux 5.0 0.0 100.0 n/a n/a False 0.944038 False 0.0 0.0 0.2 1.0 visage 3.0 40.0 104 n/a 4.0 1.10645 1.875 12.0 3.0 60.0 11.0 80.0 False True True False 3.0 False 15.0 0.975003 2.0 False
+S22 50.0 0.310351 n/a n/a False -0.249045 4.0 False 5.0 n/a 1.0 20.0 0.783854 1.5 False False 2.0 0.866667 4.4 300.0 n/a 12.0 False 15.0 7.0 0.666667 20.0 10.0 35.0 False 0.0 9.0 0.0 4.0 0.695147 50.0 2.0 10.0 0.534809 3.0 28.0 4.0 62.0 45.0 n/a 10.0 0.0 3.0 0 False 4.0 True 5.0 0.999154 0.471502 False 40.0 False False 3.0 False 0.461929 n/a 10.0 50.0 20.0 30.0 40.0 50.0 d 15.0 35.0 4.0 False 0.0 True 2.0 False 5.0 False 2.0 0.977155 False True 1.0 15.0 10.0 0.786574 4.33333 0 6.0 0.0 40.0 0 n/a False 0.997375 False 0.0 4.0 0.2 3.0 Visages 4.0 80.0 188 n/a 18.0 0.79227 9.20139 5.0 5.0 70.0 10.0 50.0 False True False False 2.5 False 18.0 0.955999 3.0 False
+S23 50.0 0.508968 1.0 1.0 False -0.0350254 2.5 False 3.0 1.0 1.0 10.0 0.871767 1.54545 False True 1.0 0.433333 2.8 800.0 1.0 11.0 False 14.0 5.0 0.5 20.0 10.0 30.0 False 0.0 10.0 0.0 2.0 0.800143 15.0 0.0 10.0 0.836741 3.0 23.0 4.0 64.0 44.0 1.0 3.0 0.0 3.0 0 False 4.0 True 2.0 0.992409 0.7681 False 30.0 False True 2.0 False 0.757553 n/a 15.0 40.0 15.0 40.0 60.0 70.0 u 15.0 50.0 2.0 False 0.0 True 3.0 False 4.0 False 1.0 0.855351 False False 1.0 10.0 10.0 0.916341 0.0 n/a 6.0 0.0 40.0 0 n/a False 0.984198 False 1.0 2.0 0.214286 2.0 n/a 2.0 40.0 323 n/a 9.0 0.911936 6.14583 7.0 2.0 50.0 10.0 200.0 False True True False 2.0 False 17.0 1.14246 2.0 False
+S24 60.0 0.671362 1.0 1.0 False -0.0573619 3.0 False 3.0 1.0 2.0 25.0 0.944763 0.947368 True True 2.0 0.5 3.2 300.0 1.0 19.0 False 18.5 8.0 0.333333 35.0 10.0 75.0 False 0.0 9.0 0.0 2.0 0.951386 600.0 1.0 9.0 0.887401 3.0 34.0 3.0 57.0 45.0 1.0 6.0 0.0 1.0 0 False 2.0 True 2.0 0.990636 1.00301 False 45.0 False True 1.0 False 0.999262 n/a 10.0 35.0 25.0 60.0 70.0 80.0 u 25.0 70.0 2.0 False 0.0 True 2.0 False 3.0 False 0.0 0.673082 False False 1.0 20.0 20.0 1.08045 0.0 VISAGES -1.0 2.0 30.0 0 n/a False 1.04792 False 2.0 1.5 -0.027027 1.0 LIEUX 3.0 500.0 335 n/a 14.0 1.08431 4.13194 7.0 4.0 90.0 10.0 300.0 False True True True 3.0 False 18.0 1.06108 2.0 False
+S25 50.0 0.688949 1.0 1.0 False -0.0489149 1.0 False 4.0 1.0 1.0 20.0 0.948051 2.0 False True 0.0 0.566667 3.0 500.0 0.0 10.0 False 15.0 8.5 0.666667 40.0 10.0 60.0 False 0.0 10.0 0.0 3.0 0.875224 800.0 1.0 10.0 0.899136 3.0 40.0 5.0 76.0 35.0 1.0 7.0 0.0 3.0 n/a False 2.0 True 2.0 0.979872 1.04007 False 70.0 False False 2.0 False 1.02544 n/a 15.0 30.0 25.0 50.0 70.0 100.0 u 20.0 60.0 4.0 False 0.0 True 1.0 False 4.0 False 1.0 0.575015 False False 1.0 4.0 15.0 1.00105 3.33333 animaux 10.0 2.0 50.0 0 n/a False 0.991503 False 1.0 2.5 0.333333 2.0 n/a 3.0 10.0 9 n/a 6.0 0.997507 7.05556 4.0 3.0 50.0 16.0 6.0 False True False False 1.2 True 20.0 1.09846 3.0 False
+S26 35.0 0.455105 n/a n/a False -0.00552304 1.0 False 2.0 n/a 2.0 5.0 0.96991 2.07692 True True 1.0 0.433333 1.8 240.0 n/a 13.0 True 20.0 12.0 0.25 20.0 10.0 35.0 False 0.2 9.0 3.0 1.0 0.801922 5.0 0.0 10.0 0.964387 3.0 32.0 5.0 64.0 43.0 n/a 4.0 1.0 3.0 dyslexie, pblm de: lecture, inversion de syllabes,dorganisation, emploi du tps False 4.0 True 4.0 0.996225 0.68226 False 10.0 True False 1.0 False 0.677383 n/a 10.0 20.0 17.0 40.0 50.0 60.0 d 15.0 45.0 2.0 True 0.0 True 3.0 False 4.0 True 2.0 0.610165 False False 1.0 6.0 7.0 0.919298 0.0 n/a 14.0 3.0 50.0 0 n/a False 0.969552 True 2.0 2.0 0.35 3.0 VISAGES LIEUX 3.0 15.0 347 n/a 6.0 0.913964 6.52083 5.0 3.0 60.0 10.0 4.0 False True True True 1.5 True 27.0 0.830617 3.0 False
+S27 30.0 0.400822 1.0 1.0 False -0.0253511 2.0 False 4.0 1.0 2.0 4.0 0.941145 1.38462 False False 0.0 0.966667 4.2 300.0 1.0 13.0 False 15.5 8.0 0.75 20.0 10.0 40.0 False 0.0 10.0 0.0 3.0 0.676112 60.0 1.0 10.0 0.915794 3.0 27.0 4.0 65.0 42.0 1.0 10.0 0.0 3.0 0 False 4.0 True 4.0 0.998677 0.60153 False 80.0 False False 3.0 False 0.596588 n/a 15.0 30.0 20.0 40.0 50.0 60.0 d 20.0 40.0 4.0 False 0.0 True 1.0 False 4.0 False 2.0 0.870445 False True 1.0 15.0 16.0 0.768781 3.0 n/a 5.0 0.0 80.0 0 n/a False 0.993971 False 1.0 1.5 0.16129 1.0 VISAGES 4.0 100.0 331 n/a 8.0 0.770575 6.22917 7.0 4.0 50.0 11.0 100.0 False True False False 2.0 False 18.0 1.06635 2.0 False
+S28 53.0 1.08503 n/a n/a False -0.0193036 4.0 False 3.0 n/a 3.0 15.0 0.918141 1.77778 True False 2.0 0.666667 3.2 600.0 n/a 9.0 False 12.5 8.0 0.583333 20.0 10.0 55.0 False 0.0 10.0 0.0 3.0 1.09877 25.0 2.0 9.0 0.898837 3.0 25.0 4.0 65.0 42.0 n/a 7.0 0.0 3.0 0 False 2.0 True 5.0 0.99648 1.60522 False 30.0 False False 2.0 False 1.61497 n/a 15.0 25.0 25.0 105.0 76.0 135.0 u 15.0 90.0 3.0 False 0.0 True 2.0 False 4.0 False 2.0 0.814187 False False 1.0 9.0 16.0 1.25582 2.0 n/a 7.0 2.0 50.0 0 n/a False 0.987764 False 1.0 1.5 0.28 3.0 VIGAGE 5.0 50.0 294 n/a 18.0 1.25228 6.56944 8.0 5.0 70.0 13.0 50.0 False True False True 12.0 False 16.0 0.81182 2.0 False
+S29 34.0 0.403552 n/a n/a False -0.032888 3.5 False 3.0 n/a 2.0 5.0 0.915869 1.8 False True 2.0 0.433333 3.0 800.0 2.0 10.0 False 14.0 10.0 0.666667 15.0 10.0 30.0 False 0.0 8.0 0.0 3.0 0.737564 500.0 2.0 10.0 0.882981 3.0 33.0 4.0 57.0 42.0 1.0 5.0 0.0 3.0 0 False 2.0 True 4.0 0.997662 0.613726 False 40.0 False False 2.0 False 0.600651 n/a 10.0 20.0 20.0 35.0 47.0 60.0 d 15.0 35.0 4.0 False 0.0 True 1.0 False 4.0 False 2.0 0.404527 False False 1.0 10.0 15.0 0.84771 0.0 n/a 8.0 0.0 40.0 0 n/a False 0.987342 False 1.0 1.5 0.285714 3.0 VISAGES ANIMAUX 4.0 500.0 330 n/a 17.0 0.840613 7.01389 4.0 4.0 1.0 11.0 300.0 False True False False 3.0 False 18.0 1.08016 3.0 False
+S30 60.0 0.46732 n/a n/a False -0.281506 1.0 False 4.0 n/a 1.0 50.0 0.818848 1.88889 False False 0.0 0.566667 3.6 400.0 n/a 9.0 False 13.0 10.0 0.75 30.0 10.0 40.0 False 0.5 9.0 0.0 3.0 0.757308 70.0 1.0 8.0 0.537342 3.0 25.0 5.0 62.0 42.0 n/a 7.0 0.0 3.0 0 False 4.0 True 4.0 0.9921 0.72291 False 250.0 False False 2.0 False 0.695564 n/a 15.0 40.0 30.0 90.0 60.0 60.0 u 20.0 40.0 3.0 False 0.0 True 3.0 False 3.0 False 2.0 0.78383 False False 1.0 15.0 15.0 0.864595 3.33333 0 8.0 0.0 50.0 nombre / espace n/a False 0.941167 False 1.0 4.0 0.307692 1.0 Visages 3.0 60.0 177 n/a 6.0 0.863115 8.60417 5.0 2.0 50.0 10.0 20.0 False True False False 1.0 False 17.0 1.05261 3.0 False
+S31 40.0 0.580558 n/a n/a False 0.0131732 2.5 False 4.0 n/a 2.0 5.0 0.967509 1.46154 False True 1.0 0.533333 4.4 800.0 n/a 13.0 False 16.0 11.0 0.666667 20.0 11.0 40.0 False 0.0 10.0 0.0 1.0 0.868769 200.0 1.0 10.0 0.980682 3.0 30.0 4.0 63.0 45.0 n/a 4.0 0.0 2.0 0 False 4.0 True 3.0 0.999827 0.86083 False 600.0 False False 2.0 False 0.864108 n/a 12.0 25.0 18.0 50.0 60.0 70.0 d 14.0 60.0 4.0 False 0.0 True 5.0 False 4.0 False 0.0 0.789305 False False 1.0 7.0 12.0 0.993075 4.0 VISAGE 6.0 0.0 50.0 0 n/a False 1.00572 False 2.0 3.0 0.1875 2.0 LIEUX 3.0 150.0 295 n/a 11.0 0.99015 6.74306 5.0 4.0 80.0 10.0 300.0 False True True False 2.5 False 19.0 1.33373 2.0 False
+S32 60.0 1.50179 n/a n/a False -0.0628016 0.0 False 4.0 n/a 1.0 10.0 0.937975 1.57143 False True 0.0 0.833333 3.6 500.0 0.0 14.0 False 18.0 7.0 n/a 40.0 15.0 120.0 False 0.0 10.0 0.0 3.0 1.12305 20.0 0.0 8.0 0.875174 3.0 27.0 4.0 64.0 43.0 n/a 9.0 0.0 1.0 0 False 4.0 True 5.0 0.998799 2.15269 False 60.0 False False 3.0 False 2.23528 n/a 15.0 40.0 30.0 150.0 100.0 150.0 d 30.0 170.0 4.0 False 1.0 True 0.0 False 4.0 False 0.0 0.866485 False False 1.0 10.0 15.0 1.26973 3.33333 Visages animaux 8.0 0.0 40.0 0 n/a False 0.994238 False 2.0 2.5 0.222222 1.0 lieux 5.0 150.0 185 n/a 2.0 1.27996 4.5625 5.0 5.0 80.0 14.0 15.0 True True False False 2.0 False 22.0 1.06178 n/a False
+S33 80.0 1.00954 n/a n/a False -0.037087 2.0 False 3.0 n/a 3.0 6.0 0.970922 1.875 True True 1.0 0.733333 2.8 400.0 n/a 8.0 True 11.5 11.0 0.583333 35.0 10.0 90.0 False 0.2 7.0 2.0 4.0 1.07425 30.0 2.0 9.0 0.933835 3.0 32.0 4.0 65.0 42.0 n/a 10.0 0.0 3.0 apprentissage lecture False 3.0 True 4.0 0.999484 1.50266 False 80.0 False False 2.0 False 1.5026 n/a 15.0 50.0 25.0 90.0 100.0 110.0 u 25.0 100.0 3.0 True 0.0 True 1.0 False 5.0 False 1.0 0.882616 False False 1.0 20.0 15.0 1.22089 3.33333 0 7.0 2.0 100.0 0 n/a True 1.00767 False 1.0 2.0 0.304348 2.0 0 3.0 150.0 216 n/a 12.0 1.22434 6.61111 6.0 4.0 80.0 10.0 70.0 False True False False 2.5 False 15.0 1.04328 1.0 False
+S34 39.0 0.546959 n/a n/a False -0.0169346 3.5 False 2.0 n/a 1.0 20.0 0.978523 1.77778 False False 2.0 0.766667 3.0 350.0 n/a 9.0 False 12.5 8.0 1.0 29.0 13.0 55.0 False 0.33 10.0 0.0 2.0 0.790664 50.0 2.0 10.0 0.961589 3.0 33.0 4.0 72.0 44.0 n/a 9.0 0.0 3.0 timbre de voix False 3.0 True n/a 0.999336 0.808399 False 90.0 False False 2.0 False 0.8141 n/a 13.0 36.0 21.0 50.0 60.0 70.0 d 18.0 60.0 4.0 False 0.0 True 0.0 False 3.0 False 1.0 0.95104 True False 1.0 17.0 13.0 0.897307 1.66667 0 7.0 0.0 40.0 n/a n/a False 1.03377 True 2.0 3.0 0.28 2.0 lieux 2.0 50.0 191 n/a 17.0 0.901132 7.875 4.0 2.0 75.0 16.0 100.0 False True True False 3.0 False 16.0 0.952927 3.0 False
+S35 45.0 0.739662 n/a n/a False -0.0104976 3.0 False 4.0 n/a 1.0 4.0 0.956899 2.1 True False 1.0 0.533333 2.4 350.0 n/a 10.0 False 15.5 9.0 0.833333 30.0 12.0 50.0 False 0.6 7.0 0.0 1.0 0.966636 30.0 0.0 8.0 0.946401 3.0 32.0 4.0 70.0 43.0 n/a 3.0 0.0 1.0 positionement main gauche False 4.0 True 4.0 0.999391 1.07854 False 8.0 False False 2.0 False 1.10092 n/a 10.0 30.0 30.0 75.0 70.0 80.0 d 15.0 85.0 3.0 False 1.0 True 2.0 False 4.0 False 1.0 0.814216 True False 1.0 5.0 6.0 1.09427 2.66667 0 11.0 2.0 60.0 0 n/a False 1.02351 True 1.0 4.0 0.354839 1.0 0 4.0 60.0 192 n/a 10.0 1.10169 6.90278 6.0 1.0 50.0 13.0 20.0 True True False False 2.5 False 21.0 0.995345 2.0 False
+S36 24.0 0.373996 n/a n/a False 0.0331708 0.5 False 4.0 n/a 1.0 4.0 0.885147 2.22222 False True 0.0 0.8 2.8 450.0 n/a 9.0 False 14.5 7.0 0.583333 20.0 11.0 39.0 False 0.5 9.0 0.0 3.0 0.668698 167.0 0.0 9.0 0.918318 3.0 28.0 4.0 55.0 43.0 n/a 7.0 0.0 3.0 0 False 4.0 True 2.0 0.998932 0.556324 False 30.0 False False 3.0 False 0.556659 n/a 13.0 15.0 16.0 35.0 45.0 50.0 u 15.0 41.0 4.0 False 0.0 True 2.0 False 4.0 False 1.0 0.856854 False True 1.0 7.0 11.0 0.768194 3.66667 0 11.0 0.0 45.0 0 n/a False 0.970847 False 1.0 1.0 0.37931 2.0 tout 2.0 30.0 200 n/a 3.0 0.762126 5.50694 5.0 2.0 70.0 12.0 40.0 False True True False 2.5 False 20.0 1.08659 3.0 False
+S37 60.0 1.20749 n/a n/a False 0.00848409 4.0 False 0.0 n/a 3.0 20.0 0.911086 1.33333 False False 2.0 0.733333 3.8 300.0 n/a 9.0 False 10.5 9.0 0.833333 45.0 15.0 85.0 False 0.0 6.0 0.0 0.0 0.988676 60.0 2.0 10.0 0.91957 3.0 30.0 4.0 64.0 44.0 n/a 8.0 0.0 3.0 0 False 4.0 True 3.0 0.999972 1.76399 False 45.0 False False 3.0 False 1.79724 n/a 16.0 26.0 30.0 60.0 100.0 150.0 d 25.0 130.0 4.0 False 0.0 True 5.0 False 0.0 False 1.0 0.957402 False True 1.0 15.0 12.0 1.12971 0.0 n/a 3.0 0.0 50.0 0 n/a False 1.00563 False 2.0 4.0 0.142857 1.0 LIEUX,VISAGE 5.0 35.0 291 n/a 18.0 1.12681 8.63194 7.0 2.0 90.0 13.0 80.0 False True True False 2.5 False 12.0 0.938097 2.0 False
+S38 n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a 368 n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a
+S39 50.0 0.621052 n/a n/a False -0.0259647 0.5 False 5.0 n/a 1.0 25.0 0.923161 1.58333 False False 0.0 0.733333 2.8 800.0 n/a 12.0 False 15.5 10.0 0.666667 25.0 10.0 30.0 False 0.0 9.0 0.0 4.0 0.840421 110.0 0.0 10.0 0.897196 3.0 30.0 5.0 61.0 41.0 n/a 10.0 0.0 3.0 LANGUES False 4.0 True 5.0 0.995976 0.934155 False 50.0 False False 2.0 False 0.924379 n/a 15.0 30.0 20.0 60.0 70.0 80.0 d 20.0 60.0 2.0 False 0.0 True 2.0 False 4.0 False 2.0 0.947885 True False 1.0 13.0 10.0 0.962968 4.0 0 7.0 0.0 58.0 n/a n/a False 0.950016 False 2.0 4.0 0.225806 1.0 visages, lieux 4.0 100.0 139 n/a 3.0 0.957841 8.68056 4.0 5.0 80.0 10.0 30.0 False True False True 2.0 False 19.0 1.13179 3.0 False
+S40 60.0 0.669262 n/a n/a False -0.120663 3.0 False 4.0 n/a 1.0 6.0 0.869703 1.26667 False True 2.0 0.85 2.8 400.0 n/a 15.0 False 17.0 6.0 0.75 30.0 12.0 35.0 False 0.29 10.0 0.0 3.0 0.798569 80.0 1.0 10.0 0.74904 3.0 22.0 3.0 61.0 42.0 0.0 7.0 0.0 2.0 0 False 4.0 True 2.0 0.988815 1.03409 False 100.0 False False 1.0 True 0.996137 n/a 15.0 30.0 28.0 50.0 70.0 110.0 d 18.0 45.0 4.0 False 0.0 True 0.0 False 3.0 False 2.0 0.917762 False False 1.0 7.0 18.0 0.923717 3.5 lieux 4.0 0.0 60.0 Chiffres lettres, noms, mots / couleurs, prenoms / gout, toucher, nombres / temps n/a False 1.01591 False 1.0 2.0 0.117647 2.0 Visages 3.0 50.0 197 n/a 14.0 0.910141 5.83333 6.0 2.0 70.0 10.0 90.0 False True False False 2.0 False 19.0 1.1343 2.0 False
+S41 50.0 0.634911 n/a n/a False -0.123459 1.5 False 4.0 n/a 3.0 6.0 0.911603 1.33333 False True 0.0 0.8 5.0 400.0 n/a 12.0 False 14.0 10.0 0.583333 25.0 10.0 40.0 False 0.0 10.0 0.0 3.0 0.892371 60.0 1.0 10.0 0.788143 3.0 27.0 3.0 63.0 41.0 n/a 10.0 0.0 3.0 0 False 2.0 True 2.0 0.994467 0.985329 False 75.0 False False 2.0 False 0.945008 n/a 12.0 30.0 20.0 50.0 80.0 90.0 d 15.0 40.0 4.0 False 0.0 True 1.0 False 5.0 False 1.0 0.910247 False False 1.0 20.0 10.0 1.03135 2.0 n/a 4.0 0.0 50.0 0 n/a False 1.035 False 1.0 1.0 0.142857 1.0 n/a 4.0 80.0 348 n/a 7.0 1.01705 5.29861 7.0 4.0 40.0 11.0 50.0 False True True False 3.0 False 16.0 0.979685 2.0 False
+S42 70.0 0.971599 n/a n/a False -0.0145183 3.0 False 3.0 n/a 3.0 20.0 0.93927 1.83333 False False 1.0 0.9 3.4 500.0 n/a 12.0 False 17.0 10.0 0.666667 30.0 15.0 77.0 False 0.0 10.0 0.0 2.0 0.955744 50.0 1.0 10.0 0.924752 3.0 32.0 4.0 65.0 44.0 2.0 10.0 0.0 3.0 0 True 4.0 True 4.0 0.99983 1.46297 False 250.0 False False 3.0 False 1.44614 n/a 15.0 40.0 20.0 70.0 90.0 130.0 d 25.0 80.0 4.0 False 0.0 True 0.0 False 4.0 False 2.0 0.893647 False False 1.0 15.0 15.0 1.09782 2.0 n/a 10.0 0.0 70.0 0 n/a False 1.01353 False 2.0 2.0 0.294118 3.0 VISAGE, LIEUX,PHYSIONOMIE 5.0 130.0 324 n/a 12.0 1.08928 6.53472 9.0 4.0 65.0 11.0 50.0 False True False False 4.0 False 22.0 1.00161 2.0 False
+S43 50.0 0.444483 n/a n/a False -0.0592845 2.5 False 3.0 n/a 2.0 35.0 0.889422 1.91667 False False 2.0 0.933333 3.2 600.0 n/a 12.0 False 17.5 7.0 0.916667 25.0 15.0 40.0 False 0.0 10.0 0.0 2.0 0.608799 40.0 1.0 10.0 0.830138 3.0 22.0 4.0 68.0 43.0 n/a 9.0 1.0 3.0 0 False 2.0 True 3.0 0.988576 0.669578 False 100.0 False False 2.0 False 0.661573 n/a 20.0 50.0 25.0 50.0 60.0 70.0 u 25.0 50.0 4.0 False 0.0 True 1.0 False 4.0 False 0.0 0.8933 False False 1.0 12.0 18.0 0.692751 3.0 VISAGES 11.0 0.0 50.0 0 n/a False 0.988251 False 2.0 3.0 0.314286 1.0 LIEUX 5.0 40.0 349 n/a 13.0 0.693858 7.93056 6.0 4.0 60.0 12.0 25.0 False True False True 2.5 False 23.0 0.986973 3.0 False
+S44 60.0 1.05413 n/a n/a False -0.0291271 5.0 False 4.0 n/a 2.0 10.0 0.913654 1.07692 False True 2.0 0.666667 2.4 600.0 n/a 13.0 False 13.5 10.0 0.833333 50.0 15.0 65.0 False 0.0 10.0 0.0 3.0 0.863541 20.0 2.0 7.0 0.884527 3.0 25.0 5.0 55.0 42.0 n/a 10.0 0.0 3.0 0 False 4.0 True 2.0 0.99285 1.59484 False 100.0 False True 2.0 True 1.56897 n/a 25.0 40.0 25.0 78.0 115.0 150.0 u 30.0 85.0 3.0 False 1.0 True 2.0 False 3.0 False 2.0 0.6925 False False 1.0 6.0 15.0 0.99406 0.0 n/a 1.0 0.0 50.0 0 n/a False 0.920358 False 2.0 1.5 0.037037 3.0 VISAGE ET LIEUX 2.0 15.0 293 n/a 20.0 0.984191 6.73611 6.0 1.0 80.0 13.0 6.0 False True False False 3.0 False 14.0 0.943294 3.0 False
+S45 30.0 0.287899 n/a n/a False -0.0142111 1.5 False 4.0 n/a 3.0 30.0 0.89745 2.4 False True 1.0 0.733333 3.4 600.0 n/a 10.0 False 17.0 6.0 0.583333 20.0 6.0 20.0 False 0.25 9.0 0.0 3.0 0.706925 80.0 1.0 9.0 0.883239 3.0 27.0 5.0 70.0 45.0 n/a 7.0 0.0 3.0 0 False 4.0 True 3.0 0.992768 0.419834 False 30.0 False False 2.0 False 0.428512 n/a 12.0 25.0 15.0 30.0 30.0 40.0 u 12.0 40.0 2.0 False 0.0 True 2.0 False 5.0 False 1.0 0.912762 False False 1.0 8.0 12.0 0.796829 3.33333 0 14.0 0.0 40.0 0 n/a False 0.977134 False 2.0 2.5 0.411765 1.0 lieux 3.0 60.0 170 n/a 9.0 0.805694 7.23611 6.0 3.0 50.0 10.0 100.0 False True False False 3.0 False 24.0 1.04265 4.0 False
+S46 50.0 0.719223 n/a n/a False -0.0376729 3.0 False 2.0 n/a 1.0 150.0 0.917437 1.69231 True True 2.0 0.733333 2.6 400.0 n/a 13.0 False 17.5 6.0 0.5 25.0 15.0 80.0 False 0.0 10.0 0.0 2.0 0.927479 40.0 1.0 10.0 0.879764 3.0 30.0 5.0 52.0 40.0 0.0 8.0 0.0 3.0 0 False 4.0 True 4.0 0.994182 1.05988 False 200.0 False False 2.0 False 1.0705 n/a 10.0 30.0 20.0 70.0 65.0 80.0 d 20.0 75.0 1.0 False 0.0 True 4.0 False 3.0 False 2.0 0.743006 False False 1.0 20.0 13.0 1.05708 1.0 FLEURS 9.0 2.0 50.0 0 n/a False 0.919182 False 2.0 2.5 0.257143 1.0 VISAGES LIEUX 4.0 150.0 337 n/a 14.0 1.05706 7.20833 6.0 4.0 80.0 15.0 100.0 False True True True 3.0 False 22.0 0.976954 2.0 False
+S47 50.0 0.747239 n/a n/a False -0.0657451 4.0 False 4.0 n/a 2.0 n/a 0.91669 1.81818 False True 2.0 0.533333 3.6 n/a n/a 11.0 False 15.5 n/a 0.916667 25.0 12.0 45.0 False 0.0 6.0 0.0 2.0 0.839307 n/a 2.0 10.0 0.850945 3.0 30.0 4.0 60.0 45.0 n/a 9.0 0.0 3.0 0 False 2.0 True 2.0 0.999447 1.11427 False n/a False False 3.0 False 1.1122 n/a 18.0 40.0 30.0 45.0 100.0 90.0 d 20.0 80.0 1.0 False 2.0 True 1.0 False 4.0 False 1.0 n/a False False 1.0 n/a n/a 0.95479 2.66667 0 9.0 0.0 n/a n/a n/a False 0.997244 False 1.0 2.5 0.290323 2.0 0 4.0 n/a 218 n/a 18.0 0.956572 7.24306 9.0 4.0 n/a 10.0 n/a False True False False n/a False 20.0 n/a 3.0 False
+S48 30.0 0.507131 n/a n/a False -0.00956098 0.5 False 2.0 n/a 1.0 20.0 0.939729 2.77778 False True 0.0 0.733333 4.0 500.0 n/a 9.0 False 17.0 7.0 0.833333 20.0 10.0 40.0 False 0.0 10.0 0.0 3.0 0.824241 40.0 1.0 10.0 0.930168 3.0 30.0 5.0 65.0 43.0 n/a 9.0 0.0 2.0 0 False 4.0 True 4.0 0.996104 0.752623 False 20.0 False False 2.0 True 0.754819 n/a 10.0 20.0 15.0 30.0 50.0 70.0 d 15.0 50.0 4.0 False 0.0 True 0.0 False 4.0 False 1.0 0.917877 False False 1.0 15.0 7.0 0.943009 2.33333 lieux 16.0 0.0 52.0 n/a n/a False 0.96704 False 0.0 0.0 0.470588 1.0 Visages 4.0 70.0 168 n/a 5.0 0.9394 4.09028 7.0 5.0 50.0 13.0 30.0 False True True False 3.0 False 25.0 0.966885 2.0 False
+S49 30.0 0.329163 n/a n/a False -0.0534856 2.0 False 3.0 n/a 1.0 7.0 0.781903 2.09091 False False 1.0 0.8 3.0 400.0 n/a 11.0 True 17.0 10.0 0.833333 20.0 10.0 25.0 False 0.0 9.0 3.0 3.0 0.616801 30.0 2.0 9.0 0.728418 3.0 27.0 4.0 62.0 42.0 n/a 7.0 0.0 3.0 APPRENTISSAGE LECTURE / DYSLEXIE False 4.0 True 3.0 0.999214 0.50128 False 50.0 False False 2.0 False 0.489929 n/a 10.0 20.0 30.0 25.0 50.0 55.0 u 20.0 35.0 2.0 True 0.0 True 1.0 True 3.0 True 2.0 0.942988 False False 1.0 8.0 10.0 0.704073 3.0 0 12.0 0.0 40.0 0 n/a True 0.985763 True 1.0 3.5 0.352941 2.0 Visages 3.0 100.0 171 n/a 12.0 0.702978 8.17361 5.0 4.0 45.0 10.0 60.0 False True False False 1.2 False 23.0 1.1189 2.0 False
+S50 60.0 0.801137 n/a n/a False -0.0291117 0.5 False 4.0 n/a 1.0 50.0 0.98375 1.66667 False True 0.5 0.666667 2.6 n/a n/a 9.0 False 12.0 10.0 0.666667 40.0 15.0 80.0 False 0.25 10.0 0.0 3.0 0.826063 60.0 0.0 10.0 0.954638 3.0 25.0 5.0 63.0 43.0 n/a 7.0 1.0 3.0 n/a False 4.0 True 3.0 0.991647 1.16622 False 30.0 False False 2.0 False 1.19242 n/a 20.0 50.0 30.0 70.0 80.0 95.0 u 27.0 100.0 4.0 False 0.0 True 1.0 False 4.0 False 0.0 n/a False False 1.0 8.0 12.5 0.933209 3.33333 visage 6.0 0.0 70.0 n/a n/a False 0.946907 False 1.0 1.5 0.25 1.0 n/a 3.0 150.0 117 n/a 4.0 0.941477 6.13889 4.0 3.0 75.0 10.0 250.0 False False True True 1.5 False 15.0 n/a 2.0 False
+S51 120.0 0.902599 n/a n/a False -0.231889 4.0 False 3.0 n/a 2.0 10.0 0.752758 1.71429 False True 1.0 0.833333 2.6 700.0 n/a 7.0 False 9.5 7.0 0.833333 50.0 17.0 54.0 False 0.17 10.0 0.0 2.0 0.812932 30.0 2.0 10.0 0.520869 3.0 30.0 4.0 60.0 40.0 n/a 7.0 0.0 2.0 0 False 4.0 True 3.0 0.999712 1.25798 False 200.0 False False 2.0 False 1.34344 n/a 20.0 80.0 42.0 120.0 50.0 90.0 d 30.0 160.0 4.0 False 0.0 True 2.0 False 4.0 False 1.0 0.89375 False False 1.0 10.0 18.0 0.90344 2.66667 0 5.0 0.0 40.0 n/a n/a False 0.982427 False 1.0 1.5 0.263158 2.0 0 2.0 100.0 173 n/a 16.0 0.926512 5.69444 8.0 3.0 60.0 11.0 115.0 False True True False 2.0 False 12.0 1.1715 3.0 False
+S52 55.0 0.87824 n/a n/a False -0.00832569 2.0 False 5.0 n/a 1.0 20.0 0.971116 1.77778 True True 1.0 0.766667 2.6 400.0 n/a 9.0 False 12.5 7.0 0.5 35.0 10.0 75.0 False 0.0 8.0 0.0 2.0 1.0228 75.0 1.0 7.0 0.96279 3.0 25.0 4.0 61.0 42.0 n/a 9.0 0.0 1.0 0 False 4.0 True 1.0 0.997485 1.29562 False 150.0 False False 1.0 True 1.30718 n/a 12.0 30.0 25.0 80.0 80.0 100.0 u 25.0 90.0 3.0 False 0.0 True 2.0 False 4.0 False 2.0 0.855701 False False 1.0 20.0 12.0 1.16281 3.66667 0 7.0 2.0 60.0 0 n/a False 0.976732 False 1.0 2.0 0.28 2.0 Visages 3.0 100.0 206 n/a 10.0 1.1657 4.66667 4.0 5.0 60.0 10.0 15.0 False True False False 2.0 False 16.0 1.02892 2.0 False
+S53 57.0 0.721953 1.0 1.0 False -0.038159 2.0 False 3.0 1.0 2.0 21.0 0.949123 2.0 False True 1.0 0.6 2.0 400.0 1.0 10.0 False 15.0 7.0 0.666667 18.0 8.0 47.0 False 0.5 10.0 0.0 2.0 1.04459 500.0 2.0 9.0 0.910964 3.0 25.0 4.0 53.0 34.0 1.0 8.0 0.0 3.0 "confusion entre ""p""et""b"",""a"" et""d"",""v""et""f"" a9ans pendant3-4mois " True 2.0 False 3.0 0.999318 1.09054 False 40.0 False False 2.0 False 1.07456 n/a 11.0 36.0 22.0 52.0 78.0 89.0 u 13.0 61.0 2.0 False 1.0 True 6.0 True 3.0 False 1.0 0.727899 False False 1.0 9.0 17.0 1.19193 0.0 n/a 10.0 0.0 40.0 0 n/a False 0.92573 True 1.0 1.5 0.333333 1.0 n/a 4.0 60.0 299 n/a 12.0 1.19054 6.53472 5.0 4.0 70.0 12.0 12.0 False True False False 1.8 False 20.0 1.04877 3.0 False
+S54 38.0 0.383918 n/a 0.0 False -0.103711 1.0 False 3.0 n/a 3.0 5.0 0.86639 1.8 True True 1.0 0.666667 2.8 300.0 n/a 10.0 False 14.0 12.0 0.75 20.0 10.0 30.0 False 0.33 8.0 1.0 3.0 0.731965 10.0 1.0 9.0 0.76268 3.0 30.0 4.0 64.0 42.0 n/a 9.0 0.0 2.0 DYSORTHOGRAPHIE DYSLEXIE False 3.0 True 2.0 0.999901 0.594111 False 20.0 False False 2.0 False 0.571427 n/a 10.0 25.0 15.0 25.0 50.0 60.0 u 12.0 30.0 4.0 True 0.0 True 1.0 True 4.0 True 2.0 0.799681 False False 0.0 4.0 8.0 0.846727 3.0 noms 8.0 2.0 45.0 n/a n/a False 0.999775 True 1.0 1.5 0.285714 1.0 Visages 2.0 12.0 179 n/a 6.0 0.834232 4.625 12.0 2.0 40.0 10.0 50.0 False True True False 1.5 False 18.0 0.95225 3.0 False
+S55 38.0 0.351037 n/a n/a False -0.0959172 2.5 False 2.0 n/a 2.0 15.0 0.874188 1.4 True True 2.0 0.53 2.6 500.0 n/a 10.0 False 12.0 8.0 0.5 19.0 9.0 25.0 False 0.0 10.0 0.0 2.0 0.670693 75.0 1.0 7.0 0.778271 3.0 28.0 4.0 75.0 45.0 n/a 5.0 1.0 3.0 0 False 3.0 True 1.0 0.997022 0.542072 False 35.0 False False 1.0 True 0.522487 n/a 13.0 27.0 20.0 39.0 45.0 57.0 d 15.0 29.0 4.0 False 0.0 True 2.0 False 3.0 False 1.0 0.969419 False False 1.0 10.0 13.0 0.771524 2.0 n/a 4.0 3.0 45.0 0 n/a False 1.03044 False 2.0 3.0 0.166667 3.0 LIEUX 2.0 50.0 297 n/a 13.0 0.764399 7.08333 6.0 1.0 55.0 10.0 75.0 False True True False 2.5 True 14.0 1.02732 2.0 False
+S56 50.0 0.728235 1.0 1.0 False -0.0200327 2.5 False 3.0 1.0 2.0 13.0 0.958526 1.55556 False False 1.0 0.7 3.0 450.0 1.0 9.0 False 11.5 9.0 0.666667 30.0 10.0 40.0 False 0.0 8.0 0.0 2.0 0.891965 35.0 2.0 9.0 0.938493 3.0 32.0 5.0 62.0 44.0 1.0 6.0 0.0 3.0 zozottement False 3.0 True 4.0 0.996171 1.08598 False 45.0 False False 2.0 False 1.08391 n/a 15.0 30.0 20.0 50.0 70.0 100.0 d 20.0 70.0 0.0 False 1.0 True 1.0 False 4.0 False 2.0 0.976141 True False 1.0 13.0 14.0 1.02026 2.66667 n/a 5.0 0.0 45.0 0 n/a False 0.966929 True 1.0 1.0 0.217391 1.0 visage 3.0 75.0 39 n/a 13.0 1.01659 6.15972 5.0 3.0 80.0 13.0 35.0 False True True True 3.0 False 14.0 0.967209 2.0 False
+S57 45.0 0.543197 n/a n/a False -0.036005 0.5 False 4.0 n/a 1.0 20.0 0.969654 2.0 False False 0.0 0.766667 2.4 700.0 n/a 9.0 False 13.5 6.5 0.583333 30.0 10.0 60.0 False 0.13 10.0 0.0 1.0 0.817328 30.0 1.0 10.0 0.933649 3.0 25.0 4.0 60.0 45.0 n/a 10.0 0.0 3.0 0 False 3.0 True 4.0 0.996329 0.804771 False 50.0 False False 2.0 False 0.8085 n/a 15.0 30.0 25.0 50.0 55.0 70.0 d 17.0 60.0 1.0 False 0.0 True 0.0 False 4.0 False 2.0 0.930744 False False 0.0 10.0 15.0 0.927787 2.33333 0 9.0 0.0 50.0 0 n/a False 0.98254 False 2.0 3.0 0.333333 2.0 visages, lieux 4.0 25.0 181 n/a 3.0 0.931521 7.61111 4.0 2.0 80.0 12.0 80.0 False True True False 1.2 False 18.0 1.14636 3.0 False
+S58 49.0 0.482002 n/a n/a False -0.0484288 1.5 False 5.0 n/a 1.0 10.0 0.95826 2.5 False False 1.0 0.933333 4.2 450.0 n/a 8.0 False 14.0 6.0 0.833333 30.0 10.0 50.0 False 0.2 9.0 0.0 4.0 0.770706 30.0 1.0 9.0 0.909831 3.0 35.0 4.0 62.0 45.0 n/a 9.0 0.0 3.0 0 False 4.0 True 4.0 0.997881 0.72737 False 50.0 False False 3.0 False 0.717416 n/a 15.0 30.0 20.0 50.0 55.0 65.0 u 20.0 50.0 4.0 False 0.0 True 4.0 False 5.0 False 1.0 0.950643 False True 1.0 14.0 12.0 0.880939 4.33333 0 12.0 0.0 50.0 0 n/a False 1.01537 False 1.0 3.0 0.428571 2.0 0 4.0 30.0 201 n/a 9.0 0.878385 8.06944 4.0 4.0 100.0 10.0 40.0 False True True False 2.5 False 20.0 1.01326 3.0 False
+S59 80.0 1.21402 n/a n/a False -0.0345568 0.0 False 3.0 n/a 1.0 15.0 0.975677 1.46154 False False 1.0 0.6 4.2 400.0 n/a 13.0 False 16.0 8.0 0.583333 40.0 10.0 100.0 False 0.0 8.0 0.0 4.0 1.14589 100.0 0.0 8.0 0.94112 3.0 35.0 5.0 60.0 40.0 n/a 4.0 0.0 3.0 0 False 4.0 True 3.0 0.992796 1.81669 False 50.0 False False 3.0 False 1.80695 n/a 15.0 40.0 30.0 100.0 100.0 150.0 d 20.0 100.0 3.0 False 0.0 True 1.0 False 3.0 False 1.0 0.748922 False False 0.0 20.0 100.0 1.30699 3.5 0 6.0 0.0 50.0 0 n/a False 0.956471 False 1.0 3.0 0.1875 3.0 0 3.5 60.0 203 n/a 2.0 1.30599 7.65278 n/a 4.0 100.0 15.0 30.0 False True True False 5.0 False 19.0 0.806267 2.0 False
+S60 45.0 0.705189 1.0 1.0 False -0.0101898 0.0 False 3.0 1.0 1.0 7.0 0.974984 1.55556 False False 0.0 0.933333 3.6 380.0 1.0 9.0 False 11.5 8.5 0.416667 30.0 12.0 55.0 False 0.333333 10.0 0.0 3.0 0.828774 10.0 0.0 9.0 0.964794 3.0 30.0 5.0 64.0 45.0 1.0 10.0 0.0 2.0 n/a False 4.0 True 2.0 0.996178 1.04281 False 20.0 False n/a 3.0 False 1.04961 n/a 15.0 35.0 30.0 50.0 75.0 95.0 d 25.0 75.0 3.0 False 0.0 True 1.0 False 5.0 False 2.0 0.680142 False False 0.0 12.0 12.0 0.939798 3.0 lieux 5.0 0.0 50.0 0 n/a False 0.970066 False 0.0 2.5 0.217391 1.0 visage 3.0 40.0 132 n/a 0.0 0.944566 5.28472 7.0 5.0 50.0 12.0 10.0 False True True False 7.0 False 14.0 0.738193 2.0 False
+S61 30.0 0.420859 n/a n/a False -0.0346947 1.0 False 3.0 n/a 3.0 17.5 0.946556 2.45455 False False 2.0 0.5 3.4 400.0 n/a 11.0 False 19.0 8.0 0.833333 20.0 10.0 30.0 False 0.666667 9.0 0.0 2.0 0.753665 100.0 1.0 8.0 0.911862 3.0 29.0 3.0 60.0 45.0 n/a 1.0 1.0 3.0 0 False 2.0 True 3.0 0.994075 0.603338 False 40.0 False False 1.0 False 0.626411 n/a 10.0 20.0 15.0 30.0 40.0 50.0 u 15.0 60.0 1.0 False 0.0 True 3.0 False 3.0 False 0.0 0.853415 False False 1.0 10.0 15.0 0.854203 2.5 physionomie 16.0 0.0 52.0 n/a n/a False 1.044 False 2.0 4.0 0.421053 2.0 lieux 3.0 25.0 199 n/a 10.0 0.858964 8.25694 9.0 3.0 50.0 11.0 200.0 False True False False 2.0 False 27.0 1.02602 3.0 False
+S62 n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a 367 n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a
+S63 40.0 0.710036 1.0 1.0 False -0.00756445 1.0 False 4.0 1.0 3.0 5.0 0.952403 1.85714 False True 0.0 0.833333 2.4 1000.0 1.0 7.0 False 10.0 8.0 0.583333 25.0 10.0 60.0 False 0.0 10.0 0.0 2.0 0.912774 800.0 1.0 10.0 0.944839 3.0 25.0 3.5 60.0 42.0 1.0 9.0 0.0 2.0 0 False 2.0 True 1.0 0.997006 1.03295 False 400.0 False True 2.0 False 1.05682 n/a 15.0 25.0 20.0 70.0 60.0 80.0 u 20.0 80.0 4.0 False 0.0 True 3.0 False 4.0 False 2.0 0.235942 False False 0.0 4.0 8.0 1.03665 3.0 LIEUX 6.0 0.0 50.0 0 n/a False 0.996833 False 0.0 1.0 0.3 1.0 VISAGES 2.0 200.0 325 n/a 4.0 1.0403 3.75694 11.0 1.0 60.0 14.0 500.0 False True True False 500.0 False 13.0 0.782561 2.0 False
+S64 40.0 0.526118 n/a n/a False -0.000933116 4.0 False 4.0 n/a 1.0 50.0 0.971842 1.7 False False 2.0 0.4 2.4 600.0 0.0 10.0 False 13.5 7.0 0.75 20.0 10.0 40.0 False 0.75 8.0 1.0 3.0 0.88201 30.0 2.0 7.0 0.970909 3.0 36.0 5.0 60.0 40.0 n/a 4.0 0.0 3.0 0 False 2.0 True 1.0 0.991759 0.772525 False 10.0 False False 1.0 False 0.783079 n/a 10.0 25.0 15.0 50.0 50.0 60.0 u 15.0 60.0 1.0 True 0.0 True 3.0 False 4.0 False 2.0 0.726744 False False 1.0 3.0 20.0 1.00469 0.0 ESPECES ANIMALES 7.0 0.0 45.0 0 n/a True 0.958743 False 1.0 2.5 0.259259 2.0 VISAGE 1.0 40.0 296 n/a 18.0 1.00524 7.35417 5.0 1.0 50.0 12.0 20.0 False True False False 2.0 False 17.0 0.975383 3.0 False
+S65 30.0 0.422172 1.0 1.0 False -0.0217241 3.5 False 3.0 1.0 1.0 10.0 0.956833 1.58333 False False 2.0 0.866667 3.8 500.0 1.0 12.0 False 15.5 7.0 0.916667 20.0 10.0 40.0 False 0.0 10.0 0.0 4.0 0.757414 40.0 2.0 10.0 0.935109 3.0 30.0 5.0 64.0 43.0 1.0 8.0 0.0 3.0 0 False 3.0 True 4.0 0.996173 0.615527 False 60.0 False False 3.0 False 0.628364 n/a 10.0 30.0 20.0 30.0 40.0 60.0 d 15.0 50.0 4.0 False 0.0 True 1.0 False 4.0 False 1.0 0.939091 False False 1.0 30.0 12.0 0.853278 2.0 n/a 7.0 0.0 55.0 0 n/a False 0.964347 False 1.0 2.5 0.225806 2.0 n/a 4.0 70.0 327 n/a 17.0 0.863237 8.05556 4.0 4.0 80.0 10.0 40.0 False True False False 3.0 False 19.0 0.994149 3.0 False
+S66 50.0 0.602292 n/a n/a False -0.0338606 1.5 False 4.0 n/a 1.0 20.0 0.934056 2.11111 False False 0.0 0.6 3.2 400.0 n/a 9.0 False 14.0 9.0 0.5 15.0 7.0 35.0 False 0.0 10.0 0.0 3.0 1.0295 25.0 1.0 9.0 0.900195 3.0 25.0 3.0 65.0 42.0 n/a 8.0 0.0 3.0 0 False 4.0 True 3.0 0.992627 0.904788 False 35.0 False False 3.0 False 0.896458 n/a 10.0 30.0 15.0 50.0 50.0 80.0 u 10.0 50.0 4.0 False 0.0 True 1.0 False 5.0 False 2.0 0.894138 False False 1.0 20.0 15.0 1.17632 0.0 n/a 10.0 0.0 50.0 0 n/a False 1.03726 False 2.0 3.0 0.357143 1.0 VISAGES LIEUX 3.0 90.0 344 n/a 7.0 1.17333 7.27083 5.0 3.0 80.0 12.0 20.0 False True False True 2.0 False 19.0 0.942724 2.0 False
+S67 50.0 0.760311 n/a n/a False -0.090743 0.5 False 3.0 n/a 2.0 40.0 0.957141 1.75 False False 0.0 0.7 2.8 300.0 n/a 8.0 False 11.0 7.0 0.166667 40.0 12.0 60.0 False 0.25 8.0 0.0 2.0 0.895573 50.0 0.0 10.0 0.866398 3.0 32.0 5.0 65.0 44.0 2.0 5.0 0.0 3.0 0 False 3.0 True 2.0 0.996432 1.11832 False 150.0 False False 2.0 True 1.13165 n/a 15.0 45.0 25.0 100.0 70.0 90.0 u 25.0 80.0 3.0 False 0.0 True 2.0 False 5.0 False 1.0 0.719087 False False 1.0 3.0 12.0 1.01291 2.33333 0 6.0 0.0 58.0 Chiffres, voyelles en couleur n/a False 0.975137 False 2.0 3.0 0.272727 1.0 Lieux, itineraires 2.0 40.0 215 n/a 3.0 1.0207 6.49306 5.0 2.0 80.0 10.0 8.0 False True True False 2.0 False 14.0 1.00441 1.0 False
+S68 42.0 0.518261 n/a n/a False -0.0204349 2.0 False 5.0 n/a 1.0 5.0 0.936235 1.88889 False False 1.0 1.0 4.2 700.0 n/a 9.0 False 13.0 7.0 0.833333 27.0 12.0 47.0 False 0.666667 10.0 1.0 3.0 0.753259 15.0 1.0 10.0 0.9158 3.0 33.0 4.0 63.0 43.0 n/a 10.0 0.0 3.0 n/a False 4.0 True 5.0 0.999161 0.76944 False 50.0 True False 3.0 False 0.771384 n/a 12.0 27.0 23.0 32.0 58.0 72.0 u 21.0 59.0 1.0 True 0.0 True 0.0 False 5.0 False 1.0 0.850019 False False 1.0 8.0 15.0 0.858164 4.0 n/a 8.0 0.0 40.0 0 n/a False 1.00769 False 2.0 4.0 0.307692 1.0 lieux 5.0 50.0 94 n/a 10.0 0.858501 8.90278 6.0 5.0 60.0 16.0 130.0 False True False False 3.0 False 17.0 1.08324 3.0 False
+S69 40.0 0.320483 n/a n/a False -0.0823311 4.0 False 4.0 n/a 1.0 32.5 0.906829 2.14286 False False 2.0 0.7 4.2 450.0 n/a 7.0 False 11.0 9.0 0.5 20.0 13.0 40.0 False 0.0 7.0 0.0 4.0 0.601481 150.0 2.0 9.0 0.824498 3.0 25.0 5.0 60.0 48.0 n/a 8.0 0.0 3.0 n/a False 4.0 True 4.0 0.989427 0.488542 False 2500.0 False False 2.0 True 0.47701 n/a 12.0 30.0 25.0 40.0 45.0 50.0 u 20.0 35.0 4.0 False 0.0 True 3.0 False 5.0 False 2.0 0.554342 False False 1.0 8.0 15.0 0.68626 4.0 n/a 8.0 0.0 35.0 couleur, mot, espace n/a False 0.95227 False 2.0 4.0 0.363636 2.0 visage, lieux 4.0 200.0 105 n/a 18.0 0.685518 9.0 4.0 5.0 70.0 13.0 10.0 False True False False 2.5 False 15.0 1.11756 3.0 False
+S70 350.0 4.37116 n/a n/a False -0.082708 3.0 False 4.0 n/a 1.0 15.0 0.923019 1.5 False False 2.0 0.766667 3.8 500.0 n/a 10.0 False 12.5 9.0 0.833333 50.0 15.0 250.0 False 0.0 8.0 0.0 3.0 1.71511 20.0 2.0 10.0 0.840311 3.0 25.0 4.0 68.0 43.0 n/a 8.0 0.0 3.0 0 False 4.0 True 4.0 0.995391 6.66643 False 200.0 False False 3.0 False 6.50608 n/a 15.0 100.0 30.0 200.0 400.0 500.0 d 20.0 300.0 2.0 False 0.0 True 1.0 False 5.0 False 2.0 0.832625 False False 1.0 5.0 6.0 1.97093 3.33333 0 5.0 0.0 40.0 Odeurs, images : souvenirs n/a False 0.998561 False 0.0 3.0 0.2 1.0 Visages 5.0 70.0 187 n/a 16.0 1.95474 8.42361 5.0 5.0 40.0 14.0 50.0 False True True False 3.0 False 15.0 1.0604 4.0 False
+S71 20.0 0.212617 n/a n/a False -0.0629865 1.5 False n/a n/a 2.0 15.0 0.830302 1.55556 False False 0.0 0.5 3.2 400.0 n/a 9.0 False 11.5 8.0 0.5 15.0 10.0 20.0 False 0.0 6.0 0.0 n/a 0.516706 40.0 1.0 7.0 0.767316 3.0 25.0 4.0 60.0 42.0 n/a 3.0 0.0 3.0 0 False 3.0 True 2.0 0.997657 0.325419 False 50.0 False False 2.0 False 0.316461 n/a 10.0 20.0 15.0 20.0 30.0 40.0 u 10.0 20.0 1.0 False 0.0 True 2.0 False n/a False 2.0 0.968262 False False 1.0 15.0 10.0 0.594702 n/a 0 5.0 0.0 50.0 n/a n/a False 0.97386 False 1.0 3.0 0.217391 1.0 Visages 2.0 60.0 159 n/a 7.0 0.588898 7.16667 6.0 3.0 100.0 10.0 100.0 False True True False 2.0 False 14.0 1.05611 3.0 False
+S72 60.0 0.715723 1.0 1.0 False -0.0551373 2.0 False 2.0 2.0 1.0 40.0 0.958627 1.33333 True True 1.0 0.433333 3.6 450.0 1.0 15.0 False 17.5 7.0 0.416667 30.0 10.0 70.0 False 0.0 8.0 2.0 0.0 1.0041 30.0 1.0 7.0 0.90349 3.0 21.0 3.0 67.0 45.0 1.0 5.0 0.0 3.0 pbl de deglutition a9ans(suce son pouce) False 3.0 True 3.0 0.98314 1.07017 False 50.0 False False 1.0 False 1.06529 n/a 10.0 30.0 20.0 70.0 70.0 80.0 d 20.0 70.0 2.0 True 0.0 True 2.0 False 3.0 False 0.0 0.830847 False False 1.0 20.0 14.0 1.14585 0.0 PHYSIONOMIE 5.0 3.0 60.0 0 n/a True 1.03714 True 1.0 2.5 0.142857 1.0 ESPECES VEGETALES 3.0 110.0 329 n/a 10.0 1.14439 6.59722 8.0 2.0 50.0 10.0 20.0 False True True False 5.0 True 20.0 0.841678 2.0 True
+S73 40.0 0.927448 1.0 1.0 False -0.00182578 n/a False n/a 1.0 3.0 15.0 0.979823 1.90476 False False n/a 0.766667 3.2 300.0 0.0 8.4 False 12.2 8.0 0.916667 25.0 10.0 50.0 False 0.0 9.0 0.0 n/a 1.07666 60.0 n/a 10.0 0.977997 3.0 30.0 3.0 63.0 41.0 1.0 10.0 0.0 3.0 n/a n/a 2.0 True 4.0 0.994564 1.36044 False 70.0 False False n/a False 1.38042 n/a 10.0 30.0 20.0 70.0 80.0 110.0 n/a 18.0 90.0 4.0 False 0.0 True 3.0 False n/a False 2.0 0.979557 False False n/a 15.0 13.0 1.22344 n/a espece animal 7.6 0.0 60.0 n/a n/a False 1.0435 False 1.0 1.0 0.311475 1.0 visage 3.0 60.0 365 n/a n/a 1.22709 n/a 7.0 3.0 50.0 10.0 55.0 False True n/a False 3.0 False 16.0 0.929294 3.0 False
+S74 30.0 0.382676 n/a n/a False -0.0665277 2.5 True 4.0 n/a 1.0 40.0 0.920906 1.66667 False True 1.0 0.8 3.6 250.0 n/a 9.0 False 12.0 12.0 0.833333 30.0 12.0 50.0 False 0.2 9.0 1.0 3.0 0.637316 20.0 1.0 10.0 0.854378 3.0 32.0 4.0 62.0 42.0 n/a 7.0 0.0 3.0 EXPRESSION ORALE False 4.0 True 5.0 0.999392 0.562843 False 30.0 False False 3.0 False 0.569578 n/a 15.0 30.0 20.0 50.0 50.0 50.0 U? 25.0 50.0 1.0 True 2.0 True 3.0 True 4.0 False 2.0 0.859567 False False 1.0 10.0 10.0 0.720039 3.5 lieux 6.0 2.0 60.0 0 n/a False 0.999466 True 0.0 0.0 0.25 1.0 Visages 5.0 50.0 207 n/a 11.0 0.726359 5.81944 4.0 5.0 50.0 10.0 30.0 False True True False 2.5 True 15.0 0.819761 3.0 False
+S75 90.0 1.17674 1.0 1.0 False -0.0322937 1.5 False 4.0 1.0 1.0 30.0 0.962962 1.5 False False 1.0 0.966667 5.0 300.0 1.0 10.0 False 12.5 7.0 0.666667 40.0 10.0 80.0 False 0.2 10.0 0.0 5.0 1.06134 15.0 1.0 10.0 0.930669 3.0 32.0 4.0 64.0 43.0 1.0 10.0 0.0 3.0 0 False 3.0 True 3.0 0.999677 1.77613 False 40.0 False False 3.0 False 1.75148 n/a 20.0 50.0 30.0 80.0 120.0 150.0 u 25.0 100.0 3.0 False 0.0 True 1.0 False 5.0 False 2.0 0.843897 False False 0.0 7.0 10.0 1.2123 4.0 n/a 5.0 0.0 60.0 0 n/a False 1.00794 False 2.0 3.5 0.2 2.0 LIEUX VISAGES 3.0 60.0 319 n/a 7.0 1.20962 7.72222 6.0 5.0 70.0 13.0 120.0 False True True True 3.0 False 15.0 0.945441 2.0 False
+S76 50.0 0.611865 n/a n/a False -0.0818007 3.5 False 4.0 n/a 1.0 20.0 0.921049 1.66667 False False 2.0 0.833333 2.6 500.0 n/a 9.0 False 12.0 7.0 0.25 30.0 10.0 35.0 False 0.0 10.0 0.0 3.0 0.873615 150.0 2.0 10.0 0.839249 3.0 33.0 4.0 66.0 45.0 n/a 6.0 0.0 3.0 0 False 4.0 True 3.0 0.999685 0.93416 False 200.0 False False 2.0 True 0.910705 n/a 10.0 30.0 20.0 40.0 70.0 90.0 u 20.0 50.0 3.0 False 0.0 True 3.0 False 3.0 False 2.0 0.825401 False True 1.0 50.0 15.0 1.0031 3.33333 0 6.0 0.0 30.0 Couleur / mots n/a False 1.02149 False 2.0 3.5 0.25 2.0 visages, lieux 3.0 200.0 172 n/a 17.0 0.995672 7.95833 6.0 3.0 65.0 10.0 100.0 False True False False 2.0 False 15.0 1.09488 3.0 False
+S77 45.0 0.689299 n/a n/a False -0.0180914 1.0 False 5.0 n/a 2.0 10.0 0.968552 2.11111 True True 0.0 0.966667 3.0 500.0 n/a 9.0 False 14.0 11.0 0.416667 20.0 10.0 40.0 False 0.0 9.0 0.0 4.0 0.981267 15.0 1.0 10.0 0.950461 3.0 30.0 4.0 64.0 43.0 n/a 10.0 n/a 3.0 n/a False 4.0 True 3.0 0.999983 1.01458 False 500.0 False False 3.0 False 1.02596 n/a 10.0 30.0 20.0 70.0 60.0 80.0 u 15.0 70.0 2.0 False 1.0 True 3.0 False 5.0 False 2.0 0.671399 False False 1.0 7.0 10.0 1.11533 4.33333 lieux 10.0 3.0 60.0 0 n/a False 1.00274 False 1.0 0.0 0.357143 2.0 visage 4.0 700.0 115 n/a 6.0 1.11837 4.65972 5.0 4.0 80.0 15.0 20.0 False True True False 2.0 True 19.0 1.19359 2.0 False
+S78 40.0 0.548867 n/a n/a False -0.0193456 3.0 False 4.0 n/a 2.0 25.0 0.950317 1.7 False False 2.0 0.7 3.8 600.0 n/a 10.0 False 13.5 15.0 0.916667 40.0 10.0 50.0 False 0.0 10.0 0.0 3.0 0.813199 60.0 1.0 10.0 0.930971 3.0 30.0 4.0 62.0 41.0 1.0 7.0 2.0 3.0 0 False 2.0 True 3.0 0.999859 0.815318 False 45.0 False False 2.0 False 0.816939 n/a 15.0 30.0 20.0 60.0 60.0 70.0 u 20.0 60.0 2.0 False 0.0 True 2.0 False 4.0 False 2.0 0.905331 False False 1.0 10.0 15.0 0.925195 2.0 n/a 7.0 0.0 50.0 0 n/a False 0.991229 False 1.0 2.5 0.259259 1.0 VISAGES 1.0 30.0 328 n/a 14.0 0.926816 6.74306 9.0 2.0 60.0 16.0 112.0 False True False False 3.0 False 17.0 0.960007 n/a False
+S79 42.0 0.449873 n/a 0.0 False 0.00970278 4.0 False 3.0 n/a 1.0 12.0 0.905277 1.4 False False 2.0 0.566667 1.8 350.0 n/a 10.0 False 12.0 7.0 0.666667 28.0 16.0 30.0 False 0.25 9.0 0.0 1.0 0.603731 30.0 2.0 9.0 0.914979 3.0 27.0 4.0 68.0 45.0 n/a 6.0 0.0 3.0 0 False 4.0 True 1.0 0.997786 0.671734 False 100.0 False True 1.0 False 0.669595 n/a 18.0 28.0 21.0 50.0 59.0 63.0 d 22.0 55.0 3.0 False 0.0 True 3.0 True 5.0 False 1.0 0.917245 False False 1.0 20.0 12.0 0.693804 1.66667 Mettre nom sur un visage 4.0 0.0 70.0 Chiffres ds espace n/a False 1.01049 False 1.0 3.5 0.166667 3.0 tout 1.0 80.0 198 n/a 18.0 0.688082 8.22222 4.0 1.0 50.0 12.0 100.0 False False False False 2.0 False 14.0 1.03246 3.0 False
+S80 48.0 0.634019 n/a n/a False -0.00810036 2.5 False 4.0 n/a 2.0 30.0 0.948885 1.5 False True 1.0 0.733333 2.6 530.0 n/a 10.0 False 12.5 13.0 0.5 31.0 8.0 41.0 False 0.0 7.0 0.0 2.0 0.91701 250.0 0.0 10.0 0.940784 3.0 25.0 4.0 62.0 43.0 n/a 10.0 0.0 3.0 0 False 3.0 True 3.0 0.996996 0.946805 False 20.0 False False 2.0 False 0.94368 n/a 12.0 35.0 34.0 56.0 68.0 86.0 u 19.0 63.0 2.0 False 1.0 True 1.0 False 5.0 False 2.0 0.798489 False False 1.0 6.0 18.0 1.03757 3.33333 0 5.0 0.0 62.0 0 n/a False 0.982516 False 2.0 2.0 0.2 1.0 visages, lieux 3.0 45.0 180 n/a 9.0 1.04513 6.375 8.0 3.0 75.0 10.0 50.0 False True True False 3.0 False 15.0 0.987773 3.0 False
+S81 n/a n/a n/a n/a False n/a n/a False n/a n/a n/a 15.0 n/a n/a n/a n/a n/a n/a n/a 500.0 n/a n/a False n/a 8.0 n/a n/a n/a n/a False n/a n/a n/a n/a n/a 40.0 n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a False 40.0 n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a 1.0 0.979913 False n/a n/a 10.0 15.0 n/a n/a n/a n/a n/a 55.0 n/a n/a n/a n/a n/a 1.0 n/a n/a n/a n/a n/a 50.0 217 n/a n/a n/a n/a n/a n/a 90.0 n/a 60.0 n/a n/a n/a n/a 3.0 n/a n/a 1.00486 n/a False
+S82 55.0 0.611077 n/a n/a False -0.0475203 3.5 False 3.0 n/a 1.0 15.0 0.963192 2.0 True True 1.0 0.85 2.4 1000.0 n/a 10.0 False 15.0 8.0 0.583333 25.0 11.0 45.0 False 0.33 10.0 0.0 3.0 0.877608 15.0 2.0 10.0 0.915672 3.0 30.0 3.0 66.0 43.0 n/a 7.0 0.0 1.0 0 False 3.0 True 3.0 0.994773 0.92664 False 25.0 False False 2.0 False 0.909533 n/a 12.0 30.0 20.0 50.0 68.0 80.0 u 17.0 55.0 2.0 False 0.0 True 2.0 False 4.0 False 2.0 0.745845 False False 1.0 8.0 12.0 1.0073 3.0 lieux 10.0 2.0 50.0 0 n/a False 1.05757 False 0.0 2.0 0.333333 2.0 Visages 3.0 20.0 195 n/a 15.0 1.00022 5.27778 4.0 4.0 50.0 13.0 6.0 False True False False 2.0 False 20.0 1.00696 2.0 False
+S83 55.0 0.752174 n/a n/a False -0.0102645 3.0 False 3.0 n/a 1.0 7.0 0.983114 1.25 False True 1.0 1.0 3.4 600.0 n/a 12.0 False 13.5 8.0 0.75 30.0 10.0 60.0 False 0.0 10.0 0.0 3.0 0.946814 15.0 2.0 10.0 0.972849 3.0 35.0 3.0 65.0 43.0 n/a 10.0 0.0 3.0 0 False 3.0 True 4.0 0.992436 1.10866 False 100.0 False False 3.0 False 1.11954 n/a 13.0 40.0 25.0 75.0 70.0 90.0 d 25.0 80.0 4.0 False 0.0 True 1.0 False 4.0 False 2.0 0.777745 False False 1.0 8.0 12.0 1.07195 2.66667 lieux 3.0 0.0 50.0 0 n/a False 1.06735 False 0.0 1.0 0.111111 3.0 Visages 4.0 30.0 184 n/a 14.0 1.0791 6.4375 5.0 4.0 60.0 11.0 50.0 False True False False 8.0 False 15.0 0.904109 3.0 False
+S84 70.0 0.918418 n/a n/a False 0.053325 1.0 False 4.0 n/a 1.0 7.0 0.888236 1.54545 False False 1.0 0.8 3.4 450.0 n/a 11.0 False 14.0 11.0 0.75 40.0 12.0 75.0 False 0.25 10.0 0.0 3.0 1.15816 80.0 1.0 10.0 0.941561 3.0 33.0 5.0 63.0 42.0 n/a 9.0 0.0 3.0 0 False 4.0 True 3.0 0.995588 1.37754 False 70.0 False False 3.0 False 1.36698 n/a 5.0 40.0 35.0 70.0 95.0 110.0 d 20.0 85.0 4.0 False 0.0 True 0.0 False 4.0 False 2.0 0.818761 False False 1.0 5.0 14.0 1.3146 3.33333 0 6.0 0.0 45.0 0 n/a False 0.966338 False 2.0 2.5 0.214286 2.0 visages, lieux 3.0 25.0 193 n/a 8.0 1.31998 7.10417 5.0 3.0 60.0 10.0 9.0 False True True False 1.5 False 17.0 1.05465 2.0 False
+S85 25.0 0.278677 n/a n/a False -0.022051 3.0 False 4.0 n/a 2.0 20.0 0.94183 2.0 False False 1.0 0.6 4.0 500.0 0.0 9.0 False 13.5 9.0 0.833333 25.0 10.0 30.0 False 0.33 8.0 0.0 2.0 0.562786 60.0 2.0 9.0 0.919779 3.0 30.0 5.0 60.0 40.0 n/a 9.0 0.0 3.0 0 False 3.0 True 3.0 0.995747 0.400515 False 80.0 False False 2.0 False 0.414786 n/a 15.0 25.0 20.0 30.0 35.0 40.0 u 15.0 45.0 4.0 False 0.0 True 3.0 False 4.0 False 2.0 0.962147 False False 1.0 10.0 12.0 0.631332 3.0 animaux 9.0 0.0 65.0 0 n/a False 0.944038 False 1.0 n/a 0.333333 2.0 Visages 3.0 50.0 169 n/a 14.0 0.641416 5.56944 6.0 4.0 60.0 13.0 30.0 False True n/a False 2.0 False 18.0 1.04717 4.0 False
+S86 40.0 0.780401 1.0 1.0 False -0.0458562 1.5 False 4.0 1.0 1.0 50.0 0.878883 1.75 False True 0.0 0.5 3.4 750.0 1.0 10.0 False 13.75 9.0 0.416667 40.0 12.0 90.0 True 0.0 9.0 3.0 3.0 0.993049 90.0 2.0 10.0 0.833027 3.0 32.0 4.0 63.0 45.0 1.0 6.0 0.0 3.0 dyslexie, confusion che/jeu, f/v False 4.0 True 4.0 0.999649 1.14484 True 30.0 False False 2.0 False 1.16156 n/a 10.0 20.0 28.0 70.0 65.0 90.0 u 15.0 80.0 4.0 True 0.0 True 2.0 True 4.0 True 1.0 0.89167 False False 1.0 12.0 11.0 1.13006 0.0 n/a 7.5 0.0 60.0 0 n/a False 1.01092 True 1.0 1.5 0.272727 1.0 n/a 2.0 80.0 346 n/a 9.0 1.13179 6.26389 6.0 4.0 70.0 13.0 30.0 False True n/a True 2.5 False 17.5 1.04276 3.0 False
+S87 n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a 369 n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a
+S88 45.0 0.525943 n/a 0.0 False -0.0442923 0.0 False 4.0 n/a 1.0 35.0 0.958444 1.875 False False 0.0 0.6 3.6 500.0 n/a 8.0 True 11.5 10.0 0.75 25.0 10.0 40.0 False 0.5 8.0 2.0 2.0 0.825556 60.0 1.0 10.0 0.914152 3.0 32.0 5.0 60.0 42.0 n/a 8.0 0.0 3.0 APPRENTISSAGE LECTURE, math False 3.0 True 3.0 0.995658 0.77895 False 100.0 True True 1.0 False 0.782818 n/a 15.0 35.0 20.0 60.0 60.0 60.0 d 15.0 60.0 3.0 True 1.0 True 0.0 False 3.0 False 2.0 0.860257 False True 0.0 20.0 15.0 0.93793 2.33333 noms 7.0 0.0 60.0 nombre / espace, gouts et sons n/a False 0.955381 True 2.0 3.0 0.304348 1.0 visages, lieux 1.0 150.0 178 n/a 2.0 0.940899 7.375 4.0 1.0 80.0 10.0 400.0 False True True False 3.0 False 15.0 1.05283 2.0 False
+S89 70.0 1.09973 n/a n/a False -0.0425949 1.0 False 5.0 n/a 3.0 40.0 0.927972 2.55556 False True 0.0 0.666667 3.0 200.0 n/a 9.0 False 16.0 20.0 0.583333 40.0 11.0 60.0 False 0.0 10.0 0.0 3.0 1.01285 150.0 0.0 10.0 0.885377 3.0 24.0 3.0 62.0 38.0 n/a 7.0 0.0 2.0 0 True 4.0 True 3.0 0.992471 1.64304 False 40.0 False False 3.0 False 1.63685 n/a 15.0 30.0 25.0 50.0 100.0 150.0 d 25.0 100.0 2.0 False 0.0 True 1.0 False 5.0 False 2.0 0.00909366 False True 0.0 15.0 10.0 1.16136 4.0 LIEUX 14.0 0.0 5.0 0 n/a False 1.01316 False 0.0 0.0 0.4375 1.0 VISAGE 5.0 1000.0 289 n/a 2.0 1.15436 3.38194 9.0 3.0 50.0 18.0 300.0 False True True False 1000.0 False 23.0 0.126279 2.0 False
+S90 80.0 1.19538 n/a n/a False -0.00869327 3.0 False 2.0 n/a 3.0 15.0 0.894658 1.71429 False False 2.0 0.7 2.8 400.0 n/a 7.0 False 9.5 7.0 0.666667 60.0 10.0 40.0 False 0.33 10.0 1.0 1.0 1.11558 20.0 2.0 10.0 0.885965 3.0 22.0 5.0 62.0 45.0 n/a 7.0 0.0 3.0 en histoire False 4.0 True 2.0 0.983444 1.75143 False 30.0 True False 1.0 False 1.77922 n/a 15.0 60.0 30.0 80.0 100.0 150.0 d 15.0 130.0 2.0 True 1.0 True 0.0 False 4.0 False 1.0 0.905508 False False 1.0 8.0 10.0 1.26396 1.66667 lieux 5.0 0.0 60.0 n/a n/a False 0.939536 False 0.0 1.5 0.263158 1.0 0 3.0 20.0 213 n/a 16.0 1.27144 5.84722 10.0 2.0 80.0 10.0 30.0 False True True False 2.5 False 12.0 0.953995 2.0 False
+S91 50.0 0.611427 1.0 1.0 False -0.00681096 3.5 False 3.0 1.0 2.0 20.0 0.966239 1.6 False False 2.0 0.9 4.2 500.0 1.0 10.0 False 13.0 7.0 0.833333 20.0 10.0 50.0 False 0.0 10.0 0.0 3.0 0.920033 40.0 2.0 10.0 0.959428 3.0 23.0 5.0 61.0 43.0 1.0 10.0 0.0 3.0 deglutition a 15ans pendant 4mois False 4.0 True 4.0 0.987777 0.899697 False 120.0 False False 2.0 False 0.910054 n/a 10.0 30.0 20.0 50.0 60.0 70.0 u 20.0 70.0 2.0 False 0.0 True 1.0 False 4.0 False 1.0 n/a False False 1.0 15.0 10.0 1.04483 2.0 n/a 6.0 0.0 60.0 0 n/a False 0.934578 True 2.0 3.0 0.230769 2.0 LIEUX 4.0 60.0 334 n/a 17.0 1.04858 8.25694 7.0 3.0 n/a 10.0 140.0 False True False True 2.0 False 16.0 n/a 4.0 False
+S92 38.0 0.475912 n/a n/a False -0.0850252 1.5 False 5.0 n/a 1.0 6.0 0.785702 1.44444 False True 1.0 0.8 3.2 500.0 n/a 9.0 False 11.0 9.0 0.75 25.0 12.0 29.0 False 0.0 10.0 0.0 3.0 0.696258 120.0 1.0 9.0 0.700677 3.0 32.0 5.0 65.0 43.0 n/a 8.0 2.0 3.0 0 False 4.0 True 4.0 0.99624 0.744678 False 200.0 False False 3.0 False 0.708352 n/a 15.0 25.0 24.0 44.0 66.0 77.0 u 12.0 29.0 4.0 False 0.0 True n/a False 5.0 False 1.0 0.815552 False True 1.0 15.0 12.0 0.810939 3.66667 0 4.0 0.0 52.0 Suites ds espaCe et couleurs n/a False 0.972245 False 1.0 2.0 0.181818 2.0 0 5.0 20.0 196 n/a 9.0 0.793536 6.95833 6.0 5.0 80.0 10.0 50.0 False True False False 3.0 False 13.0 1.04952 3.0 False
+S93 50.0 0.717351 n/a 0.0 False -0.0384674 3.5 False 3.0 n/a 1.0 20.0 0.959921 2.08333 False False 1.0 1.0 4.8 280.0 n/a 12.0 False 18.5 8.0 0.916667 40.0 12.0 70.0 False 0.0 10.0 0.0 3.0 0.856346 30.0 1.0 10.0 0.921454 3.0 35.0 4.0 60.0 43.0 n/a 10.0 0.0 3.0 0 False 3.0 True 4.0 0.997048 1.0501 False 30.0 False False 3.0 False 1.06771 n/a 15.0 40.0 30.0 50.0 60.0 100.0 d 20.0 80.0 4.0 False 0.0 True 1.0 False 4.0 False 1.0 0.907422 False False 1.0 10.0 12.0 0.967146 3.0 NOMS 13.0 0.0 50.0 NUM DE TELEPHONE n/a False 1.00396 False 2.0 3.0 0.351351 1.0 LIEUX CHIFFRES 4.0 120.0 343 n/a 13.0 0.975992 8.03472 5.0 5.0 50.0 12.0 100.0 False True n/a False 2.0 False 25.0 0.980029 2.0 False
+S94 53.0 0.913518 n/a n/a False -0.0127455 4.0 False 3.0 n/a 1.0 17.0 0.992355 2.1 False False 1.0 0.9 4.7 250.0 n/a 10.0 False 15.5 6.5 1.0 30.0 10.0 60.0 False 0.0 9.0 0.0 3.0 1.03356 50.0 2.0 10.0 0.97961 3.0 36.0 5.0 64.0 43.0 n/a 9.0 0.0 3.0 0 False 1.0 True 5.0 0.994238 1.35131 False 65.0 False False 3.0 False 1.35969 n/a 13.0 38.0 25.0 60.0 90.0 110.0 d 18.0 90.0 4.0 False 0.0 True 5.0 False 4.0 False 1.0 0.937513 False False 1.0 15.0 15.0 1.17454 3.33333 0 11.0 0.0 50.0 nombre / espace n/a False 0.979051 False 1.0 4.0 0.354839 3.0 0 4.0 55.0 189 n/a 16.0 1.17797 9.66667 4.0 4.0 60.0 10.0 120.0 False True n/a False 2.75 False 21.0 0.933082 4.0 False
diff --git a/nilearn/datasets/tests/data/localizer_index.json b/nilearn/datasets/tests/data/localizer_index.json
new file mode 100755
index 0000000000..2d0bb9fb2f
--- /dev/null
+++ b/nilearn/datasets/tests/data/localizer_index.json
@@ -0,0 +1,114 @@
+[
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_mask.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_spm.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Auditory&VisualCalculationVsSentences_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Auditory&VisualCalculationVsSentences_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Auditory&VisualCalculationVsSentences_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Auditory&VisualCalculation_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Auditory&VisualCalculation_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Auditory&VisualCalculation_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Auditory&VisualMotorVsCognitiveProcessing_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Auditory&VisualMotorVsCognitiveProcessing_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Auditory&VisualMotorVsCognitiveProcessing_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Auditory&VisualSentences_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Auditory&VisualSentences_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Auditory&VisualSentences_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryCalculationVsAuditorySentences_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryCalculationVsAuditorySentences_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryCalculationVsAuditorySentences_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryCalculation_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryCalculation_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryCalculation_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryClickVsAuditorySentences_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryClickVsAuditorySentences_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryClickVsAuditorySentences_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryProcessingVsVisualProcessing_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryProcessingVsVisualProcessing_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryProcessingVsVisualProcessing_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryProcessing_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryProcessing_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditoryProcessing_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditorySentences_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditorySentences_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-AuditorySentences_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Checkerboard_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Checkerboard_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Checkerboard_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-CognitiveProcessingVsMotor_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-CognitiveProcessingVsMotor_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-CognitiveProcessingVsMotor_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-EffectsOfInterest_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-EffectsOfInterest_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-EffectsOfInterest_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-HorizontalCheckerboard_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-HorizontalCheckerboard_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-HorizontalCheckerboard_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-HorizontalVsVerticalCheckerboard_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-HorizontalVsVerticalCheckerboard_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-HorizontalVsVerticalCheckerboard_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-LeftAuditory&VisualClickVsRightAuditory&VisualClick_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-LeftAuditory&VisualClickVsRightAuditory&VisualClick_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-LeftAuditory&VisualClickVsRightAuditory&VisualClick_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-LeftAuditory&VisualClick_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-LeftAuditory&VisualClick_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-LeftAuditory&VisualClick_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-LeftAuditoryClick_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-LeftAuditoryClick_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-LeftAuditoryClick_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-LeftVisualClick_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-LeftVisualClick_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-LeftVisualClick_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Motor_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Motor_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-Motor_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-RightAuditory&VisualClickVsLeftAuditory&VisualClick_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-RightAuditory&VisualClickVsLeftAuditory&VisualClick_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-RightAuditory&VisualClickVsLeftAuditory&VisualClick_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-RightAuditory&VisualClick_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-RightAuditory&VisualClick_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-RightAuditory&VisualClick_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-RightAuditoryClick_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-RightAuditoryClick_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-RightAuditoryClick_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-RightVisualClick_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-RightVisualClick_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-RightVisualClick_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VerticalCheckerboard_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VerticalCheckerboard_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VerticalCheckerboard_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VerticalVsHorizontalCheckerboard_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VerticalVsHorizontalCheckerboard_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VerticalVsHorizontalCheckerboard_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualCalculationVsSentences_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualCalculationVsSentences_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualCalculationVsSentences_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualCalculation_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualCalculation_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualCalculation_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualClickVsVisualSentences_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualClickVsVisualSentences_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualClickVsVisualSentences_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualProcessingVsAuditoryProcessing_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualProcessingVsAuditoryProcessing_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualProcessingVsAuditoryProcessing_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualProcessingVsCheckerboard_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualProcessingVsCheckerboard_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualProcessingVsCheckerboard_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualProcessing_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualProcessing_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualProcessing_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualSentencesVsCheckerboard_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualSentencesVsCheckerboard_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualSentencesVsCheckerboard_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualSentences_cmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualSentences_contrasts.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_acq-VisualSentences_tmaps.nii.gz",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_design.json",
+ "/localizer/derivatives/spm_1st_level/sub-{0}/sub-{0}_task-localizer_design.npy",
+ "/localizer/derivatives/spm_preprocessing/sub-{0}/sub-{0}_T1w.nii.gz",
+ "/localizer/derivatives/spm_preprocessing/sub-{0}/sub-{0}_task-localizer_bold.nii.gz",
+ "/localizer/sub-{0}/anat/sub-{0}_T1w.nii.gz",
+ "/localizer/sub-{0}/func/sub-{0}_task-localizer_bold.json",
+ "/localizer/sub-{0}/func/sub-{0}_task-localizer_bold.nii.gz"
+]
+
diff --git a/nilearn/datasets/tests/data/localizer_participants.tsv b/nilearn/datasets/tests/data/localizer_participants.tsv
new file mode 100644
index 0000000000..a029d440d6
--- /dev/null
+++ b/nilearn/datasets/tests/data/localizer_participants.tsv
@@ -0,0 +1,95 @@
+participant_id age sex site family language
+S01 24 M SHFJ F01 French
+S02 20 M SHFJ F02 French
+S03 22 F SHFJ F03 French
+S04 20 M Neurospin F04 French
+S05 23 F Neurospin F05 French
+S06 19 M Neurospin F06 French
+S07 26 F Neurospin F07 French
+S08 27 M Neurospin F89 French
+S09 21 F Neurospin F09 French
+S10 24 F SHFJ F10 French
+S11 47 F SHFJ F11 French
+S12 23 F SHFJ F12 French
+S13 19 M Neurospin F13 French
+S14 21 F SHFJ F14 French
+S15 22 F SHFJ F15 French
+S16 24 F SHFJ F16 French
+S17 22 M SHFJ F17 French
+S18 20 F Neurospin F18 French
+S19 18 M SHFJ F52 French
+S20 25 F SHFJ F20 French
+S21 21 M SHFJ F21 French
+S22 40 M SHFJ F22 French
+S23 24 F Neurospin F23 French
+S24 18 F Neurospin F24 French
+S25 24 F SHFJ F25 French
+S26 24 F Neurospin F26 French
+S27 30 M Neurospin F27 French
+S28 18 F Neurospin F28 French
+S29 21 F Neurospin F29 French
+S30 34 F SHFJ F30 French
+S31 22 F Neurospin F31 French
+S32 26 F SHFJ F32 French
+S33 21 F SHFJ F33 French
+S34 21 M SHFJ F34 French
+S35 24 F SHFJ F35 French
+S36 25 F SHFJ F36 French
+S37 22 M Neurospin F37 French
+S38 n/a M SHFJ F38 French
+S39 22 M SHFJ F39 French
+S40 24 F SHFJ F40 French
+S41 18 M Neurospin F41 French
+S42 26 M Neurospin F42 French
+S43 49 M Neurospin F43 French
+S44 34 F SHFJ F44 French
+S45 21 M SHFJ F45 French
+S46 24 F Neurospin F46 French
+S47 19 M SHFJ F47 French
+S48 21 F SHFJ F48 French
+S49 22 F SHFJ F49 French
+S50 32 F SHFJ F50 French
+S51 30 M SHFJ F51 French
+S52 22 F SHFJ F52 French
+S53 18 F Neurospin F53 French
+S54 20 F SHFJ F54 French
+S55 21 F Neurospin F55 French
+S56 23 M Neurospin F56 French
+S57 20 F SHFJ F57 French
+S58 34 M SHFJ F58 French
+S59 30 M SHFJ F59 French
+S60 21 M Neurospin F60 French
+S61 23 M SHFJ F61 French
+S62 n/a F SHFJ F62 French
+S63 19 F Neurospin F63 French
+S64 21 F Neurospin F64 French
+S65 19 M Neurospin F65 French
+S66 26 M Neurospin F66 French
+S67 44 F SHFJ F67 French
+S68 20 M SHFJ F68 French
+S69 21 F SHFJ F69 French
+S70 25 M SHFJ F59 French
+S71 21 M SHFJ F71 French
+S72 37 F Neurospin F72 French
+S73 19 M Neurospin F73 French
+S74 21 M SHFJ F74 French
+S75 20 M Neurospin F75 French
+S76 28 F SHFJ F76 French
+S77 23 F SHFJ F77 French
+S78 29 M Neurospin F78 French
+S79 43 F SHFJ F79 French
+S80 19 F SHFJ F80 French
+S81 n/a M SHFJ F81 French
+S82 20 F SHFJ F82 French
+S83 20 F Neurospin F83 French
+S84 23 F SHFJ F84 French
+S85 21 M SHFJ F85 French
+S86 31 M Neurospin F86 French
+S87 n/a M SHFJ F87 French
+S88 19 M SHFJ F88 French
+S89 29 M Neurospin F89 French
+S90 21 M SHFJ F90 French
+S91 23 M Neurospin F91 French
+S92 26 F SHFJ F92 French
+S93 36 M Neurospin F93 French
+S94 41 M SHFJ F94 French
diff --git a/nilearn/datasets/tests/test_atlas.py b/nilearn/datasets/tests/test_atlas.py
index e6984c4d6c..a2ce5b8cf1 100644
--- a/nilearn/datasets/tests/test_atlas.py
+++ b/nilearn/datasets/tests/test_atlas.py
@@ -565,7 +565,7 @@ def test_fetch_atlas_pauli_2017():
@with_setup(tst.setup_tmpdata, tst.teardown_tmpdata)
def test_fetch_atlas_schaefer_2018():
- valid_n_rois = [100, 200, 300, 400, 500, 600, 800, 1000]
+ valid_n_rois = list(range(100, 1100, 100))
valid_yeo_networks = [7, 17]
valid_resolution_mm = [1, 2]
diff --git a/nilearn/datasets/tests/test_func.py b/nilearn/datasets/tests/test_func.py
index 27193e9ac0..9c52e3dbca 100644
--- a/nilearn/datasets/tests/test_func.py
+++ b/nilearn/datasets/tests/test_func.py
@@ -5,6 +5,7 @@
# License: simplified BSD
import os
+import uuid
import numpy as np
import json
import nibabel
@@ -12,7 +13,8 @@
from sklearn.utils import check_random_state
from nose import with_setup
-from nose.tools import assert_true, assert_equal, assert_not_equal
+from nose.tools import (
+ assert_true, assert_false, assert_equal, assert_not_equal)
from . import test_utils as tst
from nilearn.datasets import utils, func
@@ -146,193 +148,145 @@ def test_miyawaki2008():
assert_not_equal(dataset.description, '')
+with open(os.path.join(tst.datadir, 'localizer_index.json')) as of:
+ localizer_template = json.load(of)
+LOCALIZER_INDEX = {}
+for idx in range(1, 95):
+ idx = str(idx).zfill(2)
+ sid = 'S{0}'.format(idx)
+ LOCALIZER_INDEX.update(dict(
+ (key.format(sid), uuid.uuid4().hex)
+ for key in localizer_template))
+LOCALIZER_INDEX['/localizer/phenotype/behavioural.tsv'] = uuid.uuid4().hex
+LOCALIZER_PARTICIPANTS = np.recfromcsv(
+ os.path.join(tst.datadir, 'localizer_participants.tsv'), delimiter='\t')
+LOCALIZER_BEHAVIOURAL = np.recfromcsv(
+ os.path.join(tst.datadir, 'localizer_behavioural.tsv'), delimiter='\t')
+
+
+def mock_localizer_index(*args, **kwargs):
+ return LOCALIZER_INDEX
+
+
+def mock_np_recfromcsv(*args, **kwargs):
+ if args[0].endswith('participants.tsv'):
+ return LOCALIZER_PARTICIPANTS
+ elif args[0].endswith('behavioural.tsv'):
+ return LOCALIZER_BEHAVIOURAL
+ else:
+ raise ValueError('Unexpected args!')
+
+
+def setup_localizer():
+ global original_json_load
+ global mock_json_load
+ mock_json_load = mock_localizer_index
+ original_json_load = json.load
+ json.load = mock_json_load
+
+ global original_np_recfromcsv
+ global mock_np_recfromcsv
+ mock_np_recfromcsv = mock_np_recfromcsv
+ original_np_recfromcsv = np.recfromcsv
+ np.recfromcsv = mock_np_recfromcsv
+
+
+def teardown_localizer():
+ global original_json_load
+ json.load = original_json_load
+
+ global original_np_recfromcsv
+ np.recfromcsv = original_np_recfromcsv
+
+
@with_setup(setup_mock, teardown_mock)
@with_setup(tst.setup_tmpdata, tst.teardown_tmpdata)
+@with_setup(setup_localizer, teardown_localizer)
def test_fetch_localizer_contrasts():
- local_url = "file://" + tst.datadir
- ids = np.asarray([('S%2d' % i).encode() for i in range(94)])
- ids = ids.view(dtype=[('subject_id', 'S3')])
- tst.mock_fetch_files.add_csv('cubicwebexport.csv', ids)
- tst.mock_fetch_files.add_csv('cubicwebexport2.csv', ids)
-
- # Disabled: cannot be tested without actually fetching covariates CSV file
- # All subjects
- dataset = func.fetch_localizer_contrasts(["checkerboard"],
- data_dir=tst.tmpdir,
- url=local_url,
- verbose=0)
- assert_true(dataset.anats is None)
- assert_true(dataset.tmaps is None)
- assert_true(dataset.masks is None)
- assert_true(isinstance(dataset.ext_vars, np.recarray))
- assert_true(isinstance(dataset.cmaps[0], _basestring))
- assert_equal(dataset.ext_vars.size, 94)
- assert_equal(len(dataset.cmaps), 94)
-
- # 20 subjects
- dataset = func.fetch_localizer_contrasts(["checkerboard"],
- n_subjects=20,
- data_dir=tst.tmpdir,
- url=local_url,
- verbose=0)
- assert_true(dataset.anats is None)
- assert_true(dataset.tmaps is None)
- assert_true(dataset.masks is None)
+ # 2 subjects
+ dataset = func.fetch_localizer_contrasts(
+ ['checkerboard'],
+ n_subjects=2,
+ data_dir=tst.tmpdir,
+ verbose=1)
+ assert_false(hasattr(dataset, 'anats'))
+ assert_false(hasattr(dataset, 'tmaps'))
+ assert_false(hasattr(dataset, 'masks'))
assert_true(isinstance(dataset.cmaps[0], _basestring))
assert_true(isinstance(dataset.ext_vars, np.recarray))
- assert_equal(len(dataset.cmaps), 20)
- assert_equal(dataset.ext_vars.size, 20)
+ assert_equal(len(dataset.cmaps), 2)
+ assert_equal(dataset.ext_vars.size, 2)
# Multiple contrasts
dataset = func.fetch_localizer_contrasts(
- ["checkerboard", "horizontal checkerboard"],
- n_subjects=20, data_dir=tst.tmpdir,
- verbose=0)
- assert_true(dataset.anats is None)
- assert_true(dataset.tmaps is None)
- assert_true(dataset.masks is None)
+ ['checkerboard', 'horizontal checkerboard'],
+ n_subjects=2,
+ data_dir=tst.tmpdir,
+ verbose=1)
assert_true(isinstance(dataset.ext_vars, np.recarray))
assert_true(isinstance(dataset.cmaps[0], _basestring))
- assert_equal(len(dataset.cmaps), 20 * 2) # two contrasts are fetched
- assert_equal(dataset.ext_vars.size, 20)
-
- # get_anats=True
- dataset = func.fetch_localizer_contrasts(["checkerboard"],
- data_dir=tst.tmpdir,
- url=local_url,
- get_anats=True,
- verbose=0)
- assert_true(dataset.masks is None)
- assert_true(dataset.tmaps is None)
- assert_true(isinstance(dataset.ext_vars, np.recarray))
- assert_true(isinstance(dataset.anats[0], _basestring))
- assert_true(isinstance(dataset.cmaps[0], _basestring))
- assert_equal(dataset.ext_vars.size, 94)
- assert_equal(len(dataset.anats), 94)
- assert_equal(len(dataset.cmaps), 94)
-
- # get_masks=True
- dataset = func.fetch_localizer_contrasts(["checkerboard"],
- data_dir=tst.tmpdir,
- url=local_url,
- get_masks=True,
- verbose=0)
- assert_true(dataset.anats is None)
- assert_true(dataset.tmaps is None)
- assert_true(isinstance(dataset.ext_vars, np.recarray))
- assert_true(isinstance(dataset.cmaps[0], _basestring))
- assert_true(isinstance(dataset.masks[0], _basestring))
- assert_equal(dataset.ext_vars.size, 94)
- assert_equal(len(dataset.cmaps), 94)
- assert_equal(len(dataset.masks), 94)
-
- # get_tmaps=True
- dataset = func.fetch_localizer_contrasts(["checkerboard"],
- data_dir=tst.tmpdir,
- url=local_url,
- get_tmaps=True,
- verbose=0)
- assert_true(dataset.anats is None)
- assert_true(dataset.masks is None)
- assert_true(isinstance(dataset.ext_vars, np.recarray))
- assert_true(isinstance(dataset.cmaps[0], _basestring))
- assert_true(isinstance(dataset.tmaps[0], _basestring))
- assert_equal(dataset.ext_vars.size, 94)
- assert_equal(len(dataset.cmaps), 94)
- assert_equal(len(dataset.tmaps), 94)
+ assert_equal(len(dataset.cmaps), 2 * 2) # two contrasts are fetched
+ assert_equal(dataset.ext_vars.size, 2)
# all get_*=True
- dataset = func.fetch_localizer_contrasts(["checkerboard"],
- data_dir=tst.tmpdir,
- url=local_url,
- get_anats=True,
- get_masks=True,
- get_tmaps=True,
- verbose=0)
-
+ dataset = func.fetch_localizer_contrasts(
+ ['checkerboard'],
+ n_subjects=1,
+ data_dir=tst.tmpdir,
+ get_anats=True,
+ get_masks=True,
+ get_tmaps=True,
+ verbose=1)
assert_true(isinstance(dataset.ext_vars, np.recarray))
assert_true(isinstance(dataset.anats[0], _basestring))
assert_true(isinstance(dataset.cmaps[0], _basestring))
assert_true(isinstance(dataset.masks[0], _basestring))
assert_true(isinstance(dataset.tmaps[0], _basestring))
- assert_equal(dataset.ext_vars.size, 94)
- assert_equal(len(dataset.anats), 94)
- assert_equal(len(dataset.cmaps), 94)
- assert_equal(len(dataset.masks), 94)
- assert_equal(len(dataset.tmaps), 94)
+ assert_equal(dataset.ext_vars.size, 1)
+ assert_equal(len(dataset.anats), 1)
+ assert_equal(len(dataset.cmaps), 1)
+ assert_equal(len(dataset.masks), 1)
+ assert_equal(len(dataset.tmaps), 1)
assert_not_equal(dataset.description, '')
# grab a given list of subjects
- dataset2 = func.fetch_localizer_contrasts(["checkerboard"],
- n_subjects=[2, 3, 5],
- data_dir=tst.tmpdir,
- url=local_url,
- get_anats=True,
- get_masks=True,
- get_tmaps=True,
- verbose=0)
-
- # Check that we are getting only 3 subjects
+ dataset2 = func.fetch_localizer_contrasts(
+ ['checkerboard'],
+ n_subjects=[2, 3, 5],
+ data_dir=tst.tmpdir,
+ verbose=1)
assert_equal(dataset2.ext_vars.size, 3)
- assert_equal(len(dataset2.anats), 3)
assert_equal(len(dataset2.cmaps), 3)
- assert_equal(len(dataset2.masks), 3)
- assert_equal(len(dataset2.tmaps), 3)
- np.testing.assert_array_equal(dataset2.ext_vars,
- dataset.ext_vars[[1, 2, 4]])
- np.testing.assert_array_equal(dataset2.anats,
- np.array(dataset.anats)[[1, 2, 4]])
- np.testing.assert_array_equal(dataset2.cmaps,
- np.array(dataset.cmaps)[[1, 2, 4]])
- np.testing.assert_array_equal(dataset2.masks,
- np.array(dataset.masks)[[1, 2, 4]])
- np.testing.assert_array_equal(dataset2.tmaps,
- np.array(dataset.tmaps)[[1, 2, 4]])
+ assert_equal([row[0] for row in dataset2.ext_vars],
+ [b'S02', b'S03', b'S05'])
@with_setup(setup_mock, teardown_mock)
@with_setup(tst.setup_tmpdata, tst.teardown_tmpdata)
+@with_setup(setup_localizer, teardown_localizer)
def test_fetch_localizer_calculation_task():
- local_url = "file://" + tst.datadir
- ids = np.asarray(['S%2d' % i for i in range(94)])
- ids = ids.view(dtype=[('subject_id', 'S3')])
- tst.mock_fetch_files.add_csv('cubicwebexport.csv', ids)
- tst.mock_fetch_files.add_csv('cubicwebexport2.csv', ids)
-
- # Disabled: cannot be tested without actually fetching covariates CSV file
- # All subjects
- dataset = func.fetch_localizer_calculation_task(data_dir=tst.tmpdir,
- url=local_url,
- verbose=0)
- assert_true(isinstance(dataset.ext_vars, np.recarray))
- assert_true(isinstance(dataset.cmaps[0], _basestring))
- assert_equal(dataset.ext_vars.size, 1)
- assert_equal(len(dataset.cmaps), 1)
-
- # 20 subjects
- dataset = func.fetch_localizer_calculation_task(n_subjects=20,
- data_dir=tst.tmpdir,
- url=local_url,
- verbose=0)
+ # 2 subjects
+ dataset = func.fetch_localizer_calculation_task(
+ n_subjects=2,
+ data_dir=tst.tmpdir,
+ verbose=1)
assert_true(isinstance(dataset.ext_vars, np.recarray))
assert_true(isinstance(dataset.cmaps[0], _basestring))
- assert_equal(dataset.ext_vars.size, 20)
- assert_equal(len(dataset.cmaps), 20)
+ assert_equal(dataset.ext_vars.size, 2)
+ assert_equal(len(dataset.cmaps), 2)
assert_not_equal(dataset.description, '')
@with_setup(setup_mock, teardown_mock)
@with_setup(tst.setup_tmpdata, tst.teardown_tmpdata)
+@with_setup(setup_localizer, teardown_localizer)
def test_fetch_localizer_button_task():
- local_url = "file://" + tst.datadir
-
- # Disabled: cannot be tested without actually fetching covariates CSV file
- # Only one subject
- dataset = func.fetch_localizer_button_task(data_dir=tst.tmpdir,
- url=local_url,
- verbose=0)
- assert_true(isinstance(dataset.tmap, _basestring))
- assert_true(isinstance(dataset.anat, _basestring))
+ # 2 subjects
+ dataset = func.fetch_localizer_button_task(
+ data_dir=tst.tmpdir,
+ verbose=1)
+ assert_true(isinstance(dataset.tmaps[0], _basestring))
+ assert_true(isinstance(dataset.anats[0], _basestring))
assert_not_equal(dataset.description, '')
diff --git a/nilearn/datasets/utils.py b/nilearn/datasets/utils.py
index 446cae359e..d9aade43fa 100644
--- a/nilearn/datasets/utils.py
+++ b/nilearn/datasets/utils.py
@@ -336,9 +336,13 @@ def _uncompress_file(file_, delete_archive=True, verbose=1):
processed = True
elif ext == '.gz' or header.startswith(b'\x1f\x8b'):
import gzip
- gz = gzip.open(file_)
if ext == '.tgz':
filename = filename + '.tar'
+ elif ext == '':
+ # For gzip file, we rely on the assumption that there is an extenstion
+ shutil.move(file_, file_ + '.gz')
+ file_ = file_ + '.gz'
+ gz = gzip.open(file_)
out = open(filename, 'wb')
shutil.copyfileobj(gz, out, 8192)
gz.close()
diff --git a/nilearn/decoding/searchlight.py b/nilearn/decoding/searchlight.py
index 5829b1ff5b..c853f9e0de 100644
--- a/nilearn/decoding/searchlight.py
+++ b/nilearn/decoding/searchlight.py
@@ -16,7 +16,7 @@
import numpy as np
-from sklearn.externals.joblib import Parallel, delayed, cpu_count
+from nilearn._utils.compat import Parallel, delayed, cpu_count
from sklearn import svm
from sklearn.base import BaseEstimator
from sklearn.exceptions import ConvergenceWarning
diff --git a/nilearn/decoding/space_net.py b/nilearn/decoding/space_net.py
index 9867b3ca21..368513a8ef 100644
--- a/nilearn/decoding/space_net.py
+++ b/nilearn/decoding/space_net.py
@@ -24,7 +24,7 @@
from sklearn.linear_model.base import LinearModel
from sklearn.feature_selection import (SelectPercentile, f_regression,
f_classif)
-from sklearn.externals.joblib import Memory, Parallel, delayed
+from nilearn._utils.compat import Memory, Parallel, delayed
from sklearn.preprocessing import LabelBinarizer
from sklearn.metrics import accuracy_score
from ..input_data.masker_validation import check_embedded_nifti_masker
diff --git a/nilearn/decoding/tests/test_searchlight.py b/nilearn/decoding/tests/test_searchlight.py
index c731ad92e0..fc7b42f9df 100644
--- a/nilearn/decoding/tests/test_searchlight.py
+++ b/nilearn/decoding/tests/test_searchlight.py
@@ -100,10 +100,10 @@ def test_searchlight():
rand = np.random.RandomState(0)
data = rand.rand(5, 5, 5)
data_img = nibabel.Nifti1Image(data, affine=np.eye(4))
- imgs = [data_img, data_img, data_img, data_img, data_img, data_img]
+ imgs = [data_img] * 12
# labels
- y = [0, 1, 0, 1, 0, 1]
+ y = [0, 1] * 6
# run searchlight on list of 3D images
sl = searchlight.SearchLight(mask_img)
diff --git a/nilearn/decomposition/base.py b/nilearn/decomposition/base.py
index bb6fad4044..d479dd2078 100644
--- a/nilearn/decomposition/base.py
+++ b/nilearn/decomposition/base.py
@@ -14,7 +14,7 @@
import sklearn
import nilearn
from sklearn.base import BaseEstimator, TransformerMixin
-from sklearn.externals.joblib import Memory, Parallel, delayed
+from nilearn._utils.compat import Memory, Parallel, delayed
from sklearn.linear_model import LinearRegression
from sklearn.utils import check_random_state
from sklearn.utils.extmath import randomized_svd, svd_flip
diff --git a/nilearn/decomposition/canica.py b/nilearn/decomposition/canica.py
index ef6d77d63a..2a4ad45aac 100644
--- a/nilearn/decomposition/canica.py
+++ b/nilearn/decomposition/canica.py
@@ -10,7 +10,7 @@
import numpy as np
from scipy.stats import scoreatpercentile
from sklearn.decomposition import fastica
-from sklearn.externals.joblib import Memory, delayed, Parallel
+from nilearn._utils.compat import Memory, delayed, Parallel
from sklearn.utils import check_random_state
from .multi_pca import MultiPCA
diff --git a/nilearn/decomposition/dict_learning.py b/nilearn/decomposition/dict_learning.py
index e31b2e734f..25c79a435f 100644
--- a/nilearn/decomposition/dict_learning.py
+++ b/nilearn/decomposition/dict_learning.py
@@ -15,7 +15,7 @@
import numpy as np
import sklearn
from sklearn.decomposition import dict_learning_online
-from sklearn.externals.joblib import Memory
+from nilearn._utils.compat import Memory
from sklearn.linear_model import Ridge
from .base import BaseDecomposition
diff --git a/nilearn/decomposition/multi_pca.py b/nilearn/decomposition/multi_pca.py
index 5b888c615d..84b6daeb45 100644
--- a/nilearn/decomposition/multi_pca.py
+++ b/nilearn/decomposition/multi_pca.py
@@ -3,7 +3,7 @@
This is a good initialization method for ICA.
"""
import numpy as np
-from sklearn.externals.joblib import Memory
+from nilearn._utils.compat import Memory
from sklearn.utils.extmath import randomized_svd
from .base import BaseDecomposition
diff --git a/nilearn/externals/README.md b/nilearn/externals/README.md
new file mode 100644
index 0000000000..0e6519bbed
--- /dev/null
+++ b/nilearn/externals/README.md
@@ -0,0 +1,5 @@
+This directory contains bundled external dependencies.
+
+Note for distribution packagers: if you want to remove the duplicated
+code and depend on a packaged version, we suggest that you simply do a
+symbolic link in this directory.
diff --git a/nilearn/externals/__init__.py b/nilearn/externals/__init__.py
new file mode 100644
index 0000000000..c861213890
--- /dev/null
+++ b/nilearn/externals/__init__.py
@@ -0,0 +1,7 @@
+"""
+External, bundled dependencies for Nilearn.
+
+To ignore linting on these files, at the top define:
+
+# flake8: noqa
+"""
diff --git a/nilearn/externals/conftest.py b/nilearn/externals/conftest.py
new file mode 100644
index 0000000000..f3bb9d9e9a
--- /dev/null
+++ b/nilearn/externals/conftest.py
@@ -0,0 +1,8 @@
+# Do not collect any tests in externals. This is more robust than using
+# --ignore because --ignore needs a path and it is not convenient to pass in
+# the externals path (very long install-dependent path in site-packages) when
+# using --pyargs
+
+
+def pytest_ignore_collect(path, config):
+ return True
diff --git a/nilearn/externals/install_tempita.sh b/nilearn/externals/install_tempita.sh
new file mode 100644
index 0000000000..9e6c1d4425
--- /dev/null
+++ b/nilearn/externals/install_tempita.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+# Script to do a local install of tempita
+set +x
+export LC_ALL=C
+INSTALL_FOLDER=tmp/tempita_install
+rm -rf tempita $INSTALL_FOLDER
+if [ -z "$1" ]
+then
+ TEMPITA=tempita
+else
+ TEMPITA=$1
+fi
+
+pip install --no-cache $TEMPITA --target $INSTALL_FOLDER
+cp -r $INSTALL_FOLDER/tempita tempita
+rm -rf $INSTALL_FOLDER
+
+# Needed to rewrite the doctests
+# Note: BSD sed -i needs an argument unders OSX
+# so first renaming to .bak and then deleting backup files
+find tempita -name "*.py" | xargs sed -i.bak "s/from tempita/from nilearn.externals.tempita/"
+find tempita -name "*.bak" | xargs rm
diff --git a/nilearn/externals/tempita/__init__.py b/nilearn/externals/tempita/__init__.py
new file mode 100644
index 0000000000..91f4091672
--- /dev/null
+++ b/nilearn/externals/tempita/__init__.py
@@ -0,0 +1,1311 @@
+# flake8: noqa
+"""
+A small templating language
+
+This implements a small templating language. This language implements
+if/elif/else, for/continue/break, expressions, and blocks of Python
+code. The syntax is::
+
+ {{any expression (function calls etc)}}
+ {{any expression | filter}}
+ {{for x in y}}...{{endfor}}
+ {{if x}}x{{elif y}}y{{else}}z{{endif}}
+ {{py:x=1}}
+ {{py:
+ def foo(bar):
+ return 'baz'
+ }}
+ {{default var = default_value}}
+ {{# comment}}
+
+You use this with the ``Template`` class or the ``sub`` shortcut.
+The ``Template`` class takes the template string and the name of
+the template (for errors) and a default namespace. Then (like
+``string.Template``) you can call the ``tmpl.substitute(**kw)``
+method to make a substitution (or ``tmpl.substitute(a_dict)``).
+
+``sub(content, **kw)`` substitutes the template immediately. You
+can use ``__name='tmpl.html'`` to set the name of the template.
+
+If there are syntax errors ``TemplateError`` will be raised.
+"""
+from __future__ import absolute_import, division, print_function
+
+import re
+import sys
+try:
+ from urllib.parse import quote as url_quote
+ from io import StringIO
+ from html import escape as html_escape
+except ImportError:
+ from urllib import quote as url_quote
+ from cStringIO import StringIO
+ from cgi import escape as html_escape
+import os
+import tokenize
+from ._looper import looper
+from .compat3 import (
+ PY3, bytes, basestring_, next, is_unicode, coerce_text, iteritems)
+
+__all__ = ['TemplateError', 'Template', 'sub', 'HTMLTemplate',
+ 'sub_html', 'html', 'bunch']
+
+in_re = re.compile(r'\s+in\s+')
+var_re = re.compile(r'^[a-z_][a-z0-9_]*$', re.I)
+
+
+class TemplateError(Exception):
+ """Exception raised while parsing a template
+ """
+
+ def __init__(self, message, position, name=None):
+ Exception.__init__(self, message)
+ self.position = position
+ self.name = name
+
+ def __str__(self):
+ msg = ' '.join(self.args)
+ if self.position:
+ msg = '%s at line %s column %s' % (
+ msg, self.position[0], self.position[1])
+ if self.name:
+ msg += ' in %s' % self.name
+ return msg
+
+
+class _TemplateContinue(Exception):
+ pass
+
+
+class _TemplateBreak(Exception):
+ pass
+
+
+def get_file_template(name, from_template):
+ path = os.path.join(os.path.dirname(from_template.name), name)
+ return from_template.__class__.from_filename(
+ path, namespace=from_template.namespace,
+ get_template=from_template.get_template)
+
+
+class Template(object):
+
+ default_namespace = {
+ 'start_braces': '{{',
+ 'end_braces': '}}',
+ 'looper': looper,
+ }
+
+ default_encoding = 'utf8'
+ default_inherit = None
+
+ def __init__(self, content, name=None, namespace=None, stacklevel=None,
+ get_template=None, default_inherit=None, line_offset=0,
+ delimeters=None):
+ self.content = content
+
+ # set delimeters
+ if delimeters is None:
+ delimeters = (self.default_namespace['start_braces'],
+ self.default_namespace['end_braces'])
+ else:
+ assert len(delimeters) == 2 and all(
+ [isinstance(delimeter, basestring_)
+ for delimeter in delimeters])
+ self.default_namespace = self.__class__.default_namespace.copy()
+ self.default_namespace['start_braces'] = delimeters[0]
+ self.default_namespace['end_braces'] = delimeters[1]
+ self.delimeters = delimeters
+
+ self._unicode = is_unicode(content)
+ if name is None and stacklevel is not None:
+ try:
+ caller = sys._getframe(stacklevel)
+ except ValueError:
+ pass
+ else:
+ globals = caller.f_globals
+ lineno = caller.f_lineno
+ if '__file__' in globals:
+ name = globals['__file__']
+ if name.endswith('.pyc') or name.endswith('.pyo'):
+ name = name[:-1]
+ elif '__name__' in globals:
+ name = globals['__name__']
+ else:
+ name = ''
+ if lineno:
+ name += ':%s' % lineno
+ self.name = name
+ self._parsed = parse(
+ content, name=name, line_offset=line_offset,
+ delimeters=self.delimeters)
+ if namespace is None:
+ namespace = {}
+ self.namespace = namespace
+ self.get_template = get_template
+ if default_inherit is not None:
+ self.default_inherit = default_inherit
+
+ def from_filename(cls, filename, namespace=None, encoding=None,
+ default_inherit=None, get_template=get_file_template):
+ f = open(filename, 'rb')
+ c = f.read()
+ f.close()
+ if encoding:
+ c = c.decode(encoding)
+ elif PY3:
+ c = c.decode('latin-1')
+ return cls(content=c, name=filename, namespace=namespace,
+ default_inherit=default_inherit, get_template=get_template)
+
+ from_filename = classmethod(from_filename)
+
+ def __repr__(self):
+ return '<%s %s name=%r>' % (
+ self.__class__.__name__,
+ hex(id(self))[2:], self.name)
+
+ def substitute(self, *args, **kw):
+ if args:
+ if kw:
+ raise TypeError(
+ "You can only give positional *or* keyword arguments")
+ if len(args) > 1:
+ raise TypeError(
+ "You can only give one positional argument")
+ if not hasattr(args[0], 'items'):
+ raise TypeError(
+ ("If you pass in a single argument, you must pass in a ",
+ "dict-like object (with a .items() method); you gave %r")
+ % (args[0],))
+ kw = args[0]
+ ns = kw
+ ns['__template_name__'] = self.name
+ if self.namespace:
+ ns.update(self.namespace)
+ result, defs, inherit = self._interpret(ns)
+ if not inherit:
+ inherit = self.default_inherit
+ if inherit:
+ result = self._interpret_inherit(result, defs, inherit, ns)
+ return result
+
+ def _interpret(self, ns):
+ # __traceback_hide__ = True
+ parts = []
+ defs = {}
+ self._interpret_codes(self._parsed, ns, out=parts, defs=defs)
+ if '__inherit__' in defs:
+ inherit = defs.pop('__inherit__')
+ else:
+ inherit = None
+ return ''.join(parts), defs, inherit
+
+ def _interpret_inherit(self, body, defs, inherit_template, ns):
+ # __traceback_hide__ = True
+ if not self.get_template:
+ raise TemplateError(
+ 'You cannot use inheritance without passing in get_template',
+ position=None, name=self.name)
+ templ = self.get_template(inherit_template, self)
+ self_ = TemplateObject(self.name)
+ for name, value in iteritems(defs):
+ setattr(self_, name, value)
+ self_.body = body
+ ns = ns.copy()
+ ns['self'] = self_
+ return templ.substitute(ns)
+
+ def _interpret_codes(self, codes, ns, out, defs):
+ # __traceback_hide__ = True
+ for item in codes:
+ if isinstance(item, basestring_):
+ out.append(item)
+ else:
+ self._interpret_code(item, ns, out, defs)
+
+ def _interpret_code(self, code, ns, out, defs):
+ # __traceback_hide__ = True
+ name, pos = code[0], code[1]
+ if name == 'py':
+ self._exec(code[2], ns, pos)
+ elif name == 'continue':
+ raise _TemplateContinue()
+ elif name == 'break':
+ raise _TemplateBreak()
+ elif name == 'for':
+ vars, expr, content = code[2], code[3], code[4]
+ expr = self._eval(expr, ns, pos)
+ self._interpret_for(vars, expr, content, ns, out, defs)
+ elif name == 'cond':
+ parts = code[2:]
+ self._interpret_if(parts, ns, out, defs)
+ elif name == 'expr':
+ parts = code[2].split('|')
+ base = self._eval(parts[0], ns, pos)
+ for part in parts[1:]:
+ func = self._eval(part, ns, pos)
+ base = func(base)
+ out.append(self._repr(base, pos))
+ elif name == 'default':
+ var, expr = code[2], code[3]
+ if var not in ns:
+ result = self._eval(expr, ns, pos)
+ ns[var] = result
+ elif name == 'inherit':
+ expr = code[2]
+ value = self._eval(expr, ns, pos)
+ defs['__inherit__'] = value
+ elif name == 'def':
+ name = code[2]
+ signature = code[3]
+ parts = code[4]
+ ns[name] = defs[name] = TemplateDef(
+ self, name, signature, body=parts, ns=ns, pos=pos)
+ elif name == 'comment':
+ return
+ else:
+ assert 0, "Unknown code: %r" % name
+
+ def _interpret_for(self, vars, expr, content, ns, out, defs):
+ # __traceback_hide__ = True
+ for item in expr:
+ if len(vars) == 1:
+ ns[vars[0]] = item
+ else:
+ if len(vars) != len(item):
+ raise ValueError(
+ 'Need %i items to unpack (got %i items)'
+ % (len(vars), len(item)))
+ for name, value in zip(vars, item):
+ ns[name] = value
+ try:
+ self._interpret_codes(content, ns, out, defs)
+ except _TemplateContinue:
+ continue
+ except _TemplateBreak:
+ break
+
+ def _interpret_if(self, parts, ns, out, defs):
+ # __traceback_hide__ = True
+ # @@: if/else/else gets through
+ for part in parts:
+ assert not isinstance(part, basestring_)
+ name, pos = part[0], part[1]
+ if name == 'else':
+ result = True
+ else:
+ result = self._eval(part[2], ns, pos)
+ if result:
+ self._interpret_codes(part[3], ns, out, defs)
+ break
+
+ def _eval(self, code, ns, pos):
+ # __traceback_hide__ = True
+ try:
+ try:
+ value = eval(code, self.default_namespace, ns)
+ except SyntaxError as e:
+ raise SyntaxError(
+ 'invalid syntax in expression: %s' % code)
+ return value
+ except:
+ exc_info = sys.exc_info()
+ e = exc_info[1]
+ if getattr(e, 'args', None):
+ arg0 = e.args[0]
+ else:
+ arg0 = coerce_text(e)
+ e.args = (self._add_line_info(arg0, pos),)
+ if PY3:
+ raise(e)
+ else:
+ raise (exc_info[1], e, exc_info[2])
+
+ def _exec(self, code, ns, pos):
+ # __traceback_hide__ = True
+ try:
+ exec(code, self.default_namespace, ns)
+ except:
+ exc_info = sys.exc_info()
+ e = exc_info[1]
+ if e.args:
+ e.args = (self._add_line_info(e.args[0], pos),)
+ else:
+ e.args = (self._add_line_info(None, pos),)
+ if PY3:
+ raise(e)
+ else:
+ raise (exc_info[1], e, exc_info[2])
+
+ def _repr(self, value, pos):
+ # __traceback_hide__ = True
+ try:
+ if value is None:
+ return ''
+ if self._unicode:
+ value = str(value)
+ if not is_unicode(value):
+ value = value.decode('utf-8')
+ else:
+ if not isinstance(value, basestring_):
+ value = coerce_text(value)
+ if (is_unicode(value) and self.default_encoding):
+ value = value.encode(self.default_encoding)
+ except:
+ exc_info = sys.exc_info()
+ e = exc_info[1]
+ e.args = (self._add_line_info(e.args[0], pos),)
+ if PY3:
+ raise(e)
+ else:
+ raise (exc_info[1], e, exc_info[2])
+ else:
+ if self._unicode and isinstance(value, bytes):
+ if not self.default_encoding:
+ raise UnicodeDecodeError(
+ 'Cannot decode bytes value %r into unicode '
+ '(no default_encoding provided)' % value)
+ try:
+ value = value.decode(self.default_encoding)
+ except UnicodeDecodeError as e:
+ raise UnicodeDecodeError(
+ e.encoding,
+ e.object,
+ e.start,
+ e.end,
+ e.reason + ' in string %r' % value)
+ elif not self._unicode and is_unicode(value):
+ if not self.default_encoding:
+ raise UnicodeEncodeError(
+ 'Cannot encode unicode value %r into bytes '
+ '(no default_encoding provided)' % value)
+ value = value.encode(self.default_encoding)
+ return value
+
+ def _add_line_info(self, msg, pos):
+ msg = "%s at line %s column %s" % (
+ msg, pos[0], pos[1])
+ if self.name:
+ msg += " in file %s" % self.name
+ return msg
+
+
+def sub(content, delimeters=None, **kw):
+ name = kw.get('__name')
+ tmpl = Template(content, name=name, delimeters=delimeters)
+ return tmpl.substitute(kw)
+
+
+def paste_script_template_renderer(content, vars, filename=None):
+ tmpl = Template(content, name=filename)
+ return tmpl.substitute(vars)
+
+
+class bunch(dict):
+
+ def __init__(self, **kw):
+ for name, value in iteritems(kw):
+ setattr(self, name, value)
+
+ def __setattr__(self, name, value):
+ self[name] = value
+
+ def __getattr__(self, name):
+ try:
+ return self[name]
+ except KeyError:
+ raise AttributeError(name)
+
+ def __getitem__(self, key):
+ if 'default' in self:
+ try:
+ return dict.__getitem__(self, key)
+ except KeyError:
+ return dict.__getitem__(self, 'default')
+ else:
+ return dict.__getitem__(self, key)
+
+ def __repr__(self):
+ items = [
+ (k, v) for k, v in iteritems(self)]
+ items.sort()
+ return '<%s %s>' % (
+ self.__class__.__name__,
+ ' '.join(['%s=%r' % (k, v) for k, v in items]))
+
+############################################################
+# HTML Templating
+############################################################
+
+
+class html(object):
+
+ def __init__(self, value):
+ self.value = value
+
+ def __str__(self):
+ return self.value
+
+ def __html__(self):
+ return self.value
+
+ def __repr__(self):
+ return '<%s %r>' % (
+ self.__class__.__name__, self.value)
+
+
+def html_quote(value, force=True):
+ if not force and hasattr(value, '__html__'):
+ return value.__html__()
+ if value is None:
+ return ''
+ if not isinstance(value, basestring_):
+ value = coerce_text(value)
+ if sys.version >= "3" and isinstance(value, bytes):
+ value = html_escape(value.decode('latin1'), 1)
+ value = value.encode('latin1')
+ else:
+ value = html_escape(value, 1)
+ if sys.version < "3":
+ if is_unicode(value):
+ value = value.encode('ascii', 'xmlcharrefreplace')
+ return value
+
+
+def url(v):
+ v = coerce_text(v)
+ if is_unicode(v):
+ v = v.encode('utf8')
+ return url_quote(v)
+
+
+def attr(**kw):
+ kw = list(iteritems(kw))
+ kw.sort()
+ parts = []
+ for name, value in kw:
+ if value is None:
+ continue
+ if name.endswith('_'):
+ name = name[:-1]
+ parts.append('%s="%s"' % (html_quote(name), html_quote(value)))
+ return html(' '.join(parts))
+
+
+class HTMLTemplate(Template):
+
+ default_namespace = Template.default_namespace.copy()
+ default_namespace.update(dict(
+ html=html,
+ attr=attr,
+ url=url,
+ html_quote=html_quote))
+
+ def _repr(self, value, pos):
+ if hasattr(value, '__html__'):
+ value = value.__html__()
+ quote = False
+ else:
+ quote = True
+ plain = Template._repr(self, value, pos)
+ if quote:
+ return html_quote(plain)
+ else:
+ return plain
+
+
+def sub_html(content, **kw):
+ name = kw.get('__name')
+ tmpl = HTMLTemplate(content, name=name)
+ return tmpl.substitute(kw)
+
+
+class TemplateDef(object):
+ def __init__(self, template, func_name, func_signature,
+ body, ns, pos, bound_self=None):
+ self._template = template
+ self._func_name = func_name
+ self._func_signature = func_signature
+ self._body = body
+ self._ns = ns
+ self._pos = pos
+ self._bound_self = bound_self
+
+ def __repr__(self):
+ return '' % (
+ self._func_name, self._func_signature,
+ self._template.name, self._pos)
+
+ def __str__(self):
+ return self()
+
+ def __call__(self, *args, **kw):
+ values = self._parse_signature(args, kw)
+ ns = self._ns.copy()
+ ns.update(values)
+ if self._bound_self is not None:
+ ns['self'] = self._bound_self
+ out = []
+ subdefs = {}
+ self._template._interpret_codes(self._body, ns, out, subdefs)
+ return ''.join(out)
+
+ def __get__(self, obj, type=None):
+ if obj is None:
+ return self
+ return self.__class__(
+ self._template, self._func_name, self._func_signature,
+ self._body, self._ns, self._pos, bound_self=obj)
+
+ def _parse_signature(self, args, kw):
+ values = {}
+ sig_args, var_args, var_kw, defaults = self._func_signature
+ extra_kw = {}
+ for name, value in iteritems(kw):
+ if not var_kw and name not in sig_args:
+ raise TypeError(
+ 'Unexpected argument %s' % name)
+ if name in sig_args:
+ values[sig_args] = value
+ else:
+ extra_kw[name] = value
+ args = list(args)
+ sig_args = list(sig_args)
+ while args:
+ while sig_args and sig_args[0] in values:
+ sig_args.pop(0)
+ if sig_args:
+ name = sig_args.pop(0)
+ values[name] = args.pop(0)
+ elif var_args:
+ values[var_args] = tuple(args)
+ break
+ else:
+ raise TypeError(
+ 'Extra position arguments: %s'
+ % ', '.join(repr(v) for v in args))
+ for name, value_expr in iteritems(defaults):
+ if name not in values:
+ values[name] = self._template._eval(
+ value_expr, self._ns, self._pos)
+ for name in sig_args:
+ if name not in values:
+ raise TypeError(
+ 'Missing argument: %s' % name)
+ if var_kw:
+ values[var_kw] = extra_kw
+ return values
+
+
+class TemplateObject(object):
+
+ def __init__(self, name):
+ self.__name = name
+ self.get = TemplateObjectGetter(self)
+
+ def __repr__(self):
+ return '<%s %s>' % (self.__class__.__name__, self.__name)
+
+
+class TemplateObjectGetter(object):
+
+ def __init__(self, template_obj):
+ self.__template_obj = template_obj
+
+ def __getattr__(self, attr):
+ return getattr(self.__template_obj, attr, Empty)
+
+ def __repr__(self):
+ return '<%s around %r>' % (
+ self.__class__.__name__, self.__template_obj)
+
+
+class _Empty(object):
+ def __call__(self, *args, **kw):
+ return self
+
+ def __str__(self):
+ return ''
+
+ def __repr__(self):
+ return 'Empty'
+
+ def __unicode__(self):
+ return '' if PY3 else u''
+
+ def __iter__(self):
+ return iter(())
+
+ def __bool__(self):
+ return False
+
+ if sys.version < "3":
+ __nonzero__ = __bool__
+
+Empty = _Empty()
+del _Empty
+
+############################################################
+# Lexing and Parsing
+############################################################
+
+
+def lex(s, name=None, trim_whitespace=True, line_offset=0, delimeters=None):
+ if delimeters is None:
+ delimeters = (Template.default_namespace['start_braces'],
+ Template.default_namespace['end_braces'])
+ in_expr = False
+ chunks = []
+ last = 0
+ last_pos = (line_offset + 1, 1)
+ token_re = re.compile(r'%s|%s' % (re.escape(delimeters[0]),
+ re.escape(delimeters[1])))
+ for match in token_re.finditer(s):
+ expr = match.group(0)
+ pos = find_position(s, match.end(), last, last_pos)
+ if expr == delimeters[0] and in_expr:
+ raise TemplateError('%s inside expression' % delimeters[0],
+ position=pos,
+ name=name)
+ elif expr == delimeters[1] and not in_expr:
+ raise TemplateError('%s outside expression' % delimeters[1],
+ position=pos,
+ name=name)
+ if expr == delimeters[0]:
+ part = s[last:match.start()]
+ if part:
+ chunks.append(part)
+ in_expr = True
+ else:
+ chunks.append((s[last:match.start()], last_pos))
+ in_expr = False
+ last = match.end()
+ last_pos = pos
+ if in_expr:
+ raise TemplateError('No %s to finish last expression' % delimeters[1],
+ name=name, position=last_pos)
+ part = s[last:]
+ if part:
+ chunks.append(part)
+ if trim_whitespace:
+ chunks = trim_lex(chunks)
+ return chunks
+
+lex.__doc__ = """
+Lex a string into chunks:
+
+ >>> lex('hey')
+ ['hey']
+ >>> lex('hey {{you}}')
+ ['hey ', ('you', (1, 7))]
+ >>> lex('hey {{')
+ Traceback (most recent call last):
+ ...
+ tempita.TemplateError: No }} to finish last expression at line 1 column 7
+ >>> lex('hey }}')
+ Traceback (most recent call last):
+ ...
+ tempita.TemplateError: }} outside expression at line 1 column 7
+ >>> lex('hey {{ {{')
+ Traceback (most recent call last):
+ ...
+ tempita.TemplateError: {{ inside expression at line 1 column 10
+
+""" if PY3 else """
+Lex a string into chunks:
+
+ >>> lex('hey')
+ ['hey']
+ >>> lex('hey {{you}}')
+ ['hey ', ('you', (1, 7))]
+ >>> lex('hey {{')
+ Traceback (most recent call last):
+ ...
+ TemplateError: No }} to finish last expression at line 1 column 7
+ >>> lex('hey }}')
+ Traceback (most recent call last):
+ ...
+ TemplateError: }} outside expression at line 1 column 7
+ >>> lex('hey {{ {{')
+ Traceback (most recent call last):
+ ...
+ TemplateError: {{ inside expression at line 1 column 10
+
+"""
+
+statement_re = re.compile(r'^(?:if |elif |for |def |inherit |default |py:)')
+single_statements = ['else', 'endif', 'endfor', 'enddef', 'continue', 'break']
+trail_whitespace_re = re.compile(r'\n\r?[\t ]*$')
+lead_whitespace_re = re.compile(r'^[\t ]*\n')
+
+
+def trim_lex(tokens):
+ last_trim = None
+ for i in range(len(tokens)):
+ current = tokens[i]
+ if isinstance(tokens[i], basestring_):
+ # we don't trim this
+ continue
+ item = current[0]
+ if not statement_re.search(item) and item not in single_statements:
+ continue
+ if not i:
+ prev = ''
+ else:
+ prev = tokens[i - 1]
+ if i + 1 >= len(tokens):
+ next_chunk = ''
+ else:
+ next_chunk = tokens[i + 1]
+ if (not
+ isinstance(next_chunk, basestring_) or
+ not isinstance(prev, basestring_)):
+ continue
+ prev_ok = not prev or trail_whitespace_re.search(prev)
+ if i == 1 and not prev.strip():
+ prev_ok = True
+ if last_trim is not None and last_trim + 2 == i and not prev.strip():
+ prev_ok = 'last'
+ if (prev_ok and (not next_chunk or lead_whitespace_re.search(
+ next_chunk) or (
+ i == len(tokens) - 2 and not next_chunk.strip()))):
+ if prev:
+ if ((i == 1 and not prev.strip()) or prev_ok == 'last'):
+ tokens[i - 1] = ''
+ else:
+ m = trail_whitespace_re.search(prev)
+ # +1 to leave the leading \n on:
+ prev = prev[:m.start() + 1]
+ tokens[i - 1] = prev
+ if next_chunk:
+ last_trim = i
+ if i == len(tokens) - 2 and not next_chunk.strip():
+ tokens[i + 1] = ''
+ else:
+ m = lead_whitespace_re.search(next_chunk)
+ next_chunk = next_chunk[m.end():]
+ tokens[i + 1] = next_chunk
+ return tokens
+
+trim_lex.__doc__ = r"""
+ Takes a lexed set of tokens, and removes whitespace when there is
+ a directive on a line by itself:
+
+ >>> tokens = lex('{{if x}}\nx\n{{endif}}\ny', trim_whitespace=False)
+ >>> tokens
+ [('if x', (1, 3)), '\nx\n', ('endif', (3, 3)), '\ny']
+ >>> trim_lex(tokens)
+ [('if x', (1, 3)), 'x\n', ('endif', (3, 3)), 'y']
+ """ if PY3 else r"""
+ Takes a lexed set of tokens, and removes whitespace when there is
+ a directive on a line by itself:
+
+ >>> tokens = lex('{{if x}}\nx\n{{endif}}\ny', trim_whitespace=False)
+ >>> tokens
+ [('if x', (1, 3)), '\nx\n', ('endif', (3, 3)), '\ny']
+ >>> trim_lex(tokens)
+ [('if x', (1, 3)), 'x\n', ('endif', (3, 3)), 'y']
+ """
+
+
+def find_position(string, index, last_index, last_pos):
+ """
+ Given a string and index, return (line, column)
+ """
+ lines = string.count('\n', last_index, index)
+ if lines > 0:
+ column = index - string.rfind('\n', last_index, index)
+ else:
+ column = last_pos[1] + (index - last_index)
+ return (last_pos[0] + lines, column)
+
+
+def parse(s, name=None, line_offset=0, delimeters=None):
+
+ if delimeters is None:
+ delimeters = (Template.default_namespace['start_braces'],
+ Template.default_namespace['end_braces'])
+ tokens = lex(s, name=name, line_offset=line_offset, delimeters=delimeters)
+ result = []
+ while tokens:
+ next_chunk, tokens = parse_expr(tokens, name)
+ result.append(next_chunk)
+ return result
+
+parse.__doc__ = r"""
+ Parses a string into a kind of AST
+
+ >>> parse('{{x}}')
+ [('expr', (1, 3), 'x')]
+ >>> parse('foo')
+ ['foo']
+ >>> parse('{{if x}}test{{endif}}')
+ [('cond', (1, 3), ('if', (1, 3), 'x', ['test']))]
+ >>> parse(
+ ... 'series->{{for x in y}}x={{x}}{{endfor}}'
+ ... ) #doctest: +NORMALIZE_WHITESPACE
+ ['series->',
+ ('for', (1, 11), ('x',), 'y', ['x=', ('expr', (1, 27), 'x')])]
+ >>> parse('{{for x, y in z:}}{{continue}}{{endfor}}')
+ [('for', (1, 3), ('x', 'y'), 'z', [('continue', (1, 21))])]
+ >>> parse('{{py:x=1}}')
+ [('py', (1, 3), 'x=1')]
+ >>> parse(
+ ... '{{if x}}a{{elif y}}b{{else}}c{{endif}}'
+ ... ) #doctest: +NORMALIZE_WHITESPACE
+ [('cond', (1, 3), ('if', (1, 3), 'x', ['a']),
+ ('elif', (1, 12), 'y', ['b']), ('else', (1, 23), None, ['c']))]
+
+ Some exceptions::
+
+ >>> parse('{{continue}}')
+ Traceback (most recent call last):
+ ...
+ tempita.TemplateError: continue outside of for loop at line 1 column 3
+ >>> parse('{{if x}}foo')
+ Traceback (most recent call last):
+ ...
+ tempita.TemplateError: No {{endif}} at line 1 column 3
+ >>> parse('{{else}}')
+ Traceback (most recent call last):
+ ...
+ tempita.TemplateError: else outside of an if block at line 1 column 3
+ >>> parse('{{if x}}{{for x in y}}{{endif}}{{endfor}}')
+ Traceback (most recent call last):
+ ...
+ tempita.TemplateError: Unexpected endif at line 1 column 25
+ >>> parse('{{if}}{{endif}}')
+ Traceback (most recent call last):
+ ...
+ tempita.TemplateError: if with no expression at line 1 column 3
+ >>> parse('{{for x y}}{{endfor}}')
+ Traceback (most recent call last):
+ ...
+ tempita.TemplateError: Bad for (no "in") in 'x y' at line 1 column 3
+ >>> parse('{{py:x=1\ny=2}}') #doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ tempita.TemplateError: Multi-line py blocks must start
+ with a newline at line 1 column 3
+ """ if PY3 else r"""
+ Parses a string into a kind of AST
+
+ >>> parse('{{x}}')
+ [('expr', (1, 3), 'x')]
+ >>> parse('foo')
+ ['foo']
+ >>> parse('{{if x}}test{{endif}}')
+ [('cond', (1, 3), ('if', (1, 3), 'x', ['test']))]
+ >>> parse(
+ ... 'series->{{for x in y}}x={{x}}{{endfor}}'
+ ... ) #doctest: +NORMALIZE_WHITESPACE
+ ['series->',
+ ('for', (1, 11), ('x',), 'y', ['x=', ('expr', (1, 27), 'x')])]
+ >>> parse('{{for x, y in z:}}{{continue}}{{endfor}}')
+ [('for', (1, 3), ('x', 'y'), 'z', [('continue', (1, 21))])]
+ >>> parse('{{py:x=1}}')
+ [('py', (1, 3), 'x=1')]
+ >>> parse(
+ ... '{{if x}}a{{elif y}}b{{else}}c{{endif}}'
+ ... ) #doctest: +NORMALIZE_WHITESPACE
+ [('cond', (1, 3), ('if', (1, 3), 'x', ['a']),
+ ('elif', (1, 12), 'y', ['b']), ('else', (1, 23), None, ['c']))]
+
+ Some exceptions::
+
+ >>> parse('{{continue}}')
+ Traceback (most recent call last):
+ ...
+ TemplateError: continue outside of for loop at line 1 column 3
+ >>> parse('{{if x}}foo')
+ Traceback (most recent call last):
+ ...
+ TemplateError: No {{endif}} at line 1 column 3
+ >>> parse('{{else}}')
+ Traceback (most recent call last):
+ ...
+ TemplateError: else outside of an if block at line 1 column 3
+ >>> parse('{{if x}}{{for x in y}}{{endif}}{{endfor}}')
+ Traceback (most recent call last):
+ ...
+ TemplateError: Unexpected endif at line 1 column 25
+ >>> parse('{{if}}{{endif}}')
+ Traceback (most recent call last):
+ ...
+ TemplateError: if with no expression at line 1 column 3
+ >>> parse('{{for x y}}{{endfor}}')
+ Traceback (most recent call last):
+ ...
+ TemplateError: Bad for (no "in") in 'x y' at line 1 column 3
+ >>> parse('{{py:x=1\ny=2}}') #doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TemplateError: Multi-line py blocks must start
+ with a newline at line 1 column 3
+ """
+
+
+def parse_expr(tokens, name, context=()):
+ if isinstance(tokens[0], basestring_):
+ return tokens[0], tokens[1:]
+ expr, pos = tokens[0]
+ expr = expr.strip()
+ if expr.startswith('py:'):
+ expr = expr[3:].lstrip(' \t')
+ if expr.startswith('\n') or expr.startswith('\r'):
+ expr = expr.lstrip('\r\n')
+ if '\r' in expr:
+ expr = expr.replace('\r\n', '\n')
+ expr = expr.replace('\r', '')
+ expr += '\n'
+ else:
+ if '\n' in expr:
+ raise TemplateError(
+ 'Multi-line py blocks must start with a newline',
+ position=pos, name=name)
+ return ('py', pos, expr), tokens[1:]
+ elif expr in ('continue', 'break'):
+ if 'for' not in context:
+ raise TemplateError(
+ 'continue outside of for loop',
+ position=pos, name=name)
+ return (expr, pos), tokens[1:]
+ elif expr.startswith('if '):
+ return parse_cond(tokens, name, context)
+ elif (expr.startswith('elif ') or expr == 'else'):
+ raise TemplateError(
+ '%s outside of an if block' % expr.split()[0],
+ position=pos, name=name)
+ elif expr in ('if', 'elif', 'for'):
+ raise TemplateError(
+ '%s with no expression' % expr,
+ position=pos, name=name)
+ elif expr in ('endif', 'endfor', 'enddef'):
+ raise TemplateError(
+ 'Unexpected %s' % expr,
+ position=pos, name=name)
+ elif expr.startswith('for '):
+ return parse_for(tokens, name, context)
+ elif expr.startswith('default '):
+ return parse_default(tokens, name, context)
+ elif expr.startswith('inherit '):
+ return parse_inherit(tokens, name, context)
+ elif expr.startswith('def '):
+ return parse_def(tokens, name, context)
+ elif expr.startswith('#'):
+ return ('comment', pos, tokens[0][0]), tokens[1:]
+ return ('expr', pos, tokens[0][0]), tokens[1:]
+
+
+def parse_cond(tokens, name, context):
+ start = tokens[0][1]
+ pieces = []
+ context = context + ('if',)
+ while 1:
+ if not tokens:
+ raise TemplateError(
+ 'Missing {{endif}}',
+ position=start, name=name)
+ if (isinstance(tokens[0], tuple) and tokens[0][0] == 'endif'):
+ return ('cond', start) + tuple(pieces), tokens[1:]
+ next_chunk, tokens = parse_one_cond(tokens, name, context)
+ pieces.append(next_chunk)
+
+
+def parse_one_cond(tokens, name, context):
+ (first, pos), tokens = tokens[0], tokens[1:]
+ content = []
+ if first.endswith(':'):
+ first = first[:-1]
+ if first.startswith('if '):
+ part = ('if', pos, first[3:].lstrip(), content)
+ elif first.startswith('elif '):
+ part = ('elif', pos, first[5:].lstrip(), content)
+ elif first == 'else':
+ part = ('else', pos, None, content)
+ else:
+ assert 0, "Unexpected token %r at %s" % (first, pos)
+ while 1:
+ if not tokens:
+ raise TemplateError(
+ 'No {{endif}}',
+ position=pos, name=name)
+ if (isinstance(tokens[0], tuple) and (
+ tokens[0][0] == 'endif' or tokens[0][0].startswith(
+ 'elif ') or tokens[0][0] == 'else')):
+ return part, tokens
+ next_chunk, tokens = parse_expr(tokens, name, context)
+ content.append(next_chunk)
+
+
+def parse_for(tokens, name, context):
+ first, pos = tokens[0]
+ tokens = tokens[1:]
+ context = ('for',) + context
+ content = []
+ assert first.startswith('for ')
+ if first.endswith(':'):
+ first = first[:-1]
+ first = first[3:].strip()
+ match = in_re.search(first)
+ if not match:
+ raise TemplateError(
+ 'Bad for (no "in") in %r' % first,
+ position=pos, name=name)
+ vars = first[:match.start()]
+ if '(' in vars:
+ raise TemplateError(
+ 'You cannot have () in the variable section of a for loop (%r)'
+ % vars, position=pos, name=name)
+ vars = tuple([
+ v.strip() for v in first[:match.start()].split(',')
+ if v.strip()])
+ expr = first[match.end():]
+ while 1:
+ if not tokens:
+ raise TemplateError(
+ 'No {{endfor}}',
+ position=pos, name=name)
+ if (isinstance(tokens[0], tuple) and tokens[0][0] == 'endfor'):
+ return ('for', pos, vars, expr, content), tokens[1:]
+ next_chunk, tokens = parse_expr(tokens, name, context)
+ content.append(next_chunk)
+
+
+def parse_default(tokens, name, context):
+ first, pos = tokens[0]
+ assert first.startswith('default ')
+ first = first.split(None, 1)[1]
+ parts = first.split('=', 1)
+ if len(parts) == 1:
+ raise TemplateError(
+ "Expression must be {{default var=value}}; no = found in %r" %
+ first, position=pos, name=name)
+ var = parts[0].strip()
+ if ',' in var:
+ raise TemplateError(
+ "{{default x, y = ...}} is not supported",
+ position=pos, name=name)
+ if not var_re.search(var):
+ raise TemplateError(
+ "Not a valid variable name for {{default}}: %r"
+ % var, position=pos, name=name)
+ expr = parts[1].strip()
+ return ('default', pos, var, expr), tokens[1:]
+
+
+def parse_inherit(tokens, name, context):
+ first, pos = tokens[0]
+ assert first.startswith('inherit ')
+ expr = first.split(None, 1)[1]
+ return ('inherit', pos, expr), tokens[1:]
+
+
+def parse_def(tokens, name, context):
+ first, start = tokens[0]
+ tokens = tokens[1:]
+ assert first.startswith('def ')
+ first = first.split(None, 1)[1]
+ if first.endswith(':'):
+ first = first[:-1]
+ if '(' not in first:
+ func_name = first
+ sig = ((), None, None, {})
+ elif not first.endswith(')'):
+ raise TemplateError("Function definition doesn't end with ): %s" %
+ first, position=start, name=name)
+ else:
+ first = first[:-1]
+ func_name, sig_text = first.split('(', 1)
+ sig = parse_signature(sig_text, name, start)
+ context = context + ('def',)
+ content = []
+ while 1:
+ if not tokens:
+ raise TemplateError(
+ 'Missing {{enddef}}',
+ position=start, name=name)
+ if (isinstance(tokens[0], tuple) and tokens[0][0] == 'enddef'):
+ return ('def', start, func_name, sig, content), tokens[1:]
+ next_chunk, tokens = parse_expr(tokens, name, context)
+ content.append(next_chunk)
+
+
+def parse_signature(sig_text, name, pos):
+ tokens = tokenize.generate_tokens(StringIO(sig_text).readline)
+ sig_args = []
+ var_arg = None
+ var_kw = None
+ defaults = {}
+
+ def get_token(pos=False):
+ try:
+ tok_type, tok_string, (srow, scol), (erow, ecol), line = next(
+ tokens)
+ except StopIteration:
+ return tokenize.ENDMARKER, ''
+ if pos:
+ return tok_type, tok_string, (srow, scol), (erow, ecol)
+ else:
+ return tok_type, tok_string
+ while 1:
+ var_arg_type = None
+ tok_type, tok_string = get_token()
+ if tok_type == tokenize.ENDMARKER:
+ break
+ if tok_type == tokenize.OP and (
+ tok_string == '*' or tok_string == '**'):
+ var_arg_type = tok_string
+ tok_type, tok_string = get_token()
+ if tok_type != tokenize.NAME:
+ raise TemplateError('Invalid signature: (%s)' % sig_text,
+ position=pos, name=name)
+ var_name = tok_string
+ tok_type, tok_string = get_token()
+ if tok_type == tokenize.ENDMARKER or (
+ tok_type == tokenize.OP and tok_string == ','):
+ if var_arg_type == '*':
+ var_arg = var_name
+ elif var_arg_type == '**':
+ var_kw = var_name
+ else:
+ sig_args.append(var_name)
+ if tok_type == tokenize.ENDMARKER:
+ break
+ continue
+ if var_arg_type is not None:
+ raise TemplateError('Invalid signature: (%s)' % sig_text,
+ position=pos, name=name)
+ if tok_type == tokenize.OP and tok_string == '=':
+ nest_type = None
+ unnest_type = None
+ nest_count = 0
+ start_pos = end_pos = None
+ parts = []
+ while 1:
+ tok_type, tok_string, s, e = get_token(True)
+ if start_pos is None:
+ start_pos = s
+ end_pos = e
+ if tok_type == tokenize.ENDMARKER and nest_count:
+ raise TemplateError('Invalid signature: (%s)' % sig_text,
+ position=pos, name=name)
+ if (not nest_count and
+ (tok_type == tokenize.ENDMARKER or
+ (tok_type == tokenize.OP and tok_string == ','))):
+ default_expr = isolate_expression(
+ sig_text, start_pos, end_pos)
+ defaults[var_name] = default_expr
+ sig_args.append(var_name)
+ break
+ parts.append((tok_type, tok_string))
+ if nest_count \
+ and tok_type == tokenize.OP \
+ and tok_string == nest_type:
+ nest_count += 1
+ elif nest_count \
+ and tok_type == tokenize.OP \
+ and tok_string == unnest_type:
+ nest_count -= 1
+ if not nest_count:
+ nest_type = unnest_type = None
+ elif not nest_count \
+ and tok_type == tokenize.OP \
+ and tok_string in ('(', '[', '{'):
+ nest_type = tok_string
+ nest_count = 1
+ unnest_type = {'(': ')', '[': ']', '{': '}'}[nest_type]
+ return sig_args, var_arg, var_kw, defaults
+
+
+def isolate_expression(string, start_pos, end_pos):
+ srow, scol = start_pos
+ srow -= 1
+ erow, ecol = end_pos
+ erow -= 1
+ lines = string.splitlines(True)
+ if srow == erow:
+ return lines[srow][scol:ecol]
+ parts = [lines[srow][scol:]]
+ parts.extend(lines[srow + 1:erow])
+ if erow < len(lines):
+ # It'll sometimes give (end_row_past_finish, 0)
+ parts.append(lines[erow][:ecol])
+ return ''.join(parts)
+
+_fill_command_usage = """\
+%prog [OPTIONS] TEMPLATE arg=value
+
+Use py:arg=value to set a Python value; otherwise all values are
+strings.
+"""
+
+
+def fill_command(args=None):
+ import sys
+ import optparse
+ import pkg_resources
+ import os
+ if args is None:
+ args = sys.argv[1:]
+ dist = pkg_resources.get_distribution('Paste')
+ parser = optparse.OptionParser(
+ version=coerce_text(dist),
+ usage=_fill_command_usage)
+ parser.add_option(
+ '-o', '--output',
+ dest='output',
+ metavar="FILENAME",
+ help="File to write output to (default stdout)")
+ parser.add_option(
+ '--html',
+ dest='use_html',
+ action='store_true',
+ help="Use HTML style filling (including automatic HTML quoting)")
+ parser.add_option(
+ '--env',
+ dest='use_env',
+ action='store_true',
+ help="Put the environment in as top-level variables")
+ options, args = parser.parse_args(args)
+ if len(args) < 1:
+ print('You must give a template filename')
+ sys.exit(2)
+ template_name = args[0]
+ args = args[1:]
+ vars = {}
+ if options.use_env:
+ vars.update(os.environ)
+ for value in args:
+ if '=' not in value:
+ print('Bad argument: %r' % value)
+ sys.exit(2)
+ name, value = value.split('=', 1)
+ if name.startswith('py:'):
+ name = name[:3]
+ value = eval(value)
+ vars[name] = value
+ if template_name == '-':
+ template_content = sys.stdin.read()
+ template_name = ''
+ else:
+ f = open(template_name, 'rb', encoding="latin-1")
+ template_content = f.read()
+ f.close()
+ if options.use_html:
+ TemplateClass = HTMLTemplate
+ else:
+ TemplateClass = Template
+ template = TemplateClass(template_content, name=template_name)
+ result = template.substitute(vars)
+ if options.output:
+ f = open(options.output, 'wb')
+ f.write(result)
+ f.close()
+ else:
+ sys.stdout.write(result)
+
+if __name__ == '__main__':
+ fill_command()
diff --git a/nilearn/externals/tempita/_looper.py b/nilearn/externals/tempita/_looper.py
new file mode 100644
index 0000000000..a2a67800d8
--- /dev/null
+++ b/nilearn/externals/tempita/_looper.py
@@ -0,0 +1,163 @@
+"""
+Helper for looping over sequences, particular in templates.
+
+Often in a loop in a template it's handy to know what's next up,
+previously up, if this is the first or last item in the sequence, etc.
+These can be awkward to manage in a normal Python loop, but using the
+looper you can get a better sense of the context. Use like::
+
+ >>> for loop, item in looper(['a', 'b', 'c']):
+ ... print(loop.number, item)
+ ... if not loop.last:
+ ... print('---')
+ 1 a
+ ---
+ 2 b
+ ---
+ 3 c
+
+"""
+from __future__ import absolute_import, division, print_function
+
+import sys
+from .compat3 import basestring_
+
+__all__ = ['looper']
+
+
+class looper(object):
+ """
+ Helper for looping (particularly in templates)
+
+ Use this like::
+
+ for loop, item in looper(seq):
+ if loop.first:
+ ...
+ """
+
+ def __init__(self, seq):
+ self.seq = seq
+
+ def __iter__(self):
+ return looper_iter(self.seq)
+
+ def __repr__(self):
+ return '<%s for %r>' % (
+ self.__class__.__name__, self.seq)
+
+
+class looper_iter(object):
+
+ def __init__(self, seq):
+ self.seq = list(seq)
+ self.pos = 0
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ if self.pos >= len(self.seq):
+ raise StopIteration
+ result = loop_pos(self.seq, self.pos), self.seq[self.pos]
+ self.pos += 1
+ return result
+
+ if sys.version < "3":
+ next = __next__
+
+
+class loop_pos(object):
+
+ def __init__(self, seq, pos):
+ self.seq = seq
+ self.pos = pos
+
+ def __repr__(self):
+ return '' % (
+ self.seq[self.pos], self.pos)
+
+ def index(self):
+ return self.pos
+ index = property(index)
+
+ def number(self):
+ return self.pos + 1
+ number = property(number)
+
+ def item(self):
+ return self.seq[self.pos]
+ item = property(item)
+
+ def __next__(self):
+ try:
+ return self.seq[self.pos + 1]
+ except IndexError:
+ return None
+ __next__ = property(__next__)
+
+ if sys.version < "3":
+ next = __next__
+
+ def previous(self):
+ if self.pos == 0:
+ return None
+ return self.seq[self.pos - 1]
+ previous = property(previous)
+
+ def odd(self):
+ return not self.pos % 2
+ odd = property(odd)
+
+ def even(self):
+ return self.pos % 2
+ even = property(even)
+
+ def first(self):
+ return self.pos == 0
+ first = property(first)
+
+ def last(self):
+ return self.pos == len(self.seq) - 1
+ last = property(last)
+
+ def length(self):
+ return len(self.seq)
+ length = property(length)
+
+ def first_group(self, getter=None):
+ """
+ Returns true if this item is the start of a new group,
+ where groups mean that some attribute has changed. The getter
+ can be None (the item itself changes), an attribute name like
+ ``'.attr'``, a function, or a dict key or list index.
+ """
+ if self.first:
+ return True
+ return self._compare_group(self.item, self.previous, getter)
+
+ def last_group(self, getter=None):
+ """
+ Returns true if this item is the end of a new group,
+ where groups mean that some attribute has changed. The getter
+ can be None (the item itself changes), an attribute name like
+ ``'.attr'``, a function, or a dict key or list index.
+ """
+ if self.last:
+ return True
+ return self._compare_group(self.item, self.__next__, getter)
+
+ def _compare_group(self, item, other, getter):
+ if getter is None:
+ return item != other
+ elif (isinstance(getter, basestring_) and getter.startswith('.')):
+ getter = getter[1:]
+ if getter.endswith('()'):
+ getter = getter[:-2]
+ return getattr(item, getter)() != getattr(other, getter)()
+ else:
+ return getattr(item, getter) != getattr(other, getter)
+ elif hasattr(getter, '__call__'):
+ return getter(item) != getter(other)
+ else:
+ return item[getter] != other[getter]
diff --git a/nilearn/externals/tempita/compat3.py b/nilearn/externals/tempita/compat3.py
new file mode 100644
index 0000000000..861f5aaf1a
--- /dev/null
+++ b/nilearn/externals/tempita/compat3.py
@@ -0,0 +1,56 @@
+# flake8: noqa
+from __future__ import absolute_import, division, print_function
+
+import sys
+
+__all__ = ['PY3', 'b', 'basestring_', 'bytes', 'next', 'is_unicode',
+ 'iteritems']
+
+PY3 = True if sys.version_info[0] == 3 else False
+
+if sys.version_info[0] < 3:
+
+ def next(obj):
+ return obj.next()
+
+ def iteritems(d, **kw):
+ return d.iteritems(**kw)
+
+ b = bytes = str
+ basestring_ = basestring
+
+else:
+
+ def b(s):
+ if isinstance(s, str):
+ return s.encode('latin1')
+ return bytes(s)
+
+ def iteritems(d, **kw):
+ return iter(d.items(**kw))
+
+ next = next
+ basestring_ = (bytes, str)
+ bytes = bytes
+
+text = str
+
+
+def is_unicode(obj):
+ if sys.version_info[0] < 3:
+ return isinstance(obj, unicode)
+ else:
+ return isinstance(obj, str)
+
+
+def coerce_text(v):
+ if not isinstance(v, basestring_):
+ if sys.version_info[0] < 3:
+ attr = '__unicode__'
+ else:
+ attr = '__str__'
+ if hasattr(v, attr):
+ return unicode(v)
+ else:
+ return bytes(v)
+ return v
diff --git a/nilearn/image/image.py b/nilearn/image/image.py
index 0387ee1ea5..61623200df 100644
--- a/nilearn/image/image.py
+++ b/nilearn/image/image.py
@@ -14,7 +14,7 @@
from scipy.stats import scoreatpercentile
import copy
import nibabel
-from sklearn.externals.joblib import Parallel, delayed
+from nilearn._utils.compat import Parallel, delayed
from .. import signal
from .._utils import (check_niimg_4d, check_niimg_3d, check_niimg, as_ndarray,
@@ -172,8 +172,8 @@ def _smooth_array(arr, affine, fwhm=None, ensure_finite=True, copy=True):
filtering.
copy: bool
- if True, input array is not modified. False by default: the filtering
- is performed in-place.
+ if True, input array is not modified. True by default: the filtering
+ is not performed in-place.
Returns
-------
@@ -705,7 +705,7 @@ def new_img_like(ref_niimg, data, affine=None, copy_header=False):
return klass(data, affine, header=header)
-def threshold_img(img, threshold, mask_img=None):
+def threshold_img(img, threshold, mask_img=None, copy=True):
""" Threshold the given input image, mostly statistical or atlas images.
Thresholding can be done based on direct image intensities or selection
@@ -732,6 +732,10 @@ def threshold_img(img, threshold, mask_img=None):
Mask image applied to mask the input data.
If None, no masking will be applied.
+ copy: bool
+ if True, input array is not modified. True by default: the filtering
+ is not performed in-place.
+
Returns
-------
threshold_img: Nifti1Image
@@ -742,6 +746,8 @@ def threshold_img(img, threshold, mask_img=None):
img = check_niimg(img)
img_data = _safe_get_data(img, ensure_finite=True)
+ if copy:
+ img_data = img_data.copy()
affine = img.affine
if mask_img is not None:
diff --git a/nilearn/image/tests/test_image.py b/nilearn/image/tests/test_image.py
index 92232c75e2..fe78003965 100644
--- a/nilearn/image/tests/test_image.py
+++ b/nilearn/image/tests/test_image.py
@@ -499,6 +499,27 @@ def test_threshold_img():
# when threshold is a percentile
thr_maps_percent2 = threshold_img(img, threshold='2%')
+def test_threshold_img_copy():
+
+ img_zeros = Nifti1Image(np.zeros((10, 10, 10, 10)), np.eye(4))
+ img_ones = Nifti1Image(np.ones((10, 10, 10, 10)), np.eye(4))
+
+ # Check that copy does not mutate. It returns modified copy.
+ thresholded = threshold_img(img_ones, 2) # threshold 2 > 1
+
+ # Original img_ones should have all ones.
+ assert_array_equal(img_ones.get_data(), np.ones((10, 10, 10, 10)))
+ # Thresholded should have all zeros.
+ assert_array_equal(thresholded.get_data(), np.zeros((10, 10, 10, 10)))
+
+ # Check that not copying does mutate.
+ img_to_mutate = Nifti1Image(np.ones((10, 10, 10, 10)), np.eye(4))
+ thresholded = threshold_img(img_to_mutate, 2, copy=False)
+ # Check that original mutates
+ assert_array_equal(img_to_mutate.get_data(), np.zeros((10, 10, 10, 10)))
+ # And that returned value is also thresholded.
+ assert_array_equal(img_to_mutate.get_data(), thresholded.get_data())
+
def test_isnan_threshold_img_data():
shape = (10, 10, 10)
diff --git a/nilearn/input_data/base_masker.py b/nilearn/input_data/base_masker.py
index f90b54785f..af604b581e 100644
--- a/nilearn/input_data/base_masker.py
+++ b/nilearn/input_data/base_masker.py
@@ -10,7 +10,7 @@
import numpy as np
from sklearn.base import BaseEstimator, TransformerMixin
-from sklearn.externals.joblib import Memory
+from nilearn._utils.compat import Memory
from .. import masking
from .. import image
diff --git a/nilearn/input_data/multi_nifti_masker.py b/nilearn/input_data/multi_nifti_masker.py
index f0f5737684..b70f44297e 100644
--- a/nilearn/input_data/multi_nifti_masker.py
+++ b/nilearn/input_data/multi_nifti_masker.py
@@ -8,7 +8,7 @@
import itertools
import warnings
-from sklearn.externals.joblib import Memory, Parallel, delayed
+from nilearn._utils.compat import Memory, Parallel, delayed
from .. import _utils
from .. import image
@@ -36,12 +36,18 @@ class MultiNiftiMasker(NiftiMasker, CacheMixin):
fine tune the mask extraction.
smoothing_fwhm: float, optional
- If smoothing_fwhm is not None, it gives the size in millimeters of the
- spatial smoothing to apply to the signal.
-
- standardize: boolean, optional
- If standardize is True, the time-series are centered and normed:
- their mean is put to 0 and their variance to 1 in the time dimension.
+ If smoothing_fwhm is not None, it gives the size in millimeters of
+ the spatial smoothing to apply to the signal.
+
+ standardize: {'zscore', 'psc', True, False}, default is 'zscore'
+ Strategy to standardize the signal.
+ 'zscore': the signal is z-scored. Timeseries are shifted
+ to zero mean and scaled to unit variance.
+ 'psc': Timeseries are shifted to zero mean value and scaled
+ to percent signal change (as compared to original mean signal).
+ True : the signal is z-scored. Timeseries are shifted
+ to zero mean and scaled to unit variance.
+ False : Do not standardize the data.
detrend: boolean, optional
This parameter is passed to signal.clean. Please see the related
@@ -121,13 +127,11 @@ class MultiNiftiMasker(NiftiMasker, CacheMixin):
"""
def __init__(self, mask_img=None, smoothing_fwhm=None,
- standardize=False, detrend=False,
- low_pass=None, high_pass=None, t_r=None,
- target_affine=None, target_shape=None,
- mask_strategy='background', mask_args=None, dtype=None,
- memory=Memory(cachedir=None), memory_level=0,
- n_jobs=1, verbose=0
- ):
+ standardize=False, detrend=False, low_pass=None,
+ high_pass=None, t_r=None, target_affine=None,
+ target_shape=None, mask_strategy='background',
+ mask_args=None, dtype=None, memory=Memory(cachedir=None),
+ memory_level=0, n_jobs=1, verbose=0):
# Mask is provided or computed
self.mask_img = mask_img
diff --git a/nilearn/input_data/nifti_labels_masker.py b/nilearn/input_data/nifti_labels_masker.py
index f4e6dca9ea..22223e6b52 100644
--- a/nilearn/input_data/nifti_labels_masker.py
+++ b/nilearn/input_data/nifti_labels_masker.py
@@ -4,7 +4,7 @@
import numpy as np
-from sklearn.externals.joblib import Memory
+from nilearn._utils.compat import Memory
from .. import _utils
from .._utils import logger, CacheMixin, _compose_err_msg
@@ -56,9 +56,15 @@ class NiftiLabelsMasker(BaseMasker, CacheMixin):
If smoothing_fwhm is not None, it gives the full-width half maximum in
millimeters of the spatial smoothing to apply to the signal.
- standardize: boolean, optional
- If standardize is True, the time-series are centered and normed:
- their mean is put to 0 and their variance to 1 in the time dimension.
+ standardize: {'zscore', 'psc', True, False}, default is 'zscore'
+ Strategy to standardize the signal.
+ 'zscore': the signal is z-scored. Timeseries are shifted
+ to zero mean and scaled to unit variance.
+ 'psc': Timeseries are shifted to zero mean value and scaled
+ to percent signal change (as compared to original mean signal).
+ True : the signal is z-scored. Timeseries are shifted
+ to zero mean and scaled to unit variance.
+ False : Do not standardize the data.
detrend: boolean, optional
This parameter is passed to signal.clean. Please see the related
diff --git a/nilearn/input_data/nifti_maps_masker.py b/nilearn/input_data/nifti_maps_masker.py
index 0cb57567f9..c9ff8525ab 100644
--- a/nilearn/input_data/nifti_maps_masker.py
+++ b/nilearn/input_data/nifti_maps_masker.py
@@ -3,7 +3,7 @@
"""
import numpy as np
-from sklearn.externals.joblib import Memory
+from nilearn._utils.compat import Memory
from .. import _utils
from .._utils import logger, CacheMixin
@@ -22,11 +22,11 @@ def __init__(self, _resampled_maps_img_, _resampled_mask_img_):
self._resampled_mask_img_ = _resampled_mask_img_
def __call__(self, imgs):
- from ..regions import signal_extraction
+ from ..regions import signal_extraction
- return signal_extraction.img_to_signals_maps(
- imgs, self._resampled_maps_img_,
- mask_img=self._resampled_mask_img_)
+ return signal_extraction.img_to_signals_maps(
+ imgs, self._resampled_maps_img_,
+ mask_img=self._resampled_mask_img_)
class NiftiMapsMasker(BaseMasker, CacheMixin):
@@ -58,9 +58,15 @@ class NiftiMapsMasker(BaseMasker, CacheMixin):
If smoothing_fwhm is not None, it gives the full-width half maximum in
millimeters of the spatial smoothing to apply to the signal.
- standardize: boolean, optional
- If standardize is True, the time-series are centered and normed:
- their mean is put to 0 and their variance to 1 in the time dimension.
+ standardize: {'zscore', 'psc', True, False}, default is 'zscore'
+ Strategy to standardize the signal.
+ 'zscore': the signal is z-scored. Timeseries are shifted
+ to zero mean and scaled to unit variance.
+ 'psc': Timeseries are shifted to zero mean value and scaled
+ to percent signal change (as compared to original mean signal).
+ True : the signal is z-scored. Timeseries are shifted
+ to zero mean and scaled to unit variance.
+ False : Do not standardize the data.
detrend: boolean, optional
This parameter is passed to signal.clean. Please see the related
@@ -116,10 +122,9 @@ class NiftiMapsMasker(BaseMasker, CacheMixin):
# memory and memory_level are used by CacheMixin.
def __init__(self, maps_img, mask_img=None,
- allow_overlap=True,
- smoothing_fwhm=None, standardize=False, detrend=False,
- low_pass=None, high_pass=None, t_r=None, dtype=None,
- resampling_target="data",
+ allow_overlap=True, smoothing_fwhm=None, standardize=False,
+ detrend=False, low_pass=None, high_pass=None, t_r=None,
+ dtype=None, resampling_target="data",
memory=Memory(cachedir=None, verbose=0), memory_level=0,
verbose=0):
self.maps_img = maps_img
diff --git a/nilearn/input_data/nifti_masker.py b/nilearn/input_data/nifti_masker.py
index 9a752b7c89..cd1a29fa36 100644
--- a/nilearn/input_data/nifti_masker.py
+++ b/nilearn/input_data/nifti_masker.py
@@ -4,14 +4,16 @@
# Author: Gael Varoquaux, Alexandre Abraham
# License: simplified BSD
+import warnings
from copy import copy as copy_object
-from sklearn.externals.joblib import Memory
+from nilearn._utils.compat import Memory
from .base_masker import BaseMasker, filter_and_extract
from .. import _utils
from .. import image
from .. import masking
+from nilearn.reporting import ReportMixin
from .._utils import CacheMixin
from .._utils.class_inspect import get_params
from .._utils.niimg import img_data_dtype
@@ -63,7 +65,7 @@ def filter_and_mask(imgs, mask_img_, parameters,
return data
-class NiftiMasker(BaseMasker, CacheMixin):
+class NiftiMasker(BaseMasker, CacheMixin, ReportMixin):
"""Applying a mask to extract time-series from Niimg-like objects.
NiftiMasker is useful when preprocessing (detrending, standardization,
@@ -86,25 +88,31 @@ class NiftiMasker(BaseMasker, CacheMixin):
If smoothing_fwhm is not None, it gives the full-width half maximum in
millimeters of the spatial smoothing to apply to the signal.
- standardize : boolean, optional
- If standardize is True, the time-series are centered and normed:
- their mean is put to 0 and their variance to 1 in the time dimension.
+ standardize: {'zscore', 'psc', True, False}, default is 'zscore'
+ Strategy to standardize the signal.
+ 'zscore': the signal is z-scored. Timeseries are shifted
+ to zero mean and scaled to unit variance.
+ 'psc': Timeseries are shifted to zero mean value and scaled
+ to percent signal change (as compared to original mean signal).
+ True : the signal is z-scored. Timeseries are shifted
+ to zero mean and scaled to unit variance.
+ False : Do not standardize the data.
detrend : boolean, optional
This parameter is passed to signal.clean. Please see the related
- documentation for details
+ documentation for details: :func:`nilearn.signal.clean`.
low_pass: None or float, optional
This parameter is passed to signal.clean. Please see the related
- documentation for details
+ documentation for details: :func:`nilearn.signal.clean`.
high_pass: None or float, optional
This parameter is passed to signal.clean. Please see the related
- documentation for details
+ documentation for details: :func:`nilearn.signal.clean`.
t_r : float, optional
This parameter is passed to signal.clean. Please see the related
- documentation for details
+ documentation for details: :func:`nilearn.signal.clean`.
target_affine : 3x3 or 4x4 matrix, optional
This parameter is passed to image.resample_img. Please see the
@@ -178,7 +186,7 @@ def __init__(self, mask_img=None, sessions=None, smoothing_fwhm=None,
mask_strategy='background',
mask_args=None, sample_mask=None, dtype=None,
memory_level=1, memory=Memory(cachedir=None),
- verbose=0
+ verbose=0, reports=True,
):
# Mask is provided or computed
self.mask_img = mask_img
@@ -200,9 +208,78 @@ def __init__(self, mask_img=None, sessions=None, smoothing_fwhm=None,
self.memory = memory
self.memory_level = memory_level
self.verbose = verbose
+ self.reports = reports
+ self._report_description = ('This report shows the input Nifti '
+ 'image overlaid with the outlines of the '
+ 'mask (in green). We recommend to inspect '
+ 'the report for the overlap between the '
+ 'mask and its input image. ')
+ self._overlay_text = ('\n To see the input Nifti image before '
+ 'resampling, hover over the displayed image.')
self._shelving = False
+ def _reporting(self):
+ """
+ Returns
+ -------
+ displays : list
+ A list of all displays to be rendered.
+ """
+ try:
+ from nilearn import plotting
+ except ImportError:
+ with warnings.catch_warnings():
+ mpl_unavail_msg = ('Matplotlib is not imported! '
+ 'No reports will be generated.')
+ warnings.filterwarnings('always', message=mpl_unavail_msg)
+ warnings.warn(category=ImportWarning,
+ message=mpl_unavail_msg)
+ return [None]
+
+ img = self._reporting_data['images']
+ mask = self._reporting_data['mask']
+ if img is not None:
+ dim = image.load_img(img).shape
+ if len(dim) == 4:
+ # compute middle image from 4D series for plotting
+ img = image.index_img(img, dim[-1] // 2)
+ else: # images were not provided to fit
+ img = mask
+
+ # create display of retained input mask, image
+ # for visual comparison
+ init_display = plotting.plot_img(img,
+ black_bg=False,
+ cmap='CMRmap_r')
+ init_display.add_contours(mask, levels=[.5], colors='g',
+ linewidths=2.5)
+
+ if 'transform' not in self._reporting_data:
+ return [init_display]
+
+ else: # if resampling was performed
+ self._report_description = (self._report_description +
+ self._overlay_text)
+
+ # create display of resampled NiftiImage and mask
+ # assuming that resampl_img has same dim as img
+ resampl_img, resampl_mask = self._reporting_data['transform']
+ if resampl_img is not None:
+ if len(dim) == 4:
+ # compute middle image from 4D series for plotting
+ resampl_img = image.index_img(resampl_img, dim[-1] // 2)
+ else: # images were not provided to fit
+ resampl_img = resampl_mask
+
+ final_display = plotting.plot_img(resampl_img,
+ black_bg=False,
+ cmap='CMRmap_r')
+ final_display.add_contours(resampl_mask, levels=[.5],
+ colors='g', linewidths=2.5)
+
+ return [init_display, final_display]
+
def _check_fitted(self):
if not hasattr(self, 'mask_img_'):
raise ValueError('It seems that %s has not been fitted. '
@@ -248,6 +325,11 @@ def fit(self, imgs=None, y=None):
else:
self.mask_img_ = _utils.check_niimg_3d(self.mask_img)
+ if self.reports: # save inputs for reporting
+ self._reporting_data = {'images': imgs, 'mask': self.mask_img_}
+ else:
+ self._reporting_data = None
+
# If resampling is requested, resample also the mask
# Resampling: allows the user to change the affine, the shape or both
if self.verbose > 0:
@@ -257,14 +339,25 @@ def fit(self, imgs=None, y=None):
target_affine=self.target_affine,
target_shape=self.target_shape,
copy=False, interpolation='nearest')
- if self.target_affine is not None:
+ if self.target_affine is not None: # resample image to target affine
self.affine_ = self.target_affine
- else:
+ else: # resample image to mask affine
self.affine_ = self.mask_img_.affine
# Load data in memory
self.mask_img_.get_data()
if self.verbose > 10:
print("[%s.fit] Finished fit" % self.__class__.__name__)
+
+ if (self.target_shape is not None) or (self.target_affine is not None):
+ if self.reports:
+ if imgs is not None:
+ resampl_imgs = self._cache(image.resample_img)(
+ imgs, target_affine=self.affine_,
+ copy=False, interpolation='nearest')
+ else: # imgs not provided to fit
+ resampl_imgs = None
+ self._reporting_data['transform'] = [resampl_imgs, self.mask_img_]
+
return self
def transform_single_imgs(self, imgs, confounds=None, copy=True):
@@ -279,7 +372,7 @@ def transform_single_imgs(self, imgs, confounds=None, copy=True):
confounds: CSV file or array-like, optional
This parameter is passed to signal.clean. Please see the related
- documentation for details.
+ documentation for details: :func:`nilearn.signal.clean`.
shape: (number of scans, number of confounds)
Returns
diff --git a/nilearn/input_data/nifti_spheres_masker.py b/nilearn/input_data/nifti_spheres_masker.py
index fc7e829d58..9eb8aef701 100644
--- a/nilearn/input_data/nifti_spheres_masker.py
+++ b/nilearn/input_data/nifti_spheres_masker.py
@@ -7,7 +7,7 @@
import numpy as np
import warnings
from sklearn import neighbors
-from sklearn.externals.joblib import Memory
+from nilearn._utils.compat import Memory
from ..image.resampling import coord_transform
from .._utils.niimg_conversions import _safe_get_data
@@ -167,9 +167,15 @@ class NiftiSpheresMasker(BaseMasker, CacheMixin):
If smoothing_fwhm is not None, it gives the full-width half maximum in
millimeters of the spatial smoothing to apply to the signal.
- standardize: boolean, optional
- If standardize is True, the time-series are centered and normed:
- their mean is set to 0 and their variance to 1 in the time dimension.
+ standardize: {'zscore', 'psc', True, False}, default is 'zscore'
+ Strategy to standardize the signal.
+ 'zscore': the signal is z-scored. Timeseries are shifted
+ to zero mean and scaled to unit variance.
+ 'psc': Timeseries are shifted to zero mean value and scaled
+ to percent signal change (as compared to original mean signal).
+ True : the signal is z-scored. Timeseries are shifted
+ to zero mean and scaled to unit variance.
+ False : Do not standardize the data.
detrend: boolean, optional
This parameter is passed to signal.clean. Please see the related
diff --git a/nilearn/input_data/tests/test_base_masker.py b/nilearn/input_data/tests/test_base_masker.py
index 3903e9935b..967b6d03c2 100644
--- a/nilearn/input_data/tests/test_base_masker.py
+++ b/nilearn/input_data/tests/test_base_masker.py
@@ -37,7 +37,7 @@ def test_cropping_code_paths():
"low_pass": None,
"t_r": None,
"detrend": None,
- "standardize": None
+ "standardize": 'zscore',
}
# Now do the two maskings
diff --git a/nilearn/input_data/tests/test_masker_validation.py b/nilearn/input_data/tests/test_masker_validation.py
index 7972769919..4522d7edb3 100644
--- a/nilearn/input_data/tests/test_masker_validation.py
+++ b/nilearn/input_data/tests/test_masker_validation.py
@@ -3,7 +3,7 @@
import numpy as np
from sklearn.base import BaseEstimator
-from sklearn.externals.joblib import Memory
+from nilearn._utils.compat import Memory
from nilearn._utils.testing import assert_warns
from nilearn.input_data.masker_validation import check_embedded_nifti_masker
@@ -54,10 +54,10 @@ def test_check_embedded_nifti_masker():
if param_key not in ['memory', 'memory_level', 'n_jobs',
'verbose']:
assert_equal(getattr(masker, param_key),
- getattr(mask, param_key))
+ getattr(mask, param_key))
else:
assert_equal(getattr(masker, param_key),
- getattr(owner, param_key))
+ getattr(owner, param_key))
# Check use of mask as mask_img
shape = (6, 8, 10, 5)
diff --git a/nilearn/input_data/tests/test_multi_nifti_masker.py b/nilearn/input_data/tests/test_multi_nifti_masker.py
index 620864d10c..ef46fe0814 100644
--- a/nilearn/input_data/tests/test_multi_nifti_masker.py
+++ b/nilearn/input_data/tests/test_multi_nifti_masker.py
@@ -14,7 +14,7 @@
from nose import SkipTest
from nose.tools import assert_true, assert_false, assert_raises, assert_equal
from numpy.testing import assert_array_equal
-from sklearn.externals.joblib import Memory
+from nilearn._utils.compat import Memory
from nilearn._utils.exceptions import DimensionError
from nilearn._utils.testing import assert_raises_regex, write_tmp_imgs
@@ -116,7 +116,7 @@ def test_3d_images():
def test_joblib_cache():
- from sklearn.externals.joblib import hash
+ from nilearn._utils.compat import hash
# Dummy mask
mask = np.zeros((40, 40, 40))
mask[20, 20, 20] = 1
@@ -196,3 +196,37 @@ def test_dtype():
masked_img = masker.transform([[img]])
assert(masked_img[0].dtype == np.float32)
+
+
+def test_standardization():
+ data_shape = (9, 9, 5)
+ n_samples = 500
+
+ signals = np.random.randn(2, np.prod(data_shape), n_samples)
+ means = np.random.randn(2, np.prod(data_shape), 1) * 50 + 1000
+ signals += means
+
+ img1 = Nifti1Image(signals[0].reshape(data_shape + (n_samples,)),
+ np.eye(4))
+ img2 = Nifti1Image(signals[1].reshape(data_shape + (n_samples,)),
+ np.eye(4))
+
+ mask = Nifti1Image(np.ones(data_shape), np.eye(4))
+
+ # z-score
+ masker = MultiNiftiMasker(mask, standardize='zscore')
+ trans_signals = masker.fit_transform([img1, img2])
+
+ for ts in trans_signals:
+ np.testing.assert_almost_equal(ts.mean(0), 0)
+ np.testing.assert_almost_equal(ts.std(0), 1)
+
+ # psc
+ masker = MultiNiftiMasker(mask, standardize='psc')
+ trans_signals = masker.fit_transform([img1, img2])
+
+ for ts, s in zip(trans_signals, signals):
+ np.testing.assert_almost_equal(ts.mean(0), 0)
+ np.testing.assert_almost_equal(ts,
+ (s / s.mean(1)[:, np.newaxis] *
+ 100 - 100).T)
diff --git a/nilearn/input_data/tests/test_nifti_labels_masker.py b/nilearn/input_data/tests/test_nifti_labels_masker.py
index 18e7148e3b..fe936028a6 100644
--- a/nilearn/input_data/tests/test_nifti_labels_masker.py
+++ b/nilearn/input_data/tests/test_nifti_labels_masker.py
@@ -266,3 +266,38 @@ def test_nifti_labels_masker_resampling():
compressed_img2 = masker.inverse_transform(transformed2)
np.testing.assert_array_equal(compressed_img.get_data(),
compressed_img2.get_data())
+
+
+def test_standardization():
+ data_shape = (9, 9, 5)
+ n_samples = 500
+
+ signals = np.random.randn(np.prod(data_shape), n_samples)
+ means = np.random.randn(np.prod(data_shape), 1) * 50 + 1000
+ signals += means
+ img = nibabel.Nifti1Image(
+ signals.reshape(data_shape + (n_samples,)), np.eye(4)
+ )
+
+ labels = data_gen.generate_labeled_regions((9, 9, 5), 10)
+
+ # Unstandarized
+ masker = NiftiLabelsMasker(labels, standardize=False)
+ unstandarized_label_signals = masker.fit_transform(img)
+
+ # z-score
+ masker = NiftiLabelsMasker(labels, standardize='zscore')
+ trans_signals = masker.fit_transform(img)
+
+ np.testing.assert_almost_equal(trans_signals.mean(0), 0)
+ np.testing.assert_almost_equal(trans_signals.std(0), 1)
+
+ # psc
+ masker = NiftiLabelsMasker(labels, standardize='psc')
+ trans_signals = masker.fit_transform(img)
+
+ np.testing.assert_almost_equal(trans_signals.mean(0), 0)
+ np.testing.assert_almost_equal(trans_signals,
+ (unstandarized_label_signals /
+ unstandarized_label_signals.mean(0) *
+ 100 - 100))
diff --git a/nilearn/input_data/tests/test_nifti_maps_masker.py b/nilearn/input_data/tests/test_nifti_maps_masker.py
index 82c09b9b76..e931220999 100644
--- a/nilearn/input_data/tests/test_nifti_maps_masker.py
+++ b/nilearn/input_data/tests/test_nifti_maps_masker.py
@@ -298,3 +298,39 @@ def test_nifti_maps_masker_overlap():
allow_overlap=False)
assert_raises_regex(ValueError, 'Overlap detected',
non_overlapping_masker.fit_transform, fmri_img)
+
+
+def test_standardization():
+ data_shape = (9, 9, 5)
+ n_samples = 500
+
+ signals = np.random.randn(np.prod(data_shape), n_samples)
+ means = np.random.randn(np.prod(data_shape), 1) * 50 + 1000
+ signals += means
+ img = nibabel.Nifti1Image(signals.reshape(data_shape + (n_samples,)),
+ np.eye(4))
+
+ maps, _ = data_gen.generate_maps((9, 9, 5), 10)
+
+ # Unstandarized
+ masker = NiftiMapsMasker(maps, standardize=False)
+ unstandarized_label_signals = masker.fit_transform(img)
+
+ # z-score
+ masker = NiftiMapsMasker(maps,
+ standardize='zscore')
+ trans_signals = masker.fit_transform(img)
+
+ np.testing.assert_almost_equal(trans_signals.mean(0), 0)
+ np.testing.assert_almost_equal(trans_signals.std(0), 1)
+
+ # psc
+ masker = NiftiMapsMasker(maps, standardize='psc')
+ trans_signals = masker.fit_transform(img)
+
+ np.testing.assert_almost_equal(trans_signals.mean(0), 0)
+ np.testing.assert_almost_equal(
+ trans_signals,
+ unstandarized_label_signals /
+ unstandarized_label_signals.mean(0) * 100 - 100,
+ )
diff --git a/nilearn/input_data/tests/test_nifti_masker.py b/nilearn/input_data/tests/test_nifti_masker.py
index 4c857ff820..94eb09aa54 100644
--- a/nilearn/input_data/tests/test_nifti_masker.py
+++ b/nilearn/input_data/tests/test_nifti_masker.py
@@ -233,7 +233,7 @@ def test_sessions():
def test_joblib_cache():
- from sklearn.externals.joblib import hash, Memory
+ from nilearn._utils.compat import hash, Memory
mask = np.zeros((40, 40, 40))
mask[20, 20, 20] = 1
mask_img = Nifti1Image(mask, np.eye(4))
@@ -390,3 +390,31 @@ def test_dtype():
masker_2 = NiftiMasker(dtype='float64')
assert(masker_2.fit_transform(img_32).dtype == np.float64)
assert(masker_2.fit_transform(img_64).dtype == np.float64)
+
+
+def test_standardization():
+ data_shape = (9, 9, 5)
+ n_samples = 500
+
+ signals = np.random.randn(np.prod(data_shape), n_samples)
+ means = np.random.randn(np.prod(data_shape), 1) * 50 + 1000
+ signals += means
+ img = Nifti1Image(signals.reshape(data_shape + (n_samples,)), np.eye(4))
+
+ mask = Nifti1Image(np.ones(data_shape), np.eye(4))
+
+ # z-score
+ masker = NiftiMasker(mask, standardize='zscore')
+ trans_signals = masker.fit_transform(img)
+
+ np.testing.assert_almost_equal(trans_signals.mean(0), 0)
+ np.testing.assert_almost_equal(trans_signals.std(0), 1)
+
+ # psc
+ masker = NiftiMasker(mask, standardize='psc')
+ trans_signals = masker.fit_transform(img)
+
+ np.testing.assert_almost_equal(trans_signals.mean(0), 0)
+ np.testing.assert_almost_equal(trans_signals,
+ (signals / signals.mean(1)[:, np.newaxis] *
+ 100 - 100).T)
diff --git a/nilearn/input_data/tests/test_nifti_spheres_masker.py b/nilearn/input_data/tests/test_nifti_spheres_masker.py
index 21d1c2cef7..0df537ec1c 100644
--- a/nilearn/input_data/tests/test_nifti_spheres_masker.py
+++ b/nilearn/input_data/tests/test_nifti_spheres_masker.py
@@ -5,6 +5,7 @@
from nilearn._utils.testing import assert_raises_regex
from nose.tools import assert_false
+
def test_seed_extraction():
data = np.random.random((3, 3, 3, 5))
img = nibabel.Nifti1Image(data, np.eye(4))
@@ -62,6 +63,7 @@ def test_anisotropic_sphere_extraction():
affine_2[0, 0] = 4
mask_img = nibabel.Nifti1Image(mask_img, affine=affine_2)
masker = NiftiSpheresMasker([(2, 1, 2)], radius=1, mask_img=mask_img)
+
masker.fit()
s = masker.transform(img)
assert_array_equal(s[:, 0], data[1, 0, 1])
@@ -151,3 +153,26 @@ def test_is_nifti_spheres_masker_give_nans():
# When mask_img is provided, the seed interacts within the brain, so no nan
masker = NiftiSpheresMasker(seeds=seed, radius=2., mask_img=mask_img)
assert_false(np.isnan(np.sum(masker.fit_transform(img))))
+
+
+def test_standardization():
+ data = np.random.random((3, 3, 3, 5))
+ img = nibabel.Nifti1Image(data, np.eye(4))
+
+ # test zscore
+ masker = NiftiSpheresMasker([(1, 1, 1)], standardize='zscore')
+ # Test the fit
+ s = masker.fit_transform(img)
+
+ np.testing.assert_almost_equal(s.mean(), 0)
+ np.testing.assert_almost_equal(s.std(), 1)
+
+ # test psc
+ masker = NiftiSpheresMasker([(1, 1, 1)], standardize='psc')
+ # Test the fit
+ s = masker.fit_transform(img)
+
+ np.testing.assert_almost_equal(s.mean(), 0)
+ np.testing.assert_almost_equal(s.ravel(), data[1, 1, 1] /
+ data[1, 1, 1].mean() * 100 - 100,
+ )
diff --git a/nilearn/masking.py b/nilearn/masking.py
index 88d0453cff..6708151537 100644
--- a/nilearn/masking.py
+++ b/nilearn/masking.py
@@ -8,7 +8,7 @@
import numpy as np
from scipy import ndimage
-from sklearn.externals.joblib import Parallel, delayed
+from nilearn._utils.compat import Parallel, delayed
from . import _utils
from .image import new_img_like
diff --git a/nilearn/mass_univariate/permuted_least_squares.py b/nilearn/mass_univariate/permuted_least_squares.py
index bf4e616bf6..91d3dda2bf 100644
--- a/nilearn/mass_univariate/permuted_least_squares.py
+++ b/nilearn/mass_univariate/permuted_least_squares.py
@@ -8,7 +8,7 @@
import numpy as np
from scipy import linalg
from sklearn.utils import check_random_state
-import sklearn.externals.joblib as joblib
+from nilearn._utils.compat import joblib
def normalize_matrix_on_axis(m, axis=0):
@@ -34,11 +34,11 @@ def normalize_matrix_on_axis(m, axis=0):
... normalize_matrix_on_axis)
>>> X = np.array([[0, 4], [1, 0]])
>>> normalize_matrix_on_axis(X)
- array([[ 0., 1.],
- [ 1., 0.]])
+ array([[0., 1.],
+ [1., 0.]])
>>> normalize_matrix_on_axis(X, axis=1)
- array([[ 0., 1.],
- [ 1., 0.]])
+ array([[0., 1.],
+ [1., 0.]])
"""
if m.ndim > 2:
diff --git a/nilearn/plotting/__init__.py b/nilearn/plotting/__init__.py
index bfa0b879e0..a47a92d3e2 100644
--- a/nilearn/plotting/__init__.py
+++ b/nilearn/plotting/__init__.py
@@ -53,5 +53,5 @@ def _set_mpl_backend():
'show', 'plot_matrix', 'view_surf', 'view_img_on_surf',
'view_img', 'view_connectome', 'view_markers',
'find_parcellation_cut_coords', 'find_probabilistic_atlas_cut_coords',
- 'plot_surf', 'plot_surf_stat_map', 'plot_surf_roi',
+ 'plot_surf', 'plot_surf_stat_map', 'plot_surf_roi'
]
diff --git a/nilearn/plotting/cm.py b/nilearn/plotting/cm.py
index 1c989f4caa..9ee553e664 100644
--- a/nilearn/plotting/cm.py
+++ b/nilearn/plotting/cm.py
@@ -38,16 +38,16 @@ def _pigtailed_cmap(cmap, swap_order=('green', 'red', 'blue')):
orig_cdict = cmap._segmentdata.copy()
cdict = dict()
- cdict['green'] = [(0.5*(1-p), c1, c2)
- for (p, c1, c2) in reversed(orig_cdict[swap_order[0]])]
- cdict['blue'] = [(0.5*(1-p), c1, c2)
- for (p, c1, c2) in reversed(orig_cdict[swap_order[1]])]
- cdict['red'] = [(0.5*(1-p), c1, c2)
- for (p, c1, c2) in reversed(orig_cdict[swap_order[2]])]
+ cdict['green'] = [(0.5 * (1 - p), c1, c2)
+ for (p, c1, c2) in reversed(orig_cdict[swap_order[0]])]
+ cdict['blue'] = [(0.5 * (1 - p), c1, c2)
+ for (p, c1, c2) in reversed(orig_cdict[swap_order[1]])]
+ cdict['red'] = [(0.5 * (1 - p), c1, c2)
+ for (p, c1, c2) in reversed(orig_cdict[swap_order[2]])]
for color in ('red', 'green', 'blue'):
- cdict[color].extend([(0.5*(1+p), c1, c2)
- for (p, c1, c2) in orig_cdict[color]])
+ cdict[color].extend([(0.5 * (1 + p), c1, c2)
+ for (p, c1, c2) in orig_cdict[color]])
return cdict
@@ -149,19 +149,28 @@ def alpha_cmap(color, name='', alpha_min=0.5, alpha_max=1.):
_cmaps_data['bwr'] = _colors.LinearSegmentedColormap.from_list(
'bwr', _bwr_data)._segmentdata.copy()
+
################################################################################
# Build colormaps and their reverse.
+
+# backported and adapted from matplotlib since it's deprecated in 3.2
+def _revcmap(data):
+ data_r = {}
+ for key, val in data.items():
+ data_r[key] = [(1.0 - x, y1, y0) for x, y0, y1 in reversed(val)]
+ return data_r
+
+
_cmap_d = dict()
for _cmapname in list(_cmaps_data.keys()): # needed as dict changes within loop
_cmapname_r = _cmapname + '_r'
_cmapspec = _cmaps_data[_cmapname]
- _cmaps_data[_cmapname_r] = _cm.revcmap(_cmapspec)
+ _cmaps_data[_cmapname_r] = _revcmap(_cmapspec)
_cmap_d[_cmapname] = _colors.LinearSegmentedColormap(
- _cmapname, _cmapspec, _cm.LUTSIZE)
+ _cmapname, _cmapspec, _cm.LUTSIZE)
_cmap_d[_cmapname_r] = _colors.LinearSegmentedColormap(
- _cmapname_r, _cmaps_data[_cmapname_r],
- _cm.LUTSIZE)
+ _cmapname_r, _cmaps_data[_cmapname_r], _cm.LUTSIZE)
################################################################################
# A few transparent colormaps
@@ -212,13 +221,15 @@ def alpha_cmap(color, name='', alpha_min=0.5, alpha_max=1.):
def dim_cmap(cmap, factor=.3, to_white=True):
""" Dim a colormap to white, or to black.
"""
- assert factor >= 0 and factor <=1, ValueError(
- 'Dimming factor must be larger than 0 and smaller than 1, %s was passed.'
- % factor)
+ assert 0 <= factor <= 1, ValueError(
+ 'Dimming factor must be larger than 0 and smaller than 1, %s was '
+ 'passed.' % factor)
if to_white:
- dimmer = lambda c: 1 - factor*(1-c)
+ def dimmer(c):
+ return 1 - factor * (1 - c)
else:
- dimmer = lambda c: factor*c
+ def dimmer(c):
+ return factor * c
cdict = cmap._segmentdata.copy()
for c_index, color in enumerate(('red', 'green', 'blue')):
color_lst = list()
@@ -227,19 +238,17 @@ def dim_cmap(cmap, factor=.3, to_white=True):
cdict[color] = color_lst
return _colors.LinearSegmentedColormap(
- '%s_dimmed' % cmap.name,
- cdict,
- _cm.LUTSIZE)
+ '%s_dimmed' % cmap.name, cdict, _cm.LUTSIZE)
def replace_inside(outer_cmap, inner_cmap, vmin, vmax):
""" Replace a colormap by another inside a pair of values.
"""
assert vmin < vmax, ValueError('vmin must be smaller than vmax')
- assert vmin >= 0, ValueError('vmin must be larger than 0, %s was passed.'
- % vmin)
- assert vmax <= 1, ValueError('vmax must be smaller than 1, %s was passed.'
- % vmax)
+ assert vmin >= 0, ValueError('vmin must be larger than 0, %s was passed.'
+ % vmin)
+ assert vmax <= 1, ValueError('vmax must be smaller than 1, %s was passed.'
+ % vmax)
outer_cdict = outer_cmap._segmentdata.copy()
inner_cdict = inner_cmap._segmentdata.copy()
@@ -257,7 +266,6 @@ def replace_inside(outer_cmap, inner_cmap, vmin, vmax):
this_cdict['green'].append((p, g, g))
this_cdict['blue'].append((p, b, b))
-
for c_index, color in enumerate(('red', 'green', 'blue')):
color_lst = list()
@@ -266,8 +274,9 @@ def replace_inside(outer_cmap, inner_cmap, vmin, vmax):
break
color_lst.append((value, c1, c2))
- color_lst.append((vmin, outer_cmap(vmin)[c_index],
- inner_cmap(vmin)[c_index]))
+ color_lst.append((vmin,
+ outer_cmap(vmin)[c_index],
+ inner_cmap(vmin)[c_index]))
for value, c1, c2 in inner_cdict[color]:
if value <= vmin:
@@ -276,8 +285,9 @@ def replace_inside(outer_cmap, inner_cmap, vmin, vmax):
break
color_lst.append((value, c1, c2))
- color_lst.append((vmax, inner_cmap(vmax)[c_index],
- outer_cmap(vmax)[c_index]))
+ color_lst.append((vmax,
+ inner_cmap(vmax)[c_index],
+ outer_cmap(vmax)[c_index]))
for value, c1, c2 in outer_cdict[color]:
if value <= vmax:
@@ -287,8 +297,5 @@ def replace_inside(outer_cmap, inner_cmap, vmin, vmax):
cdict[color] = color_lst
return _colors.LinearSegmentedColormap(
- '%s_inside_%s' % (inner_cmap.name, outer_cmap.name),
- cdict,
- _cm.LUTSIZE)
-
-
+ '%s_inside_%s' % (inner_cmap.name, outer_cmap.name),
+ cdict, _cm.LUTSIZE)
diff --git a/nilearn/plotting/data/html/connectome_plot_template.html b/nilearn/plotting/data/html/connectome_plot_template.html
index 9fe2adfaca..11e592a173 100644
--- a/nilearn/plotting/data/html/connectome_plot_template.html
+++ b/nilearn/plotting/data/html/connectome_plot_template.html
@@ -25,6 +25,14 @@
data.push(info);
let layout = getLayout("connectome-plot", "select-view", false);
+
+ layout['title'] = {
+ text: connectomeInfo['connectome']['title'],
+ font: {size: connectomeInfo['connectome']["title_fontsize"],
+ color: textColor(connectomeInfo["black_bg"])},
+ yref: 'paper',
+ y: .9};
+
let config = getConfig();
Plotly.plot(divId, data, layout, config);
@@ -47,7 +55,8 @@
"select-view", false),
getConfig(),
connectomeInfo["connectome"]["cbar_fontsize"],
- connectomeInfo["connectome"]["cbar_height"]);
+ connectomeInfo["connectome"]["cbar_height"],
+ textColor(connectomeInfo["black_bg"]));
}
}
diff --git a/nilearn/plotting/data/html/surface_plot_template.html b/nilearn/plotting/data/html/surface_plot_template.html
index 9854b5a6d8..ba56e986fe 100644
--- a/nilearn/plotting/data/html/surface_plot_template.html
+++ b/nilearn/plotting/data/html/surface_plot_template.html
@@ -22,6 +22,12 @@
info['lighting'] = getLighting();
let layout = getLayout("surface-plot", "select-view",
surfaceMapInfo["black_bg"]);
+ layout['title'] = {
+ text: surfaceMapInfo['title'],
+ font: {size: surfaceMapInfo["title_fontsize"],
+ color: textColor(surfaceMapInfo["black_bg"])},
+ yref: 'paper',
+ y: .95};
let config = getConfig();
Plotly.react(divId, data, layout, config);
@@ -32,7 +38,8 @@
surfaceMapInfo["cmax"],
divId, layout, config,
surfaceMapInfo["cbar_fontsize"],
- surfaceMapInfo["cbar_height"]);
+ surfaceMapInfo["cbar_height"],
+ color=textColor(surfaceMapInfo["black_bg"]));
}
}
diff --git a/nilearn/plotting/data/js/plotly-gl3d-latest.min.js b/nilearn/plotting/data/js/plotly-gl3d-latest.min.js
index 2c2af6e989..2c8865bef8 100644
--- a/nilearn/plotting/data/js/plotly-gl3d-latest.min.js
+++ b/nilearn/plotting/data/js/plotly-gl3d-latest.min.js
@@ -1,7 +1,7 @@
/**
-* plotly.js (gl3d - minified) v1.38.3
-* Copyright 2012-2018, Plotly, Inc.
+* plotly.js (gl3d - minified) v1.46.1
+* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
* Licensed under the MIT license
*/
-!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Plotly=t()}}(function(){return function(){return function t(e,r,n){function i(o,s){if(!r[o]){if(!e[o]){var l="function"==typeof require&&require;if(!s&&l)return l(o,!0);if(a)return a(o,!0);var u=new Error("Cannot find module '"+o+"'");throw u.code="MODULE_NOT_FOUND",u}var c=r[o]={exports:{}};e[o][0].call(c.exports,function(t){var r=e[o][1][t];return i(r||t)},c,c.exports,t,e,r,n)}return r[o].exports}for(var a="function"==typeof require&&require,o=0;oMath.abs(e))u.rotate(o,0,0,-t*i*Math.PI*p.rotateSpeed/window.innerWidth);else{var s=p.zoomSpeed*a*e/window.innerHeight*(o-u.lastT())/100;u.pan(o,0,0,f*(Math.exp(s)-1))}},!0),p};var n=t("right-now"),i=t("3d-view"),a=t("mouse-change"),o=t("mouse-wheel"),s=t("mouse-event-offset"),l=t("has-passive-events")},{"3d-view":10,"has-passive-events":232,"mouse-change":250,"mouse-event-offset":251,"mouse-wheel":253,"right-now":295}],10:[function(t,e,r){"use strict";e.exports=function(t){var e=(t=t||{}).eye||[0,0,1],r=t.center||[0,0,0],s=t.up||[0,1,0],l=t.distanceLimits||[0,1/0],u=t.mode||"turntable",c=n(),f=i(),h=a();return c.setDistanceLimits(l[0],l[1]),c.lookAt(0,e,r,s),f.setDistanceLimits(l[0],l[1]),f.lookAt(0,e,r,s),h.setDistanceLimits(l[0],l[1]),h.lookAt(0,e,r,s),new o({turntable:c,orbit:f,matrix:h},u)};var n=t("turntable-camera-controller"),i=t("orbit-camera-controller"),a=t("matrix-camera-controller");function o(t,e){this._controllerNames=Object.keys(t),this._controllerList=this._controllerNames.map(function(e){return t[e]}),this._mode=e,this._active=t[e],this._active||(this._mode="turntable",this._active=t.turntable),this.modes=this._controllerNames,this.computedMatrix=this._active.computedMatrix,this.computedEye=this._active.computedEye,this.computedUp=this._active.computedUp,this.computedCenter=this._active.computedCenter,this.computedRadius=this._active.computedRadius}var s=o.prototype;[["flush",1],["idle",1],["lookAt",4],["rotate",4],["pan",4],["translate",4],["setMatrix",2],["setDistanceLimits",2],["setDistance",2]].forEach(function(t){for(var e=t[0],r=[],n=0;n0?l-4:l;var c=0;for(e=0;e>16&255,s[c++]=n>>8&255,s[c++]=255&n;2===o?(n=i[t.charCodeAt(e)]<<2|i[t.charCodeAt(e+1)]>>4,s[c++]=255&n):1===o&&(n=i[t.charCodeAt(e)]<<10|i[t.charCodeAt(e+1)]<<4|i[t.charCodeAt(e+2)]>>2,s[c++]=n>>8&255,s[c++]=255&n);return s},r.fromByteArray=function(t){for(var e,r=t.length,i=r%3,a="",o=[],s=0,l=r-i;sl?l:s+16383));1===i?(e=t[r-1],a+=n[e>>2],a+=n[e<<4&63],a+="=="):2===i&&(e=(t[r-2]<<8)+t[r-1],a+=n[e>>10],a+=n[e>>4&63],a+=n[e<<2&63],a+="=");return o.push(a),o.join("")};for(var n=[],i=[],a="undefined"!=typeof Uint8Array?Uint8Array:Array,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s=0,l=o.length;s0)throw new Error("Invalid string. Length must be a multiple of 4");return"="===t[e-2]?2:"="===t[e-1]?1:0}function c(t,e,r){for(var i,a,o=[],s=e;s>18&63]+n[a>>12&63]+n[a>>6&63]+n[63&a]);return o.join("")}i["-".charCodeAt(0)]=62,i["_".charCodeAt(0)]=63},{}],19:[function(t,e,r){"use strict";var n=t("./lib/rationalize");e.exports=function(t,e){return n(t[0].mul(e[1]).add(e[0].mul(t[1])),t[1].mul(e[1]))}},{"./lib/rationalize":29}],20:[function(t,e,r){"use strict";e.exports=function(t,e){return t[0].mul(e[1]).cmp(e[0].mul(t[1]))}},{}],21:[function(t,e,r){"use strict";var n=t("./lib/rationalize");e.exports=function(t,e){return n(t[0].mul(e[1]),t[1].mul(e[0]))}},{"./lib/rationalize":29}],22:[function(t,e,r){"use strict";var n=t("./is-rat"),i=t("./lib/is-bn"),a=t("./lib/num-to-bn"),o=t("./lib/str-to-bn"),s=t("./lib/rationalize"),l=t("./div");e.exports=function t(e,r){if(n(e))return r?l(e,t(r)):[e[0].clone(),e[1].clone()];var u=0;var c,f;if(i(e))c=e.clone();else if("string"==typeof e)c=o(e);else{if(0===e)return[a(0),a(1)];if(e===Math.floor(e))c=a(e);else{for(;e!==Math.floor(e);)e*=Math.pow(2,256),u-=256;c=a(e)}}if(n(r))c.mul(r[1]),f=r[0].clone();else if(i(r))f=r.clone();else if("string"==typeof r)f=o(r);else if(r)if(r===Math.floor(r))f=a(r);else{for(;r!==Math.floor(r);)r*=Math.pow(2,256),u+=256;f=a(r)}else f=a(1);u>0?c=c.ushln(u):u<0&&(f=f.ushln(-u));return s(c,f)}},{"./div":21,"./is-rat":23,"./lib/is-bn":27,"./lib/num-to-bn":28,"./lib/rationalize":29,"./lib/str-to-bn":30}],23:[function(t,e,r){"use strict";var n=t("./lib/is-bn");e.exports=function(t){return Array.isArray(t)&&2===t.length&&n(t[0])&&n(t[1])}},{"./lib/is-bn":27}],24:[function(t,e,r){"use strict";var n=t("bn.js");e.exports=function(t){return t.cmp(new n(0))}},{"bn.js":37}],25:[function(t,e,r){"use strict";var n=t("./bn-sign");e.exports=function(t){var e=t.length,r=t.words,i=0;if(1===e)i=r[0];else if(2===e)i=r[0]+67108864*r[1];else for(var a=0;a20)return 52;return r+32}},{"bit-twiddle":36,"double-bits":83}],27:[function(t,e,r){"use strict";t("bn.js");e.exports=function(t){return t&&"object"==typeof t&&Boolean(t.words)}},{"bn.js":37}],28:[function(t,e,r){"use strict";var n=t("bn.js"),i=t("double-bits");e.exports=function(t){var e=i.exponent(t);return e<52?new n(t):new n(t*Math.pow(2,52-e)).ushln(e-52)}},{"bn.js":37,"double-bits":83}],29:[function(t,e,r){"use strict";var n=t("./num-to-bn"),i=t("./bn-sign");e.exports=function(t,e){var r=i(t),a=i(e);if(0===r)return[n(0),n(1)];if(0===a)return[n(0),n(0)];a<0&&(t=t.neg(),e=e.neg());var o=t.gcd(e);if(o.cmpn(1))return[t.div(o),e.div(o)];return[t,e]}},{"./bn-sign":24,"./num-to-bn":28}],30:[function(t,e,r){"use strict";var n=t("bn.js");e.exports=function(t){return new n(t)}},{"bn.js":37}],31:[function(t,e,r){"use strict";var n=t("./lib/rationalize");e.exports=function(t,e){return n(t[0].mul(e[0]),t[1].mul(e[1]))}},{"./lib/rationalize":29}],32:[function(t,e,r){"use strict";var n=t("./lib/bn-sign");e.exports=function(t){return n(t[0])*n(t[1])}},{"./lib/bn-sign":24}],33:[function(t,e,r){"use strict";var n=t("./lib/rationalize");e.exports=function(t,e){return n(t[0].mul(e[1]).sub(t[1].mul(e[0])),t[1].mul(e[1]))}},{"./lib/rationalize":29}],34:[function(t,e,r){"use strict";var n=t("./lib/bn-to-num"),i=t("./lib/ctz");e.exports=function(t){var e=t[0],r=t[1];if(0===e.cmpn(0))return 0;var a=e.abs().divmod(r.abs()),o=a.div,s=n(o),l=a.mod,u=e.negative!==r.negative?-1:1;if(0===l.cmpn(0))return u*s;if(s){var c=i(s)+4,f=n(l.ushln(c).divRound(r));return u*(s+f*Math.pow(2,-c))}var h=r.bitLength()-l.bitLength()+53,f=n(l.ushln(h).divRound(r));return h<1023?u*f*Math.pow(2,-h):(f*=Math.pow(2,-1023),u*f*Math.pow(2,1023-h))}},{"./lib/bn-to-num":25,"./lib/ctz":26}],35:[function(t,e,r){"use strict";function n(t,e,r,n,i,a){var o=["function ",t,"(a,l,h,",n.join(","),"){",a?"":"var i=",r?"l-1":"h+1",";while(l<=h){var m=(l+h)>>>1,x=a",i?".get(m)":"[m]"];return a?e.indexOf("c")<0?o.push(";if(x===y){return m}else if(x<=y){"):o.push(";var p=c(x,y);if(p===0){return m}else if(p<=0){"):o.push(";if(",e,"){i=m;"),r?o.push("l=m+1}else{h=m-1}"):o.push("h=m-1}else{l=m+1}"),o.push("}"),a?o.push("return -1};"):o.push("return i};"),o.join("")}function i(t,e,r,i){return new Function([n("A","x"+t+"y",e,["y"],!1,i),n("B","x"+t+"y",e,["y"],!0,i),n("P","c(x,y)"+t+"0",e,["y","c"],!1,i),n("Q","c(x,y)"+t+"0",e,["y","c"],!0,i),"function dispatchBsearch",r,"(a,y,c,l,h){if(a.shape){if(typeof(c)==='function'){return Q(a,(l===undefined)?0:l|0,(h===undefined)?a.shape[0]-1:h|0,y,c)}else{return B(a,(c===undefined)?0:c|0,(l===undefined)?a.shape[0]-1:l|0,y)}}else{if(typeof(c)==='function'){return P(a,(l===undefined)?0:l|0,(h===undefined)?a.length-1:h|0,y,c)}else{return A(a,(c===undefined)?0:c|0,(l===undefined)?a.length-1:l|0,y)}}}return dispatchBsearch",r].join(""))()}e.exports={ge:i(">=",!1,"GE"),gt:i(">",!1,"GT"),lt:i("<",!0,"LT"),le:i("<=",!0,"LE"),eq:i("-",!0,"EQ",!0)}},{}],36:[function(t,e,r){"use strict";"use restrict";function n(t){var e=32;return(t&=-t)&&e--,65535&t&&(e-=16),16711935&t&&(e-=8),252645135&t&&(e-=4),858993459&t&&(e-=2),1431655765&t&&(e-=1),e}r.INT_BITS=32,r.INT_MAX=2147483647,r.INT_MIN=-1<<31,r.sign=function(t){return(t>0)-(t<0)},r.abs=function(t){var e=t>>31;return(t^e)-e},r.min=function(t,e){return e^(t^e)&-(t65535)<<4,e|=r=((t>>>=e)>255)<<3,e|=r=((t>>>=r)>15)<<2,(e|=r=((t>>>=r)>3)<<1)|(t>>>=r)>>1},r.log10=function(t){return t>=1e9?9:t>=1e8?8:t>=1e7?7:t>=1e6?6:t>=1e5?5:t>=1e4?4:t>=1e3?3:t>=100?2:t>=10?1:0},r.popCount=function(t){return 16843009*((t=(858993459&(t-=t>>>1&1431655765))+(t>>>2&858993459))+(t>>>4)&252645135)>>>24},r.countTrailingZeros=n,r.nextPow2=function(t){return t+=0===t,--t,t|=t>>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,(t|=t>>>16)+1},r.prevPow2=function(t){return t|=t>>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,(t|=t>>>16)-(t>>>1)},r.parity=function(t){return t^=t>>>16,t^=t>>>8,t^=t>>>4,27030>>>(t&=15)&1};var i=new Array(256);!function(t){for(var e=0;e<256;++e){var r=e,n=e,i=7;for(r>>>=1;r;r>>>=1)n<<=1,n|=1&r,--i;t[e]=n<>>8&255]<<16|i[t>>>16&255]<<8|i[t>>>24&255]},r.interleave2=function(t,e){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t&=65535)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e&=65535)|e<<8))|e<<4))|e<<2))|e<<1))<<1},r.deinterleave2=function(t,e){return(t=65535&((t=16711935&((t=252645135&((t=858993459&((t=t>>>e&1431655765)|t>>>1))|t>>>2))|t>>>4))|t>>>16))<<16>>16},r.interleave3=function(t,e,r){return t=1227133513&((t=3272356035&((t=251719695&((t=4278190335&((t&=1023)|t<<16))|t<<8))|t<<4))|t<<2),(t|=(e=1227133513&((e=3272356035&((e=251719695&((e=4278190335&((e&=1023)|e<<16))|e<<8))|e<<4))|e<<2))<<1)|(r=1227133513&((r=3272356035&((r=251719695&((r=4278190335&((r&=1023)|r<<16))|r<<8))|r<<4))|r<<2))<<2},r.deinterleave3=function(t,e){return(t=1023&((t=4278190335&((t=251719695&((t=3272356035&((t=t>>>e&1227133513)|t>>>2))|t>>>4))|t>>>8))|t>>>16))<<22>>22},r.nextCombination=function(t){var e=t|t-1;return e+1|(~e&-~e)-1>>>n(t)+1}},{}],37:[function(t,e,r){!function(e,r){"use strict";function n(t,e){if(!t)throw new Error(e||"Assertion failed")}function i(t,e){t.super_=e;var r=function(){};r.prototype=e.prototype,t.prototype=new r,t.prototype.constructor=t}function a(t,e,r){if(a.isBN(t))return t;this.negative=0,this.words=null,this.length=0,this.red=null,null!==t&&("le"!==e&&"be"!==e||(r=e,e=10),this._init(t||0,e||10,r||"be"))}var o;"object"==typeof e?e.exports=a:r.BN=a,a.BN=a,a.wordSize=26;try{o=t("buffer").Buffer}catch(t){}function s(t,e,r){for(var n=0,i=Math.min(t.length,r),a=e;a=49&&o<=54?o-49+10:o>=17&&o<=22?o-17+10:15&o}return n}function l(t,e,r,n){for(var i=0,a=Math.min(t.length,r),o=e;o=49?s-49+10:s>=17?s-17+10:s}return i}a.isBN=function(t){return t instanceof a||null!==t&&"object"==typeof t&&t.constructor.wordSize===a.wordSize&&Array.isArray(t.words)},a.max=function(t,e){return t.cmp(e)>0?t:e},a.min=function(t,e){return t.cmp(e)<0?t:e},a.prototype._init=function(t,e,r){if("number"==typeof t)return this._initNumber(t,e,r);if("object"==typeof t)return this._initArray(t,e,r);"hex"===e&&(e=16),n(e===(0|e)&&e>=2&&e<=36);var i=0;"-"===(t=t.toString().replace(/\s+/g,""))[0]&&i++,16===e?this._parseHex(t,i):this._parseBase(t,e,i),"-"===t[0]&&(this.negative=1),this.strip(),"le"===r&&this._initArray(this.toArray(),e,r)},a.prototype._initNumber=function(t,e,r){t<0&&(this.negative=1,t=-t),t<67108864?(this.words=[67108863&t],this.length=1):t<4503599627370496?(this.words=[67108863&t,t/67108864&67108863],this.length=2):(n(t<9007199254740992),this.words=[67108863&t,t/67108864&67108863,1],this.length=3),"le"===r&&this._initArray(this.toArray(),e,r)},a.prototype._initArray=function(t,e,r){if(n("number"==typeof t.length),t.length<=0)return this.words=[0],this.length=1,this;this.length=Math.ceil(t.length/3),this.words=new Array(this.length);for(var i=0;i=0;i-=3)o=t[i]|t[i-1]<<8|t[i-2]<<16,this.words[a]|=o<>>26-s&67108863,(s+=24)>=26&&(s-=26,a++);else if("le"===r)for(i=0,a=0;i>>26-s&67108863,(s+=24)>=26&&(s-=26,a++);return this.strip()},a.prototype._parseHex=function(t,e){this.length=Math.ceil((t.length-e)/6),this.words=new Array(this.length);for(var r=0;r=e;r-=6)i=s(t,r,r+6),this.words[n]|=i<>>26-a&4194303,(a+=24)>=26&&(a-=26,n++);r+6!==e&&(i=s(t,e,r+6),this.words[n]|=i<>>26-a&4194303),this.strip()},a.prototype._parseBase=function(t,e,r){this.words=[0],this.length=1;for(var n=0,i=1;i<=67108863;i*=e)n++;n--,i=i/e|0;for(var a=t.length-r,o=a%n,s=Math.min(a,a-o)+r,u=0,c=r;c1&&0===this.words[this.length-1];)this.length--;return this._normSign()},a.prototype._normSign=function(){return 1===this.length&&0===this.words[0]&&(this.negative=0),this},a.prototype.inspect=function(){return(this.red?""};var u=["","0","00","000","0000","00000","000000","0000000","00000000","000000000","0000000000","00000000000","000000000000","0000000000000","00000000000000","000000000000000","0000000000000000","00000000000000000","000000000000000000","0000000000000000000","00000000000000000000","000000000000000000000","0000000000000000000000","00000000000000000000000","000000000000000000000000","0000000000000000000000000"],c=[0,0,25,16,12,11,10,9,8,8,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],f=[0,0,33554432,43046721,16777216,48828125,60466176,40353607,16777216,43046721,1e7,19487171,35831808,62748517,7529536,11390625,16777216,24137569,34012224,47045881,64e6,4084101,5153632,6436343,7962624,9765625,11881376,14348907,17210368,20511149,243e5,28629151,33554432,39135393,45435424,52521875,60466176];function h(t,e,r){r.negative=e.negative^t.negative;var n=t.length+e.length|0;r.length=n,n=n-1|0;var i=0|t.words[0],a=0|e.words[0],o=i*a,s=67108863&o,l=o/67108864|0;r.words[0]=s;for(var u=1;u>>26,f=67108863&l,h=Math.min(u,e.length-1),d=Math.max(0,u-t.length+1);d<=h;d++){var p=u-d|0;c+=(o=(i=0|t.words[p])*(a=0|e.words[d])+f)/67108864|0,f=67108863&o}r.words[u]=0|f,l=0|c}return 0!==l?r.words[u]=0|l:r.length--,r.strip()}a.prototype.toString=function(t,e){var r;if(e=0|e||1,16===(t=t||10)||"hex"===t){r="";for(var i=0,a=0,o=0;o>>24-i&16777215)||o!==this.length-1?u[6-l.length]+l+r:l+r,(i+=2)>=26&&(i-=26,o--)}for(0!==a&&(r=a.toString(16)+r);r.length%e!=0;)r="0"+r;return 0!==this.negative&&(r="-"+r),r}if(t===(0|t)&&t>=2&&t<=36){var h=c[t],d=f[t];r="";var p=this.clone();for(p.negative=0;!p.isZero();){var g=p.modn(d).toString(t);r=(p=p.idivn(d)).isZero()?g+r:u[h-g.length]+g+r}for(this.isZero()&&(r="0"+r);r.length%e!=0;)r="0"+r;return 0!==this.negative&&(r="-"+r),r}n(!1,"Base should be between 2 and 36")},a.prototype.toNumber=function(){var t=this.words[0];return 2===this.length?t+=67108864*this.words[1]:3===this.length&&1===this.words[2]?t+=4503599627370496+67108864*this.words[1]:this.length>2&&n(!1,"Number can only safely store up to 53 bits"),0!==this.negative?-t:t},a.prototype.toJSON=function(){return this.toString(16)},a.prototype.toBuffer=function(t,e){return n(void 0!==o),this.toArrayLike(o,t,e)},a.prototype.toArray=function(t,e){return this.toArrayLike(Array,t,e)},a.prototype.toArrayLike=function(t,e,r){var i=this.byteLength(),a=r||Math.max(1,i);n(i<=a,"byte array longer than desired length"),n(a>0,"Requested array length <= 0"),this.strip();var o,s,l="le"===e,u=new t(a),c=this.clone();if(l){for(s=0;!c.isZero();s++)o=c.andln(255),c.iushrn(8),u[s]=o;for(;s=4096&&(r+=13,e>>>=13),e>=64&&(r+=7,e>>>=7),e>=8&&(r+=4,e>>>=4),e>=2&&(r+=2,e>>>=2),r+e},a.prototype._zeroBits=function(t){if(0===t)return 26;var e=t,r=0;return 0==(8191&e)&&(r+=13,e>>>=13),0==(127&e)&&(r+=7,e>>>=7),0==(15&e)&&(r+=4,e>>>=4),0==(3&e)&&(r+=2,e>>>=2),0==(1&e)&&r++,r},a.prototype.bitLength=function(){var t=this.words[this.length-1],e=this._countBits(t);return 26*(this.length-1)+e},a.prototype.zeroBits=function(){if(this.isZero())return 0;for(var t=0,e=0;et.length?this.clone().ior(t):t.clone().ior(this)},a.prototype.uor=function(t){return this.length>t.length?this.clone().iuor(t):t.clone().iuor(this)},a.prototype.iuand=function(t){var e;e=this.length>t.length?t:this;for(var r=0;rt.length?this.clone().iand(t):t.clone().iand(this)},a.prototype.uand=function(t){return this.length>t.length?this.clone().iuand(t):t.clone().iuand(this)},a.prototype.iuxor=function(t){var e,r;this.length>t.length?(e=this,r=t):(e=t,r=this);for(var n=0;nt.length?this.clone().ixor(t):t.clone().ixor(this)},a.prototype.uxor=function(t){return this.length>t.length?this.clone().iuxor(t):t.clone().iuxor(this)},a.prototype.inotn=function(t){n("number"==typeof t&&t>=0);var e=0|Math.ceil(t/26),r=t%26;this._expand(e),r>0&&e--;for(var i=0;i0&&(this.words[i]=~this.words[i]&67108863>>26-r),this.strip()},a.prototype.notn=function(t){return this.clone().inotn(t)},a.prototype.setn=function(t,e){n("number"==typeof t&&t>=0);var r=t/26|0,i=t%26;return this._expand(r+1),this.words[r]=e?this.words[r]|1<t.length?(r=this,n=t):(r=t,n=this);for(var i=0,a=0;a>>26;for(;0!==i&&a>>26;if(this.length=r.length,0!==i)this.words[this.length]=i,this.length++;else if(r!==this)for(;at.length?this.clone().iadd(t):t.clone().iadd(this)},a.prototype.isub=function(t){if(0!==t.negative){t.negative=0;var e=this.iadd(t);return t.negative=1,e._normSign()}if(0!==this.negative)return this.negative=0,this.iadd(t),this.negative=1,this._normSign();var r,n,i=this.cmp(t);if(0===i)return this.negative=0,this.length=1,this.words[0]=0,this;i>0?(r=this,n=t):(r=t,n=this);for(var a=0,o=0;o>26,this.words[o]=67108863&e;for(;0!==a&&o>26,this.words[o]=67108863&e;if(0===a&&o>>13,d=0|o[1],p=8191&d,g=d>>>13,v=0|o[2],m=8191&v,y=v>>>13,b=0|o[3],x=8191&b,_=b>>>13,w=0|o[4],M=8191&w,A=w>>>13,T=0|o[5],k=8191&T,E=T>>>13,S=0|o[6],L=8191&S,C=S>>>13,P=0|o[7],O=8191&P,R=P>>>13,I=0|o[8],N=8191&I,z=I>>>13,D=0|o[9],F=8191&D,j=D>>>13,B=0|s[0],U=8191&B,V=B>>>13,H=0|s[1],q=8191&H,G=H>>>13,X=0|s[2],W=8191&X,Y=X>>>13,Z=0|s[3],Q=8191&Z,J=Z>>>13,K=0|s[4],$=8191&K,tt=K>>>13,et=0|s[5],rt=8191&et,nt=et>>>13,it=0|s[6],at=8191&it,ot=it>>>13,st=0|s[7],lt=8191&st,ut=st>>>13,ct=0|s[8],ft=8191&ct,ht=ct>>>13,dt=0|s[9],pt=8191&dt,gt=dt>>>13;r.negative=t.negative^e.negative,r.length=19;var vt=(u+(n=Math.imul(f,U))|0)+((8191&(i=(i=Math.imul(f,V))+Math.imul(h,U)|0))<<13)|0;u=((a=Math.imul(h,V))+(i>>>13)|0)+(vt>>>26)|0,vt&=67108863,n=Math.imul(p,U),i=(i=Math.imul(p,V))+Math.imul(g,U)|0,a=Math.imul(g,V);var mt=(u+(n=n+Math.imul(f,q)|0)|0)+((8191&(i=(i=i+Math.imul(f,G)|0)+Math.imul(h,q)|0))<<13)|0;u=((a=a+Math.imul(h,G)|0)+(i>>>13)|0)+(mt>>>26)|0,mt&=67108863,n=Math.imul(m,U),i=(i=Math.imul(m,V))+Math.imul(y,U)|0,a=Math.imul(y,V),n=n+Math.imul(p,q)|0,i=(i=i+Math.imul(p,G)|0)+Math.imul(g,q)|0,a=a+Math.imul(g,G)|0;var yt=(u+(n=n+Math.imul(f,W)|0)|0)+((8191&(i=(i=i+Math.imul(f,Y)|0)+Math.imul(h,W)|0))<<13)|0;u=((a=a+Math.imul(h,Y)|0)+(i>>>13)|0)+(yt>>>26)|0,yt&=67108863,n=Math.imul(x,U),i=(i=Math.imul(x,V))+Math.imul(_,U)|0,a=Math.imul(_,V),n=n+Math.imul(m,q)|0,i=(i=i+Math.imul(m,G)|0)+Math.imul(y,q)|0,a=a+Math.imul(y,G)|0,n=n+Math.imul(p,W)|0,i=(i=i+Math.imul(p,Y)|0)+Math.imul(g,W)|0,a=a+Math.imul(g,Y)|0;var bt=(u+(n=n+Math.imul(f,Q)|0)|0)+((8191&(i=(i=i+Math.imul(f,J)|0)+Math.imul(h,Q)|0))<<13)|0;u=((a=a+Math.imul(h,J)|0)+(i>>>13)|0)+(bt>>>26)|0,bt&=67108863,n=Math.imul(M,U),i=(i=Math.imul(M,V))+Math.imul(A,U)|0,a=Math.imul(A,V),n=n+Math.imul(x,q)|0,i=(i=i+Math.imul(x,G)|0)+Math.imul(_,q)|0,a=a+Math.imul(_,G)|0,n=n+Math.imul(m,W)|0,i=(i=i+Math.imul(m,Y)|0)+Math.imul(y,W)|0,a=a+Math.imul(y,Y)|0,n=n+Math.imul(p,Q)|0,i=(i=i+Math.imul(p,J)|0)+Math.imul(g,Q)|0,a=a+Math.imul(g,J)|0;var xt=(u+(n=n+Math.imul(f,$)|0)|0)+((8191&(i=(i=i+Math.imul(f,tt)|0)+Math.imul(h,$)|0))<<13)|0;u=((a=a+Math.imul(h,tt)|0)+(i>>>13)|0)+(xt>>>26)|0,xt&=67108863,n=Math.imul(k,U),i=(i=Math.imul(k,V))+Math.imul(E,U)|0,a=Math.imul(E,V),n=n+Math.imul(M,q)|0,i=(i=i+Math.imul(M,G)|0)+Math.imul(A,q)|0,a=a+Math.imul(A,G)|0,n=n+Math.imul(x,W)|0,i=(i=i+Math.imul(x,Y)|0)+Math.imul(_,W)|0,a=a+Math.imul(_,Y)|0,n=n+Math.imul(m,Q)|0,i=(i=i+Math.imul(m,J)|0)+Math.imul(y,Q)|0,a=a+Math.imul(y,J)|0,n=n+Math.imul(p,$)|0,i=(i=i+Math.imul(p,tt)|0)+Math.imul(g,$)|0,a=a+Math.imul(g,tt)|0;var _t=(u+(n=n+Math.imul(f,rt)|0)|0)+((8191&(i=(i=i+Math.imul(f,nt)|0)+Math.imul(h,rt)|0))<<13)|0;u=((a=a+Math.imul(h,nt)|0)+(i>>>13)|0)+(_t>>>26)|0,_t&=67108863,n=Math.imul(L,U),i=(i=Math.imul(L,V))+Math.imul(C,U)|0,a=Math.imul(C,V),n=n+Math.imul(k,q)|0,i=(i=i+Math.imul(k,G)|0)+Math.imul(E,q)|0,a=a+Math.imul(E,G)|0,n=n+Math.imul(M,W)|0,i=(i=i+Math.imul(M,Y)|0)+Math.imul(A,W)|0,a=a+Math.imul(A,Y)|0,n=n+Math.imul(x,Q)|0,i=(i=i+Math.imul(x,J)|0)+Math.imul(_,Q)|0,a=a+Math.imul(_,J)|0,n=n+Math.imul(m,$)|0,i=(i=i+Math.imul(m,tt)|0)+Math.imul(y,$)|0,a=a+Math.imul(y,tt)|0,n=n+Math.imul(p,rt)|0,i=(i=i+Math.imul(p,nt)|0)+Math.imul(g,rt)|0,a=a+Math.imul(g,nt)|0;var wt=(u+(n=n+Math.imul(f,at)|0)|0)+((8191&(i=(i=i+Math.imul(f,ot)|0)+Math.imul(h,at)|0))<<13)|0;u=((a=a+Math.imul(h,ot)|0)+(i>>>13)|0)+(wt>>>26)|0,wt&=67108863,n=Math.imul(O,U),i=(i=Math.imul(O,V))+Math.imul(R,U)|0,a=Math.imul(R,V),n=n+Math.imul(L,q)|0,i=(i=i+Math.imul(L,G)|0)+Math.imul(C,q)|0,a=a+Math.imul(C,G)|0,n=n+Math.imul(k,W)|0,i=(i=i+Math.imul(k,Y)|0)+Math.imul(E,W)|0,a=a+Math.imul(E,Y)|0,n=n+Math.imul(M,Q)|0,i=(i=i+Math.imul(M,J)|0)+Math.imul(A,Q)|0,a=a+Math.imul(A,J)|0,n=n+Math.imul(x,$)|0,i=(i=i+Math.imul(x,tt)|0)+Math.imul(_,$)|0,a=a+Math.imul(_,tt)|0,n=n+Math.imul(m,rt)|0,i=(i=i+Math.imul(m,nt)|0)+Math.imul(y,rt)|0,a=a+Math.imul(y,nt)|0,n=n+Math.imul(p,at)|0,i=(i=i+Math.imul(p,ot)|0)+Math.imul(g,at)|0,a=a+Math.imul(g,ot)|0;var Mt=(u+(n=n+Math.imul(f,lt)|0)|0)+((8191&(i=(i=i+Math.imul(f,ut)|0)+Math.imul(h,lt)|0))<<13)|0;u=((a=a+Math.imul(h,ut)|0)+(i>>>13)|0)+(Mt>>>26)|0,Mt&=67108863,n=Math.imul(N,U),i=(i=Math.imul(N,V))+Math.imul(z,U)|0,a=Math.imul(z,V),n=n+Math.imul(O,q)|0,i=(i=i+Math.imul(O,G)|0)+Math.imul(R,q)|0,a=a+Math.imul(R,G)|0,n=n+Math.imul(L,W)|0,i=(i=i+Math.imul(L,Y)|0)+Math.imul(C,W)|0,a=a+Math.imul(C,Y)|0,n=n+Math.imul(k,Q)|0,i=(i=i+Math.imul(k,J)|0)+Math.imul(E,Q)|0,a=a+Math.imul(E,J)|0,n=n+Math.imul(M,$)|0,i=(i=i+Math.imul(M,tt)|0)+Math.imul(A,$)|0,a=a+Math.imul(A,tt)|0,n=n+Math.imul(x,rt)|0,i=(i=i+Math.imul(x,nt)|0)+Math.imul(_,rt)|0,a=a+Math.imul(_,nt)|0,n=n+Math.imul(m,at)|0,i=(i=i+Math.imul(m,ot)|0)+Math.imul(y,at)|0,a=a+Math.imul(y,ot)|0,n=n+Math.imul(p,lt)|0,i=(i=i+Math.imul(p,ut)|0)+Math.imul(g,lt)|0,a=a+Math.imul(g,ut)|0;var At=(u+(n=n+Math.imul(f,ft)|0)|0)+((8191&(i=(i=i+Math.imul(f,ht)|0)+Math.imul(h,ft)|0))<<13)|0;u=((a=a+Math.imul(h,ht)|0)+(i>>>13)|0)+(At>>>26)|0,At&=67108863,n=Math.imul(F,U),i=(i=Math.imul(F,V))+Math.imul(j,U)|0,a=Math.imul(j,V),n=n+Math.imul(N,q)|0,i=(i=i+Math.imul(N,G)|0)+Math.imul(z,q)|0,a=a+Math.imul(z,G)|0,n=n+Math.imul(O,W)|0,i=(i=i+Math.imul(O,Y)|0)+Math.imul(R,W)|0,a=a+Math.imul(R,Y)|0,n=n+Math.imul(L,Q)|0,i=(i=i+Math.imul(L,J)|0)+Math.imul(C,Q)|0,a=a+Math.imul(C,J)|0,n=n+Math.imul(k,$)|0,i=(i=i+Math.imul(k,tt)|0)+Math.imul(E,$)|0,a=a+Math.imul(E,tt)|0,n=n+Math.imul(M,rt)|0,i=(i=i+Math.imul(M,nt)|0)+Math.imul(A,rt)|0,a=a+Math.imul(A,nt)|0,n=n+Math.imul(x,at)|0,i=(i=i+Math.imul(x,ot)|0)+Math.imul(_,at)|0,a=a+Math.imul(_,ot)|0,n=n+Math.imul(m,lt)|0,i=(i=i+Math.imul(m,ut)|0)+Math.imul(y,lt)|0,a=a+Math.imul(y,ut)|0,n=n+Math.imul(p,ft)|0,i=(i=i+Math.imul(p,ht)|0)+Math.imul(g,ft)|0,a=a+Math.imul(g,ht)|0;var Tt=(u+(n=n+Math.imul(f,pt)|0)|0)+((8191&(i=(i=i+Math.imul(f,gt)|0)+Math.imul(h,pt)|0))<<13)|0;u=((a=a+Math.imul(h,gt)|0)+(i>>>13)|0)+(Tt>>>26)|0,Tt&=67108863,n=Math.imul(F,q),i=(i=Math.imul(F,G))+Math.imul(j,q)|0,a=Math.imul(j,G),n=n+Math.imul(N,W)|0,i=(i=i+Math.imul(N,Y)|0)+Math.imul(z,W)|0,a=a+Math.imul(z,Y)|0,n=n+Math.imul(O,Q)|0,i=(i=i+Math.imul(O,J)|0)+Math.imul(R,Q)|0,a=a+Math.imul(R,J)|0,n=n+Math.imul(L,$)|0,i=(i=i+Math.imul(L,tt)|0)+Math.imul(C,$)|0,a=a+Math.imul(C,tt)|0,n=n+Math.imul(k,rt)|0,i=(i=i+Math.imul(k,nt)|0)+Math.imul(E,rt)|0,a=a+Math.imul(E,nt)|0,n=n+Math.imul(M,at)|0,i=(i=i+Math.imul(M,ot)|0)+Math.imul(A,at)|0,a=a+Math.imul(A,ot)|0,n=n+Math.imul(x,lt)|0,i=(i=i+Math.imul(x,ut)|0)+Math.imul(_,lt)|0,a=a+Math.imul(_,ut)|0,n=n+Math.imul(m,ft)|0,i=(i=i+Math.imul(m,ht)|0)+Math.imul(y,ft)|0,a=a+Math.imul(y,ht)|0;var kt=(u+(n=n+Math.imul(p,pt)|0)|0)+((8191&(i=(i=i+Math.imul(p,gt)|0)+Math.imul(g,pt)|0))<<13)|0;u=((a=a+Math.imul(g,gt)|0)+(i>>>13)|0)+(kt>>>26)|0,kt&=67108863,n=Math.imul(F,W),i=(i=Math.imul(F,Y))+Math.imul(j,W)|0,a=Math.imul(j,Y),n=n+Math.imul(N,Q)|0,i=(i=i+Math.imul(N,J)|0)+Math.imul(z,Q)|0,a=a+Math.imul(z,J)|0,n=n+Math.imul(O,$)|0,i=(i=i+Math.imul(O,tt)|0)+Math.imul(R,$)|0,a=a+Math.imul(R,tt)|0,n=n+Math.imul(L,rt)|0,i=(i=i+Math.imul(L,nt)|0)+Math.imul(C,rt)|0,a=a+Math.imul(C,nt)|0,n=n+Math.imul(k,at)|0,i=(i=i+Math.imul(k,ot)|0)+Math.imul(E,at)|0,a=a+Math.imul(E,ot)|0,n=n+Math.imul(M,lt)|0,i=(i=i+Math.imul(M,ut)|0)+Math.imul(A,lt)|0,a=a+Math.imul(A,ut)|0,n=n+Math.imul(x,ft)|0,i=(i=i+Math.imul(x,ht)|0)+Math.imul(_,ft)|0,a=a+Math.imul(_,ht)|0;var Et=(u+(n=n+Math.imul(m,pt)|0)|0)+((8191&(i=(i=i+Math.imul(m,gt)|0)+Math.imul(y,pt)|0))<<13)|0;u=((a=a+Math.imul(y,gt)|0)+(i>>>13)|0)+(Et>>>26)|0,Et&=67108863,n=Math.imul(F,Q),i=(i=Math.imul(F,J))+Math.imul(j,Q)|0,a=Math.imul(j,J),n=n+Math.imul(N,$)|0,i=(i=i+Math.imul(N,tt)|0)+Math.imul(z,$)|0,a=a+Math.imul(z,tt)|0,n=n+Math.imul(O,rt)|0,i=(i=i+Math.imul(O,nt)|0)+Math.imul(R,rt)|0,a=a+Math.imul(R,nt)|0,n=n+Math.imul(L,at)|0,i=(i=i+Math.imul(L,ot)|0)+Math.imul(C,at)|0,a=a+Math.imul(C,ot)|0,n=n+Math.imul(k,lt)|0,i=(i=i+Math.imul(k,ut)|0)+Math.imul(E,lt)|0,a=a+Math.imul(E,ut)|0,n=n+Math.imul(M,ft)|0,i=(i=i+Math.imul(M,ht)|0)+Math.imul(A,ft)|0,a=a+Math.imul(A,ht)|0;var St=(u+(n=n+Math.imul(x,pt)|0)|0)+((8191&(i=(i=i+Math.imul(x,gt)|0)+Math.imul(_,pt)|0))<<13)|0;u=((a=a+Math.imul(_,gt)|0)+(i>>>13)|0)+(St>>>26)|0,St&=67108863,n=Math.imul(F,$),i=(i=Math.imul(F,tt))+Math.imul(j,$)|0,a=Math.imul(j,tt),n=n+Math.imul(N,rt)|0,i=(i=i+Math.imul(N,nt)|0)+Math.imul(z,rt)|0,a=a+Math.imul(z,nt)|0,n=n+Math.imul(O,at)|0,i=(i=i+Math.imul(O,ot)|0)+Math.imul(R,at)|0,a=a+Math.imul(R,ot)|0,n=n+Math.imul(L,lt)|0,i=(i=i+Math.imul(L,ut)|0)+Math.imul(C,lt)|0,a=a+Math.imul(C,ut)|0,n=n+Math.imul(k,ft)|0,i=(i=i+Math.imul(k,ht)|0)+Math.imul(E,ft)|0,a=a+Math.imul(E,ht)|0;var Lt=(u+(n=n+Math.imul(M,pt)|0)|0)+((8191&(i=(i=i+Math.imul(M,gt)|0)+Math.imul(A,pt)|0))<<13)|0;u=((a=a+Math.imul(A,gt)|0)+(i>>>13)|0)+(Lt>>>26)|0,Lt&=67108863,n=Math.imul(F,rt),i=(i=Math.imul(F,nt))+Math.imul(j,rt)|0,a=Math.imul(j,nt),n=n+Math.imul(N,at)|0,i=(i=i+Math.imul(N,ot)|0)+Math.imul(z,at)|0,a=a+Math.imul(z,ot)|0,n=n+Math.imul(O,lt)|0,i=(i=i+Math.imul(O,ut)|0)+Math.imul(R,lt)|0,a=a+Math.imul(R,ut)|0,n=n+Math.imul(L,ft)|0,i=(i=i+Math.imul(L,ht)|0)+Math.imul(C,ft)|0,a=a+Math.imul(C,ht)|0;var Ct=(u+(n=n+Math.imul(k,pt)|0)|0)+((8191&(i=(i=i+Math.imul(k,gt)|0)+Math.imul(E,pt)|0))<<13)|0;u=((a=a+Math.imul(E,gt)|0)+(i>>>13)|0)+(Ct>>>26)|0,Ct&=67108863,n=Math.imul(F,at),i=(i=Math.imul(F,ot))+Math.imul(j,at)|0,a=Math.imul(j,ot),n=n+Math.imul(N,lt)|0,i=(i=i+Math.imul(N,ut)|0)+Math.imul(z,lt)|0,a=a+Math.imul(z,ut)|0,n=n+Math.imul(O,ft)|0,i=(i=i+Math.imul(O,ht)|0)+Math.imul(R,ft)|0,a=a+Math.imul(R,ht)|0;var Pt=(u+(n=n+Math.imul(L,pt)|0)|0)+((8191&(i=(i=i+Math.imul(L,gt)|0)+Math.imul(C,pt)|0))<<13)|0;u=((a=a+Math.imul(C,gt)|0)+(i>>>13)|0)+(Pt>>>26)|0,Pt&=67108863,n=Math.imul(F,lt),i=(i=Math.imul(F,ut))+Math.imul(j,lt)|0,a=Math.imul(j,ut),n=n+Math.imul(N,ft)|0,i=(i=i+Math.imul(N,ht)|0)+Math.imul(z,ft)|0,a=a+Math.imul(z,ht)|0;var Ot=(u+(n=n+Math.imul(O,pt)|0)|0)+((8191&(i=(i=i+Math.imul(O,gt)|0)+Math.imul(R,pt)|0))<<13)|0;u=((a=a+Math.imul(R,gt)|0)+(i>>>13)|0)+(Ot>>>26)|0,Ot&=67108863,n=Math.imul(F,ft),i=(i=Math.imul(F,ht))+Math.imul(j,ft)|0,a=Math.imul(j,ht);var Rt=(u+(n=n+Math.imul(N,pt)|0)|0)+((8191&(i=(i=i+Math.imul(N,gt)|0)+Math.imul(z,pt)|0))<<13)|0;u=((a=a+Math.imul(z,gt)|0)+(i>>>13)|0)+(Rt>>>26)|0,Rt&=67108863;var It=(u+(n=Math.imul(F,pt))|0)+((8191&(i=(i=Math.imul(F,gt))+Math.imul(j,pt)|0))<<13)|0;return u=((a=Math.imul(j,gt))+(i>>>13)|0)+(It>>>26)|0,It&=67108863,l[0]=vt,l[1]=mt,l[2]=yt,l[3]=bt,l[4]=xt,l[5]=_t,l[6]=wt,l[7]=Mt,l[8]=At,l[9]=Tt,l[10]=kt,l[11]=Et,l[12]=St,l[13]=Lt,l[14]=Ct,l[15]=Pt,l[16]=Ot,l[17]=Rt,l[18]=It,0!==u&&(l[19]=u,r.length++),r};function p(t,e,r){return(new g).mulp(t,e,r)}function g(t,e){this.x=t,this.y=e}Math.imul||(d=h),a.prototype.mulTo=function(t,e){var r=this.length+t.length;return 10===this.length&&10===t.length?d(this,t,e):r<63?h(this,t,e):r<1024?function(t,e,r){r.negative=e.negative^t.negative,r.length=t.length+e.length;for(var n=0,i=0,a=0;a>>26)|0)>>>26,o&=67108863}r.words[a]=s,n=o,o=i}return 0!==n?r.words[a]=n:r.length--,r.strip()}(this,t,e):p(this,t,e)},g.prototype.makeRBT=function(t){for(var e=new Array(t),r=a.prototype._countBits(t)-1,n=0;n>=1;return n},g.prototype.permute=function(t,e,r,n,i,a){for(var o=0;o>>=1)i++;return 1<>>=13,r[2*o+1]=8191&a,a>>>=13;for(o=2*e;o>=26,e+=i/67108864|0,e+=a>>>26,this.words[r]=67108863&a}return 0!==e&&(this.words[r]=e,this.length++),this},a.prototype.muln=function(t){return this.clone().imuln(t)},a.prototype.sqr=function(){return this.mul(this)},a.prototype.isqr=function(){return this.imul(this.clone())},a.prototype.pow=function(t){var e=function(t){for(var e=new Array(t.bitLength()),r=0;r>>i}return e}(t);if(0===e.length)return new a(1);for(var r=this,n=0;n=0);var e,r=t%26,i=(t-r)/26,a=67108863>>>26-r<<26-r;if(0!==r){var o=0;for(e=0;e>>26-r}o&&(this.words[e]=o,this.length++)}if(0!==i){for(e=this.length-1;e>=0;e--)this.words[e+i]=this.words[e];for(e=0;e=0),i=e?(e-e%26)/26:0;var a=t%26,o=Math.min((t-a)/26,this.length),s=67108863^67108863>>>a<o)for(this.length-=o,u=0;u=0&&(0!==c||u>=i);u--){var f=0|this.words[u];this.words[u]=c<<26-a|f>>>a,c=f&s}return l&&0!==c&&(l.words[l.length++]=c),0===this.length&&(this.words[0]=0,this.length=1),this.strip()},a.prototype.ishrn=function(t,e,r){return n(0===this.negative),this.iushrn(t,e,r)},a.prototype.shln=function(t){return this.clone().ishln(t)},a.prototype.ushln=function(t){return this.clone().iushln(t)},a.prototype.shrn=function(t){return this.clone().ishrn(t)},a.prototype.ushrn=function(t){return this.clone().iushrn(t)},a.prototype.testn=function(t){n("number"==typeof t&&t>=0);var e=t%26,r=(t-e)/26,i=1<=0);var e=t%26,r=(t-e)/26;if(n(0===this.negative,"imaskn works only with positive numbers"),this.length<=r)return this;if(0!==e&&r++,this.length=Math.min(r,this.length),0!==e){var i=67108863^67108863>>>e<=67108864;e++)this.words[e]-=67108864,e===this.length-1?this.words[e+1]=1:this.words[e+1]++;return this.length=Math.max(this.length,e+1),this},a.prototype.isubn=function(t){if(n("number"==typeof t),n(t<67108864),t<0)return this.iaddn(-t);if(0!==this.negative)return this.negative=0,this.iaddn(t),this.negative=1,this;if(this.words[0]-=t,1===this.length&&this.words[0]<0)this.words[0]=-this.words[0],this.negative=1;else for(var e=0;e>26)-(l/67108864|0),this.words[i+r]=67108863&a}for(;i>26,this.words[i+r]=67108863&a;if(0===s)return this.strip();for(n(-1===s),s=0,i=0;i>26,this.words[i]=67108863&a;return this.negative=1,this.strip()},a.prototype._wordDiv=function(t,e){var r=(this.length,t.length),n=this.clone(),i=t,o=0|i.words[i.length-1];0!==(r=26-this._countBits(o))&&(i=i.ushln(r),n.iushln(r),o=0|i.words[i.length-1]);var s,l=n.length-i.length;if("mod"!==e){(s=new a(null)).length=l+1,s.words=new Array(s.length);for(var u=0;u=0;f--){var h=67108864*(0|n.words[i.length+f])+(0|n.words[i.length+f-1]);for(h=Math.min(h/o|0,67108863),n._ishlnsubmul(i,h,f);0!==n.negative;)h--,n.negative=0,n._ishlnsubmul(i,1,f),n.isZero()||(n.negative^=1);s&&(s.words[f]=h)}return s&&s.strip(),n.strip(),"div"!==e&&0!==r&&n.iushrn(r),{div:s||null,mod:n}},a.prototype.divmod=function(t,e,r){return n(!t.isZero()),this.isZero()?{div:new a(0),mod:new a(0)}:0!==this.negative&&0===t.negative?(s=this.neg().divmod(t,e),"mod"!==e&&(i=s.div.neg()),"div"!==e&&(o=s.mod.neg(),r&&0!==o.negative&&o.iadd(t)),{div:i,mod:o}):0===this.negative&&0!==t.negative?(s=this.divmod(t.neg(),e),"mod"!==e&&(i=s.div.neg()),{div:i,mod:s.mod}):0!=(this.negative&t.negative)?(s=this.neg().divmod(t.neg(),e),"div"!==e&&(o=s.mod.neg(),r&&0!==o.negative&&o.isub(t)),{div:s.div,mod:o}):t.length>this.length||this.cmp(t)<0?{div:new a(0),mod:this}:1===t.length?"div"===e?{div:this.divn(t.words[0]),mod:null}:"mod"===e?{div:null,mod:new a(this.modn(t.words[0]))}:{div:this.divn(t.words[0]),mod:new a(this.modn(t.words[0]))}:this._wordDiv(t,e);var i,o,s},a.prototype.div=function(t){return this.divmod(t,"div",!1).div},a.prototype.mod=function(t){return this.divmod(t,"mod",!1).mod},a.prototype.umod=function(t){return this.divmod(t,"mod",!0).mod},a.prototype.divRound=function(t){var e=this.divmod(t);if(e.mod.isZero())return e.div;var r=0!==e.div.negative?e.mod.isub(t):e.mod,n=t.ushrn(1),i=t.andln(1),a=r.cmp(n);return a<0||1===i&&0===a?e.div:0!==e.div.negative?e.div.isubn(1):e.div.iaddn(1)},a.prototype.modn=function(t){n(t<=67108863);for(var e=(1<<26)%t,r=0,i=this.length-1;i>=0;i--)r=(e*r+(0|this.words[i]))%t;return r},a.prototype.idivn=function(t){n(t<=67108863);for(var e=0,r=this.length-1;r>=0;r--){var i=(0|this.words[r])+67108864*e;this.words[r]=i/t|0,e=i%t}return this.strip()},a.prototype.divn=function(t){return this.clone().idivn(t)},a.prototype.egcd=function(t){n(0===t.negative),n(!t.isZero());var e=this,r=t.clone();e=0!==e.negative?e.umod(t):e.clone();for(var i=new a(1),o=new a(0),s=new a(0),l=new a(1),u=0;e.isEven()&&r.isEven();)e.iushrn(1),r.iushrn(1),++u;for(var c=r.clone(),f=e.clone();!e.isZero();){for(var h=0,d=1;0==(e.words[0]&d)&&h<26;++h,d<<=1);if(h>0)for(e.iushrn(h);h-- >0;)(i.isOdd()||o.isOdd())&&(i.iadd(c),o.isub(f)),i.iushrn(1),o.iushrn(1);for(var p=0,g=1;0==(r.words[0]&g)&&p<26;++p,g<<=1);if(p>0)for(r.iushrn(p);p-- >0;)(s.isOdd()||l.isOdd())&&(s.iadd(c),l.isub(f)),s.iushrn(1),l.iushrn(1);e.cmp(r)>=0?(e.isub(r),i.isub(s),o.isub(l)):(r.isub(e),s.isub(i),l.isub(o))}return{a:s,b:l,gcd:r.iushln(u)}},a.prototype._invmp=function(t){n(0===t.negative),n(!t.isZero());var e=this,r=t.clone();e=0!==e.negative?e.umod(t):e.clone();for(var i,o=new a(1),s=new a(0),l=r.clone();e.cmpn(1)>0&&r.cmpn(1)>0;){for(var u=0,c=1;0==(e.words[0]&c)&&u<26;++u,c<<=1);if(u>0)for(e.iushrn(u);u-- >0;)o.isOdd()&&o.iadd(l),o.iushrn(1);for(var f=0,h=1;0==(r.words[0]&h)&&f<26;++f,h<<=1);if(f>0)for(r.iushrn(f);f-- >0;)s.isOdd()&&s.iadd(l),s.iushrn(1);e.cmp(r)>=0?(e.isub(r),o.isub(s)):(r.isub(e),s.isub(o))}return(i=0===e.cmpn(1)?o:s).cmpn(0)<0&&i.iadd(t),i},a.prototype.gcd=function(t){if(this.isZero())return t.abs();if(t.isZero())return this.abs();var e=this.clone(),r=t.clone();e.negative=0,r.negative=0;for(var n=0;e.isEven()&&r.isEven();n++)e.iushrn(1),r.iushrn(1);for(;;){for(;e.isEven();)e.iushrn(1);for(;r.isEven();)r.iushrn(1);var i=e.cmp(r);if(i<0){var a=e;e=r,r=a}else if(0===i||0===r.cmpn(1))break;e.isub(r)}return r.iushln(n)},a.prototype.invm=function(t){return this.egcd(t).a.umod(t)},a.prototype.isEven=function(){return 0==(1&this.words[0])},a.prototype.isOdd=function(){return 1==(1&this.words[0])},a.prototype.andln=function(t){return this.words[0]&t},a.prototype.bincn=function(t){n("number"==typeof t);var e=t%26,r=(t-e)/26,i=1<>>26,s&=67108863,this.words[o]=s}return 0!==a&&(this.words[o]=a,this.length++),this},a.prototype.isZero=function(){return 1===this.length&&0===this.words[0]},a.prototype.cmpn=function(t){var e,r=t<0;if(0!==this.negative&&!r)return-1;if(0===this.negative&&r)return 1;if(this.strip(),this.length>1)e=1;else{r&&(t=-t),n(t<=67108863,"Number is too big");var i=0|this.words[0];e=i===t?0:it.length)return 1;if(this.length=0;r--){var n=0|this.words[r],i=0|t.words[r];if(n!==i){ni&&(e=1);break}}return e},a.prototype.gtn=function(t){return 1===this.cmpn(t)},a.prototype.gt=function(t){return 1===this.cmp(t)},a.prototype.gten=function(t){return this.cmpn(t)>=0},a.prototype.gte=function(t){return this.cmp(t)>=0},a.prototype.ltn=function(t){return-1===this.cmpn(t)},a.prototype.lt=function(t){return-1===this.cmp(t)},a.prototype.lten=function(t){return this.cmpn(t)<=0},a.prototype.lte=function(t){return this.cmp(t)<=0},a.prototype.eqn=function(t){return 0===this.cmpn(t)},a.prototype.eq=function(t){return 0===this.cmp(t)},a.red=function(t){return new w(t)},a.prototype.toRed=function(t){return n(!this.red,"Already a number in reduction context"),n(0===this.negative,"red works only with positives"),t.convertTo(this)._forceRed(t)},a.prototype.fromRed=function(){return n(this.red,"fromRed works only with numbers in reduction context"),this.red.convertFrom(this)},a.prototype._forceRed=function(t){return this.red=t,this},a.prototype.forceRed=function(t){return n(!this.red,"Already a number in reduction context"),this._forceRed(t)},a.prototype.redAdd=function(t){return n(this.red,"redAdd works only with red numbers"),this.red.add(this,t)},a.prototype.redIAdd=function(t){return n(this.red,"redIAdd works only with red numbers"),this.red.iadd(this,t)},a.prototype.redSub=function(t){return n(this.red,"redSub works only with red numbers"),this.red.sub(this,t)},a.prototype.redISub=function(t){return n(this.red,"redISub works only with red numbers"),this.red.isub(this,t)},a.prototype.redShl=function(t){return n(this.red,"redShl works only with red numbers"),this.red.shl(this,t)},a.prototype.redMul=function(t){return n(this.red,"redMul works only with red numbers"),this.red._verify2(this,t),this.red.mul(this,t)},a.prototype.redIMul=function(t){return n(this.red,"redMul works only with red numbers"),this.red._verify2(this,t),this.red.imul(this,t)},a.prototype.redSqr=function(){return n(this.red,"redSqr works only with red numbers"),this.red._verify1(this),this.red.sqr(this)},a.prototype.redISqr=function(){return n(this.red,"redISqr works only with red numbers"),this.red._verify1(this),this.red.isqr(this)},a.prototype.redSqrt=function(){return n(this.red,"redSqrt works only with red numbers"),this.red._verify1(this),this.red.sqrt(this)},a.prototype.redInvm=function(){return n(this.red,"redInvm works only with red numbers"),this.red._verify1(this),this.red.invm(this)},a.prototype.redNeg=function(){return n(this.red,"redNeg works only with red numbers"),this.red._verify1(this),this.red.neg(this)},a.prototype.redPow=function(t){return n(this.red&&!t.red,"redPow(normalNum)"),this.red._verify1(this),this.red.pow(this,t)};var v={k256:null,p224:null,p192:null,p25519:null};function m(t,e){this.name=t,this.p=new a(e,16),this.n=this.p.bitLength(),this.k=new a(1).iushln(this.n).isub(this.p),this.tmp=this._tmp()}function y(){m.call(this,"k256","ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f")}function b(){m.call(this,"p224","ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001")}function x(){m.call(this,"p192","ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff")}function _(){m.call(this,"25519","7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed")}function w(t){if("string"==typeof t){var e=a._prime(t);this.m=e.p,this.prime=e}else n(t.gtn(1),"modulus must be greater than 1"),this.m=t,this.prime=null}function M(t){w.call(this,t),this.shift=this.m.bitLength(),this.shift%26!=0&&(this.shift+=26-this.shift%26),this.r=new a(1).iushln(this.shift),this.r2=this.imod(this.r.sqr()),this.rinv=this.r._invmp(this.m),this.minv=this.rinv.mul(this.r).isubn(1).div(this.m),this.minv=this.minv.umod(this.r),this.minv=this.r.sub(this.minv)}m.prototype._tmp=function(){var t=new a(null);return t.words=new Array(Math.ceil(this.n/13)),t},m.prototype.ireduce=function(t){var e,r=t;do{this.split(r,this.tmp),e=(r=(r=this.imulK(r)).iadd(this.tmp)).bitLength()}while(e>this.n);var n=e0?r.isub(this.p):r.strip(),r},m.prototype.split=function(t,e){t.iushrn(this.n,0,e)},m.prototype.imulK=function(t){return t.imul(this.k)},i(y,m),y.prototype.split=function(t,e){for(var r=Math.min(t.length,9),n=0;n>>22,i=a}i>>>=22,t.words[n-10]=i,0===i&&t.length>10?t.length-=10:t.length-=9},y.prototype.imulK=function(t){t.words[t.length]=0,t.words[t.length+1]=0,t.length+=2;for(var e=0,r=0;r>>=26,t.words[r]=i,e=n}return 0!==e&&(t.words[t.length++]=e),t},a._prime=function(t){if(v[t])return v[t];var e;if("k256"===t)e=new y;else if("p224"===t)e=new b;else if("p192"===t)e=new x;else{if("p25519"!==t)throw new Error("Unknown prime "+t);e=new _}return v[t]=e,e},w.prototype._verify1=function(t){n(0===t.negative,"red works only with positives"),n(t.red,"red works only with red numbers")},w.prototype._verify2=function(t,e){n(0==(t.negative|e.negative),"red works only with positives"),n(t.red&&t.red===e.red,"red works only with red numbers")},w.prototype.imod=function(t){return this.prime?this.prime.ireduce(t)._forceRed(this):t.umod(this.m)._forceRed(this)},w.prototype.neg=function(t){return t.isZero()?t.clone():this.m.sub(t)._forceRed(this)},w.prototype.add=function(t,e){this._verify2(t,e);var r=t.add(e);return r.cmp(this.m)>=0&&r.isub(this.m),r._forceRed(this)},w.prototype.iadd=function(t,e){this._verify2(t,e);var r=t.iadd(e);return r.cmp(this.m)>=0&&r.isub(this.m),r},w.prototype.sub=function(t,e){this._verify2(t,e);var r=t.sub(e);return r.cmpn(0)<0&&r.iadd(this.m),r._forceRed(this)},w.prototype.isub=function(t,e){this._verify2(t,e);var r=t.isub(e);return r.cmpn(0)<0&&r.iadd(this.m),r},w.prototype.shl=function(t,e){return this._verify1(t),this.imod(t.ushln(e))},w.prototype.imul=function(t,e){return this._verify2(t,e),this.imod(t.imul(e))},w.prototype.mul=function(t,e){return this._verify2(t,e),this.imod(t.mul(e))},w.prototype.isqr=function(t){return this.imul(t,t.clone())},w.prototype.sqr=function(t){return this.mul(t,t)},w.prototype.sqrt=function(t){if(t.isZero())return t.clone();var e=this.m.andln(3);if(n(e%2==1),3===e){var r=this.m.add(new a(1)).iushrn(2);return this.pow(t,r)}for(var i=this.m.subn(1),o=0;!i.isZero()&&0===i.andln(1);)o++,i.iushrn(1);n(!i.isZero());var s=new a(1).toRed(this),l=s.redNeg(),u=this.m.subn(1).iushrn(1),c=this.m.bitLength();for(c=new a(2*c*c).toRed(this);0!==this.pow(c,u).cmp(l);)c.redIAdd(l);for(var f=this.pow(c,i),h=this.pow(t,i.addn(1).iushrn(1)),d=this.pow(t,i),p=o;0!==d.cmp(s);){for(var g=d,v=0;0!==g.cmp(s);v++)g=g.redSqr();n(v=0;n--){for(var u=e.words[n],c=l-1;c>=0;c--){var f=u>>c&1;i!==r[0]&&(i=this.sqr(i)),0!==f||0!==o?(o<<=1,o|=f,(4===++s||0===n&&0===c)&&(i=this.mul(i,r[o]),s=0,o=0)):s=0}l=26}return i},w.prototype.convertTo=function(t){var e=t.umod(this.m);return e===t?e.clone():e},w.prototype.convertFrom=function(t){var e=t.clone();return e.red=null,e},a.mont=function(t){return new M(t)},i(M,w),M.prototype.convertTo=function(t){return this.imod(t.ushln(this.shift))},M.prototype.convertFrom=function(t){var e=this.imod(t.mul(this.rinv));return e.red=null,e},M.prototype.imul=function(t,e){if(t.isZero()||e.isZero())return t.words[0]=0,t.length=1,t;var r=t.imul(e),n=r.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=r.isub(n).iushrn(this.shift),a=i;return i.cmp(this.m)>=0?a=i.isub(this.m):i.cmpn(0)<0&&(a=i.iadd(this.m)),a._forceRed(this)},M.prototype.mul=function(t,e){if(t.isZero()||e.isZero())return new a(0)._forceRed(this);var r=t.mul(e),n=r.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=r.isub(n).iushrn(this.shift),o=i;return i.cmp(this.m)>=0?o=i.isub(this.m):i.cmpn(0)<0&&(o=i.iadd(this.m)),o._forceRed(this)},M.prototype.invm=function(t){return this.imod(t._invmp(this.m).mul(this.r2))._forceRed(this)}}(void 0===e||e,this)},{buffer:46}],38:[function(t,e,r){"use strict";e.exports=function(t){var e,r,n,i=t.length,a=0;for(e=0;e>>1;if(!(c<=0)){var f,h=i.mallocDouble(2*c*s),d=i.mallocInt32(s);if((s=l(t,c,h,d))>0){if(1===c&&n)a.init(s),f=a.sweepComplete(c,r,0,s,h,d,0,s,h,d);else{var p=i.mallocDouble(2*c*u),g=i.mallocInt32(u);(u=l(e,c,p,g))>0&&(a.init(s+u),f=1===c?a.sweepBipartite(c,r,0,s,h,d,0,u,p,g):o(c,r,n,s,h,d,u,p,g),i.free(p),i.free(g))}i.free(h),i.free(d)}return f}}}function c(t,e){n.push([t,e])}},{"./lib/intersect":41,"./lib/sweep":45,"typedarray-pool":328}],40:[function(t,e,r){"use strict";var n="d",i="ax",a="vv",o="fp",s="es",l="rs",u="re",c="rb",f="ri",h="rp",d="bs",p="be",g="bb",v="bi",m="bp",y="rv",b="Q",x=[n,i,a,l,u,c,f,d,p,g,v];function _(t){var e="bruteForce"+(t?"Full":"Partial"),r=[],_=x.slice();t||_.splice(3,0,o);var w=["function "+e+"("+_.join()+"){"];function M(e,o){var _=function(t,e,r){var o="bruteForce"+(t?"Red":"Blue")+(e?"Flip":"")+(r?"Full":""),_=["function ",o,"(",x.join(),"){","var ",s,"=2*",n,";"],w="for(var i="+l+","+h+"="+s+"*"+l+";i<"+u+";++i,"+h+"+="+s+"){var x0="+c+"["+i+"+"+h+"],x1="+c+"["+i+"+"+h+"+"+n+"],xi="+f+"[i];",M="for(var j="+d+","+m+"="+s+"*"+d+";j<"+p+";++j,"+m+"+="+s+"){var y0="+g+"["+i+"+"+m+"],"+(r?"y1="+g+"["+i+"+"+m+"+"+n+"],":"")+"yi="+v+"[j];";return t?_.push(w,b,":",M):_.push(M,b,":",w),r?_.push("if(y1"+p+"-"+d+"){"),t?(M(!0,!1),w.push("}else{"),M(!1,!1)):(w.push("if("+o+"){"),M(!0,!0),w.push("}else{"),M(!0,!1),w.push("}}else{if("+o+"){"),M(!1,!0),w.push("}else{"),M(!1,!1),w.push("}")),w.push("}}return "+e);var A=r.join("")+w.join("");return new Function(A)()}r.partial=_(!1),r.full=_(!0)},{}],41:[function(t,e,r){"use strict";e.exports=function(t,e,r,a,c,E,S,L,C){!function(t,e){var r=8*i.log2(e+1)*(t+1)|0,a=i.nextPow2(x*r);w.length0;){var I=(O-=1)*x,N=w[I],z=w[I+1],D=w[I+2],F=w[I+3],j=w[I+4],B=w[I+5],U=O*_,V=M[U],H=M[U+1],q=1&B,G=!!(16&B),X=c,W=E,Y=L,Z=C;if(q&&(X=L,W=C,Y=c,Z=E),!(2&B&&(D=v(t,N,z,D,X,W,H),z>=D)||4&B&&(z=m(t,N,z,D,X,W,V))>=D)){var Q=D-z,J=j-F;if(G){if(t*Q*(Q+J)=p0)&&!(p1>=hi)",["p0","p1"]),g=c("lo===p0",["p0"]),v=c("lo>>1,h=2*t,d=f,p=s[h*f+e];for(;u=b?(d=y,p=b):m>=_?(d=v,p=m):(d=x,p=_):b>=_?(d=y,p=b):_>=m?(d=v,p=m):(d=x,p=_);for(var w=h*(c-1),M=h*d,A=0;Ar&&i[f+e]>u;--c,f-=o){for(var h=f,d=f+o,p=0;p=0&&i.push("lo=e[k+n]");t.indexOf("hi")>=0&&i.push("hi=e[k+o]");return r.push(n.replace("_",i.join()).replace("$",t)),Function.apply(void 0,r)};var n="for(var j=2*a,k=j*c,l=k,m=c,n=b,o=a+b,p=c;d>p;++p,k+=j){var _;if($)if(m===p)m+=1,l+=j;else{for(var s=0;j>s;++s){var t=e[k+s];e[k+s]=e[l],e[l++]=t}var u=f[p];f[p]=f[m],f[m++]=u}}return m"},{}],44:[function(t,e,r){"use strict";e.exports=function(t,e){e<=4*n?i(0,e-1,t):function t(e,r,f){var h=(r-e+1)/6|0,d=e+h,p=r-h,g=e+r>>1,v=g-h,m=g+h,y=d,b=v,x=g,_=m,w=p,M=e+1,A=r-1,T=0;u(y,b,f)&&(T=y,y=b,b=T);u(_,w,f)&&(T=_,_=w,w=T);u(y,x,f)&&(T=y,y=x,x=T);u(b,x,f)&&(T=b,b=x,x=T);u(y,_,f)&&(T=y,y=_,_=T);u(x,_,f)&&(T=x,x=_,_=T);u(b,w,f)&&(T=b,b=w,w=T);u(b,x,f)&&(T=b,b=x,x=T);u(_,w,f)&&(T=_,_=w,w=T);var k=f[2*b];var E=f[2*b+1];var S=f[2*_];var L=f[2*_+1];var C=2*y;var P=2*x;var O=2*w;var R=2*d;var I=2*g;var N=2*p;for(var z=0;z<2;++z){var D=f[C+z],F=f[P+z],j=f[O+z];f[R+z]=D,f[I+z]=F,f[N+z]=j}o(v,e,f);o(m,r,f);for(var B=M;B<=A;++B)if(c(B,k,E,f))B!==M&&a(B,M,f),++M;else if(!c(B,S,L,f))for(;;){if(c(A,S,L,f)){c(A,k,E,f)?(s(B,M,A,f),++M,--A):(a(B,A,f),--A);break}if(--At;){var u=r[l-2],c=r[l-1];if(ur[e+1])}function c(t,e,r,n){var i=n[t*=2];return i>>1;a(d,E);for(var S=0,L=0,M=0;M=o)p(u,c,L--,C=C-o|0);else if(C>=0)p(s,l,S--,C);else if(C<=-o){C=-C-o|0;for(var P=0;P>>1;a(d,S);for(var L=0,C=0,P=0,A=0;A>1==d[2*A+3]>>1&&(R=2,A+=1),O<0){for(var I=-(O>>1)-1,N=0;N>1)-1;0===R?p(s,l,L--,I):1===R?p(u,c,C--,I):2===R&&p(f,h,P--,I)}}},scanBipartite:function(t,e,r,n,i,u,c,f,h,v,m,y){var b=0,x=2*t,_=e,w=e+t,M=1,A=1;n?A=o:M=o;for(var T=i;T>>1;a(d,L);for(var C=0,T=0;T=o?(O=!n,k-=o):(O=!!n,k-=1),O)g(s,l,C++,k);else{var R=y[k],I=x*k,N=m[I+e+1],z=m[I+e+1+t];t:for(var D=0;D>>1;a(d,M);for(var A=0,b=0;b=o)s[A++]=x-o;else{var k=p[x-=1],E=v*x,S=h[E+e+1],L=h[E+e+1+t];t:for(var C=0;C=0;--C)if(s[C]===x){for(var I=C+1;Ia)throw new RangeError("Invalid typed array length");var e=new Uint8Array(t);return e.__proto__=s.prototype,e}function s(t,e,r){if("number"==typeof t){if("string"==typeof e)throw new Error("If encoding is specified then the first argument must be a string");return c(t)}return l(t,e,r)}function l(t,e,r){if("number"==typeof t)throw new TypeError('"value" argument must not be a number');return B(t)||t&&B(t.buffer)?function(t,e,r){if(e<0||t.byteLength=a)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a.toString(16)+" bytes");return 0|t}function d(t,e){if(s.isBuffer(t))return t.length;if(ArrayBuffer.isView(t)||B(t))return t.byteLength;"string"!=typeof t&&(t=""+t);var r=t.length;if(0===r)return 0;for(var n=!1;;)switch(e){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":case void 0:return D(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return F(t).length;default:if(n)return D(t).length;e=(""+e).toLowerCase(),n=!0}}function p(t,e,r){var n=t[e];t[e]=t[r],t[r]=n}function g(t,e,r,n,i){if(0===t.length)return-1;if("string"==typeof r?(n=r,r=0):r>2147483647?r=2147483647:r<-2147483648&&(r=-2147483648),U(r=+r)&&(r=i?0:t.length-1),r<0&&(r=t.length+r),r>=t.length){if(i)return-1;r=t.length-1}else if(r<0){if(!i)return-1;r=0}if("string"==typeof e&&(e=s.from(e,n)),s.isBuffer(e))return 0===e.length?-1:v(t,e,r,n,i);if("number"==typeof e)return e&=255,"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(t,e,r):Uint8Array.prototype.lastIndexOf.call(t,e,r):v(t,[e],r,n,i);throw new TypeError("val must be string, number or Buffer")}function v(t,e,r,n,i){var a,o=1,s=t.length,l=e.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||e.length<2)return-1;o=2,s/=2,l/=2,r/=2}function u(t,e){return 1===o?t[e]:t.readUInt16BE(e*o)}if(i){var c=-1;for(a=r;as&&(r=s-l),a=r;a>=0;a--){for(var f=!0,h=0;hi&&(n=i):n=i;var a=e.length;n>a/2&&(n=a/2);for(var o=0;o>8,i=r%256,a.push(i),a.push(n);return a}(e,t.length-r),t,r,n)}function M(t,e,r){return 0===e&&r===t.length?n.fromByteArray(t):n.fromByteArray(t.slice(e,r))}function A(t,e,r){r=Math.min(t.length,r);for(var n=[],i=e;i239?4:u>223?3:u>191?2:1;if(i+f<=r)switch(f){case 1:u<128&&(c=u);break;case 2:128==(192&(a=t[i+1]))&&(l=(31&u)<<6|63&a)>127&&(c=l);break;case 3:a=t[i+1],o=t[i+2],128==(192&a)&&128==(192&o)&&(l=(15&u)<<12|(63&a)<<6|63&o)>2047&&(l<55296||l>57343)&&(c=l);break;case 4:a=t[i+1],o=t[i+2],s=t[i+3],128==(192&a)&&128==(192&o)&&128==(192&s)&&(l=(15&u)<<18|(63&a)<<12|(63&o)<<6|63&s)>65535&&l<1114112&&(c=l)}null===c?(c=65533,f=1):c>65535&&(c-=65536,n.push(c>>>10&1023|55296),c=56320|1023&c),n.push(c),i+=f}return function(t){var e=t.length;if(e<=T)return String.fromCharCode.apply(String,t);var r="",n=0;for(;nthis.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(e>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return S(this,e,r);case"utf8":case"utf-8":return A(this,e,r);case"ascii":return k(this,e,r);case"latin1":case"binary":return E(this,e,r);case"base64":return M(this,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return L(this,e,r);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}.apply(this,arguments)},s.prototype.toLocaleString=s.prototype.toString,s.prototype.equals=function(t){if(!s.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t||0===s.compare(this,t)},s.prototype.inspect=function(){var t="",e=r.INSPECT_MAX_BYTES;return this.length>0&&(t=this.toString("hex",0,e).match(/.{2}/g).join(" "),this.length>e&&(t+=" ... ")),""},s.prototype.compare=function(t,e,r,n,i){if(!s.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===e&&(e=0),void 0===r&&(r=t?t.length:0),void 0===n&&(n=0),void 0===i&&(i=this.length),e<0||r>t.length||n<0||i>this.length)throw new RangeError("out of range index");if(n>=i&&e>=r)return 0;if(n>=i)return-1;if(e>=r)return 1;if(this===t)return 0;for(var a=(i>>>=0)-(n>>>=0),o=(r>>>=0)-(e>>>=0),l=Math.min(a,o),u=this.slice(n,i),c=t.slice(e,r),f=0;f>>=0,isFinite(r)?(r>>>=0,void 0===n&&(n="utf8")):(n=r,r=void 0)}var i=this.length-e;if((void 0===r||r>i)&&(r=i),t.length>0&&(r<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var a=!1;;)switch(n){case"hex":return m(this,t,e,r);case"utf8":case"utf-8":return y(this,t,e,r);case"ascii":return b(this,t,e,r);case"latin1":case"binary":return x(this,t,e,r);case"base64":return _(this,t,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return w(this,t,e,r);default:if(a)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),a=!0}},s.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var T=4096;function k(t,e,r){var n="";r=Math.min(t.length,r);for(var i=e;in)&&(r=n);for(var i="",a=e;ar)throw new RangeError("Trying to access beyond buffer length")}function P(t,e,r,n,i,a){if(!s.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>i||et.length)throw new RangeError("Index out of range")}function O(t,e,r,n,i,a){if(r+n>t.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function R(t,e,r,n,a){return e=+e,r>>>=0,a||O(t,0,r,4),i.write(t,e,r,n,23,4),r+4}function I(t,e,r,n,a){return e=+e,r>>>=0,a||O(t,0,r,8),i.write(t,e,r,n,52,8),r+8}s.prototype.slice=function(t,e){var r=this.length;(t=~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),(e=void 0===e?r:~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),e>>=0,e>>>=0,r||C(t,e,this.length);for(var n=this[t],i=1,a=0;++a>>=0,e>>>=0,r||C(t,e,this.length);for(var n=this[t+--e],i=1;e>0&&(i*=256);)n+=this[t+--e]*i;return n},s.prototype.readUInt8=function(t,e){return t>>>=0,e||C(t,1,this.length),this[t]},s.prototype.readUInt16LE=function(t,e){return t>>>=0,e||C(t,2,this.length),this[t]|this[t+1]<<8},s.prototype.readUInt16BE=function(t,e){return t>>>=0,e||C(t,2,this.length),this[t]<<8|this[t+1]},s.prototype.readUInt32LE=function(t,e){return t>>>=0,e||C(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},s.prototype.readUInt32BE=function(t,e){return t>>>=0,e||C(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},s.prototype.readIntLE=function(t,e,r){t>>>=0,e>>>=0,r||C(t,e,this.length);for(var n=this[t],i=1,a=0;++a=(i*=128)&&(n-=Math.pow(2,8*e)),n},s.prototype.readIntBE=function(t,e,r){t>>>=0,e>>>=0,r||C(t,e,this.length);for(var n=e,i=1,a=this[t+--n];n>0&&(i*=256);)a+=this[t+--n]*i;return a>=(i*=128)&&(a-=Math.pow(2,8*e)),a},s.prototype.readInt8=function(t,e){return t>>>=0,e||C(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},s.prototype.readInt16LE=function(t,e){t>>>=0,e||C(t,2,this.length);var r=this[t]|this[t+1]<<8;return 32768&r?4294901760|r:r},s.prototype.readInt16BE=function(t,e){t>>>=0,e||C(t,2,this.length);var r=this[t+1]|this[t]<<8;return 32768&r?4294901760|r:r},s.prototype.readInt32LE=function(t,e){return t>>>=0,e||C(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},s.prototype.readInt32BE=function(t,e){return t>>>=0,e||C(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},s.prototype.readFloatLE=function(t,e){return t>>>=0,e||C(t,4,this.length),i.read(this,t,!0,23,4)},s.prototype.readFloatBE=function(t,e){return t>>>=0,e||C(t,4,this.length),i.read(this,t,!1,23,4)},s.prototype.readDoubleLE=function(t,e){return t>>>=0,e||C(t,8,this.length),i.read(this,t,!0,52,8)},s.prototype.readDoubleBE=function(t,e){return t>>>=0,e||C(t,8,this.length),i.read(this,t,!1,52,8)},s.prototype.writeUIntLE=function(t,e,r,n){(t=+t,e>>>=0,r>>>=0,n)||P(this,t,e,r,Math.pow(2,8*r)-1,0);var i=1,a=0;for(this[e]=255&t;++a>>=0,r>>>=0,n)||P(this,t,e,r,Math.pow(2,8*r)-1,0);var i=r-1,a=1;for(this[e+i]=255&t;--i>=0&&(a*=256);)this[e+i]=t/a&255;return e+r},s.prototype.writeUInt8=function(t,e,r){return t=+t,e>>>=0,r||P(this,t,e,1,255,0),this[e]=255&t,e+1},s.prototype.writeUInt16LE=function(t,e,r){return t=+t,e>>>=0,r||P(this,t,e,2,65535,0),this[e]=255&t,this[e+1]=t>>>8,e+2},s.prototype.writeUInt16BE=function(t,e,r){return t=+t,e>>>=0,r||P(this,t,e,2,65535,0),this[e]=t>>>8,this[e+1]=255&t,e+2},s.prototype.writeUInt32LE=function(t,e,r){return t=+t,e>>>=0,r||P(this,t,e,4,4294967295,0),this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t,e+4},s.prototype.writeUInt32BE=function(t,e,r){return t=+t,e>>>=0,r||P(this,t,e,4,4294967295,0),this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t,e+4},s.prototype.writeIntLE=function(t,e,r,n){if(t=+t,e>>>=0,!n){var i=Math.pow(2,8*r-1);P(this,t,e,r,i-1,-i)}var a=0,o=1,s=0;for(this[e]=255&t;++a>0)-s&255;return e+r},s.prototype.writeIntBE=function(t,e,r,n){if(t=+t,e>>>=0,!n){var i=Math.pow(2,8*r-1);P(this,t,e,r,i-1,-i)}var a=r-1,o=1,s=0;for(this[e+a]=255&t;--a>=0&&(o*=256);)t<0&&0===s&&0!==this[e+a+1]&&(s=1),this[e+a]=(t/o>>0)-s&255;return e+r},s.prototype.writeInt8=function(t,e,r){return t=+t,e>>>=0,r||P(this,t,e,1,127,-128),t<0&&(t=255+t+1),this[e]=255&t,e+1},s.prototype.writeInt16LE=function(t,e,r){return t=+t,e>>>=0,r||P(this,t,e,2,32767,-32768),this[e]=255&t,this[e+1]=t>>>8,e+2},s.prototype.writeInt16BE=function(t,e,r){return t=+t,e>>>=0,r||P(this,t,e,2,32767,-32768),this[e]=t>>>8,this[e+1]=255&t,e+2},s.prototype.writeInt32LE=function(t,e,r){return t=+t,e>>>=0,r||P(this,t,e,4,2147483647,-2147483648),this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24,e+4},s.prototype.writeInt32BE=function(t,e,r){return t=+t,e>>>=0,r||P(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t,e+4},s.prototype.writeFloatLE=function(t,e,r){return R(this,t,e,!0,r)},s.prototype.writeFloatBE=function(t,e,r){return R(this,t,e,!1,r)},s.prototype.writeDoubleLE=function(t,e,r){return I(this,t,e,!0,r)},s.prototype.writeDoubleBE=function(t,e,r){return I(this,t,e,!1,r)},s.prototype.copy=function(t,e,r,n){if(!s.isBuffer(t))throw new TypeError("argument should be a Buffer");if(r||(r=0),n||0===n||(n=this.length),e>=t.length&&(e=t.length),e||(e=0),n>0&&n=this.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-e=0;--a)t[a+e]=this[a+r];else Uint8Array.prototype.set.call(t,this.subarray(r,n),e);return i},s.prototype.fill=function(t,e,r,n){if("string"==typeof t){if("string"==typeof e?(n=e,e=0,r=this.length):"string"==typeof r&&(n=r,r=this.length),void 0!==n&&"string"!=typeof n)throw new TypeError("encoding must be a string");if("string"==typeof n&&!s.isEncoding(n))throw new TypeError("Unknown encoding: "+n);if(1===t.length){var i=t.charCodeAt(0);("utf8"===n&&i<128||"latin1"===n)&&(t=i)}}else"number"==typeof t&&(t&=255);if(e<0||this.length>>=0,r=void 0===r?this.length:r>>>0,t||(t=0),"number"==typeof t)for(a=e;a55295&&r<57344){if(!i){if(r>56319){(e-=3)>-1&&a.push(239,191,189);continue}if(o+1===n){(e-=3)>-1&&a.push(239,191,189);continue}i=r;continue}if(r<56320){(e-=3)>-1&&a.push(239,191,189),i=r;continue}r=65536+(i-55296<<10|r-56320)}else i&&(e-=3)>-1&&a.push(239,191,189);if(i=null,r<128){if((e-=1)<0)break;a.push(r)}else if(r<2048){if((e-=2)<0)break;a.push(r>>6|192,63&r|128)}else if(r<65536){if((e-=3)<0)break;a.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;a.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return a}function F(t){return n.toByteArray(function(t){if((t=(t=t.split("=")[0]).trim().replace(N,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function j(t,e,r,n){for(var i=0;i=e.length||i>=t.length);++i)e[i+r]=t[i];return i}function B(t){return t instanceof ArrayBuffer||null!=t&&null!=t.constructor&&"ArrayBuffer"===t.constructor.name&&"number"==typeof t.byteLength}function U(t){return t!=t}},{"base64-js":18,ieee754:233}],48:[function(t,e,r){"use strict";var n=t("./lib/monotone"),i=t("./lib/triangulation"),a=t("./lib/delaunay"),o=t("./lib/filter");function s(t){return[Math.min(t[0],t[1]),Math.max(t[0],t[1])]}function l(t,e){return t[0]-e[0]||t[1]-e[1]}function u(t,e,r){return e in t?t[e]:r}e.exports=function(t,e,r){Array.isArray(e)?(r=r||{},e=e||[]):(r=e||{},e=[]);var c=!!u(r,"delaunay",!0),f=!!u(r,"interior",!0),h=!!u(r,"exterior",!0),d=!!u(r,"infinity",!1);if(!f&&!h||0===t.length)return[];var p=n(t,e);if(c||f!==h||d){for(var g=i(t.length,function(t){return t.map(s).sort(l)}(e)),v=0;v0;){for(var c=r.pop(),s=r.pop(),f=-1,h=-1,l=o[s],p=1;p=0||(e.flip(s,c),i(t,e,r,f,s,h),i(t,e,r,s,h,f),i(t,e,r,h,c,f),i(t,e,r,c,f,h)))}}},{"binary-search-bounds":53,"robust-in-sphere":299}],50:[function(t,e,r){"use strict";var n,i=t("binary-search-bounds");function a(t,e,r,n,i,a,o){this.cells=t,this.neighbor=e,this.flags=n,this.constraint=r,this.active=i,this.next=a,this.boundary=o}function o(t,e){return t[0]-e[0]||t[1]-e[1]||t[2]-e[2]}e.exports=function(t,e,r){var n=function(t,e){for(var r=t.cells(),n=r.length,i=0;i0||l.length>0;){for(;s.length>0;){var d=s.pop();if(u[d]!==-i){u[d]=i;c[d];for(var p=0;p<3;++p){var g=h[3*d+p];g>=0&&0===u[g]&&(f[3*d+p]?l.push(g):(s.push(g),u[g]=i))}}}var v=l;l=s,s=v,l.length=0,i=-i}var m=function(t,e,r){for(var n=0,i=0;i1&&i(r[h[d-2]],r[h[d-1]],a)>0;)t.push([h[d-1],h[d-2],o]),d-=1;h.length=d,h.push(o);var p=c.upperIds;for(d=p.length;d>1&&i(r[p[d-2]],r[p[d-1]],a)<0;)t.push([p[d-2],p[d-1],o]),d-=1;p.length=d,p.push(o)}}function d(t,e){var r;return(r=t.a[0]m[0]&&i.push(new u(m,v,s,f),new u(v,m,o,f))}i.sort(c);for(var y=i[0].a[0]-(1+Math.abs(i[0].a[0]))*Math.pow(2,-52),b=[new l([y,1],[y,0],-1,[],[],[],[])],x=[],f=0,_=i.length;f<_;++f){var w=i[f],M=w.type;M===a?h(x,b,t,w.a,w.idx):M===s?p(b,t,w):g(b,t,w)}return x}},{"binary-search-bounds":53,"robust-orientation":301}],52:[function(t,e,r){"use strict";var n=t("binary-search-bounds");function i(t,e){this.stars=t,this.edges=e}e.exports=function(t,e){for(var r=new Array(t),n=0;n=0}}(),a.removeTriangle=function(t,e,r){var n=this.stars;o(n[t],e,r),o(n[e],r,t),o(n[r],t,e)},a.addTriangle=function(t,e,r){var n=this.stars;n[t].push(e,r),n[e].push(r,t),n[r].push(t,e)},a.opposite=function(t,e){for(var r=this.stars[e],n=1,i=r.length;n>>1,x=a[m]"];return i?e.indexOf("c")<0?a.push(";if(x===y){return m}else if(x<=y){"):a.push(";var p=c(x,y);if(p===0){return m}else if(p<=0){"):a.push(";if(",e,"){i=m;"),r?a.push("l=m+1}else{h=m-1}"):a.push("h=m-1}else{l=m+1}"),a.push("}"),i?a.push("return -1};"):a.push("return i};"),a.join("")}function i(t,e,r,i){return new Function([n("A","x"+t+"y",e,["y"],i),n("P","c(x,y)"+t+"0",e,["y","c"],i),"function dispatchBsearch",r,"(a,y,c,l,h){if(typeof(c)==='function'){return P(a,(l===void 0)?0:l|0,(h===void 0)?a.length-1:h|0,y,c)}else{return A(a,(c===void 0)?0:c|0,(l===void 0)?a.length-1:l|0,y)}}return dispatchBsearch",r].join(""))()}e.exports={ge:i(">=",!1,"GE"),gt:i(">",!1,"GT"),lt:i("<",!0,"LT"),le:i("<=",!0,"LE"),eq:i("-",!0,"EQ",!0)}},{}],54:[function(t,e,r){"use strict";e.exports=function(t){for(var e=1,r=1;rr?r:t:te?e:t}},{}],58:[function(t,e,r){"use strict";e.exports=function(t,e,r){var n;if(r){n=e;for(var i=new Array(e.length),a=0;ae[2]?1:0)}function m(t,e,r){if(0!==t.length){if(e)for(var n=0;n=0;--a){var b=e[c=(E=n[a])[0]],x=b[0],_=b[1],w=t[x],M=t[_];if((w[0]-M[0]||w[1]-M[1])<0){var A=x;x=_,_=A}b[0]=x;var T,k=b[1]=E[1];for(i&&(T=b[2]);a>0&&n[a-1][0]===c;){var E,S=(E=n[--a])[1];i?e.push([k,S,T]):e.push([k,S]),k=S}i?e.push([k,_,T]):e.push([k,_])}return h}(t,e,h,v,r));return m(e,y,r),!!y||(h.length>0||v.length>0)}},{"./lib/rat-seg-intersect":59,"big-rat":22,"big-rat/cmp":20,"big-rat/to-float":34,"box-intersect":39,nextafter:266,"rat-vec":290,"robust-segment-intersect":304,"union-find":329}],59:[function(t,e,r){"use strict";e.exports=function(t,e,r,n){var a=s(e,t),f=s(n,r),h=c(a,f);if(0===o(h))return null;var d=s(t,r),p=c(f,d),g=i(p,h),v=u(a,g);return l(t,v)};var n=t("big-rat/mul"),i=t("big-rat/div"),a=t("big-rat/sub"),o=t("big-rat/sign"),s=t("rat-vec/sub"),l=t("rat-vec/add"),u=t("rat-vec/muls");function c(t,e){return a(n(t[0],e[1]),n(t[1],e[0]))}},{"big-rat/div":21,"big-rat/mul":31,"big-rat/sign":32,"big-rat/sub":33,"rat-vec/add":289,"rat-vec/muls":291,"rat-vec/sub":292}],60:[function(t,e,r){"use strict";e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],61:[function(t,e,r){"use strict";var n=t("color-rgba"),i=t("clamp"),a=t("dtype");e.exports=function(t,e){"float"!==e&&e||(e="array"),"uint"===e&&(e="uint8"),"uint_clamped"===e&&(e="uint8_clamped");var r=a(e),o=new r(4);if(t instanceof r)return Array.isArray(t)?t.slice():(o.set(t),o);var s="uint8"!==e&&"uint8_clamped"!==e;return t instanceof Uint8Array||t instanceof Uint8ClampedArray?(o[0]=t[0],o[1]=t[1],o[2]=t[2],o[3]=null!=t[3]?t[3]:255,s&&(o[0]/=255,o[1]/=255,o[2]/=255,o[3]/=255),o):(t.length&&"string"!=typeof t||((t=n(t))[0]/=255,t[1]/=255,t[2]/=255),s?(o[0]=t[0],o[1]=t[1],o[2]=t[2],o[3]=null!=t[3]?t[3]:1):(o[0]=i(Math.round(255*t[0]),0,255),o[1]=i(Math.round(255*t[1]),0,255),o[2]=i(Math.round(255*t[2]),0,255),o[3]=null==t[3]?255:i(Math.floor(255*t[3]),0,255)),o)}},{clamp:57,"color-rgba":63,dtype:84}],62:[function(t,e,r){(function(r){"use strict";var n=t("color-name"),i=t("is-plain-obj"),a=t("defined");e.exports=function(t){var e,s,l=[],u=1;if("string"==typeof t)if(n[t])l=n[t].slice(),s="rgb";else if("transparent"===t)u=0,s="rgb",l=[0,0,0];else if(/^#[A-Fa-f0-9]+$/.test(t)){var c=t.slice(1),f=c.length,h=f<=4;u=1,h?(l=[parseInt(c[0]+c[0],16),parseInt(c[1]+c[1],16),parseInt(c[2]+c[2],16)],4===f&&(u=parseInt(c[3]+c[3],16)/255)):(l=[parseInt(c[0]+c[1],16),parseInt(c[2]+c[3],16),parseInt(c[4]+c[5],16)],8===f&&(u=parseInt(c[6]+c[7],16)/255)),l[0]||(l[0]=0),l[1]||(l[1]=0),l[2]||(l[2]=0),s="rgb"}else if(e=/^((?:rgb|hs[lvb]|hwb|cmyk?|xy[zy]|gray|lab|lchu?v?|[ly]uv|lms)a?)\s*\(([^\)]*)\)/.exec(t)){var d=e[1],c=d.replace(/a$/,"");s=c;var f="cmyk"===c?4:"gray"===c?1:3;l=e[2].trim().split(/\s*,\s*/).map(function(t,e){if(/%$/.test(t))return e===f?parseFloat(t)/100:"rgb"===c?255*parseFloat(t)/100:parseFloat(t);if("h"===c[e]){if(/deg$/.test(t))return parseFloat(t);if(void 0!==o[t])return o[t]}return parseFloat(t)}),d===c&&l.push(1),u=void 0===l[f]?1:l[f],l=l.slice(0,f)}else t.length>10&&/[0-9](?:\s|\/)/.test(t)&&(l=t.match(/([0-9]+)/g).map(function(t){return parseFloat(t)}),s=t.match(/([a-z])/ig).join("").toLowerCase());else if("number"==typeof t)s="rgb",l=[t>>>16,(65280&t)>>>8,255&t];else if(i(t)){var p=a(t.r,t.red,t.R,null);null!==p?(s="rgb",l=[p,a(t.g,t.green,t.G),a(t.b,t.blue,t.B)]):(s="hsl",l=[a(t.h,t.hue,t.H),a(t.s,t.saturation,t.S),a(t.l,t.lightness,t.L,t.b,t.brightness)]),u=a(t.a,t.alpha,t.opacity,1),null!=t.opacity&&(u/=100)}else(Array.isArray(t)||r.ArrayBuffer&&ArrayBuffer.isView&&ArrayBuffer.isView(t))&&(l=[t[0],t[1],t[2]],s="rgb",u=4===t.length?t[3]:1);return{space:s,values:l,alpha:u}};var o={red:0,orange:60,yellow:120,green:180,blue:240,purple:300}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"color-name":60,defined:81,"is-plain-obj":241}],63:[function(t,e,r){"use strict";var n=t("color-parse"),i=t("color-space/hsl"),a=t("clamp");e.exports=function(t){var e;if("string"!=typeof t)throw Error("Argument should be a string");var r=n(t);return r.space?((e=Array(3))[0]=a(r.values[0],0,255),e[1]=a(r.values[1],0,255),e[2]=a(r.values[2],0,255),"h"===r.space[0]&&(e=i.rgb(e)),e.push(a(r.alpha,0,1)),e):[]}},{clamp:57,"color-parse":62,"color-space/hsl":64}],64:[function(t,e,r){"use strict";var n=t("./rgb");e.exports={name:"hsl",min:[0,0,0],max:[360,100,100],channel:["hue","saturation","lightness"],alias:["HSL"],rgb:function(t){var e,r,n,i,a,o=t[0]/360,s=t[1]/100,l=t[2]/100;if(0===s)return[a=255*l,a,a];e=2*l-(r=l<.5?l*(1+s):l+s-l*s),i=[0,0,0];for(var u=0;u<3;u++)(n=o+1/3*-(u-1))<0?n++:n>1&&n--,a=6*n<1?e+6*(r-e)*n:2*n<1?r:3*n<2?e+(r-e)*(2/3-n)*6:e,i[u]=255*a;return i}},n.hsl=function(t){var e,r,n=t[0]/255,i=t[1]/255,a=t[2]/255,o=Math.min(n,i,a),s=Math.max(n,i,a),l=s-o;return s===o?e=0:n===s?e=(i-a)/l:i===s?e=2+(a-n)/l:a===s&&(e=4+(n-i)/l),(e=Math.min(60*e,360))<0&&(e+=360),r=(o+s)/2,[e,100*(s===o?0:r<=.5?l/(s+o):l/(2-s-o)),100*r]}},{"./rgb":65}],65:[function(t,e,r){"use strict";e.exports={name:"rgb",min:[0,0,0],max:[255,255,255],channel:["red","green","blue"],alias:["RGB"]}},{}],66:[function(t,e,r){e.exports={jet:[{index:0,rgb:[0,0,131]},{index:.125,rgb:[0,60,170]},{index:.375,rgb:[5,255,255]},{index:.625,rgb:[255,255,0]},{index:.875,rgb:[250,0,0]},{index:1,rgb:[128,0,0]}],hsv:[{index:0,rgb:[255,0,0]},{index:.169,rgb:[253,255,2]},{index:.173,rgb:[247,255,2]},{index:.337,rgb:[0,252,4]},{index:.341,rgb:[0,252,10]},{index:.506,rgb:[1,249,255]},{index:.671,rgb:[2,0,253]},{index:.675,rgb:[8,0,253]},{index:.839,rgb:[255,0,251]},{index:.843,rgb:[255,0,245]},{index:1,rgb:[255,0,6]}],hot:[{index:0,rgb:[0,0,0]},{index:.3,rgb:[230,0,0]},{index:.6,rgb:[255,210,0]},{index:1,rgb:[255,255,255]}],cool:[{index:0,rgb:[0,255,255]},{index:1,rgb:[255,0,255]}],spring:[{index:0,rgb:[255,0,255]},{index:1,rgb:[255,255,0]}],summer:[{index:0,rgb:[0,128,102]},{index:1,rgb:[255,255,102]}],autumn:[{index:0,rgb:[255,0,0]},{index:1,rgb:[255,255,0]}],winter:[{index:0,rgb:[0,0,255]},{index:1,rgb:[0,255,128]}],bone:[{index:0,rgb:[0,0,0]},{index:.376,rgb:[84,84,116]},{index:.753,rgb:[169,200,200]},{index:1,rgb:[255,255,255]}],copper:[{index:0,rgb:[0,0,0]},{index:.804,rgb:[255,160,102]},{index:1,rgb:[255,199,127]}],greys:[{index:0,rgb:[0,0,0]},{index:1,rgb:[255,255,255]}],yignbu:[{index:0,rgb:[8,29,88]},{index:.125,rgb:[37,52,148]},{index:.25,rgb:[34,94,168]},{index:.375,rgb:[29,145,192]},{index:.5,rgb:[65,182,196]},{index:.625,rgb:[127,205,187]},{index:.75,rgb:[199,233,180]},{index:.875,rgb:[237,248,217]},{index:1,rgb:[255,255,217]}],greens:[{index:0,rgb:[0,68,27]},{index:.125,rgb:[0,109,44]},{index:.25,rgb:[35,139,69]},{index:.375,rgb:[65,171,93]},{index:.5,rgb:[116,196,118]},{index:.625,rgb:[161,217,155]},{index:.75,rgb:[199,233,192]},{index:.875,rgb:[229,245,224]},{index:1,rgb:[247,252,245]}],yiorrd:[{index:0,rgb:[128,0,38]},{index:.125,rgb:[189,0,38]},{index:.25,rgb:[227,26,28]},{index:.375,rgb:[252,78,42]},{index:.5,rgb:[253,141,60]},{index:.625,rgb:[254,178,76]},{index:.75,rgb:[254,217,118]},{index:.875,rgb:[255,237,160]},{index:1,rgb:[255,255,204]}],bluered:[{index:0,rgb:[0,0,255]},{index:1,rgb:[255,0,0]}],rdbu:[{index:0,rgb:[5,10,172]},{index:.35,rgb:[106,137,247]},{index:.5,rgb:[190,190,190]},{index:.6,rgb:[220,170,132]},{index:.7,rgb:[230,145,90]},{index:1,rgb:[178,10,28]}],picnic:[{index:0,rgb:[0,0,255]},{index:.1,rgb:[51,153,255]},{index:.2,rgb:[102,204,255]},{index:.3,rgb:[153,204,255]},{index:.4,rgb:[204,204,255]},{index:.5,rgb:[255,255,255]},{index:.6,rgb:[255,204,255]},{index:.7,rgb:[255,153,255]},{index:.8,rgb:[255,102,204]},{index:.9,rgb:[255,102,102]},{index:1,rgb:[255,0,0]}],rainbow:[{index:0,rgb:[150,0,90]},{index:.125,rgb:[0,0,200]},{index:.25,rgb:[0,25,255]},{index:.375,rgb:[0,152,255]},{index:.5,rgb:[44,255,150]},{index:.625,rgb:[151,255,0]},{index:.75,rgb:[255,234,0]},{index:.875,rgb:[255,111,0]},{index:1,rgb:[255,0,0]}],portland:[{index:0,rgb:[12,51,131]},{index:.25,rgb:[10,136,186]},{index:.5,rgb:[242,211,56]},{index:.75,rgb:[242,143,56]},{index:1,rgb:[217,30,30]}],blackbody:[{index:0,rgb:[0,0,0]},{index:.2,rgb:[230,0,0]},{index:.4,rgb:[230,210,0]},{index:.7,rgb:[255,255,255]},{index:1,rgb:[160,200,255]}],earth:[{index:0,rgb:[0,0,130]},{index:.1,rgb:[0,180,180]},{index:.2,rgb:[40,210,40]},{index:.4,rgb:[230,230,50]},{index:.6,rgb:[120,70,20]},{index:1,rgb:[255,255,255]}],electric:[{index:0,rgb:[0,0,0]},{index:.15,rgb:[30,0,100]},{index:.4,rgb:[120,0,100]},{index:.6,rgb:[160,90,0]},{index:.8,rgb:[230,200,0]},{index:1,rgb:[255,250,220]}],alpha:[{index:0,rgb:[255,255,255,0]},{index:1,rgb:[255,255,255,1]}],viridis:[{index:0,rgb:[68,1,84]},{index:.13,rgb:[71,44,122]},{index:.25,rgb:[59,81,139]},{index:.38,rgb:[44,113,142]},{index:.5,rgb:[33,144,141]},{index:.63,rgb:[39,173,129]},{index:.75,rgb:[92,200,99]},{index:.88,rgb:[170,220,50]},{index:1,rgb:[253,231,37]}],inferno:[{index:0,rgb:[0,0,4]},{index:.13,rgb:[31,12,72]},{index:.25,rgb:[85,15,109]},{index:.38,rgb:[136,34,106]},{index:.5,rgb:[186,54,85]},{index:.63,rgb:[227,89,51]},{index:.75,rgb:[249,140,10]},{index:.88,rgb:[249,201,50]},{index:1,rgb:[252,255,164]}],magma:[{index:0,rgb:[0,0,4]},{index:.13,rgb:[28,16,68]},{index:.25,rgb:[79,18,123]},{index:.38,rgb:[129,37,129]},{index:.5,rgb:[181,54,122]},{index:.63,rgb:[229,80,100]},{index:.75,rgb:[251,135,97]},{index:.88,rgb:[254,194,135]},{index:1,rgb:[252,253,191]}],plasma:[{index:0,rgb:[13,8,135]},{index:.13,rgb:[75,3,161]},{index:.25,rgb:[125,3,168]},{index:.38,rgb:[168,34,150]},{index:.5,rgb:[203,70,121]},{index:.63,rgb:[229,107,93]},{index:.75,rgb:[248,148,65]},{index:.88,rgb:[253,195,40]},{index:1,rgb:[240,249,33]}],warm:[{index:0,rgb:[125,0,179]},{index:.13,rgb:[172,0,187]},{index:.25,rgb:[219,0,170]},{index:.38,rgb:[255,0,130]},{index:.5,rgb:[255,63,74]},{index:.63,rgb:[255,123,0]},{index:.75,rgb:[234,176,0]},{index:.88,rgb:[190,228,0]},{index:1,rgb:[147,255,0]}],cool:[{index:0,rgb:[125,0,179]},{index:.13,rgb:[116,0,218]},{index:.25,rgb:[98,74,237]},{index:.38,rgb:[68,146,231]},{index:.5,rgb:[0,204,197]},{index:.63,rgb:[0,247,146]},{index:.75,rgb:[0,255,88]},{index:.88,rgb:[40,255,8]},{index:1,rgb:[147,255,0]}],"rainbow-soft":[{index:0,rgb:[125,0,179]},{index:.1,rgb:[199,0,180]},{index:.2,rgb:[255,0,121]},{index:.3,rgb:[255,108,0]},{index:.4,rgb:[222,194,0]},{index:.5,rgb:[150,255,0]},{index:.6,rgb:[0,255,55]},{index:.7,rgb:[0,246,150]},{index:.8,rgb:[50,167,222]},{index:.9,rgb:[103,51,235]},{index:1,rgb:[124,0,186]}],bathymetry:[{index:0,rgb:[40,26,44]},{index:.13,rgb:[59,49,90]},{index:.25,rgb:[64,76,139]},{index:.38,rgb:[63,110,151]},{index:.5,rgb:[72,142,158]},{index:.63,rgb:[85,174,163]},{index:.75,rgb:[120,206,163]},{index:.88,rgb:[187,230,172]},{index:1,rgb:[253,254,204]}],cdom:[{index:0,rgb:[47,15,62]},{index:.13,rgb:[87,23,86]},{index:.25,rgb:[130,28,99]},{index:.38,rgb:[171,41,96]},{index:.5,rgb:[206,67,86]},{index:.63,rgb:[230,106,84]},{index:.75,rgb:[242,149,103]},{index:.88,rgb:[249,193,135]},{index:1,rgb:[254,237,176]}],chlorophyll:[{index:0,rgb:[18,36,20]},{index:.13,rgb:[25,63,41]},{index:.25,rgb:[24,91,59]},{index:.38,rgb:[13,119,72]},{index:.5,rgb:[18,148,80]},{index:.63,rgb:[80,173,89]},{index:.75,rgb:[132,196,122]},{index:.88,rgb:[175,221,162]},{index:1,rgb:[215,249,208]}],density:[{index:0,rgb:[54,14,36]},{index:.13,rgb:[89,23,80]},{index:.25,rgb:[110,45,132]},{index:.38,rgb:[120,77,178]},{index:.5,rgb:[120,113,213]},{index:.63,rgb:[115,151,228]},{index:.75,rgb:[134,185,227]},{index:.88,rgb:[177,214,227]},{index:1,rgb:[230,241,241]}],"freesurface-blue":[{index:0,rgb:[30,4,110]},{index:.13,rgb:[47,14,176]},{index:.25,rgb:[41,45,236]},{index:.38,rgb:[25,99,212]},{index:.5,rgb:[68,131,200]},{index:.63,rgb:[114,156,197]},{index:.75,rgb:[157,181,203]},{index:.88,rgb:[200,208,216]},{index:1,rgb:[241,237,236]}],"freesurface-red":[{index:0,rgb:[60,9,18]},{index:.13,rgb:[100,17,27]},{index:.25,rgb:[142,20,29]},{index:.38,rgb:[177,43,27]},{index:.5,rgb:[192,87,63]},{index:.63,rgb:[205,125,105]},{index:.75,rgb:[216,162,148]},{index:.88,rgb:[227,199,193]},{index:1,rgb:[241,237,236]}],oxygen:[{index:0,rgb:[64,5,5]},{index:.13,rgb:[106,6,15]},{index:.25,rgb:[144,26,7]},{index:.38,rgb:[168,64,3]},{index:.5,rgb:[188,100,4]},{index:.63,rgb:[206,136,11]},{index:.75,rgb:[220,174,25]},{index:.88,rgb:[231,215,44]},{index:1,rgb:[248,254,105]}],par:[{index:0,rgb:[51,20,24]},{index:.13,rgb:[90,32,35]},{index:.25,rgb:[129,44,34]},{index:.38,rgb:[159,68,25]},{index:.5,rgb:[182,99,19]},{index:.63,rgb:[199,134,22]},{index:.75,rgb:[212,171,35]},{index:.88,rgb:[221,210,54]},{index:1,rgb:[225,253,75]}],phase:[{index:0,rgb:[145,105,18]},{index:.13,rgb:[184,71,38]},{index:.25,rgb:[186,58,115]},{index:.38,rgb:[160,71,185]},{index:.5,rgb:[110,97,218]},{index:.63,rgb:[50,123,164]},{index:.75,rgb:[31,131,110]},{index:.88,rgb:[77,129,34]},{index:1,rgb:[145,105,18]}],salinity:[{index:0,rgb:[42,24,108]},{index:.13,rgb:[33,50,162]},{index:.25,rgb:[15,90,145]},{index:.38,rgb:[40,118,137]},{index:.5,rgb:[59,146,135]},{index:.63,rgb:[79,175,126]},{index:.75,rgb:[120,203,104]},{index:.88,rgb:[193,221,100]},{index:1,rgb:[253,239,154]}],temperature:[{index:0,rgb:[4,35,51]},{index:.13,rgb:[23,51,122]},{index:.25,rgb:[85,59,157]},{index:.38,rgb:[129,79,143]},{index:.5,rgb:[175,95,130]},{index:.63,rgb:[222,112,101]},{index:.75,rgb:[249,146,66]},{index:.88,rgb:[249,196,65]},{index:1,rgb:[232,250,91]}],turbidity:[{index:0,rgb:[34,31,27]},{index:.13,rgb:[65,50,41]},{index:.25,rgb:[98,69,52]},{index:.38,rgb:[131,89,57]},{index:.5,rgb:[161,112,59]},{index:.63,rgb:[185,140,66]},{index:.75,rgb:[202,174,88]},{index:.88,rgb:[216,209,126]},{index:1,rgb:[233,246,171]}],"velocity-blue":[{index:0,rgb:[17,32,64]},{index:.13,rgb:[35,52,116]},{index:.25,rgb:[29,81,156]},{index:.38,rgb:[31,113,162]},{index:.5,rgb:[50,144,169]},{index:.63,rgb:[87,173,176]},{index:.75,rgb:[149,196,189]},{index:.88,rgb:[203,221,211]},{index:1,rgb:[254,251,230]}],"velocity-green":[{index:0,rgb:[23,35,19]},{index:.13,rgb:[24,64,38]},{index:.25,rgb:[11,95,45]},{index:.38,rgb:[39,123,35]},{index:.5,rgb:[95,146,12]},{index:.63,rgb:[152,165,18]},{index:.75,rgb:[201,186,69]},{index:.88,rgb:[233,216,137]},{index:1,rgb:[255,253,205]}],cubehelix:[{index:0,rgb:[0,0,0]},{index:.07,rgb:[22,5,59]},{index:.13,rgb:[60,4,105]},{index:.2,rgb:[109,1,135]},{index:.27,rgb:[161,0,147]},{index:.33,rgb:[210,2,142]},{index:.4,rgb:[251,11,123]},{index:.47,rgb:[255,29,97]},{index:.53,rgb:[255,54,69]},{index:.6,rgb:[255,85,46]},{index:.67,rgb:[255,120,34]},{index:.73,rgb:[255,157,37]},{index:.8,rgb:[241,191,57]},{index:.87,rgb:[224,220,93]},{index:.93,rgb:[218,241,142]},{index:1,rgb:[227,253,198]}]}},{}],67:[function(t,e,r){"use strict";var n=t("./colorScale"),i=t("lerp");function a(t){return[t[0]/255,t[1]/255,t[2]/255,t[3]]}function o(t){for(var e,r="#",n=0;n<3;++n)r+=("00"+(e=(e=t[n]).toString(16))).substr(e.length);return r}function s(t){return"rgba("+t.join(",")+")"}e.exports=function(t){var e,r,l,u,c,f,h,d,p,g;t||(t={});d=(t.nshades||72)-1,h=t.format||"hex",(f=t.colormap)||(f="jet");if("string"==typeof f){if(f=f.toLowerCase(),!n[f])throw Error(f+" not a supported colorscale");c=n[f]}else{if(!Array.isArray(f))throw Error("unsupported colormap option",f);c=f.slice()}if(c.length>d)throw new Error(f+" map requires nshades to be at least size "+c.length);p=Array.isArray(t.alpha)?2!==t.alpha.length?[1,1]:t.alpha.slice():"number"==typeof t.alpha?[t.alpha,t.alpha]:[1,1];e=c.map(function(t){return Math.round(t.index*d)}),p[0]=Math.min(Math.max(p[0],0),1),p[1]=Math.min(Math.max(p[1],0),1);var v=c.map(function(t,e){var r=c[e].index,n=c[e].rgb.slice();return 4===n.length&&n[3]>=0&&n[3]<=1?n:(n[3]=p[0]+(p[1]-p[0])*r,n)}),m=[];for(g=0;g0?-1:l(t,e,a)?-1:1:0===s?u>0?1:l(t,e,r)?1:-1:i(u-s)}var h=n(t,e,r);if(h>0)return o>0&&n(t,e,a)>0?1:-1;if(h<0)return o>0||n(t,e,a)>0?1:-1;var d=n(t,e,a);return d>0?1:l(t,e,r)?1:-1};var n=t("robust-orientation"),i=t("signum"),a=t("two-sum"),o=t("robust-product"),s=t("robust-sum");function l(t,e,r){var n=a(t[0],-e[0]),i=a(t[1],-e[1]),l=a(r[0],-e[0]),u=a(r[1],-e[1]),c=s(o(n,l),o(i,u));return c[c.length-1]>=0}},{"robust-orientation":301,"robust-product":302,"robust-sum":306,signum:307,"two-sum":327}],69:[function(t,e,r){e.exports=function(t,e){var r=t.length,a=t.length-e.length;if(a)return a;switch(r){case 0:return 0;case 1:return t[0]-e[0];case 2:return t[0]+t[1]-e[0]-e[1]||n(t[0],t[1])-n(e[0],e[1]);case 3:var o=t[0]+t[1],s=e[0]+e[1];if(a=o+t[2]-(s+e[2]))return a;var l=n(t[0],t[1]),u=n(e[0],e[1]);return n(l,t[2])-n(u,e[2])||n(l+t[2],o)-n(u+e[2],s);case 4:var c=t[0],f=t[1],h=t[2],d=t[3],p=e[0],g=e[1],v=e[2],m=e[3];return c+f+h+d-(p+g+v+m)||n(c,f,h,d)-n(p,g,v,m,p)||n(c+f,c+h,c+d,f+h,f+d,h+d)-n(p+g,p+v,p+m,g+v,g+m,v+m)||n(c+f+h,c+f+d,c+h+d,f+h+d)-n(p+g+v,p+g+m,p+v+m,g+v+m);default:for(var y=t.slice().sort(i),b=e.slice().sort(i),x=0;xt[r][0]&&(r=n);return er?[[r],[e]]:[[e]]}},{}],73:[function(t,e,r){"use strict";e.exports=function(t){var e=n(t),r=e.length;if(r<=2)return[];for(var i=new Array(r),a=e[r-1],o=0;o=e[l]&&(s+=1);a[o]=s}}return t}(o,r)}};var n=t("incremental-convex-hull"),i=t("affine-hull")},{"affine-hull":13,"incremental-convex-hull":234}],75:[function(t,e,r){"use strict";e.exports=function(t,e,r,n,i,a){var o=i-1,s=i*i,l=o*o,u=(1+2*i)*l,c=i*l,f=s*(3-2*i),h=s*o;if(t.length){a||(a=new Array(t.length));for(var d=t.length-1;d>=0;--d)a[d]=u*t[d]+c*e[d]+f*r[d]+h*n[d];return a}return u*t+c*e+f*r+h*n},e.exports.derivative=function(t,e,r,n,i,a){var o=6*i*i-6*i,s=3*i*i-4*i+1,l=-6*i*i+6*i,u=3*i*i-2*i;if(t.length){a||(a=new Array(t.length));for(var c=t.length-1;c>=0;--c)a[c]=o*t[c]+s*e[c]+l*r[c]+u*n[c];return a}return o*t+s*e+l*r[c]+u*n}},{}],76:[function(t,e,r){"use strict";var n=t("./lib/thunk.js");function i(){this.argTypes=[],this.shimArgs=[],this.arrayArgs=[],this.arrayBlockIndices=[],this.scalarArgs=[],this.offsetArgs=[],this.offsetArgIndex=[],this.indexArgs=[],this.shapeArgs=[],this.funcName="",this.pre=null,this.body=null,this.post=null,this.debug=!1}e.exports=function(t){var e=new i;e.pre=t.pre,e.body=t.body,e.post=t.post;var r=t.args.slice(0);e.argTypes=r;for(var a=0;a0)throw new Error("cwise: pre() block may not reference array args");if(a0)throw new Error("cwise: post() block may not reference array args")}else if("scalar"===o)e.scalarArgs.push(a),e.shimArgs.push("scalar"+a);else if("index"===o){if(e.indexArgs.push(a),a0)throw new Error("cwise: pre() block may not reference array index");if(a0)throw new Error("cwise: post() block may not reference array index")}else if("shape"===o){if(e.shapeArgs.push(a),ar.length)throw new Error("cwise: Too many arguments in pre() block");if(e.body.args.length>r.length)throw new Error("cwise: Too many arguments in body() block");if(e.post.args.length>r.length)throw new Error("cwise: Too many arguments in post() block");return e.debug=!!t.printCode||!!t.debug,e.funcName=t.funcName||"cwise",e.blockSize=t.blockSize||64,n(e)}},{"./lib/thunk.js":78}],77:[function(t,e,r){"use strict";var n=t("uniq");function i(t,e,r){var n,i,a=t.length,o=e.arrayArgs.length,s=e.indexArgs.length>0,l=[],u=[],c=0,f=0;for(n=0;n0&&l.push("var "+u.join(",")),n=a-1;n>=0;--n)c=t[n],l.push(["for(i",n,"=0;i",n,"0&&l.push(["index[",f,"]-=s",f].join("")),l.push(["++index[",c,"]"].join(""))),l.push("}")}return l.join("\n")}function a(t,e,r){for(var n=t.body,i=[],a=[],o=0;o0&&y.push("shape=SS.slice(0)"),t.indexArgs.length>0){var b=new Array(r);for(l=0;l0&&m.push("var "+y.join(",")),l=0;l3&&m.push(a(t.pre,t,s));var M=a(t.body,t,s),A=function(t){for(var e=0,r=t[0].length;e0,u=[],c=0;c0;){"].join("")),u.push(["if(j",c,"<",s,"){"].join("")),u.push(["s",e[c],"=j",c].join("")),u.push(["j",c,"=0"].join("")),u.push(["}else{s",e[c],"=",s].join("")),u.push(["j",c,"-=",s,"}"].join("")),l&&u.push(["index[",e[c],"]=j",c].join(""));for(c=0;c3&&m.push(a(t.post,t,s)),t.debug&&console.log("-----Generated cwise routine for ",e,":\n"+m.join("\n")+"\n----------");var T=[t.funcName||"unnamed","_cwise_loop_",o[0].join("s"),"m",A,function(t){for(var e=new Array(t.length),r=!0,n=0;n0&&(r=r&&e[n]===e[n-1])}return r?e[0]:e.join("")}(s)].join("");return new Function(["function ",T,"(",v.join(","),"){",m.join("\n"),"} return ",T].join(""))()}},{uniq:330}],78:[function(t,e,r){"use strict";var n=t("./compile.js");e.exports=function(t){var e=["'use strict'","var CACHED={}"],r=[],i=t.funcName+"_cwise_thunk";e.push(["return function ",i,"(",t.shimArgs.join(","),"){"].join(""));for(var a=[],o=[],s=[["array",t.arrayArgs[0],".shape.slice(",Math.max(0,t.arrayBlockIndices[0]),t.arrayBlockIndices[0]<0?","+t.arrayBlockIndices[0]+")":")"].join("")],l=[],u=[],c=0;c0&&(l.push("array"+t.arrayArgs[0]+".shape.length===array"+f+".shape.length+"+(Math.abs(t.arrayBlockIndices[0])-Math.abs(t.arrayBlockIndices[c]))),u.push("array"+t.arrayArgs[0]+".shape[shapeIndex+"+Math.max(0,t.arrayBlockIndices[0])+"]===array"+f+".shape[shapeIndex+"+Math.max(0,t.arrayBlockIndices[c])+"]"))}for(t.arrayArgs.length>1&&(e.push("if (!("+l.join(" && ")+")) throw new Error('cwise: Arrays do not all have the same dimensionality!')"),e.push("for(var shapeIndex=array"+t.arrayArgs[0]+".shape.length-"+Math.abs(t.arrayBlockIndices[0])+"; shapeIndex--\x3e0;) {"),e.push("if (!("+u.join(" && ")+")) throw new Error('cwise: Arrays do not all have the same shape!')"),e.push("}")),c=0;ce?1:t>=e?0:NaN}function d(t){return null===t?NaN:+t}function p(t){return!isNaN(t)}function g(t){return{left:function(e,r,n,i){for(arguments.length<3&&(n=0),arguments.length<4&&(i=e.length);n>>1;t(e[a],r)<0?n=a+1:i=a}return n},right:function(e,r,n,i){for(arguments.length<3&&(n=0),arguments.length<4&&(i=e.length);n>>1;t(e[a],r)>0?i=a:n=a+1}return n}}}t.ascending=h,t.descending=function(t,e){return et?1:e>=t?0:NaN},t.min=function(t,e){var r,n,i=-1,a=t.length;if(1===arguments.length){for(;++i=n){r=n;break}for(;++in&&(r=n)}else{for(;++i=n){r=n;break}for(;++in&&(r=n)}return r},t.max=function(t,e){var r,n,i=-1,a=t.length;if(1===arguments.length){for(;++i=n){r=n;break}for(;++ir&&(r=n)}else{for(;++i=n){r=n;break}for(;++ir&&(r=n)}return r},t.extent=function(t,e){var r,n,i,a=-1,o=t.length;if(1===arguments.length){for(;++a=n){r=i=n;break}for(;++an&&(r=n),i=n){r=i=n;break}for(;++an&&(r=n),i1)return o/(l-1)},t.deviation=function(){var e=t.variance.apply(this,arguments);return e?Math.sqrt(e):e};var v=g(h);function m(t){return t.length}t.bisectLeft=v.left,t.bisect=t.bisectRight=v.right,t.bisector=function(t){return g(1===t.length?function(e,r){return h(t(e),r)}:t)},t.shuffle=function(t,e,r){(a=arguments.length)<3&&(r=t.length,a<2&&(e=0));for(var n,i,a=r-e;a;)i=Math.random()*a--|0,n=t[a+e],t[a+e]=t[i+e],t[i+e]=n;return t},t.permute=function(t,e){for(var r=e.length,n=new Array(r);r--;)n[r]=t[e[r]];return n},t.pairs=function(t){for(var e=0,r=t.length-1,n=t[0],i=new Array(r<0?0:r);e=0;)for(e=(n=t[i]).length;--e>=0;)r[--o]=n[e];return r};var y=Math.abs;function b(t,e){for(var r in e)Object.defineProperty(t.prototype,r,{value:e[r],enumerable:!1})}function x(){this._=Object.create(null)}t.range=function(t,e,r){if(arguments.length<3&&(r=1,arguments.length<2&&(e=t,t=0)),(e-t)/r==1/0)throw new Error("infinite range");var n,i=[],a=function(t){var e=1;for(;t*e%1;)e*=10;return e}(y(r)),o=-1;if(t*=a,e*=a,(r*=a)<0)for(;(n=t+r*++o)>e;)i.push(n/a);else for(;(n=t+r*++o)=i.length)return r?r.call(n,a):e?a.sort(e):a;for(var l,u,c,f,h=-1,d=a.length,p=i[s++],g=new x;++h=i.length)return e;var n=[],o=a[r++];return e.forEach(function(e,i){n.push({key:e,values:t(i,r)})}),o?n.sort(function(t,e){return o(t.key,e.key)}):n}(o(t.map,e,0),0)},n.key=function(t){return i.push(t),n},n.sortKeys=function(t){return a[i.length-1]=t,n},n.sortValues=function(t){return e=t,n},n.rollup=function(t){return r=t,n},n},t.set=function(t){var e=new C;if(t)for(var r=0,n=t.length;r=0&&(n=t.slice(r+1),t=t.slice(0,r)),t)return arguments.length<2?this[t].on(n):this[t].on(n,e);if(2===arguments.length){if(null==e)for(t in this)this.hasOwnProperty(t)&&this[t].on(n,null);return this}},t.event=null,t.requote=function(t){return t.replace(U,"\\$&")};var U=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,V={}.__proto__?function(t,e){t.__proto__=e}:function(t,e){for(var r in e)t[r]=e[r]};function H(t){return V(t,W),t}var q=function(t,e){return e.querySelector(t)},G=function(t,e){return e.querySelectorAll(t)},X=function(t,e){var r=t.matches||t[R(t,"matchesSelector")];return(X=function(t,e){return r.call(t,e)})(t,e)};"function"==typeof Sizzle&&(q=function(t,e){return Sizzle(t,e)[0]||null},G=Sizzle,X=Sizzle.matchesSelector),t.selection=function(){return t.select(i.documentElement)};var W=t.selection.prototype=[];function Y(t){return"function"==typeof t?t:function(){return q(t,this)}}function Z(t){return"function"==typeof t?t:function(){return G(t,this)}}W.select=function(t){var e,r,n,i,a=[];t=Y(t);for(var o=-1,s=this.length;++o=0&&"xmlns"!==(r=t.slice(0,e))&&(t=t.slice(e+1)),J.hasOwnProperty(r)?{space:J[r],local:t}:t}},W.attr=function(e,r){if(arguments.length<2){if("string"==typeof e){var n=this.node();return(e=t.ns.qualify(e)).local?n.getAttributeNS(e.space,e.local):n.getAttribute(e)}for(r in e)this.each(K(r,e[r]));return this}return this.each(K(e,r))},W.classed=function(t,e){if(arguments.length<2){if("string"==typeof t){var r=this.node(),n=(t=et(t)).length,i=-1;if(e=r.classList){for(;++i=0;)(r=n[i])&&(a&&a!==r.nextSibling&&a.parentNode.insertBefore(r,a),a=r);return this},W.sort=function(t){t=function(t){arguments.length||(t=h);return function(e,r){return e&&r?t(e.__data__,r.__data__):!e-!r}}.apply(this,arguments);for(var e=-1,r=this.length;++e0&&(e=e.slice(0,o));var l=pt.get(e);function u(){var t=this[a];t&&(this.removeEventListener(e,t,t.$),delete this[a])}return l&&(e=l,s=vt),o?r?function(){var t=s(r,n(arguments));u.call(this),this.addEventListener(e,this[a]=t,t.$=i),t._=r}:u:r?N:function(){var r,n=new RegExp("^__on([^.]+)"+t.requote(e)+"$");for(var i in this)if(r=i.match(n)){var a=this[i];this.removeEventListener(r[1],a,a.$),delete this[i]}}}t.selection.enter=ft,t.selection.enter.prototype=ht,ht.append=W.append,ht.empty=W.empty,ht.node=W.node,ht.call=W.call,ht.size=W.size,ht.select=function(t){for(var e,r,n,i,a,o=[],s=-1,l=this.length;++s=n&&(n=e+1);!(o=s[n])&&++n0?1:t<0?-1:0}function Ot(t,e,r){return(e[0]-t[0])*(r[1]-t[1])-(e[1]-t[1])*(r[0]-t[0])}function Rt(t){return t>1?0:t<-1?Tt:Math.acos(t)}function It(t){return t>1?St:t<-1?-St:Math.asin(t)}function Nt(t){return((t=Math.exp(t))+1/t)/2}function zt(t){return(t=Math.sin(t/2))*t}var Dt=Math.SQRT2;t.interpolateZoom=function(t,e){var r,n,i=t[0],a=t[1],o=t[2],s=e[0],l=e[1],u=e[2],c=s-i,f=l-a,h=c*c+f*f;if(h0&&(e=e.transition().duration(g)),e.call(w.event)}function E(){u&&u.domain(l.range().map(function(t){return(t-h.x)/h.k}).map(l.invert)),f&&f.domain(c.range().map(function(t){return(t-h.y)/h.k}).map(c.invert))}function S(t){v++||t({type:"zoomstart"})}function L(t){E(),t({type:"zoom",scale:h.k,translate:[h.x,h.y]})}function C(t){--v||(t({type:"zoomend"}),r=null)}function P(){var e=this,r=_.of(e,arguments),n=0,i=t.select(o(e)).on(y,function(){n=1,T(t.mouse(e),a),L(r)}).on(b,function(){i.on(y,null).on(b,null),s(n),C(r)}),a=M(t.mouse(e)),s=bt(e);fs.call(e),S(r)}function O(){var e,r=this,n=_.of(r,arguments),i={},a=0,o=".zoom-"+t.event.changedTouches[0].identifier,l="touchmove"+o,u="touchend"+o,c=[],f=t.select(r),d=bt(r);function p(){var n=t.touches(r);return e=h.k,n.forEach(function(t){t.identifier in i&&(i[t.identifier]=M(t))}),n}function g(){var e=t.event.target;t.select(e).on(l,v).on(u,y),c.push(e);for(var n=t.event.changedTouches,o=0,f=n.length;o1){m=d[0];var b=d[1],x=m[0]-b[0],_=m[1]-b[1];a=x*x+_*_}}function v(){var o,l,u,c,f=t.touches(r);fs.call(r);for(var h=0,d=f.length;h360?t-=360:t<0&&(t+=360),t<60?n+(i-n)*t/60:t<180?i:t<240?n+(i-n)*(240-t)/60:n}(t))}return t=isNaN(t)?0:(t%=360)<0?t+360:t,e=isNaN(e)?0:e<0?0:e>1?1:e,n=2*(r=r<0?0:r>1?1:r)-(i=r<=.5?r*(1+e):r+e-r*e),new ae(a(t+120),a(t),a(t-120))}function Gt(e,r,n){return this instanceof Gt?(this.h=+e,this.c=+r,void(this.l=+n)):arguments.length<2?e instanceof Gt?new Gt(e.h,e.c,e.l):ee(e instanceof Yt?e.l:(e=he((e=t.rgb(e)).r,e.g,e.b)).l,e.a,e.b):new Gt(e,r,n)}Ht.brighter=function(t){return t=Math.pow(.7,arguments.length?t:1),new Vt(this.h,this.s,this.l/t)},Ht.darker=function(t){return t=Math.pow(.7,arguments.length?t:1),new Vt(this.h,this.s,t*this.l)},Ht.rgb=function(){return qt(this.h,this.s,this.l)},t.hcl=Gt;var Xt=Gt.prototype=new Ut;function Wt(t,e,r){return isNaN(t)&&(t=0),isNaN(e)&&(e=0),new Yt(r,Math.cos(t*=Lt)*e,Math.sin(t)*e)}function Yt(t,e,r){return this instanceof Yt?(this.l=+t,this.a=+e,void(this.b=+r)):arguments.length<2?t instanceof Yt?new Yt(t.l,t.a,t.b):t instanceof Gt?Wt(t.h,t.c,t.l):he((t=ae(t)).r,t.g,t.b):new Yt(t,e,r)}Xt.brighter=function(t){return new Gt(this.h,this.c,Math.min(100,this.l+Zt*(arguments.length?t:1)))},Xt.darker=function(t){return new Gt(this.h,this.c,Math.max(0,this.l-Zt*(arguments.length?t:1)))},Xt.rgb=function(){return Wt(this.h,this.c,this.l).rgb()},t.lab=Yt;var Zt=18,Qt=.95047,Jt=1,Kt=1.08883,$t=Yt.prototype=new Ut;function te(t,e,r){var n=(t+16)/116,i=n+e/500,a=n-r/200;return new ae(ie(3.2404542*(i=re(i)*Qt)-1.5371385*(n=re(n)*Jt)-.4985314*(a=re(a)*Kt)),ie(-.969266*i+1.8760108*n+.041556*a),ie(.0556434*i-.2040259*n+1.0572252*a))}function ee(t,e,r){return t>0?new Gt(Math.atan2(r,e)*Ct,Math.sqrt(e*e+r*r),t):new Gt(NaN,NaN,t)}function re(t){return t>.206893034?t*t*t:(t-4/29)/7.787037}function ne(t){return t>.008856?Math.pow(t,1/3):7.787037*t+4/29}function ie(t){return Math.round(255*(t<=.00304?12.92*t:1.055*Math.pow(t,1/2.4)-.055))}function ae(t,e,r){return this instanceof ae?(this.r=~~t,this.g=~~e,void(this.b=~~r)):arguments.length<2?t instanceof ae?new ae(t.r,t.g,t.b):ce(""+t,ae,qt):new ae(t,e,r)}function oe(t){return new ae(t>>16,t>>8&255,255&t)}function se(t){return oe(t)+""}$t.brighter=function(t){return new Yt(Math.min(100,this.l+Zt*(arguments.length?t:1)),this.a,this.b)},$t.darker=function(t){return new Yt(Math.max(0,this.l-Zt*(arguments.length?t:1)),this.a,this.b)},$t.rgb=function(){return te(this.l,this.a,this.b)},t.rgb=ae;var le=ae.prototype=new Ut;function ue(t){return t<16?"0"+Math.max(0,t).toString(16):Math.min(255,t).toString(16)}function ce(t,e,r){var n,i,a,o=0,s=0,l=0;if(n=/([a-z]+)\((.*)\)/.exec(t=t.toLowerCase()))switch(i=n[2].split(","),n[1]){case"hsl":return r(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return e(pe(i[0]),pe(i[1]),pe(i[2]))}return(a=ge.get(t))?e(a.r,a.g,a.b):(null==t||"#"!==t.charAt(0)||isNaN(a=parseInt(t.slice(1),16))||(4===t.length?(o=(3840&a)>>4,o|=o>>4,s=240&a,s|=s>>4,l=15&a,l|=l<<4):7===t.length&&(o=(16711680&a)>>16,s=(65280&a)>>8,l=255&a)),e(o,s,l))}function fe(t,e,r){var n,i,a=Math.min(t/=255,e/=255,r/=255),o=Math.max(t,e,r),s=o-a,l=(o+a)/2;return s?(i=l<.5?s/(o+a):s/(2-o-a),n=t==o?(e-r)/s+(e0&&l<1?0:n),new Vt(n,i,l)}function he(t,e,r){var n=ne((.4124564*(t=de(t))+.3575761*(e=de(e))+.1804375*(r=de(r)))/Qt),i=ne((.2126729*t+.7151522*e+.072175*r)/Jt);return Yt(116*i-16,500*(n-i),200*(i-ne((.0193339*t+.119192*e+.9503041*r)/Kt)))}function de(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function pe(t){var e=parseFloat(t);return"%"===t.charAt(t.length-1)?Math.round(2.55*e):e}le.brighter=function(t){t=Math.pow(.7,arguments.length?t:1);var e=this.r,r=this.g,n=this.b,i=30;return e||r||n?(e&&e=200&&e<300||304===e){try{t=i.call(o,u)}catch(t){return void s.error.call(o,t)}s.load.call(o,t)}else s.error.call(o,u)}return!this.XDomainRequest||"withCredentials"in u||!/^(http(s)?:)?\/\//.test(e)||(u=new XDomainRequest),"onload"in u?u.onload=u.onerror=f:u.onreadystatechange=function(){u.readyState>3&&f()},u.onprogress=function(e){var r=t.event;t.event=e;try{s.progress.call(o,u)}finally{t.event=r}},o.header=function(t,e){return t=(t+"").toLowerCase(),arguments.length<2?l[t]:(null==e?delete l[t]:l[t]=e+"",o)},o.mimeType=function(t){return arguments.length?(r=null==t?null:t+"",o):r},o.responseType=function(t){return arguments.length?(c=t,o):c},o.response=function(t){return i=t,o},["get","post"].forEach(function(t){o[t]=function(){return o.send.apply(o,[t].concat(n(arguments)))}}),o.send=function(t,n,i){if(2===arguments.length&&"function"==typeof n&&(i=n,n=null),u.open(t,e,!0),null==r||"accept"in l||(l.accept=r+",*/*"),u.setRequestHeader)for(var a in l)u.setRequestHeader(a,l[a]);return null!=r&&u.overrideMimeType&&u.overrideMimeType(r),null!=c&&(u.responseType=c),null!=i&&o.on("error",i).on("load",function(t){i(null,t)}),s.beforesend.call(o,u),u.send(null==n?null:n),o},o.abort=function(){return u.abort(),o},t.rebind(o,s,"on"),null==a?o:o.get(function(t){return 1===t.length?function(e,r){t(null==e?r:null)}:t}(a))}ge.forEach(function(t,e){ge.set(t,oe(e))}),t.functor=ve,t.xhr=me(P),t.dsv=function(t,e){var r=new RegExp('["'+t+"\n]"),n=t.charCodeAt(0);function i(t,r,n){arguments.length<3&&(n=r,r=null);var i=ye(t,e,null==r?a:o(r),n);return i.row=function(t){return arguments.length?i.response(null==(r=t)?a:o(t)):r},i}function a(t){return i.parse(t.responseText)}function o(t){return function(e){return i.parse(e.responseText,t)}}function s(e){return e.map(l).join(t)}function l(t){return r.test(t)?'"'+t.replace(/\"/g,'""')+'"':t}return i.parse=function(t,e){var r;return i.parseRows(t,function(t,n){if(r)return r(t,n-1);var i=new Function("d","return {"+t.map(function(t,e){return JSON.stringify(t)+": d["+e+"]"}).join(",")+"}");r=e?function(t,r){return e(i(t),r)}:i})},i.parseRows=function(t,e){var r,i,a={},o={},s=[],l=t.length,u=0,c=0;function f(){if(u>=l)return o;if(i)return i=!1,a;var e=u;if(34===t.charCodeAt(e)){for(var r=e;r++24?(isFinite(e)&&(clearTimeout(we),we=setTimeout(Te,e)),_e=0):(_e=1,Me(Te))}function ke(){for(var t=Date.now(),e=be;e;)t>=e.t&&e.c(t-e.t)&&(e.c=null),e=e.n;return t}function Ee(){for(var t,e=be,r=1/0;e;)e.c?(e.t8?function(t){return t/r}:function(t){return t*r},symbol:t}});t.formatPrefix=function(e,r){var n=0;return(e=+e)&&(e<0&&(e*=-1),r&&(e=t.round(e,Se(e,r))),n=1+Math.floor(1e-12+Math.log(e)/Math.LN10),n=Math.max(-24,Math.min(24,3*Math.floor((n-1)/3)))),Le[8+n/3]};var Ce=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,Pe=t.map({b:function(t){return t.toString(2)},c:function(t){return String.fromCharCode(t)},o:function(t){return t.toString(8)},x:function(t){return t.toString(16)},X:function(t){return t.toString(16).toUpperCase()},g:function(t,e){return t.toPrecision(e)},e:function(t,e){return t.toExponential(e)},f:function(t,e){return t.toFixed(e)},r:function(e,r){return(e=t.round(e,Se(e,r))).toFixed(Math.max(0,Math.min(20,Se(e*(1+1e-15),r))))}});function Oe(t){return t+""}var Re=t.time={},Ie=Date;function Ne(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}Ne.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){ze.setUTCDate.apply(this._,arguments)},setDay:function(){ze.setUTCDay.apply(this._,arguments)},setFullYear:function(){ze.setUTCFullYear.apply(this._,arguments)},setHours:function(){ze.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){ze.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){ze.setUTCMinutes.apply(this._,arguments)},setMonth:function(){ze.setUTCMonth.apply(this._,arguments)},setSeconds:function(){ze.setUTCSeconds.apply(this._,arguments)},setTime:function(){ze.setTime.apply(this._,arguments)}};var ze=Date.prototype;function De(t,e,r){function n(e){var r=t(e),n=a(r,1);return e-r1)for(;o68?1900:2e3),r+i[0].length):-1}function Qe(t,e,r){return/^[+-]\d{4}$/.test(e=e.slice(r,r+5))?(t.Z=-e,r+5):-1}function Je(t,e,r){Be.lastIndex=0;var n=Be.exec(e.slice(r,r+2));return n?(t.m=n[0]-1,r+n[0].length):-1}function Ke(t,e,r){Be.lastIndex=0;var n=Be.exec(e.slice(r,r+2));return n?(t.d=+n[0],r+n[0].length):-1}function $e(t,e,r){Be.lastIndex=0;var n=Be.exec(e.slice(r,r+3));return n?(t.j=+n[0],r+n[0].length):-1}function tr(t,e,r){Be.lastIndex=0;var n=Be.exec(e.slice(r,r+2));return n?(t.H=+n[0],r+n[0].length):-1}function er(t,e,r){Be.lastIndex=0;var n=Be.exec(e.slice(r,r+2));return n?(t.M=+n[0],r+n[0].length):-1}function rr(t,e,r){Be.lastIndex=0;var n=Be.exec(e.slice(r,r+2));return n?(t.S=+n[0],r+n[0].length):-1}function nr(t,e,r){Be.lastIndex=0;var n=Be.exec(e.slice(r,r+3));return n?(t.L=+n[0],r+n[0].length):-1}function ir(t){var e=t.getTimezoneOffset(),r=e>0?"-":"+",n=y(e)/60|0,i=y(e)%60;return r+Ve(n,"0",2)+Ve(i,"0",2)}function ar(t,e,r){Ue.lastIndex=0;var n=Ue.exec(e.slice(r,r+1));return n?r+n[0].length:-1}function or(t){for(var e=t.length,r=-1;++r0&&s>0&&(l+s+1>e&&(s=Math.max(1,e-l)),a.push(t.substring(r-=s,r+s)),!((l+=s+1)>e));)s=i[o=(o+1)%i.length];return a.reverse().join(n)}:P;return function(e){var n=Ce.exec(e),i=n[1]||" ",s=n[2]||">",l=n[3]||"-",u=n[4]||"",c=n[5],f=+n[6],h=n[7],d=n[8],p=n[9],g=1,v="",m="",y=!1,b=!0;switch(d&&(d=+d.substring(1)),(c||"0"===i&&"="===s)&&(c=i="0",s="="),p){case"n":h=!0,p="g";break;case"%":g=100,m="%",p="f";break;case"p":g=100,m="%",p="r";break;case"b":case"o":case"x":case"X":"#"===u&&(v="0"+p.toLowerCase());case"c":b=!1;case"d":y=!0,d=0;break;case"s":g=-1,p="r"}"$"===u&&(v=a[0],m=a[1]),"r"!=p||d||(p="g"),null!=d&&("g"==p?d=Math.max(1,Math.min(21,d)):"e"!=p&&"f"!=p||(d=Math.max(0,Math.min(20,d)))),p=Pe.get(p)||Oe;var x=c&&h;return function(e){var n=m;if(y&&e%1)return"";var a=e<0||0===e&&1/e<0?(e=-e,"-"):"-"===l?"":l;if(g<0){var u=t.formatPrefix(e,d);e=u.scale(e),n=u.symbol+m}else e*=g;var _,w,M=(e=p(e,d)).lastIndexOf(".");if(M<0){var A=b?e.lastIndexOf("e"):-1;A<0?(_=e,w=""):(_=e.substring(0,A),w=e.substring(A))}else _=e.substring(0,M),w=r+e.substring(M+1);!c&&h&&(_=o(_,1/0));var T=v.length+_.length+w.length+(x?0:a.length),k=T"===s?k+a+e:"^"===s?k.substring(0,T>>=1)+a+e+k.substring(T):a+(x?e:k+e))+n}}}(e),timeFormat:function(e){var r=e.dateTime,n=e.date,i=e.time,a=e.periods,o=e.days,s=e.shortDays,l=e.months,u=e.shortMonths;function c(t){var e=t.length;function r(r){for(var n,i,a,o=[],s=-1,l=0;++s=u)return-1;if(37===(i=e.charCodeAt(s++))){if(o=e.charAt(s++),!(a=w[o in je?e.charAt(s++):o])||(n=a(t,r,n))<0)return-1}else if(i!=r.charCodeAt(n++))return-1}return n}c.utc=function(t){var e=c(t);function r(t){try{var r=new(Ie=Ne);return r._=t,e(r)}finally{Ie=Date}}return r.parse=function(t){try{Ie=Ne;var r=e.parse(t);return r&&r._}finally{Ie=Date}},r.toString=e.toString,r},c.multi=c.utc.multi=or;var h=t.map(),d=He(o),p=qe(o),g=He(s),v=qe(s),m=He(l),y=qe(l),b=He(u),x=qe(u);a.forEach(function(t,e){h.set(t.toLowerCase(),e)});var _={a:function(t){return s[t.getDay()]},A:function(t){return o[t.getDay()]},b:function(t){return u[t.getMonth()]},B:function(t){return l[t.getMonth()]},c:c(r),d:function(t,e){return Ve(t.getDate(),e,2)},e:function(t,e){return Ve(t.getDate(),e,2)},H:function(t,e){return Ve(t.getHours(),e,2)},I:function(t,e){return Ve(t.getHours()%12||12,e,2)},j:function(t,e){return Ve(1+Re.dayOfYear(t),e,3)},L:function(t,e){return Ve(t.getMilliseconds(),e,3)},m:function(t,e){return Ve(t.getMonth()+1,e,2)},M:function(t,e){return Ve(t.getMinutes(),e,2)},p:function(t){return a[+(t.getHours()>=12)]},S:function(t,e){return Ve(t.getSeconds(),e,2)},U:function(t,e){return Ve(Re.sundayOfYear(t),e,2)},w:function(t){return t.getDay()},W:function(t,e){return Ve(Re.mondayOfYear(t),e,2)},x:c(n),X:c(i),y:function(t,e){return Ve(t.getFullYear()%100,e,2)},Y:function(t,e){return Ve(t.getFullYear()%1e4,e,4)},Z:ir,"%":function(){return"%"}},w={a:function(t,e,r){g.lastIndex=0;var n=g.exec(e.slice(r));return n?(t.w=v.get(n[0].toLowerCase()),r+n[0].length):-1},A:function(t,e,r){d.lastIndex=0;var n=d.exec(e.slice(r));return n?(t.w=p.get(n[0].toLowerCase()),r+n[0].length):-1},b:function(t,e,r){b.lastIndex=0;var n=b.exec(e.slice(r));return n?(t.m=x.get(n[0].toLowerCase()),r+n[0].length):-1},B:function(t,e,r){m.lastIndex=0;var n=m.exec(e.slice(r));return n?(t.m=y.get(n[0].toLowerCase()),r+n[0].length):-1},c:function(t,e,r){return f(t,_.c.toString(),e,r)},d:Ke,e:Ke,H:tr,I:tr,j:$e,L:nr,m:Je,M:er,p:function(t,e,r){var n=h.get(e.slice(r,r+=2).toLowerCase());return null==n?-1:(t.p=n,r)},S:rr,U:Xe,w:Ge,W:We,x:function(t,e,r){return f(t,_.x.toString(),e,r)},X:function(t,e,r){return f(t,_.X.toString(),e,r)},y:Ze,Y:Ye,Z:Qe,"%":ar};return c}(e)}};var sr=t.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});function lr(){}t.format=sr.numberFormat,t.geo={},lr.prototype={s:0,t:0,add:function(t){cr(t,this.t,ur),cr(ur.s,this.s,this),this.s?this.t+=ur.t:this.s=ur.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var ur=new lr;function cr(t,e,r){var n=r.s=t+e,i=n-t,a=n-i;r.t=t-a+(e-i)}function fr(t,e){t&&dr.hasOwnProperty(t.type)&&dr[t.type](t,e)}t.geo.stream=function(t,e){t&&hr.hasOwnProperty(t.type)?hr[t.type](t,e):fr(t,e)};var hr={Feature:function(t,e){fr(t.geometry,e)},FeatureCollection:function(t,e){for(var r=t.features,n=-1,i=r.length;++n=0?1:-1,s=o*a,l=Math.cos(e),u=Math.sin(e),c=i*u,f=n*l+c*Math.cos(s),h=c*o*Math.sin(s);Sr.add(Math.atan2(h,f)),r=t,n=l,i=u}Lr.point=function(o,s){Lr.point=a,r=(t=o)*Lt,n=Math.cos(s=(e=s)*Lt/2+Tt/4),i=Math.sin(s)},Lr.lineEnd=function(){a(t,e)}}function Pr(t){var e=t[0],r=t[1],n=Math.cos(r);return[n*Math.cos(e),n*Math.sin(e),Math.sin(r)]}function Or(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function Rr(t,e){return[t[1]*e[2]-t[2]*e[1],t[2]*e[0]-t[0]*e[2],t[0]*e[1]-t[1]*e[0]]}function Ir(t,e){t[0]+=e[0],t[1]+=e[1],t[2]+=e[2]}function Nr(t,e){return[t[0]*e,t[1]*e,t[2]*e]}function zr(t){var e=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=e,t[1]/=e,t[2]/=e}function Dr(t){return[Math.atan2(t[1],t[0]),It(t[2])]}function Fr(t,e){return y(t[0]-e[0])Mt?i=90:u<-Mt&&(r=-90),f[0]=e,f[1]=n}};function d(t,a){c.push(f=[e=t,n=t]),ai&&(i=a)}function p(t,o){var s=Pr([t*Lt,o*Lt]);if(l){var u=Rr(l,s),c=Rr([u[1],-u[0],0],u);zr(c),c=Dr(c);var f=t-a,h=f>0?1:-1,p=c[0]*Ct*h,g=y(f)>180;if(g^(h*ai&&(i=v);else if(g^(h*a<(p=(p+360)%360-180)&&pi&&(i=o);g?t_(e,n)&&(n=t):_(t,n)>_(e,n)&&(e=t):n>=e?(tn&&(n=t)):t>a?_(e,t)>_(e,n)&&(n=t):_(t,n)>_(e,n)&&(e=t)}else d(t,o);l=s,a=t}function g(){h.point=p}function v(){f[0]=e,f[1]=n,h.point=d,l=null}function m(t,e){if(l){var r=t-a;u+=y(r)>180?r+(r>0?360:-360):r}else o=t,s=e;Lr.point(t,e),p(t,e)}function b(){Lr.lineStart()}function x(){m(o,s),Lr.lineEnd(),y(u)>Mt&&(e=-(n=180)),f[0]=e,f[1]=n,l=null}function _(t,e){return(e-=t)<0?e+360:e}function w(t,e){return t[0]-e[0]}function M(t,e){return e[0]<=e[1]?e[0]<=t&&t<=e[1]:t_(g[0],g[1])&&(g[1]=d[1]),_(d[0],g[1])>_(g[0],g[1])&&(g[0]=d[0])):s.push(g=d);for(var l,u,d,p=-1/0,g=(o=0,s[u=s.length-1]);o<=u;g=d,++o)d=s[o],(l=_(g[1],d[0]))>p&&(p=l,e=d[0],n=g[1])}return c=f=null,e===1/0||r===1/0?[[NaN,NaN],[NaN,NaN]]:[[e,r],[n,i]]}}(),t.geo.centroid=function(e){mr=yr=br=xr=_r=wr=Mr=Ar=Tr=kr=Er=0,t.geo.stream(e,jr);var r=Tr,n=kr,i=Er,a=r*r+n*n+i*i;return a=0;--s)i.point((f=c[s])[0],f[1]);else n(d.x,d.p.x,-1,i);d=d.p}c=(d=d.o).z,p=!p}while(!d.v);i.lineEnd()}}}function Yr(t){if(e=t.length){for(var e,r,n=0,i=t[0];++n=0?1:-1,M=w*_,A=M>Tt,T=p*b;if(Sr.add(Math.atan2(T*w*Math.sin(M),g*x+T*Math.cos(M))),a+=A?_+w*kt:_,A^h>=r^m>=r){var k=Rr(Pr(f),Pr(t));zr(k);var E=Rr(i,k);zr(E);var S=(A^_>=0?-1:1)*It(E[2]);(n>S||n===S&&(k[0]||k[1]))&&(o+=A^_>=0?1:-1)}if(!v++)break;h=m,p=b,g=x,f=t}}return(a<-Mt||a0){for(b||(o.polygonStart(),b=!0),o.lineStart();++a1&&2&e&&r.push(r.pop().concat(r.shift())),s.push(r.filter(Jr))}return c}}function Jr(t){return t.length>1}function Kr(){var t,e=[];return{lineStart:function(){e.push(t=[])},point:function(e,r){t.push([e,r])},lineEnd:N,buffer:function(){var r=e;return e=[],t=null,r},rejoin:function(){e.length>1&&e.push(e.pop().concat(e.shift()))}}}function $r(t,e){return((t=t.x)[0]<0?t[1]-St-Mt:St-t[1])-((e=e.x)[0]<0?e[1]-St-Mt:St-e[1])}var tn=Qr(Xr,function(t){var e,r=NaN,n=NaN,i=NaN;return{lineStart:function(){t.lineStart(),e=1},point:function(a,o){var s=a>0?Tt:-Tt,l=y(a-r);y(l-Tt)0?St:-St),t.point(i,n),t.lineEnd(),t.lineStart(),t.point(s,n),t.point(a,n),e=0):i!==s&&l>=Tt&&(y(r-i)Mt?Math.atan((Math.sin(e)*(a=Math.cos(n))*Math.sin(r)-Math.sin(n)*(i=Math.cos(e))*Math.sin(t))/(i*a*o)):(e+n)/2}(r,n,a,o),t.point(i,n),t.lineEnd(),t.lineStart(),t.point(s,n),e=0),t.point(r=a,n=o),i=s},lineEnd:function(){t.lineEnd(),r=n=NaN},clean:function(){return 2-e}}},function(t,e,r,n){var i;if(null==t)i=r*St,n.point(-Tt,i),n.point(0,i),n.point(Tt,i),n.point(Tt,0),n.point(Tt,-i),n.point(0,-i),n.point(-Tt,-i),n.point(-Tt,0),n.point(-Tt,i);else if(y(t[0]-e[0])>Mt){var a=t[0]0)){if(a/=h,h<0){if(a0){if(a>f)return;a>c&&(c=a)}if(a=r-l,h||!(a<0)){if(a/=h,h<0){if(a>f)return;a>c&&(c=a)}else if(h>0){if(a0)){if(a/=d,d<0){if(a0){if(a>f)return;a>c&&(c=a)}if(a=n-u,d||!(a<0)){if(a/=d,d<0){if(a>f)return;a>c&&(c=a)}else if(d>0){if(a0&&(i.a={x:l+c*h,y:u+c*d}),f<1&&(i.b={x:l+f*h,y:u+f*d}),i}}}}}}var rn=1e9;function nn(e,r,n,i){return function(l){var u,c,f,h,d,p,g,v,m,y,b,x=l,_=Kr(),w=en(e,r,n,i),M={point:k,lineStart:function(){M.point=E,c&&c.push(f=[]);y=!0,m=!1,g=v=NaN},lineEnd:function(){u&&(E(h,d),p&&m&&_.rejoin(),u.push(_.buffer()));M.point=k,m&&l.lineEnd()},polygonStart:function(){l=_,u=[],c=[],b=!0},polygonEnd:function(){l=x,u=t.merge(u);var r=function(t){for(var e=0,r=c.length,n=t[1],i=0;in&&Ot(u,a,t)>0&&++e:a[1]<=n&&Ot(u,a,t)<0&&--e,u=a;return 0!==e}([e,i]),n=b&&r,a=u.length;(n||a)&&(l.polygonStart(),n&&(l.lineStart(),A(null,null,1,l),l.lineEnd()),a&&Wr(u,o,r,A,l),l.polygonEnd()),u=c=f=null}};function A(t,o,l,u){var c=0,f=0;if(null==t||(c=a(t,l))!==(f=a(o,l))||s(t,o)<0^l>0)do{u.point(0===c||3===c?e:n,c>1?i:r)}while((c=(c+l+4)%4)!==f);else u.point(o[0],o[1])}function T(t,a){return e<=t&&t<=n&&r<=a&&a<=i}function k(t,e){T(t,e)&&l.point(t,e)}function E(t,e){var r=T(t=Math.max(-rn,Math.min(rn,t)),e=Math.max(-rn,Math.min(rn,e)));if(c&&f.push([t,e]),y)h=t,d=e,p=r,y=!1,r&&(l.lineStart(),l.point(t,e));else if(r&&m)l.point(t,e);else{var n={a:{x:g,y:v},b:{x:t,y:e}};w(n)?(m||(l.lineStart(),l.point(n.a.x,n.a.y)),l.point(n.b.x,n.b.y),r||l.lineEnd(),b=!1):r&&(l.lineStart(),l.point(t,e),b=!1)}g=t,v=e,m=r}return M};function a(t,i){return y(t[0]-e)0?0:3:y(t[0]-n)0?2:1:y(t[1]-r)0?1:0:i>0?3:2}function o(t,e){return s(t.x,e.x)}function s(t,e){var r=a(t,1),n=a(e,1);return r!==n?r-n:0===r?e[1]-t[1]:1===r?t[0]-e[0]:2===r?t[1]-e[1]:e[0]-t[0]}}function an(t){var e=0,r=Tt/3,n=Ln(t),i=n(e,r);return i.parallels=function(t){return arguments.length?n(e=t[0]*Tt/180,r=t[1]*Tt/180):[e/Tt*180,r/Tt*180]},i}function on(t,e){var r=Math.sin(t),n=(r+Math.sin(e))/2,i=1+r*(2*n-r),a=Math.sqrt(i)/n;function o(t,e){var r=Math.sqrt(i-2*n*Math.sin(e))/n;return[r*Math.sin(t*=n),a-r*Math.cos(t)]}return o.invert=function(t,e){var r=a-e;return[Math.atan2(t,r)/n,It((i-(t*t+r*r)*n*n)/(2*n))]},o}t.geo.clipExtent=function(){var t,e,r,n,i,a,o={stream:function(t){return i&&(i.valid=!1),(i=a(t)).valid=!0,i},extent:function(s){return arguments.length?(a=nn(t=+s[0][0],e=+s[0][1],r=+s[1][0],n=+s[1][1]),i&&(i.valid=!1,i=null),o):[[t,e],[r,n]]}};return o.extent([[0,0],[960,500]])},(t.geo.conicEqualArea=function(){return an(on)}).raw=on,t.geo.albers=function(){return t.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},t.geo.albersUsa=function(){var e,r,n,i,a=t.geo.albers(),o=t.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),s=t.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(t,r){e=[t,r]}};function u(t){var a=t[0],o=t[1];return e=null,r(a,o),e||(n(a,o),e)||i(a,o),e}return u.invert=function(t){var e=a.scale(),r=a.translate(),n=(t[0]-r[0])/e,i=(t[1]-r[1])/e;return(i>=.12&&i<.234&&n>=-.425&&n<-.214?o:i>=.166&&i<.234&&n>=-.214&&n<-.115?s:a).invert(t)},u.stream=function(t){var e=a.stream(t),r=o.stream(t),n=s.stream(t);return{point:function(t,i){e.point(t,i),r.point(t,i),n.point(t,i)},sphere:function(){e.sphere(),r.sphere(),n.sphere()},lineStart:function(){e.lineStart(),r.lineStart(),n.lineStart()},lineEnd:function(){e.lineEnd(),r.lineEnd(),n.lineEnd()},polygonStart:function(){e.polygonStart(),r.polygonStart(),n.polygonStart()},polygonEnd:function(){e.polygonEnd(),r.polygonEnd(),n.polygonEnd()}}},u.precision=function(t){return arguments.length?(a.precision(t),o.precision(t),s.precision(t),u):a.precision()},u.scale=function(t){return arguments.length?(a.scale(t),o.scale(.35*t),s.scale(t),u.translate(a.translate())):a.scale()},u.translate=function(t){if(!arguments.length)return a.translate();var e=a.scale(),c=+t[0],f=+t[1];return r=a.translate(t).clipExtent([[c-.455*e,f-.238*e],[c+.455*e,f+.238*e]]).stream(l).point,n=o.translate([c-.307*e,f+.201*e]).clipExtent([[c-.425*e+Mt,f+.12*e+Mt],[c-.214*e-Mt,f+.234*e-Mt]]).stream(l).point,i=s.translate([c-.205*e,f+.212*e]).clipExtent([[c-.214*e+Mt,f+.166*e+Mt],[c-.115*e-Mt,f+.234*e-Mt]]).stream(l).point,u},u.scale(1070)};var sn,ln,un,cn,fn,hn,dn={point:N,lineStart:N,lineEnd:N,polygonStart:function(){ln=0,dn.lineStart=pn},polygonEnd:function(){dn.lineStart=dn.lineEnd=dn.point=N,sn+=y(ln/2)}};function pn(){var t,e,r,n;function i(t,e){ln+=n*t-r*e,r=t,n=e}dn.point=function(a,o){dn.point=i,t=r=a,e=n=o},dn.lineEnd=function(){i(t,e)}}var gn={point:function(t,e){tfn&&(fn=t);ehn&&(hn=e)},lineStart:N,lineEnd:N,polygonStart:N,polygonEnd:N};function vn(){var t=mn(4.5),e=[],r={point:n,lineStart:function(){r.point=i},lineEnd:o,polygonStart:function(){r.lineEnd=s},polygonEnd:function(){r.lineEnd=o,r.point=n},pointRadius:function(e){return t=mn(e),r},result:function(){if(e.length){var t=e.join("");return e=[],t}}};function n(r,n){e.push("M",r,",",n,t)}function i(t,n){e.push("M",t,",",n),r.point=a}function a(t,r){e.push("L",t,",",r)}function o(){r.point=n}function s(){e.push("Z")}return r}function mn(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}var yn,bn={point:xn,lineStart:_n,lineEnd:wn,polygonStart:function(){bn.lineStart=Mn},polygonEnd:function(){bn.point=xn,bn.lineStart=_n,bn.lineEnd=wn}};function xn(t,e){br+=t,xr+=e,++_r}function _n(){var t,e;function r(r,n){var i=r-t,a=n-e,o=Math.sqrt(i*i+a*a);wr+=o*(t+r)/2,Mr+=o*(e+n)/2,Ar+=o,xn(t=r,e=n)}bn.point=function(n,i){bn.point=r,xn(t=n,e=i)}}function wn(){bn.point=xn}function Mn(){var t,e,r,n;function i(t,e){var i=t-r,a=e-n,o=Math.sqrt(i*i+a*a);wr+=o*(r+t)/2,Mr+=o*(n+e)/2,Ar+=o,Tr+=(o=n*t-r*e)*(r+t),kr+=o*(n+e),Er+=3*o,xn(r=t,n=e)}bn.point=function(a,o){bn.point=i,xn(t=r=a,e=n=o)},bn.lineEnd=function(){i(t,e)}}function An(t){var e=4.5,r={point:n,lineStart:function(){r.point=i},lineEnd:o,polygonStart:function(){r.lineEnd=s},polygonEnd:function(){r.lineEnd=o,r.point=n},pointRadius:function(t){return e=t,r},result:N};function n(r,n){t.moveTo(r+e,n),t.arc(r,n,e,0,kt)}function i(e,n){t.moveTo(e,n),r.point=a}function a(e,r){t.lineTo(e,r)}function o(){r.point=n}function s(){t.closePath()}return r}function Tn(t){var e=.5,r=Math.cos(30*Lt),n=16;function i(e){return(n?function(e){var r,i,o,s,l,u,c,f,h,d,p,g,v={point:m,lineStart:y,lineEnd:x,polygonStart:function(){e.polygonStart(),v.lineStart=_},polygonEnd:function(){e.polygonEnd(),v.lineStart=y}};function m(r,n){r=t(r,n),e.point(r[0],r[1])}function y(){f=NaN,v.point=b,e.lineStart()}function b(r,i){var o=Pr([r,i]),s=t(r,i);a(f,h,c,d,p,g,f=s[0],h=s[1],c=r,d=o[0],p=o[1],g=o[2],n,e),e.point(f,h)}function x(){v.point=m,e.lineEnd()}function _(){y(),v.point=w,v.lineEnd=M}function w(t,e){b(r=t,e),i=f,o=h,s=d,l=p,u=g,v.point=b}function M(){a(f,h,c,d,p,g,i,o,r,s,l,u,n,e),v.lineEnd=x,x()}return v}:function(e){return En(e,function(r,n){r=t(r,n),e.point(r[0],r[1])})})(e)}function a(n,i,o,s,l,u,c,f,h,d,p,g,v,m){var b=c-n,x=f-i,_=b*b+x*x;if(_>4*e&&v--){var w=s+d,M=l+p,A=u+g,T=Math.sqrt(w*w+M*M+A*A),k=Math.asin(A/=T),E=y(y(A)-1)e||y((b*P+x*O)/_-.5)>.3||s*d+l*p+u*g0&&16,i):Math.sqrt(e)},i}function kn(t){this.stream=t}function En(t,e){return{point:e,sphere:function(){t.sphere()},lineStart:function(){t.lineStart()},lineEnd:function(){t.lineEnd()},polygonStart:function(){t.polygonStart()},polygonEnd:function(){t.polygonEnd()}}}function Sn(t){return Ln(function(){return t})()}function Ln(e){var r,n,i,a,o,s,l=Tn(function(t,e){return[(t=r(t,e))[0]*u+a,o-t[1]*u]}),u=150,c=480,f=250,h=0,d=0,p=0,g=0,v=0,m=tn,b=P,x=null,_=null;function w(t){return[(t=i(t[0]*Lt,t[1]*Lt))[0]*u+a,o-t[1]*u]}function M(t){return(t=i.invert((t[0]-a)/u,(o-t[1])/u))&&[t[0]*Ct,t[1]*Ct]}function A(){i=Gr(n=Rn(p,g,v),r);var t=r(h,d);return a=c-t[0]*u,o=f+t[1]*u,T()}function T(){return s&&(s.valid=!1,s=null),w}return w.stream=function(t){return s&&(s.valid=!1),(s=Cn(m(n,l(b(t))))).valid=!0,s},w.clipAngle=function(t){return arguments.length?(m=null==t?(x=t,tn):function(t){var e=Math.cos(t),r=e>0,n=y(e)>Mt;return Qr(i,function(t){var e,s,l,u,c;return{lineStart:function(){u=l=!1,c=1},point:function(f,h){var d,p=[f,h],g=i(f,h),v=r?g?0:o(f,h):g?o(f+(f<0?Tt:-Tt),h):0;if(!e&&(u=l=g)&&t.lineStart(),g!==l&&(d=a(e,p),(Fr(e,d)||Fr(p,d))&&(p[0]+=Mt,p[1]+=Mt,g=i(p[0],p[1]))),g!==l)c=0,g?(t.lineStart(),d=a(p,e),t.point(d[0],d[1])):(d=a(e,p),t.point(d[0],d[1]),t.lineEnd()),e=d;else if(n&&e&&r^g){var m;v&s||!(m=a(p,e,!0))||(c=0,r?(t.lineStart(),t.point(m[0][0],m[0][1]),t.point(m[1][0],m[1][1]),t.lineEnd()):(t.point(m[1][0],m[1][1]),t.lineEnd(),t.lineStart(),t.point(m[0][0],m[0][1])))}!g||e&&Fr(e,p)||t.point(p[0],p[1]),e=p,l=g,s=v},lineEnd:function(){l&&t.lineEnd(),e=null},clean:function(){return c|(u&&l)<<1}}},Dn(t,6*Lt),r?[0,-t]:[-Tt,t-Tt]);function i(t,r){return Math.cos(t)*Math.cos(r)>e}function a(t,r,n){var i=[1,0,0],a=Rr(Pr(t),Pr(r)),o=Or(a,a),s=a[0],l=o-s*s;if(!l)return!n&&t;var u=e*o/l,c=-e*s/l,f=Rr(i,a),h=Nr(i,u);Ir(h,Nr(a,c));var d=f,p=Or(h,d),g=Or(d,d),v=p*p-g*(Or(h,h)-1);if(!(v<0)){var m=Math.sqrt(v),b=Nr(d,(-p-m)/g);if(Ir(b,h),b=Dr(b),!n)return b;var x,_=t[0],w=r[0],M=t[1],A=r[1];w<_&&(x=_,_=w,w=x);var T=w-_,k=y(T-Tt)0^b[1]<(y(b[0]-_)Tt^(_<=b[0]&&b[0]<=w)){var E=Nr(d,(-p+m)/g);return Ir(E,h),[b,Dr(E)]}}}function o(e,n){var i=r?t:Tt-t,a=0;return e<-i?a|=1:e>i&&(a|=2),n<-i?a|=4:n>i&&(a|=8),a}}((x=+t)*Lt),T()):x},w.clipExtent=function(t){return arguments.length?(_=t,b=t?nn(t[0][0],t[0][1],t[1][0],t[1][1]):P,T()):_},w.scale=function(t){return arguments.length?(u=+t,A()):u},w.translate=function(t){return arguments.length?(c=+t[0],f=+t[1],A()):[c,f]},w.center=function(t){return arguments.length?(h=t[0]%360*Lt,d=t[1]%360*Lt,A()):[h*Ct,d*Ct]},w.rotate=function(t){return arguments.length?(p=t[0]%360*Lt,g=t[1]%360*Lt,v=t.length>2?t[2]%360*Lt:0,A()):[p*Ct,g*Ct,v*Ct]},t.rebind(w,l,"precision"),function(){return r=e.apply(this,arguments),w.invert=r.invert&&M,A()}}function Cn(t){return En(t,function(e,r){t.point(e*Lt,r*Lt)})}function Pn(t,e){return[t,e]}function On(t,e){return[t>Tt?t-kt:t<-Tt?t+kt:t,e]}function Rn(t,e,r){return t?e||r?Gr(Nn(t),zn(e,r)):Nn(t):e||r?zn(e,r):On}function In(t){return function(e,r){return[(e+=t)>Tt?e-kt:e<-Tt?e+kt:e,r]}}function Nn(t){var e=In(t);return e.invert=In(-t),e}function zn(t,e){var r=Math.cos(t),n=Math.sin(t),i=Math.cos(e),a=Math.sin(e);function o(t,e){var o=Math.cos(e),s=Math.cos(t)*o,l=Math.sin(t)*o,u=Math.sin(e),c=u*r+s*n;return[Math.atan2(l*i-c*a,s*r-u*n),It(c*i+l*a)]}return o.invert=function(t,e){var o=Math.cos(e),s=Math.cos(t)*o,l=Math.sin(t)*o,u=Math.sin(e),c=u*i-l*a;return[Math.atan2(l*i+u*a,s*r+c*n),It(c*r-s*n)]},o}function Dn(t,e){var r=Math.cos(t),n=Math.sin(t);return function(i,a,o,s){var l=o*e;null!=i?(i=Fn(r,i),a=Fn(r,a),(o>0?ia)&&(i+=o*kt)):(i=t+o*kt,a=t-.5*l);for(var u,c=i;o>0?c>a:c2?t[2]*Lt:0),e.invert=function(e){return(e=t.invert(e[0]*Lt,e[1]*Lt))[0]*=Ct,e[1]*=Ct,e},e},On.invert=Pn,t.geo.circle=function(){var t,e,r=[0,0],n=6;function i(){var t="function"==typeof r?r.apply(this,arguments):r,n=Rn(-t[0]*Lt,-t[1]*Lt,0).invert,i=[];return e(null,null,1,{point:function(t,e){i.push(t=n(t,e)),t[0]*=Ct,t[1]*=Ct}}),{type:"Polygon",coordinates:[i]}}return i.origin=function(t){return arguments.length?(r=t,i):r},i.angle=function(r){return arguments.length?(e=Dn((t=+r)*Lt,n*Lt),i):t},i.precision=function(r){return arguments.length?(e=Dn(t*Lt,(n=+r)*Lt),i):n},i.angle(90)},t.geo.distance=function(t,e){var r,n=(e[0]-t[0])*Lt,i=t[1]*Lt,a=e[1]*Lt,o=Math.sin(n),s=Math.cos(n),l=Math.sin(i),u=Math.cos(i),c=Math.sin(a),f=Math.cos(a);return Math.atan2(Math.sqrt((r=f*o)*r+(r=u*c-l*f*s)*r),l*c+u*f*s)},t.geo.graticule=function(){var e,r,n,i,a,o,s,l,u,c,f,h,d=10,p=d,g=90,v=360,m=2.5;function b(){return{type:"MultiLineString",coordinates:x()}}function x(){return t.range(Math.ceil(i/g)*g,n,g).map(f).concat(t.range(Math.ceil(l/v)*v,s,v).map(h)).concat(t.range(Math.ceil(r/d)*d,e,d).filter(function(t){return y(t%g)>Mt}).map(u)).concat(t.range(Math.ceil(o/p)*p,a,p).filter(function(t){return y(t%v)>Mt}).map(c))}return b.lines=function(){return x().map(function(t){return{type:"LineString",coordinates:t}})},b.outline=function(){return{type:"Polygon",coordinates:[f(i).concat(h(s).slice(1),f(n).reverse().slice(1),h(l).reverse().slice(1))]}},b.extent=function(t){return arguments.length?b.majorExtent(t).minorExtent(t):b.minorExtent()},b.majorExtent=function(t){return arguments.length?(i=+t[0][0],n=+t[1][0],l=+t[0][1],s=+t[1][1],i>n&&(t=i,i=n,n=t),l>s&&(t=l,l=s,s=t),b.precision(m)):[[i,l],[n,s]]},b.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],o=+t[0][1],a=+t[1][1],r>e&&(t=r,r=e,e=t),o>a&&(t=o,o=a,a=t),b.precision(m)):[[r,o],[e,a]]},b.step=function(t){return arguments.length?b.majorStep(t).minorStep(t):b.minorStep()},b.majorStep=function(t){return arguments.length?(g=+t[0],v=+t[1],b):[g,v]},b.minorStep=function(t){return arguments.length?(d=+t[0],p=+t[1],b):[d,p]},b.precision=function(t){return arguments.length?(m=+t,u=jn(o,a,90),c=Bn(r,e,m),f=jn(l,s,90),h=Bn(i,n,m),b):m},b.majorExtent([[-180,-90+Mt],[180,90-Mt]]).minorExtent([[-180,-80-Mt],[180,80+Mt]])},t.geo.greatArc=function(){var e,r,n=Un,i=Vn;function a(){return{type:"LineString",coordinates:[e||n.apply(this,arguments),r||i.apply(this,arguments)]}}return a.distance=function(){return t.geo.distance(e||n.apply(this,arguments),r||i.apply(this,arguments))},a.source=function(t){return arguments.length?(n=t,e="function"==typeof t?null:t,a):n},a.target=function(t){return arguments.length?(i=t,r="function"==typeof t?null:t,a):i},a.precision=function(){return arguments.length?a:0},a},t.geo.interpolate=function(t,e){return r=t[0]*Lt,n=t[1]*Lt,i=e[0]*Lt,a=e[1]*Lt,o=Math.cos(n),s=Math.sin(n),l=Math.cos(a),u=Math.sin(a),c=o*Math.cos(r),f=o*Math.sin(r),h=l*Math.cos(i),d=l*Math.sin(i),p=2*Math.asin(Math.sqrt(zt(a-n)+o*l*zt(i-r))),g=1/Math.sin(p),(v=p?function(t){var e=Math.sin(t*=p)*g,r=Math.sin(p-t)*g,n=r*c+e*h,i=r*f+e*d,a=r*s+e*u;return[Math.atan2(i,n)*Ct,Math.atan2(a,Math.sqrt(n*n+i*i))*Ct]}:function(){return[r*Ct,n*Ct]}).distance=p,v;var r,n,i,a,o,s,l,u,c,f,h,d,p,g,v},t.geo.length=function(e){return yn=0,t.geo.stream(e,Hn),yn};var Hn={sphere:N,point:N,lineStart:function(){var t,e,r;function n(n,i){var a=Math.sin(i*=Lt),o=Math.cos(i),s=y((n*=Lt)-t),l=Math.cos(s);yn+=Math.atan2(Math.sqrt((s=o*Math.sin(s))*s+(s=r*a-e*o*l)*s),e*a+r*o*l),t=n,e=a,r=o}Hn.point=function(i,a){t=i*Lt,e=Math.sin(a*=Lt),r=Math.cos(a),Hn.point=n},Hn.lineEnd=function(){Hn.point=Hn.lineEnd=N}},lineEnd:N,polygonStart:N,polygonEnd:N};function qn(t,e){function r(e,r){var n=Math.cos(e),i=Math.cos(r),a=t(n*i);return[a*i*Math.sin(e),a*Math.sin(r)]}return r.invert=function(t,r){var n=Math.sqrt(t*t+r*r),i=e(n),a=Math.sin(i),o=Math.cos(i);return[Math.atan2(t*a,n*o),Math.asin(n&&r*a/n)]},r}var Gn=qn(function(t){return Math.sqrt(2/(1+t))},function(t){return 2*Math.asin(t/2)});(t.geo.azimuthalEqualArea=function(){return Sn(Gn)}).raw=Gn;var Xn=qn(function(t){var e=Math.acos(t);return e&&e/Math.sin(e)},P);function Wn(t,e){var r=Math.cos(t),n=function(t){return Math.tan(Tt/4+t/2)},i=t===e?Math.sin(t):Math.log(r/Math.cos(e))/Math.log(n(e)/n(t)),a=r*Math.pow(n(t),i)/i;if(!i)return Qn;function o(t,e){a>0?e<-St+Mt&&(e=-St+Mt):e>St-Mt&&(e=St-Mt);var r=a/Math.pow(n(e),i);return[r*Math.sin(i*t),a-r*Math.cos(i*t)]}return o.invert=function(t,e){var r=a-e,n=Pt(i)*Math.sqrt(t*t+r*r);return[Math.atan2(t,r)/i,2*Math.atan(Math.pow(a/n,1/i))-St]},o}function Yn(t,e){var r=Math.cos(t),n=t===e?Math.sin(t):(r-Math.cos(e))/(e-t),i=r/n+t;if(y(n)1&&Ot(t[r[n-2]],t[r[n-1]],t[i])<=0;)--n;r[n++]=i}return r.slice(0,n)}function ii(t,e){return t[0]-e[0]||t[1]-e[1]}(t.geo.stereographic=function(){return Sn($n)}).raw=$n,ti.invert=function(t,e){return[-e,2*Math.atan(Math.exp(t))-St]},(t.geo.transverseMercator=function(){var t=Jn(ti),e=t.center,r=t.rotate;return t.center=function(t){return t?e([-t[1],t[0]]):[(t=e())[1],-t[0]]},t.rotate=function(t){return t?r([t[0],t[1],t.length>2?t[2]+90:90]):[(t=r())[0],t[1],t[2]-90]},r([0,0,90])}).raw=ti,t.geom={},t.geom.hull=function(t){var e=ei,r=ri;if(arguments.length)return n(t);function n(t){if(t.length<3)return[];var n,i=ve(e),a=ve(r),o=t.length,s=[],l=[];for(n=0;n=0;--n)d.push(t[s[u[n]][2]]);for(n=+f;nMt)s=s.L;else{if(!((i=a-wi(s,o))>Mt)){n>-Mt?(e=s.P,r=s):i>-Mt?(e=s,r=s.N):e=r=s;break}if(!s.R){e=s;break}s=s.R}var l=mi(t);if(fi.insert(e,l),e||r){if(e===r)return Ei(e),r=mi(e.site),fi.insert(l,r),l.edge=r.edge=Ci(e.site,l.site),ki(e),void ki(r);if(r){Ei(e),Ei(r);var u=e.site,c=u.x,f=u.y,h=t.x-c,d=t.y-f,p=r.site,g=p.x-c,v=p.y-f,m=2*(h*v-d*g),y=h*h+d*d,b=g*g+v*v,x={x:(v*y-d*b)/m+c,y:(h*b-g*y)/m+f};Pi(r.edge,u,p,x),l.edge=Ci(u,t,null,x),r.edge=Ci(t,p,null,x),ki(e),ki(r)}else l.edge=Ci(e.site,l.site)}}function _i(t,e){var r=t.site,n=r.x,i=r.y,a=i-e;if(!a)return n;var o=t.P;if(!o)return-1/0;var s=(r=o.site).x,l=r.y,u=l-e;if(!u)return s;var c=s-n,f=1/a-1/u,h=c/u;return f?(-h+Math.sqrt(h*h-2*f*(c*c/(-2*u)-l+u/2+i-a/2)))/f+n:(n+s)/2}function wi(t,e){var r=t.N;if(r)return _i(r,e);var n=t.site;return n.y===e?n.x:1/0}function Mi(t){this.site=t,this.edges=[]}function Ai(t,e){return e.angle-t.angle}function Ti(){Ii(this),this.x=this.y=this.arc=this.site=this.cy=null}function ki(t){var e=t.P,r=t.N;if(e&&r){var n=e.site,i=t.site,a=r.site;if(n!==a){var o=i.x,s=i.y,l=n.x-o,u=n.y-s,c=a.x-o,f=2*(l*(v=a.y-s)-u*c);if(!(f>=-At)){var h=l*l+u*u,d=c*c+v*v,p=(v*h-u*d)/f,g=(l*d-c*h)/f,v=g+s,m=gi.pop()||new Ti;m.arc=t,m.site=i,m.x=p+o,m.y=v+Math.sqrt(p*p+g*g),m.cy=v,t.circle=m;for(var y=null,b=di._;b;)if(m.y=s)return;if(h>p){if(a){if(a.y>=u)return}else a={x:v,y:l};r={x:v,y:u}}else{if(a){if(a.y1)if(h>p){if(a){if(a.y>=u)return}else a={x:(l-i)/n,y:l};r={x:(u-i)/n,y:u}}else{if(a){if(a.y=s)return}else a={x:o,y:n*o+i};r={x:s,y:n*s+i}}else{if(a){if(a.xMt||y(i-r)>Mt)&&(s.splice(o,0,new Oi((m=a.site,b=c,x=y(n-f)Mt?{x:f,y:y(e-f)Mt?{x:y(r-p)Mt?{x:h,y:y(e-h)Mt?{x:y(r-d)=r&&u.x<=i&&u.y>=n&&u.y<=o?[[r,o],[i,o],[i,n],[r,n]]:[]).point=t[s]}),e}function s(t){return t.map(function(t,e){return{x:Math.round(n(t,e)/Mt)*Mt,y:Math.round(i(t,e)/Mt)*Mt,i:e}})}return o.links=function(t){return Fi(s(t)).edges.filter(function(t){return t.l&&t.r}).map(function(e){return{source:t[e.l.i],target:t[e.r.i]}})},o.triangles=function(t){var e=[];return Fi(s(t)).cells.forEach(function(r,n){for(var i,a,o,s,l=r.site,u=r.edges.sort(Ai),c=-1,f=u.length,h=u[f-1].edge,d=h.l===l?h.r:h.l;++ca&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(r=r[0])===(n=n[0])?s[o]?s[o]+=n:s[++o]=n:(s[++o]=null,l.push({i:o,x:Gi(r,n)})),a=Yi.lastIndex;return ag&&(g=l.x),l.y>v&&(v=l.y),u.push(l.x),c.push(l.y);else for(f=0;fg&&(g=x),_>v&&(v=_),u.push(x),c.push(_)}var w=g-d,M=v-p;function A(t,e,r,n,i,a,o,s){if(!isNaN(r)&&!isNaN(n))if(t.leaf){var l=t.x,u=t.y;if(null!=l)if(y(l-r)+y(u-n)<.01)T(t,e,r,n,i,a,o,s);else{var c=t.point;t.x=t.y=t.point=null,T(t,c,l,u,i,a,o,s),T(t,e,r,n,i,a,o,s)}else t.x=r,t.y=n,t.point=e}else T(t,e,r,n,i,a,o,s)}function T(t,e,r,n,i,a,o,s){var l=.5*(i+o),u=.5*(a+s),c=r>=l,f=n>=u,h=f<<1|c;t.leaf=!1,c?i=l:o=l,f?a=u:s=u,A(t=t.nodes[h]||(t.nodes[h]={leaf:!0,nodes:[],point:null,x:null,y:null,add:function(t){A(k,t,+m(t,++f),+b(t,f),d,p,g,v)}}),e,r,n,i,a,o,s)}w>M?v=p+w:g=d+M;var k={leaf:!0,nodes:[],point:null,x:null,y:null,add:function(t){A(k,t,+m(t,++f),+b(t,f),d,p,g,v)}};if(k.visit=function(t){!function t(e,r,n,i,a,o){if(!e(r,n,i,a,o)){var s=.5*(n+a),l=.5*(i+o),u=r.nodes;u[0]&&t(e,u[0],n,i,s,l),u[1]&&t(e,u[1],s,i,a,l),u[2]&&t(e,u[2],n,l,s,o),u[3]&&t(e,u[3],s,l,a,o)}}(t,k,d,p,g,v)},k.find=function(t){return function(t,e,r,n,i,a,o){var s,l=1/0;return function t(u,c,f,h,d){if(!(c>a||f>o||h=_)<<1|e>=x,M=w+4;w=0&&!(n=t.interpolators[i](e,r)););return n}function Qi(t,e){var r,n=[],i=[],a=t.length,o=e.length,s=Math.min(t.length,e.length);for(r=0;r=1)return 1;var e=t*t,r=e*t;return 4*(t<.5?r:3*(t-e)+r-.75)}function aa(t){return 1-Math.cos(t*St)}function oa(t){return Math.pow(2,10*(t-1))}function sa(t){return 1-Math.sqrt(1-t*t)}function la(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}function ua(t,e){return e-=t,function(r){return Math.round(t+e*r)}}function ca(t){var e,r,n,i=[t.a,t.b],a=[t.c,t.d],o=ha(i),s=fa(i,a),l=ha(((e=a)[0]+=(n=-s)*(r=i)[0],e[1]+=n*r[1],e))||0;i[0]*a[1]=0?t.slice(0,n):t,a=n>=0?t.slice(n+1):"in";return i=Ki.get(i)||Ji,a=$i.get(a)||P,e=a(i.apply(null,r.call(arguments,1))),function(t){return t<=0?0:t>=1?1:e(t)}},t.interpolateHcl=function(e,r){e=t.hcl(e),r=t.hcl(r);var n=e.h,i=e.c,a=e.l,o=r.h-n,s=r.c-i,l=r.l-a;isNaN(s)&&(s=0,i=isNaN(i)?r.c:i);isNaN(o)?(o=0,n=isNaN(n)?r.h:n):o>180?o-=360:o<-180&&(o+=360);return function(t){return Wt(n+o*t,i+s*t,a+l*t)+""}},t.interpolateHsl=function(e,r){e=t.hsl(e),r=t.hsl(r);var n=e.h,i=e.s,a=e.l,o=r.h-n,s=r.s-i,l=r.l-a;isNaN(s)&&(s=0,i=isNaN(i)?r.s:i);isNaN(o)?(o=0,n=isNaN(n)?r.h:n):o>180?o-=360:o<-180&&(o+=360);return function(t){return qt(n+o*t,i+s*t,a+l*t)+""}},t.interpolateLab=function(e,r){e=t.lab(e),r=t.lab(r);var n=e.l,i=e.a,a=e.b,o=r.l-n,s=r.a-i,l=r.b-a;return function(t){return te(n+o*t,i+s*t,a+l*t)+""}},t.interpolateRound=ua,t.transform=function(e){var r=i.createElementNS(t.ns.prefix.svg,"g");return(t.transform=function(t){if(null!=t){r.setAttribute("transform",t);var e=r.transform.baseVal.consolidate()}return new ca(e?e.matrix:da)})(e)},ca.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var da={a:1,b:0,c:0,d:1,e:0,f:0};function pa(t){return t.length?t.pop()+",":""}function ga(e,r){var n=[],i=[];return e=t.transform(e),r=t.transform(r),function(t,e,r,n){if(t[0]!==e[0]||t[1]!==e[1]){var i=r.push("translate(",null,",",null,")");n.push({i:i-4,x:Gi(t[0],e[0])},{i:i-2,x:Gi(t[1],e[1])})}else(e[0]||e[1])&&r.push("translate("+e+")")}(e.translate,r.translate,n,i),function(t,e,r,n){t!==e?(t-e>180?e+=360:e-t>180&&(t+=360),n.push({i:r.push(pa(r)+"rotate(",null,")")-2,x:Gi(t,e)})):e&&r.push(pa(r)+"rotate("+e+")")}(e.rotate,r.rotate,n,i),function(t,e,r,n){t!==e?n.push({i:r.push(pa(r)+"skewX(",null,")")-2,x:Gi(t,e)}):e&&r.push(pa(r)+"skewX("+e+")")}(e.skew,r.skew,n,i),function(t,e,r,n){if(t[0]!==e[0]||t[1]!==e[1]){var i=r.push(pa(r)+"scale(",null,",",null,")");n.push({i:i-4,x:Gi(t[0],e[0])},{i:i-2,x:Gi(t[1],e[1])})}else 1===e[0]&&1===e[1]||r.push(pa(r)+"scale("+e+")")}(e.scale,r.scale,n,i),e=r=null,function(t){for(var e,r=-1,a=i.length;++r0?n=t:(e.c=null,e.t=NaN,e=null,l.end({type:"end",alpha:n=0})):t>0&&(l.start({type:"start",alpha:n=t}),e=Ae(s.tick)),s):n},s.start=function(){var t,e,r,n=m.length,l=y.length,c=u[0],p=u[1];for(t=0;t=0;)r.push(i[n])}function La(t,e){for(var r=[t],n=[];null!=(t=r.pop());)if(n.push(t),(a=t.children)&&(i=a.length))for(var i,a,o=-1;++o=0;)o.push(c=u[l]),c.parent=a,c.depth=a.depth+1;r&&(a.value=0),a.children=u}else r&&(a.value=+r.call(n,a,a.depth)||0),delete a.children;return La(i,function(e){var n,i;t&&(n=e.children)&&n.sort(t),r&&(i=e.parent)&&(i.value+=e.value)}),s}return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(Sa(t,function(t){t.children&&(t.value=0)}),La(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},t.layout.partition=function(){var e=t.layout.hierarchy(),r=[1,1];function n(t,n){var i=e.call(this,t,n);return function t(e,r,n,i){var a=e.children;if(e.x=r,e.y=e.depth*i,e.dx=n,e.dy=i,a&&(o=a.length)){var o,s,l,u=-1;for(n=e.value?n/e.value:0;++us&&(s=n),o.push(n)}for(r=0;ri&&(n=r,i=e);return n}function Ha(t){return t.reduce(qa,0)}function qa(t,e){return t+e[1]}function Ga(t,e){return Xa(t,Math.ceil(Math.log(e.length)/Math.LN2+1))}function Xa(t,e){for(var r=-1,n=+t[0],i=(t[1]-n)/e,a=[];++r<=e;)a[r]=i*r+n;return a}function Wa(e){return[t.min(e),t.max(e)]}function Ya(t,e){return t.value-e.value}function Za(t,e){var r=t._pack_next;t._pack_next=e,e._pack_prev=t,e._pack_next=r,r._pack_prev=e}function Qa(t,e){t._pack_next=e,e._pack_prev=t}function Ja(t,e){var r=e.x-t.x,n=e.y-t.y,i=t.r+e.r;return.999*i*i>r*r+n*n}function Ka(t){if((e=t.children)&&(l=e.length)){var e,r,n,i,a,o,s,l,u=1/0,c=-1/0,f=1/0,h=-1/0;if(e.forEach($a),(r=e[0]).x=-r.r,r.y=0,b(r),l>1&&((n=e[1]).x=n.r,n.y=0,b(n),l>2))for(eo(r,n,i=e[2]),b(i),Za(r,i),r._pack_prev=i,Za(i,n),n=r._pack_next,a=3;a0)for(o=-1;++o=f[0]&&l<=f[1]&&((s=u[t.bisect(h,l,1,p)-1]).y+=g,s.push(a[o]));return u}return a.value=function(t){return arguments.length?(r=t,a):r},a.range=function(t){return arguments.length?(n=ve(t),a):n},a.bins=function(t){return arguments.length?(i="number"==typeof t?function(e){return Xa(e,t)}:ve(t),a):i},a.frequency=function(t){return arguments.length?(e=!!t,a):e},a},t.layout.pack=function(){var e,r=t.layout.hierarchy().sort(Ya),n=0,i=[1,1];function a(t,a){var o=r.call(this,t,a),s=o[0],l=i[0],u=i[1],c=null==e?Math.sqrt:"function"==typeof e?e:function(){return e};if(s.x=s.y=0,La(s,function(t){t.r=+c(t.value)}),La(s,Ka),n){var f=n*(e?1:Math.max(2*s.r/l,2*s.r/u))/2;La(s,function(t){t.r+=f}),La(s,Ka),La(s,function(t){t.r-=f})}return function t(e,r,n,i){var a=e.children;e.x=r+=i*e.x;e.y=n+=i*e.y;e.r*=i;if(a)for(var o=-1,s=a.length;++od.x&&(d=t),t.depth>p.depth&&(p=t)});var g=r(h,d)/2-h.x,v=n[0]/(d.x+r(d,h)/2+g),m=n[1]/(p.depth||1);Sa(c,function(t){t.x=(t.x+g)*v,t.y=t.depth*m})}return u}function o(t){var e=t.children,n=t.parent.children,i=t.i?n[t.i-1]:null;if(e.length){!function(t){var e,r=0,n=0,i=t.children,a=i.length;for(;--a>=0;)(e=i[a]).z+=r,e.m+=r,r+=e.s+(n+=e.c)}(t);var a=(e[0].z+e[e.length-1].z)/2;i?(t.z=i.z+r(t._,i._),t.m=t.z-a):t.z=a}else i&&(t.z=i.z+r(t._,i._));t.parent.A=function(t,e,n){if(e){for(var i,a=t,o=t,s=e,l=a.parent.children[0],u=a.m,c=o.m,f=s.m,h=l.m;s=io(s),a=no(a),s&&a;)l=no(l),(o=io(o)).a=t,(i=s.z+f-a.z-u+r(s._,a._))>0&&(ao(oo(s,t,n),t,i),u+=i,c+=i),f+=s.m,u+=a.m,h+=l.m,c+=o.m;s&&!io(o)&&(o.t=s,o.m+=f-c),a&&!no(l)&&(l.t=a,l.m+=u-h,n=t)}return n}(t,i,t.parent.A||n[0])}function s(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}function l(t){t.x*=n[0],t.y=t.depth*n[1]}return a.separation=function(t){return arguments.length?(r=t,a):r},a.size=function(t){return arguments.length?(i=null==(n=t)?l:null,a):i?null:n},a.nodeSize=function(t){return arguments.length?(i=null==(n=t)?null:l,a):i?n:null},Ea(a,e)},t.layout.cluster=function(){var e=t.layout.hierarchy().sort(null).value(null),r=ro,n=[1,1],i=!1;function a(a,o){var s,l=e.call(this,a,o),u=l[0],c=0;La(u,function(e){var n=e.children;n&&n.length?(e.x=function(t){return t.reduce(function(t,e){return t+e.x},0)/t.length}(n),e.y=function(e){return 1+t.max(e,function(t){return t.y})}(n)):(e.x=s?c+=r(e,s):0,e.y=0,s=e)});var f=function t(e){var r=e.children;return r&&r.length?t(r[0]):e}(u),h=function t(e){var r,n=e.children;return n&&(r=n.length)?t(n[r-1]):e}(u),d=f.x-r(f,h)/2,p=h.x+r(h,f)/2;return La(u,i?function(t){t.x=(t.x-u.x)*n[0],t.y=(u.y-t.y)*n[1]}:function(t){t.x=(t.x-d)/(p-d)*n[0],t.y=(1-(u.y?t.y/u.y:1))*n[1]}),l}return a.separation=function(t){return arguments.length?(r=t,a):r},a.size=function(t){return arguments.length?(i=null==(n=t),a):i?null:n},a.nodeSize=function(t){return arguments.length?(i=null!=(n=t),a):i?n:null},Ea(a,e)},t.layout.treemap=function(){var e,r=t.layout.hierarchy(),n=Math.round,i=[1,1],a=null,o=so,s=!1,l="squarify",u=.5*(1+Math.sqrt(5));function c(t,e){for(var r,n,i=-1,a=t.length;++i0;)s.push(r=u[i-1]),s.area+=r.area,"squarify"!==l||(n=d(s,g))<=h?(u.pop(),h=n):(s.area-=s.pop().area,p(s,g,a,!1),g=Math.min(a.dx,a.dy),s.length=s.area=0,h=1/0);s.length&&(p(s,g,a,!0),s.length=s.area=0),e.forEach(f)}}function h(t){var e=t.children;if(e&&e.length){var r,n=o(t),i=e.slice(),a=[];for(c(i,n.dx*n.dy/t.value),a.area=0;r=i.pop();)a.push(r),a.area+=r.area,null!=r.z&&(p(a,r.z?n.dx:n.dy,n,!i.length),a.length=a.area=0);e.forEach(h)}}function d(t,e){for(var r,n=t.area,i=0,a=1/0,o=-1,s=t.length;++oi&&(i=r));return e*=e,(n*=n)?Math.max(e*i*u/n,n/(e*a*u)):1/0}function p(t,e,r,i){var a,o=-1,s=t.length,l=r.x,u=r.y,c=e?n(t.area/e):0;if(e==r.dx){for((i||c>r.dy)&&(c=r.dy);++or.dx)&&(c=r.dx);++o1);return t+e*r*Math.sqrt(-2*Math.log(i)/i)}},logNormal:function(){var e=t.random.normal.apply(t,arguments);return function(){return Math.exp(e())}},bates:function(e){var r=t.random.irwinHall(e);return function(){return r()/e}},irwinHall:function(t){return function(){for(var e=0,r=0;r2?vo:fo,s=i?ma:va;return a=t(e,r,s,n),o=t(r,e,s,Zi),l}function l(t){return a(t)}l.invert=function(t){return o(t)};l.domain=function(t){return arguments.length?(e=t.map(Number),s()):e};l.range=function(t){return arguments.length?(r=t,s()):r};l.rangeRound=function(t){return l.range(t).interpolate(ua)};l.clamp=function(t){return arguments.length?(i=t,s()):i};l.interpolate=function(t){return arguments.length?(n=t,s()):n};l.ticks=function(t){return xo(e,t)};l.tickFormat=function(t,r){return _o(e,t,r)};l.nice=function(t){return yo(e,t),s()};l.copy=function(){return t(e,r,n,i)};return s()}([0,1],[0,1],Zi,!1)};var wo={s:1,g:1,p:1,r:1,e:1};function Mo(t){return-Math.floor(Math.log(t)/Math.LN10+.01)}t.scale.log=function(){return function e(r,n,i,a){function o(t){return(i?Math.log(t<0?0:t):-Math.log(t>0?0:-t))/Math.log(n)}function s(t){return i?Math.pow(n,t):-Math.pow(n,-t)}function l(t){return r(o(t))}l.invert=function(t){return s(r.invert(t))};l.domain=function(t){return arguments.length?(i=t[0]>=0,r.domain((a=t.map(Number)).map(o)),l):a};l.base=function(t){return arguments.length?(n=+t,r.domain(a.map(o)),l):n};l.nice=function(){var t=ho(a.map(o),i?Math:To);return r.domain(t),a=t.map(s),l};l.ticks=function(){var t=uo(a),e=[],r=t[0],l=t[1],u=Math.floor(o(r)),c=Math.ceil(o(l)),f=n%1?2:n;if(isFinite(c-u)){if(i){for(;u0;h--)e.push(s(u)*h);for(u=0;e[u]l;c--);e=e.slice(u,c)}return e};l.tickFormat=function(e,r){if(!arguments.length)return Ao;arguments.length<2?r=Ao:"function"!=typeof r&&(r=t.format(r));var i=Math.max(1,n*e/l.ticks().length);return function(t){var e=t/s(Math.round(o(t)));return e*n0?i[t-1]:r[0],tf?0:1;if(u=Et)return l(u,d)+(s?l(s,1-d):"")+"Z";var p,g,v,m,y,b,x,_,w,M,A,T,k=0,E=0,S=[];if((m=(+o.apply(this,arguments)||0)/2)&&(v=n===Oo?Math.sqrt(s*s+u*u):+n.apply(this,arguments),d||(E*=-1),u&&(E=It(v/u*Math.sin(m))),s&&(k=It(v/s*Math.sin(m)))),u){y=u*Math.cos(c+E),b=u*Math.sin(c+E),x=u*Math.cos(f-E),_=u*Math.sin(f-E);var L=Math.abs(f-c-2*E)<=Tt?0:1;if(E&&Fo(y,b,x,_)===d^L){var C=(c+f)/2;y=u*Math.cos(C),b=u*Math.sin(C),x=_=null}}else y=b=0;if(s){w=s*Math.cos(f-k),M=s*Math.sin(f-k),A=s*Math.cos(c+k),T=s*Math.sin(c+k);var P=Math.abs(c-f+2*k)<=Tt?0:1;if(k&&Fo(w,M,A,T)===1-d^P){var O=(c+f)/2;w=s*Math.cos(O),M=s*Math.sin(O),A=T=null}}else w=M=0;if(h>Mt&&(p=Math.min(Math.abs(u-s)/2,+r.apply(this,arguments)))>.001){g=s0?0:1}function jo(t,e,r,n,i){var a=t[0]-e[0],o=t[1]-e[1],s=(i?n:-n)/Math.sqrt(a*a+o*o),l=s*o,u=-s*a,c=t[0]+l,f=t[1]+u,h=e[0]+l,d=e[1]+u,p=(c+h)/2,g=(f+d)/2,v=h-c,m=d-f,y=v*v+m*m,b=r-n,x=c*d-h*f,_=(m<0?-1:1)*Math.sqrt(Math.max(0,b*b*y-x*x)),w=(x*m-v*_)/y,M=(-x*v-m*_)/y,A=(x*m+v*_)/y,T=(-x*v+m*_)/y,k=w-p,E=M-g,S=A-p,L=T-g;return k*k+E*E>S*S+L*L&&(w=A,M=T),[[w-l,M-u],[w*r/b,M*r/b]]}function Bo(t){var e=ei,r=ri,n=Xr,i=Vo,a=i.key,o=.7;function s(a){var s,l=[],u=[],c=-1,f=a.length,h=ve(e),d=ve(r);function p(){l.push("M",i(t(u),o))}for(;++c1&&i.push("H",n[0]);return i.join("")},"step-before":qo,"step-after":Go,basis:Yo,"basis-open":function(t){if(t.length<4)return Vo(t);var e,r=[],n=-1,i=t.length,a=[0],o=[0];for(;++n<3;)e=t[n],a.push(e[0]),o.push(e[1]);r.push(Zo(Ko,a)+","+Zo(Ko,o)),--n;for(;++n9&&(i=3*e/Math.sqrt(i),o[s]=i*r,o[s+1]=i*n));s=-1;for(;++s<=l;)i=(t[Math.min(l,s+1)][0]-t[Math.max(0,s-1)][0])/(6*(1+o[s]*o[s])),a.push([i||0,o[s]*i||0]);return a}(t))}});function Vo(t){return t.length>1?t.join("L"):t+"Z"}function Ho(t){return t.join("L")+"Z"}function qo(t){for(var e=0,r=t.length,n=t[0],i=[n[0],",",n[1]];++e1){s=e[1],a=t[l],l++,n+="C"+(i[0]+o[0])+","+(i[1]+o[1])+","+(a[0]-s[0])+","+(a[1]-s[1])+","+a[0]+","+a[1];for(var u=2;uTt)+",1 "+e}function l(t,e,r,n){return"Q 0,0 "+n}return a.radius=function(t){return arguments.length?(r=ve(t),a):r},a.source=function(e){return arguments.length?(t=ve(e),a):t},a.target=function(t){return arguments.length?(e=ve(t),a):e},a.startAngle=function(t){return arguments.length?(n=ve(t),a):n},a.endAngle=function(t){return arguments.length?(i=ve(t),a):i},a},t.svg.diagonal=function(){var t=Un,e=Vn,r=is;function n(n,i){var a=t.call(this,n,i),o=e.call(this,n,i),s=(a.y+o.y)/2,l=[a,{x:a.x,y:s},{x:o.x,y:s},o];return"M"+(l=l.map(r))[0]+"C"+l[1]+" "+l[2]+" "+l[3]}return n.source=function(e){return arguments.length?(t=ve(e),n):t},n.target=function(t){return arguments.length?(e=ve(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},t.svg.diagonal.radial=function(){var e=t.svg.diagonal(),r=is,n=e.projection;return e.projection=function(t){return arguments.length?n(function(t){return function(){var e=t.apply(this,arguments),r=e[0],n=e[1]-St;return[r*Math.cos(n),r*Math.sin(n)]}}(r=t)):r},e},t.svg.symbol=function(){var t=os,e=as;function r(r,n){return(ls.get(t.call(this,r,n))||ss)(e.call(this,r,n))}return r.type=function(e){return arguments.length?(t=ve(e),r):t},r.size=function(t){return arguments.length?(e=ve(t),r):e},r};var ls=t.map({circle:ss,cross:function(t){var e=Math.sqrt(t/5)/2;return"M"+-3*e+","+-e+"H"+-e+"V"+-3*e+"H"+e+"V"+-e+"H"+3*e+"V"+e+"H"+e+"V"+3*e+"H"+-e+"V"+e+"H"+-3*e+"Z"},diamond:function(t){var e=Math.sqrt(t/(2*cs)),r=e*cs;return"M0,"+-e+"L"+r+",0 0,"+e+" "+-r+",0Z"},square:function(t){var e=Math.sqrt(t)/2;return"M"+-e+","+-e+"L"+e+","+-e+" "+e+","+e+" "+-e+","+e+"Z"},"triangle-down":function(t){var e=Math.sqrt(t/us),r=e*us/2;return"M0,"+r+"L"+e+","+-r+" "+-e+","+-r+"Z"},"triangle-up":function(t){var e=Math.sqrt(t/us),r=e*us/2;return"M0,"+-r+"L"+e+","+r+" "+-e+","+r+"Z"}});t.svg.symbolTypes=ls.keys();var us=Math.sqrt(3),cs=Math.tan(30*Lt);W.transition=function(t){for(var e,r,n=ps||++ms,i=xs(t),a=[],o=gs||{time:Date.now(),ease:ia,delay:0,duration:250},s=-1,l=this.length;++s0;)u[--h].call(t,o);if(a>=1)return f.event&&f.event.end.call(t,t.__data__,e),--c.count?delete c[n]:delete t[r],1}f||(a=i.time,o=Ae(function(t){var e=f.delay;if(o.t=e+a,e<=t)return h(t-e);o.c=h},0,a),f=c[n]={tween:new x,time:a,timer:o,delay:i.delay,duration:i.duration,ease:i.ease,index:e},i=null,++c.count)}vs.call=W.call,vs.empty=W.empty,vs.node=W.node,vs.size=W.size,t.transition=function(e,r){return e&&e.transition?ps?e.transition(r):e:t.selection().transition(e)},t.transition.prototype=vs,vs.select=function(t){var e,r,n,i=this.id,a=this.namespace,o=[];t=Y(t);for(var s=-1,l=this.length;++srect,.s>rect").attr("width",s[1]-s[0])}function g(t){t.select(".extent").attr("y",l[0]),t.selectAll(".extent,.e>rect,.w>rect").attr("height",l[1]-l[0])}function v(){var f,v,m=this,y=t.select(t.event.target),b=n.of(m,arguments),x=t.select(m),_=y.datum(),w=!/^(n|s)$/.test(_)&&i,M=!/^(e|w)$/.test(_)&&a,A=y.classed("extent"),T=bt(m),k=t.mouse(m),E=t.select(o(m)).on("keydown.brush",function(){32==t.event.keyCode&&(A||(f=null,k[0]-=s[1],k[1]-=l[1],A=2),F())}).on("keyup.brush",function(){32==t.event.keyCode&&2==A&&(k[0]+=s[1],k[1]+=l[1],A=0,F())});if(t.event.changedTouches?E.on("touchmove.brush",C).on("touchend.brush",O):E.on("mousemove.brush",C).on("mouseup.brush",O),x.interrupt().selectAll("*").interrupt(),A)k[0]=s[0]-k[0],k[1]=l[0]-k[1];else if(_){var S=+/w$/.test(_),L=+/^n/.test(_);v=[s[1-S]-k[0],l[1-L]-k[1]],k[0]=s[S],k[1]=l[L]}else t.event.altKey&&(f=k.slice());function C(){var e=t.mouse(m),r=!1;v&&(e[0]+=v[0],e[1]+=v[1]),A||(t.event.altKey?(f||(f=[(s[0]+s[1])/2,(l[0]+l[1])/2]),k[0]=s[+(e[0]1?{floor:function(e){for(;s(e=t.floor(e));)e=Rs(e-1);return e},ceil:function(e){for(;s(e=t.ceil(e));)e=Rs(+e+1);return e}}:t))},i.ticks=function(t,e){var r=uo(i.domain()),n=null==t?a(r,10):"number"==typeof t?a(r,t):!t.range&&[{range:t},e];return n&&(t=n[0],e=n[1]),t.range(r[0],Rs(+r[1]+1),e<1?1:e)},i.tickFormat=function(){return n},i.copy=function(){return Os(e.copy(),r,n)},mo(i,e)}function Rs(t){return new Date(t)}Ss.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Ps:Cs,Ps.parse=function(t){var e=new Date(t);return isNaN(e)?null:e},Ps.toString=Cs.toString,Re.second=De(function(t){return new Ie(1e3*Math.floor(t/1e3))},function(t,e){t.setTime(t.getTime()+1e3*Math.floor(e))},function(t){return t.getSeconds()}),Re.seconds=Re.second.range,Re.seconds.utc=Re.second.utc.range,Re.minute=De(function(t){return new Ie(6e4*Math.floor(t/6e4))},function(t,e){t.setTime(t.getTime()+6e4*Math.floor(e))},function(t){return t.getMinutes()}),Re.minutes=Re.minute.range,Re.minutes.utc=Re.minute.utc.range,Re.hour=De(function(t){var e=t.getTimezoneOffset()/60;return new Ie(36e5*(Math.floor(t/36e5-e)+e))},function(t,e){t.setTime(t.getTime()+36e5*Math.floor(e))},function(t){return t.getHours()}),Re.hours=Re.hour.range,Re.hours.utc=Re.hour.utc.range,Re.month=De(function(t){return(t=Re.day(t)).setDate(1),t},function(t,e){t.setMonth(t.getMonth()+e)},function(t){return t.getMonth()}),Re.months=Re.month.range,Re.months.utc=Re.month.utc.range;var Is=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Ns=[[Re.second,1],[Re.second,5],[Re.second,15],[Re.second,30],[Re.minute,1],[Re.minute,5],[Re.minute,15],[Re.minute,30],[Re.hour,1],[Re.hour,3],[Re.hour,6],[Re.hour,12],[Re.day,1],[Re.day,2],[Re.week,1],[Re.month,1],[Re.month,3],[Re.year,1]],zs=Ss.multi([[".%L",function(t){return t.getMilliseconds()}],[":%S",function(t){return t.getSeconds()}],["%I:%M",function(t){return t.getMinutes()}],["%I %p",function(t){return t.getHours()}],["%a %d",function(t){return t.getDay()&&1!=t.getDate()}],["%b %d",function(t){return 1!=t.getDate()}],["%B",function(t){return t.getMonth()}],["%Y",Xr]]),Ds={range:function(e,r,n){return t.range(Math.ceil(e/n)*n,+r,n).map(Rs)},floor:P,ceil:P};Ns.year=Re.year,Re.scale=function(){return Os(t.scale.linear(),Ns,zs)};var Fs=Ns.map(function(t){return[t[0].utc,t[1]]}),js=Ls.multi([[".%L",function(t){return t.getUTCMilliseconds()}],[":%S",function(t){return t.getUTCSeconds()}],["%I:%M",function(t){return t.getUTCMinutes()}],["%I %p",function(t){return t.getUTCHours()}],["%a %d",function(t){return t.getUTCDay()&&1!=t.getUTCDate()}],["%b %d",function(t){return 1!=t.getUTCDate()}],["%B",function(t){return t.getUTCMonth()}],["%Y",Xr]]);function Bs(t){return JSON.parse(t.responseText)}function Us(t){var e=i.createRange();return e.selectNode(i.body),e.createContextualFragment(t.responseText)}Fs.year=Re.year.utc,Re.scale.utc=function(){return Os(t.scale.linear(),Fs,js)},t.text=me(function(t){return t.responseText}),t.json=function(t,e){return ye(t,"application/json",Bs,e)},t.html=function(t,e){return ye(t,"text/html",Us,e)},t.xml=me(function(t){return t.responseXML}),"object"==typeof e&&e.exports?e.exports=t:this.d3=t}()},{}],81:[function(t,e,r){e.exports=function(){for(var t=0;t=2)return!1;t[r]=n}return!0}):_.filter(function(t){for(var e=0;e<=s;++e){var r=m[t[e]];if(r<0)return!1;t[e]=r}return!0});if(1&s)for(var c=0;c<_.length;++c){var x=_[c],h=x[0];x[0]=x[1],x[1]=h}return _}},{"incremental-convex-hull":234,uniq:330}],83:[function(t,e,r){(function(t){var r=!1;if("undefined"!=typeof Float64Array){var n=new Float64Array(1),i=new Uint32Array(n.buffer);if(n[0]=1,r=!0,1072693248===i[1]){e.exports=function(t){return n[0]=t,[i[0],i[1]]},e.exports.pack=function(t,e){return i[0]=t,i[1]=e,n[0]},e.exports.lo=function(t){return n[0]=t,i[0]},e.exports.hi=function(t){return n[0]=t,i[1]}}else if(1072693248===i[0]){e.exports=function(t){return n[0]=t,[i[1],i[0]]},e.exports.pack=function(t,e){return i[1]=t,i[0]=e,n[0]},e.exports.lo=function(t){return n[0]=t,i[1]},e.exports.hi=function(t){return n[0]=t,i[0]}}else r=!1}if(!r){var a=new t(8);e.exports=function(t){return a.writeDoubleLE(t,0,!0),[a.readUInt32LE(0,!0),a.readUInt32LE(4,!0)]},e.exports.pack=function(t,e){return a.writeUInt32LE(t,0,!0),a.writeUInt32LE(e,4,!0),a.readDoubleLE(0,!0)},e.exports.lo=function(t){return a.writeDoubleLE(t,0,!0),a.readUInt32LE(0,!0)},e.exports.hi=function(t){return a.writeDoubleLE(t,0,!0),a.readUInt32LE(4,!0)}}e.exports.sign=function(t){return e.exports.hi(t)>>>31},e.exports.exponent=function(t){return(e.exports.hi(t)<<1>>>21)-1023},e.exports.fraction=function(t){var r=e.exports.lo(t),n=e.exports.hi(t),i=1048575&n;return 2146435072&n&&(i+=1<<20),[r,i]},e.exports.denormalized=function(t){return!(2146435072&e.exports.hi(t))}}).call(this,t("buffer").Buffer)},{buffer:47}],84:[function(t,e,r){e.exports=function(t){switch(t){case"int8":return Int8Array;case"int16":return Int16Array;case"int32":return Int32Array;case"uint8":return Uint8Array;case"uint16":return Uint16Array;case"uint32":return Uint32Array;case"float32":return Float32Array;case"float64":return Float64Array;case"array":return Array;case"uint8_clamped":return Uint8ClampedArray}}},{}],85:[function(t,e,r){"use strict";e.exports=function(t,e){switch(void 0===e&&(e=0),typeof t){case"number":if(t>0)return function(t,e){var r,n;for(r=new Array(t),n=0;n0&&this._events[t].length>r&&(this._events[t].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[t].length),"function"==typeof console.trace&&console.trace()),this},n.prototype.on=n.prototype.addListener,n.prototype.once=function(t,e){if(!i(e))throw TypeError("listener must be a function");var r=!1;function n(){this.removeListener(t,n),r||(r=!0,e.apply(this,arguments))}return n.listener=e,this.on(t,n),this},n.prototype.removeListener=function(t,e){var r,n,o,s;if(!i(e))throw TypeError("listener must be a function");if(!this._events||!this._events[t])return this;if(o=(r=this._events[t]).length,n=-1,r===e||i(r.listener)&&r.listener===e)delete this._events[t],this._events.removeListener&&this.emit("removeListener",t,e);else if(a(r)){for(s=o;s-- >0;)if(r[s]===e||r[s].listener&&r[s].listener===e){n=s;break}if(n<0)return this;1===r.length?(r.length=0,delete this._events[t]):r.splice(n,1),this._events.removeListener&&this.emit("removeListener",t,e)}return this},n.prototype.removeAllListeners=function(t){var e,r;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[t]&&delete this._events[t],this;if(0===arguments.length){for(e in this._events)"removeListener"!==e&&this.removeAllListeners(e);return this.removeAllListeners("removeListener"),this._events={},this}if(i(r=this._events[t]))this.removeListener(t,r);else if(r)for(;r.length;)this.removeListener(t,r[r.length-1]);return delete this._events[t],this},n.prototype.listeners=function(t){return this._events&&this._events[t]?i(this._events[t])?[this._events[t]]:this._events[t].slice():[]},n.prototype.listenerCount=function(t){if(this._events){var e=this._events[t];if(i(e))return 1;if(e)return e.length}return 0},n.listenerCount=function(t,e){return t.listenerCount(e)}},{}],89:[function(t,e,r){"use strict";e.exports=function(t,e,r){var n=e||0,i=r||1;return[[t[12]+t[0],t[13]+t[1],t[14]+t[2],t[15]+t[3]],[t[12]-t[0],t[13]-t[1],t[14]-t[2],t[15]-t[3]],[t[12]+t[4],t[13]+t[5],t[14]+t[6],t[15]+t[7]],[t[12]-t[4],t[13]-t[5],t[14]-t[6],t[15]-t[7]],[n*t[12]+t[8],n*t[13]+t[9],n*t[14]+t[10],n*t[15]+t[11]],[i*t[12]-t[8],i*t[13]-t[9],i*t[14]-t[10],i*t[15]-t[11]]]}},{}],90:[function(t,e,r){"use strict";e.exports=function(t){var e=typeof t;if("string"===e){var r=t;if(0===(t=+t)&&function(t){for(var e,r=t.length,n=0;n13)&&32!==e&&133!==e&&160!==e&&5760!==e&&6158!==e&&(e<8192||e>8205)&&8232!==e&&8233!==e&&8239!==e&&8287!==e&&8288!==e&&12288!==e&&65279!==e)return!1;return!0}(r))return!1}else if("number"!==e)return!1;return t-t<1}},{}],91:[function(t,e,r){"use strict";e.exports=function(t,e,r){switch(arguments.length){case 0:return new o([0],[0],0);case 1:if("number"==typeof t){var n=l(t);return new o(n,n,0)}return new o(t,l(t.length),0);case 2:if("number"==typeof e){var n=l(t.length);return new o(t,n,+e)}r=0;case 3:if(t.length!==e.length)throw new Error("state and velocity lengths must match");return new o(t,e,r)}};var n=t("cubic-hermite"),i=t("binary-search-bounds");function a(t,e,r){return Math.min(e,Math.max(t,r))}function o(t,e,r){this.dimension=t.length,this.bounds=[new Array(this.dimension),new Array(this.dimension)];for(var n=0;n=r-1){h=l.length-1;var p=t-e[r-1];for(d=0;d=r-1)for(var c=s.length-1,f=(e[r-1],0);f=0;--r)if(t[--e])return!1;return!0},s.jump=function(t){var e=this.lastT(),r=this.dimension;if(!(t0;--f)n.push(a(l[f-1],u[f-1],arguments[f])),i.push(0)}},s.push=function(t){var e=this.lastT(),r=this.dimension;if(!(t1e-6?1/s:0;this._time.push(t);for(var h=r;h>0;--h){var d=a(u[h-1],c[h-1],arguments[h]);n.push(d),i.push((d-n[o++])*f)}}},s.set=function(t){var e=this.dimension;if(!(t0;--l)r.push(a(o[l-1],s[l-1],arguments[l])),n.push(0)}},s.move=function(t){var e=this.lastT(),r=this.dimension;if(!(t<=e||arguments.length!==r+1)){var n=this._state,i=this._velocity,o=n.length-this.dimension,s=this.bounds,l=s[0],u=s[1],c=t-e,f=c>1e-6?1/c:0;this._time.push(t);for(var h=r;h>0;--h){var d=arguments[h];n.push(a(l[h-1],u[h-1],n[o++]+d)),i.push(d*f)}}},s.idle=function(t){var e=this.lastT();if(!(t=0;--f)n.push(a(l[f],u[f],n[o]+c*i[o])),i.push(0),o+=1}}},{"binary-search-bounds":35,"cubic-hermite":75}],92:[function(t,e,r){"use strict";e.exports=function(t){return new u(t||p,null)};var n=0,i=1;function a(t,e,r,n,i,a){this._color=t,this.key=e,this.value=r,this.left=n,this.right=i,this._count=a}function o(t){return new a(t._color,t.key,t.value,t.left,t.right,t._count)}function s(t,e){return new a(t,e.key,e.value,e.left,e.right,e._count)}function l(t){t._count=1+(t.left?t.left._count:0)+(t.right?t.right._count:0)}function u(t,e){this._compare=t,this.root=e}var c=u.prototype;function f(t,e){this.tree=t,this._stack=e}Object.defineProperty(c,"keys",{get:function(){var t=[];return this.forEach(function(e,r){t.push(e)}),t}}),Object.defineProperty(c,"values",{get:function(){var t=[];return this.forEach(function(e,r){t.push(r)}),t}}),Object.defineProperty(c,"length",{get:function(){return this.root?this.root._count:0}}),c.insert=function(t,e){for(var r=this._compare,o=this.root,c=[],f=[];o;){var h=r(t,o.key);c.push(o),f.push(h),o=h<=0?o.left:o.right}c.push(new a(n,t,e,null,null,1));for(var d=c.length-2;d>=0;--d){o=c[d];f[d]<=0?c[d]=new a(o._color,o.key,o.value,c[d+1],o.right,o._count+1):c[d]=new a(o._color,o.key,o.value,o.left,c[d+1],o._count+1)}for(d=c.length-1;d>1;--d){var p=c[d-1];o=c[d];if(p._color===i||o._color===i)break;var g=c[d-2];if(g.left===p)if(p.left===o){if(!(v=g.right)||v._color!==n){if(g._color=n,g.left=p.right,p._color=i,p.right=g,c[d-2]=p,c[d-1]=o,l(g),l(p),d>=3)(m=c[d-3]).left===g?m.left=p:m.right=p;break}p._color=i,g.right=s(i,v),g._color=n,d-=1}else{if(!(v=g.right)||v._color!==n){if(p.right=o.left,g._color=n,g.left=o.right,o._color=i,o.left=p,o.right=g,c[d-2]=o,c[d-1]=p,l(g),l(p),l(o),d>=3)(m=c[d-3]).left===g?m.left=o:m.right=o;break}p._color=i,g.right=s(i,v),g._color=n,d-=1}else if(p.right===o){if(!(v=g.left)||v._color!==n){if(g._color=n,g.right=p.left,p._color=i,p.left=g,c[d-2]=p,c[d-1]=o,l(g),l(p),d>=3)(m=c[d-3]).right===g?m.right=p:m.left=p;break}p._color=i,g.left=s(i,v),g._color=n,d-=1}else{var v;if(!(v=g.left)||v._color!==n){var m;if(p.left=o.right,g._color=n,g.right=o.left,o._color=i,o.right=p,o.left=g,c[d-2]=o,c[d-1]=p,l(g),l(p),l(o),d>=3)(m=c[d-3]).right===g?m.right=o:m.left=o;break}p._color=i,g.left=s(i,v),g._color=n,d-=1}}return c[0]._color=i,new u(r,c[0])},c.forEach=function(t,e,r){if(this.root)switch(arguments.length){case 1:return function t(e,r){var n;if(r.left&&(n=t(e,r.left)))return n;return(n=e(r.key,r.value))||(r.right?t(e,r.right):void 0)}(t,this.root);case 2:return function t(e,r,n,i){if(r(e,i.key)<=0){var a;if(i.left&&(a=t(e,r,n,i.left)))return a;if(a=n(i.key,i.value))return a}if(i.right)return t(e,r,n,i.right)}(e,this._compare,t,this.root);case 3:if(this._compare(e,r)>=0)return;return function t(e,r,n,i,a){var o,s=n(e,a.key),l=n(r,a.key);if(s<=0){if(a.left&&(o=t(e,r,n,i,a.left)))return o;if(l>0&&(o=i(a.key,a.value)))return o}if(l>0&&a.right)return t(e,r,n,i,a.right)}(e,r,this._compare,t,this.root)}},Object.defineProperty(c,"begin",{get:function(){for(var t=[],e=this.root;e;)t.push(e),e=e.left;return new f(this,t)}}),Object.defineProperty(c,"end",{get:function(){for(var t=[],e=this.root;e;)t.push(e),e=e.right;return new f(this,t)}}),c.at=function(t){if(t<0)return new f(this,[]);for(var e=this.root,r=[];;){if(r.push(e),e.left){if(t=e.right._count)break;e=e.right}return new f(this,[])},c.ge=function(t){for(var e=this._compare,r=this.root,n=[],i=0;r;){var a=e(t,r.key);n.push(r),a<=0&&(i=n.length),r=a<=0?r.left:r.right}return n.length=i,new f(this,n)},c.gt=function(t){for(var e=this._compare,r=this.root,n=[],i=0;r;){var a=e(t,r.key);n.push(r),a<0&&(i=n.length),r=a<0?r.left:r.right}return n.length=i,new f(this,n)},c.lt=function(t){for(var e=this._compare,r=this.root,n=[],i=0;r;){var a=e(t,r.key);n.push(r),a>0&&(i=n.length),r=a<=0?r.left:r.right}return n.length=i,new f(this,n)},c.le=function(t){for(var e=this._compare,r=this.root,n=[],i=0;r;){var a=e(t,r.key);n.push(r),a>=0&&(i=n.length),r=a<0?r.left:r.right}return n.length=i,new f(this,n)},c.find=function(t){for(var e=this._compare,r=this.root,n=[];r;){var i=e(t,r.key);if(n.push(r),0===i)return new f(this,n);r=i<=0?r.left:r.right}return new f(this,[])},c.remove=function(t){var e=this.find(t);return e?e.remove():this},c.get=function(t){for(var e=this._compare,r=this.root;r;){var n=e(t,r.key);if(0===n)return r.value;r=n<=0?r.left:r.right}};var h=f.prototype;function d(t,e){t.key=e.key,t.value=e.value,t.left=e.left,t.right=e.right,t._color=e._color,t._count=e._count}function p(t,e){return te?1:0}Object.defineProperty(h,"valid",{get:function(){return this._stack.length>0}}),Object.defineProperty(h,"node",{get:function(){return this._stack.length>0?this._stack[this._stack.length-1]:null},enumerable:!0}),h.clone=function(){return new f(this.tree,this._stack.slice())},h.remove=function(){var t=this._stack;if(0===t.length)return this.tree;var e=new Array(t.length),r=t[t.length-1];e[e.length-1]=new a(r._color,r.key,r.value,r.left,r.right,r._count);for(var c=t.length-2;c>=0;--c){(r=t[c]).left===t[c+1]?e[c]=new a(r._color,r.key,r.value,e[c+1],r.right,r._count):e[c]=new a(r._color,r.key,r.value,r.left,e[c+1],r._count)}if((r=e[e.length-1]).left&&r.right){var f=e.length;for(r=r.left;r.right;)e.push(r),r=r.right;var h=e[f-1];e.push(new a(r._color,h.key,h.value,r.left,r.right,r._count)),e[f-1].key=r.key,e[f-1].value=r.value;for(c=e.length-2;c>=f;--c)r=e[c],e[c]=new a(r._color,r.key,r.value,r.left,e[c+1],r._count);e[f-1].left=e[f]}if((r=e[e.length-1])._color===n){var p=e[e.length-2];p.left===r?p.left=null:p.right===r&&(p.right=null),e.pop();for(c=0;c