Repository: nilearn/nilearn

Issue:
Improve cuts in nilearn.reporting.make_glm_report
<!--Provide a brief description what you would like changes and why.-->

[`make_glm_report`](https://nilearn.github.io/dev/modules/generated/nilearn.reporting.make_glm_report.html) does not allow to choose the coords of the cuts we want, on the contrary to [`plot_stat_map`](https://nilearn.github.io/dev/modules/generated/nilearn.plotting.plot_stat_map.html) method. 

In addition, defaults cut are not the same for the mask and the computed statistical map. 

Also, when there is nothing significant, the default cuts don't cover the whole brain but only a small part (non uniformly distributed).

![image](https://user-images.githubusercontent.com/9747190/205360003-9a33a481-95cf-48f6-90f3-f8ebc956cb55.png)
![image](https://user-images.githubusercontent.com/9747190/205359771-74d4e076-c52f-4dee-aacb-068e0f998b44.png)


<!--Please fill in the following information, to the best of your ability.-->
### Benefits to the change

User-friendly and easy to perform changes I guess.



Discussion:
Hi @AudreyDuran,

Thanks for this suggestion ! Since `make_glm_report` is [calling `plot_stat_map` internally](https://github.com/nilearn/nilearn/blob/ffc0489b19b01b3231862846fc15ef72cfdbd249/nilearn/reporting/glm_reporter.py#L909-L913), we should be able to set coordinates appropriately by creating a new argument for `make_glm_report` and passing it through.

Do you want to open a pull request for this ?

Resolving patch:
diff --git a/nilearn/reporting/glm_reporter.py b/nilearn/reporting/glm_reporter.py
--- a/nilearn/reporting/glm_reporter.py
+++ b/nilearn/reporting/glm_reporter.py
@@ -21,6 +21,7 @@
 import pandas as pd
 from matplotlib import pyplot as plt
 
+from .._utils import fill_doc
 from nilearn.plotting import (plot_glass_brain,
                               plot_roi,
                               plot_stat_map,
@@ -47,6 +48,7 @@
                                        'glm_reporter_templates')
 
 
+@fill_doc
 def make_glm_report(model,
                     contrasts,
                     title=None,
@@ -58,6 +60,7 @@ def make_glm_report(model,
                     two_sided=False,
                     min_distance=8.,
                     plot_type='slice',
+                    cut_coords=None,
                     display_mode=None,
                     report_dims=(1600, 800),
                     ):
@@ -142,6 +145,8 @@ def make_glm_report(model,
         Specifies the type of plot to be drawn for the statistical maps.
         Default='slice'.
 
+    %(cut_coords)s
+
     display_mode : string, optional
         Default is 'z' if plot_type is 'slice'; '
         ortho' if plot_type is 'glass'.
@@ -186,10 +191,10 @@ def make_glm_report(model,
         design_matrices = [model.design_matrix_]
 
     html_head_template_path = os.path.join(HTML_TEMPLATE_ROOT_PATH,
-                                          'report_head_template.html')
+                                           'report_head_template.html')
 
     html_body_template_path = os.path.join(HTML_TEMPLATE_ROOT_PATH,
-                                          'report_body_template.html')
+                                           'report_body_template.html')
 
     with open(html_head_template_path) as html_head_file_obj:
         html_head_template_text = html_head_file_obj.read()
@@ -240,6 +245,7 @@ def make_glm_report(model,
         two_sided=two_sided,
         min_distance=min_distance,
         bg_img=bg_img,
+        cut_coords=cut_coords,
         display_mode=display_mode,
         plot_type=plot_type,
     )
@@ -250,13 +256,18 @@ def make_glm_report(model,
                           'page_heading_2': page_heading_2,
                           'model_attributes': model_attributes_html,
                           'all_contrasts_with_plots': ''.join(
-                               contrast_plots.values()),
+                              contrast_plots.values()),
                           'design_matrices': html_design_matrices,
                           'mask_plot': mask_plot_html_code,
                           'component': all_components_text,
-                         }
-    report_text_body = report_body_template.safe_substitute(**report_values_body)
-    report_text = HTMLReport(body=report_text_body, head_tpl=report_head_template, head_values=report_values_head)
+                          }
+    report_text_body = report_body_template.safe_substitute(
+        **report_values_body)
+    report_text = HTMLReport(
+        body=report_text_body,
+        head_tpl=report_head_template,
+        head_values=report_values_head
+    )
     # setting report size for better visual experience in Jupyter Notebooks.
     report_text.width, report_text.height = _check_report_dims(report_dims)
     return report_text
@@ -655,11 +666,12 @@ def _mask_to_svg(mask_img, bg_img):
     return mask_plot_svg
 
 
+@fill_doc
 def _make_stat_maps_contrast_clusters(stat_img, contrasts_plots, threshold,
                                       alpha,
                                       cluster_threshold, height_control,
                                       two_sided,
-                                      min_distance, bg_img,
+                                      min_distance, bg_img, cut_coords,
                                       display_mode, plot_type):
     """Populates a smaller HTML sub-template with the proper values,
     make a list containing one or more of such components
@@ -712,6 +724,8 @@ def _make_stat_maps_contrast_clusters(stat_img, contrasts_plots, threshold,
         If nothing is specified, the MNI152 template will be used.
         To turn off background image, just pass "bg_img=False".
 
+    %(cut_coords)s
+
     display_mode : string
         Choose the direction of the cuts:
         'x' - sagittal, 'y' - coronal, 'z' - axial,
@@ -758,6 +772,7 @@ def _make_stat_maps_contrast_clusters(stat_img, contrasts_plots, threshold,
         stat_map_svg = _stat_map_to_svg(
             stat_img=thresholded_stat_map,
             bg_img=bg_img,
+            cut_coords=cut_coords,
             display_mode=display_mode,
             plot_type=plot_type,
             table_details=table_details,
@@ -859,8 +874,10 @@ def _clustering_params_to_dataframe(threshold,
     return table_details
 
 
+@fill_doc
 def _stat_map_to_svg(stat_img,
                      bg_img,
+                     cut_coords,
                      display_mode,
                      plot_type,
                      table_details,
@@ -882,6 +899,9 @@ def _stat_map_to_svg(stat_img,
         If nothing is specified, the MNI152 template will be used.
         To turn off background image, just pass "bg_img=False".
 
+
+    %(cut_coords)s
+
     display_mode : string
         Choose the direction of the cuts:
         'x' - sagittal, 'y' - coronal, 'z' - axial,
@@ -909,6 +929,7 @@ def _stat_map_to_svg(stat_img,
     if plot_type == 'slice':
         stat_map_plot = plot_stat_map(stat_img,
                                       bg_img=bg_img,
+                                      cut_coords=cut_coords,
                                       display_mode=display_mode,
                                       )
     elif plot_type == 'glass':


Test patch:
diff --git a/nilearn/reporting/tests/test_glm_reporter.py b/nilearn/reporting/tests/test_glm_reporter.py
--- a/nilearn/reporting/tests/test_glm_reporter.py
+++ b/nilearn/reporting/tests/test_glm_reporter.py
@@ -30,7 +30,8 @@
 def test_flm_reporting(use_method):
     with InTemporaryDirectory():
         shapes, rk = ((7, 8, 7, 15), (7, 8, 7, 16)), 3
-        mask, fmri_data, design_matrices = write_fake_fmri_data_and_design(shapes, rk)
+        mask, fmri_data, design_matrices = write_fake_fmri_data_and_design(
+            shapes, rk)
         flm = FirstLevelModel(mask_img=mask).fit(
             fmri_data, design_matrices=design_matrices)
         contrast = np.eye(3)[1]
@@ -43,7 +44,7 @@ def test_flm_reporting(use_method):
                                               height_control=None,
                                               min_distance=15,
                                               alpha=0.001, threshold=2.78,
-            )
+                                              )
         '''
         catches & raises UnicodeEncodeError in HTMLDocument.get_iframe()
         Python2's limited unicode support causes  HTMLDocument.get_iframe() to
@@ -228,33 +229,38 @@ def _generate_img():
     return nib.Nifti1Image(data_positive, mni_affine)
 
 
-def test_stat_map_to_svg_slice_z():
+@pytest.mark.parametrize("cut_coords", [None, (5, 4, 3)])
+def test_stat_map_to_svg_slice_z(cut_coords):
     with InTemporaryDirectory():
         img = _generate_img()
         table_details = pd.DataFrame.from_dict({'junk': 0}, orient='index')
         stat_map_html_code = glmr._stat_map_to_svg(  # noqa: F841
             stat_img=img,
             bg_img=None,
+            cut_coords=cut_coords,
             display_mode='ortho',
             plot_type='slice',
             table_details=table_details,
         )
 
 
-def test_stat_map_to_svg_glass_z():
+@pytest.mark.parametrize("cut_coords", [None, (5, 4, 3)])
+def test_stat_map_to_svg_glass_z(cut_coords):
     with InTemporaryDirectory():
         img = _generate_img()
         table_details = pd.DataFrame.from_dict({'junk': 0}, orient='index')
         stat_map_html_code = glmr._stat_map_to_svg(  # noqa: F841
             stat_img=img,
             bg_img=None,
+            cut_coords=cut_coords,
             display_mode='z',
             plot_type='glass',
             table_details=table_details,
         )
 
 
-def test_stat_map_to_svg_invalid_plot_type():
+@pytest.mark.parametrize("cut_coords", [None, (5, 4, 3)])
+def test_stat_map_to_svg_invalid_plot_type(cut_coords):
     with InTemporaryDirectory():
         img = _generate_img()
         expected_error = ValueError(
@@ -264,6 +270,7 @@ def test_stat_map_to_svg_invalid_plot_type():
             stat_map_html_code = glmr._stat_map_to_svg(  # noqa: F841
                 stat_img=img,
                 bg_img=None,
+                cut_coords=cut_coords,
                 display_mode='z',
                 plot_type='junk',
                 table_details={'junk': 0