diff --git a/mne/data/html_templates.py b/mne/data/html_templates.py index e1943fe0e0d..304abc731a1 100644 --- a/mne/data/html_templates.py +++ b/mne/data/html_templates.py @@ -1,20 +1,30 @@ +import uuid from ..externals.tempita import Template - info_template = Template(""" +{{style}} + + + + + + {{if meas_date is not None}} {{else}}{{endif}} - + {{if info['experimenter'] is not None}} {{else}}{{endif}} + {{if info['subject_info'] is not None}} {{if 'his_id' in info['subject_info'].keys()}} @@ -22,7 +32,14 @@ {{endif}} {{else}}{{endif}} + + + + + {{if info['dig'] is not None}} @@ -30,49 +47,55 @@ {{endif}} - + - + {{if info['bads'] is not None}} {{else}}{{endif}} - + - + + + + + + - + - + -
+ +
Measurement date{{meas_date}}Unknown
Experimenter{{info['experimenter']}}Unknown
ParticipantUnknown
+ +
Digitized points{{len(info['dig'])}} pointsNot available
Good channels {{n_mag}} magnetometer, {{n_grad}} gradiometer, and {{n_eeg}} EEG channels
Bad channels{{', '.join(info['bads'])}}None
EOG channels {{eog}}
ECG channels {{ecg}}
+ +
Sampling frequency {{u'%0.2f' % info['sfreq']}} Hz
Highpass {{u'%0.2f' % info['highpass']}} Hz
Lowpass {{u'%0.2f' % info['lowpass']}} Hz
-""") - -raw_template = Template(""" -{{info_repr[:-9]}} - + {{if filenames is not None}} + Filenames {{', '.join(filenames)}} - + {{endif}} + {{if duration is not None}} + Duration {{duration}} (HH:MM:SS) + {{endif}} """) @@ -100,3 +123,46 @@ """) + + +def _section_style(section_id): + """Set CSS style for collapsible section's label.""" + html = f"""#{section_id} ~ table [for="{section_id}"]::before {{ + display: inline-block; + content: "►"; + font-size: 11px; + width: 15px; + text-align: left; + }} + + #{section_id}:checked ~ table [for="{section_id}"]::before {{ + content: "▼"; + }} + + #{section_id} ~ table tr.{section_id} {{ + visibility: collapse; + }} + + #{section_id}:checked ~ table tr.{section_id} {{ + visibility: visible; + }} + """ + return html + + +def _collapsible_sections_reprt_html(sections): + """Set style and unique ID for all collapsible sections.""" + style = "" + + for i in ids_: + style += f""" + + """ + + return style, ids_ diff --git a/mne/io/base.py b/mne/io/base.py index d12ba267652..36001804429 100644 --- a/mne/io/base.py +++ b/mne/io/base.py @@ -52,7 +52,6 @@ from ..viz import plot_raw, plot_raw_psd, plot_raw_psd_topo, _RAW_CLIP_DEF from ..event import find_events, concatenate_events from ..annotations import Annotations, _combine_annotations, _sync_onset -from ..data.html_templates import raw_template class TimeMixin(object): @@ -1709,9 +1708,8 @@ def _repr_html_(self, caption=None): m, s = divmod(self._last_time - self.first_time, 60) h, m = divmod(m, 60) duration = f'{int(h):02d}:{int(m):02d}:{int(s):02d}' - return raw_template.substitute( - info_repr=self.info._repr_html_(caption=caption), - filenames=basenames, duration=duration) + return self.info._repr_html_( + caption=caption, filenames=basenames, duration=duration) def add_events(self, events, stim_channel=None, replace=False): """Add events to stim channel. diff --git a/mne/io/meas_info.py b/mne/io/meas_info.py index 153578dc288..c527b077bd5 100644 --- a/mne/io/meas_info.py +++ b/mne/io/meas_info.py @@ -39,7 +39,8 @@ _dig_kind_rev, _dig_kind_ints, _read_dig_fif) from ._digitization import write_dig as _dig_write_dig from .compensator import get_current_comp -from ..data.html_templates import info_template +from ..data.html_templates import (info_template, + _collapsible_sections_reprt_html) b = bytes # alias @@ -809,7 +810,8 @@ def pick_channels(self, ch_names, ordered=False): def ch_names(self): return self['ch_names'] - def _repr_html_(self, caption=None): + def _repr_html_(self, caption=None, filenames=None, + duration=None): if isinstance(caption, str): html = f'

{caption}

' else: @@ -831,9 +833,13 @@ def _repr_html_(self, caption=None): if meas_date is not None: meas_date = meas_date.strftime("%B %d, %Y %H:%M:%S") + ' GMT' + sections = ['General', 'Channels', 'Data'] + style, section_ids = _collapsible_sections_reprt_html(sections) html += info_template.substitute( + style=style, section_ids=section_ids, sections=sections, caption=caption, info=self, meas_date=meas_date, n_eeg=n_eeg, - n_grad=n_grad, n_mag=n_mag, eog=eog, ecg=ecg) + n_grad=n_grad, n_mag=n_mag, eog=eog, ecg=ecg, filenames=filenames, + duration=duration) return html diff --git a/tutorials/intro/plot_20_events_from_raw.py b/tutorials/intro/plot_20_events_from_raw.py index dca39323377..af621811b4d 100644 --- a/tutorials/intro/plot_20_events_from_raw.py +++ b/tutorials/intro/plot_20_events_from_raw.py @@ -11,7 +11,7 @@ In the :ref:`introductory tutorial ` we saw an example of reading experimental events from a :term:`"STIM" channel `; here we'll discuss :term:`events` and :term:`annotations` more +channel>`; here we will discuss :term:`events` and :term:`annotations` more broadly, give more detailed information about reading from STIM channels, and give an example of reading events that are in a marker file or included in the data file as an embedded array. The tutorials :ref:`tut-event-arrays` and diff --git a/tutorials/misc/plot_report.py b/tutorials/misc/plot_report.py index 5db79181b14..29a64e34724 100644 --- a/tutorials/misc/plot_report.py +++ b/tutorials/misc/plot_report.py @@ -56,7 +56,7 @@ # will open the HTML in a new tab in the browser. To disable this, use the # ``open_browser=False`` parameter of :meth:`~mne.Report.save`. # -# For our first example, we'll generate a barebones report for all the +# For our first example, we will generate a barebones report for all the # :file:`.fif` files containing raw data in the sample dataset, by passing the # pattern ``*raw.fif`` to :meth:`~mne.Report.parse_folder`. We'll omit the # ``subject`` and ``subjects_dir`` parameters from the :class:`~mne.Report`