Repository: nilearn/nilearn

Issue:
reorder dosenbach ROIs in csv or in examples ?
I have a version of dosenbach ROIs reoredered. It shows nice connectivity blocks.
![dosenbach](https://cloud.githubusercontent.com/assets/7080143/17456206/0c8cb5d4-5bd0-11e6-93c5-14e6603164b6.png) vs 
![dosenbach_ordered](https://cloud.githubusercontent.com/assets/7080143/17456212/18c4b1f8-5bd0-11e6-9df8-8d2da5e08b15.png)

I don't know if it is better to change the ROIs order in the csv file or reorder them in examples.



Discussion:
> I have a version of dosenbach ROIs reoredered. It shows nice connectivity
> blocks.

I'd rather reorder them in them CSV.

However, I think that changing this silently is a bit dangerous.

We could add an option to the loader, and warn that in 1 release the
default will change and the non reordered version will disappear.

That said, I don't find the reordered matrix much more structured. If you
add more subjects/data does it become more structured?

> I'd rather reorder them in them CSV.

I am -1 on this for several reasons:
- Several people rely on the numbering of the regions to identify them. If they are mixed up without them knowing, they may make a mistake.
- I don't know where this reordering comes from, but if another one pops up, we may have to chose one.
- If we offer the ability to get the original and reordered versions, the maskers will not be aware of that and they will compute everything for each version.

Since this is a plotting feature, I would be in favor of adding an index in the bunch and let the user reorder things if he wants to do it. An even better option would be to have a function that automatically reorders columns in a connectivity matrix to exhibit structure.


Resolving patch:
diff --git a/examples/03_connectivity/plot_seed_based_connectome.py b/examples/03_connectivity/plot_seed_based_connectome.py
deleted file mode 100644
--- a/examples/03_connectivity/plot_seed_based_connectome.py
+++ /dev/null
@@ -1,90 +0,0 @@
-"""
-Extract signals and plot a connectome for seed-based atlases
-============================================================
-
-This example shows how to extract signals from spherical seed-based
-atlases such as Power-264 atlas (Power, 2011) and Dosenbach-160 (Dosenbach,
-2010). We estimate connectome using sparse inverse covariance.
-
-Dosenbach N.U., Nardos B., et al. "Prediction of individual brain maturity
-using fMRI.", 2010, Science 329, 1358-1361.
-
-Power, Jonathan D., et al. "Functional network organization of the
-human brain." Neuron 72.4 (2011): 665-678.
-"""
-
-import numpy as np
-import matplotlib.pyplot as plt
-from nilearn import datasets, connectome, plotting, input_data
-
-
-###############################################################################
-# Atlas and dataset fetching
-
-# Fetch the coordinates of power atlas
-power = datasets.fetch_coords_power_2011()
-power_coords = np.vstack((
-    power.rois['x'],
-    power.rois['y'],
-    power.rois['z'],
-)).T
-
-dosenbach = datasets.fetch_coords_dosenbach_2010()
-dosenbach_coords = np.vstack((
-    dosenbach.rois['x'],
-    dosenbach.rois['y'],
-    dosenbach.rois['z'],
-)).T
-
-# Fetch the first subject of ADHD dataset
-adhd = datasets.fetch_adhd(n_subjects=1)
-
-
-###############################################################################
-# Masking: taking the signal in a sphere of radius 5 around Power coords
-
-power_masker = input_data.NiftiSpheresMasker(
-    seeds=power_coords, smoothing_fwhm=4, radius=5.,
-    standardize=True, detrend=True,
-    low_pass=0.1, high_pass=0.01, t_r=2.5)
-
-dosenbach_masker = input_data.NiftiSpheresMasker(
-    seeds=dosenbach_coords, smoothing_fwhm=4, radius=4.,
-    standardize=True, detrend=True,
-    low_pass=0.1, high_pass=0.01, t_r=2.5)
-
-power_timeseries = power_masker.fit_transform(
-    adhd.func[0], confounds=adhd.confounds[0])
-
-dosenbach_timeseries = dosenbach_masker.fit_transform(
-    adhd.func[0], confounds=adhd.confounds[0])
-
-###############################################################################
-# Extract and plot correlation matrix
-
-for atlas in ['Power', 'Dosenbach']:
-
-    if atlas == 'Power':
-        timeseries = power_timeseries
-        coords = power_coords
-    else:
-        timeseries = dosenbach_timeseries
-        coords = dosenbach_coords
-
-    connectivity = connectome.ConnectivityMeasure(kind='correlation')
-    corr_matrix = connectivity.fit_transform([timeseries])[0]
-    np.fill_diagonal(corr_matrix, 0)
-
-    plt.figure()
-    vmax = np.max(np.abs(corr_matrix))
-    plt.imshow(corr_matrix, vmin=-vmax, vmax=vmax, cmap='RdBu_r',
-               interpolation='nearest')
-    plt.colorbar()
-    plt.title(atlas + 'correlation matrix')
-
-    # Plot the connectome
-    plotting.plot_connectome(corr_matrix, coords,
-                             edge_threshold='99.8%', node_size=20,
-                             title=atlas + 'correlation connectome')
-
-plotting.show()
diff --git a/examples/03_connectivity/plot_sphere_based_connectome.py b/examples/03_connectivity/plot_sphere_based_connectome.py
new file mode 100644
--- /dev/null
+++ b/examples/03_connectivity/plot_sphere_based_connectome.py
@@ -0,0 +1,160 @@
+"""
+Extract signals on spheres from an atlas and plot a connectome
+==============================================================
+
+This example shows how to extract signals from spherical regions
+centered on coordinates from Power-264 atlas [1] and Dosenbach-160 [2].
+We estimate connectome using **sparse inverse covariance**, to recover
+the functional brain **networks structure**.
+
+References
+----------
+[1] Power, Jonathan D., et al. "Functional network organization of the
+human brain." Neuron 72.4 (2011): 665-678.
+
+[2] Dosenbach N.U., Nardos B., et al. "Prediction of individual brain maturity
+using fMRI.", 2010, Science 329, 1358-1361.
+
+"""
+
+###############################################################################
+# Load fMRI data and Power atlas
+# ------------------------------
+
+###############################################################################
+# We are going to use a single subject from the ADHD dataset.
+from nilearn import datasets
+
+adhd = datasets.fetch_adhd(n_subjects=1)
+
+###############################################################################
+# We store the paths to its functional image and the confounds file.
+fmri_filename = adhd.func[0]
+confounds_filename = adhd.confounds[0]
+print('Functional image is {0},\nconfounds are {1}.'.format(fmri_filename,
+      confounds_filename))
+
+###############################################################################
+# We fetch the coordinates of Power atlas.
+power = datasets.fetch_coords_power_2011()
+print('Power atlas comes with {0}.'.format(power.keys()))
+
+###############################################################################
+# Compute within spheres averaged time-series
+# -------------------------------------------
+
+###############################################################################
+# We can compute the mean signal within **spheres** of a fixed radius around
+# a sequence of (x, y, z) coordinates with the object
+# :class:`nilearn.input_data.NiftiSpheresMasker`.
+# So we collect the regions coordinates in a numpy array
+import numpy as np
+
+coords = np.vstack((
+    power.rois['x'],
+    power.rois['y'],
+    power.rois['z'],
+)).T
+
+print('Stacked power coordinates in array of shape {0}.'.format(coords.shape))
+
+###############################################################################
+# and define spheres masker, with small enough radius to avoid regions overlap.
+from nilearn import  input_data
+
+spheres_masker = input_data.NiftiSpheresMasker(
+    seeds=coords, smoothing_fwhm=4, radius=5.,
+    detrend=True, standardize=True, low_pass=0.1, high_pass=0.01, t_r=2.5)
+
+###############################################################################
+# Voxel-wise time-series within each sphere are averaged. The resulting signal
+# is then prepared by the masker object: Detrended, cleaned from counfounds,
+# band-pass filtered and **standardized to 1 variance**.
+timeseries = spheres_masker.fit_transform(fmri_filename,
+                                          confounds=confounds_filename)
+
+###############################################################################
+# Estimate correlations
+# ---------------------
+
+###############################################################################
+# All starts with the estimation of the signals **covariance** matrix. Here the
+# number of ROIs exceeds the number of samples,
+print('time series has {0} samples'.format(timeseries.shape[0]))
+
+###############################################################################
+# in which situation the graphical lasso **sparse inverse covariance**
+# estimator captures well the covariance **structure**.
+from sklearn.covariance import GraphLassoCV
+
+covariance_estimator = GraphLassoCV(verbose=1)
+
+###############################################################################
+# We just fit our regions signals into the `GraphLassoCV` object
+covariance_estimator.fit(timeseries)
+
+###############################################################################
+# and get the ROI-to-ROI covariance matrix.
+matrix = covariance_estimator.covariance_
+print('Covariance matrix has shape {0}.'.format(matrix.shape))
+
+###############################################################################
+# Plot matrix and graph
+# ---------------------
+
+###############################################################################
+# We use `matplotlib` plotting functions to visualize our correlation matrix
+# and display the graph of connections with `nilearn.plotting.plot_connectome`.
+import matplotlib.pyplot as plt
+from nilearn import plotting
+
+plt.imshow(matrix, vmin=-1., vmax=1., cmap='RdBu_r', interpolation='nearest')
+plt.colorbar()
+plt.title('Power correlation matrix')
+
+# Tweak edge_threshold to keep only the strongest connections.
+plotting.plot_connectome(matrix, coords, title='Power correlation graph',
+                         edge_threshold='99.8%', node_size=20, colorbar=True)
+
+###############################################################################
+# Note the 1. on the matrix diagonal: These are the signals variances, set to
+# 1. by the `spheres_masker`.
+
+###############################################################################
+# Connectome extracted from Dosenbach's atlas
+# -------------------------------------------
+
+###############################################################################
+# We repeat the same steps for Dosenbach's atlas.
+dosenbach = datasets.fetch_coords_dosenbach_2010()
+
+coords = np.vstack((
+    dosenbach.rois['x'],
+    dosenbach.rois['y'],
+    dosenbach.rois['z'],
+)).T
+
+spheres_masker = input_data.NiftiSpheresMasker(
+    seeds=coords, smoothing_fwhm=4, radius=4.5,
+    detrend=True, standardize=True, low_pass=0.1, high_pass=0.01, t_r=2.5)
+
+timeseries = spheres_masker.fit_transform(fmri_filename,
+                                          confounds=confounds_filename)
+
+covariance_estimator = GraphLassoCV()
+covariance_estimator.fit(timeseries)
+matrix = covariance_estimator.covariance_
+
+plt.figure()
+plt.imshow(matrix, vmin=-1., vmax=1., cmap='RdBu_r', interpolation='nearest')
+plt.colorbar()
+plt.title('Dosenbach correlation matrix')
+
+plotting.plot_connectome(matrix, coords, title='Dosenbach correlation graph',
+                         edge_threshold="99.7%", node_size=20, colorbar=True)
+
+###############################################################################
+# We can easily identify the Dosenbach's networks from the matrix blocks.
+print('Dosenbach networks names are {0}'.format(np.unique(dosenbach.networks)))
+
+plotting.show()
diff --git a/nilearn/datasets/atlas.py b/nilearn/datasets/atlas.py
--- a/nilearn/datasets/atlas.py
+++ b/nilearn/datasets/atlas.py
@@ -739,11 +739,17 @@ def fetch_atlas_basc_multiscale_2015(version='sym', data_dir=None,
     return Bunch(**params)
 
 
-def fetch_coords_dosenbach_2010():
+def fetch_coords_dosenbach_2010(ordered_regions=True):
     """Load the Dosenbach et al. 160 ROIs. These ROIs cover
     much of the cerebral cortex and cerebellum and are assigned to 6
     networks.
 
+    Parameters
+    ----------
+    ordered_regions : bool, optional
+        ROIs from same networks are grouped together and ordered with respect
+        to their names and their locations (anterior to posterior).
+
     Returns
     -------
     data: sklearn.datasets.base.Bunch
@@ -763,6 +769,9 @@ def fetch_coords_dosenbach_2010():
     csv = os.path.join(package_directory, "data", "dosenbach_2010.csv")
     out_csv = np.recfromcsv(csv)
 
+    if ordered_regions:
+        out_csv = np.sort(out_csv, order=['network', 'name', 'y'])
+
     # We add the ROI number to its name, since names are not unique
     names = out_csv['name']
     numbers = out_csv['number']


Test patch:
diff --git a/nilearn/datasets/tests/test_atlas.py b/nilearn/datasets/tests/test_atlas.py
--- a/nilearn/datasets/tests/test_atlas.py
+++ b/nilearn/datasets/tests/test_atlas.py
@@ -394,3 +394,7 @@ def test_fetch_coords_dosenbach_2010():
     assert_equal(len(bunch.labels), 160)
     assert_equal(len(np.unique(bunch.networks)), 6)
     assert_not_equal(bunch.description, '')
+    np.testing.assert_array_equal(bunch.networks, np.sort(bunch.networks))
+
+    bunch = atlas.fetch_coords_dosenbach_2010(ordered_regions=False)
+    assert_true(np.any(bunch.networks != np.sort(bunch.networks)))