Repository: mne-tools/mne-python

Issue:
RFC: suppress filter params output in some cases?
The new output summarizing filter params (added in #6294) is really cool, but `create_ecg_epochs` and `create_eog_epochs` each involve two filtering steps, and the filter params are not fully under user control, so the output is maybe less necessary in those cases. I wonder if it makes sense to have a way to suppress the `filter_data` messages without fully disabling all `create_ecg_epochs` messages?  Ideas:

- if `verbose` is `None` in the call to `create_ecg_epochs`, automatically pass `verbose=False` to the `filter_data` call.  User can still see all the messages by passing `verbose=True`, and will see no messages (from either `create_ecg_epochs` or `filter_data`) by passing `verbose=False`.
- a new boolean param in `create_ecg_epochs` that gets passed to `filter_data`'s `verbose` param, called `show_filter_params` or `filter_verbose` or something similar.




Discussion:
Or just always pass verbose=False in the find_ecg_events call. Users probably don't need to know the characteristics used to filter just for the purposes of finding the events. And if they want this information they can make a separate call to find_ecg_events
(the parameters that are used to filter the raw data before epoching the data should arguably always be with the rest of the logging messages, because they reflect the filtering characteristics of the Epochs you get back)
Not sure I fully understand your second comment @larsoner...  I thought you were saying

> maybe we should always suppress the filter messages when `filter_data` is called (via `find_ecg_events`) from within `create_ecg_epochs`

but then you said the parameters should arguably *always* be there?
When filtering the ecg signal no output, when filtering the raw data to epoch, yes output
> When filtering the ecg signal no output, when filtering the raw data to epoch, yes output

OK, agreed.
So I think the only change you should need to make is passing verbose=False to the find_ecg_events call the occurs within create_ecg_epochs
yup.  I'll wait half a day to let others weigh in before implementing.
Ok for me


Resolving patch:
diff --git a/mne/preprocessing/ecg.py b/mne/preprocessing/ecg.py
--- a/mne/preprocessing/ecg.py
+++ b/mne/preprocessing/ecg.py
@@ -18,8 +18,10 @@
 from .. import create_info
 
 
+@verbose
 def qrs_detector(sfreq, ecg, thresh_value=0.6, levels=2.5, n_thresh=3,
-                 l_freq=5, h_freq=35, tstart=0, filter_length='10s'):
+                 l_freq=5, h_freq=35, tstart=0, filter_length='10s',
+                 verbose=None):
     """Detect QRS component in ECG channels.
 
     QRS is the main wave on the heart beat.
@@ -45,6 +47,7 @@ def qrs_detector(sfreq, ecg, thresh_value=0.6, levels=2.5, n_thresh=3,
         Start detection after tstart seconds.
     filter_length : str | int | None
         Number of taps to use for filtering.
+    %(verbose)s
 
     Returns
     -------
@@ -217,10 +220,11 @@ def find_ecg_events(raw, event_id=999, ch_name=None, tstart=0.0,
             verbose=use_verbose))
     ecg = np.concatenate(ecgs)
 
-    # detecting QRS and generating event file
+    # detecting QRS and generating event file. Since not user-controlled, don't
+    # output filter params here (hardcode verbose=False)
     ecg_events = qrs_detector(raw.info['sfreq'], ecg, tstart=tstart,
                               thresh_value=qrs_threshold, l_freq=None,
-                              h_freq=None)
+                              h_freq=None, verbose=False)
 
     # map ECG events back to original times
     remap = np.empty(len(ecg), int)
diff --git a/mne/preprocessing/eog.py b/mne/preprocessing/eog.py
--- a/mne/preprocessing/eog.py
+++ b/mne/preprocessing/eog.py
@@ -67,25 +67,30 @@ def find_eog_events(raw, event_id=998, l_freq=1, h_freq=10,
                                   sampling_rate=raw.info['sfreq'],
                                   first_samp=raw.first_samp,
                                   filter_length=filter_length,
-                                  tstart=tstart, thresh=thresh)
+                                  tstart=tstart, thresh=thresh,
+                                  verbose=verbose)
     # Map times to corresponding samples.
     eog_events[:, 0] = np.round(times[eog_events[:, 0] -
                                       raw.first_samp]).astype(int)
     return eog_events
 
 
+@verbose
 def _find_eog_events(eog, event_id, l_freq, h_freq, sampling_rate, first_samp,
-                     filter_length='10s', tstart=0., thresh=None):
+                     filter_length='10s', tstart=0., thresh=None,
+                     verbose=None):
     """Find EOG events."""
     logger.info('Filtering the data to remove DC offset to help '
                 'distinguish blinks from saccades')
 
     # filtering to remove dc offset so that we know which is blink and saccades
+    # hardcode verbose=False to suppress filter param messages (since this
+    # filter is not under user control)
     fmax = np.minimum(45, sampling_rate / 2.0 - 0.75)  # protect Nyquist
     filteog = np.array([filter_data(
         x, sampling_rate, 2, fmax, None, filter_length, 0.5, 0.5,
-        phase='zero-double', fir_window='hann', fir_design='firwin2')
-        for x in eog])
+        phase='zero-double', fir_window='hann', fir_design='firwin2',
+        verbose=False) for x in eog])
     temp = np.sqrt(np.sum(filteog ** 2, axis=1))
 
     indexmax = np.argmax(temp)


Test patch: